osaka/src/pages/LockerStatus.jsx

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;