- 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,
cameraControls: action.payload,
};
case "RESET_REGION_PAINTER":
return {
...state,
regionPainter: {
...state.regionPainter,
paintedCells: new Map(),
paintMode: "painter",
},
};
default:
return state;
}

View File

@@ -58,7 +58,7 @@ const CameraControls = ({ state, dispatch }: CameraControlProps) => {
{({ values }) => (
<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>
<div className="flex flex-row gap-4">
<div className="flex flex-row gap-1 md:gap-4">
<div>
<label
htmlFor="auto"

View File

@@ -1,6 +1,7 @@
import { useCameraSettingsContext } from "../../../../app/context/CameraSettingsContext";
import SliderComponent from "../../../../components/ui/SliderComponent";
import type { CameraSettings } from "../../../../utils/types";
import { useTargetDetection } from "../../hooks/useTargetDetection";
type RegionProps = {
state: CameraSettings;
@@ -8,9 +9,11 @@ type RegionProps = {
const Region = ({ state }: RegionProps) => {
const { dispatch } = useCameraSettingsContext();
const { mutation } = useTargetDetection();
const paintMode = state.regionPainter.paintMode;
const regions = state.regionPainter.regions;
const brushSize = state.regionPainter.brushSize;
const paintedCells = state.regionPainter.paintedCells;
const handleChangePaintMode = (event: React.ChangeEvent<HTMLInputElement>) => {
const mode = event.target.value as "painter" | "eraser";
@@ -24,7 +27,47 @@ const Region = ({ state }: RegionProps) => {
};
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 (
<div className="flex flex-col gap-4 mt-[2%]">
@@ -88,28 +131,30 @@ const Region = ({ state }: RegionProps) => {
{regions.map((region, idx) => {
const inputID = `region-${idx}`;
return (
<label
htmlFor={inputID}
key={region.name}
className={`items-center p-4 m-1 rounded-xl border flex flex-row justify-between
<div className="my-2 md:my-4">
<label
htmlFor={inputID}
key={region.name}
className={`items-center p-4 m-1 rounded-xl border flex flex-row justify-between
${state.regionPainter.selectedRegionIndex === idx ? "border-gray-400 bg-[#202b36]" : "bg-[#253445] border-gray-700"} hover:bg-[#202b36] hover:cursor-pointer`}
>
<div className="flex flex-row gap-4 items-center">
<input
type="radio"
id={inputID}
checked={state.regionPainter.selectedRegionIndex === idx}
name="region"
className="sr-only"
onChange={() => {
handlePaintMode("painter");
handleChangeRegion(idx);
}}
/>
<span className="text-lg">{region.name}</span>
<div className="w-6 h-6 rounded mt-1" style={{ backgroundColor: region.brushColour }}></div>
</div>
</label>
>
<div className="flex flex-row gap-4 items-center">
<input
type="radio"
id={inputID}
checked={state.regionPainter.selectedRegionIndex === idx}
name="region"
className="sr-only"
onChange={() => {
handlePaintMode("painter");
handleChangeRegion(idx);
}}
/>
<span className="text-lg">{region.name}</span>
<div className="w-6 h-6 rounded mt-1" style={{ backgroundColor: region.brushColour }}></div>
</div>
</label>
</div>
);
})}
</div>
@@ -124,7 +169,12 @@ const Region = ({ state }: RegionProps) => {
>
Save
</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>

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";
payload: number;
}
| {
type: "RESET_REGION_PAINTER";
};
export type CameraStatus = {
@@ -141,3 +144,12 @@ export type StoreData = {
sanityCheck: boolean;
sanityCheckFormula: string;
};
export type ColourData = {
id: string | number;
cells: number[][];
};
export type ColourDetectionPayload = {
regions: ColourData[];
};