'use client'; import { useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { api } from '@/lib/api'; import { Card, CardContent } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Skeleton } from '@/components/ui/skeleton'; import { Search, ChevronRight } from 'lucide-react'; import { format } from 'date-fns'; interface Invoice { id: string; invoiceNumber: string; dueDate: string; subtotal: string; lateFee: string; total: string; amountPaid: string; balance: string; status: string; client?: { firstName: string; lastName: string; accountNumber: string }; } interface InvoicesResponse { data: Invoice[]; total: number; } const statusColors: Record = { SENT: 'bg-blue-100 text-blue-700', PARTIAL: 'bg-yellow-100 text-yellow-700', PAID: 'bg-green-100 text-green-700', OVERDUE: 'bg-red-100 text-red-700', DRAFT: 'bg-gray-100 text-gray-500', VOID: 'bg-gray-100 text-gray-400', }; const peso = (v: string | number) => '₱' + Number(v ?? 0).toLocaleString('en-PH', { minimumFractionDigits: 2 }); export default function InvoicesPage() { const [search, setSearch] = useState(''); const [statusFilter, setStatusFilter] = useState(''); const [page, setPage] = useState(1); const { data, isLoading } = useQuery({ queryKey: ['invoices', search, statusFilter, page], queryFn: async () => { const params = new URLSearchParams({ page: String(page), limit: '20' }); if (search) params.set('search', search); if (statusFilter) params.set('status', statusFilter); const res = await api.get(`/api/v1/invoices?${params}`); return res.data; }, staleTime: 30_000, }); const invoices = data?.data ?? []; const total = data?.total ?? 0; return (

Invoices

{total} invoices

{ setSearch(e.target.value); setPage(1); }} />
{isLoading ? Array.from({ length: 8 }).map((_, i) => ( {Array.from({ length: 7 }).map((_, j) => ( ))} )) : invoices.map((inv) => ( ))}
Invoice # Client Due Date Total Balance Status
{inv.invoiceNumber} {inv.client ? `${inv.client.firstName} ${inv.client.lastName}` : '—'}
{inv.client?.accountNumber}
{inv.dueDate ? format(new Date(inv.dueDate), 'MMM d, yyyy') : '—'} {peso(inv.total)} {Number(inv.balance) > 0 ? ( {peso(inv.balance)} ) : ( Paid )} {inv.status}
{!isLoading && invoices.length === 0 && (
No invoices found
)} {total > 20 && (

Showing {(page - 1) * 20 + 1}–{Math.min(page * 20, total)} of {total}

)}
); }