"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, LibreChatBalance, } from "@/lib/types"; interface DashboardUser { userId: string; userName: string; conversations: number; tokens: number; credits: number; } // Interface pour les transactions (vraie source de consommation) interface TransactionDocument { _id: string; user: unknown; // ObjectId dans MongoDB rawAmount?: number; tokenType?: string; model?: string; } export function DashboardUsersList() { const [topUsers, setTopUsers] = useState([]); const [isLoading, setIsLoading] = useState(true); // Récupérer toutes les données nécessaires const { data: users, loading: usersLoading } = useCollection("users", { limit: 1000 }); const { data: conversations, loading: conversationsLoading } = useCollection("conversations", { limit: 1000 }); const { data: balances, loading: balancesLoading } = useCollection("balances", { limit: 1000 }); // Transactions = vraie source de consommation de tokens const { data: transactions, loading: transactionsLoading } = useCollection("transactions", { limit: 10000 }); const processUsers = useCallback(() => { if (!users?.length || !conversations?.length || !balances?.length) { return; } console.log("🔄 Processing users data..."); console.log("Users:", users.length); console.log("Conversations:", conversations.length); console.log("Balances:", balances.length); console.log("Transactions:", transactions?.length || 0); const processedUsers: DashboardUser[] = []; // Créer une map des transactions par utilisateur (user est un ObjectId, on compare en string) const tokensByUser = new Map(); if (transactions?.length) { transactions.forEach((tx: TransactionDocument) => { // tx.user est un ObjectId, on le convertit en string pour la comparaison const txUserId = String(tx.user); const tokens = Math.abs(tx.rawAmount || 0); tokensByUser.set(txUserId, (tokensByUser.get(txUserId) || 0) + tokens); }); } users.forEach((user: LibreChatUser) => { const userId = user._id; // Obtenir les conversations de l'utilisateur (user dans conversations est un string) const userConversations = conversations.filter( (conv: LibreChatConversation) => String(conv.user) === userId ); // Obtenir les tokens depuis les transactions (vraie consommation) const tokensFromTransactions = tokensByUser.get(userId) || 0; // Obtenir le balance de l'utilisateur const userBalance = balances.find( (balance: LibreChatBalance) => String(balance.user) === userId ); const credits = userBalance?.tokenCredits || 0; // Ajouter l'utilisateur s'il a consommé des tokens if (tokensFromTransactions > 0) { processedUsers.push({ userId: userId, userName: user.name || user.username || user.email || "Utilisateur inconnu", conversations: userConversations.length, tokens: tokensFromTransactions, 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("📊 Processing summary:", { totalUsers: users.length, usersWithActivity: processedUsers.length, top5Users: sortedUsers.length, }); console.log("✅ Top 5 users:", sortedUsers); setTopUsers(sortedUsers); setIsLoading(false); }, [users, conversations, balances, transactions]); useEffect(() => { const allDataLoaded = !usersLoading && !conversationsLoading && !balancesLoading && !transactionsLoading; if (allDataLoaded) { processUsers(); } else { setIsLoading(true); } }, [ usersLoading, conversationsLoading, balancesLoading, transactionsLoading, 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

))}
); }