- updated backoffice setup

- need to add async loading state
This commit is contained in:
2025-10-07 14:00:58 +01:00
parent 3e564b933d
commit c2c2fc76f2
6 changed files with 251 additions and 153 deletions

View File

@@ -1,88 +1,182 @@
import { Field, Form, Formik } 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 = () => {
const [showPwd, setShowPwd] = useState(false);
const initialValues = {
backOfficeURL: "",
username: "",
password: "",
connectTimeoutSeconds: 0,
readTimeoutSeconds: 0,
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 = (values) => {
console.log(values);
const handleSubmit = (values: InitialValuesForm) => {
backOfficeMutation.mutate(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 (
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
<Form>
<div className="flex flex-col space-y-2 px-2">
<FormGroup>
<label htmlFor="backoffice" className="m-0">
Back Office URL
</label>
<Field
name={"backOfficeURL"}
type="text"
id="backoffice"
placeholder="https://www.backoffice.com"
className="p-1.5 border border-gray-400 rounded-lg w-full md:w-60"
/>
</FormGroup>
<FormGroup>
<label htmlFor="username">Username</label>
<Field
name={"username"}
type="text"
id="username"
placeholder="Back office username"
className="p-1.5 border border-gray-400 rounded-lg w-full md:w-60"
/>
</FormGroup>
<FormGroup>
<label htmlFor="password">Password</label>
<Field
name={"password"}
type={showPwd ? "text" : "password"}
id="password"
placeholder="Back office password"
className="p-1.5 border border-gray-400 rounded-lg w-full md:w-60"
/>
<FontAwesomeIcon
type="button"
className="absolute right-5 end-0"
onClick={() => setShowPwd((s) => !s)}
icon={showPwd ? faEyeSlash : faEye}
/>
</FormGroup>
<FormGroup>
<label htmlFor="connectTimeoutSeconds">
Connect Timeout Seconds
</label>
<Field
name={"connectTimeoutSeconds"}
type="number"
id="connectTimeoutSeconds"
className="p-1.5 border border-gray-400 rounded-lg w-full md:w-60"
/>
</FormGroup>
<FormGroup>
<label htmlFor="readTimeoutSeconds">Read Timeout Seconds</label>
<Field
name={"readTimeoutSeconds"}
type="number"
id="readTimeoutSeconds"
placeholder="https://example.com"
className="p-1.5 border border-gray-400 rounded-lg w-full md:w-60"
/>
</FormGroup>
</div>
</Form>
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
enableReinitialize
validate={validateValues}
>
{({ errors, touched }) => (
<Form>
<div className="flex flex-col space-y-2 px-2">
<FormGroup>
<label htmlFor="backoffice" className="m-0">
Back Office URL
</label>
<Field
name={"backOfficeURL"}
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`}
/>
</FormGroup>
<FormGroup>
<label htmlFor="username">Username</label>
<Field
name={"username"}
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`}
/>
</FormGroup>
<FormGroup>
<label htmlFor="password">Password</label>
<Field
name={"password"}
type={showPwd ? "text" : "password"}
id="password"
placeholder="Back office password"
className={`p-1.5 border ${
errors.password && touched.password
? "border-red-500"
: "border-gray-400 "
} rounded-lg w-full md:w-60`}
/>
<FontAwesomeIcon
type="button"
className="absolute right-5 end-0"
onClick={() => setShowPwd((s) => !s)}
icon={showPwd ? faEyeSlash : faEye}
/>
</FormGroup>
<FormGroup>
<label htmlFor="connectTimeoutSeconds">
Connect Timeout Seconds
</label>
<Field
name={"connectTimeoutSeconds"}
type="number"
id="connectTimeoutSeconds"
className={`p-1.5 border ${
errors.connectTimeoutSeconds && touched.connectTimeoutSeconds
? "border-red-500"
: "border-gray-400 "
} rounded-lg w-full md:w-60`}
/>
</FormGroup>
<FormGroup>
<label htmlFor="readTimeoutSeconds">Read Timeout Seconds</label>
<Field
name={"readTimeoutSeconds"}
type="number"
id="readTimeoutSeconds"
placeholder="https://example.com"
className={`p-1.5 border ${
errors.readTimeoutSeconds && touched.readTimeoutSeconds
? "border-red-500"
: "border-gray-400 "
} rounded-lg w-full md:w-60`}
/>
</FormGroup>
</div>
<button
type="submit"
className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full md:w-[50%]"
>
Save Changes
</button>
<ValidationToastOnce />
</Form>
)}
</Formik>
);
};

View File

@@ -1,10 +1,8 @@
import { Field, useFormikContext } from "formik";
import { Field } from "formik";
import FormGroup from "../components/FormGroup";
import FormToggle from "../components/FormToggle";
const OverviewTextFields = () => {
useFormikContext();
return (
<div className="flex flex-col space-y-2 px-2">
<FormGroup>

View File

@@ -1,78 +1,12 @@
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 = {
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 (
<div className="mx-auto grid grid-cols-1 sm:grid-cols-1 lg:grid-cols-2 gap-2 px-2 sm:px-4 lg:px-0 w-full">
<BearerTypeCard />
<ChannelCard />
</div>
// <Formik initialValues={initialValues} onSubmit={handleSubmit}>
// <Form className="flex flex-col space-y-3">
// <div className="mx-auto grid grid-cols-1 sm:grid-cols-1 lg:grid-cols-2 gap-2 px-2 sm:px-4 lg:px-0 w-full">
//
// </div>
// <AdvancedToggle
// advancedToggle={advancedToggle}
// onAdvancedChange={setAdvancedToggle}
// />
// {advancedToggle && (
// <>
// <div className="md:col-span-2">
// <SightingDataCard />
// </div>
// <div className="md:col-span-2">
// <OverviewTextCard />
// </div>
// </>
// )}
// <button
// type="submit"
// className="bg-[#26B170] text-white px-4 py-2 rounded hover:bg-green-700 transition w-full md:w-[50%]"
// >
// Save Changes
// </button>
// </Form>
// </Formik>
);
};

View File

@@ -1,10 +1,8 @@
import { Field, useFormikContext } from "formik";
import { Field } from "formik";
import FormGroup from "../components/FormGroup";
import FormToggle from "../components/FormToggle";
const SightingDataFields = () => {
useFormikContext();
return (
<div className="flex flex-col space-y-2 px-2">
<FormGroup>