From 17a4a6de8d7e1565cc9b2b3d22c759a366dc6895 Mon Sep 17 00:00:00 2001 From: Toba Ojo Date: Wed, 8 Oct 2025 15:46:54 +0100 Subject: [PATCH] - updated state for tracking sessions - removed un used state in sighting feed - added groupings depending on sightings --- src/components/HistoryList/AlertItem.tsx | 2 + src/components/SessionForm/SessionCard.tsx | 64 ++++++++++++++++--- .../SightingsWidget/SightingWidget.tsx | 12 +++- src/context/NPEDUserContext.ts | 6 +- .../providers/NPEDUserContextProvider.tsx | 4 +- src/hooks/useSightingFeed.ts | 9 --- src/types/types.ts | 9 +++ 7 files changed, 82 insertions(+), 24 deletions(-) diff --git a/src/components/HistoryList/AlertItem.tsx b/src/components/HistoryList/AlertItem.tsx index ccdcb26..13053d6 100644 --- a/src/components/HistoryList/AlertItem.tsx +++ b/src/components/HistoryList/AlertItem.tsx @@ -19,6 +19,8 @@ const AlertItem = ({ item }: AlertItemProps) => { // const {d} = useCameraBlackboard(); const motionAway = (item?.motion ?? "").toUpperCase() === "AWAY"; + // [34].metadata.hotlistMatches["MAV_Hotlist.csv"] + //check if true is in any hotlist property const isHotListHit = item?.metadata?.hotlistMatches?.Hotlist0 === true; const isNPEDHitA = item?.metadata?.npedJSON?.["NPED CATEGORY"] === "A"; const isNPEDHitB = item?.metadata?.npedJSON?.["NPED CATEGORY"] === "B"; 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/SightingsWidget/SightingWidget.tsx b/src/components/SightingsWidget/SightingWidget.tsx index 3305233..754e03e 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"; @@ -61,10 +61,18 @@ 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]); diff --git a/src/context/NPEDUserContext.ts b/src/context/NPEDUserContext.ts index 749fd7d..7b36b9e 100644 --- a/src/context/NPEDUserContext.ts +++ b/src/context/NPEDUserContext.ts @@ -1,13 +1,13 @@ import { createContext, useContext, type SetStateAction } from "react"; -import type { NPEDUser, SightingType } from "../types/types"; +import type { NPEDUser, ReducedSightingType } from "../types/types"; type UserContextValue = { user: NPEDUser | null; setUser: React.Dispatch>; sessionStarted: boolean; setSessionStarted: React.Dispatch>; - sessionList: SightingType[]; - setSessionList: React.Dispatch>; + sessionList: ReducedSightingType[]; + setSessionList: React.Dispatch>; }; export const NPEDUserContext = createContext( diff --git a/src/context/providers/NPEDUserContextProvider.tsx b/src/context/providers/NPEDUserContextProvider.tsx index 2a15b3a..e76247f 100644 --- a/src/context/providers/NPEDUserContextProvider.tsx +++ b/src/context/providers/NPEDUserContextProvider.tsx @@ -1,5 +1,5 @@ import { useState, type ReactNode } from "react"; -import type { NPEDUser, SightingType } from "../../types/types"; +import type { NPEDUser, ReducedSightingType } from "../../types/types"; import { NPEDUserContext } from "../NPEDUserContext"; type NPEDUserProviderType = { @@ -9,7 +9,7 @@ type NPEDUserProviderType = { export const NPEDUserProvider = ({ children }: NPEDUserProviderType) => { const [user, setUser] = useState(null); const [sessionStarted, setSessionStarted] = useState(false); - const [sessionList, setSessionList] = useState([]); + const [sessionList, setSessionList] = useState([]); return ( ([]); const [selectedRef, setSelectedRef] = useState(null); const [sessionStarted, setSessionStarted] = useState(false); - const [sessionList, setSessionList] = useState([]); const mostRecent = sightings[0] ?? null; const latestRef = mostRecent?.ref ?? null; const [selectedSighting, setSelectedSighting] = useState( @@ -76,13 +75,6 @@ export function useSightingFeed(url: string | undefined) { staleTime: 0, }); - useEffect(() => { - if (sessionStarted) { - if (!mostRecent) return; - setSessionList([...sessionList, mostRecent]); - } - }, [mostRecent, sessionList, sessionStarted]); - useEffect(() => { const data = query.data; if (!data) return; @@ -129,7 +121,6 @@ export function useSightingFeed(url: string | undefined) { setSelectedRef, mostRecent, selectedSighting, - sessionList, sessionStarted, setSessionStarted, setSelectedSighting, diff --git a/src/types/types.ts b/src/types/types.ts index 6169124..8d35242 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -30,6 +30,11 @@ export type SightingType = { metadata?: Metadata; }; +export type ReducedSightingType = { + vrm: string; + metadata?: Metadata; +}; + export type CameraSettingValues = { friendlyName: string; cameraAddress: string; @@ -103,6 +108,10 @@ export type NpedJSON = { status_code: number; reason_phrase: string; "NPED CATEGORY": "A" | "B" | "C" | "D"; + "MOT STATUS": boolean; + "TAX STATUS": boolean; + vrm: string; + "INSURANCE STATUS": string; }; export type NPEDUser = {