/** * Account Billing Page * Consolidated billing dashboard with invoices, payments, and credit balance */ import { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import { CreditCard, Download, AlertCircle, Loader2, FileText, CheckCircle, XCircle, Clock, DollarSign, TrendingUp, } from 'lucide-react'; import { getInvoices, getPayments, getCreditBalance, downloadInvoicePDF, type Invoice, type Payment, type CreditBalance, } from '../../services/billing.api'; import { Card } from '../../components/ui/card'; import BillingRecentTransactions from '../../components/billing/BillingRecentTransactions'; type TabType = 'overview' | 'invoices' | 'payments'; export default function AccountBillingPage() { const [activeTab, setActiveTab] = useState('overview'); const [creditBalance, setCreditBalance] = useState(null); const [invoices, setInvoices] = useState([]); const [payments, setPayments] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); useEffect(() => { loadData(); }, []); const loadData = async () => { try { setLoading(true); const [balanceRes, invoicesRes, paymentsRes] = await Promise.all([ getCreditBalance(), getInvoices(), getPayments(), ]); setCreditBalance(balanceRes); setInvoices(invoicesRes.results); setPayments(paymentsRes.results); } catch (err: any) { setError(err.message || 'Failed to load billing data'); console.error('Billing data load error:', err); } finally { setLoading(false); } }; const handleDownloadInvoice = async (invoiceId: number, invoiceNumber: string) => { try { const blob = await downloadInvoicePDF(invoiceId); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `invoice-${invoiceNumber}.pdf`; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); } catch (err) { alert('Failed to download invoice'); } }; const getStatusBadge = (status: string) => { const styles: Record = { paid: { bg: 'bg-green-100', text: 'text-green-800', icon: CheckCircle }, pending: { bg: 'bg-yellow-100', text: 'text-yellow-800', icon: Clock }, failed: { bg: 'bg-red-100', text: 'text-red-800', icon: XCircle }, void: { bg: 'bg-gray-100', text: 'text-gray-800', icon: XCircle }, completed: { bg: 'bg-green-100', text: 'text-green-800', icon: CheckCircle }, pending_approval: { bg: 'bg-blue-100', text: 'text-blue-800', icon: Clock }, }; const style = styles[status] || styles.pending; const Icon = style.icon; return ( {status.replace('_', ' ').toUpperCase()} ); }; if (loading) { return (
); } return (

Plans & Billing

{/* Recent Transactions (moved from Credits & Billing overview) */}

Manage your subscription, credits, and billing

Purchase Credits
{error && (

{error}

)} {/* Tabs */}
{/* Overview Tab */} {activeTab === 'overview' && creditBalance && (
{/* Stats Cards */}

Current Balance

{creditBalance?.credits?.toLocaleString() || '0'}

Available credits

Monthly Allocation

{creditBalance?.plan_credits_per_month?.toLocaleString() || '0'}

Credits per month

Used This Month

{creditBalance?.credits_used_this_month?.toLocaleString() || '0'}

Credits consumed

{/* Quick Actions */}

Quick Actions

Purchase Credits View Usage Analytics

Account Summary

Remaining Credits: {creditBalance?.credits_remaining?.toLocaleString() || '0'}
Total Invoices: {invoices.length}
Paid Invoices: {invoices.filter(inv => inv.status === 'paid').length}
)} {/* Invoices Tab */} {activeTab === 'invoices' && (
{invoices.length === 0 ? ( ) : ( invoices.map((invoice) => ( )) )}
Invoice Date Amount Status Actions
No invoices yet
{invoice.invoice_number}
{invoice.line_items[0] && (
{invoice.line_items[0].description}
)}
{new Date(invoice.created_at).toLocaleDateString()} ${invoice.total_amount} {getStatusBadge(invoice.status)}
)} {/* Payments Tab */} {activeTab === 'payments' && (
{payments.length === 0 ? ( ) : ( payments.map((payment) => ( )) )}
Date Method Reference Amount Status
No payments yet
{new Date(payment.created_at).toLocaleDateString()}
{payment.payment_method.replace('_', ' ')}
{payment.transaction_reference || '-'} ${payment.amount} {getStatusBadge(payment.status)}
)}
); }