148 lines
4.0 KiB
JavaScript
148 lines
4.0 KiB
JavaScript
import FormBox from "../components/FormBox";
|
|
import FormField from "../components/FormField";
|
|
import FormInput from "../components/FormInput";
|
|
import FormSelect from "../components/FormSelect";
|
|
import { useTranslation } from "react-i18next";
|
|
import { useState } from "react";
|
|
import clsx from "clsx";
|
|
import Button from "../components/Button";
|
|
import { lockerService } from "../services/locker.service";
|
|
import { useLoading } from "../hooks/useLoading";
|
|
import { AnimatePresence } from "motion/react";
|
|
import Notification from "../components/Notification";
|
|
|
|
function LockerStatus() {
|
|
const { t } = useTranslation();
|
|
const [lockerDetails, setLockerDetails] = useState({
|
|
cabinetId: "",
|
|
lockerId: "",
|
|
status: "",
|
|
cabinetIdValid: true,
|
|
lockerIdValid: true,
|
|
statusValid: true,
|
|
});
|
|
const { isLoading, setIsLoading } = useLoading();
|
|
const [notification, setNotification] = useState({ message: "", type: "" });
|
|
|
|
const formFields = [
|
|
{
|
|
name: "cabinetId",
|
|
label: t("cabinetId"),
|
|
type: "input",
|
|
maxLength: 6,
|
|
readOnly: isLoading,
|
|
validate: (value) => /^[A-Z]{2}[0-9]{4}/.test(value),
|
|
},
|
|
{
|
|
name: "lockerId",
|
|
label: t("lockerId"),
|
|
type: "input",
|
|
maxLength: 6,
|
|
readOnly: isLoading,
|
|
validate: (value) => /^[A-Z]{2}[0-9]{4}/.test(value),
|
|
},
|
|
{
|
|
name: "status",
|
|
label: t("status"),
|
|
type: "select",
|
|
readOnly: isLoading,
|
|
options: [
|
|
{ value: "open", label: t("open") },
|
|
{ value: "close", label: t("close") },
|
|
],
|
|
validate: (value) => value !== "",
|
|
},
|
|
];
|
|
|
|
const handleSubmit = async (e) => {
|
|
e.preventDefault();
|
|
let isValid = true;
|
|
const newValidationState = { ...lockerDetails };
|
|
|
|
// Validate account details fields
|
|
formFields.forEach((field) => {
|
|
if (field.validate) {
|
|
const fieldIsValid = field.validate(lockerDetails[field.name]);
|
|
newValidationState[`${field.name}Valid`] = fieldIsValid;
|
|
if (!fieldIsValid) isValid = false;
|
|
}
|
|
});
|
|
|
|
setLockerDetails(newValidationState);
|
|
|
|
if (!isValid) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
setIsLoading(true);
|
|
const response = await lockerService.changeLockerStatus(
|
|
lockerDetails.cabinetId,
|
|
lockerDetails.lockerId,
|
|
lockerDetails.status
|
|
);
|
|
setNotification({
|
|
message: response.data.message,
|
|
type: "success",
|
|
});
|
|
} catch (error) {
|
|
setNotification({
|
|
message: error.message,
|
|
type: "error",
|
|
});
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const renderField = (field) => {
|
|
const commonProps = {
|
|
value: lockerDetails[field.name],
|
|
valid: lockerDetails[`${field.name}Valid`],
|
|
onChange: (e) => {
|
|
const newLockerDetails = { ...lockerDetails };
|
|
newLockerDetails[field.name] = e.target.value.toUpperCase();
|
|
newLockerDetails[`${field.name}Valid`] = true;
|
|
setLockerDetails(newLockerDetails);
|
|
},
|
|
maxLength: field.maxLength,
|
|
className: clsx(!lockerDetails[`${field.name}Valid`] && "border-error"),
|
|
};
|
|
|
|
return (
|
|
<FormField key={field.name} label={field.label} icon={field.icon}>
|
|
{field.type === "input" ? (
|
|
<FormInput
|
|
{...commonProps}
|
|
type={field.subType}
|
|
readOnly={field.readOnly}
|
|
/>
|
|
) : (
|
|
<FormSelect {...commonProps} options={field.options} />
|
|
)}
|
|
</FormField>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<AnimatePresence>
|
|
{notification.message !== "" && <Notification {...notification} />}
|
|
</AnimatePresence>
|
|
<div className="relative">
|
|
{notification.type === "success" && (
|
|
<div className="absolute inset-0 bg-[#fff]/50 z-10 rounded-3xl" />
|
|
)}
|
|
<FormBox title={t("lockerStatus")}>
|
|
<div className="p-2 pt-7 flex flex-col gap-4">
|
|
{formFields.map(renderField)}
|
|
</div>
|
|
<Button text={t("submit")} onClick={handleSubmit} />
|
|
</FormBox>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default LockerStatus;
|