diff --git a/src/components/SightingModal/SightingModal.tsx b/src/components/SightingModal/SightingModal.tsx index 9e31bfc..668f202 100644 --- a/src/components/SightingModal/SightingModal.tsx +++ b/src/components/SightingModal/SightingModal.tsx @@ -23,8 +23,7 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }: const { dispatch } = useAlertHitContext(); const { query, mutation } = useCameraBlackboard(); - const hotlistName = getHotlistName(sighting?.metadata?.hotlistMatches); - + const hotlistNames = getHotlistName(sighting?.metadata?.hotlistMatches); const handleAcknowledgeButton = () => { try { if (!sighting) { @@ -117,16 +116,6 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }:
plate patch - {hotlistName && ( -
-

Hotlist

-
-

- {hotlistName ? hotlistName[0].replace(/\.csv$/i, "") : "-"} -

-
-
- )}
{isHotListHit && hotlistHit} @@ -134,6 +123,20 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }: {isNPEDHitB && hotlistHit} {isNPEDHitC && hotlistHit} + {hotlistNames && ( +
+

Hotlists

+
+ {hotlistNames.map((hotlistName) => ( +
+

+ {hotlistName ? hotlistName?.replace(/\.csv$/i, "") : "-"} +

+
+ ))} +
+
+ )}
([]); useNow(1000); const { state } = useSoundContext(); @@ -78,6 +79,14 @@ export default function SightingHistoryWidget({ className, title }: SightingHist const hasAutoOpenedRef = useRef(false); const npedRef = useRef(false); + const enqueue = useCallback((sighting: SightingType, kind: HitKind) => { + const id = sighting.vrm ?? sighting.ref; + if (processedRefs.current.has(id)) return; + processedRefs.current.add(id); + + setModalQueue((q) => [...q, { id, sighting, kind }]); + }, []); + const reduceObject = (obj: SightingType): ReducedSightingType => { return { vrm: obj.vrm, @@ -113,26 +122,15 @@ export default function SightingHistoryWidget({ className, title }: SightingHist const id = sighting.vrm; if (processedRefs.current.has(id)) continue; - const isHot = checkIsHotListHit(sighting); - const cat = sighting?.metadata?.npedJSON?.["NPED CATEGORY"]; + const isHotlistHit = checkIsHotListHit(sighting); + const npedcategory = sighting?.metadata?.npedJSON?.["NPED CATEGORY"]; + const isNPED = npedcategory === "A" || npedcategory === "B" || npedcategory === "C"; - if (cat === "A" || cat === "B" || cat === "C") { - npedSound(); - setSelectedSighting(sighting); - setSightingModalOpen(true); - processedRefs.current.add(id); - break; // stop after one new open per render cycle - } - - if (isHot) { - hotlistsound(); - setSelectedSighting(sighting); - setSightingModalOpen(true); - processedRefs.current.add(id); - break; + if (isNPED || isHotlistHit) { + enqueue(sighting, isNPED ? "NPED" : "HOTLIST"); // enqueue ONLY } } - }, [rows, hotlistsound, npedSound, setSightingModalOpen, setSelectedSighting]); + }, [rows, enqueue]); useEffect(() => { rows?.forEach((obj) => { @@ -165,22 +163,33 @@ export default function SightingHistoryWidget({ className, title }: SightingHist }); if (firstNPED) { - setSelectedSighting(firstNPED); - npedSound(); - setSightingModalOpen(true); + enqueue(firstNPED, "NPED"); + npedRef.current = true; } if (firstHot) { - setSelectedSighting(firstHot); - hotlistsound(); - setSightingModalOpen(true); + enqueue(firstHot, "HOTLIST"); + hasAutoOpenedRef.current = true; } - }, [hotlistsound, npedSound, setSelectedSighting]); + }, [enqueue, hotlistsound, npedSound, rows, setSelectedSighting, setSightingModalOpen]); + + 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]); const handleClose = () => { setSightingModalOpen(false); + setModalQueue((q) => q.slice(1)); }; return ( <> diff --git a/src/types/types.ts b/src/types/types.ts index 72a2369..504ae90 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -371,3 +371,11 @@ export type ModemSettingsType = { password: string; authenticationType: string; }; + +export type HitKind = "NPED" | "HOTLIST"; + +export type QueuedHit = { + id: number | string; + sighting: SightingType; + kind: HitKind; +}; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index dc164e9..537853e 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -147,10 +147,12 @@ export const checkIsHotListHit = (sigthing: SightingType | null) => { }; export function getHotlistName(obj: HotlistMatches | undefined) { - if (!obj || Object.values(obj).includes(false)) return; + if (!obj) return; - const keys = Object.keys(obj); - return keys; + const hotlistNames = Object.entries(obj) + .filter(([, value]) => value === true) + .map(([key]) => key); + return hotlistNames; } export const getNPEDCategory = (r?: SightingType | null) =>