"use client"; import { useState, useMemo } from "react"; import { useCollection } from "@/hooks/useCollection"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { ChevronLeft, ChevronRight } from "lucide-react"; import { formatDate, formatCurrency } from "@/lib/utils"; import { LibreChatTransaction, LibreChatUser } from "@/lib/types"; // Interface étendue pour les transactions avec description optionnelle interface TransactionWithDescription extends LibreChatTransaction { description?: string; } export function TransactionsTable() { const { data: transactions, loading } = useCollection("transactions"); const { data: users } = useCollection("users"); const [currentPage, setCurrentPage] = useState(1); const itemsPerPage = 10; // Créer une map pour les lookups rapides des utilisateurs const usersMap = useMemo(() => { if (!users) return new Map(); return new Map(users.map((user) => [user._id, user])); }, [users]); const totalPages = Math.ceil((transactions?.length || 0) / itemsPerPage); const handlePrevPage = () => { setCurrentPage((prev) => Math.max(1, prev - 1)); }; const handleNextPage = () => { setCurrentPage((prev) => Math.min(totalPages, prev + 1)); }; // Fonction pour obtenir le nom d'utilisateur const getUserName = (userId: string): string => { if (!userId || userId === "undefined") return "Utilisateur inconnu"; const user = usersMap.get(userId); return user?.name || user?.email || `Utilisateur ${userId.slice(-8)}`; }; // Fonction pour formater le montant en euros const formatAmount = (rawAmount: number): string => { // Convertir les tokens en euros (exemple: 1000 tokens = 1 euro) const euros = rawAmount / 1000; return formatCurrency(euros); }; // Fonction pour obtenir la description const getDescription = (transaction: LibreChatTransaction): string => { const transactionWithDesc = transaction as TransactionWithDescription; if (transactionWithDesc.description && typeof transactionWithDesc.description === 'string' && transactionWithDesc.description !== "undefined") { return transactionWithDesc.description; } // Générer une description basée sur le type et le montant const amount = Math.abs(Number(transaction.rawAmount) || 0); if (amount > 0) { return `Consommation de ${amount.toLocaleString()} tokens`; } return "Transaction sans description"; }; if (loading) { return ( Transactions
{Array.from({ length: 5 }).map((_, i) => (
))}
); } return ( Transactions récentes ({transactions?.length || 0})
ID Utilisateur Type Montant Tokens Description Date {transactions ?.slice( (currentPage - 1) * itemsPerPage, currentPage * itemsPerPage ) .map((transaction) => { const userName = getUserName(transaction.user); const description = getDescription(transaction); const tokenAmount = Math.abs( Number(transaction.rawAmount) || 0 ); const isCredit = Number(transaction.rawAmount) > 0; return ( {transaction._id.slice(-8)}
{transaction.user?.slice(-8) || "N/A"}
{userName}
{isCredit ? "Crédit" : "Débit"} {formatAmount(transaction.rawAmount)} {tokenAmount > 0 && ( {tokenAmount.toLocaleString()} tokens )} {description} {formatDate(new Date(transaction.createdAt))}
); })}
{/* Pagination */}
Page {currentPage} sur {totalPages} ({transactions?.length || 0}{" "} éléments au total)
); }