import { useState, useEffect } from "react"; import useAuth from "@/hooks/useAuth"; import { db } from "@/lib/firebase"; import { collection, query, where, getDocs, doc, getDoc, orderBy, limit } from "firebase/firestore"; import { getProjectsByStatus, ProjectStatus } from "@/services/projectService"; export interface DashboardStats { activeProjects: number; totalClients: number; totalQuotes: number; acceptanceRate: number; totalRevenue: number; completedProjects: number; pendingAppointments: number; unreadMessages: number; artisansContacted: number; messagesNonLus: number; // Properties for ArtisanStats totalProjects: number; totalAppointments: number; pendingRevenue: number; recentActivity: { type: 'project' | 'quote' | 'appointment' | 'message'; title: string; date: Date; id: string; }[]; isLoading: boolean; } export default function useDashboardStats() { const { userData, currentUser, isClient, isArtisan } = useAuth(); const [stats, setStats] = useState({ activeProjects: 0, totalClients: 0, totalQuotes: 0, acceptanceRate: 0, totalRevenue: 0, completedProjects: 0, pendingAppointments: 0, unreadMessages: 0, artisansContacted: 0, messagesNonLus: 0, totalProjects: 0, totalAppointments: 0, pendingRevenue: 0, recentActivity: [], isLoading: true }); useEffect(() => { async function fetchDashboardData() { if (!currentUser || !userData) { setStats(prev => ({ ...prev, isLoading: false })); return; } try { // Récupérer les données en fonction du rôle de l'utilisateur if (isClient) { await fetchClientStats(currentUser.uid); } else if (isArtisan) { await fetchArtisanStats(currentUser.uid); } } catch (error) { console.error("Erreur lors de la récupération des statistiques:", error); setStats(prev => ({ ...prev, isLoading: false })); } } async function fetchClientStats(userId: string) { // 1. Projets actifs const activeProjects = await getProjectsByStatus(userId, "client", "in_progress"); // 2. Artisans contactés const artisansContactedQuery = query( collection(db, "messages"), where("clientId", "==", userId), orderBy("createdAt", "desc") ); const messagesSnapshot = await getDocs(artisansContactedQuery); const uniqueArtisans = new Set(); messagesSnapshot.forEach(doc => { const data = doc.data(); if (data.artisanId) uniqueArtisans.add(data.artisanId); }); // 3. Messages non lus const unreadMessagesQuery = query( collection(db, "messages"), where("recipientId", "==", userId), where("isRead", "==", false) ); const unreadMessagesSnapshot = await getDocs(unreadMessagesQuery); // Définir les statistiques du client setStats({ activeProjects: activeProjects.length, artisansContacted: uniqueArtisans.size, messagesNonLus: unreadMessagesSnapshot.size, totalClients: 0, totalQuotes: 0, acceptanceRate: 0, totalRevenue: 0, completedProjects: 0, pendingAppointments: 0, unreadMessages: unreadMessagesSnapshot.size, totalProjects: activeProjects.length, totalAppointments: 0, pendingRevenue: 0, recentActivity: getRecentActivityFromSnapshots(messagesSnapshot), isLoading: false }); } async function fetchArtisanStats(userId: string) { // 1. Projets actifs const activeProjects = await getProjectsByStatus(userId, "artisan", "in_progress"); // 2. Projets terminés const completedProjects = await getProjectsByStatus(userId, "artisan", "completed"); // 3. Total des clients uniques const projectsQuery = query( collection(db, "projects"), where("artisanId", "==", userId) ); const projectsSnapshot = await getDocs(projectsQuery); const uniqueClients = new Set(); projectsSnapshot.forEach(doc => { const data = doc.data(); if (data.clientId) uniqueClients.add(data.clientId); }); // 4. Taux d'acceptation const quotesQuery = query( collection(db, "projectApplications"), where("artisanId", "==", userId) ); const quotesSnapshot = await getDocs(quotesQuery); const totalQuotes = quotesSnapshot.size; let acceptedQuotes = 0; quotesSnapshot.forEach(doc => { const data = doc.data(); if (data.status === "accepted") acceptedQuotes++; }); const acceptanceRate = totalQuotes > 0 ? Math.round((acceptedQuotes / totalQuotes) * 100) : 0; // 5. Revenus totaux et en attente const paymentsQuery = query( collection(db, "payments"), where("artisanId", "==", userId) ); const paymentsSnapshot = await getDocs(paymentsQuery); let totalRevenue = 0; let pendingRevenue = 0; paymentsSnapshot.forEach(doc => { const data = doc.data(); if (data.status === "completed") { totalRevenue += data.amount || 0; } else if (data.status === "pending") { pendingRevenue += data.amount || 0; } }); // 6. Rendez-vous const appointmentsQuery = query( collection(db, "appointments"), where("artisanId", "==", userId) ); const appointmentsSnapshot = await getDocs(appointmentsQuery); let pendingAppointments = 0; appointmentsSnapshot.forEach(doc => { const data = doc.data(); if (data.status === "pending" || data.status === "confirmed") { pendingAppointments++; } }); // 7. Messages non lus const unreadMessagesQuery = query( collection(db, "messages"), where("recipientId", "==", userId), where("isRead", "==", false) ); const unreadMessagesSnapshot = await getDocs(unreadMessagesQuery); // Définir les statistiques de l'artisan setStats({ activeProjects: activeProjects.length, totalClients: uniqueClients.size, totalQuotes: totalQuotes, acceptanceRate: acceptanceRate, totalRevenue: totalRevenue, completedProjects: completedProjects.length, pendingAppointments: pendingAppointments, unreadMessages: unreadMessagesSnapshot.size, artisansContacted: 0, messagesNonLus: unreadMessagesSnapshot.size, totalProjects: activeProjects.length + completedProjects.length, totalAppointments: appointmentsSnapshot.size, pendingRevenue: pendingRevenue, recentActivity: getRecentActivityFromSnapshots( unreadMessagesSnapshot, projectsSnapshot ), isLoading: false }); } function getRecentActivityFromSnapshots(...snapshots: any[]) { const activities: any[] = []; snapshots.forEach(snapshot => { snapshot.forEach((doc: any) => { const data = doc.data(); if (data.type === 'message') { activities.push({ type: 'message', title: `Message de ${data.senderName || 'Utilisateur'}`, date: data.createdAt?.toDate() || new Date(), id: doc.id }); } else if (data.title) { activities.push({ type: 'project', title: data.title, date: data.createdAt?.toDate() || new Date(), id: doc.id }); } }); }); // Trier par date décroissante et limiter à 5 activités return activities .sort((a, b) => b.date.getTime() - a.date.getTime()) .slice(0, 5); } fetchDashboardData(); }, [currentUser, userData, isClient, isArtisan]); return stats; }