- minor big fixes

- default settings toggled
-update camera zoom need to test
This commit is contained in:
2025-11-04 13:38:06 +00:00
parent 76643cc84c
commit 61894c0c42
9 changed files with 43 additions and 51 deletions

View File

@@ -5,6 +5,7 @@ import { useCameraZoom } from "../../hooks/useCameraZoom";
import { useEffect } from "react";
import Loading from "../UI/Loading";
import ErrorState from "../UI/ErrorState";
import { zoomMapping } from "../../utils/utils";
type SnapshotContainerProps = {
side: string;
@@ -13,20 +14,14 @@ type SnapshotContainerProps = {
onZoomLevelChange?: (level: number) => void;
};
export const SnapshotContainer = ({
side,
settingsPage,
zoomLevel,
onZoomLevelChange,
}: SnapshotContainerProps) => {
export const SnapshotContainer = ({ side, settingsPage, zoomLevel, onZoomLevelChange }: SnapshotContainerProps) => {
const { canvasRef, isError, isPending } = useGetOverviewSnapshot(side);
const cameraControllerSide =
side === "CameraA" ? "CameraControllerA" : "CameraControllerB";
const cameraControllerSide = side === "CameraA" ? "CameraControllerA" : "CameraControllerB";
const { mutation } = useCameraZoom({ camera: cameraControllerSide });
const handleZoomClick = () => {
const baseLevel = zoomLevel ?? 1;
const newLevel = baseLevel >= 8 ? 1 : baseLevel * 2;
const newLevel = baseLevel >= 4 ? 1 : baseLevel * 2;
if (onZoomLevelChange) onZoomLevelChange(newLevel);
@@ -35,9 +30,11 @@ export const SnapshotContainer = ({
useEffect(() => {
if (zoomLevel) {
const text = zoomMapping(zoomLevel);
const zoomInOptions: ZoomInOptions = {
camera: cameraControllerSide,
multiplier: zoomLevel,
multiplierText: text,
};
mutation.mutate(zoomInOptions);
}

View File

@@ -5,7 +5,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faEye, faEyeSlash } from "@fortawesome/free-regular-svg-icons";
import CardHeader from "../UI/CardHeader";
import { useCameraZoom } from "../../hooks/useCameraZoom";
import { parseRTSPUrl } from "../../utils/utils";
import { parseRTSPUrl, zoomMapping } from "../../utils/utils";
type CameraSettingsProps = {
initialData: CameraConfig;
@@ -25,7 +25,12 @@ const CameraSettingFields = ({
const [showPwd, setShowPwd] = useState(false);
const cameraControllerSide = initialData?.id === "CameraA" ? "CameraControllerA" : "CameraControllerB";
const { mutation, query } = useCameraZoom({ camera: cameraControllerSide });
const zoomOptions = [1, 2, 4, 8];
const zoomOptions = [1, 2, 4];
// const zoomTextOptions = [
// { label: "near", value: 4 },
// { label: "medium", value: 2 },
// { label: "far", value: 1 },
// ];
const parsed = parseRTSPUrl(initialData?.propURI?.value);
@@ -36,6 +41,7 @@ const CameraSettingFields = ({
}, [query?.data, onZoomLevelChange]);
const getZoomLevel = (levelstring: string | undefined) => {
console.log(levelstring);
switch (levelstring) {
case "1x":
return 1;
@@ -46,8 +52,6 @@ const CameraSettingFields = ({
case "4x":
return 4;
case "8x":
return 8;
default:
return 1;
}
@@ -80,11 +84,13 @@ const CameraSettingFields = ({
const handleRadioButtonChange = async (levelNumber: number) => {
if (!onZoomLevelChange || !zoomLevel) return;
const text = zoomMapping(levelNumber);
onZoomLevelChange(levelNumber);
const zoomInOptions: ZoomInOptions = {
camera: cameraControllerSide,
multiplier: levelNumber,
multiplierText: text,
};
mutation.mutate(zoomInOptions);
@@ -169,7 +175,7 @@ const CameraSettingFields = ({
</div>
<div className="my-3">
<CardHeader title="Zoom settings" />
<div className="mx-auto grid grid-cols-4 items-center">
<div className="mx-auto grid grid-cols-3 place-items-center">
{zoomOptions.map((zoom) => (
<div key={zoom} className="my-3">
<Field
@@ -187,7 +193,7 @@ const CameraSettingFields = ({
peer-checked:border-2 peer-checked:border-blue-900
peer-checked:text-blue-600 peer-checked:bg-gray-100"
>
x{zoom}
{zoomMapping(zoom)}
</label>
</div>
))}

View File

@@ -40,9 +40,7 @@ const NumberPlate = ({ motion, vrm, size }: NumberPlateProps) => {
return (
<div
className={`relative ${options.plateWidth} ${
options.borderWidth
} border-black rounded-xl text-nowrap
className={`relative ${options.plateWidth} ${options.borderWidth} border-black rounded-xl text-nowrap
text-black px-6 py-2
${motion ? "bg-yellow-400" : "bg-white"}`}
>
@@ -50,9 +48,7 @@ const NumberPlate = ({ motion, vrm, size }: NumberPlateProps) => {
<div className="absolute inset-y-0 left-0 bg-blue-600 w-8 flex flex-col">
<GB />
</div>
<p className={`pl-4 font-extrabold ${options.textSize} text-right`}>
{vrm && formatNumberPlate(vrm)}
</p>
<p className={`pl-4 font-extrabold ${options.textSize} text-right`}>{vrm && formatNumberPlate(vrm)}</p>
</div>
</div>
);

View File

@@ -58,9 +58,7 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
type="text"
id="backoffice"
placeholder="https://www.backoffice.com"
className={`p-1.5 border ${
errors.backOfficeURL && touched.backOfficeURL ? "border-red-500" : "border-gray-400 "
} rounded-lg w-full md:w-60`}
className={`p-1.5 border border-gray-400 rounded-lg w-full md:w-60`}
/>
</FormGroup>
<FormGroup>
@@ -70,9 +68,7 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
type="text"
id="username"
placeholder="Back office username"
className={`p-1.5 border ${
errors.username && touched.username ? "border-red-500" : "border-gray-400 "
} rounded-lg w-full md:w-60`}
className={`p-1.5 border border-gray-400 rounded-lg w-full md:w-60`}
/>
</FormGroup>
<FormGroup>
@@ -159,7 +155,6 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
id="timestampSource"
className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445] w-full md:w-60"
>
<option value="">-- Select format --</option>
<option value={"UTC"}>UTC</option>
<option value={"local"}>Local</option>
</Field>
@@ -172,9 +167,8 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
id="GPSFormat"
className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445] w-full md:w-60"
>
<option value="">-- Select format --</option>
<option value={"Decimal Degrees"}>Decimal degrees</option>
<option value={"Minutes"}>Minutes</option>
<option value={"Decimal Degrees"}>Decimal degrees</option>
</Field>
</FormGroup>
</>

View File

@@ -46,16 +46,6 @@ const SettingForms = () => {
const validateValues = (values: InitialValuesForm): InitialValuesFormErrors => {
const errors: InitialValuesFormErrors = {};
const url = values.backOfficeURL?.trim();
const username = values.username?.trim();
const password = values.password?.trim();
if (!url) {
errors.backOfficeURL = "Required";
}
if (!username) errors.username = "Required";
if (!password) errors.password = "Required";
const read = Number(values.readTimeoutSeconds);
if (!Number.isFinite(read)) {
errors.readTimeoutSeconds = "Must be a number";

View File

@@ -38,7 +38,7 @@ const NavigationArrow = ({ side, settingsPage }: NavigationArrowProps) => {
icon={faArrowLeft}
size="2xl"
className="absolute top-[50%] left-[2%] backdrop-blur-md hover:cursor-pointer animate-bounce z-30"
onClick={() => navigationDest(side)}
onClick={() => navigationDest("Rear")}
/>
)}
</>

View File

@@ -1,8 +1,4 @@
import {
useMutation,
useQuery,
type QueryFunctionContext,
} from "@tanstack/react-query";
import { useMutation, useQuery, type QueryFunctionContext } from "@tanstack/react-query";
import { CAM_BASE } from "../utils/config";
import type { zoomConfig, ZoomInOptions } from "../types/types";
import { toast } from "sonner";
@@ -10,7 +6,7 @@ import { useEffect } from "react";
async function zoomIn(options: ZoomInOptions) {
const response = await fetch(
`${CAM_BASE}/Ip${options.camera}-command?magnification=${options.multiplier}x`,
`${CAM_BASE}/Ip${options.camera}-command?magnification=${options.multiplierText?.toLowerCase()}`,
{
signal: AbortSignal.timeout(500),
}
@@ -22,11 +18,9 @@ async function zoomIn(options: ZoomInOptions) {
return response.json();
}
async function fetchZoomInConfig({
queryKey,
}: QueryFunctionContext<[string, zoomConfig]>) {
async function fetchZoomInConfig({ queryKey }: QueryFunctionContext<[string, zoomConfig]>) {
const [, { camera }] = queryKey;
const response = await fetch(`${CAM_BASE}/Ip${camera}-inspect`, {
const response = await fetch(`${CAM_BASE}/Ip${camera}-command`, {
signal: AbortSignal.timeout(500),
});
if (!response.ok) {

View File

@@ -374,6 +374,7 @@ export type ModemConfig = {
export type ZoomInOptions = {
camera: string;
multiplier: number;
multiplierText?: string;
};
export type zoomConfig = {
@@ -407,5 +408,6 @@ export type NPEDSTATE = {
export type NPEDACTION = {
type: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
payload: any;
};

View File

@@ -158,3 +158,16 @@ export function getHotlistName(obj: HotlistMatches | undefined) {
export const getNPEDCategory = (r?: SightingType | null) =>
r?.metadata?.npedJSON?.["NPED CATEGORY"] as "A" | "B" | "C" | "D" | undefined;
export const zoomMapping = (zoomLevel: number) => {
switch (zoomLevel) {
case 1:
return "Far";
case 2:
return "Medium";
case 4:
return "Close";
default:
break;
}
};