import React, { useMemo } from 'react'; import { AlertCircle, CalendarClock, FileText, Lock, Loader2 } from 'lucide-react'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { toast } from 'sonner'; import { SpotlightCard } from '../../../components/SpotlightCard'; import { formatAmount } from '../data/invoices'; import { stripeConfig } from '../config/stripeConfig'; import { startCheckout } from '../services/checkoutService'; /** * Outstanding tab — summarizes everything the customer still owes: a headline * total-due figure plus the list of unpaid invoices, with overdue ones flagged. * Reads the same invoice/paid data as the "Make a Payment" tab so the two views * never disagree. */ const OutstandingPanel = ({ invoices, paidIds = [], customerEmail }) => { const navigate = useNavigate(); const [redirectingId, setRedirectingId] = useState(null); const due = useMemo( () => invoices .filter((i) => !(i.status === 'paid' || paidIds.includes(i.id))) .sort((a, b) => new Date(a.dueDate) - new Date(b.dueDate)), [invoices, paidIds] ); // Total owed, assuming all unpaid invoices share a currency (they do here). const totalCents = due.reduce((sum, i) => sum + (i.amount || 0), 0); const currency = due[0]?.currency || 'usd'; // Midnight today, so an invoice due today is not counted as overdue. const today = new Date(); today.setHours(0, 0, 0, 0); const isOverdue = (inv) => new Date(inv.dueDate) < today; const overdueCount = due.filter(isOverdue).length; const handlePay = async (invoice) => { if (redirectingId) return; setRedirectingId(invoice.id); if (!stripeConfig.isConfigured) { navigate(`/payments/demo-checkout?invoice=${encodeURIComponent(invoice.id)}`); return; } try { await startCheckout({ invoiceId: invoice.id, customerEmail }); } catch (err) { toast.error('Unable to start checkout', { description: err.message }); setRedirectingId(null); } }; if (due.length === 0) { return (
Total Outstanding
{formatAmount(totalCents, currency, stripeConfig.locale)}
Across {due.length} invoice{due.length === 1 ? '' : 's'} {overdueCount > 0 && ( {' '}· {overdueCount} overdue )}
{inv.description}
{overdue &&