'use client'; import { useState } from 'react'; import { useParams, useRouter } from 'next/navigation'; import { Plus, Trash2 } from 'lucide-react'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Button } from '@/components/ui/button'; import { DataTable } from '@/components/shared/data-table'; import { FilterBar } from '@/components/shared/filter-bar'; import { PageHeader } from '@/components/shared/page-header'; import { EmptyState } from '@/components/shared/empty-state'; import { TableSkeleton } from '@/components/shared/loading-skeleton'; import { PermissionGate } from '@/components/shared/permission-gate'; import { invoiceFilterDefinitions } from '@/components/invoices/invoice-filters'; import { getInvoiceColumns, type InvoiceRow } from '@/components/invoices/invoice-columns'; import { usePaginatedQuery } from '@/hooks/use-paginated-query'; import { useRealtimeInvalidation } from '@/hooks/use-realtime-invalidation'; import { apiFetch } from '@/lib/api/client'; const STATUS_TABS = [ { label: 'All', value: '' }, { label: 'Draft', value: 'draft' }, { label: 'Sent', value: 'sent' }, { label: 'Paid', value: 'paid' }, { label: 'Overdue', value: 'overdue' }, ] as const; export default function InvoicesPage() { const params = useParams<{ portSlug: string }>(); const portSlug = params?.portSlug ?? ''; const router = useRouter(); const queryClient = useQueryClient(); const [deleteTarget, setDeleteTarget] = useState(null); const { data, pagination, isLoading, isFetching, sort, setSort, setPage, setPageSize, filters, setFilter, clearFilters, } = usePaginatedQuery({ queryKey: ['invoices'], endpoint: '/api/v1/invoices', filterDefinitions: invoiceFilterDefinitions, }); const activeStatus = (filters.status as string) ?? ''; useRealtimeInvalidation({ 'invoice:created': [['invoices']], 'invoice:updated': [['invoices']], 'invoice:sent': [['invoices']], 'invoice:paid': [['invoices']], 'invoice:overdue': [['invoices']], }); const deleteMutation = useMutation({ mutationFn: (id: string) => apiFetch(`/api/v1/invoices/${id}`, { method: 'DELETE' }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['invoices'] }); setDeleteTarget(null); }, }); const sendMutation = useMutation({ mutationFn: (id: string) => apiFetch(`/api/v1/invoices/${id}/send`, { method: 'POST' }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['invoices'] }); }, }); const columns = getInvoiceColumns({ portSlug, onSend: (invoice) => sendMutation.mutate(invoice.id), onRecordPayment: (invoice) => router.push(`/${portSlug}/invoices/${invoice.id}?tab=payment`), onDelete: (invoice) => setDeleteTarget(invoice), }); return (
} /> {/* Status quick-filter tabs */}
{STATUS_TABS.map((tab) => ( ))}
f.key !== 'status')} values={filters} onChange={setFilter} onClear={clearFilters} /> {isLoading ? ( ) : ( { setPage(p); setPageSize(ps); }} sort={sort} onSortChange={setSort} isLoading={isFetching && !isLoading} getRowId={(row) => row.id} emptyState={ router.push(`/${portSlug}/invoices/new`), }} /> } /> )} {/* Delete confirmation */} {deleteTarget && (

Delete Invoice?

This will permanently delete invoice{' '} {deleteTarget.invoiceNumber}. This action cannot be undone.

)}
); }