62 lines
2.3 KiB
JavaScript
62 lines
2.3 KiB
JavaScript
import { cn, fmt } from '@/lib/utils';
|
||
import { paymentSummary } from '@/lib/trackerUtils';
|
||
|
||
export function PaymentProgress({ row, threshold, onOpen, onMarkFullAmount, compact = false, className }) {
|
||
const summary = paymentSummary(row, threshold);
|
||
const barTone = summary.remaining === 0
|
||
? 'bg-emerald-500'
|
||
: summary.paid > 0
|
||
? 'bg-amber-500'
|
||
: 'bg-muted-foreground/40';
|
||
|
||
const amountLabel = (() => {
|
||
if (summary.paid === 0) return '—';
|
||
if (summary.overpaid > 0) return `${fmt(summary.paid)} · overpaid`;
|
||
if (summary.remaining > 0) return `${fmt(summary.paidTowardDue)} paid`;
|
||
return fmt(summary.paidTowardDue);
|
||
})();
|
||
|
||
const showQuickFix = onMarkFullAmount && summary.partial && summary.paid > 0;
|
||
|
||
return (
|
||
<div className={cn('w-full', className)}>
|
||
<button
|
||
type="button"
|
||
onClick={onOpen}
|
||
className={cn(
|
||
'w-full rounded-md text-left transition-colors hover:bg-accent/60 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',
|
||
compact ? 'p-2' : 'px-2 py-1',
|
||
)}
|
||
title="View payment history"
|
||
>
|
||
<div className="flex items-center justify-between gap-2 text-xs">
|
||
<span className={cn('tracker-number text-xs font-semibold', summary.paid > 0 ? 'text-emerald-300' : 'text-muted-foreground/85')}>
|
||
{amountLabel}
|
||
</span>
|
||
{summary.count > 1 && (
|
||
<span className="shrink-0 rounded-full bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
|
||
{summary.count}×
|
||
</span>
|
||
)}
|
||
</div>
|
||
<div className="mt-1.5 h-1.5 overflow-hidden rounded-full bg-muted">
|
||
<div
|
||
className={cn('h-full rounded-full transition-all', barTone)}
|
||
style={{ width: `${summary.percent}%` }}
|
||
/>
|
||
</div>
|
||
</button>
|
||
{showQuickFix && (
|
||
<button
|
||
type="button"
|
||
onClick={onMarkFullAmount}
|
||
className="mt-0.5 w-full rounded px-2 py-0.5 text-left text-[10px] text-muted-foreground/60 transition-colors hover:bg-accent/50 hover:text-foreground"
|
||
title={`Set ${fmt(summary.paidTowardDue)} as the full amount due this month`}
|
||
>
|
||
✓ {fmt(summary.paidTowardDue)} is the full amount
|
||
</button>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|