111 lines
3.1 KiB
TypeScript
111 lines
3.1 KiB
TypeScript
"use client"
|
||
|
||
import { Separator } from "@/shared/components/ui/separator"
|
||
import { formatCurrency } from "@/shared/utils/formatters"
|
||
import { cn } from "@/shared/lib/utils"
|
||
import type { DocumentTotals } from "@/shared/hooks/use-document-totals"
|
||
|
||
export type DocumentTotalsSummaryProps = {
|
||
totals: DocumentTotals
|
||
discountType?: string | null
|
||
taxLabel?: string | null
|
||
/** Override labels for line groups, keyed by group name */
|
||
groupLabels?: Record<string, number>
|
||
}
|
||
|
||
function SummaryRow({
|
||
label,
|
||
value,
|
||
muted = false,
|
||
className,
|
||
}: {
|
||
label: string
|
||
value: string
|
||
muted?: boolean
|
||
className?: string
|
||
}) {
|
||
return (
|
||
<div className={cn("flex items-center justify-between text-sm", className)}>
|
||
<span className={muted ? "text-muted-foreground" : ""}>{label}</span>
|
||
<span className={muted ? "text-muted-foreground" : ""}>{value}</span>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export function DocumentTotalsSummary({
|
||
totals,
|
||
discountType,
|
||
taxLabel,
|
||
groupLabels,
|
||
}: DocumentTotalsSummaryProps) {
|
||
const {
|
||
subTotal,
|
||
lineItemDiscount,
|
||
transactionDiscount,
|
||
totalDiscount,
|
||
taxAmount,
|
||
total,
|
||
hasLineItems,
|
||
} = totals
|
||
|
||
if (!hasLineItems) return null
|
||
|
||
return (
|
||
<div className="space-y-2">
|
||
{/* Group breakdowns */}
|
||
{groupLabels &&
|
||
Object.entries(groupLabels).map(([label, amount]) => (
|
||
<SummaryRow
|
||
key={label}
|
||
label={label}
|
||
value={formatCurrency(amount)}
|
||
muted
|
||
/>
|
||
))}
|
||
|
||
{groupLabels && Object.keys(groupLabels).length > 0 && <Separator />}
|
||
|
||
{/* Subtotal */}
|
||
<SummaryRow label="Subtotal" value={formatCurrency(subTotal)} />
|
||
|
||
{/* Line-item discount */}
|
||
{discountType === "line_item_level" && lineItemDiscount > 0 && (
|
||
<SummaryRow
|
||
label="Line Discounts"
|
||
value={`– ${formatCurrency(lineItemDiscount)}`}
|
||
muted
|
||
/>
|
||
)}
|
||
|
||
{/* Transaction-level discount */}
|
||
{discountType === "transaction_level" && transactionDiscount > 0 && (
|
||
<SummaryRow
|
||
label="Discount"
|
||
value={`– ${formatCurrency(transactionDiscount)}`}
|
||
muted
|
||
/>
|
||
)}
|
||
|
||
{/* Tax */}
|
||
{taxAmount > 0 && (
|
||
<SummaryRow
|
||
label={taxLabel ?? "Tax"}
|
||
value={`+ ${formatCurrency(taxAmount)}`}
|
||
muted
|
||
/>
|
||
)}
|
||
|
||
<Separator />
|
||
|
||
{/* Total */}
|
||
<div className={cn(
|
||
"flex items-center justify-between rounded-md px-3 py-2 text-sm font-semibold",
|
||
"bg-primary/10 text-primary",
|
||
)}>
|
||
<span>Total</span>
|
||
<span>{formatCurrency(total)}</span>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|