"use client"; import { useState, useMemo, useEffect } 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 { Input } from "@/components/ui/input"; import { ChevronLeft, ChevronRight, Search, X } from "lucide-react"; import { formatDate } from "@/lib/utils"; import { LibreChatUser, LibreChatBalance } from "@/lib/types"; // Couleurs prédéfinies pour les référents const REFERENT_COLORS: Record = { "Emmanuel WATHELE": "#3B82F6", // Bleu "IHECS": "#10B981", // Vert "Patrice De La Broise": "#F59E0B", // Orange }; export function UsersTable() { const [page, setPage] = useState(1); const [searchInput, setSearchInput] = useState(""); // Ce que l'utilisateur tape const [activeSearch, setActiveSearch] = useState(""); // Ce qui est réellement recherché const [activeReferent, setActiveReferent] = useState(undefined); const limit = 20; // Réinitialiser la page à 1 quand une nouvelle recherche ou filtre est lancé useEffect(() => { setPage(1); }, [activeSearch, activeReferent]); const { data: users = [], total = 0, loading: usersLoading, } = useCollection("users", { page, limit, search: activeSearch, referent: activeReferent, }); const handleReferentClick = (referent: string) => { if (activeReferent === referent) { setActiveReferent(undefined); // Toggle off } else { setActiveReferent(referent); } }; const clearReferentFilter = () => { setActiveReferent(undefined); }; // Fonction pour lancer la recherche const handleSearch = () => { setActiveSearch(searchInput); }; // Gérer la touche Entrée const handleKeyPress = (e: React.KeyboardEvent) => { if (e.key === "Enter") { handleSearch(); } }; // Charger tous les balances pour associer les crédits const { data: balances = [] } = useCollection("balances", { limit: 1000, }); // Créer une map des crédits par utilisateur const creditsMap = useMemo(() => { const map = new Map(); balances.forEach((balance) => { map.set(balance.user, balance.tokenCredits || 0); }); return map; }, [balances]); const totalPages = Math.ceil(total / limit); const handlePrevPage = () => { setPage((prev) => Math.max(1, prev - 1)); }; const handleNextPage = () => { setPage((prev) => Math.min(totalPages, prev + 1)); }; if (usersLoading) { return ( Liste des utilisateurs
{Array.from({ length: 5 }).map((_, i) => (
))}
); } return (
Liste des utilisateurs ({total})
{activeReferent && ( {activeReferent} )}
setSearchInput(e.target.value)} onKeyPress={handleKeyPress} className="pl-10" />
ID Nom Email Référent Rôle Crédits Créé le {users.length > 0 ? ( users.map((user) => { const userCredits = creditsMap.get(user._id) || 0; const referentColor = user.referent ? (REFERENT_COLORS[user.referent] || "#6B7280") : null; return ( {user._id.slice(-8)}
{referentColor && (
)} {user.name}
{user.email} {user.referent ? ( ) : ( - )} {user.role} {userCredits.toLocaleString()} crédits {formatDate(user.createdAt)} ); }) ) : ( {activeSearch ? `Aucun utilisateur trouvé pour "${activeSearch}"` : "Aucun utilisateur trouvé"} )}
{/* Pagination */}
{activeSearch ? ( {total} résultat(s) pour "{activeSearch}" - Page {page} sur {totalPages} ) : ( Page {page} sur {totalPages} ({total} utilisateurs au total) )}
); }