2025-09-08 15:21:17 +01:00
|
|
|
import Card from "../UI/Card";
|
|
|
|
|
import CardHeader from "../UI/CardHeader";
|
2025-10-27 09:35:59 +00:00
|
|
|
import { useIntegrationsContext } from "../../context/IntegrationsContext";
|
2025-10-08 15:46:54 +01:00
|
|
|
import type { ReducedSightingType } from "../../types/types";
|
|
|
|
|
import { toast } from "sonner";
|
2025-10-22 08:54:42 +01:00
|
|
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
|
|
|
import { faFloppyDisk, faPause, faPlay, faStop } from "@fortawesome/free-solid-svg-icons";
|
2025-10-24 12:10:10 +01:00
|
|
|
import VehicleSessionItem from "../UI/VehicleSessionItem";
|
2025-10-27 08:28:44 +00:00
|
|
|
import { useCameraBlackboard } from "../../hooks/useCameraBlackboard";
|
2025-09-08 15:21:17 +01:00
|
|
|
|
|
|
|
|
const SessionCard = () => {
|
2025-10-27 11:04:53 +00:00
|
|
|
const { state, dispatch } = useIntegrationsContext();
|
2025-10-27 08:28:44 +00:00
|
|
|
const { mutation } = useCameraBlackboard();
|
2025-10-24 12:10:10 +01:00
|
|
|
|
2025-10-27 11:04:53 +00:00
|
|
|
const sessionStarted = state.sessionStarted;
|
|
|
|
|
const sessionPaused = state.sessionPaused;
|
|
|
|
|
const sessionList = state.sessionList;
|
|
|
|
|
|
|
|
|
|
const sightings = [...new Map(sessionList?.map((vehicle) => [vehicle.vrm, vehicle]))];
|
2025-10-08 15:46:54 +01:00
|
|
|
|
|
|
|
|
const dedupedSightings = sightings.map((sighting) => sighting[1]);
|
|
|
|
|
|
2025-10-27 11:04:53 +00:00
|
|
|
const vehicles = dedupedSightings.reduce<Record<string, ReducedSightingType[]>>(
|
2025-10-08 15:46:54 +01:00
|
|
|
(acc, item) => {
|
2025-10-22 08:54:42 +01:00
|
|
|
const hotlisthit = Object.values(item.metadata?.hotlistMatches ?? {}).includes(true);
|
2025-10-15 15:15:04 +01:00
|
|
|
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);
|
2025-10-22 08:54:42 +01:00
|
|
|
if (hotlisthit) acc.hotlistHit.push(item);
|
2025-10-27 08:28:44 +00:00
|
|
|
acc.vehicles.push(item);
|
2025-10-08 15:46:54 +01:00
|
|
|
return acc;
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
npedCatA: [],
|
|
|
|
|
npedCatB: [],
|
|
|
|
|
npedCatC: [],
|
|
|
|
|
npedCatD: [],
|
|
|
|
|
notTaxed: [],
|
|
|
|
|
notMOT: [],
|
2025-10-22 08:54:42 +01:00
|
|
|
hotlistHit: [],
|
2025-10-27 08:28:44 +00:00
|
|
|
vehicles: [],
|
2025-10-08 15:46:54 +01:00
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2025-10-27 08:28:44 +00:00
|
|
|
const handleStartClick = () => {
|
2025-10-27 11:04:53 +00:00
|
|
|
dispatch({ type: "SESSIONSTART", payload: !sessionStarted });
|
|
|
|
|
dispatch({ type: "SESSIONPAUSE", payload: false });
|
2025-10-27 08:28:44 +00:00
|
|
|
toast(`${sessionStarted ? "Vehicle tracking session ended" : "Vehicle tracking session started"}`);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handlepauseClick = () => {
|
2025-10-27 11:04:53 +00:00
|
|
|
dispatch({ type: "SESSIONPAUSE", payload: !sessionPaused });
|
2025-10-27 08:28:44 +00:00
|
|
|
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");
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-08 15:21:17 +01:00
|
|
|
return (
|
2025-10-15 15:15:04 +01:00
|
|
|
<Card className="p-4 col-span-3">
|
2025-09-16 14:20:38 +01:00
|
|
|
<CardHeader title="Session" />
|
2025-10-15 15:15:04 +01:00
|
|
|
<div className="flex flex-col gap-4 px-3">
|
2025-09-08 15:21:17 +01:00
|
|
|
<button
|
2025-10-15 15:15:04 +01:00
|
|
|
className={`${sessionStarted ? "bg-red-600" : "bg-[#26B170]"} text-white px-4 py-2 rounded ${
|
2025-10-08 15:46:54 +01:00
|
|
|
sessionStarted ? "hover:bg-red-700" : "hover:bg-green-700"
|
|
|
|
|
} transition w-full`}
|
2025-09-25 10:38:49 +01:00
|
|
|
onClick={handleStartClick}
|
2025-09-08 15:21:17 +01:00
|
|
|
>
|
2025-10-22 08:54:42 +01:00
|
|
|
<div className="flex flex-row gap-3 items-center justify-self-center">
|
|
|
|
|
<FontAwesomeIcon icon={sessionStarted ? faStop : faPlay} />
|
|
|
|
|
<p>{sessionStarted ? "End Session" : "Start Session"}</p>
|
|
|
|
|
</div>
|
2025-09-08 15:21:17 +01:00
|
|
|
</button>
|
2025-10-22 08:54:42 +01:00
|
|
|
<div className="flex flex-col lg:flex-row gap-5">
|
|
|
|
|
{sessionStarted && (
|
|
|
|
|
<button
|
|
|
|
|
className={`bg-blue-600 text-white px-4 py-2 rounded transition w-full lg:w-[50%]`}
|
|
|
|
|
onClick={handleSaveCick}
|
|
|
|
|
>
|
|
|
|
|
<div className="flex flex-row gap-3 items-center justify-self-center">
|
|
|
|
|
<FontAwesomeIcon icon={faFloppyDisk} />
|
|
|
|
|
<p>Save session</p>
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
{sessionStarted && (
|
|
|
|
|
<button
|
|
|
|
|
className={`bg-gray-300 text-gray-800 px-4 py-2 rounded transition w-full lg:w-[50%]`}
|
2025-10-24 12:10:10 +01:00
|
|
|
onClick={handlepauseClick}
|
2025-10-22 08:54:42 +01:00
|
|
|
>
|
|
|
|
|
<div className="flex flex-row gap-3 items-center justify-self-center">
|
2025-10-24 12:10:10 +01:00
|
|
|
<FontAwesomeIcon icon={sessionPaused ? faPlay : faPause} />
|
|
|
|
|
<p>{sessionPaused ? "Resume session" : "Pause session"}</p>
|
2025-10-22 08:54:42 +01:00
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2025-09-16 14:20:38 +01:00
|
|
|
|
|
|
|
|
<ul className="text-white space-y-2">
|
2025-10-24 12:10:10 +01:00
|
|
|
<VehicleSessionItem
|
2025-10-27 08:28:44 +00:00
|
|
|
sessionNumber={vehicles.vehicles.length}
|
2025-10-24 12:10:10 +01:00
|
|
|
textColour="text-green-400"
|
|
|
|
|
vehicleTag={"Number of Vehicles sightings:"}
|
|
|
|
|
/>
|
|
|
|
|
<VehicleSessionItem
|
|
|
|
|
sessionNumber={vehicles.notTaxed.length}
|
|
|
|
|
textColour="text-amber-400"
|
|
|
|
|
vehicleTag={"Vehicles without Tax:"}
|
|
|
|
|
/>
|
|
|
|
|
<VehicleSessionItem
|
|
|
|
|
sessionNumber={vehicles.notMOT.length}
|
|
|
|
|
textColour="text-red-500"
|
|
|
|
|
vehicleTag={"Vehicles without MOT:"}
|
|
|
|
|
/>
|
|
|
|
|
<VehicleSessionItem
|
|
|
|
|
sessionNumber={vehicles.hotlistHit.length}
|
|
|
|
|
textColour="text-blue-400"
|
|
|
|
|
vehicleTag={"Vehicles on Hotlists:"}
|
|
|
|
|
/>
|
|
|
|
|
<VehicleSessionItem
|
|
|
|
|
sessionNumber={vehicles.npedCatA.length}
|
|
|
|
|
textColour="text-gray-300"
|
|
|
|
|
vehicleTag={"Vehicles with NPED Cat A:"}
|
|
|
|
|
/>
|
|
|
|
|
<VehicleSessionItem
|
|
|
|
|
sessionNumber={vehicles.npedCatB.length}
|
|
|
|
|
textColour="text-gray-300"
|
|
|
|
|
vehicleTag={"Vehicles with NPED Cat B:"}
|
|
|
|
|
/>
|
|
|
|
|
<VehicleSessionItem
|
|
|
|
|
sessionNumber={vehicles.npedCatC.length}
|
|
|
|
|
textColour="text-gray-300"
|
|
|
|
|
vehicleTag={"Vehicles with NPED Cat C:"}
|
|
|
|
|
/>
|
2025-09-16 14:20:38 +01:00
|
|
|
</ul>
|
2025-09-08 15:21:17 +01:00
|
|
|
</div>
|
|
|
|
|
</Card>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default SessionCard;
|