diff --git a/package.json b/package.json index d2f2808..7beb15a 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "react-tabs": "^6.1.0", "react-use": "^17.6.0", "sonner": "^2.0.7", - "tailwindcss": "^4.1.11" + "tailwindcss": "^4.1.11", + "use-debounce": "^10.0.6" }, "devDependencies": { "@eslint/js": "^9.32.0", diff --git a/src/App.tsx b/src/App.tsx index 3d9f929..980e322 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,7 +5,7 @@ import FrontCamera from "./pages/FrontCamera"; import RearCamera from "./pages/RearCamera"; import SystemSettings from "./pages/SystemSettings"; import Session from "./pages/Session"; -import { NPEDUserProvider } from "./context/providers/NPEDUserContextProvider"; +import { IntegrationsProvider } from "./context/providers/IntegrationsContextProvider"; import { AlertHitProvider } from "./context/providers/AlertHitProvider"; import { SoundProvider } from "react-sounds"; import SoundContextProvider from "./context/providers/SoundContextProvider"; @@ -14,7 +14,7 @@ function App() { return ( - + }> @@ -27,7 +27,7 @@ function App() { - + ); diff --git a/src/assets/sounds/ui/Attention.wav b/src/assets/sounds/ui/Attention.wav new file mode 100644 index 0000000..150341b Binary files /dev/null and b/src/assets/sounds/ui/Attention.wav differ diff --git a/src/assets/sounds/ui/Warning.wav b/src/assets/sounds/ui/Warning.wav index e9b946e..db8a59f 100644 Binary files a/src/assets/sounds/ui/Warning.wav and b/src/assets/sounds/ui/Warning.wav differ diff --git a/src/components/SessionForm/SessionCard.tsx b/src/components/SessionForm/SessionCard.tsx index a5dc93e..4d0cab2 100644 --- a/src/components/SessionForm/SessionCard.tsx +++ b/src/components/SessionForm/SessionCard.tsx @@ -1,30 +1,36 @@ import Card from "../UI/Card"; import CardHeader from "../UI/CardHeader"; -import { useNPEDContext } from "../../context/NPEDUserContext"; +import { useIntegrationsContext } from "../../context/IntegrationsContext"; import type { ReducedSightingType } from "../../types/types"; 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 } = useNPEDContext(); + const { state, dispatch } = useIntegrationsContext(); + const { mutation } = useCameraBlackboard(); - const handleStartClick = () => { - setSessionStarted(!sessionStarted); - toast(`${sessionStarted ? "Vehicle tracking session Ended" : "Vehicle tracking session Started"}`); - }; + const sessionStarted = state.sessionStarted; + const sessionPaused = state.sessionPaused; + const sessionList = state.sessionList; - const sightings = [...new Map(sessionList.map((vehicle) => [vehicle.vrm, vehicle]))]; + const sightings = [...new Map(sessionList?.map((vehicle) => [vehicle.vrm, vehicle]))]; const dedupedSightings = sightings.map((sighting) => sighting[1]); const vehicles = dedupedSightings.reduce>( (acc, item) => { + 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"] === "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); - + if (hotlisthit) acc.hotlistHit.push(item); + acc.vehicles.push(item); return acc; }, { @@ -34,9 +40,32 @@ const SessionCard = () => { npedCatD: [], notTaxed: [], notMOT: [], + hotlistHit: [], + vehicles: [], } ); + const handleStartClick = () => { + dispatch({ type: "SESSIONSTART", payload: !sessionStarted }); + dispatch({ type: "SESSIONPAUSE", payload: false }); + toast(`${sessionStarted ? "Vehicle tracking session ended" : "Vehicle tracking session started"}`); + }; + + const handlepauseClick = () => { + dispatch({ type: "SESSIONPAUSE", payload: !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 ( @@ -47,34 +76,72 @@ const SessionCard = () => { } transition w-full`} onClick={handleStartClick} > - {sessionStarted ? "End Session" : "Start Session"} +
+ +

{sessionStarted ? "End Session" : "Start Session"}

+
+
+ {sessionStarted && ( + + )} + {sessionStarted && ( + + )} +
    -
  • -

    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/NPED/NPEDFields.tsx b/src/components/SettingForms/NPED/NPEDFields.tsx index 3e42d24..795c074 100644 --- a/src/components/SettingForms/NPED/NPEDFields.tsx +++ b/src/components/SettingForms/NPED/NPEDFields.tsx @@ -6,16 +6,18 @@ import { toast } from "sonner"; import { faEyeSlash, faEye } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useState } from "react"; +import { useIntegrationsContext } from "../../../context/IntegrationsContext"; const NPEDFields = () => { + const { state } = useIntegrationsContext(); const [showPwd, setShowPwd] = useState(false); - const { signIn, user, signOut } = useNPEDAuth(); + const { signIn, signOut } = useNPEDAuth(); - const initialValues = user + const initialValues = state.npedUser ? { - username: user?.propUsername?.value, - password: user?.propPassword?.value, - clientId: user?.propClientID?.value, + username: state.npedUser?.propUsername?.value, + password: state.npedUser?.propPassword?.value, + clientId: state.npedUser?.propClientID?.value, frontId: "NPED", rearId: "NPED", } @@ -48,20 +50,13 @@ const NPEDFields = () => { }; return ( - + {({ errors, touched, isSubmitting }) => (
{touched.username && errors.username && ( - - {errors.username} - + {errors.username} )} { className="p-2 border border-gray-400 rounded-lg w-full" /> {touched.password && errors.password && ( - - {errors.password} - + {errors.password} )} { {touched.clientId && errors.clientId && ( - - {errors.clientId} - + {errors.clientId} )} { className="p-1.5 border border-gray-400 rounded-lg" /> - {!user?.propClientID?.value ? ( + {!state.npedUser?.propClientID?.value ? (