"use client"; import { useState, 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 { Calendar, Event } from "@prisma/client"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; interface CalendarClientProps { initialCalendars: (Calendar & { events: Event[] })[]; userId: string; } interface EventFormData { title: string; description: string | null; start: string; end: string; allDay: boolean; location: string | null; calendarId?: string; } export function CalendarClient({ initialCalendars, userId }: CalendarClientProps) { const [calendars, setCalendars] = useState(initialCalendars); const [selectedCalendarId, setSelectedCalendarId] = useState( initialCalendars[0]?.id || "" ); const [view, setView] = useState<"dayGridMonth" | "timeGridWeek" | "timeGridDay">("dayGridMonth"); const [isEventModalOpen, setIsEventModalOpen] = useState(false); const [selectedEvent, setSelectedEvent] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [eventForm, setEventForm] = useState({ title: "", description: null, start: "", end: "", allDay: false, location: null, }); const calendarRef = useRef(null); const handleDateSelect = (selectInfo: any) => { const startDate = new Date(selectInfo.start); const endDate = new Date(selectInfo.end); setEventForm({ title: "", description: null, start: startDate.toISOString().slice(0, 16), end: endDate.toISOString().slice(0, 16), allDay: selectInfo.allDay, location: null, calendarId: selectedCalendarId, }); setIsEventModalOpen(true); }; const handleEventClick = (clickInfo: any) => { const event = clickInfo.event; const startDate = new Date(event.start); const endDate = new Date(event.end || event.start); setSelectedEvent(event.extendedProps.originalEvent); setEventForm({ title: event.title, description: event.extendedProps.description, start: startDate.toISOString().slice(0, 16), end: endDate.toISOString().slice(0, 16), allDay: event.isAllDay, location: event.extendedProps.location, calendarId: event.extendedProps.calendarId, }); setIsEventModalOpen(true); }; const handleEventSubmit = async () => { try { setLoading(true); const method = selectedEvent ? "PUT" : "POST"; const url = selectedEvent ? `/api/calendar?id=${selectedEvent.id}` : "/api/calendar"; const response = await fetch(url, { method, headers: { "Content-Type": "application/json", }, body: JSON.stringify({ ...eventForm, id: selectedEvent?.id, start: new Date(eventForm.start), end: new Date(eventForm.end), userId, }), }); if (!response.ok) { throw new Error("Erreur lors de la sauvegarde de l'événement"); } // Refresh calendar data const eventsResponse = await fetch("/api/calendar"); const updatedEvents = await eventsResponse.json(); setCalendars(calendars.map(cal => ({ ...cal, events: updatedEvents.filter((event: Event) => event.calendarId === cal.id) }))); setIsEventModalOpen(false); setSelectedEvent(null); setEventForm({ title: "", description: null, start: "", end: "", allDay: false, location: null, }); } catch (error) { setError((error as Error).message); } finally { setLoading(false); } }; const handleEventDelete = async () => { if (!selectedEvent) return; try { setLoading(true); const response = await fetch(`/api/calendar?id=${selectedEvent.id}`, { method: "DELETE", }); if (!response.ok) { throw new Error("Erreur lors de la suppression de l'événement"); } // Refresh calendar data const eventsResponse = await fetch("/api/calendar"); const updatedEvents = await eventsResponse.json(); setCalendars(calendars.map(cal => ({ ...cal, events: updatedEvents.filter((event: Event) => event.calendarId === cal.id) }))); setIsEventModalOpen(false); setSelectedEvent(null); } catch (error) { setError((error as Error).message); } finally { setLoading(false); } }; const handleViewChange = (newView: "dayGridMonth" | "timeGridWeek" | "timeGridDay") => { setView(newView); if (calendarRef.current) { const calendarApi = calendarRef.current.getApi(); calendarApi.changeView(newView); } }; return (
{/* Calendar filters and options */}
{calendars.map((calendar) => ( ))}
{/* View selector */} handleViewChange("dayGridMonth")} > Mois handleViewChange("timeGridWeek")} > Semaine handleViewChange("timeGridDay")} > Jour {/* Calendar display */} {error && (
Erreur: {error}
)} {loading ? (
Chargement des événements...
) : ( cal.events.map(event => ({ id: event.id, title: event.title, start: event.start, end: event.end, allDay: event.isAllDay, description: event.description, location: event.location, calendarId: event.calendarId, originalEvent: event, })) )} locale={frLocale} selectable={true} selectMirror={true} dayMaxEvents={true} weekends={true} select={handleDateSelect} eventClick={handleEventClick} height="auto" aspectRatio={1.8} /> )}
{/* Event creation/edit dialog */} {selectedEvent ? "Modifier l'événement" : "Nouvel événement"}
setEventForm({ ...eventForm, title: e.target.value }) } />