@@ -111,7 +163,7 @@ const CameraSettingFields = ({
{errors.password}
)}
-
+
-
-
+
+
+
+ {zoomOptions.map((zoom) => (
+
+ handleRadioButtonChange(zoom)}
+ />
+
+
+ ))}
+
+
+
+ {updateCameraConfigError ? (
+
+ ) : (
+
+ )}
+
)}
diff --git a/src/components/CameraSettings/CameraSettings.tsx b/src/components/CameraSettings/CameraSettings.tsx
index 19f1484..2a0a68e 100644
--- a/src/components/CameraSettings/CameraSettings.tsx
+++ b/src/components/CameraSettings/CameraSettings.tsx
@@ -4,26 +4,34 @@ import CardHeader from "../UI/CardHeader";
import CameraSettingFields from "./CameraSettingFields";
import { faWrench } from "@fortawesome/free-solid-svg-icons";
-const CameraSettings = ({ title, side }: { title: string; side: string }) => {
- const {
- data,
- isError,
- isPending,
- updateCameraConfig,
- updateCameraConfigError,
- } = useFetchCameraConfig(side);
+const CameraSettings = ({
+ title,
+ side,
+ zoomLevel,
+ onZoomLevelChange,
+}: {
+ title: string;
+ side: string;
+ zoomLevel?: number;
+ onZoomLevelChange?: (level: number) => void;
+}) => {
+ const { data, updateCameraConfig, updateCameraConfigError } =
+ useFetchCameraConfig(side);
console.log(updateCameraConfigError);
-
return (
- {isPending && <>Loading camera config>}
- {isError && <>Error fetching camera config>}
-
+
+ {
+
+ }
);
diff --git a/src/components/FrontCameraOverview/FrontCameraOverviewCard.tsx b/src/components/FrontCameraOverview/FrontCameraOverviewCard.tsx
index 6c449dd..75503b1 100644
--- a/src/components/FrontCameraOverview/FrontCameraOverviewCard.tsx
+++ b/src/components/FrontCameraOverview/FrontCameraOverviewCard.tsx
@@ -2,14 +2,14 @@ import clsx from "clsx";
import Card from "../UI/Card";
import { useSwipeable } from "react-swipeable";
import { useNavigate } from "react-router";
-import { useOverviewVideo } from "../../hooks/useOverviewVideo";
+
import SightingOverview from "../SightingOverview/SightingOverview";
const FrontCameraOverviewCard = () => {
- useOverviewVideo();
const navigate = useNavigate();
const handlers = useSwipeable({
onSwipedRight: () => navigate("/camera-settings"),
+ onSwipedLeft: () => navigate("/rear-camera-settings"),
trackMouse: true,
});
diff --git a/src/components/FrontCameraSettings/OverviewVideoContainer.tsx b/src/components/FrontCameraSettings/OverviewVideoContainer.tsx
index 7ed4c87..1a0b7a8 100644
--- a/src/components/FrontCameraSettings/OverviewVideoContainer.tsx
+++ b/src/components/FrontCameraSettings/OverviewVideoContainer.tsx
@@ -1,20 +1,32 @@
import clsx from "clsx";
import { SnapshotContainer } from "../CameraOverview/SnapshotContainer";
import Card from "../UI/Card";
-import { useNavigate } from "react-router";
+import { useNavigate, useLocation } from "react-router";
import { useSwipeable } from "react-swipeable";
const OverviewVideoContainer = ({
side,
settingsPage,
+ zoomLevel,
+ onZoomLevelChange,
}: {
title: string;
side: string;
settingsPage?: boolean;
+ zoomLevel?: number;
+ onZoomLevelChange?: (level: number) => void;
}) => {
const navigate = useNavigate();
+ const location = useLocation();
const handlers = useSwipeable({
- onSwipedLeft: () => navigate("/"),
+ onSwipedLeft: () => {
+ if (location.pathname === "/rear-camera-settings") return;
+ navigate("/");
+ },
+ onSwipedRight: () => {
+ if (location.pathname === "/camera-settings") return;
+ navigate("/");
+ },
trackMouse: true,
});
return (
@@ -24,7 +36,12 @@ const OverviewVideoContainer = ({
)}
>
-
+
);
diff --git a/src/components/HistoryList/AlertItem.tsx b/src/components/HistoryList/AlertItem.tsx
index ccdcb26..89838a2 100644
--- a/src/components/HistoryList/AlertItem.tsx
+++ b/src/components/HistoryList/AlertItem.tsx
@@ -15,7 +15,7 @@ type AlertItemProps = {
const AlertItem = ({ item }: AlertItemProps) => {
const [isModalOpen, setIsModalOpen] = useState(false);
- const { dispatch } = useAlertHitContext();
+ const { dispatch, isError } = useAlertHitContext();
// const {d} = useCameraBlackboard();
const motionAway = (item?.motion ?? "").toUpperCase() === "AWAY";
@@ -24,6 +24,7 @@ const AlertItem = ({ item }: AlertItemProps) => {
const isNPEDHitB = item?.metadata?.npedJSON?.["NPED CATEGORY"] === "B";
const isNPEDHitC = item?.metadata?.npedJSON?.["NPED CATEGORY"] === "C";
+ console.log(isError);
const handleClick = () => {
setIsModalOpen(true);
};
diff --git a/src/components/SettingForms/BearerType/BearerTypeFields.tsx b/src/components/SettingForms/BearerType/BearerTypeFields.tsx
index db276b4..b06dde3 100644
--- a/src/components/SettingForms/BearerType/BearerTypeFields.tsx
+++ b/src/components/SettingForms/BearerType/BearerTypeFields.tsx
@@ -1,32 +1,75 @@
-import { Field, useFormikContext } from "formik";
+import { Field, Form, Formik } from "formik";
import FormToggle from "../components/FormToggle";
+import { useCameraOutput } from "../../../hooks/useCameraOutput";
+import { cleanArray } from "../../../utils/utils";
+import FormGroup from "../components/FormGroup";
+import type { BearerTypeFieldType } from "../../../types/types";
export const ValuesComponent = () => {
return null;
};
const BearerTypeFields = () => {
- useFormikContext();
+ const { dispatcherQuery, dispatcherMutation } = useCameraOutput();
+
+ const format = dispatcherQuery?.data?.propFormat?.value;
+ const rawOptions = dispatcherQuery?.data?.propFormat?.accepted;
+ const enabled = dispatcherQuery?.data?.propEnabled?.value;
+ const verbose = dispatcherQuery?.data?.propVerbose?.value;
+ const options = cleanArray(rawOptions);
+
+ const initialValues: BearerTypeFieldType = {
+ format: format ?? "JSON",
+ enabled: enabled === "true",
+ verbose: verbose === "true",
+ };
+
+ const handleSubmit = async (values: BearerTypeFieldType) => {
+ await dispatcherMutation.mutateAsync(values);
+ };
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ {({ isSubmitting }) => (
+
+ )}
+
);
};
diff --git a/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx b/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx
index 7ed45a5..387eec0 100644
--- a/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx
+++ b/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx
@@ -1,72 +1,185 @@
-import { Field, useFormikContext } from "formik";
+import { Field, Form, Formik, useFormikContext } from "formik";
import FormGroup from "../components/FormGroup";
-import { useState } from "react";
+import { useEffect, useState } from "react";
import { faEyeSlash, faEye } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { useCameraOutput } from "../../../hooks/useCameraOutput";
+import type {
+ InitialValuesForm,
+ InitialValuesFormErrors,
+} from "../../../types/types";
+import { toast } from "sonner";
const ChannelFields = () => {
- useFormikContext();
const [showPwd, setShowPwd] = useState(false);
+ const { backOfficeQuery, backOfficeMutation } = useCameraOutput();
+
+ const backOfficeURL = backOfficeQuery?.data?.propBackofficeURL?.value;
+ const username = backOfficeQuery?.data?.propUsername?.value;
+ const password = backOfficeQuery?.data?.propPassword?.value;
+ const connectTimeoutSeconds =
+ backOfficeQuery?.data?.propConnectTimeoutSeconds?.value;
+ const readTimeoutSeconds =
+ backOfficeQuery?.data?.propReadTimeoutSeconds?.value;
+
+ const initialValues: InitialValuesForm = {
+ backOfficeURL: backOfficeURL ?? "",
+ username: username ?? "",
+ password: password ?? "",
+ connectTimeoutSeconds: Number(connectTimeoutSeconds),
+ readTimeoutSeconds: Number(readTimeoutSeconds),
+ };
+
+ const handleSubmit = async (values: InitialValuesForm) => {
+ await backOfficeMutation.mutateAsync(values);
+ };
+
+ const ValidationToastOnce = () => {
+ const { submitCount, isValid } = useFormikContext();
+ useEffect(() => {
+ if (submitCount > 0 && !isValid) {
+ toast.error("Check fields are filled in");
+ }
+ }, [submitCount, isValid]);
+ return null;
+ };
+
+ 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";
+ } else if (read < 0) {
+ errors.readTimeoutSeconds = "Must be ≥ 0";
+ }
+
+ const connect = Number(values.connectTimeoutSeconds);
+ if (!Number.isFinite(connect)) {
+ errors.connectTimeoutSeconds = "Must be a number";
+ } else if (connect < 0) {
+ errors.connectTimeoutSeconds = "Must be ≥ 0";
+ }
+
+ return errors;
+ };
+
return (
-
-
-
-
-
-
-
-
-
-
-
-
- setShowPwd((s) => !s)}
- icon={showPwd ? faEyeSlash : faEye}
- />
-
-
-
-
-
-
-
-
-
-
+
+ {({ errors, touched, isSubmitting }) => (
+
+ )}
+
);
};
diff --git a/src/components/SettingForms/NPED/NPEDFields.tsx b/src/components/SettingForms/NPED/NPEDFields.tsx
index 0288916..ee0c9ee 100644
--- a/src/components/SettingForms/NPED/NPEDFields.tsx
+++ b/src/components/SettingForms/NPED/NPEDFields.tsx
@@ -27,12 +27,11 @@ const NPEDFields = () => {
rearId: "NPED",
};
- const handleSubmit = (values: NPEDFieldType) => {
+ const handleSubmit = async (values: NPEDFieldType) => {
const valuesToSend = {
...values,
};
- signIn(valuesToSend);
- toast.success("Signed into NPED Successfully");
+ await signIn(valuesToSend);
};
const validateValues = (values: NPEDFieldType) => {
@@ -55,7 +54,7 @@ const NPEDFields = () => {
validate={validateValues}
enableReinitialize
>
- {({ errors, touched }) => (
+ {({ errors, touched, isSubmitting }) => (