- added functionality to save sighting sessions to black board

This commit is contained in:
2025-10-27 08:28:44 +00:00
parent 9975e6a6ca
commit 18534ceb2c
5 changed files with 87 additions and 21 deletions

View File

@@ -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<Record<string, ReducedSightingType[]>>(
const vehicles = savedSightings.reduce<Record<string, ReducedSightingType[]>>(
(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 (
<Card className="p-4 col-span-3">
<CardHeader title="Session" />
@@ -94,7 +105,7 @@ const SessionCard = () => {
<ul className="text-white space-y-2">
<VehicleSessionItem
sessionNumber={dedupedSightings.length}
sessionNumber={vehicles.vehicles.length}
textColour="text-green-400"
vehicleTag={"Number of Vehicles sightings:"}
/>

View File

@@ -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<SetStateAction<boolean>>;
sessionList: ReducedSightingType[];
setSessionList: React.Dispatch<SetStateAction<ReducedSightingType[]>>;
savedSightings: DedupedSightings;
setSavedSightings: React.Dispatch<SetStateAction<DedupedSightings>>;
};
export const NPEDUserContext = createContext<UserContextValue | undefined>(undefined);

View File

@@ -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<NPEDUser | null>(null);
const [sessionStarted, setSessionStarted] = useState(false);
const [sessionList, setSessionList] = useState<ReducedSightingType[]>([]);
const [sessionPaused, setSessionPaused] = useState(false);
const [savedSightings, setSavedSightings] = useState<DedupedSightings | []>([]);
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 (
<NPEDUserContext.Provider
value={{
@@ -23,6 +40,8 @@ export const NPEDUserProvider = ({ children }: NPEDUserProviderType) => {
setSessionList,
sessionPaused,
setSessionPaused,
savedSightings,
setSavedSightings,
}}
>
{children}

View File

@@ -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 };
}
}

View File

@@ -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;
};