import React, { useState } from 'react'; import { AlertCircle, ChevronDown, BellOff, SkipForward, CreditCard } from 'lucide-react'; import { toast } from 'sonner'; import { api } from '@/api.js'; import { cn, fmt } from '@/lib/utils'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '@/components/ui/collapsible'; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, } from '@/components/ui/dropdown-menu'; function snoozeUntil(days) { const d = new Date(); d.setDate(d.getDate() + days); return d.toISOString().slice(0, 10); } function daysOverdueLabel(dueDate) { if (!dueDate) return 'overdue'; const today = new Date(); today.setHours(0, 0, 0, 0); const due = new Date(`${dueDate}T00:00:00`); const days = Math.floor((today - due) / 86_400_000); if (days <= 0) return 'due today'; return `${days} ${days === 1 ? 'day' : 'days'} overdue`; } function OverdueRow({ row, year, month, onPayNow, onRefresh }) { const [loading, setLoading] = useState(false); const threshold = row.actual_amount ?? row.expected_amount; async function handleSkip() { setLoading(true); try { await api.saveBillMonthlyState(row.id, { year, month, is_skipped: true, actual_amount: row.actual_amount, notes: row.monthly_notes, }); onRefresh(); } catch { toast.error('Failed to skip bill'); } finally { setLoading(false); } } async function handleSnooze(days) { setLoading(true); try { await api.snoozeOverdue(row.id, { year, month, snoozed_until: snoozeUntil(days), actual_amount: row.actual_amount, notes: row.monthly_notes, is_skipped: false, }); toast.success(`Snoozed for ${days} ${days === 1 ? 'day' : 'days'}`); onRefresh(); } catch { toast.error('Failed to snooze bill'); } finally { setLoading(false); } } return (
All overdue bills are snoozed.
)}