mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-06 06:32:05 +00:00
194 lines
6.2 KiB
TypeScript
194 lines
6.2 KiB
TypeScript
import { useEffect } from "react";
|
|
import { Controller, useForm } from "react-hook-form";
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import { useNavigate, useParams } from "react-router";
|
|
import {
|
|
Alert,
|
|
Box,
|
|
Button,
|
|
CircularProgress,
|
|
FormControl,
|
|
InputLabel,
|
|
MenuItem,
|
|
Paper,
|
|
Select,
|
|
Stack,
|
|
TextField,
|
|
Typography,
|
|
} from "@mui/material";
|
|
import { accountSchema, type AccountFormValues } from "@/domain/accounts/schemas/account-schema";
|
|
import { useAccountDetail } from "@/domain/accounts/use-cases/use-account-detail";
|
|
import { useCreateAccount } from "@/domain/accounts/use-cases/use-create-account";
|
|
import { useUpdateAccount } from "@/domain/accounts/use-cases/use-update-account";
|
|
|
|
const defaultValues: AccountFormValues = {
|
|
AccountName: "",
|
|
AccountNumber: "",
|
|
Industry: "",
|
|
Website: "",
|
|
Notes: "",
|
|
Address1: "",
|
|
Address2: "",
|
|
City: "",
|
|
State: "",
|
|
Zip: "",
|
|
Country: "US",
|
|
};
|
|
|
|
export default function AccountFormPage() {
|
|
const { id } = useParams();
|
|
const navigate = useNavigate();
|
|
const isEdit = Boolean(id);
|
|
|
|
const { data: account, isLoading, error } = useAccountDetail(id);
|
|
const createAccount = useCreateAccount();
|
|
const updateAccount = useUpdateAccount();
|
|
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
reset,
|
|
control,
|
|
formState: { errors },
|
|
} = useForm<AccountFormValues>({
|
|
resolver: zodResolver(accountSchema),
|
|
defaultValues,
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (account && isEdit) {
|
|
reset({
|
|
AccountName: account.AccountName ?? "",
|
|
AccountNumber: account.AccountNumber ?? "",
|
|
Industry: account.Industry ?? "",
|
|
Website: account.Website ?? "",
|
|
Notes: account.Notes ?? "",
|
|
Address1: account.Address1 ?? "",
|
|
Address2: account.Address2 ?? "",
|
|
City: account.City ?? "",
|
|
State: account.State ?? "",
|
|
Zip: account.Zip ?? "",
|
|
Country: account.Country ?? "US",
|
|
});
|
|
}
|
|
}, [account, isEdit, reset]);
|
|
|
|
const isSaving = createAccount.isPending || updateAccount.isPending;
|
|
|
|
const onSubmit = (values: AccountFormValues) => {
|
|
if (isEdit && id) {
|
|
updateAccount.mutate({ id, values });
|
|
return;
|
|
}
|
|
createAccount.mutate(values);
|
|
};
|
|
|
|
if (isEdit && isLoading) {
|
|
return (
|
|
<Box className="flex justify-center p-10">
|
|
<CircularProgress />
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Box className="mx-auto max-w-4xl p-4">
|
|
<Paper variant="outlined" className="p-6">
|
|
<Stack spacing={4}>
|
|
<Stack
|
|
direction="row"
|
|
sx={{
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
}}
|
|
>
|
|
<Typography variant="h5" component="h1">
|
|
{isEdit ? "Edit Account" : "Create an Account"}
|
|
</Typography>
|
|
<Button variant="text" onClick={() => navigate("/accounts")}>
|
|
Back to list
|
|
</Button>
|
|
</Stack>
|
|
|
|
{Boolean(error) && (
|
|
<Alert severity="error">
|
|
{error instanceof Error ? error.message : "Failed to load account"}
|
|
</Alert>
|
|
)}
|
|
|
|
<Box component="form" onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-6">
|
|
<Stack spacing={2}>
|
|
<Typography variant="subtitle1" className="font-semibold">
|
|
General Details
|
|
</Typography>
|
|
<Stack direction={{ xs: "column", md: "row" }} spacing={2}>
|
|
<TextField
|
|
{...register("AccountName")}
|
|
label="Account Name"
|
|
required
|
|
error={Boolean(errors.AccountName)}
|
|
helperText={errors.AccountName?.message}
|
|
fullWidth
|
|
/>
|
|
<TextField {...register("AccountNumber")} label="Account Number" fullWidth />
|
|
</Stack>
|
|
<Stack direction={{ xs: "column", md: "row" }} spacing={2}>
|
|
<TextField {...register("Industry")} label="Industry" fullWidth />
|
|
<TextField {...register("Website")} label="Website" fullWidth />
|
|
</Stack>
|
|
<TextField {...register("Notes")} label="Notes" fullWidth multiline minRows={2} />
|
|
</Stack>
|
|
|
|
<Stack spacing={2}>
|
|
<Typography variant="subtitle1" className="font-semibold">
|
|
Address
|
|
</Typography>
|
|
<Stack direction={{ xs: "column", md: "row" }} spacing={2}>
|
|
<TextField {...register("Address1")} label="Address 1" fullWidth />
|
|
<TextField {...register("Address2")} label="Address 2" fullWidth />
|
|
</Stack>
|
|
<Stack direction={{ xs: "column", md: "row" }} spacing={2}>
|
|
<TextField {...register("City")} label="City" fullWidth />
|
|
<TextField {...register("State")} label="State / Province" fullWidth />
|
|
<TextField {...register("Zip")} label="Zip/Postal Code" fullWidth />
|
|
</Stack>
|
|
<Controller
|
|
name="Country"
|
|
control={control}
|
|
render={({ field }) => (
|
|
<FormControl fullWidth>
|
|
<InputLabel id="country-label">Country</InputLabel>
|
|
<Select
|
|
{...field}
|
|
labelId="country-label"
|
|
label="Country"
|
|
value={field.value ?? "US"}
|
|
>
|
|
<MenuItem value="">Select Country</MenuItem>
|
|
<MenuItem value="US">United States</MenuItem>
|
|
</Select>
|
|
</FormControl>
|
|
)}
|
|
/>
|
|
</Stack>
|
|
|
|
<Stack
|
|
direction="row"
|
|
spacing={2}
|
|
sx={{
|
|
justifyContent: "flex-end",
|
|
}}
|
|
>
|
|
<Button variant="outlined" onClick={() => navigate("/accounts")} disabled={isSaving}>
|
|
Cancel
|
|
</Button>
|
|
<Button type="submit" variant="contained" disabled={isSaving}>
|
|
{isSaving ? "Saving..." : isEdit ? "Update Account" : "Create Account"}
|
|
</Button>
|
|
</Stack>
|
|
</Box>
|
|
</Stack>
|
|
</Paper>
|
|
</Box>
|
|
);
|
|
}
|