diff --git a/src/components/HistoryList/AlertItem.tsx b/src/components/HistoryList/AlertItem.tsx index ccdcb26..48c12ce 100644 --- a/src/components/HistoryList/AlertItem.tsx +++ b/src/components/HistoryList/AlertItem.tsx @@ -8,6 +8,7 @@ import { useAlertHitContext } from "../../context/AlertHitContext"; 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 } from "../../utils/utils"; type AlertItemProps = { item: SightingType; @@ -19,7 +20,8 @@ const AlertItem = ({ item }: AlertItemProps) => { // const {d} = useCameraBlackboard(); const motionAway = (item?.motion ?? "").toUpperCase() === "AWAY"; - const isHotListHit = item?.metadata?.hotlistMatches?.Hotlist0 === true; + + const isHotListHit = checkIsHotListHit(item); const isNPEDHitA = item?.metadata?.npedJSON?.["NPED CATEGORY"] === "A"; const isNPEDHitB = item?.metadata?.npedJSON?.["NPED CATEGORY"] === "B"; const isNPEDHitC = item?.metadata?.npedJSON?.["NPED CATEGORY"] === "C"; diff --git a/src/components/SessionForm/SessionCard.tsx b/src/components/SessionForm/SessionCard.tsx index 1394bb8..c722910 100644 --- a/src/components/SessionForm/SessionCard.tsx +++ b/src/components/SessionForm/SessionCard.tsx @@ -1,32 +1,80 @@ import Card from "../UI/Card"; import CardHeader from "../UI/CardHeader"; import { useNPEDContext } from "../../context/NPEDUserContext"; +import type { ReducedSightingType } from "../../types/types"; +import { toast } from "sonner"; const SessionCard = () => { const { sessionStarted, setSessionStarted, sessionList } = useNPEDContext(); const handleStartClick = () => { setSessionStarted(!sessionStarted); + toast( + `${ + sessionStarted + ? "Vehicle tracking session Ended" + : "Vehicle tracking session Started" + }` + ); }; + const sightings = [ + ...new Map(sessionList.map((vehicle) => [vehicle.vrm, vehicle])), + ]; + + const dedupedSightings = sightings.map((sighting) => sighting[1]); + + const vehicles = dedupedSightings.reduce< + Record + >( + (acc, item) => { + if (item.metadata?.npedJSON["NPED CATEGORY"] === "A") + acc.npedCatA.push(item); + if (item.metadata?.npedJSON["NPED CATEGORY"] === "B") + acc.npedCatB.push(item); + if (item.metadata?.npedJSON["NPED CATEGORY"] === "C") + acc.npedCatC.push(item); + if (item.metadata?.npedJSON["NPED CATEGORY"] === "D") + acc.npedCatD.push(item); + if (item.metadata?.npedJSON["TAX STATUS"] === false) + acc.notTaxed.push(item); + if (item.metadata?.npedJSON["MOT STATUS"] === false) + acc.notMOT.push(item); + + return acc; + }, + { + npedCatA: [], + npedCatB: [], + npedCatC: [], + npedCatD: [], + notTaxed: [], + notMOT: [], + } + ); + return (
    -
  • Number of Vehicles: {sessionList.length}
  • -
  • Vehicles without Tax:
  • -
  • Vehicles without MOT:
  • -
  • Vehicles with NPED Cat A:
  • -
  • Vehicles with NPED Cat B:
  • -
  • Vehicles with NPED Cat C:
  • +
  • Number of Vehicles: {dedupedSightings.length}
  • +
  • Vehicles without Tax: {vehicles.notTaxed.length}
  • +
  • Vehicles without MOT: {vehicles.notMOT.length}
  • +
  • Vehicles with NPED Cat A: {vehicles.npedCatA.length}
  • +
  • Vehicles with NPED Cat B: {vehicles.npedCatB.length}
  • +
  • Vehicles with NPED Cat C: {vehicles.npedCatC.length}
diff --git a/src/components/SettingForms/Sound/SoundSettingsFields.tsx b/src/components/SettingForms/Sound/SoundSettingsFields.tsx index af5e8f1..3cc4d6f 100644 --- a/src/components/SettingForms/Sound/SoundSettingsFields.tsx +++ b/src/components/SettingForms/Sound/SoundSettingsFields.tsx @@ -2,15 +2,14 @@ import { Field, FieldArray, Form, Formik } from "formik"; import FormGroup from "../components/FormGroup"; import type { FormValues, Hotlist } from "../../../types/types"; import { useSoundContext } from "../../../context/SoundContext"; +import { useCameraBlackboard } from "../../../hooks/useCameraBlackboard"; import { toast } from "sonner"; const SoundSettingsFields = () => { const { state, dispatch } = useSoundContext(); - const hotlists: Hotlist[] = [ - { name: "hotlist0", sound: "" }, - { name: "hotlist1", sound: "" }, - { name: "hotlist2", sound: "" }, - ]; + const { mutation } = useCameraBlackboard(); + + const hotlists: Hotlist[] = state.hotlists; const soundOptions = state?.soundOptions?.map((soundOption) => ({ value: soundOption?.name, @@ -23,9 +22,18 @@ const SoundSettingsFields = () => { hotlists, }; - const handleSubmit = (values: FormValues) => { + const handleSubmit = async (values: FormValues) => { dispatch({ type: "UPDATE", payload: values }); - toast.success("Sound settings updated"); + const result = await mutation.mutateAsync({ + operation: "INSERT", + path: "soundSettings", + value: values, + }); + if (result.reason !== "OK") { + toast.error("Cannot update sound settings"); + } else { + toast.success("Sound Settings successfully updated"); + } }; return ( @@ -68,8 +76,8 @@ const SoundSettingsFields = () => { name="hotlists" render={() => (
- {values.hotlists.length > 0 ? ( - values.hotlists.map((hotlist, index) => ( + {values?.hotlists?.length > 0 ? ( + values?.hotlists?.map((hotlist, index) => (
{ - // const isNPEDHit = obj?.metadata?.npedJSON?.status_code === 404; const isNPEDHitD = obj?.metadata?.npedJSON?.["NPED CATEGORY"] === "D"; return ( diff --git a/src/components/SightingsWidget/SightingWidget.tsx b/src/components/SightingsWidget/SightingWidget.tsx index 3305233..1e730f7 100644 --- a/src/components/SightingsWidget/SightingWidget.tsx +++ b/src/components/SightingsWidget/SightingWidget.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import type { SightingType } from "../../types/types"; +import type { ReducedSightingType, SightingType } from "../../types/types"; import { BLANK_IMG, getSoundFileURL } from "../../utils/utils"; import NumberPlate from "../PlateStack/NumberPlate"; import Card from "../UI/Card"; @@ -13,10 +13,12 @@ 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 { useNPEDContext } from "../../context/NPEDUserContext"; import { useSoundContext } from "../../context/SoundContext"; import Loading from "../UI/Loading"; +import { checkIsHotListHit } from "../../utils/utils"; function useNow(tickMs = 1000) { const [, setNow] = useState(() => Date.now()); @@ -43,11 +45,16 @@ export default function SightingHistoryWidget({ useNow(1000); const { state } = useSoundContext(); - const soundSrc = useMemo(() => { + const soundSrcNped = useMemo(() => { return getSoundFileURL(state.NPEDsound) ?? popup; }, [state.NPEDsound]); - const { play } = useSound(soundSrc); + const soundSrcHotlist = useMemo(() => { + return getSoundFileURL(state?.hotlists?.[0]?.sound) ?? notification; + }, [state.hotlists]); + + const { play: npedSound } = useSound(soundSrcNped); + const { play: hotlistsound } = useSound(soundSrcHotlist); const { sightings, setSelectedSighting, @@ -61,15 +68,24 @@ export default function SightingHistoryWidget({ const { dispatch } = useAlertHitContext(); const { sessionStarted, setSessionList, sessionList } = useNPEDContext(); + const reduceObject = (obj: SightingType): ReducedSightingType => { + return { + vrm: obj.vrm, + metadata: obj?.metadata, + }; + }; + useEffect(() => { if (sessionStarted) { if (!mostRecent) return; - setSessionList([...sessionList, mostRecent]); + const reducedMostRecent = reduceObject(mostRecent); + setSessionList([...sessionList, reducedMostRecent]); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [mostRecent, sessionStarted, setSessionList]); const hasAutoOpenedRef = useRef(false); + const npedRef = useRef(false); const onRowClick = useCallback( (sighting: SightingType) => { @@ -98,24 +114,43 @@ export default function SightingHistoryWidget({ }); } }); - }, [dispatch, rows]); + }, [dispatch]); useEffect(() => { - if (hasAutoOpenedRef.current) return; - const firstHot = rows?.find((r) => { - const isHotListHit = r?.metadata?.hotlistMatches?.Hotlist0 === true; + if (hasAutoOpenedRef.current || npedRef.current) return; + const firstNPED = rows.find((r) => { const isNPEDHitA = r?.metadata?.npedJSON?.["NPED CATEGORY"] === "A"; const isNPEDHitB = r?.metadata?.npedJSON?.["NPED CATEGORY"] === "B"; const isNPEDHitC = r?.metadata?.npedJSON?.["NPED CATEGORY"] === "C"; - return isNPEDHitA || isNPEDHitB || isNPEDHitC || isHotListHit; + return isNPEDHitA || isNPEDHitB || isNPEDHitC; }); + const firstHot = rows?.find((r) => { + const isHotListHit = checkIsHotListHit(r); + + return isHotListHit; + }); + + if (firstNPED) { + setSelectedSighting(firstNPED); + console.log("first"); + npedSound(); + setSightingModalOpen(true); + npedRef.current = true; + } + if (firstHot) { setSelectedSighting(firstHot); - play(); + hotlistsound(); setSightingModalOpen(true); hasAutoOpenedRef.current = true; } - }, [play, rows, setSelectedSighting, setSightingModalOpen]); + }, [ + hotlistsound, + npedSound, + rows, + setSelectedSighting, + setSightingModalOpen, + ]); const handleClose = () => { setSightingModalOpen(false); @@ -144,11 +179,8 @@ export default function SightingHistoryWidget({ obj?.metadata?.npedJSON?.["NPED CATEGORY"] === "B"; const isNPEDHitC = obj?.metadata?.npedJSON?.["NPED CATEGORY"] === "C"; - const isNPEDHitD = - obj?.metadata?.npedJSON?.["NPED CATEGORY"] === "D"; const motionAway = (obj?.motion ?? "").toUpperCase() === "AWAY"; - const isHotListHit = - obj?.metadata?.hotlistMatches?.Hotlist0 === true; + const isHotListHit = checkIsHotListHit(obj); return (
onRowClick(obj)} >
{ + const { mutation, query } = useCameraBlackboard(); const [enabled, setEnabled] = useSoundEnabled(); - const handleClick = () => { - setEnabled(!enabled); + const handleClick = async () => { + const newEnabled = !enabled; + setEnabled(newEnabled); + await mutation.mutateAsync({ + operation: "INSERT", + path: "soundEnabled", + value: { enabled: newEnabled }, + }); }; + useEffect(() => { + setEnabled(query?.data?.soundEnabled?.enabled); + }, [query?.data?.soundEnabled?.enabled, setEnabled]); return (