import React, { useState } from 'react'; import { ChevronDown, History } from 'lucide-react'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; import { cn } from '@/lib/utils'; function fmt(v) { return (Number(v) || 0).toLocaleString(undefined, { style: 'currency', currency: 'USD', maximumFractionDigits: 0, }); } function fmtFull(v) { return (Number(v) || 0).toLocaleString(undefined, { style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 2, }); } function dateRange(plan) { const start = plan.started_at ? new Date(plan.started_at).toLocaleDateString(undefined, { month: 'short', year: 'numeric' }) : '—'; const end = plan.completed_at || plan.paused_at ? new Date(plan.completed_at || plan.paused_at).toLocaleDateString(undefined, { month: 'short', year: 'numeric' }) : plan.status === 'abandoned' ? 'abandoned' : 'present'; return `${start} – ${end}`; } function StatusBadge({ status }) { const map = { active: 'bg-emerald-500/12 text-emerald-600 dark:text-emerald-400', paused: 'bg-amber-500/12 text-amber-600 dark:text-amber-400', completed: 'bg-indigo-500/12 text-indigo-600 dark:text-indigo-400', abandoned: 'bg-rose-500/12 text-rose-600 dark:text-rose-400', }; const labels = { active: 'Active', paused: 'Paused', completed: 'Completed', abandoned: 'Abandoned' }; return ( {labels[status] ?? status} ); } function MethodBadge({ method }) { const map = { snowball: 'Snowball', avalanche: 'Avalanche', custom: 'Custom' }; return ( {map[method] ?? method} ); } // ─── Expanded plan detail ───────────────────────────────────────────────────── function PlanDetail({ plan }) { const snapshot = plan.plan_snapshot ?? {}; const debts = snapshot.debts ?? []; return (
{/* Summary stats */}
{snapshot.projected_months && (

Projected payoff

{snapshot.projected_payoff_date ?? '—'}

)} {snapshot.interest_saved > 0 && (

Interest saved

{fmt(snapshot.interest_saved)}

)} {snapshot.minimum_only_months && (

Minimum-only months

{snapshot.minimum_only_months}

)} {plan.extra_payment > 0 && (

Extra/mo

{fmtFull(plan.extra_payment)}

)}
{/* Per-debt snapshot table */} {debts.length > 0 && (

Debt snapshot at start of plan

{debts.map(d => { const current = plan.current_debts?.find(c => c.bill_id === d.bill_id); const curBal = current?.current_balance; const isPaidOff = curBal !== null && curBal !== undefined && curBal <= 0; return ( ); })}
Debt Starting balance Projected payoff Projected interest Current balance
{d.name} {fmtFull(d.starting_balance)} {d.projected_payoff_date ?? '—'} {d.projected_total_interest != null ? fmtFull(d.projected_total_interest) : '—'} {isPaidOff ? ( Paid off ✓ ) : curBal != null ? ( fmtFull(curBal) ) : ( removed )}
)} {plan.notes && (

{plan.notes}

)}
); } // ─── Single plan row ────────────────────────────────────────────────────────── function PlanRow({ plan }) { const [expanded, setExpanded] = useState(false); const snapshot = plan.plan_snapshot ?? {}; const debtCount = (snapshot.debts ?? []).length; return (
); } // ─── PlanHistoryPanel ───────────────────────────────────────────────────────── export default function PlanHistoryPanel({ plans = [] }) { const [open, setOpen] = useState(false); const historical = plans.filter(p => !['active', 'paused'].includes(p.status)); if (historical.length === 0) return null; return (
{historical.map(plan => ( ))}
); }