diff --git a/package.json b/package.json
index c38c457..3ffc1cd 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
"react-modal": "^3.16.3",
"react-router": "^7.8.0",
"react-swipeable": "^7.0.2",
+ "react-tabs": "^6.1.0",
"tailwindcss": "^4.1.11"
},
"devDependencies": {
diff --git a/src/components/CameraOverview/SnapshotContainer.tsx b/src/components/CameraOverview/SnapshotContainer.tsx
index d4cf2c6..4f9810c 100644
--- a/src/components/CameraOverview/SnapshotContainer.tsx
+++ b/src/components/CameraOverview/SnapshotContainer.tsx
@@ -3,14 +3,18 @@ import NavigationArrow from "../UI/NavigationArrow";
type SnapshotContainerProps = {
side: string;
+ settingsPage?: boolean;
};
-export const SnapshotContainer = ({ side }: SnapshotContainerProps) => {
+export const SnapshotContainer = ({
+ side,
+ settingsPage,
+}: SnapshotContainerProps) => {
const { canvasRef } = useGetOverviewSnapshot(side);
return (
-
+
);
diff --git a/src/components/CameraSettings/CameraSettingFields.tsx b/src/components/CameraSettings/CameraSettingFields.tsx
index f55fff6..f9b99f6 100644
--- a/src/components/CameraSettings/CameraSettingFields.tsx
+++ b/src/components/CameraSettings/CameraSettingFields.tsx
@@ -5,21 +5,20 @@ import type {
} from "../../types/types";
const CameraSettingFields = () => {
- const initialValues = {
+ const initialValues: CameraSettingValues = {
friendlyName: "",
cameraAddress: "",
userName: "",
password: "",
setupCamera: 1,
};
+
const validateValues = (values: CameraSettingValues) => {
const errors: CameraSettingErrorValues = {};
-
if (!values.friendlyName) errors.friendlyName = "Required";
if (!values.cameraAddress) errors.cameraAddress = "Required";
if (!values.userName) errors.userName = "Required";
if (!values.password) errors.password = "Required";
- console.log(errors);
return errors;
};
@@ -35,100 +34,101 @@ const CameraSettingFields = () => {
validate={validateValues}
validateOnChange={false}
>
- {({ errors }) => {
- return (
-
- );
- }}
+
+
+
+
+
+
+
+
+
+ {touched.cameraAddress && errors.cameraAddress && (
+
+ {errors.cameraAddress}
+
+ )}
+
+
+
+
+
+ {touched.userName && errors.userName && (
+
+ {errors.userName}
+
+ )}
+
+
+
+
+
+ {touched.password && errors.password && (
+
+ {errors.password}
+
+ )}
+
+
+
+
+
+ )}
);
};
diff --git a/src/components/FrontCameraOverview/FrontCameraOverviewCard.tsx b/src/components/FrontCameraOverview/FrontCameraOverviewCard.tsx
index 0c96114..a4ae37c 100644
--- a/src/components/FrontCameraOverview/FrontCameraOverviewCard.tsx
+++ b/src/components/FrontCameraOverview/FrontCameraOverviewCard.tsx
@@ -19,7 +19,7 @@ const FrontCameraOverviewCard = () => {
-
+
);
diff --git a/src/components/FrontCameraSettings/OverviewVideoContainer.tsx b/src/components/FrontCameraSettings/OverviewVideoContainer.tsx
index 8bef1d4..207b2f6 100644
--- a/src/components/FrontCameraSettings/OverviewVideoContainer.tsx
+++ b/src/components/FrontCameraSettings/OverviewVideoContainer.tsx
@@ -7,15 +7,17 @@ import CardHeader from "../UI/CardHeader";
const OverviewVideoContainer = ({
title,
side,
+ settingsPage,
}: {
title: string;
side: string;
+ settingsPage?: boolean;
}) => {
return (
-
+
);
diff --git a/src/components/Output/OutputForm.tsx b/src/components/Output/OutputForm.tsx
index e69de29..fe18f83 100644
--- a/src/components/Output/OutputForm.tsx
+++ b/src/components/Output/OutputForm.tsx
@@ -0,0 +1,13 @@
+import { Formik, Form, Field } from "formik";
+
+const OutputForm = () => {
+ const initialValues = {
+ includeVRM: false,
+ includeMotion: false,
+ includeTimestamp: false,
+ timeStampFormat: "utc",
+ };
+ return OutputForm
;
+};
+
+export default OutputForm;
diff --git a/src/components/PlateStack/NumberPlate.tsx b/src/components/PlateStack/NumberPlate.tsx
index 8e1b261..6011261 100644
--- a/src/components/PlateStack/NumberPlate.tsx
+++ b/src/components/PlateStack/NumberPlate.tsx
@@ -1,9 +1,9 @@
import { GB } from "country-flag-icons/react/3x2";
import { formatNumberPlate } from "../../utils/utils";
-import type { Sighting } from "../../types/types";
+import type { SightingType } from "../../types/types";
type NumberPlateProps = {
- sighting: Sighting;
+ sighting: SightingType;
};
const NumberPlate = ({ sighting }: NumberPlateProps) => {
diff --git a/src/components/SettingForms/BearerType/BearerTypeCard.tsx b/src/components/SettingForms/BearerType/BearerTypeCard.tsx
new file mode 100644
index 0000000..0b0442a
--- /dev/null
+++ b/src/components/SettingForms/BearerType/BearerTypeCard.tsx
@@ -0,0 +1,14 @@
+import Card from "../../UI/Card";
+import CardHeader from "../../UI/CardHeader";
+import BearerTypeFields from "./BearerTypeFields";
+
+const BearerTypeCard = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default BearerTypeCard;
diff --git a/src/components/SettingForms/BearerType/BearerTypeFields.tsx b/src/components/SettingForms/BearerType/BearerTypeFields.tsx
new file mode 100644
index 0000000..9270860
--- /dev/null
+++ b/src/components/SettingForms/BearerType/BearerTypeFields.tsx
@@ -0,0 +1,35 @@
+import { Field, useFormikContext } from "formik";
+
+import FormToggle from "../components/FormToggle";
+
+export const ValuesComponent = () => {
+ return null;
+};
+
+const BearerTypeFields = () => {
+ const { values } = useFormikContext();
+ console.log(values);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default BearerTypeFields;
diff --git a/src/components/SettingForms/Channel1-JSON/ChannelCard.tsx b/src/components/SettingForms/Channel1-JSON/ChannelCard.tsx
new file mode 100644
index 0000000..7df5df8
--- /dev/null
+++ b/src/components/SettingForms/Channel1-JSON/ChannelCard.tsx
@@ -0,0 +1,14 @@
+import Card from "../../UI/Card";
+import CardHeader from "../../UI/CardHeader";
+import ChannelFields from "./ChannelFields";
+
+const ChannelCard = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default ChannelCard;
diff --git a/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx b/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx
new file mode 100644
index 0000000..3290afe
--- /dev/null
+++ b/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx
@@ -0,0 +1,64 @@
+import { Field, useFormikContext } from "formik";
+import FormGroup from "../components/FormGroup";
+
+const ChannelFields = () => {
+ useFormikContext();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default ChannelFields;
diff --git a/src/components/SettingForms/NPED/NPEDCard.tsx b/src/components/SettingForms/NPED/NPEDCard.tsx
new file mode 100644
index 0000000..c55acef
--- /dev/null
+++ b/src/components/SettingForms/NPED/NPEDCard.tsx
@@ -0,0 +1,12 @@
+import Card from "../../UI/Card";
+import CardHeader from "../../UI/CardHeader";
+
+const NPEDCard = () => {
+ return (
+
+
+
+ );
+};
+
+export default NPEDCard;
diff --git a/src/components/SettingForms/NPED/NPEDFields.tsx b/src/components/SettingForms/NPED/NPEDFields.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/SettingForms/OverviewText/OverviewTextCard.tsx b/src/components/SettingForms/OverviewText/OverviewTextCard.tsx
new file mode 100644
index 0000000..7855cd8
--- /dev/null
+++ b/src/components/SettingForms/OverviewText/OverviewTextCard.tsx
@@ -0,0 +1,14 @@
+import Card from "../../UI/Card";
+import CardHeader from "../../UI/CardHeader";
+import OverviewTextFields from "./OverviewTextFields";
+
+const OverviewTextCard = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default OverviewTextCard;
diff --git a/src/components/SettingForms/OverviewText/OverviewTextFields.tsx b/src/components/SettingForms/OverviewText/OverviewTextFields.tsx
new file mode 100644
index 0000000..23545c9
--- /dev/null
+++ b/src/components/SettingForms/OverviewText/OverviewTextFields.tsx
@@ -0,0 +1,53 @@
+import { Field, useFormikContext } from "formik";
+import FormGroup from "../components/FormGroup";
+import FormToggle from "../components/FormToggle";
+
+const OverviewTextFields = () => {
+ useFormikContext();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default OverviewTextFields;
diff --git a/src/components/SettingForms/SettingForms/SettingForms.tsx b/src/components/SettingForms/SettingForms/SettingForms.tsx
new file mode 100644
index 0000000..cae1786
--- /dev/null
+++ b/src/components/SettingForms/SettingForms/SettingForms.tsx
@@ -0,0 +1,84 @@
+import { Formik, Form } from "formik";
+import BearerTypeCard from "../BearerType/BearerTypeCard";
+import ChannelCard from "../Channel1-JSON/ChannelCard";
+import type { InitialValuesForm } from "../../../types/types";
+import { useState } from "react";
+import AdvancedToggle from "../../UI/AdvancedToggle";
+import OverviewTextCard from "../OverviewText/OverviewTextCard";
+import SightingDataCard from "../SightingData/SightingDataCard";
+
+const SettingForms = () => {
+ const [advancedToggle, setAdvancedToggle] = useState(false);
+
+ const initialValues = {
+ format: "JSON",
+ enabled: false,
+ verbose: false,
+ backOfficeURL: "",
+ username: "",
+ password: "",
+ connectTimeoutSeconds: 0,
+ readTimeoutSeconds: 0,
+ overviewQuality: "high",
+ overviewImageScaleFactor: "full",
+ overviewType: "Plate Overview",
+ invertMotion: false,
+ maxPlateValueLength: 0,
+ vrmToTransit: "plain VRM ASCII (default)",
+ staticReadAction: "Use Lane Direction",
+ noRegionAction: "send",
+ countryCodeType: "IBAN 2 Character code (default)",
+ filterMinConfidence: 0,
+ filterMaxConfidence: 100,
+ overviewQualityOverride: 0,
+ sightingDataEnabled: false,
+ sighthingDataVerbose: false,
+ includeVRM: false,
+ includeMotion: false,
+ includeTimestamp: false,
+ timestampFormat: "UTC",
+ includeCameraName: false,
+ customFieldA: "",
+ customFieldB: "",
+ customFieldC: "",
+ customFieldD: "",
+ overlayPosition: "Top",
+ };
+
+ const handleSubmit = (values: InitialValuesForm) => {
+ alert(JSON.stringify(values));
+ };
+
+ return (
+
+
+
+ );
+};
+
+export default SettingForms;
diff --git a/src/components/SettingForms/SightingData/SightingDataCard.tsx b/src/components/SettingForms/SightingData/SightingDataCard.tsx
new file mode 100644
index 0000000..19c4f56
--- /dev/null
+++ b/src/components/SettingForms/SightingData/SightingDataCard.tsx
@@ -0,0 +1,14 @@
+import Card from "../../UI/Card";
+import CardHeader from "../../UI/CardHeader";
+import SightingDataFields from "./SightingDataFields";
+
+const SightingDataCard = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default SightingDataCard;
diff --git a/src/components/SettingForms/SightingData/SightingDataFields.tsx b/src/components/SettingForms/SightingData/SightingDataFields.tsx
new file mode 100644
index 0000000..e2021e2
--- /dev/null
+++ b/src/components/SettingForms/SightingData/SightingDataFields.tsx
@@ -0,0 +1,123 @@
+import { Field, useFormikContext } from "formik";
+import FormGroup from "../components/FormGroup";
+import FormToggle from "../components/FormToggle";
+
+const SightingDataFields = () => {
+ useFormikContext();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default SightingDataFields;
diff --git a/src/components/SettingForms/components/FormGroup.tsx b/src/components/SettingForms/components/FormGroup.tsx
new file mode 100644
index 0000000..081fc7b
--- /dev/null
+++ b/src/components/SettingForms/components/FormGroup.tsx
@@ -0,0 +1,15 @@
+import React from "react";
+
+type FormGroupProps = {
+ children: React.ReactNode;
+};
+
+const FormGroup = ({ children }: FormGroupProps) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default FormGroup;
diff --git a/src/components/SettingForms/components/FormToggle.tsx b/src/components/SettingForms/components/FormToggle.tsx
new file mode 100644
index 0000000..5a31f58
--- /dev/null
+++ b/src/components/SettingForms/components/FormToggle.tsx
@@ -0,0 +1,17 @@
+import { Field } from "formik";
+
+const FormToggle = ({ name, label }: { name: string; label?: string }) => {
+ return (
+
+ );
+};
+
+export default FormToggle;
diff --git a/src/components/UI/AdvancedToggle.tsx b/src/components/UI/AdvancedToggle.tsx
new file mode 100644
index 0000000..2a7a1f7
--- /dev/null
+++ b/src/components/UI/AdvancedToggle.tsx
@@ -0,0 +1,32 @@
+type AdvancedToggleProps = {
+ advancedToggle: boolean;
+ onAdvancedChange: (advancedToggle: boolean) => void;
+};
+
+const AdvancedToggle = ({
+ advancedToggle,
+ onAdvancedChange,
+}: AdvancedToggleProps) => {
+ return (
+
+
+
+ );
+};
+
+export default AdvancedToggle;
diff --git a/src/components/UI/CardHeader.tsx b/src/components/UI/CardHeader.tsx
index 1046db0..cefeeb6 100644
--- a/src/components/UI/CardHeader.tsx
+++ b/src/components/UI/CardHeader.tsx
@@ -5,7 +5,7 @@ import clsx from "clsx";
type CameraOverviewHeaderProps = {
title: string;
- icon: IconProp;
+ icon?: IconProp;
};
const CardHeader = ({ title, icon }: CameraOverviewHeaderProps) => {
@@ -15,7 +15,7 @@ const CardHeader = ({ title, icon }: CameraOverviewHeaderProps) => {
"w-full border-b border-gray-600 flex flex-row items-center space-x-2 md:mb-6"
)}
>
-
+ {icon && }
{title}
);
diff --git a/src/components/UI/NavigationArrow.tsx b/src/components/UI/NavigationArrow.tsx
index b0955e4..a3bb3b2 100644
--- a/src/components/UI/NavigationArrow.tsx
+++ b/src/components/UI/NavigationArrow.tsx
@@ -4,25 +4,48 @@ import { useNavigate } from "react-router";
type NavigationArrowProps = {
side: string;
+ settingsPage?: boolean;
};
-const NavigationArrow = ({ side }: NavigationArrowProps) => {
+const NavigationArrow = ({ side, settingsPage }: NavigationArrowProps) => {
const navigate = useNavigate();
const navigationDest = (side: string) => {
- if (side === "CameraFront") {
- navigate("/front-camera-settings");
- } else if (side === "Rear") {
+ if (settingsPage) {
navigate("/");
+ return;
+ }
+
+ if (side === "TargetDetectionFront") {
+ navigate("/front-camera-settings");
} else if (side === "TargetDetectionRear") {
navigate("/Rear-Camera-settings");
- } else {
- navigate("/");
}
};
+
+ if (settingsPage) {
+ return (
+ <>
+ {side === "TargetDetectionFront" ? (
+ navigationDest(side)}
+ />
+ ) : (
+ navigationDest(side)}
+ />
+ )}
+ >
+ );
+ }
+
return (
<>
- {side === "CameraFront" || side === "Rear" ? (
+ {side === "TargetDetectionFront" ? (
{
className="mx-auto grid grid-cols-1 sm:grid-cols-1 lg:grid-cols-2 gap-4 px-2 sm:px-4 lg:px-0 w-full"
{...handlers}
>
-
+
);
diff --git a/src/pages/RearCamera.tsx b/src/pages/RearCamera.tsx
index b3a0c59..34b3c99 100644
--- a/src/pages/RearCamera.tsx
+++ b/src/pages/RearCamera.tsx
@@ -16,7 +16,11 @@ const RearCamera = () => {
{...handlers}
>
-
+
);
};
diff --git a/src/pages/SystemSettings.tsx b/src/pages/SystemSettings.tsx
index 6ba7eff..2f90d14 100644
--- a/src/pages/SystemSettings.tsx
+++ b/src/pages/SystemSettings.tsx
@@ -1,10 +1,27 @@
-import Output from "../components/Output/Output";
+import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
+import "react-tabs/style/react-tabs.css";
+import NPEDCard from "../components/SettingForms/NPED/NPEDCard";
+import SettingForms from "../components/SettingForms/SettingForms/SettingForms";
const SystemSettings = () => {
return (
-
-
-
+
+
+
+ Output
+ Integrations
+
+
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/src/types/types.ts b/src/types/types.ts
index a82f84d..137304b 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -40,3 +40,20 @@ export type CameraSettingValues = {
export type CameraSettingErrorValues = Partial<
Record
>;
+
+export type BearerTypeFieldType = {
+ format: string;
+ enabled: boolean;
+ verbose: boolean;
+};
+
+export type InitialValuesForm = {
+ format: string;
+ enabled: boolean;
+ verbose: boolean;
+ backOfficeURL: string;
+ username: string;
+ password: string;
+ connectTimeoutSeconds: number;
+ readTimeoutSeconds: number;
+};
diff --git a/yarn.lock b/yarn.lock
index b8f9bac..43c8fa0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1029,7 +1029,7 @@ chownr@^3.0.0:
resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4"
integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==
-clsx@^2.1.1:
+clsx@^2.0.0, clsx@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
@@ -1761,7 +1761,7 @@ prelude-ls@^1.2.1:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
-prop-types@^15.7.2, prop-types@^15.8.1:
+prop-types@^15.5.0, prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@@ -1830,6 +1830,14 @@ react-swipeable@^7.0.2:
resolved "https://registry.yarnpkg.com/react-swipeable/-/react-swipeable-7.0.2.tgz#ef8858096a47144ba7060675af1cd672e00ecc12"
integrity sha512-v1Qx1l+aC2fdxKa9aKJiaU/ZxmJ5o98RMoFwUqAAzVWUcxgfHFXDDruCKXhw6zIYXm6V64JiHgP9f6mlME5l8w==
+react-tabs@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/react-tabs/-/react-tabs-6.1.0.tgz#a1fc9d9b8db4c6e7bb327a1b6783bc51a1c457a1"
+ integrity sha512-6QtbTRDKM+jA/MZTTefvigNxo0zz+gnBTVFw2CFVvq+f2BuH0nF0vDLNClL045nuTAdOoK/IL1vTP0ZLX0DAyQ==
+ dependencies:
+ clsx "^2.0.0"
+ prop-types "^15.5.0"
+
react@^19.1.1:
version "19.1.1"
resolved "https://registry.yarnpkg.com/react/-/react-19.1.1.tgz#06d9149ec5e083a67f9a1e39ce97b06a03b644af"