diff --git a/src/app/reducers/cameraFeedReducer.ts b/src/app/reducers/cameraFeedReducer.ts
index eca19d0..5a2b4f6 100644
--- a/src/app/reducers/cameraFeedReducer.ts
+++ b/src/app/reducers/cameraFeedReducer.ts
@@ -22,9 +22,9 @@ export const initialState: CameraFeedState = {
selectedRegionIndex: 0,
modeByCamera: {
- A: "brush",
- B: "brush",
- C: "brush",
+ A: "painter",
+ B: "painter",
+ C: "painter",
},
};
@@ -70,7 +70,6 @@ export function reducer(state: CameraFeedState, action: CameraFeedAction) {
},
};
case "REMOVE_REGION":
- console.log(action.payload);
return {
...state,
regionsByCamera: {
diff --git a/src/features/cameras/components/CameraGrid.tsx b/src/features/cameras/components/CameraGrid.tsx
index fc430aa..07fc554 100644
--- a/src/features/cameras/components/CameraGrid.tsx
+++ b/src/features/cameras/components/CameraGrid.tsx
@@ -3,7 +3,7 @@ import { useState } from "react";
import VideoFeedGridPainter from "./Video/VideoFeedGridPainter";
import CameraSettings from "./CameraSettings/CameraSettings";
-import PlatePatch from "./PlatePatch/PlatePatch";
+import PlatePatch from "./PlatePatch/SightingPatch";
const CameraGrid = () => {
const [tabIndex, setTabIndex] = useState(0);
diff --git a/src/features/cameras/components/PlatePatch/PlatePatch.tsx b/src/features/cameras/components/PlatePatch/PlatePatch.tsx
deleted file mode 100644
index 0feb48b..0000000
--- a/src/features/cameras/components/PlatePatch/PlatePatch.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-import Card from "../../../../ui/Card";
-
-const PlatePatch = () => {
- return PlatePatch;
-};
-
-export default PlatePatch;
diff --git a/src/features/cameras/components/PlatePatch/SightingEntryTable.tsx b/src/features/cameras/components/PlatePatch/SightingEntryTable.tsx
new file mode 100644
index 0000000..21cdb99
--- /dev/null
+++ b/src/features/cameras/components/PlatePatch/SightingEntryTable.tsx
@@ -0,0 +1,44 @@
+import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext";
+import type { DecodeReading } from "../../../../types/types";
+import { useSightingEntryAndExit } from "../../hooks/useSightingEntryAndExit";
+
+const SightingEntryTable = () => {
+ const { state } = useCameraFeedContext();
+ const cameraFeedID = state.cameraFeedID;
+ const { entryQuery } = useSightingEntryAndExit(cameraFeedID);
+
+ const isLoading = entryQuery?.isFetching;
+ const readings = entryQuery?.data?.decodes;
+
+ if (isLoading) return Loading Sighting data…;
+ return (
+
+
+
+
+
+ | VRM |
+ Lane ID |
+ Seen Count |
+ First Seen |
+ Last Seen |
+
+
+
+ {readings?.map((reading: DecodeReading) => (
+
+ | {reading?.vrm} |
+ {reading?.laneID} |
+ {reading?.seenCount} |
+ {reading?.firstSeenTimeHumane} |
+ {reading?.lastSeenTimeHumane} |
+
+ ))}
+
+
+
+
+ );
+};
+
+export default SightingEntryTable;
diff --git a/src/features/cameras/components/PlatePatch/SightingExitTable.tsx b/src/features/cameras/components/PlatePatch/SightingExitTable.tsx
new file mode 100644
index 0000000..7ca806c
--- /dev/null
+++ b/src/features/cameras/components/PlatePatch/SightingExitTable.tsx
@@ -0,0 +1,44 @@
+import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext";
+import type { DecodeReading } from "../../../../types/types";
+import { useSightingEntryAndExit } from "../../hooks/useSightingEntryAndExit";
+
+const SightingExitTable = () => {
+ const { state } = useCameraFeedContext();
+ const cameraFeedID = state.cameraFeedID;
+ const { exitQuery } = useSightingEntryAndExit(cameraFeedID);
+
+ const isLoading = exitQuery?.isFetching;
+ const readings = exitQuery?.data?.decodes;
+
+ if (isLoading) return Loading Sighting data…;
+ return (
+
+
+
+
+
+ | VRM |
+ Lane ID |
+ Seen Count |
+ First Seen |
+ Last Seen |
+
+
+
+ {readings?.map((reading: DecodeReading) => (
+
+ | {reading?.vrm} |
+ {reading?.laneID} |
+ {reading?.seenCount} |
+ {reading?.firstSeenTimeHumane} |
+ {reading?.lastSeenTimeHumane} |
+
+ ))}
+
+
+
+
+ );
+};
+
+export default SightingExitTable;
diff --git a/src/features/cameras/components/PlatePatch/SightingPatch.tsx b/src/features/cameras/components/PlatePatch/SightingPatch.tsx
new file mode 100644
index 0000000..052e72b
--- /dev/null
+++ b/src/features/cameras/components/PlatePatch/SightingPatch.tsx
@@ -0,0 +1,27 @@
+import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
+import Card from "../../../../ui/Card";
+import CardHeader from "../../../../ui/CardHeader";
+import SightingEntryTable from "./SightingEntryTable";
+import SightingExitTable from "./SightingExitTable";
+
+const PlatePatch = () => {
+ return (
+
+
+
+
+ Entry Sightings
+ Exit Sightings
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default PlatePatch;
diff --git a/src/features/cameras/components/Video/VideoFeedGridPainter.tsx b/src/features/cameras/components/Video/VideoFeedGridPainter.tsx
index 6aa48ef..e909df5 100644
--- a/src/features/cameras/components/Video/VideoFeedGridPainter.tsx
+++ b/src/features/cameras/components/Video/VideoFeedGridPainter.tsx
@@ -88,7 +88,7 @@ const VideoFeedGridPainter = () => {
const width = window.innerWidth;
const aspectRatio = 740 / 460;
- const newWidth = width * 0.36;
+ const newWidth = width * 0.39;
const newHeight = newWidth / aspectRatio;
setStageSize({ width: newWidth, height: newHeight });
};
diff --git a/src/features/cameras/hooks/useSightingEntryAndExit.ts b/src/features/cameras/hooks/useSightingEntryAndExit.ts
new file mode 100644
index 0000000..88860b3
--- /dev/null
+++ b/src/features/cameras/hooks/useSightingEntryAndExit.ts
@@ -0,0 +1,28 @@
+import { useQuery } from "@tanstack/react-query";
+import { CAMBASE } from "../../../utils/config";
+
+const fetchEntrySightings = async (cameraFeedID: string) => {
+ const response = await fetch(`${CAMBASE}/EntrySightingCreator${cameraFeedID}-list-proto-sightings`);
+ if (!response.ok) throw new Error("Cannot reach sighing entry endpoint");
+ return response.json();
+};
+
+const fetchExitSightings = async (cameraFeedID: string) => {
+ const response = await fetch(`${CAMBASE}/ExitSightingCreator${cameraFeedID}-list-proto-sightings`);
+ if (!response.ok) throw new Error("Cannot reach sighing exit endpoint");
+ return response.json();
+};
+
+export const useSightingEntryAndExit = (cameraFeedID: string) => {
+ const entryQuery = useQuery({
+ queryKey: ["Entry Sightings", cameraFeedID],
+ queryFn: () => fetchEntrySightings(cameraFeedID),
+ });
+
+ const exitQuery = useQuery({
+ queryKey: ["Exit Sightings", cameraFeedID],
+ queryFn: () => fetchExitSightings(cameraFeedID),
+ });
+
+ return { entryQuery, exitQuery };
+};
diff --git a/src/types/types.ts b/src/types/types.ts
index e012fca..d59e1ad 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -144,3 +144,15 @@ export type CameraFeedAction =
type: "RESET_PAINTED_CELLS";
payload: { cameraFeedID: "A" | "B" | "C"; paintedCells: Map };
};
+
+export type DecodeReading = {
+ id: number;
+ vrm: string;
+ laneID: number;
+ seenCount: number;
+ firstSeenTime?: number;
+ lastSeenTime?: number;
+ duplicate?: true;
+ firstSeenTimeHumane: string;
+ lastSeenTimeHumane: string;
+};