- added functionality to push to backend

- improved responsiveness
- added reset functionality
This commit is contained in:
2026-01-14 14:50:24 +00:00
parent 1c24b726b0
commit 256330f892
5 changed files with 126 additions and 24 deletions

View File

@@ -71,6 +71,16 @@ export const cameraSettingsReducer = (state: CameraSettings, action: CameraSetti
...state, ...state,
cameraControls: action.payload, cameraControls: action.payload,
}; };
case "RESET_REGION_PAINTER":
return {
...state,
regionPainter: {
...state.regionPainter,
paintedCells: new Map(),
paintMode: "painter",
},
};
default: default:
return state; return state;
} }

View File

@@ -58,7 +58,7 @@ const CameraControls = ({ state, dispatch }: CameraControlProps) => {
{({ values }) => ( {({ values }) => (
<Form className="flex flex-col gap-5 border border-gray-500 p-4 rounded-md mt-[2%]"> <Form className="flex flex-col gap-5 border border-gray-500 p-4 rounded-md mt-[2%]">
<h2 className="text-2xl mb-2">Controls</h2> <h2 className="text-2xl mb-2">Controls</h2>
<div className="flex flex-row gap-4"> <div className="flex flex-row gap-1 md:gap-4">
<div> <div>
<label <label
htmlFor="auto" htmlFor="auto"

View File

@@ -1,6 +1,7 @@
import { useCameraSettingsContext } from "../../../../app/context/CameraSettingsContext"; import { useCameraSettingsContext } from "../../../../app/context/CameraSettingsContext";
import SliderComponent from "../../../../components/ui/SliderComponent"; import SliderComponent from "../../../../components/ui/SliderComponent";
import type { CameraSettings } from "../../../../utils/types"; import type { CameraSettings } from "../../../../utils/types";
import { useTargetDetection } from "../../hooks/useTargetDetection";
type RegionProps = { type RegionProps = {
state: CameraSettings; state: CameraSettings;
@@ -8,9 +9,11 @@ type RegionProps = {
const Region = ({ state }: RegionProps) => { const Region = ({ state }: RegionProps) => {
const { dispatch } = useCameraSettingsContext(); const { dispatch } = useCameraSettingsContext();
const { mutation } = useTargetDetection();
const paintMode = state.regionPainter.paintMode; const paintMode = state.regionPainter.paintMode;
const regions = state.regionPainter.regions; const regions = state.regionPainter.regions;
const brushSize = state.regionPainter.brushSize; const brushSize = state.regionPainter.brushSize;
const paintedCells = state.regionPainter.paintedCells;
const handleChangePaintMode = (event: React.ChangeEvent<HTMLInputElement>) => { const handleChangePaintMode = (event: React.ChangeEvent<HTMLInputElement>) => {
const mode = event.target.value as "painter" | "eraser"; const mode = event.target.value as "painter" | "eraser";
@@ -24,7 +27,47 @@ const Region = ({ state }: RegionProps) => {
}; };
const handleSaveClick = () => { const handleSaveClick = () => {
console.log(state); const paintedRegions = [];
const paintedCellsArray = Array.from(paintedCells.entries());
const region1 = paintedCellsArray.filter(([, cell]) => cell.region.name === "Region 1");
const region2 = paintedCellsArray.filter(([, cell]) => cell.region.name === "Region 2");
const region3 = paintedCellsArray.filter(([, cell]) => cell.region.name === "Region 3");
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])]),
};
if (region1Data.cells.length > 0) {
paintedRegions.push(region1Data);
}
if (region2Data.cells.length > 0) {
paintedRegions.push(region2Data);
}
if (region3Data.cells.length > 0) {
paintedRegions.push(region3Data);
}
dispatch({ type: "SET_REGION_PAINTMODE", payload: "painter" });
mutation.mutate({ regions: paintedRegions });
};
const handleResetClick = () => {
paintedCells.clear();
dispatch({ type: "SET_REGION_PAINTMODE", payload: "painter" });
dispatch({ type: "RESET_REGION_PAINTER" });
mutation.mutate({ regions: [] });
}; };
return ( return (
<div className="flex flex-col gap-4 mt-[2%]"> <div className="flex flex-col gap-4 mt-[2%]">
@@ -88,6 +131,7 @@ const Region = ({ state }: RegionProps) => {
{regions.map((region, idx) => { {regions.map((region, idx) => {
const inputID = `region-${idx}`; const inputID = `region-${idx}`;
return ( return (
<div className="my-2 md:my-4">
<label <label
htmlFor={inputID} htmlFor={inputID}
key={region.name} key={region.name}
@@ -110,6 +154,7 @@ const Region = ({ state }: RegionProps) => {
<div className="w-6 h-6 rounded mt-1" style={{ backgroundColor: region.brushColour }}></div> <div className="w-6 h-6 rounded mt-1" style={{ backgroundColor: region.brushColour }}></div>
</div> </div>
</label> </label>
</div>
); );
})} })}
</div> </div>
@@ -124,7 +169,12 @@ const Region = ({ state }: RegionProps) => {
> >
Save Save
</button> </button>
<button className="p-2 rounded-lg bg-gray-500 text-white w-[40%] mt-2">Reset</button> <button
className="p-2 rounded-lg bg-gray-500 text-white w-[40%] mt-2 hover:bg-gray-700 cursor-pointer"
onClick={handleResetClick}
>
Reset
</button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,30 @@
import { useMutation } from "@tanstack/react-query";
import type { ColourDetectionPayload } from "../../../utils/types";
import { cambase } from "../../../app/config";
const sendTargetDetectionData = async (regionData: ColourDetectionPayload) => {
const regions = {
regions: regionData.regions,
};
const response = await fetch(`${cambase}/TargetDetectionColour-region-update`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(regions),
});
if (!response.ok) {
throw new Error("Failed to send target detection data");
}
return response.json();
};
export const useTargetDetection = () => {
const mutation = useMutation({
mutationKey: ["colour detection"],
mutationFn: (regionData: ColourDetectionPayload) => sendTargetDetectionData(regionData),
});
return { mutation };
};

View File

@@ -118,6 +118,9 @@ export type CameraSettingsAction =
| { | {
type: "SET_BRUSH_SIZE"; type: "SET_BRUSH_SIZE";
payload: number; payload: number;
}
| {
type: "RESET_REGION_PAINTER";
}; };
export type CameraStatus = { export type CameraStatus = {
@@ -141,3 +144,12 @@ export type StoreData = {
sanityCheck: boolean; sanityCheck: boolean;
sanityCheckFormula: string; sanityCheckFormula: string;
}; };
export type ColourData = {
id: string | number;
cells: number[][];
};
export type ColourDetectionPayload = {
regions: ColourData[];
};