"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, } 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 } // ── Default values ── const DEFAULT_VALUES: PaymentReceivedFormValues = { job_card: null, payment_mode: null, customer: null, amount_received: "", payment_number: "", payment_date: "", 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) { 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, } } // ── 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 }: PaymentReceivedFormProps) { const api = useAuthApi() const resolvedInitialData = useMemo(() => { if (!resourceId && defaultJobCard?.id != null) { return { ...(initialData as any), job_card: toRelation(defaultJobCard.id, defaultJobCard.title ?? undefined), } } return initialData }, [resourceId, defaultJobCard, initialData]) 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) 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} />
) }