From 18534ceb2c9ba9c65cb1ab8bbe38f0bac69d5356 Mon Sep 17 00:00:00 2001 From: Toba Ojo Date: Mon, 27 Oct 2025 08:28:44 +0000 Subject: [PATCH] - added functionality to save sighting sessions to black board --- src/components/SessionForm/SessionCard.tsx | 47 ++++++++++++------- src/context/NPEDUserContext.ts | 4 +- .../providers/NPEDUserContextProvider.tsx | 23 ++++++++- src/context/reducers/NPEDContextReducer.ts | 20 ++++++++ src/types/types.ts | 14 ++++++ 5 files changed, 87 insertions(+), 21 deletions(-) create mode 100644 src/context/reducers/NPEDContextReducer.ts diff --git a/src/components/SessionForm/SessionCard.tsx b/src/components/SessionForm/SessionCard.tsx index 588bc07..42cdd7f 100644 --- a/src/components/SessionForm/SessionCard.tsx +++ b/src/components/SessionForm/SessionCard.tsx @@ -6,30 +6,18 @@ import { toast } from "sonner"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faFloppyDisk, faPause, faPlay, faStop } from "@fortawesome/free-solid-svg-icons"; import VehicleSessionItem from "../UI/VehicleSessionItem"; +import { useCameraBlackboard } from "../../hooks/useCameraBlackboard"; const SessionCard = () => { - const { sessionStarted, setSessionStarted, sessionList, setSessionPaused, sessionPaused } = useNPEDContext(); - - const handleStartClick = () => { - setSessionStarted(!sessionStarted); - setSessionPaused(false); - toast(`${sessionStarted ? "Vehicle tracking session ended" : "Vehicle tracking session started"}`); - }; - - const handleSaveCick = () => { - console.log("clicked"); - }; - - const handlepauseClick = () => { - setSessionPaused(!sessionPaused); - toast(`${sessionStarted ? "Vehicle tracking session paused" : "Vehicle tracking session resumed"}`); - }; + const { sessionStarted, setSessionStarted, sessionList, setSessionPaused, sessionPaused, savedSightings } = + useNPEDContext(); + const { mutation } = useCameraBlackboard(); const sightings = [...new Map(sessionList.map((vehicle) => [vehicle.vrm, vehicle]))]; const dedupedSightings = sightings.map((sighting) => sighting[1]); - const vehicles = dedupedSightings.reduce>( + const vehicles = savedSightings.reduce>( (acc, item) => { const hotlisthit = Object.values(item.metadata?.hotlistMatches ?? {}).includes(true); if (item.metadata?.npedJSON["NPED CATEGORY"] === "A") acc.npedCatA.push(item); @@ -39,6 +27,7 @@ const SessionCard = () => { if (item.metadata?.npedJSON["TAX STATUS"] === false) acc.notTaxed.push(item); if (item.metadata?.npedJSON["MOT STATUS"] === false) acc.notMOT.push(item); if (hotlisthit) acc.hotlistHit.push(item); + acc.vehicles.push(item); return acc; }, { @@ -49,9 +38,31 @@ const SessionCard = () => { notTaxed: [], notMOT: [], hotlistHit: [], + vehicles: [], } ); + const handleStartClick = () => { + setSessionStarted(!sessionStarted); + setSessionPaused(false); + toast(`${sessionStarted ? "Vehicle tracking session ended" : "Vehicle tracking session started"}`); + }; + + const handlepauseClick = () => { + setSessionPaused(!sessionPaused); + toast(`${sessionStarted ? "Vehicle tracking session paused" : "Vehicle tracking session resumed"}`); + }; + + const handleSaveCick = async () => { + const result = await mutation.mutateAsync({ + operation: "INSERT", + path: "sessionStats", + value: dedupedSightings, + }); + + if (result.reason === "OK") toast.success("Session saved"); + }; + return ( @@ -94,7 +105,7 @@ const SessionCard = () => {
    diff --git a/src/context/NPEDUserContext.ts b/src/context/NPEDUserContext.ts index f776379..d4fba95 100644 --- a/src/context/NPEDUserContext.ts +++ b/src/context/NPEDUserContext.ts @@ -1,5 +1,5 @@ import { createContext, useContext, type SetStateAction } from "react"; -import type { NPEDUser, ReducedSightingType } from "../types/types"; +import type { DedupedSightings, NPEDUser, ReducedSightingType } from "../types/types"; type UserContextValue = { user: NPEDUser | null; @@ -10,6 +10,8 @@ type UserContextValue = { setSessionStarted: React.Dispatch>; sessionList: ReducedSightingType[]; setSessionList: React.Dispatch>; + savedSightings: DedupedSightings; + setSavedSightings: React.Dispatch>; }; export const NPEDUserContext = createContext(undefined); diff --git a/src/context/providers/NPEDUserContextProvider.tsx b/src/context/providers/NPEDUserContextProvider.tsx index 6241b8e..17b0d69 100644 --- a/src/context/providers/NPEDUserContextProvider.tsx +++ b/src/context/providers/NPEDUserContextProvider.tsx @@ -1,17 +1,34 @@ -import { useState, type ReactNode } from "react"; -import type { NPEDUser, ReducedSightingType } from "../../types/types"; +import { useEffect, useReducer, useState, type ReactNode } from "react"; +import type { DedupedSightings, NPEDUser, ReducedSightingType } from "../../types/types"; import { NPEDUserContext } from "../NPEDUserContext"; +import { useCameraBlackboard } from "../../hooks/useCameraBlackboard"; +import { initialState, reducer } from "../reducers/NPEDContextReducer"; type NPEDUserProviderType = { children: ReactNode; }; export const NPEDUserProvider = ({ children }: NPEDUserProviderType) => { + const [state, dispatch] = useReducer(reducer, initialState); + const { mutation } = useCameraBlackboard(); const [user, setUser] = useState(null); const [sessionStarted, setSessionStarted] = useState(false); const [sessionList, setSessionList] = useState([]); const [sessionPaused, setSessionPaused] = useState(false); + const [savedSightings, setSavedSightings] = useState([]); + useEffect(() => { + const fetchData = async () => { + const result = await mutation.mutateAsync({ + operation: "VIEW", + path: "sessionStats", + }); + if (!result.result) return; + setSavedSightings(result?.result); + }; + fetchData(); + }, []); + console.log(savedSightings); return ( { setSessionList, sessionPaused, setSessionPaused, + savedSightings, + setSavedSightings, }} > {children} diff --git a/src/context/reducers/NPEDContextReducer.ts b/src/context/reducers/NPEDContextReducer.ts new file mode 100644 index 0000000..4349bbc --- /dev/null +++ b/src/context/reducers/NPEDContextReducer.ts @@ -0,0 +1,20 @@ +import type { NPEDACTION, NPEDSTATE } from "../../types/types"; + +export const initialState = { + sessionStarted: false, + sessionList: [], + sessionPaused: false, + savedSightings: [], +}; + +export function reducer(state: NPEDSTATE, action: NPEDACTION) { + switch (action.type) { + case "SESSION": + return { + ...state, + sessionStarted: action.payload, + }; + default: + return { ...state }; + } +} diff --git a/src/types/types.ts b/src/types/types.ts index 504ae90..ef5e406 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -379,3 +379,17 @@ export type QueuedHit = { sighting: SightingType; kind: HitKind; }; + +export type DedupedSightings = ReducedSightingType[]; + +export type NPEDSTATE = { + sessionStarted: boolean; + sessionList: ReducedSightingType[]; + sessionPaused: boolean; + savedSightings: DedupedSightings; +}; + +export type NPEDACTION = { + type: string; + payload: any; +};