From ce79591de0932b2f13de2adf3a5c098b0e7bc9fe Mon Sep 17 00:00:00 2001 From: Toba Ojo Date: Mon, 1 Dec 2025 14:36:25 +0000 Subject: [PATCH 1/2] - enhancedcamera settings and region painter. - Can send to the back end --- src/app/reducers/cameraFeedReducer.ts | 13 +++- .../CameraSettings/CameraSettings.tsx | 2 +- .../CameraSettings/ColourPicker.tsx | 1 + .../CameraSettings/RegionSelector.tsx | 69 +++++++++++++++++-- .../components/Video/VideoFeedGridPainter.tsx | 31 +++++---- .../cameras/hooks/useColourDetection.ts | 24 +++++++ src/types/types.ts | 11 +++ src/utils/utils.ts | 9 +++ 8 files changed, 139 insertions(+), 21 deletions(-) create mode 100644 src/features/cameras/hooks/useColourDetection.ts diff --git a/src/app/reducers/cameraFeedReducer.ts b/src/app/reducers/cameraFeedReducer.ts index 5a2b4f6..fa40d6a 100644 --- a/src/app/reducers/cameraFeedReducer.ts +++ b/src/app/reducers/cameraFeedReducer.ts @@ -12,12 +12,23 @@ export const initialState: CameraFeedState = { { name: "Region 1", brushColour: "#ff0000" }, { name: "Region 2", brushColour: "#00ff00" }, { name: "Region 3", brushColour: "#0400ff" }, + { name: "Region 4", brushColour: "#ffff00" }, + { name: "Region 5", brushColour: "#fc35db" }, ], B: [ { name: "Region 1", brushColour: "#ff0000" }, { name: "Region 2", brushColour: "#00ff00" }, + { name: "Region 3", brushColour: "#0400ff" }, + { name: "Region 4", brushColour: "#ffff00" }, + { name: "Region 5", brushColour: "#fc35db" }, + ], + C: [ + { name: "Region 1", brushColour: "#ff0000" }, + { name: "Region 2", brushColour: "#00ff00" }, + { name: "Region 3", brushColour: "#0400ff" }, + { name: "Region 4", brushColour: "#ffff00" }, + { name: "Region 5", brushColour: "#fc35db" }, ], - C: [{ name: "Region 1", brushColour: "#ff0000" }], }, selectedRegionIndex: 0, diff --git a/src/features/cameras/components/CameraSettings/CameraSettings.tsx b/src/features/cameras/components/CameraSettings/CameraSettings.tsx index b36f5f7..e0be2f8 100644 --- a/src/features/cameras/components/CameraSettings/CameraSettings.tsx +++ b/src/features/cameras/components/CameraSettings/CameraSettings.tsx @@ -10,7 +10,7 @@ type CameraSettingsProps = { const CameraSettings = ({ tabIndex, setTabIndex }: CameraSettingsProps) => { return ( - + { name="" id="" value={colour} + disabled onChange={(e) => setColour(e.target.value)} className="h-8 w-8 p-0 rounded-md border border-slate-500 cursor-pointer" /> diff --git a/src/features/cameras/components/CameraSettings/RegionSelector.tsx b/src/features/cameras/components/CameraSettings/RegionSelector.tsx index 6918f2f..135511d 100644 --- a/src/features/cameras/components/CameraSettings/RegionSelector.tsx +++ b/src/features/cameras/components/CameraSettings/RegionSelector.tsx @@ -1,6 +1,7 @@ -import type { PaintedCell, Region } from "../../../../types/types"; +import type { ColourData, PaintedCell, Region } from "../../../../types/types"; import ColourPicker from "./ColourPicker"; import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext"; +import { useColourDectection } from "../../hooks/useColourDetection"; type RegionSelectorProps = { regions: Region[]; @@ -10,7 +11,10 @@ type RegionSelectorProps = { }; const RegionSelector = ({ regions, selectedRegionIndex, mode, cameraFeedID }: RegionSelectorProps) => { - const { dispatch } = useCameraFeedContext(); + const { colourMutation } = useColourDectection(); + const { state, dispatch } = useCameraFeedContext(); + const paintedCells = state.paintedCells[cameraFeedID]; + const handleChange = (e: { target: { value: string } }) => { dispatch({ type: "CHANGE_MODE", payload: { cameraFeedID: cameraFeedID, mode: e.target.value } }); }; @@ -54,6 +58,53 @@ const RegionSelector = ({ regions, selectedRegionIndex, mode, cameraFeedID }: Re }); }; + const handleSaveclick = () => { + const regions: ColourData[] = []; + const test = Array.from(paintedCells.entries()); + const region1 = test.filter(([, cell]) => cell.region.name === "Region 1"); + const region2 = test.filter(([, cell]) => cell.region.name === "Region 2"); + const region3 = test.filter(([, cell]) => cell.region.name === "Region 3"); + const region4 = test.filter(([, cell]) => cell.region.name === "Region 4"); + const region5 = test.filter(([, cell]) => cell.region.name === "Region 5"); + const region1Data = { + id: 1, + cells: region1.map(([key]) => [parseInt(key.split("-")[1]), parseInt(key.split("-")[0])]), + }; + const region2Data = { + id: 2, + cells: region2.map(([key]) => [parseInt(key.split("-")[1]), parseInt(key.split("-")[0])]), + }; + const region3Data = { + id: 3, + cells: region3.map(([key]) => [parseInt(key.split("-")[1]), parseInt(key.split("-")[0])]), + }; + const region4Data = { + id: 4, + cells: region4.map(([key]) => [parseInt(key.split("-")[1]), parseInt(key.split("-")[0])]), + }; + const region5Data = { + id: 5, + cells: region5.map(([key]) => [parseInt(key.split("-")[1]), parseInt(key.split("-")[0])]), + }; + if (region1Data.cells.length > 0) { + regions.push(region1Data); + } + if (region2Data.cells.length > 0) { + regions.push(region2Data); + } + if (region3Data.cells.length > 0) { + regions.push(region3Data); + } + if (region4Data.cells.length > 0) { + regions.push(region4Data); + } + if (region5Data.cells.length > 0) { + regions.push(region5Data); + } + + colourMutation.mutate({ cameraFeedID, regions: regions }); + }; + return (
@@ -103,7 +154,7 @@ const RegionSelector = ({ regions, selectedRegionIndex, mode, cameraFeedID }: Re ); })}
- -
@@ -139,6 +190,12 @@ const RegionSelector = ({ regions, selectedRegionIndex, mode, cameraFeedID }: Re

Actions

+ + + + ); +}; + +export default SystemConfig; diff --git a/src/features/settings/hooks/useSystemSettings.ts b/src/features/settings/hooks/useSystemSettings.ts new file mode 100644 index 0000000..46eb4e8 --- /dev/null +++ b/src/features/settings/hooks/useSystemSettings.ts @@ -0,0 +1,54 @@ +import { useQuery, useMutation } from "@tanstack/react-query"; +import { CAMBASE } from "../../../utils/config"; +import type { SystemSettings } from "../../../types/types"; +const camBase = import.meta.env.MODE !== "development" ? CAMBASE : ""; + +const fetchSystemSettings = async () => { + const response = await fetch(`${camBase}/api/fetch-config?id=GLOBAL--Device`); + if (!response.ok) { + throw new Error("Failed to fetch system settings"); + } + return response.json(); +}; + +const postSystemSettings = async (settings: SystemSettings) => { + const systemSettingConfig = { + id: "GLOBAL--Device", + fields: [ + { property: "propDeviceName", value: settings.deviceName }, + { property: "propSNTPServer", value: settings.SNTPServer }, + { + property: "propSNTPIntervalMinutes", + value: Number(settings.SNTPIntervalMinutes), + }, + { property: "propLocalTimeZone", value: settings.localTimeZone }, + { property: "propTimeSource", value: settings.timeSource }, + ], + }; + + const response = await fetch(`${camBase}/api/update-config`, { + method: "POST", + body: JSON.stringify(systemSettingConfig), + headers: { + "Content-Type": "application/json", + }, + }); + if (!response.ok) { + throw new Error("Failed to update system settings"); + } + return response.json(); +}; + +export const useSystemSettings = () => { + const systemSettingsQuery = useQuery({ + queryKey: ["systemSettings"], + queryFn: fetchSystemSettings, + }); + + const systemSettingsMutation = useMutation({ + mutationKey: ["updateSystemSettings"], + mutationFn: postSystemSettings, + }); + + return { systemSettingsQuery, systemSettingsMutation }; +}; diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 6621494..5fff20b 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -2,12 +2,14 @@ import { createRootRoute, Outlet } from "@tanstack/react-router"; import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; import Header from "../ui/Header"; import Footer from "../ui/Footer"; +import { Toaster } from "sonner"; const RootLayout = () => ( <>
+