true message
This commit is contained in:
@@ -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)} €`
|
||||
|
||||
Reference in New Issue
Block a user