diff --git a/src/app/reducers/cameraFeedReducer.ts b/src/app/reducers/cameraFeedReducer.ts index 64f8f36..eca19d0 100644 --- a/src/app/reducers/cameraFeedReducer.ts +++ b/src/app/reducers/cameraFeedReducer.ts @@ -7,6 +7,25 @@ export const initialState: CameraFeedState = { B: new Map(), C: new Map(), }, + regionsByCamera: { + A: [ + { name: "Region 1", brushColour: "#ff0000" }, + { name: "Region 2", brushColour: "#00ff00" }, + { name: "Region 3", brushColour: "#0400ff" }, + ], + B: [ + { name: "Region 1", brushColour: "#ff0000" }, + { name: "Region 2", brushColour: "#00ff00" }, + ], + C: [{ name: "Region 1", brushColour: "#ff0000" }], + }, + + selectedRegionIndex: 0, + modeByCamera: { + A: "brush", + B: "brush", + C: "brush", + }, }; export function reducer(state: CameraFeedState, action: CameraFeedAction) { @@ -16,6 +35,60 @@ export function reducer(state: CameraFeedState, action: CameraFeedAction) { ...state, cameraFeedID: action.payload, }; + case "CHANGE_MODE": + return { + ...state, + modeByCamera: { + ...state.modeByCamera, + [action.payload.cameraFeedID]: action.payload.mode, + }, + }; + case "SET_SELECTED_REGION_INDEX": + return { + ...state, + selectedRegionIndex: action.payload, + }; + case "SET_SELECTED_REGION_COLOUR": + return { + ...state, + regionsByCamera: { + ...state.regionsByCamera, + [action.payload.cameraFeedID]: state.regionsByCamera[action.payload.cameraFeedID].map((region) => + region.name === action.payload.regionName ? { ...region, brushColour: action.payload.newColour } : region, + ), + }, + }; + case "ADD_NEW_REGION": + return { + ...state, + regionsByCamera: { + ...state.regionsByCamera, + [action.payload.cameraFeedID]: [ + ...state.regionsByCamera[action.payload.cameraFeedID], + { name: action.payload.regionName, brushColour: action.payload.brushColour }, + ], + }, + }; + case "REMOVE_REGION": + console.log(action.payload); + return { + ...state, + regionsByCamera: { + ...state.regionsByCamera, + [action.payload.cameraFeedID]: state.regionsByCamera[action.payload.cameraFeedID].filter( + (region) => region.name !== action.payload.regionName, + ), + }, + }; + case "RESET_PAINTED_CELLS": + return { + ...state, + paintedCells: { + ...state.paintedCells, + [state.cameraFeedID]: new Map(), + }, + }; + default: return state; } diff --git a/src/features/cameras/components/CameraGrid.tsx b/src/features/cameras/components/CameraGrid.tsx index 649f8a3..fc430aa 100644 --- a/src/features/cameras/components/CameraGrid.tsx +++ b/src/features/cameras/components/CameraGrid.tsx @@ -1,52 +1,17 @@ -import { useRef, useState } from "react"; +import { useState } from "react"; import VideoFeedGridPainter from "./Video/VideoFeedGridPainter"; import CameraSettings from "./CameraSettings/CameraSettings"; -import type { PaintedCell, Region } from "../../../types/types"; + import PlatePatch from "./PlatePatch/PlatePatch"; const CameraGrid = () => { - const [regions, setRegions] = useState([ - { name: "Region 1", brushColour: "#ff0000" }, - { name: "Region 2", brushColour: "#00ff00" }, - { name: "Region 3", brushColour: "#0400ff" }, - ]); - const [selectedRegionIndex, setSelectedRegionIndex] = useState(0); - const [mode, setMode] = useState(""); const [tabIndex, setTabIndex] = useState(0); - const updateRegionColour = (index: number, newColour: string) => { - setRegions((prev) => prev.map((r, i) => (i === index ? { ...r, brushColour: newColour } : r))); - }; - - const paintedCellsRef = useRef>(new Map()); - return (
- - { - setRegions((prev) => [...prev, { name: `Region ${prev.length + 1}`, brushColour: "#ffffff" }]); - }} - OnRemoveRegion={() => { - setRegions((prev) => prev.filter((_, i) => i !== selectedRegionIndex)); - setSelectedRegionIndex((prev) => (prev > 0 ? prev - 1 : 0)); - }} - /> + +
); diff --git a/src/features/cameras/components/CameraSettings/CameraPanel.tsx b/src/features/cameras/components/CameraSettings/CameraPanel.tsx index c2938d2..fff0e53 100644 --- a/src/features/cameras/components/CameraSettings/CameraPanel.tsx +++ b/src/features/cameras/components/CameraSettings/CameraPanel.tsx @@ -1,33 +1,45 @@ import { useEffect } from "react"; import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext"; +import RegionSelector from "./RegionSelector"; type CameraPanelProps = { tabIndex: number; }; const CameraPanel = ({ tabIndex }: CameraPanelProps) => { - const { dispatch } = useCameraFeedContext(); + const { state, dispatch } = useCameraFeedContext(); + const cameraFeedID = state.cameraFeedID; + const regions = state.regionsByCamera[cameraFeedID]; + + const selectedRegionIndex = state.selectedRegionIndex; + const mode = state.modeByCamera[cameraFeedID]; useEffect(() => { const mapIndextoCameraId = () => { switch (tabIndex) { - case 1: + case 0: return "A"; - case 2: + case 1: return "B"; - case 3: + case 2: return "C"; default: - return null; + return "A"; } }; const cameraId = mapIndextoCameraId(); - console.log(cameraId); dispatch({ type: "SET_CAMERA_FEED", payload: cameraId }); }, [dispatch, tabIndex]); - return
CameraPanel
; + return ( + + ); }; export default CameraPanel; diff --git a/src/features/cameras/components/CameraSettings/CameraSettings.tsx b/src/features/cameras/components/CameraSettings/CameraSettings.tsx index 4a4d8d7..b36f5f7 100644 --- a/src/features/cameras/components/CameraSettings/CameraSettings.tsx +++ b/src/features/cameras/components/CameraSettings/CameraSettings.tsx @@ -1,38 +1,14 @@ import Card from "../../../../ui/Card"; import { Tab, Tabs, TabList, TabPanel } from "react-tabs"; import "react-tabs/style/react-tabs.css"; -import RegionSelector from "./RegionSelector"; -import type { PaintedCell, Region } from "../../../../types/types"; -import type { RefObject } from "react"; import CameraPanel from "./CameraPanel"; type CameraSettingsProps = { - regions: Region[]; - selectedRegionIndex: number; - onSelectRegion: (index: number) => void; - onChangeRegionColour: (index: number, colour: string) => void; - mode: string; - onSelectMode: (mode: string) => void; setTabIndex: (tabIndex: number) => void; tabIndex: number; - paintedCells: RefObject>; - onAddRegion: () => void; - OnRemoveRegion: () => void; }; -const CameraSettings = ({ - regions, - selectedRegionIndex, - onSelectRegion, - onChangeRegionColour, - mode, - onSelectMode, - tabIndex, - setTabIndex, - paintedCells, - onAddRegion, - OnRemoveRegion, -}: CameraSettingsProps) => { +const CameraSettings = ({ tabIndex, setTabIndex }: CameraSettingsProps) => { return ( setTabIndex(index)} > - Target Detection - Camera 1 - Camera 2 - Camera 3 + Camera A + Camera B + Camera C - - - diff --git a/src/features/cameras/components/CameraSettings/RegionSelector.tsx b/src/features/cameras/components/CameraSettings/RegionSelector.tsx index bddbf2e..6918f2f 100644 --- a/src/features/cameras/components/CameraSettings/RegionSelector.tsx +++ b/src/features/cameras/components/CameraSettings/RegionSelector.tsx @@ -1,45 +1,57 @@ -import ColourPicker from "./ColourPicker"; import type { PaintedCell, Region } from "../../../../types/types"; -import type { RefObject } from "react"; +import ColourPicker from "./ColourPicker"; +import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext"; type RegionSelectorProps = { regions: Region[]; selectedRegionIndex: number; - onSelectRegion: (index: number) => void; - onChangeRegionColour: (index: number, colour: string) => void; mode: string; - onSelectMode: (mode: string) => void; - paintedCells: RefObject>; - onAddRegion: () => void; - OnRemoveRegion: () => void; + cameraFeedID: "A" | "B" | "C"; }; -const RegionSelector = ({ - regions, - selectedRegionIndex, - onSelectRegion, - onChangeRegionColour, - mode, - onSelectMode, - paintedCells, - onAddRegion, - OnRemoveRegion, -}: RegionSelectorProps) => { +const RegionSelector = ({ regions, selectedRegionIndex, mode, cameraFeedID }: RegionSelectorProps) => { + const { dispatch } = useCameraFeedContext(); const handleChange = (e: { target: { value: string } }) => { - onSelectMode(e.target.value); + dispatch({ type: "CHANGE_MODE", payload: { cameraFeedID: cameraFeedID, mode: e.target.value } }); }; - const handleAddClick = () => { - onAddRegion(); + const handleAddRegionClick = () => { + const regionName = `Region ${regions.length + 1}`; + dispatch({ + type: "ADD_NEW_REGION", + payload: { cameraFeedID: cameraFeedID, regionName: regionName, brushColour: "#ffffff" }, + }); }; - const handleResetClick = () => { - const map = paintedCells.current; - map.clear(); + const handleResetRegion = () => { + dispatch({ + type: "RESET_PAINTED_CELLS", + payload: { cameraFeedID: cameraFeedID, paintedCells: new Map() }, + }); }; const handleRemoveClick = () => { - OnRemoveRegion(); + dispatch({ + type: "REMOVE_REGION", + payload: { cameraFeedID: cameraFeedID, regionName: regions[selectedRegionIndex].name }, + }); + }; + + const handleModeChange = (newMode: string) => { + dispatch({ type: "CHANGE_MODE", payload: { cameraFeedID: cameraFeedID, mode: newMode } }); + }; + + const handleRegionSelect = (index: number) => { + dispatch({ type: "SET_SELECTED_REGION_INDEX", payload: index }); + }; + + const handleRegionColourChange = (index: number, newColour: string) => { + const regionName = regions[index].name; + + dispatch({ + type: "SET_SELECTED_REGION_COLOUR", + payload: { cameraFeedID: cameraFeedID, regionName: regionName, newColour: newColour }, + }); }; return ( @@ -84,7 +96,7 @@ const RegionSelector = ({

Region Select

<> - {regions.map((region, idx) => { + {regions?.map((region, idx) => { const isSelected = selectedRegionIndex === idx; const inputId = `region-${idx}`; return ( @@ -102,20 +114,20 @@ const RegionSelector = ({ name="region" className="sr-only" onChange={() => { - onSelectMode("painter"); - onSelectRegion(idx); + handleModeChange("painter"); + handleRegionSelect(idx); }} /> {region.name}
- onChangeRegionColour(idx, c)} /> + handleRegionColourChange(idx, c)} />

{region.brushColour}

); })}
-
diff --git a/src/features/cameras/components/Video/VideoFeedGridPainter.tsx b/src/features/cameras/components/Video/VideoFeedGridPainter.tsx index a355473..6aa48ef 100644 --- a/src/features/cameras/components/Video/VideoFeedGridPainter.tsx +++ b/src/features/cameras/components/Video/VideoFeedGridPainter.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef, useState, type RefObject } from "react"; import { Stage, Layer, Image, Shape } from "react-konva"; import type { KonvaEventObject } from "konva/lib/Node"; import { useCreateVideoSnapshot } from "../../hooks/useGetvideoSnapshots"; -import type { PaintedCell, Region } from "../../../../types/types"; + import Card from "../../../../ui/Card"; import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext"; @@ -11,17 +11,13 @@ const cols = 40; const size = 20; const gap = 0; -type VideoFeedGridPainterProps = { - regions: Region[]; - selectedRegionIndex: number; - mode: string; - paintedCells: RefObject>; -}; - -const VideoFeedGridPainter = ({ regions, selectedRegionIndex, mode }: VideoFeedGridPainterProps) => { - const { state, dispatch } = useCameraFeedContext(); +const VideoFeedGridPainter = () => { + const { state } = useCameraFeedContext(); const cameraFeedID = state.cameraFeedID; const paintedCells = state.paintedCells[cameraFeedID]; + const regions = state.regionsByCamera[cameraFeedID]; + const selectedRegionIndex = state.selectedRegionIndex; + const mode = state.modeByCamera[cameraFeedID]; const { latestBitmapRef, isloading } = useCreateVideoSnapshot(); const [stageSize, setStageSize] = useState({ width: 740, height: 460 }); const isDrawingRef = useRef(false); diff --git a/src/types/types.ts b/src/types/types.ts index 95e249a..e012fca 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -103,9 +103,44 @@ export type CameraFeedState = { B: Map; C: Map; }; + regionsByCamera: { + A: Region[]; + B: Region[]; + C: Region[]; + }; + selectedRegionIndex: number; + modeByCamera: { + A: string; + B: string; + C: string; + }; + + tabIndex?: number; }; -export type CameraFeedAction = { - type: string; - payload: "A" | "B" | "C"; -}; +export type CameraFeedAction = + | { + type: "SET_CAMERA_FEED"; + payload: "A" | "B" | "C"; + } + | { + type: "CHANGE_MODE"; + payload: { cameraFeedID: "A" | "B" | "C"; mode: string }; + } + | { type: "SET_SELECTED_REGION_INDEX"; payload: number } + | { + type: "SET_SELECTED_REGION_COLOUR"; + payload: { cameraFeedID: "A" | "B" | "C"; regionName: string; newColour: string }; + } + | { + type: "ADD_NEW_REGION"; + payload: { cameraFeedID: "A" | "B" | "C"; regionName: string; brushColour: string }; + } + | { + type: "REMOVE_REGION"; + payload: { cameraFeedID: "A" | "B" | "C"; regionName: string }; + } + | { + type: "RESET_PAINTED_CELLS"; + payload: { cameraFeedID: "A" | "B" | "C"; paintedCells: Map }; + };