import { NextRequest, NextResponse } from 'next/server'; import { prisma } from '@/lib/prisma'; import { getCurrentUser } from '@/lib/auth'; // Types de période: day | 7days | 30days | month | quarter | year // Ou plage personnalisée via from & to (format ISO) function getDateRange(period: string | null, from: string | null, to: string | null): { start: Date; end: Date; prevStart: Date; prevEnd: Date; periodLabel: string; } { const now = new Date(); const endOfDay = (d: Date) => new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59, 999); const startOfDay = (d: Date) => new Date(d.getFullYear(), d.getMonth(), d.getDate()); if (from && to) { const start = new Date(from); const end = endOfDay(new Date(to)); const diff = end.getTime() - start.getTime(); const prevEnd = new Date(start.getTime() - 1); const prevStart = new Date(prevEnd.getTime() - diff); return { start: startOfDay(start), end, prevStart: startOfDay(prevStart), prevEnd: endOfDay(prevEnd), periodLabel: `${start.toLocaleDateString('fr-FR')} - ${new Date(to).toLocaleDateString('fr-FR')}`, }; } switch (period) { case 'day': { const start = startOfDay(now); const end = endOfDay(now); const yesterday = new Date(now); yesterday.setDate(yesterday.getDate() - 1); return { start, end, prevStart: startOfDay(yesterday), prevEnd: endOfDay(yesterday), periodLabel: "Aujourd'hui", }; } case 'yesterday': { const yesterday = new Date(now); yesterday.setDate(yesterday.getDate() - 1); const start = startOfDay(yesterday); const end = endOfDay(yesterday); const dayBefore = new Date(yesterday); dayBefore.setDate(dayBefore.getDate() - 1); return { start, end, prevStart: startOfDay(dayBefore), prevEnd: endOfDay(dayBefore), periodLabel: 'Hier', }; } case 'week': { // Cette semaine : lundi à aujourd'hui (ISO week, lundi = 1) const dayOfWeek = now.getDay(); const mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek; const startOfWeek = new Date(now); startOfWeek.setDate(startOfWeek.getDate() + mondayOffset); const start = startOfDay(startOfWeek); const end = endOfDay(now); const prevWeekStart = new Date(start); prevWeekStart.setDate(prevWeekStart.getDate() - 7); const prevWeekEnd = new Date(start); prevWeekEnd.setDate(prevWeekEnd.getDate() - 1); return { start, end, prevStart: startOfDay(prevWeekStart), prevEnd: endOfDay(prevWeekEnd), periodLabel: 'Cette semaine', }; } case '7days': { const start = new Date(now); start.setDate(start.getDate() - 6); const end = endOfDay(now); const prevEnd = new Date(start.getTime() - 1); const prevStart = new Date(prevEnd); prevStart.setDate(prevStart.getDate() - 6); return { start: startOfDay(start), end, prevStart: startOfDay(prevStart), prevEnd: endOfDay(prevEnd), periodLabel: '7 derniers jours', }; } case '30days': { const start = new Date(now); start.setDate(start.getDate() - 29); const end = endOfDay(now); const prevEnd = new Date(start.getTime() - 1); const prevStart = new Date(prevEnd); prevStart.setDate(prevStart.getDate() - 29); return { start: startOfDay(start), end, prevStart: startOfDay(prevStart), prevEnd: endOfDay(prevEnd), periodLabel: '30 derniers jours', }; } case 'quarter': { const q = Math.floor(now.getMonth() / 3) + 1; const startOfQuarter = new Date(now.getFullYear(), (q - 1) * 3, 1); const endOfQuarter = new Date(now.getFullYear(), q * 3, 0, 23, 59, 59, 999); const prevQuarter = q === 1 ? 4 : q - 1; const prevYear = q === 1 ? now.getFullYear() - 1 : now.getFullYear(); const prevStart = new Date(prevYear, (prevQuarter - 1) * 3, 1); const prevEnd = new Date(prevYear, prevQuarter * 3, 0, 23, 59, 59, 999); return { start: startOfQuarter, end: endOfQuarter, prevStart: prevStart, prevEnd: prevEnd, periodLabel: `T${q} ${now.getFullYear()}`, }; } case 'year': { const startOfYear = new Date(now.getFullYear(), 0, 1); const endOfYear = new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999); const prevStart = new Date(now.getFullYear() - 1, 0, 1); const prevEnd = new Date(now.getFullYear() - 1, 11, 31, 23, 59, 59, 999); return { start: startOfYear, end: endOfYear, prevStart: prevStart, prevEnd: prevEnd, periodLabel: `Année ${now.getFullYear()}`, }; } case 'month': default: { const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999); const startOfLastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1); const endOfLastMonth = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59, 999); return { start: startOfMonth, end: endOfMonth, prevStart: startOfLastMonth, prevEnd: endOfLastMonth, periodLabel: 'Mois en cours', }; } } } // GET - Récupérer les statistiques du dashboard export async function GET(request: NextRequest) { try { const user = await getCurrentUser(); if (!user) { return NextResponse.json({ error: 'Non autorisé' }, { status: 401 }); } const { searchParams } = new URL(request.url); const period = searchParams.get('period') || 'month'; const from = searchParams.get('from'); const to = searchParams.get('to'); const { start, end, prevStart, prevEnd, periodLabel } = getDateRange(period, from, to); // 1. Participations sur la période (trajets validés/terminés) const participationsMoisData = await prisma.participationFinanciere.findMany({ where: { trajet: { date: { gte: start, lte: end, }, }, }, include: { trajet: { select: { date: true } } }, }); const participationsCeMois = participationsMoisData; const montantMoyenParTrajet = 6.80; const participationsMois = participationsCeMois.reduce( (sum, p) => sum + (p.montant ?? montantMoyenParTrajet), 0 ); const nombreFactures = participationsCeMois.length; // 2. Trajets sur la période const trajetsPeriode = await prisma.trajet.count({ where: { archived: false, date: { gte: start, lte: end, }, }, }); // Trajets période précédente pour comparaison const trajetsPeriodePrecedente = await prisma.trajet.count({ where: { archived: false, date: { gte: prevStart, lte: prevEnd, }, }, }); const differenceTrajets = trajetsPeriode - trajetsPeriodePrecedente; // 3. Trajets réalisés sur la période (terminés) const trajetsRealisesPeriode = await prisma.trajet.count({ where: { archived: false, statut: 'Terminé', date: { gte: start, lte: end, }, }, }); // Trajets réalisés période précédente pour comparaison const trajetsRealisesPeriodePrecedente = await prisma.trajet.count({ where: { archived: false, statut: 'Terminé', date: { gte: prevStart, lte: prevEnd, }, }, }); const pourcentageEvolution = trajetsRealisesPeriodePrecedente > 0 ? Math.round(((trajetsRealisesPeriode - trajetsRealisesPeriodePrecedente) / trajetsRealisesPeriodePrecedente) * 100) : trajetsRealisesPeriode > 0 ? 100 : 0; // 4. Chauffeurs actifs (disponibles) const totalChauffeurs = await prisma.chauffeur.count(); const chauffeursActifs = await prisma.chauffeur.count({ where: { status: 'Disponible', }, }); return NextResponse.json({ periodLabel, participationsMois: { montant: participationsMois, nombreFactures: nombreFactures, }, trajetsAujourdhui: { nombre: trajetsPeriode, difference: differenceTrajets, }, trajetsRealisesMois: { nombre: trajetsRealisesPeriode, pourcentageEvolution: pourcentageEvolution, }, chauffeursActifs: { nombre: chauffeursActifs, total: totalChauffeurs, }, }); } catch (error) { console.error('Erreur lors de la récupération des statistiques:', error); return NextResponse.json( { error: 'Erreur serveur' }, { status: 500 } ); } }