"use client"; import { useState, useEffect, useRef } from "react"; import FullCalendar from "@fullcalendar/react"; import dayGridPlugin from "@fullcalendar/daygrid"; import timeGridPlugin from "@fullcalendar/timegrid"; import interactionPlugin from "@fullcalendar/interaction"; import frLocale from "@fullcalendar/core/locales/fr"; import { Card } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Loader2, Plus } from "lucide-react"; import { useCalendarEvents } from "@/hooks/use-calendar-events"; import { EventDialog } from "@/components/calendar/event-dialog"; import { Calendar, Calendar as CalendarType } from "@prisma/client"; import { useToast } from "@/components/ui/use-toast"; import { CalendarDialog } from "./calendar-dialog"; interface CalendarClientProps { initialCalendars: CalendarType[]; } export function CalendarClient({ initialCalendars }: CalendarClientProps) { const [isCalendarDialogOpen, setIsCalendarDialogOpen] = useState(false); const [calendars, setCalendars] = useState(initialCalendars); const [selectedCalendarId, setSelectedCalendarId] = useState( initialCalendars[0]?.id || "" ); const [view, setView] = useState< "dayGridMonth" | "timeGridWeek" | "timeGridDay" >("dayGridMonth"); const [isDialogOpen, setIsDialogOpen] = useState(false); const [selectedEvent, setSelectedEvent] = useState(null); const [dateRange, setDateRange] = useState({ start: new Date(), end: new Date(new Date().setMonth(new Date().getMonth() + 1)), }); const calendarRef = useRef(null); const { toast } = useToast(); const { events, loading, error, refresh, createEvent, updateEvent, deleteEvent, } = useCalendarEvents(selectedCalendarId, dateRange.start, dateRange.end); // Mettre à jour la plage de dates lorsque la vue change const handleDatesSet = (arg: any) => { setDateRange({ start: arg.start, end: arg.end, }); }; // Gérer la sélection d'une plage de dates pour créer un événement const handleDateSelect = (selectInfo: any) => { setSelectedEvent({ start: selectInfo.startStr, end: selectInfo.endStr, allDay: selectInfo.allDay, }); setIsDialogOpen(true); }; // Gérer le clic sur un événement existant const handleEventClick = (clickInfo: any) => { setSelectedEvent({ id: clickInfo.event.id, title: clickInfo.event.title, description: clickInfo.event.extendedProps.description, start: clickInfo.event.startStr, end: clickInfo.event.endStr, location: clickInfo.event.extendedProps.location, allDay: clickInfo.event.allDay, }); setIsDialogOpen(true); }; // Gérer la création ou mise à jour d'un événement const handleEventSave = async (eventData: any) => { try { if (eventData.id) { await updateEvent(eventData); toast({ title: "Événement mis à jour", description: "L'événement a été modifié avec succès.", }); } else { await createEvent({ ...eventData, calendarId: selectedCalendarId, }); toast({ title: "Événement créé", description: "L'événement a été ajouté au calendrier.", }); } setIsDialogOpen(false); refresh(); } catch (error) { console.error("Erreur lors de la sauvegarde de l'événement:", error); toast({ title: "Erreur", description: "Impossible d'enregistrer l'événement.", variant: "destructive", }); } }; // Gérer la suppression d'un événement const handleEventDelete = async (eventId: string) => { try { await deleteEvent(eventId); toast({ title: "Événement supprimé", description: "L'événement a été supprimé du calendrier.", }); setIsDialogOpen(false); refresh(); } catch (error) { console.error("Erreur lors de la suppression de l'événement:", error); toast({ title: "Erreur", description: "Impossible de supprimer l'événement.", variant: "destructive", }); } }; // Changer la vue du calendrier const handleViewChange = ( newView: "dayGridMonth" | "timeGridWeek" | "timeGridDay" ) => { setView(newView); if (calendarRef.current) { const calendarApi = calendarRef.current.getApi(); calendarApi.changeView(newView); } }; // Changer le calendrier sélectionné const handleCalendarChange = (calendarId: string) => { setSelectedCalendarId(calendarId); }; // Fonction pour créer un nouveau calendrier const handleCreateCalendar = async (calendarData: Partial) => { try { const response = await fetch("/api/calendars", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(calendarData), }); if (!response.ok) { throw new Error(`Erreur ${response.status}: ${await response.text()}`); } const newCalendar = await response.json(); // Mettre à jour la liste des calendriers setCalendars([...calendars, newCalendar]); // Sélectionner automatiquement le nouveau calendrier setSelectedCalendarId(newCalendar.id); toast({ title: "Calendrier créé", description: `Le calendrier "${newCalendar.name}" a été créé avec succès.`, }); } catch (error) { console.error("Erreur lors de la création du calendrier:", error); toast({ title: "Erreur", description: "Impossible de créer le calendrier.", variant: "destructive", }); } }; return (
{/* Options et filtres du calendrier */}
{calendars.map((calendar) => ( ))}
{/* Sélecteur de vue */} handleViewChange("dayGridMonth")} > Mois handleViewChange("timeGridWeek")} > Semaine handleViewChange("timeGridDay")} > Jour {/* Affichage du calendrier */} {error && (
Erreur: {error.message}
)} {loading && !events.length ? (
Chargement des événements...
) : ( ({ id: event.id, title: event.title, start: event.start, end: event.end, allDay: event.isAllDay, extendedProps: { description: event.description, location: event.location, }, }))} selectable={true} selectMirror={true} dayMaxEvents={true} weekends={true} locale={frLocale} select={handleDateSelect} eventClick={handleEventClick} datesSet={handleDatesSet} height='auto' aspectRatio={1.8} /> )}
{isCalendarDialogOpen && ( setIsCalendarDialogOpen(false)} onSave={handleCreateCalendar} /> )} {/* Dialogue pour créer/modifier un événement */} {isDialogOpen && ( setIsDialogOpen(false)} onSave={handleEventSave} onDelete={selectedEvent?.id ? handleEventDelete : undefined} calendars={calendars} /> )}
); }