"use client"; import { useEffect, useRef, useState, useCallback } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Checkbox } from "@/components/ui/checkbox"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { CategoryCombobox } from "@/components/ui/category-combobox"; import { CheckCircle2, Circle, MoreVertical, ArrowUpDown, Wand2, } from "lucide-react"; import { DropdownMenuSeparator } from "@/components/ui/dropdown-menu"; import { cn } from "@/lib/utils"; import type { Transaction, Account, Category } from "@/lib/types"; type SortField = "date" | "amount" | "description"; type SortOrder = "asc" | "desc"; interface TransactionTableProps { transactions: Transaction[]; accounts: Account[]; categories: Category[]; selectedTransactions: Set; sortField: SortField; sortOrder: SortOrder; onSortChange: (field: SortField) => void; onToggleSelectAll: () => void; onToggleSelectTransaction: (id: string) => void; onToggleReconciled: (id: string) => void; onMarkReconciled: (id: string) => void; onSetCategory: (transactionId: string, categoryId: string | null) => void; onCreateRule: (transaction: Transaction) => void; formatCurrency: (amount: number) => string; formatDate: (dateStr: string) => string; } export function TransactionTable({ transactions, accounts, categories, selectedTransactions, sortField, sortOrder, onSortChange, onToggleSelectAll, onToggleSelectTransaction, onToggleReconciled, onMarkReconciled, onSetCategory, onCreateRule, formatCurrency, formatDate, }: TransactionTableProps) { const [focusedIndex, setFocusedIndex] = useState(null); const rowRefs = useRef<(HTMLTableRowElement | null)[]>([]); const handleRowClick = useCallback( (index: number, transactionId: string) => { setFocusedIndex(index); onMarkReconciled(transactionId); }, [onMarkReconciled] ); const handleKeyDown = useCallback( (e: KeyboardEvent) => { if (focusedIndex === null || transactions.length === 0) return; if (e.key === "ArrowDown") { e.preventDefault(); const newIndex = Math.min(focusedIndex + 1, transactions.length - 1); if (newIndex !== focusedIndex) { setFocusedIndex(newIndex); onMarkReconciled(transactions[newIndex].id); rowRefs.current[newIndex]?.scrollIntoView({ behavior: "smooth", block: "nearest", }); } } else if (e.key === "ArrowUp") { e.preventDefault(); const newIndex = Math.max(focusedIndex - 1, 0); if (newIndex !== focusedIndex) { setFocusedIndex(newIndex); onMarkReconciled(transactions[newIndex].id); rowRefs.current[newIndex]?.scrollIntoView({ behavior: "smooth", block: "nearest", }); } } }, [focusedIndex, transactions, onMarkReconciled] ); useEffect(() => { document.addEventListener("keydown", handleKeyDown); return () => document.removeEventListener("keydown", handleKeyDown); }, [handleKeyDown]); // Reset focused index when transactions change useEffect(() => { setFocusedIndex(null); }, [transactions.length]); const getAccount = (accountId: string) => { return accounts.find((a) => a.id === accountId); }; return ( {transactions.length === 0 ? (

Aucune transaction trouvée

) : (
{transactions.map((transaction, index) => { const account = getAccount(transaction.accountId); const isFocused = focusedIndex === index; return ( { rowRefs.current[index] = el; }} onClick={() => handleRowClick(index, transaction.id)} className={cn( "border-b border-border last:border-0 hover:bg-muted/50 cursor-pointer", transaction.isReconciled && "bg-emerald-500/5", isFocused && "bg-primary/10 ring-1 ring-primary/30" )} > ); })}
0 } onCheckedChange={onToggleSelectAll} /> Compte Catégorie Pointé
onToggleSelectTransaction(transaction.id) } /> {formatDate(transaction.date)}

{transaction.description}

{transaction.memo && (

{transaction.memo}

)}
{account?.name || "-"} e.stopPropagation()}> onSetCategory(transaction.id, categoryId) } showBadge align="start" /> = 0 ? "text-emerald-600" : "text-red-600" )} > {transaction.amount >= 0 ? "+" : ""} {formatCurrency(transaction.amount)} e.stopPropagation()}> e.stopPropagation()}> { e.stopPropagation(); onToggleReconciled(transaction.id); }} > {transaction.isReconciled ? ( <> Dépointer ) : ( <> Pointer )} { e.stopPropagation(); onCreateRule(transaction); }} > Créer une règle
)}
); }