import * as React from "react"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { formatCurrency } from "@/lib/format-currency"; export type ExpenseCategoryData = { label: string; color: string; monthlyAmounts: number[]; }; export type ApplicantExpensesSectionProps = { applicantName: string; /** Three states: loading, access granted, access not granted. */ state: "loading" | "connected" | "pending-access"; /** Last 12 month labels (e.g. "Jan", "Feb" …). Required when state = "connected". */ monthLabels?: string[]; /** Per-category breakdown. Required when state = "connected". */ categories?: ExpenseCategoryData[]; /** Total spend over the loaded period. */ totalAmount?: number; onConnectMore?: () => void; onAddManually?: () => void; onSendRequest?: () => void; className?: string; }; export function ApplicantExpensesSection({ applicantName, state, monthLabels = [], categories = [], totalAmount = 0, onConnectMore, onAddManually, onSendRequest, className, }: ApplicantExpensesSectionProps) { return (

{applicantName}'s Expenses

{state === "loading" && } {state === "connected" && ( )} {state === "pending-access" && ( )}
); } // ─── Sub-states ─────────────────────────────────────────────────────────────── function LoadingState() { return (
Loading banking data…
); } function ConnectedState({ monthLabels, categories, totalAmount, onConnectMore, onAddManually, }: { monthLabels: string[]; categories: ExpenseCategoryData[]; totalAmount: number; onConnectMore?: () => void; onAddManually?: () => void; }) { const maxValue = Math.max( ...monthLabels.map((_, mi) => categories.reduce((sum, cat) => sum + (cat.monthlyAmounts[mi] ?? 0), 0), ), 1, ); return (
{formatCurrency(totalAmount)} Total latest 12 months
{onAddManually && ( )}
{/* Mini stacked bar chart */} {monthLabels.length > 0 && categories.length > 0 && (
{monthLabels.map((month, mi) => { const colTotal = categories.reduce( (sum, cat) => sum + (cat.monthlyAmounts[mi] ?? 0), 0, ); const heightPct = (colTotal / maxValue) * 100; return (
{categories.map((cat) => { const segPct = colTotal > 0 ? ((cat.monthlyAmounts[mi] ?? 0) / colTotal) * 100 : 0; return (
); })}
{month}
); })}
)} {/* Legend */} {categories.length > 0 && (
{categories.map((cat) => (
{cat.label}
))}
)}
); } function PendingAccessState({ applicantName, onSendRequest, }: { applicantName: string; onSendRequest?: () => void; }) { return (

Requires access to banking data

Send {applicantName} an invitation to connect their bank accounts.

); } // ─── Icons ──────────────────────────────────────────────────────────────────── function SpinnerIcon({ className }: { className?: string }) { return ( ); } function LockIcon({ className }: { className?: string }) { return ( ); }