"use client"; import { useState, useEffect } from "react"; import { adminService } from "@/services/admin.service"; import { AdminStatistics } from "@/types"; import Link from "next/link"; import { Users, Ticket, TrendingUp, AlertCircle, Gift, BarChart3, RefreshCw, MapPin, User as UserIcon, Calendar, } from "lucide-react"; export default function AdminDashboard() { const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { loadStatistics(); }, []); const loadStatistics = async () => { try { setLoading(true); setError(null); const data = await adminService.getStatistics(); setStats(data); } catch (err: any) { setError(err.message || "Erreur lors du chargement des statistiques"); setStats(null); } finally { setLoading(false); } }; if (loading) { return (
{[...Array(4)].map((_, i) => (
))}
); } if (error || !stats) { return (
{error || "Erreur lors du chargement des statistiques"}
); } // Calculer les pourcentages pour les tickets const ticketDistributedPercent = stats.tickets.total > 0 ? ((stats.tickets.distributed / stats.tickets.total) * 100).toFixed(1) : 0; const ticketUsedPercent = stats.tickets.distributed > 0 ? ((stats.tickets.used / stats.tickets.distributed) * 100).toFixed(1) : 0; return (
{/* Header */}

Dashboard Administrateur

Statistiques complètes du jeu-concours Thé Tip Top

{/* Stats Cards - Principales */}
} color="blue" link="/admin/utilisateurs" /> } color="green" link="/admin/tickets" /> } color="purple" link="/admin/tickets" /> } color="yellow" link="/admin/tickets" />
{/* Section des Tickets */}
{/* Statistiques Tickets détaillées */}

Statistiques des Tickets

Voir tout →
{/* Utilisateurs */}

Utilisateurs

Voir tout →
{/* Répartition des Lots par Catégorie */} {stats?.prizes?.byCategory && stats.prizes.byCategory.length > 0 && (

Répartition des Lots Gagnés par Catégorie

{stats.prizes.byCategory.map((prize) => ( ))}
)} {/* Statistiques Démographiques */} {stats?.demographics && (

Statistiques Démographiques des Participants

{/* Répartition par Genre */} {stats.demographics.gender && (

Répartition par Genre

)} {/* Répartition par Âge */} {stats.demographics.ageRanges && stats.demographics.ageRanges.length > 0 && (

Répartition par Âge

{stats.demographics.ageRanges.map((range, idx) => ( ))}
)}
{/* Top Villes */} {stats.demographics.topCities && stats.demographics.topCities.length > 0 && (

Top 10 Villes des Participants

{stats.demographics.topCities.slice(0, 10).map((city, idx) => ( ))}
)}
)}
); } interface StatCardProps { title: string; value: number; subtitle?: string; icon: React.ReactNode; color: "blue" | "green" | "yellow" | "purple" | "red"; link: string; } function StatCard({ title, value, subtitle, icon, color, link }: StatCardProps) { const colors = { blue: "bg-blue-100 text-blue-600", green: "bg-green-100 text-green-600", yellow: "bg-yellow-100 text-yellow-600", purple: "bg-purple-100 text-purple-600", red: "bg-red-100 text-red-600", }; return (
{icon}

{title}

{(value || 0).toLocaleString("fr-FR")}

{subtitle && (

{subtitle}

)} ); } interface StatRowProps { label: string; value: number; color?: "green" | "yellow" | "red" | "purple" | "blue"; percentage?: string | number; } function StatRow({ label, value, color, percentage }: StatRowProps) { const colors = { green: "text-green-600", yellow: "text-yellow-600", red: "text-red-600", purple: "text-purple-600", blue: "text-blue-600", }; return (
{label}
{(value || 0).toLocaleString("fr-FR")} {percentage !== undefined && ( ({percentage}%) )}
); } // Composant pour afficher une carte de lot interface PrizeCardProps { name: string; type: string; count: number; percentage: number; } function PrizeCard({ name, type, count, percentage }: PrizeCardProps) { const typeColors = { PHYSICAL: "bg-purple-100 text-purple-800", DISCOUNT: "bg-green-100 text-green-800", }; const color = typeColors[type as keyof typeof typeColors] || "bg-gray-100 text-gray-800"; return (

{name}

{type === "PHYSICAL" ? "Physique" : "Réduction"}

{count}

distribués

{percentage.toFixed(1)}%

{/* Barre de progression */}
); } // Composant pour les statistiques démographiques interface DemoStatRowProps { label: string; value: number; total?: number; percentage?: number; color?: "blue" | "pink" | "purple" | "gray" | "green"; } function DemoStatRow({ label, value, total, percentage, color }: DemoStatRowProps) { const calculatedPercentage = percentage !== undefined ? percentage : total && total > 0 ? (value / total) * 100 : 0; const colors = { blue: "bg-blue-500", pink: "bg-pink-500", purple: "bg-purple-500", gray: "bg-gray-500", green: "bg-green-500", }; const barColor = color ? colors[color] : "bg-blue-500"; return (
{label}
{value.toLocaleString("fr-FR")} ({calculatedPercentage.toFixed(1)}%)
); } // Composant pour afficher une carte de ville interface CityCardProps { rank: number; city: string; count: number; percentage: number; } function CityCard({ rank, city, count, percentage }: CityCardProps) { const rankColors = { 1: "bg-yellow-100 text-yellow-800 border-yellow-300", 2: "bg-gray-100 text-gray-800 border-gray-300", 3: "bg-orange-100 text-orange-800 border-orange-300", }; const rankColor = rankColors[rank as keyof typeof rankColors] || "bg-blue-50 text-blue-800 border-blue-200"; return (
#{rank}

{city}

{count} ({percentage.toFixed(1)}%)
); }