mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-03 19:03:15 +00:00
146 lines
4 KiB
TypeScript
146 lines
4 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { useForm } from "react-hook-form";
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import {
|
|
Alert,
|
|
Box,
|
|
Button,
|
|
CircularProgress,
|
|
Dialog,
|
|
DialogActions,
|
|
DialogContent,
|
|
DialogTitle,
|
|
Stack,
|
|
Typography,
|
|
} from "@mui/material";
|
|
import { VendorFormFields } from "./vendor-form-fields";
|
|
import { vendorSchema, type VendorFormValues } from "@/domain/vendors/schemas/vendor-schema";
|
|
import { useCreateVendor } from "@/domain/vendors/use-cases/use-create-vendor";
|
|
import { useVendorFacets } from "@/domain/vendors/use-cases/use-vendor-facets";
|
|
import type { VendorFacetCompany } from "@/domain/vendors/types/vendor";
|
|
|
|
interface VendorCreateModalProps {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
tradeOptions: string[];
|
|
}
|
|
|
|
const defaultValues: VendorFormValues = {
|
|
companyName: "",
|
|
contactName: "",
|
|
email: "",
|
|
phone: "",
|
|
companyPhone: "",
|
|
googleMapsUrl: "",
|
|
notes: "",
|
|
totalJobs: 0,
|
|
address: "",
|
|
city: "",
|
|
state: "",
|
|
zip: "",
|
|
tradeSpecialties: "",
|
|
isActive: true,
|
|
};
|
|
|
|
export function VendorCreateModal({ open, onClose, tradeOptions }: VendorCreateModalProps) {
|
|
const { data: facets, isLoading: isLoadingFacets, error: facetsError } = useVendorFacets();
|
|
const createVendor = useCreateVendor();
|
|
const [submitError, setSubmitError] = useState<string | null>(null);
|
|
|
|
const {
|
|
control,
|
|
handleSubmit,
|
|
reset,
|
|
setValue,
|
|
formState: { errors },
|
|
} = useForm<VendorFormValues>({
|
|
resolver: zodResolver(vendorSchema),
|
|
defaultValues,
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (open) {
|
|
reset(defaultValues);
|
|
setSubmitError(null);
|
|
}
|
|
}, [open, reset]);
|
|
|
|
const onCompanySelected = (company: VendorFacetCompany | null) => {
|
|
if (!company) return;
|
|
setValue("companyPhone", company.companyPhone);
|
|
setValue("email", company.email);
|
|
setValue("address", company.address);
|
|
setValue("city", company.city);
|
|
setValue("state", company.state);
|
|
setValue("zip", company.zip);
|
|
setValue("googleMapsUrl", company.googleMapsUrl);
|
|
};
|
|
|
|
const onSubmit = (values: VendorFormValues) => {
|
|
setSubmitError(null);
|
|
createVendor.mutate(values, {
|
|
onSuccess: () => {
|
|
onClose();
|
|
},
|
|
onError: (error: Error) => {
|
|
setSubmitError(error.message || "Failed to create vendor");
|
|
},
|
|
});
|
|
};
|
|
|
|
const companies = facets?.companies ?? [];
|
|
|
|
return (
|
|
<Dialog
|
|
open={open}
|
|
onClose={createVendor.isPending ? undefined : onClose}
|
|
fullWidth
|
|
maxWidth="sm"
|
|
aria-labelledby="vendor-create-dialog-title"
|
|
slotProps={{ paper: { role: "dialog" } }}
|
|
>
|
|
<DialogTitle id="vendor-create-dialog-title">
|
|
Add Vendor
|
|
<Typography variant="body2" sx={{ color: "text.secondary", mt: 0.5 }}>
|
|
Register a technician and their vendor company.
|
|
</Typography>
|
|
</DialogTitle>
|
|
<DialogContent>
|
|
<Stack spacing={2} className="mt-1">
|
|
{Boolean(facetsError) && (
|
|
<Alert severity="warning">
|
|
Company autocomplete unavailable. You can still type a company manually.
|
|
</Alert>
|
|
)}
|
|
{Boolean(submitError) && <Alert severity="error">{submitError}</Alert>}
|
|
{isLoadingFacets ? (
|
|
<CircularProgress size={24} />
|
|
) : (
|
|
<Box>
|
|
<VendorFormFields
|
|
control={control}
|
|
errors={errors}
|
|
companies={companies}
|
|
tradeOptions={tradeOptions}
|
|
onCompanySelected={onCompanySelected}
|
|
/>
|
|
</Box>
|
|
)}
|
|
</Stack>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button onClick={onClose} disabled={createVendor.isPending}>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
color="primary"
|
|
variant="contained"
|
|
onClick={handleSubmit(onSubmit)}
|
|
disabled={createVendor.isPending}
|
|
>
|
|
{createVendor.isPending ? "Saving..." : "Add Vendor"}
|
|
</Button>
|
|
</DialogActions>
|
|
</Dialog>
|
|
);
|
|
}
|