- refactored state for sessionlist, and session active and pause states

This commit is contained in:
2025-10-27 11:04:53 +00:00
parent 251a2f5e7b
commit 2d5b264041
7 changed files with 44 additions and 41 deletions

View File

@@ -9,15 +9,18 @@ import VehicleSessionItem from "../UI/VehicleSessionItem";
import { useCameraBlackboard } from "../../hooks/useCameraBlackboard"; import { useCameraBlackboard } from "../../hooks/useCameraBlackboard";
const SessionCard = () => { const SessionCard = () => {
const { sessionStarted, setSessionStarted, sessionList, setSessionPaused, sessionPaused, savedSightings } = const { state, dispatch } = useIntegrationsContext();
useIntegrationsContext();
const { mutation } = useCameraBlackboard(); const { mutation } = useCameraBlackboard();
const sightings = [...new Map(sessionList.map((vehicle) => [vehicle.vrm, vehicle]))]; const sessionStarted = state.sessionStarted;
const sessionPaused = state.sessionPaused;
const sessionList = state.sessionList;
const sightings = [...new Map(sessionList?.map((vehicle) => [vehicle.vrm, vehicle]))];
const dedupedSightings = sightings.map((sighting) => sighting[1]); const dedupedSightings = sightings.map((sighting) => sighting[1]);
const vehicles = savedSightings.reduce<Record<string, ReducedSightingType[]>>( const vehicles = dedupedSightings.reduce<Record<string, ReducedSightingType[]>>(
(acc, item) => { (acc, item) => {
const hotlisthit = Object.values(item.metadata?.hotlistMatches ?? {}).includes(true); const hotlisthit = Object.values(item.metadata?.hotlistMatches ?? {}).includes(true);
if (item.metadata?.npedJSON["NPED CATEGORY"] === "A") acc.npedCatA.push(item); if (item.metadata?.npedJSON["NPED CATEGORY"] === "A") acc.npedCatA.push(item);
@@ -43,13 +46,13 @@ const SessionCard = () => {
); );
const handleStartClick = () => { const handleStartClick = () => {
setSessionStarted(!sessionStarted); dispatch({ type: "SESSIONSTART", payload: !sessionStarted });
setSessionPaused(false); dispatch({ type: "SESSIONPAUSE", payload: false });
toast(`${sessionStarted ? "Vehicle tracking session ended" : "Vehicle tracking session started"}`); toast(`${sessionStarted ? "Vehicle tracking session ended" : "Vehicle tracking session started"}`);
}; };
const handlepauseClick = () => { const handlepauseClick = () => {
setSessionPaused(!sessionPaused); dispatch({ type: "SESSIONPAUSE", payload: !sessionPaused });
toast(`${sessionStarted ? "Vehicle tracking session paused" : "Vehicle tracking session resumed"}`); toast(`${sessionStarted ? "Vehicle tracking session paused" : "Vehicle tracking session resumed"}`);
}; };

View File

@@ -127,8 +127,8 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }:
<div className="flex flex-col border-b border-gray-600 mb-4"> <div className="flex flex-col border-b border-gray-600 mb-4">
<p className="text-gray-300">Hotlists</p> <p className="text-gray-300">Hotlists</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-[90%] lg:gap-x-[15%] w-[50%]"> <div className="grid grid-cols-1 md:grid-cols-2 gap-x-[90%] lg:gap-x-[15%] w-[50%]">
{hotlistNames.map((hotlistName) => ( {hotlistNames.map((hotlistName, index) => (
<div className="items-center px-2.5 py-0.5 rounded-sm me-2 bg-amber-500 w-55 m-2"> <div className="items-center px-2.5 py-0.5 rounded-sm me-2 bg-amber-500 w-55 m-2" key={index}>
<p className="font-medium text-2xl break-all text-amber-800"> <p className="font-medium text-2xl break-all text-amber-800">
{hotlistName ? hotlistName?.replace(/\.csv$/i, "") : "-"} {hotlistName ? hotlistName?.replace(/\.csv$/i, "") : "-"}
</p> </p>

View File

@@ -70,9 +70,11 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
mostRecent, mostRecent,
isLoading, isLoading,
} = useSightingFeedContext(); } = useSightingFeedContext();
console.log(sightings);
const { dispatch } = useAlertHitContext(); const { dispatch } = useAlertHitContext();
const { sessionStarted, setSessionList, sessionList, sessionPaused } = useIntegrationsContext(); const { state: integrationState, dispatch: integrationDispatch } = useIntegrationsContext();
const sessionStarted = integrationState.sessionStarted;
const sessionPaused = integrationState.sessionPaused;
const processedRefs = useRef<Set<number | string>>(new Set()); const processedRefs = useRef<Set<number | string>>(new Set());
@@ -99,10 +101,10 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
if (!mostRecent) return; if (!mostRecent) return;
if (sessionPaused) return; if (sessionPaused) return;
const reducedMostRecent = reduceObject(mostRecent); const reducedMostRecent = reduceObject(mostRecent);
setSessionList([...sessionList, reducedMostRecent]); integrationDispatch({ type: "ADD", payload: reducedMostRecent });
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [mostRecent, sessionStarted, setSessionList]); }, [mostRecent, sessionStarted]);
const onRowClick = useCallback( const onRowClick = useCallback(
(sighting: SightingType) => { (sighting: SightingType) => {

View File

@@ -8,7 +8,11 @@ import { useIntegrationsContext } from "../../context/IntegrationsContext";
export default function Header() { export default function Header() {
const [isFullscreen, setIsFullscreen] = useState(false); const [isFullscreen, setIsFullscreen] = useState(false);
const { sessionStarted, sessionPaused } = useIntegrationsContext(); const { state } = useIntegrationsContext();
const sessionStarted = state.sessionStarted;
const sessionPaused = state.sessionPaused;
const toggleFullscreen = () => { const toggleFullscreen = () => {
if (!document.fullscreenElement) { if (!document.fullscreenElement) {

View File

@@ -1,15 +1,7 @@
import { createContext, useContext, type ActionDispatch, type SetStateAction } from "react"; import { createContext, useContext, type ActionDispatch } from "react";
import type { DedupedSightings, NPEDACTION, NPEDSTATE, ReducedSightingType } from "../types/types"; import type { NPEDACTION, NPEDSTATE } from "../types/types";
type IntegrationsValue = { type IntegrationsValue = {
sessionStarted: boolean;
sessionPaused: boolean;
setSessionPaused: React.Dispatch<SetStateAction<boolean>>;
setSessionStarted: React.Dispatch<SetStateAction<boolean>>;
sessionList: ReducedSightingType[];
setSessionList: React.Dispatch<SetStateAction<ReducedSightingType[]>>;
savedSightings: DedupedSightings;
setSavedSightings: React.Dispatch<SetStateAction<DedupedSightings>>;
state: NPEDSTATE; state: NPEDSTATE;
dispatch: ActionDispatch<[action: NPEDACTION]>; dispatch: ActionDispatch<[action: NPEDACTION]>;
}; };

View File

@@ -1,5 +1,4 @@
import { useEffect, useReducer, useState, type ReactNode } from "react"; import { useEffect, useReducer, type ReactNode } from "react";
import type { DedupedSightings, ReducedSightingType } from "../../types/types";
import { IntegrationsContext } from "../IntegrationsContext"; import { IntegrationsContext } from "../IntegrationsContext";
import { useCameraBlackboard } from "../../hooks/useCameraBlackboard"; import { useCameraBlackboard } from "../../hooks/useCameraBlackboard";
import { initialState, reducer } from "../reducers/IntegrationsContextReducer"; import { initialState, reducer } from "../reducers/IntegrationsContextReducer";
@@ -11,10 +10,6 @@ type IntegrationsProviderType = {
export const IntegrationsProvider = ({ children }: IntegrationsProviderType) => { export const IntegrationsProvider = ({ children }: IntegrationsProviderType) => {
const [state, dispatch] = useReducer(reducer, initialState); const [state, dispatch] = useReducer(reducer, initialState);
const { mutation } = useCameraBlackboard(); const { mutation } = useCameraBlackboard();
const [sessionStarted, setSessionStarted] = useState(false);
const [sessionList, setSessionList] = useState<ReducedSightingType[]>([]);
const [sessionPaused, setSessionPaused] = useState(false);
const [savedSightings, setSavedSightings] = useState<DedupedSightings | []>([]);
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
@@ -22,23 +17,15 @@ export const IntegrationsProvider = ({ children }: IntegrationsProviderType) =>
operation: "VIEW", operation: "VIEW",
path: "sessionStats", path: "sessionStats",
}); });
if (!result.result) return; if (!result.result || typeof result.result === "string") return;
setSavedSightings(result?.result);
dispatch({ type: "UPDATE", payload: result?.result });
}; };
fetchData(); fetchData();
}, []); }, []);
return ( return (
<IntegrationsContext.Provider <IntegrationsContext.Provider
value={{ value={{
setSessionStarted,
sessionStarted,
sessionList,
setSessionList,
sessionPaused,
setSessionPaused,
savedSightings,
setSavedSightings,
state, state,
dispatch, dispatch,
}} }}

View File

@@ -25,6 +25,21 @@ export function reducer(state: NPEDSTATE, action: NPEDACTION) {
...state, ...state,
npedUser: action.payload, npedUser: action.payload,
}; };
case "SESSIONPAUSE":
return {
...state,
sessionPaused: action.payload,
};
case "ADD":
return {
...state,
sessionList: [...state.sessionList, action.payload],
};
case "UPDATE":
return {
...state,
sessionList: action.payload,
};
default: default:
return { ...state }; return { ...state };
} }