"use client"; import { useState, useEffect, useMemo } from "react"; import { useSession } from "next-auth/react"; import { useRouter } from "next/navigation"; interface Event { id: string; date: string; name: string; description: string; type: "SUMMIT" | "LAUNCH" | "FESTIVAL" | "COMPETITION"; status: "UPCOMING" | "LIVE" | "PAST"; } interface EventsPageSectionProps { events: Event[]; backgroundImage: string; initialRegistrations?: Record; } const getEventTypeColor = (type: Event["type"]) => { switch (type) { case "SUMMIT": return "from-blue-600 to-cyan-500"; case "LAUNCH": return "from-purple-600 to-pink-500"; case "FESTIVAL": return "from-pixel-gold to-orange-500"; case "COMPETITION": return "from-red-600 to-orange-500"; default: return "from-gray-600 to-gray-500"; } }; const getEventTypeLabel = (type: Event["type"]) => { switch (type) { case "SUMMIT": return "Sommet"; case "LAUNCH": return "Lancement"; case "FESTIVAL": return "Festival"; case "COMPETITION": return "Compétition"; default: return type; } }; const getStatusBadge = (status: Event["status"]) => { switch (status) { case "UPCOMING": return ( À venir ); case "LIVE": return ( En direct ); case "PAST": return ( Passé ); } }; export default function EventsPageSection({ events, backgroundImage, initialRegistrations = {}, }: EventsPageSectionProps) { const { data: session } = useSession(); const router = useRouter(); const [registrations, setRegistrations] = useState>(initialRegistrations); const [loading, setLoading] = useState>({}); const [error, setError] = useState(""); const [currentMonth, setCurrentMonth] = useState(new Date()); // Déterminer si on a des données initiales valides const hasInitialData = useMemo( () => Object.keys(initialRegistrations).length > 0, [initialRegistrations] ); // Séparer et trier les événements (du plus récent au plus ancien) const upcomingEvents = events .filter((e) => e.status === "UPCOMING" || e.status === "LIVE") .sort((a, b) => { // Trier par date décroissante (du plus récent au plus ancien) return b.date.localeCompare(a.date); }); const pastEvents = events .filter((e) => e.status === "PAST") .sort((a, b) => { // Trier par date décroissante (du plus récent au plus ancien) return b.date.localeCompare(a.date); }); // Créer un map des événements par date pour le calendrier const eventsByDate: Record = {}; events.forEach((event) => { const dateKey = event.date; // YYYY-MM-DD if (!eventsByDate[dateKey]) { eventsByDate[dateKey] = []; } eventsByDate[dateKey].push(event); }); // Synchroniser les inscriptions si la session change côté client // Ne charger que si on n'a pas de données initiales (cas où l'utilisateur se connecte après le chargement) useEffect(() => { // Si on a déjà des données initiales, ne jamais les écraser if (hasInitialData) { return; } // Si pas de session, réinitialiser seulement si on n'avait pas de données initiales if (!session?.user?.id) { setRegistrations({}); return; } // Charger les inscriptions seulement si on n'a pas de données initiales const checkRegistrations = async () => { const upcomingOnlyEvents = events.filter((e) => e.status === "UPCOMING"); const registrationChecks = upcomingOnlyEvents.map(async (event) => { try { const response = await fetch(`/api/events/${event.id}/register`); const data = await response.json(); return { eventId: event.id, registered: data.registered || false }; } catch (err) { console.error("Error checking registration:", err); return { eventId: event.id, registered: false }; } }); const results = await Promise.all(registrationChecks); const registrationsMap: Record = {}; results.forEach(({ eventId, registered }) => { registrationsMap[eventId] = registered; }); setRegistrations(registrationsMap); }; checkRegistrations(); }, [session?.user?.id, events, hasInitialData]); // Fonctions pour le calendrier const getDaysInMonth = (date: Date) => { const year = date.getFullYear(); const month = date.getMonth(); return new Date(year, month + 1, 0).getDate(); }; const getFirstDayOfMonth = (date: Date) => { const year = date.getFullYear(); const month = date.getMonth(); return new Date(year, month, 1).getDay(); }; const formatMonthYear = (date: Date) => { return date.toLocaleDateString("fr-FR", { month: "long", year: "numeric", }); }; const renderCalendar = () => { const daysInMonth = getDaysInMonth(currentMonth); const firstDay = getFirstDayOfMonth(currentMonth); const days: (number | null)[] = []; // Ajouter des jours vides pour le début du mois for (let i = 0; i < firstDay; i++) { days.push(null); } // Ajouter les jours du mois for (let day = 1; day <= daysInMonth; day++) { days.push(day); } const year = currentMonth.getFullYear(); const month = currentMonth.getMonth() + 1; return (
{/* Header du calendrier */}

{formatMonthYear(currentMonth)}

{/* Jours de la semaine */}
{["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"].map((day) => (
{day}
))}
{/* Grille du calendrier */}
{days.map((day, index) => { if (day === null) { return
; } const dateKey = `${year}-${String(month).padStart(2, "0")}-${String( day ).padStart(2, "0")}`; const dayEvents = eventsByDate[dateKey] || []; const isToday = new Date().toISOString().split("T")[0] === dateKey; const hasEvents = dayEvents.length > 0; // Déterminer la couleur principale selon le type d'événement const hasUpcoming = dayEvents.some((e) => e.status === "UPCOMING"); const hasLive = dayEvents.some((e) => e.status === "LIVE"); const hasPast = dayEvents.some((e) => e.status === "PAST"); let eventBorderColor = ""; let eventBgColor = ""; if (hasLive) { eventBorderColor = "border-red-500/80"; eventBgColor = "bg-red-500/20"; } else if (hasUpcoming) { eventBorderColor = "border-green-500/80"; eventBgColor = "bg-green-500/20"; } else if (hasPast) { eventBorderColor = "border-gray-500/60"; eventBgColor = "bg-gray-500/15"; } return (
{day}
{hasEvents && (
{dayEvents.slice(0, 3).map((event) => (
))} {dayEvents.length > 3 && (
)}
)}
); })}
); }; const renderEventCard = (event: Event) => (
{/* Event Header */}
{/* Event Content */}
{/* Status Badge */}
{getStatusBadge(event.status)} {getEventTypeLabel(event.type)}
{/* Date */}
{event.date}
{/* Event Name */}

{event.name}

{/* Description */}

{event.description}

{/* Action Button */} {event.status === "UPCOMING" && ( <> {registrations[event.id] ? ( ) : ( )} )} {event.status === "LIVE" && ( )} {event.status === "PAST" && ( )}
); const handleRegister = async (eventId: string) => { if (!session?.user?.id) { router.push("/login"); return; } setLoading((prev) => ({ ...prev, [eventId]: true })); setError(""); try { const response = await fetch(`/api/events/${eventId}/register`, { method: "POST", }); const data = await response.json(); if (!response.ok) { setError(data.error || "Une erreur est survenue"); return; } setRegistrations((prev) => ({ ...prev, [eventId]: true, })); } catch (err) { setError("Une erreur est survenue"); } finally { setLoading((prev) => ({ ...prev, [eventId]: false })); } }; const handleUnregister = async (eventId: string) => { setLoading((prev) => ({ ...prev, [eventId]: true })); setError(""); try { const response = await fetch(`/api/events/${eventId}/register`, { method: "DELETE", }); if (!response.ok) { const data = await response.json(); setError(data.error || "Une erreur est survenue"); return; } setRegistrations((prev) => ({ ...prev, [eventId]: false, })); } catch (err) { setError("Une erreur est survenue"); } finally { setLoading((prev) => ({ ...prev, [eventId]: false })); } }; return (
{/* Background Image */}
{/* Dark overlay for readability */}
{/* Content */}
{/* Title Section */}

EVENTS

Événements à venir et passés

Rejoignez-nous pour des événements tech passionnants, des compétitions et des célébrations tout au long de l'année

{/* Événements à venir */} {upcomingEvents.length > 0 && (

Événements à venir

{upcomingEvents.map(renderEventCard)}
)} {/* Calendrier */}

Calendrier

{renderCalendar()}
{/* Événements passés */} {pastEvents.length > 0 && (

Événements passés

{pastEvents.map(renderEventCard)}
)} {/* Error Message */} {error && (

{error}

)} {/* Footer Info */}

Restez informé de nos derniers événements et annonces

); }