'use client'; import { useState, useEffect, useCallback } from 'react'; import { adminService } from '@/services/admin.service'; import { Ticket } from '@/types'; import { StatusBadge, Pagination } from '@/components/ui'; import { Search, RefreshCw, X, Ticket as TicketIcon, Clock, CheckCircle, XCircle, Gift, Filter } from 'lucide-react'; export default function TicketManagement() { const [tickets, setTickets] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [page, setPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [totalTickets, setTotalTickets] = useState(0); const [filterStatus, setFilterStatus] = useState(''); const [filterPrizeType, setFilterPrizeType] = useState(''); const [selectedTicket, setSelectedTicket] = useState(null); const [ticketStats, setTicketStats] = useState({ pending: 0, claimed: 0, rejected: 0 }); const loadTickets = useCallback(async () => { try { setLoading(true); setError(null); // Construire les filtres const filters: any = {}; if (filterStatus) filters.status = filterStatus; if (filterPrizeType) filters.prizeType = filterPrizeType; const response = await adminService.getAllTickets( page, 20, Object.keys(filters).length > 0 ? filters : undefined ); // Vérifier si la réponse est directement un tableau ou un objet avec data let ticketsData: Ticket[] = []; let total = 0; let totalPagesCount = 1; if (Array.isArray(response)) { ticketsData = response; total = response.length; totalPagesCount = 1; } else if (response.data && Array.isArray(response.data)) { ticketsData = response.data; total = response.total || response.data.length; totalPagesCount = response.totalPages || 1; // Récupérer les stats du backend if (response.stats) { setTicketStats(response.stats); } } setTickets(ticketsData); setTotalPages(totalPagesCount); setTotalTickets(total); } catch (err: any) { let errorMessage = 'Erreur lors du chargement des tickets'; if (err.status === 401) { errorMessage = '🔐 Non autorisé (401) - Votre session a expiré ou votre token est invalide. Veuillez vous reconnecter.'; } else if (err.status === 403) { errorMessage = '🚫 Accès refusé (403) - Vous n\'avez pas les permissions administrateur nécessaires.'; } else if (err.status === 0 || err.message.includes('fetch')) { errorMessage = '🔌 Impossible de contacter le serveur. Vérifiez que le backend est démarré sur http://localhost:4000'; } else { errorMessage = err.message || errorMessage; } setError(errorMessage); setTickets([]); setTotalTickets(0); } finally { setLoading(false); } }, [page, filterStatus, filterPrizeType]); useEffect(() => { loadTickets(); }, [loadTickets]); // Fonction pour obtenir les initiales const getInitials = (firstName?: string, lastName?: string) => { const f = firstName?.charAt(0) || ''; const l = lastName?.charAt(0) || ''; return (f + l).toUpperCase() || '?'; }; if (loading && tickets.length === 0) { return (

Chargement des tickets...

); } return (
{/* Section filtres */}
{(filterStatus || filterPrizeType) && ( )}
{error && (

Erreur de chargement:

{error}

{error.includes('401') && (

Votre session a expiré ou votre token est invalide.

)} {error.includes('403') && (

Vous n'avez pas le rôle ADMIN requis.

)} {!error.includes('401') && !error.includes('403') && (

Vérifiez que le backend est démarré.

)}
)} {/* Stats rapides */}

{totalTickets}

Total

{ticketStats.pending}

En attente

{ticketStats.claimed}

Réclamés

{ticketStats.rejected}

Rejetés

{/* Table des tickets */}
{tickets.length === 0 ? ( ) : ( tickets.map((ticket) => ( {/* CODE TICKET */} {/* LOT GAGNÉ */} {/* STATUT */} {/* DISTRIBUÉ LE */} {/* UTILISÉ PAR */} {/* ACTIONS */} )) )}
Code Ticket Lot Gagné Statut Joué le Utilisé par Actions

{!error ? 'Aucun ticket trouvé' : 'Impossible de charger les tickets'}

{filterStatus ? `Aucun ticket avec le statut "${filterStatus === 'PENDING' ? 'En attente' : filterStatus === 'CLAIMED' ? 'Réclamé' : filterStatus === 'REJECTED' ? 'Rejeté' : filterStatus}"` : 'Aucun ticket n\'a été créé pour le moment' }

{ticket.code}
{ticket.prize?.name || 'N/A'}
{ticket.playedAt ? new Date(ticket.playedAt).toLocaleDateString('fr-FR', { year: 'numeric', month: '2-digit', day: '2-digit' }) : '-'} {ticket.user ? (
{getInitials(ticket.user.firstName, ticket.user.lastName)}
{ticket.user.firstName} {ticket.user.lastName}
{ticket.user.email}
) : ( - )}
{/* Pagination */} {/* Modal détails ticket */} {selectedTicket && (

Détails du ticket

{/* Code et Statut */}

Code ticket

{selectedTicket.code}

{/* Utilisateur */} {selectedTicket.user && (

Utilisateur

{getInitials(selectedTicket.user.firstName, selectedTicket.user.lastName)}

{selectedTicket.user.firstName} {selectedTicket.user.lastName}

{selectedTicket.user.email}

)} {/* Prix gagné */}

Prix gagné

{selectedTicket.prize?.name}

{selectedTicket.prize?.description}

{/* Dates */}

Date de jeu

{selectedTicket.playedAt ? new Date(selectedTicket.playedAt).toLocaleString('fr-FR') : 'N/A'}

{selectedTicket.validatedAt && (

Date de validation

{new Date(selectedTicket.validatedAt).toLocaleString('fr-FR')}

)}
{/* Raison du rejet */} {selectedTicket.rejectionReason && (

Raison du rejet

{selectedTicket.rejectionReason}

)}
)}
); }