Compare commits
2 Commits
5dc1d13e25
...
8b635101de
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b635101de | |||
| 696a36ba92 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "in-car-system-fe",
|
||||
"private": true,
|
||||
"version": "1.0.16",
|
||||
"version": "1.0.17",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
11
public/NPED_Cat_D.svg
Normal file
11
public/NPED_Cat_D.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 29 KiB |
@@ -8,6 +8,7 @@ import { useCameraBlackboard } from "../../hooks/useCameraBlackboard";
|
||||
import NPED_CAT_A from "/NPED_Cat_A.svg";
|
||||
import NPED_CAT_B from "/NPED_Cat_B.svg";
|
||||
import NPED_CAT_C from "/NPED_Cat_C.svg";
|
||||
import NPED_CAT_D from "/NPED_Cat_D.svg";
|
||||
import { checkIsHotListHit, formatAge, getNPEDCategory } from "../../utils/utils";
|
||||
import { faX } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faClock } from "@fortawesome/free-regular-svg-icons";
|
||||
@@ -30,6 +31,7 @@ const AlertItem = ({ item }: AlertItemProps) => {
|
||||
const isNPEDHitA = cat === "A";
|
||||
const isNPEDHitB = cat === "B";
|
||||
const isNPEDHitC = cat === "C";
|
||||
const isNPEDHitD = cat === "D";
|
||||
|
||||
const handleClick = () => {
|
||||
setIsModalOpen(true);
|
||||
@@ -69,6 +71,7 @@ const AlertItem = ({ item }: AlertItemProps) => {
|
||||
{isNPEDHitA && <img src={NPED_CAT_A} alt="NPEDHITicon" className="h-20 object-contain rounded-md" />}
|
||||
{isNPEDHitB && <img src={NPED_CAT_B} alt="NPEDHITicon" className="h-20 object-contain rounded-md" />}
|
||||
{isNPEDHitC && <img src={NPED_CAT_C} alt="NPEDHITicon" className="h-20 object-contain rounded-md" />}
|
||||
{isNPEDHitD && <img src={NPED_CAT_D} alt="NPEDHITicon" className="h-20 object-contain rounded-md" />}
|
||||
<div className={`border p-1 hidden md:block`}>
|
||||
<img src={item?.plateUrlColour} height={48} width={200} alt="colour patch" />
|
||||
</div>
|
||||
|
||||
@@ -31,9 +31,7 @@ const HistoryList = () => {
|
||||
<div className="flex flex-col gap-1 px-2">
|
||||
{state?.alertList?.length > 0 ? (
|
||||
<div className="mt-3 grid grid-cols-1 gap-3">
|
||||
{state?.alertList?.map((alertItem) => (
|
||||
<AlertItem item={alertItem} key={alertItem.vrm} />
|
||||
))}
|
||||
{state?.alertList?.map((alertItem) => <AlertItem item={alertItem} key={alertItem.vrm} />).reverse()}
|
||||
</div>
|
||||
) : (
|
||||
<div className="mt-4 flex flex-col items-center justify-center rounded-2xl border border-slate-800 bg-slate-900/40 p-10 text-center">
|
||||
|
||||
@@ -10,6 +10,7 @@ import { toast } from "sonner";
|
||||
|
||||
const NPEDCategoryPopup = () => {
|
||||
const { state, dispatch } = useIntegrationsContext();
|
||||
|
||||
const { mutation } = useCameraBlackboard();
|
||||
|
||||
const isCatAEnabled = state?.iscatEnabled?.catA;
|
||||
@@ -34,8 +35,8 @@ const NPEDCategoryPopup = () => {
|
||||
await mutation.mutateAsync({
|
||||
operation: "SAVE",
|
||||
path: "",
|
||||
value: null
|
||||
})
|
||||
value: null,
|
||||
});
|
||||
if (result?.reason === "OK") toast.success("Pop up settings saved");
|
||||
dispatch({ type: "NPEDCATENABLED", payload: values });
|
||||
};
|
||||
@@ -44,7 +45,7 @@ const NPEDCategoryPopup = () => {
|
||||
<Card className="p-4">
|
||||
<CardHeader title={"Alert Pop ups"} />
|
||||
<p className="italic my-2">Allows alerts to pop up to user.</p>
|
||||
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
|
||||
<Formik initialValues={initialValues} onSubmit={handleSubmit} enableReinitialize>
|
||||
<Form className="flex flex-col space-y-5 px-2">
|
||||
<FormGroup>
|
||||
<NPEDCatToggle name={"catA"} label="NPED Category A" />
|
||||
|
||||
@@ -172,6 +172,11 @@ const SessionCard = () => {
|
||||
textColour="text-gray-300"
|
||||
vehicleTag={"Vehicles with NPED Cat C:"}
|
||||
/>
|
||||
<VehicleSessionItem
|
||||
sessionNumber={vehicles.npedCatD.length}
|
||||
textColour="text-gray-300"
|
||||
vehicleTag={"Vehicles with NPED Cat D:"}
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -10,7 +10,8 @@ import HotListImg from "/Hotlist_Hit.svg";
|
||||
import NPED_CAT_A from "/NPED_Cat_A.svg";
|
||||
import NPED_CAT_B from "/NPED_Cat_B.svg";
|
||||
import NPED_CAT_C from "/NPED_Cat_C.svg";
|
||||
import { checkIsHotListHit, getHotlistName, getNPEDCategory } from "../../utils/utils";
|
||||
import NPED_CAT_D from "/NPED_Cat_D.svg";
|
||||
import { checkIsHotListHit, getHotlistName, getNPEDCategory, getNPEDReason } from "../../utils/utils";
|
||||
|
||||
type SightingModalProps = {
|
||||
isSightingModalOpen: boolean;
|
||||
@@ -74,11 +75,19 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }:
|
||||
};
|
||||
|
||||
const motionAway = (sighting?.motion ?? "").toUpperCase() === "AWAY";
|
||||
|
||||
const isHotListHit = checkIsHotListHit(sighting);
|
||||
const cat = getNPEDCategory(sighting);
|
||||
const isNPEDHitA = cat === "A";
|
||||
const isNPEDHitB = cat === "B";
|
||||
const isNPEDHitC = cat === "C";
|
||||
const isNPEDHitD = cat === "D";
|
||||
|
||||
const reason = getNPEDReason(sighting);
|
||||
|
||||
const insuranceStatus = reason ? reason["INSURANCE STATUS"] : null;
|
||||
const motStatus = reason ? reason["MOT STATUS"] : null;
|
||||
const taxStatus = reason ? reason["TAX STATUS"] : null;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -133,6 +142,7 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }:
|
||||
{isNPEDHitA && <img src={NPED_CAT_A} alt="hotlistHit" className="h-20 object-contain rounded-md" />}
|
||||
{isNPEDHitB && <img src={NPED_CAT_B} alt="hotlistHit" className="h-20 object-contain rounded-md" />}
|
||||
{isNPEDHitC && <img src={NPED_CAT_C} alt="hotlistHit" className="h-20 object-contain rounded-md" />}
|
||||
{isNPEDHitD && <img src={NPED_CAT_D} alt="hotlistHit" className="h-20 object-contain rounded-md" />}
|
||||
</div>
|
||||
{hotlistNames && hotlistNames.length > 0 && (
|
||||
<div className="flex flex-col border-b border-gray-600 mb-4">
|
||||
@@ -158,44 +168,97 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }:
|
||||
<h3 className="text-base md:text-lg font-semibold pb-2 border-b border-gray-700">Vehicle Info</h3>
|
||||
<dl className="mt-3 gap-x-4 gap-y-2 text-sm">
|
||||
<div>
|
||||
<dt className="text-gray-300">VRM</dt>
|
||||
<dd className="font-medium text-2xl break-all">{sighting?.vrm ?? "-"}</dd>
|
||||
<dd className="font-medium text-2xl break-all font-mono tracking-wide">{sighting?.vrm ?? "-"}</dd>
|
||||
</div>
|
||||
{isNPEDHitA || isNPEDHitB || isNPEDHitC || isNPEDHitD ? (
|
||||
<>
|
||||
<div className="">
|
||||
<dt className="text-gray-300 text-xl">Insurance</dt>
|
||||
<dd className="font-medium text-2xl flex">
|
||||
{insuranceStatus ? (
|
||||
<span
|
||||
className={`text-green-600 bg-green-300 w-[30%] px-2 rounded-lg border border-green-900`}
|
||||
>
|
||||
YES
|
||||
</span>
|
||||
) : (
|
||||
<span className={`text-red-300 bg-red-600 w-[30%] px-2 rounded-lg border border-red-900`}>
|
||||
NO
|
||||
</span>
|
||||
)}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-gray-300 text-3xl">MOT</dt>
|
||||
<dd className="font-medium text-2xl">
|
||||
{motStatus ? (
|
||||
<span
|
||||
className={`text-green-700 bg-green-400 w-[30%] px-2 rounded-lg border border-green-900`}
|
||||
>
|
||||
VALID
|
||||
</span>
|
||||
) : (
|
||||
<span className={`text-red-600 bg-red-300 w-[30%] px-2 rounded-lg border border-red-900`}>
|
||||
EXPIRED
|
||||
</span>
|
||||
)}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-gray-300 text-3xl">Tax</dt>
|
||||
<dd className="font-medium text-2xl">
|
||||
{taxStatus ? (
|
||||
<span
|
||||
className={`text-green-700 bg-green-400 w-[30%] px-2 rounded-lg border border-green-900`}
|
||||
>
|
||||
VALID
|
||||
</span>
|
||||
) : (
|
||||
<span className={`text-red-600 bg-red-300 w-[30%] px-2 rounded-lg border border-red-900`}>
|
||||
EXPIRED
|
||||
</span>
|
||||
)}
|
||||
</dd>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div>
|
||||
<dt className="text-gray-300">Motion</dt>
|
||||
<dd className="font-medium text-2xl ">{sighting?.motion ?? "-"}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-gray-300">Seen Count</dt>
|
||||
<dd className="font-medium text-2xl">{sighting?.seenCount ?? "-"}</dd>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<dt className="text-gray-300">Motion</dt>
|
||||
<dd className="font-medium text-2xl">{sighting?.motion ?? "-"}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-gray-300">Seen Count</dt>
|
||||
<dd className="font-medium text-2xl">{sighting?.seenCount ?? "-"}</dd>
|
||||
</div>
|
||||
{sighting?.make && sighting.make.trim() && sighting.make.toLowerCase() !== "disabled" && (
|
||||
<div>
|
||||
<dt className="text-gray-300">Make</dt>
|
||||
<dd className="font-medium text-2xl">{sighting.make}</dd>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{sighting?.make && sighting.make.trim() && sighting.make.toLowerCase() !== "disabled" && (
|
||||
<div>
|
||||
<dt className="text-gray-300">Make</dt>
|
||||
<dd className="font-medium text-2xl">{sighting.make}</dd>
|
||||
</div>
|
||||
{sighting?.model && sighting.model.trim() && sighting.model.toLowerCase() !== "disabled" && (
|
||||
<div>
|
||||
<dt className="text-gray-300">Model</dt>
|
||||
<dd className="font-medium text-2xl">{sighting.model}</dd>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{sighting?.color && sighting.color.trim() && sighting.color.toLowerCase() !== "disabled" && (
|
||||
<div className="sm:col-span-2">
|
||||
<dt className="text-gray-300">Colour</dt>
|
||||
<dd className="font-medium text-2xl">{sighting.color}</dd>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<dt className="text-gray-300">Time</dt>
|
||||
<dd className="font-medium text-xl">{sighting?.timeStamp ?? "-"}</dd>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{sighting?.model && sighting.model.trim() && sighting.model.toLowerCase() !== "disabled" && (
|
||||
<div>
|
||||
<dt className="text-gray-300">Model</dt>
|
||||
<dd className="font-medium text-2xl">{sighting.model}</dd>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{sighting?.color && sighting.color.trim() && sighting.color.toLowerCase() !== "disabled" && (
|
||||
<div className="sm:col-span-2">
|
||||
<dt className="text-gray-300">Colour</dt>
|
||||
<dd className="font-medium text-2xl">{sighting.color}</dd>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<dt className="text-gray-300">Time</dt>
|
||||
<dd className="font-medium text-xl">{sighting?.timeStamp ?? "-"}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
@@ -12,14 +12,10 @@ import HotListImg from "/Hotlist_Hit.svg";
|
||||
import NPED_CAT_A from "/NPED_Cat_A.svg";
|
||||
import NPED_CAT_B from "/NPED_Cat_B.svg";
|
||||
import NPED_CAT_C from "/NPED_Cat_C.svg";
|
||||
import popup from "../../assets/sounds/ui/popup_open.mp3";
|
||||
import notification from "../../assets/sounds/ui/notification.mp3";
|
||||
import { useSound } from "react-sounds";
|
||||
import NPED_CAT_D from "/NPED_Cat_D.svg";
|
||||
import { useIntegrationsContext } from "../../context/IntegrationsContext";
|
||||
import { useSoundContext } from "../../context/SoundContext";
|
||||
import Loading from "../UI/Loading";
|
||||
import { checkIsHotListHit, getNPEDCategory } from "../../utils/utils";
|
||||
import { useCachedSoundSrc } from "../../hooks/usecachedSoundSrc";
|
||||
|
||||
function useNow(tickMs = 1000) {
|
||||
const [, setNow] = useState(() => Date.now());
|
||||
@@ -41,14 +37,9 @@ type SightingHistoryProps = {
|
||||
|
||||
export default function SightingHistoryWidget({ className, title }: SightingHistoryProps) {
|
||||
const [modalQueue, setModalQueue] = useState<QueuedHit[]>([]);
|
||||
|
||||
useNow(1000);
|
||||
const { state } = useSoundContext();
|
||||
|
||||
const { src: soundSrcHotlist } = useCachedSoundSrc(state?.hotlistSound, state?.soundOptions, notification);
|
||||
const { src: soundSrcNped } = useCachedSoundSrc(state?.NPEDsound, state?.soundOptions, popup);
|
||||
|
||||
const { play: npedSound } = useSound(soundSrcNped, { volume: state.NPEDsoundVolume });
|
||||
const { play: hotlistsound } = useSound(soundSrcHotlist, { volume: state.hotlistSoundVolume });
|
||||
const {
|
||||
sightings,
|
||||
setSelectedSighting,
|
||||
@@ -73,18 +64,24 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
|
||||
const isCatCEnabled = integrationState?.iscatEnabled?.catC;
|
||||
const isCatDEnabled = integrationState?.iscatEnabled?.catD;
|
||||
|
||||
const enqueue = useCallback((sighting: SightingType, kind: HitKind) => {
|
||||
const id = sighting.vrm ?? sighting.ref;
|
||||
if (processedRefs.current.has(id)) return;
|
||||
const enqueue = useCallback(
|
||||
(sighting: SightingType, kind: HitKind) => {
|
||||
if (!sighting) return;
|
||||
|
||||
const inList = alertState?.alertList?.find((sighting) => sighting.vrm === id);
|
||||
if (inList) {
|
||||
return;
|
||||
}
|
||||
processedRefs.current.add(id);
|
||||
const id = sighting.vrm ?? sighting.ref;
|
||||
if (processedRefs.current.has(id)) return;
|
||||
|
||||
setModalQueue((q) => [...q, { id, sighting, kind }]);
|
||||
}, []);
|
||||
const inList = alertState?.alertList?.find((sighting) => sighting.vrm === id);
|
||||
if (inList) {
|
||||
return;
|
||||
}
|
||||
|
||||
processedRefs.current.add(id);
|
||||
|
||||
setModalQueue((q) => [...q, { id, sighting, kind }]);
|
||||
},
|
||||
[alertState?.alertList]
|
||||
);
|
||||
|
||||
const reduceObject = (obj: SightingType): ReducedSightingType => {
|
||||
return {
|
||||
@@ -133,31 +130,16 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
|
||||
enqueue(sighting, isNPED ? "NPED" : "HOTLIST"); // enqueue ONLY
|
||||
}
|
||||
}
|
||||
}, [rows, enqueue]);
|
||||
|
||||
useEffect(() => {
|
||||
rows?.forEach((obj) => {
|
||||
const cat = getNPEDCategory(obj);
|
||||
const isNPEDHitA = cat === "A";
|
||||
const isNPEDHitB = cat === "B";
|
||||
const isNPEDHitC = cat === "C";
|
||||
if (isNPEDHitA || isNPEDHitB || isNPEDHitC) {
|
||||
dispatch({
|
||||
type: "ADD",
|
||||
payload: obj,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [dispatch]);
|
||||
}, [rows, enqueue, isCatAEnabled, isCatBEnabled, isCatCEnabled, isCatDEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (hasAutoOpenedRef.current || npedRef.current) return;
|
||||
const firstNPED = rows.find((r) => {
|
||||
const cat = getNPEDCategory(r);
|
||||
const isNPEDHitA = cat === "A";
|
||||
const isNPEDHitB = cat === "B";
|
||||
const isNPEDHitC = cat === "C";
|
||||
const isNPEDHitD = cat === "D";
|
||||
const isNPEDHitA = cat === "A" && isCatAEnabled;
|
||||
const isNPEDHitB = cat === "B" && isCatBEnabled;
|
||||
const isNPEDHitC = cat === "C" && isCatCEnabled;
|
||||
const isNPEDHitD = cat === "D" && isCatDEnabled;
|
||||
return isNPEDHitA || isNPEDHitB || isNPEDHitC || isNPEDHitD;
|
||||
});
|
||||
const firstHot = rows?.find((r) => {
|
||||
@@ -176,20 +158,42 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
|
||||
|
||||
hasAutoOpenedRef.current = true;
|
||||
}
|
||||
}, [enqueue, hotlistsound, npedSound, rows, setSelectedSighting, setSightingModalOpen]);
|
||||
}, [
|
||||
enqueue,
|
||||
rows,
|
||||
setSelectedSighting,
|
||||
setSightingModalOpen,
|
||||
isCatAEnabled,
|
||||
isCatBEnabled,
|
||||
isCatCEnabled,
|
||||
isCatDEnabled,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isSightingModalOpen && modalQueue.length > 0) {
|
||||
const next = modalQueue[0];
|
||||
|
||||
if (next.kind === "NPED") npedSound();
|
||||
else hotlistsound();
|
||||
|
||||
setSelectedSighting(next.sighting);
|
||||
|
||||
setSightingModalOpen(true);
|
||||
}
|
||||
}, [isSightingModalOpen, npedSound, hotlistsound, setSelectedSighting, setSightingModalOpen, modalQueue]);
|
||||
}, [isSightingModalOpen, setSelectedSighting, setSightingModalOpen, modalQueue]);
|
||||
|
||||
useEffect(() => {
|
||||
rows?.forEach((obj) => {
|
||||
const cat = getNPEDCategory(obj);
|
||||
const isNPEDHitA = cat === "A";
|
||||
const isNPEDHitB = cat === "B";
|
||||
const isNPEDHitC = cat === "C";
|
||||
const isNPEDHitD = cat === "D";
|
||||
if (isNPEDHitA || isNPEDHitB || isNPEDHitC || isNPEDHitD) {
|
||||
console.log("first");
|
||||
dispatch({
|
||||
type: "ADD",
|
||||
payload: obj,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [dispatch, rows]);
|
||||
|
||||
const handleClose = () => {
|
||||
setSightingModalOpen(false);
|
||||
@@ -212,6 +216,7 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
|
||||
const isNPEDHitA = cat === "A";
|
||||
const isNPEDHitB = cat === "B";
|
||||
const isNPEDHitC = cat === "C";
|
||||
const isNPEDHitD = cat === "D";
|
||||
const motionAway = (obj?.motion ?? "").toUpperCase() === "AWAY";
|
||||
const isHotListHit = checkIsHotListHit(obj);
|
||||
return (
|
||||
@@ -230,6 +235,7 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
|
||||
{isNPEDHitA && <img src={NPED_CAT_A} alt="hotlistHit" className="h-20 object-contain rounded-md" />}
|
||||
{isNPEDHitB && <img src={NPED_CAT_B} alt="hotlistHit" className="h-20 object-contain rounded-md" />}
|
||||
{isNPEDHitC && <img src={NPED_CAT_C} alt="hotlistHit" className="h-20 object-contain rounded-md" />}
|
||||
{isNPEDHitD && <img src={NPED_CAT_D} alt="hotlistHit" className="h-20 object-contain rounded-md" />}
|
||||
<NumberPlate motion={motionAway} vrm={obj?.vrm} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,10 +36,16 @@ export const IntegrationsProvider = ({ children }: IntegrationsProviderType) =>
|
||||
});
|
||||
|
||||
if (!isMounted) return;
|
||||
if (!result?.result || typeof result.result === "string") return;
|
||||
|
||||
dispatch({ type: "UPDATE", payload: result.result });
|
||||
dispatch({ type: "NPEDCATENABLED", payload: catResult.result });
|
||||
if (result?.result && typeof result.result !== "string") {
|
||||
dispatch({ type: "UPDATE", payload: result.result });
|
||||
}
|
||||
|
||||
if (catResult?.result) {
|
||||
dispatch({ type: "NPEDCATENABLED", payload: catResult.result });
|
||||
} else {
|
||||
console.log("Early return: catResult check failed");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error in fetchData:", error);
|
||||
}
|
||||
|
||||
@@ -88,8 +88,14 @@ export function useSightingFeed(url: string | undefined) {
|
||||
const isNPEDHitA = cat === "A";
|
||||
const isNPEDHitB = cat === "B";
|
||||
const isNPEDHitC = cat === "C";
|
||||
const isNPEDHitD = cat === "D";
|
||||
|
||||
if ((isNPEDHitA && audioArmed) || (isNPEDHitB && audioArmed) || (isNPEDHitC && audioArmed)) {
|
||||
if (
|
||||
(isNPEDHitA && audioArmed) ||
|
||||
(isNPEDHitB && audioArmed) ||
|
||||
(isNPEDHitC && audioArmed) ||
|
||||
(isNPEDHitD && audioArmed)
|
||||
) {
|
||||
playNPEDHitSound();
|
||||
} else if (isHotListHit && audioArmed) {
|
||||
playHotlistsound();
|
||||
|
||||
@@ -159,6 +159,8 @@ export function getHotlistName(obj: HotlistMatches | undefined) {
|
||||
export const getNPEDCategory = (r?: SightingType | null) =>
|
||||
r?.metadata?.npedJSON?.["NPED CATEGORY"] as "A" | "B" | "C" | "D" | undefined;
|
||||
|
||||
export const getNPEDReason = (r?: SightingType | null) => r?.metadata?.npedJSON;
|
||||
|
||||
export const zoomMapping = (zoomLevel: number | undefined) => {
|
||||
switch (zoomLevel) {
|
||||
case 1:
|
||||
|
||||
Reference in New Issue
Block a user