"use client" import { useMemo } from "react" 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, RhfTextareaField, RhfAsyncSelectField, RhfDateField, RhfAutoGenerateField, } 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 { paymentReceivedFormSchema, type PaymentReceivedFormValues, } from "./payment-received.schema" import { PAYMENT_MODE_ROUTES, CUSTOMER_ROUTES, JOB_CARD_ROUTES } from "@garage/api" // ── Props ── export type PaymentReceivedFormProps = { resourceId?: string | null initialData?: unknown onSuccess?: () => void defaultJobCard?: { id?: number | null; title?: string | null } | null invoiceId?: string | null invoiceCustomer?: { id?: number | null; first_name?: string | null; last_name?: string | null } | null invoiceAmount?: number | string | null } // ── Default values ── const DEFAULT_VALUES: PaymentReceivedFormValues = { job_card: null, payment_mode: null, customer: null, amount_received: "", payment_number: "", payment_date: new Date().toISOString().split("T")[0], note: "", } // ── Mapping helpers ── function mapToFormValues(data: unknown): PaymentReceivedFormValues { const d = (data as any)?.data ?? data ?? {} return { job_card: toRelation(d.job_card_id, d.job_card_name), payment_mode: toRelation(d.payment_mode_id, d.payment_mode_name), customer: toRelation(d.customer_id, d.customer_name), amount_received: d.amount_received ? String(d.amount_received) : "", payment_number: d.payment_number || "", payment_date: d.payment_date || "", note: d.note || "", } } function mapFormToPayload(values: PaymentReceivedFormValues, invoiceId?: string | null) { return { job_card_id: toId(values.job_card), payment_mode_id: toId(values.payment_mode), customer_id: toId(values.customer), amount_received: values.amount_received, payment_number: values.payment_number || undefined, payment_date: values.payment_date, note: values.note || undefined, ...(invoiceId ? { invoice_id: Number(invoiceId) } : {}), } } // ── Shared mapOption for async selects ── const mapLookupOption = (item: any) => ({ value: String(item.id), label: item.name || item.title, }) const STORE_OBJECT = { getOptionValue: (o: any) => o, getOptionLabel: (o: any) => o.label } // ── Component ── export function PaymentReceivedForm({ resourceId, initialData, onSuccess, defaultJobCard, invoiceId, invoiceCustomer, invoiceAmount }: PaymentReceivedFormProps) { const api = useAuthApi() const resolvedInitialData = useMemo(() => { const base: any = { ...(initialData as any) } if (!resourceId) { if (defaultJobCard?.id != null) { base.job_card = toRelation(defaultJobCard.id, defaultJobCard.title ?? undefined) } if (invoiceCustomer?.id != null) { const customerLabel = invoiceCustomer.first_name ? `${invoiceCustomer.first_name} ${invoiceCustomer.last_name || ""}`.trim() : (invoiceCustomer as any).company_name || (invoiceCustomer as any).name || undefined base.customer = toRelation(invoiceCustomer.id, customerLabel) } if (invoiceAmount != null && invoiceAmount !== "") { base.amount_received = String(invoiceAmount) } } return Object.keys(base).length ? base : initialData }, [resourceId, defaultJobCard, initialData, invoiceCustomer, invoiceAmount]) const { form, isEditing } = useResourceForm({ schema: paymentReceivedFormSchema, defaultValues: DEFAULT_VALUES, resourceId, initialData: resolvedInitialData, mapToFormValues, }) const { mutate, error, isPending } = useFormMutation(form, { mutationFn: (values: PaymentReceivedFormValues) => { const payload = mapFormToPayload(values, invoiceId) const promise = isEditing && resourceId ? api.paymentReceived.update(resourceId, payload as any) : api.paymentReceived.create(payload as any) toast.promise(promise, { loading: isEditing ? "Updating payment..." : "Recording payment...", success: isEditing ? "Payment updated successfully" : "Payment recorded successfully", error: isEditing ? "Failed to update payment" : "Failed to record payment", }) return promise }, onSuccess: () => { form.reset() onSuccess?.() }, }) return ( mutate(values)}> {error && ( {isEditing ? "Failed to update payment" : "Failed to record payment"} {error.message} )}
api.customers.list()} mapOption={(item: any) => ({ value: String(item.id), label: item.first_name ? `${item.first_name} ${item.last_name || ""}`.trim() : item.name || `#${item.id}`, })} {...STORE_OBJECT} /> api.jobCards.list()} mapOption={(item: any) => ({ value: String(item.id), label: item.title, })} {...STORE_OBJECT} />
api.paymentModes.list()} mapOption={mapLookupOption} {...STORE_OBJECT} />
) }