garage-erp/apps/dashboard/modules/estimates/estimate-totals-summary.tsx
Mohammad Khyata 65964605e1 updates
Co-authored-by: Copilot <copilot@github.com>
2026-04-24 12:20:10 +03:00

84 lines
3.5 KiB
TypeScript

"use client"
import { Card, CardContent } from "@/shared/components/ui/card"
import { Separator } from "@/shared/components/ui/separator"
import { formatCurrency, formatEnum } from "@/shared/utils/formatters"
import { useEstimate } from "./estimate-context"
export function EstimateTotalsSummary() {
const estimate = useEstimate()
if (!estimate) return null
const parts = estimate.estimate_parts ?? []
const services = estimate.estimate_services ?? []
const expenses = estimate.estimate_expense_items ?? []
const discount = estimate.discount
const displayTotal = parseFloat(String(estimate.total ?? 0)) || 0
const hasItems = parts.length > 0 || services.length > 0 || expenses.length > 0
if (!hasItems && displayTotal === 0) return null
const subTotal = parseFloat(String(estimate.sub_total ?? 0)) || 0
function lineTotal(items: { quantity?: string | number; rate?: string | number }[]) {
return items.reduce((sum, item) => {
const qty = parseFloat(String(item.quantity ?? 0))
const rate = parseFloat(String(item.rate ?? 0))
return sum + (isNaN(qty) || isNaN(rate) ? 0 : qty * rate)
}, 0)
}
return (
<Card>
<CardContent className="pt-6">
<div className="ml-auto max-w-sm space-y-2">
{hasItems && (
<>
{parts.length > 0 && (
<div className="flex justify-between text-sm">
<span className="text-muted-foreground">Parts ({parts.length})</span>
<span>{formatCurrency(lineTotal(parts))}</span>
</div>
)}
{services.length > 0 && (
<div className="flex justify-between text-sm">
<span className="text-muted-foreground">Services ({services.length})</span>
<span>{formatCurrency(lineTotal(services))}</span>
</div>
)}
{expenses.length > 0 && (
<div className="flex justify-between text-sm">
<span className="text-muted-foreground">Expenses ({expenses.length})</span>
<span>{formatCurrency(lineTotal(expenses))}</span>
</div>
)}
<Separator />
</>
)}
<div className="flex justify-between text-sm font-medium">
<span>Subtotal</span>
<span>{formatCurrency(subTotal)}</span>
</div>
{discount && discount !== "no" && (
<div className="flex justify-between text-sm">
<span className="text-muted-foreground">Discount ({formatEnum(discount)})</span>
<span className="text-muted-foreground">Applied</span>
</div>
)}
<Separator />
<div className="flex justify-between text-base font-semibold">
<span>Total</span>
<span>{formatCurrency(displayTotal)}</span>
</div>
</div>
</CardContent>
</Card>
)
}