true message

This commit is contained in:
Manus
2026-06-15 11:54:58 -04:00
parent 2fde4f92a6
commit 295965fa57
2 changed files with 200 additions and 140 deletions

View File

@@ -32,7 +32,7 @@ import {
TableRow,
} from "@/components/ui/table";
import { trpc } from "@/lib/trpc";
import { Search, FileText, Download, FileSpreadsheet, Trash2, Edit, Trash, CheckCircle, CheckCircle2, ShieldCheck, RefreshCw, FolderDown, ChevronDown, ChevronRight, ChevronsUpDown, CalendarDays } from "lucide-react";
import { Search, FileText, Download, FileSpreadsheet, Trash2, Edit, Trash, CheckCircle, CheckCircle2, ShieldCheck, RefreshCw, FolderDown, ChevronDown, ChevronRight, ChevronsUpDown, CalendarDays, ArrowUpDown, ArrowUp, ArrowDown } from "lucide-react";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
// Helper : télécharge un ZIP de plusieurs PDFs annotés BAP
@@ -129,6 +129,9 @@ export default function InvoicesBAP() {
const currentYear = new Date().getFullYear();
const [selectedYear, setSelectedYear] = useState<string>(String(currentYear));
const [selectedMonth, setSelectedMonth] = useState<string>("all"); // "all" ou "01".."12"
// Tri
const [sortField, setSortField] = useState<"invoiceDate" | "createdAt">("createdAt");
const [sortDir, setSortDir] = useState<"asc" | "desc">("desc");
const toggleRow = (id: number) => {
setExpandedIds(prev => {
@@ -516,8 +519,34 @@ export default function InvoicesBAP() {
return invoice && isEligibleForExport(invoice);
});
const allEligibleSelected = (filteredInvoices?.length || 0) > 0 &&
(filteredInvoices || []).every(inv => selectedIds.includes(inv.id));
const handleSort = (field: "invoiceDate" | "createdAt") => {
if (sortField === field) {
setSortDir(d => d === "asc" ? "desc" : "asc");
} else {
setSortField(field);
setSortDir("desc");
}
};
const SortIcon = ({ field }: { field: "invoiceDate" | "createdAt" }) => {
if (sortField !== field) return <ArrowUpDown className="w-3 h-3 ml-1 opacity-40" />;
return sortDir === "asc" ? <ArrowUp className="w-3 h-3 ml-1" /> : <ArrowDown className="w-3 h-3 ml-1" />;
};
const sortedInvoices = [...(filteredInvoices || [])].sort((a, b) => {
let aVal: number, bVal: number;
if (sortField === "invoiceDate") {
aVal = a.invoiceDate ? new Date(a.invoiceDate).getTime() : 0;
bVal = b.invoiceDate ? new Date(b.invoiceDate).getTime() : 0;
} else {
aVal = a.createdAt ? new Date(a.createdAt as unknown as string).getTime() : 0;
bVal = b.createdAt ? new Date(b.createdAt as unknown as string).getTime() : 0;
}
return sortDir === "asc" ? aVal - bVal : bVal - aVal;
});
const allEligibleSelected = (sortedInvoices.length || 0) > 0 &&
sortedInvoices.every(inv => selectedIds.includes(inv.id));
return (
<DashboardLayout>
@@ -702,6 +731,25 @@ export default function InvoicesBAP() {
)}
</div>
{/* Tri */}
<div className="flex gap-2 items-center mb-3">
<span className="text-sm text-gray-500">Trier par :</span>
<Button
variant={sortField === "createdAt" ? "default" : "outline"}
size="sm"
onClick={() => handleSort("createdAt")}
>
Date réception <SortIcon field="createdAt" />
</Button>
<Button
variant={sortField === "invoiceDate" ? "default" : "outline"}
size="sm"
onClick={() => handleSort("invoiceDate")}
>
Date facture <SortIcon field="invoiceDate" />
</Button>
</div>
{/* Status Filters */}
<div className="flex flex-wrap gap-2 mb-4">
<Button
@@ -764,7 +812,7 @@ export default function InvoicesBAP() {
{/* Table */}
{isLoading ? (
<div className="text-center py-8 text-gray-500">Chargement...</div>
) : filteredInvoices && filteredInvoices.length > 0 ? (
) : sortedInvoices.length > 0 ? (
<div className="border rounded-lg overflow-hidden">
<Table>
<TableHeader>
@@ -788,7 +836,18 @@ export default function InvoicesBAP() {
</TableHead>
<TableHead>Fournisseur</TableHead>
<TableHead>N° Facture</TableHead>
<TableHead>Date</TableHead>
<TableHead
className="cursor-pointer select-none"
onClick={() => handleSort("invoiceDate")}
>
<span className="flex items-center">Date facture <SortIcon field="invoiceDate" /></span>
</TableHead>
<TableHead
className="cursor-pointer select-none"
onClick={() => handleSort("createdAt")}
>
<span className="flex items-center">Date réception <SortIcon field="createdAt" /></span>
</TableHead>
<TableHead>Montant</TableHead>
<TableHead>Score</TableHead>
<TableHead>Statut</TableHead>
@@ -796,7 +855,7 @@ export default function InvoicesBAP() {
</TableRow>
</TableHeader>
<TableBody>
{filteredInvoices.map((invoice) => {
{sortedInvoices.map((invoice) => {
const isExpanded = expandedIds.has(invoice.id);
return (
<React.Fragment key={invoice.id}>
@@ -831,6 +890,11 @@ export default function InvoicesBAP() {
? new Date(invoice.invoiceDate).toLocaleDateString("fr-FR")
: "-"}
</TableCell>
<TableCell className="text-xs text-gray-500">
{invoice.createdAt
? new Date(invoice.createdAt as unknown as string).toLocaleDateString("fr-FR")
: "-"}
</TableCell>
<TableCell>
{invoice.totalAmount
? `${parseFloat(invoice.totalAmount as string).toFixed(2)}`