import { useState, useEffect } from 'react'; import Layout from '../../components/Layout'; import LoadingButton from '../../components/LoadingButton'; import SortTh from '../../components/SortTh'; import { supabase } from '../../lib/supabase'; import { generateInvoicePDF } from '../../lib/invoice'; import { useAuth } from '../../context/AuthContext'; import { useSortable } from '../../hooks/useSortable'; const statusColor = { draft: 'not_started', sent: 'in_progress', paid: 'client_approved' }; export default function MyInvoices() { const { currentUser } = useAuth(); const companies = (currentUser?.companies?.length ? currentUser.companies : (currentUser?.company ? [currentUser.company] : [])).slice().sort((a, b) => a.name.localeCompare(b.name)); const [activeCompanyId, setActiveCompanyId] = useState(companies[0]?.id || null); const [invoices, setInvoices] = useState([]); const [loading, setLoading] = useState(true); const [generatingInvoiceId, setGeneratingInvoiceId] = useState(''); const { sortKey, sortDir, toggle, sort } = useSortable('invoice_date'); useEffect(() => { async function load() { const { data } = await supabase .from('invoices') .select('*, company:companies(name), items:invoice_items(*)') .order('created_at', { ascending: false }); setInvoices((data || []).filter(inv => inv.status !== 'draft')); setLoading(false); } load(); }, []); const handleDownload = async (invoice) => { if (generatingInvoiceId) return; setGeneratingInvoiceId(invoice.id); try { await generateInvoicePDF(invoice, invoice.company, invoice.items || []); } finally { setGeneratingInvoiceId(''); } }; const visible = companies.length > 1 && activeCompanyId ? invoices.filter(inv => inv.company_id === activeCompanyId) : invoices; const outstanding = visible.filter(i => i.status === 'sent').reduce((s, i) => s + Number(i.total), 0); const paid = visible.filter(i => i.status === 'paid').reduce((s, i) => s + Number(i.total), 0); const overdueCount = visible.filter(inv => inv.status !== 'paid' && new Date(inv.due_date) < new Date()).length; const sorted = sort(visible, (inv, key) => { if (key === 'invoice_date' || key === 'due_date') return new Date(inv[key] || 0).getTime(); if (key === 'total') return Number(inv.total || 0); return inv[key] || ''; }); const th = { sortKey, sortDir, onSort: toggle }; return (
Invoices
{visible.length} invoice{visible.length !== 1 ? 's' : ''}
${outstanding.toFixed(2)}
Outstanding
${paid.toFixed(2)}
Paid
0 ? 'var(--danger)' : undefined }}>{overdueCount}
Overdue
{companies.length > 1 && (
)} {loading ? (

Loading...

) : visible.length === 0 ? (

No invoices yet

Your invoices will appear here once they are sent.

) : (
Invoice #IssuedDueStatusTotal {sorted.map(inv => { const isOverdue = inv.status !== 'paid' && new Date(inv.due_date) < new Date(); return ( ); })}
{inv.invoice_number} {new Date(inv.invoice_date).toLocaleDateString()} {inv.due_date ? new Date(inv.due_date).toLocaleDateString() : '—'} {isOverdue && Overdue} {inv.status} ${Number(inv.total).toFixed(2)} handleDownload(inv)} > Download PDF
)}
); }