BillTracker/client/components/tracker/PaymentProgress.jsx

62 lines
2.3 KiB
React
Raw Permalink Normal View History

2026-05-31 15:06:10 -05:00
import { cn, fmt } from '@/lib/utils';
import { paymentSummary } from '@/lib/trackerUtils';
export function PaymentProgress({ row, threshold, onOpen, onMarkFullAmount, compact = false, className }) {
2026-05-31 15:06:10 -05:00
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`;
2026-05-31 15:06:10 -05:00
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)}>
2026-05-31 15:06:10 -05:00
<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',
2026-05-31 15:06:10 -05:00
)}
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')}>
2026-05-31 15:06:10 -05:00
{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>
);
}