import { useState } from "react"; import { CreditCard, Download, DollarSign, Package, Zap, Plus, Trash2 } from "lucide-react"; import { INVOICES, SAVED_PAYMENT_METHODS, PREPAID_PACKAGES, Invoice } from "../mockData.js"; interface Props { readOnly: boolean; } const STATUS_STYLES: Record = { paid: "bg-green-100 text-green-700", outstanding: "bg-amber-100 text-amber-700", overdue: "bg-red-100 text-red-700", }; export function BillingPayments({ readOnly }: Props) { const [tab, setTab] = useState<"invoices" | "payment" | "packages">("invoices"); const [autopay, setAutopay] = useState(false); const [showTipModal, setShowTipModal] = useState(false); const [showPaymentModal, setShowPaymentModal] = useState(false); const outstanding = INVOICES.filter(i => i.status === "outstanding"); const totalOutstanding = outstanding.reduce((sum, i) => sum + i.amount, 0); return (
{/* Outstanding Balance Banner */} {totalOutstanding > 0 && (

Outstanding Balance

${totalOutstanding.toFixed(2)}

{outstanding.length} unpaid invoice{outstanding.length > 1 ? "s" : ""}

{!readOnly && (
)}
)} {/* Tabs */}
{([ { id: "invoices" as const, label: "Invoices", icon: DollarSign }, { id: "payment" as const, label: "Payment Methods", icon: CreditCard }, { id: "packages" as const, label: "Packages", icon: Package }, ]).map(({ id, label, icon: Icon }) => ( ))}
{/* Invoices */} {tab === "invoices" && (
{INVOICES.map(inv => ( ))}
Date Items Amount Status
{new Date(inv.date).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })} {inv.items.join(", ")} ${inv.amount.toFixed(2)} {inv.status}
)} {/* Payment Methods */} {tab === "payment" && (
{SAVED_PAYMENT_METHODS.map(pm => (

{pm.type} •••• {pm.last4}

Expires {pm.expiry}

{pm.isDefault && ( Default )} {!readOnly && ( )}
))} {!readOnly && ( )}
{/* Autopay */}

Autopay

Automatically charge after each appointment

{!readOnly ? ( ) : ( {autopay ? "Enabled" : "Disabled"} )}
)} {/* Packages */} {tab === "packages" && (
{PREPAID_PACKAGES.map(pkg => (

{pkg.name}

{pkg.totalCredits - pkg.usedCredits}

remaining of {pkg.totalCredits}

Expires {new Date(pkg.expiresAt).toLocaleDateString()}

))}
)} {/* Tip Modal */} {showTipModal && !readOnly && ( setShowTipModal(false)} /> )} {/* Payment Modal */} {showPaymentModal && !readOnly && ( setShowPaymentModal(false)} /> )}
); } function PaymentModal({ outstanding, totalOutstanding: _totalOutstanding, onClose }: { outstanding: Invoice[]; totalOutstanding: number; onClose: () => void }) { const [selectedInvoices, setSelectedInvoices] = useState>(new Set(outstanding.map(i => i.id))); const [isProcessing, setIsProcessing] = useState(false); const [isComplete, setIsComplete] = useState(false); const toggleInvoice = (id: string) => { const next = new Set(selectedInvoices); if (next.has(id)) { next.delete(id); } else { next.add(id); } setSelectedInvoices(next); }; const handlePay = async () => { setIsProcessing(true); // Simulate payment processing await new Promise(resolve => setTimeout(resolve, 1500)); setIsProcessing(false); setIsComplete(true); }; const selectedTotal = outstanding.filter(i => selectedInvoices.has(i.id)).reduce((sum, i) => sum + i.amount, 0); if (isComplete) { return (

Payment Successful

Your payment of ${selectedTotal.toFixed(2)} has been processed. A receipt has been sent to your email.

); } return (

Pay Outstanding Balance

Select invoices to pay:

{outstanding.map(inv => ( ))}
Total ${selectedTotal.toFixed(2)}
); } function TipModal({ onClose }: { onClose: () => void }) { const [tipPercent, setTipPercent] = useState(20); const [customTip, setCustomTip] = useState(""); const presets = [15, 20, 25]; return (

Add a Tip

{presets.map(pct => ( ))}
{tipPercent === null && ( setCustomTip(e.target.value)} className="w-full border border-stone-300 rounded-lg px-3 py-2 text-sm mb-4" /> )}
); }