import { Link, useNavigate } from "@tanstack/react-router"; import { ChevronRight } from "lucide-react"; import type { Invoice } from "@rubis/shared"; import { StatusBadge } from "@/components/ui/StatusBadge"; import { formatEuros, formatDate, formatDueDelta, isOverdue } from "@/lib/format"; import { cn } from "@/lib/utils"; /** Forme enrichie utilisée par la liste : invoice + nom client + nom plan. */ export type InvoiceListItem = Invoice & { clientName: string; planName: string | null; /** Label de statut serveur, ex: "Relance J+3 envoyée". Override visuel. */ statusLabel?: string; }; type InvoiceTableProps = { invoices: InvoiceListItem[]; className?: string; }; /** * Table desktop des factures. * * Décisions visuelles : * - Échéance dépassée en bold (cf. wireframe 2.4) * - **Ligne entière cliquable** via onClick + role="link" + onKeyDown * (le chevron de droite reste un vrai pour le right-click "ouvrir * dans un nouvel onglet" + middle-click) * - Statut dans une chip sémantique (StatusBadge) * - Pas de checkbox actions-en-lot en V1 (à venir avec le backend) */ export function InvoiceTable({ invoices, className }: InvoiceTableProps) { const navigate = useNavigate(); const goToInvoice = (id: string): void => { void navigate({ to: "/factures/$id", params: { id } }); }; return (
| Client | N° facture | Montant | Échéance | Statut | Plan | |
|---|---|---|---|---|---|---|
| {invoice.clientName} | {invoice.numero} | {formatEuros(invoice.amountTtcCents)} | {formatDate(invoice.dueDate)} {formatDueDelta(invoice.dueDate)} |
|
{invoice.planName ?? — aucun} | {/* Chevron explicite — vrai pour le right-click / middle-click "ouvrir dans nouvel onglet". On stoppe la propagation pour ne pas double-naviguer via le row click. */} e.stopPropagation()} className="inline-flex size-7 items-center justify-center rounded-default text-ink-3 hover:bg-cream hover:text-rubis" aria-label={`Voir la facture ${invoice.numero}`} > |