71 lines
2.3 KiB
TypeScript
71 lines
2.3 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import { FileText } from "lucide-react"
|
|
import { Button } from "@/shared/components/ui/button"
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from "@/shared/components/ui/dialog"
|
|
import { ScrollArea } from "@/shared/components/ui/scroll-area"
|
|
import { InvoiceForm } from "@/modules/invoices/invoice-form"
|
|
import { toRelation } from "@/shared/lib/utils"
|
|
import { useEstimate } from "./estimate-context"
|
|
|
|
/**
|
|
* Maps an Estimate data object to an InvoiceFormValues shape so that
|
|
* useResourceForm's shallow spread correctly pre-fills all relational fields.
|
|
*/
|
|
function mapEstimateToInvoiceInitialData(estimate: Record<string, any>) {
|
|
return {
|
|
subject: estimate.title ?? "",
|
|
notes: estimate.footer ?? "",
|
|
|
|
// Relation fields — must be { value, label } objects for RhfAsyncSelectField
|
|
customer: toRelation(estimate.customer_id, estimate.customer_name),
|
|
vehicle: toRelation(estimate.vehicle_id, estimate.vehicle_name),
|
|
department: toRelation(estimate.department_id, estimate.department_name),
|
|
|
|
invoice_number: "",
|
|
invoice_date: estimate.date ?? "",
|
|
due_date: "",
|
|
status: "draft" as const,
|
|
}
|
|
}
|
|
|
|
export function CreateInvoiceFromEstimateButton() {
|
|
const [open, setOpen] = useState(false)
|
|
const estimateContext = useEstimate()
|
|
|
|
if (!estimateContext) return null
|
|
|
|
const initialData = estimateContext.data
|
|
? mapEstimateToInvoiceInitialData(estimateContext.data)
|
|
: undefined
|
|
|
|
return (
|
|
<>
|
|
<Button variant="outline" size="sm" onClick={() => setOpen(true)}>
|
|
<FileText className="me-2 size-4" />
|
|
Generate Invoice
|
|
</Button>
|
|
|
|
<Dialog open={open} onOpenChange={setOpen}>
|
|
<DialogContent className="min-w-2xl">
|
|
<DialogHeader>
|
|
<DialogTitle>Generate Invoice from Estimate</DialogTitle>
|
|
</DialogHeader>
|
|
<ScrollArea className="max-h-[75vh] px-1">
|
|
<InvoiceForm
|
|
initialData={initialData}
|
|
onSuccess={() => setOpen(false)}
|
|
/>
|
|
</ScrollArea>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</>
|
|
)
|
|
}
|