"use client"; import { useState, useEffect, useCallback } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Users } from "lucide-react"; import Link from "next/link"; import { useCollection } from "@/hooks/useCollection"; import { LibreChatUser, LibreChatConversation, LibreChatTransaction, LibreChatBalance, } from "@/lib/types"; interface DashboardUser { userId: string; userName: string; conversations: number; tokens: number; credits: number; } // Fonction utilitaire pour valider et convertir les dates const isValidDate = (value: unknown): value is string | number | Date => { if (!value) return false; if (value instanceof Date) return !isNaN(value.getTime()); if (typeof value === 'string' || typeof value === 'number') { const date = new Date(value); return !isNaN(date.getTime()); } return false; }; export function DashboardUsersList() { const [topUsers, setTopUsers] = useState([]); const [isLoading, setIsLoading] = useState(true); const { data: users, loading: usersLoading } = useCollection('users'); const { data: conversations, loading: conversationsLoading } = useCollection('conversations'); const { data: transactions, loading: transactionsLoading } = useCollection('transactions'); const { data: balances, loading: balancesLoading } = useCollection('balances'); const processUsers = useCallback(() => { if (!users?.length || !conversations?.length || !transactions?.length || !balances?.length) { return; } console.log("🔄 Processing users data..."); console.log("Users:", users.length); console.log("Conversations:", conversations.length); console.log("Transactions:", transactions.length); console.log("Balances:", balances.length); const processedUsers: DashboardUser[] = []; users.forEach((user: LibreChatUser) => { // Obtenir les conversations de l'utilisateur const userConversations = conversations.filter( (conv: LibreChatConversation) => conv.user === user._id ); // Obtenir les transactions de l'utilisateur const userTransactions = transactions.filter( (trans: LibreChatTransaction) => trans.user === user._id ); // Calculer les tokens consommés const totalTokens = userTransactions.reduce( (sum: number, trans: LibreChatTransaction) => sum + (trans.rawAmount || 0), 0 ); // Obtenir les balances de l'utilisateur const userBalances = balances.filter( (balance: LibreChatBalance) => balance.user === user._id ); // Trier par date de mise à jour (plus récent en premier) const sortedBalances = userBalances.sort((a, b) => { const dateA = a.updatedAt || a.createdAt; const dateB = b.updatedAt || b.createdAt; // Vérifier que les dates sont valides avant de les comparer if (isValidDate(dateA) && isValidDate(dateB)) { return new Date(dateB as string | number | Date).getTime() - new Date(dateA as string | number | Date).getTime(); } // Si seulement une date existe et est valide, la privilégier if (isValidDate(dateA) && !isValidDate(dateB)) return -1; if (!isValidDate(dateA) && isValidDate(dateB)) return 1; // Si aucune date n'existe ou n'est valide, garder l'ordre actuel return 0; }); // Prendre la balance la plus récente const latestBalance = sortedBalances[0]; const credits = latestBalance ? latestBalance.tokenCredits || 0 : 0; // Ajouter l'utilisateur seulement s'il a des données significatives if (userConversations.length > 0 || totalTokens > 0 || credits > 0) { processedUsers.push({ userId: user._id, userName: user.name || user.username || user.email || 'Utilisateur inconnu', conversations: userConversations.length, tokens: totalTokens, credits: credits, }); } }); // Trier par tokens consommés (décroissant) et prendre les 5 premiers const sortedUsers = processedUsers .sort((a, b) => b.tokens - a.tokens) .slice(0, 5); console.log("✅ Top 5 users processed:", sortedUsers); setTopUsers(sortedUsers); setIsLoading(false); }, [users, conversations, transactions, balances]); useEffect(() => { const allDataLoaded = !usersLoading && !conversationsLoading && !transactionsLoading && !balancesLoading; if (allDataLoaded) { processUsers(); } else { setIsLoading(true); } }, [usersLoading, conversationsLoading, transactionsLoading, balancesLoading, processUsers]); if (isLoading) { return ( Top 5 utilisateurs
{[...Array(5)].map((_, i) => (
))}
); } if (topUsers.length === 0) { return ( Top 5 utilisateurs
Aucun utilisateur trouvé
); } return ( Top 5 utilisateurs
{topUsers.map((user, index) => (
{index + 1}

{user.userName}

{user.conversations} conversation{user.conversations !== 1 ? 's' : ''}

{user.tokens.toLocaleString()} tokens

{user.credits.toLocaleString()} crédits

))}
); }