"use client" import { AlertTriangle, Plus, Save } from "lucide-react" import { Button } from "@/shared/components/ui/button" import { Alert, AlertTitle } from "@/shared/components/ui/alert" import { FieldGroup } from "@/shared/components/ui/field" import { Rhform, RhfTextField, RhfSelectField, RhfAsyncSelectField, } from "@/shared/components/form" import { toast } from "sonner" import { useAuthApi } from "@/shared/useApi" import { useResourceForm } from "@/shared/hooks/use-resource-form" import { useFormMutation } from "@/shared/hooks/use-form-mutation" import { toRelation, toId } from "@/shared/lib/utils" import { customerFormSchema, type CustomerFormValues, } from "./customer.schema" import { CUSTOMER_ROUTES, PAYMENT_TERM_ROUTES } from "@garage/api" import { PaymentTermCrudDialog } from "./payment-term-crud-dialog" // ── Constants ── const SALUTATION_OPTIONS = [ { value: "Mr.", label: "Mr." }, { value: "Mrs.", label: "Mrs." }, { value: "Ms.", label: "Ms." }, { value: "Miss", label: "Miss" }, { value: "Dr.", label: "Dr." }, { value: "Prof.", label: "Prof." }, ] // ── Props ── export type CustomerFormProps = { resourceId?: string | null initialData?: unknown onSuccess?: (data?: any) => void } // ── Default values ── const CUSTOMER_DEFAULT_VALUES: CustomerFormValues = { customer_type: null, referral_source: null, payment_terms: null, country: null, state: null, salutation: "", first_name: "", last_name: "", company_name: "", email: "", phone: "", alternate_phone: "", address_line_1: "", address_line_2: "", city: "", zip_code: "", } // ── Mapping helpers ── function mapCustomerToFormValues(data: unknown): CustomerFormValues { const c = (data as any)?.data ?? data ?? {} return { customer_type: toRelation(c.customer_type_id, c.customer_type?.name ?? c.customer_type_name), referral_source: toRelation(c.referral_source_id, c.referral_source_name), payment_terms: toRelation(c.payment_terms_id, c.payment_terms_name), country: toRelation(c.country_id, c.country_name), state: toRelation(c.state_id, c.state_name), salutation: c.salutation || "", first_name: c.first_name || "", last_name: c.last_name || "", company_name: c.company_name || "", email: c.email || "", phone: c.phone || "", alternate_phone: c.alternate_phone || "", address_line_1: c.address_line_1 || "", address_line_2: c.address_line_2 || "", city: c.city || "", zip_code: c.zip_code || "", } } function mapFormToPayload(values: CustomerFormValues) { return { customer_type_id: toId(values.customer_type), referral_source_id: toId(values.referral_source), payment_terms_id: toId(values.payment_terms), country_id: toId(values.country), state_id: toId(values.state), salutation: values.salutation || undefined, first_name: values.first_name, last_name: values.last_name, company_name: values.company_name || undefined, email: values.email || undefined, phone: values.phone || undefined, alternate_phone: values.alternate_phone || undefined, address_line_1: values.address_line_1 || undefined, address_line_2: values.address_line_2 || undefined, city: values.city || undefined, zip_code: values.zip_code || undefined, } } // ── Shared mapOption for async selects ── const mapLookupOption = (item: any) => ({ value: String(item.id), label: item.title||item.name || `#${item.id}`, }) const STORE_OBJECT = { getOptionValue: (o: any) => o, getOptionLabel: (o: any) => o.label || o.name || `#${o.id}` } // ── Component ── export function CustomerForm({ resourceId, initialData, onSuccess }: CustomerFormProps) { const api = useAuthApi() const { form, isEditing } = useResourceForm({ schema: customerFormSchema, defaultValues: CUSTOMER_DEFAULT_VALUES, resourceId, initialData, initialize: (id) => api.customers.show(id), queryKey: [CUSTOMER_ROUTES.BY_ID, resourceId], mapToFormValues: mapCustomerToFormValues, }) const { mutate, error, isPending } = useFormMutation(form, { mutationFn: (values: CustomerFormValues) => { const payload = mapFormToPayload(values) const promise = isEditing && resourceId ? api.customers.update(resourceId, payload) : api.customers.create(payload) toast.promise(promise, { loading: isEditing ? "Updating customer..." : "Creating customer...", success: isEditing ? "Customer updated successfully" : "Customer created successfully", error: isEditing ? "Failed to update customer" : "Failed to create customer", }) return promise }, onSuccess: (data) => { form.reset() onSuccess?.(data) }, }) return ( mutate(values)}> {error && ( {isEditing ? "Failed to update customer" : "Failed to create customer"} {error.message} )} {/* Basic Info */}
api.customers.listCustomerTypes()} mapOption={mapLookupOption} {...STORE_OBJECT} />
{/* Name */}
{/* Contact */}
{/* Relations */}
api.referralSources.list()} mapOption={mapLookupOption} {...STORE_OBJECT} />
Payment Terms
api.paymentTerms.list()} mapOption={mapLookupOption} {...STORE_OBJECT} />
{/* Address */}
api.geo.countries()} mapOption={mapLookupOption} {...STORE_OBJECT} /> api.geo.states()} mapOption={mapLookupOption} {...STORE_OBJECT} />
) }