"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, RhfTextareaField, RhfSelectField, RhfAsyncSelectField, RhfCheckboxField, } from "@/shared/components/form" import { UnitTypeInlineForm } from "@/modules/services/inline-forms/unit-type-inline-form" import { DepartmentInlineForm } from "@/modules/services/inline-forms/department-inline-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 { expenseItemFormSchema, type ExpenseItemFormValues } from "./expense-item.schema" import { EXPENSE_ITEM_ROUTES, INVENTORY_CATEGORY_ROUTES, INVENTORY_ROUTES, DEPARTMENT_ROUTES, } from "@garage/api" import { InventoryCategoryCrudDialog } from "./inventory-category-crud-dialog" import { RhfVendorSelectField } from "@/modules/vendors/rhf-vendor-select-field" // ── Constants ── const ITEM_TYPE_OPTIONS = [ { value: "Expense", label: "Expense" }, ] const mapLookupOption = (item: any) => ({ value: String(item.id), label: item.title ?? item.name ?? String(item.id), }) const STORE_OBJECT = { getOptionValue: (o: any) => o, getOptionLabel: (o: any) => o.label } // ── Props ── export type ExpenseItemFormProps = { resourceId?: string | null initialData?: unknown onSuccess?: () => void } // ── Default values ── const DEFAULT_VALUES: ExpenseItemFormValues = { item_type: "Expense", item_name: "", sku: "", item_code: "", description: "", category: null, unit_type: null, department: null, purchase_information: true, purchase_price: undefined, purchase_chart_of_account: "", purchase_preferred_vendor: null, sales_information: false, selling_price: undefined, sales_chart_of_account: "", is_active: true, } // ── Mapping helpers ── function mapToFormValues(data: unknown): ExpenseItemFormValues { const d = (data as any)?.data ?? data ?? {} return { item_type: d.item_type || "Expense", item_name: d.item_name || "", sku: d.sku || "", item_code: d.item_code || "", description: d.description || "", category: toRelation( d.category_id ?? d.category?.id, d.category_title ?? d.category_name ?? d.category?.title ?? d.category?.name, ), unit_type: toRelation( d.unit_type_id ?? d.unit_type?.id, d.unit_type_title ?? d.unit_type_name ?? d.unit_type?.title ?? d.unit_type?.name, ), department: toRelation( d.department_id ?? d.department?.id, d.department_name ?? d.department_title ?? d.department?.name ?? d.department?.title, ), purchase_information: d.purchase_information ?? true, purchase_price: d.purchase_price ?? undefined, purchase_chart_of_account: d.purchase_chart_of_account || "", purchase_preferred_vendor: toRelation( d.purchase_preferred_vendor_id ?? d.purchase_preferred_vendor?.id, d.purchase_preferred_vendor_name ?? d.purchase_preferred_vendor?.company_name ?? [d.purchase_preferred_vendor?.first_name, d.purchase_preferred_vendor?.last_name].filter(Boolean).join(" "), ), sales_information: d.sales_information ?? false, selling_price: d.selling_price ?? undefined, sales_chart_of_account: d.sales_chart_of_account || "", is_active: d.is_active ?? true, } } function mapFormToPayload(values: ExpenseItemFormValues) { return { item_type: values.item_type, item_name: values.item_name, sku: values.sku || undefined, item_code: values.item_code || undefined, description: values.description || undefined, category_id: toId(values.category), unit_type_id: toId(values.unit_type), department_id: toId(values.department), purchase_information: values.purchase_information, purchase_price: values.purchase_price, purchase_chart_of_account: values.purchase_chart_of_account || undefined, purchase_preferred_vendor_id: toId(values.purchase_preferred_vendor), sales_information: values.sales_information, selling_price: values.selling_price, sales_chart_of_account: values.sales_chart_of_account || undefined, is_active: values.is_active, } } // ── Component ── export function ExpenseItemForm({ resourceId, initialData, onSuccess }: ExpenseItemFormProps) { const api = useAuthApi() const { form, isEditing, invalidate } = useResourceForm({ schema: expenseItemFormSchema, defaultValues: DEFAULT_VALUES, resourceId, initialData, initialize: (id) => api.expenseItems.show(id), queryKey: [EXPENSE_ITEM_ROUTES.BY_ID, resourceId], mapToFormValues, }) const { mutate, error, isPending } = useFormMutation(form, { mutationFn: (values: ExpenseItemFormValues) => { const promise = isEditing && resourceId ? api.expenseItems.update(resourceId, mapFormToPayload(values)) : api.expenseItems.create(mapFormToPayload(values)) toast.promise(promise, { loading: isEditing ? "Updating expense item..." : "Creating expense item...", success: isEditing ? "Expense item updated successfully" : "Expense item created successfully", error: isEditing ? "Failed to update expense item" : "Failed to create expense item", }) return promise }, onSuccess: () => { if (!isEditing) form.reset() onSuccess?.() }, }) return ( mutate(values)}> {error && ( {isEditing ? "Failed to update expense item" : "Failed to create expense item"} {error.message} )} {/* Basic Info */}
{/* Classification */}
Category
api.inventoryCategories.list()} mapOption={mapLookupOption} {...STORE_OBJECT} />
api.inventory.listUnitTypes()} mapOption={mapLookupOption} createForm={(props) => } createLabel="Unit Type" {...STORE_OBJECT} /> api.departments.list()} mapOption={(item: any) => ({ value: String(item.id), label: item.name ?? String(item.id) })} createForm={(props) => } createLabel="Department" {...STORE_OBJECT} />
{/* Purchase Information */}
{/* TODO(phase-2): wire Purchase Chart of Account to the chart-of-accounts module (currently disabled, marked "Coming soon"). */}
{/* Sales Information */} {/*
*/} {/* Status */}
) }