"use client"; import { ApiResponse } from "@/types/types"; import request from "@/lib/request"; import "@schedule-x/theme-shadcn/dist/index.css"; import { useNextCalendarApp, ScheduleXCalendar } from "@schedule-x/react"; import { createEventsServicePlugin } from "@schedule-x/events-service"; import { createDragAndDropPlugin } from "@schedule-x/drag-and-drop"; import { createResizePlugin } from "@schedule-x/resize"; import { createEventRecurrencePlugin } from "@schedule-x/event-recurrence"; import { createViewDay, createViewWeek } from "@schedule-x/calendar"; import { useEffect, useState } from "react"; import { format } from "date-fns"; import { Dialog, DialogProps } from "@radix-ui/react-dialog"; import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { KeyedMutator } from "swr"; import { getCookie } from "cookies-next"; import { useTheme } from "next-themes"; import { EventForm, EventFormValues } from "./event-dialog"; import ICalendarEvent from "@/interfaces/ICalendarEvent"; const mapFrequencyToRrule = ( frequency: "unique" | "quotidien" | "hebdomadaire" | "mensuel", frequencyEndDate?: Date, ): string => { let rrule = ""; switch (frequency) { case "quotidien": rrule = "FREQ=DAILY"; break; case "hebdomadaire": rrule = "FREQ=WEEKLY"; break; case "mensuel": rrule = "FREQ=MONTHLY"; break; default: return ""; } if (frequencyEndDate) { const until = frequencyEndDate.getTime(); const untilDate = new Date(until); const epochDateString = untilDate .toISOString() .replace(/[-:]/g, "") .split(".")[0]; // Format as YYYYMMDDTHHmmss rrule += `;UNTIL=${epochDateString}`; } return rrule; }; const Planning: React.FC<{ events: ICalendarEvent[]; mutate?: KeyedMutator>; }> = ({ events, mutate }) => { const { resolvedTheme } = useTheme(); console.log(resolvedTheme); const isConnected = getCookie("auth_token"); const plugins = isConnected ? [ createEventsServicePlugin(), createDragAndDropPlugin(), createResizePlugin(), createEventRecurrencePlugin(), ] : []; const [eventSelected, setEventSelected] = useState( null, ); const [newEvent, setNewEvent] = useState | null>( null, ); const handleEventUpdate = async (eventSelected: ICalendarEvent) => { const event: ICalendarEvent = { ...eventSelected, start: `${new Date(eventSelected.start).toISOString()}`, end: `${new Date(eventSelected.end).toISOString()}`, }; try { const res = await request(`/events/${event.id}/update`, { method: "PATCH", body: event, requiresAuth: true, csrfToken: false, }); if (res.status === "Error") { // calendar?.events?.update(oldEvent); } } catch (e) { console.log(e); } }; const calendar = useNextCalendarApp( { theme: "shadcn", views: [createViewDay(), createViewWeek()], defaultView: "week", isDark: resolvedTheme === "dark" ? true : false, isResponsive: true, locale: "fr-FR", dayBoundaries: { start: "06:00", end: "00:00", }, events: events.map((event) => ({ ...event, start: format(new Date(event.start), "yyyy-MM-dd HH:mm"), end: format(new Date(event.end), "yyyy-MM-dd HH:mm"), })), callbacks: { onEventClick(event, e) { setEventSelected(event as ICalendarEvent); }, async onEventUpdate(newEvent) { await handleEventUpdate(newEvent as ICalendarEvent); }, }, }, plugins, ); useEffect(() => { calendar?.events.getAll(); }, []); useEffect(() => { calendar?.setTheme(resolvedTheme === "dark" ? "dark" : "light"); }, [resolvedTheme]); const AddButton: React.FC = () => ( ); return (
{newEvent && ( { setNewEvent((e) => (open ? e : null)); }} event={newEvent} onSubmitEvent={async (eventFormValues) => { const rrule = mapFrequencyToRrule( eventFormValues.frequency, eventFormValues.frequencyEndDate, ); try { const event: Omit = { ...newEvent, start: `${eventFormValues.startDate} ${eventFormValues.startTime}`, end: `${eventFormValues.endDate} ${eventFormValues.endTime}`, title: `${eventFormValues.title}`, fullDay: eventFormValues.fullDay, rrule: rrule, isVisible: eventFormValues.isVisible, }; const res = await request( `/events/new`, { method: "POST", body: event, requiresAuth: true, csrfToken: false, }, ); if (res.status === "Error") { console.log("Error"); } if (res.status === "Success") { mutate?.(); console.log("Success"); } } catch (e) { console.log(e); } }} /> )} {eventSelected && ( { setEventSelected((e) => (open ? e : null)); }} event={eventSelected} onSubmitEvent={(eventForm) => { console.log("Event form: " + eventForm); }} onDelete={async () => { calendar?.events?.remove(eventSelected.id); try { const res = await request( `/events/${eventSelected.id}/delete`, { method: "DELETE", body: eventSelected, requiresAuth: false, csrfToken: false, }, ); if (res.status === "Error") { console.log("Error"); } if (res.status === "Success") { console.log("Success"); } } catch (e) { console.log(e); } setEventSelected(null); }} onUpdate={async () => { await handleEventUpdate(eventSelected); setEventSelected(null); }} /> )}
); }; const EventDialog: React.FC< { onSubmitEvent: (eventFormValues: EventFormValues) => void; onDelete?: () => void; onUpdate?: () => void; onAdd?: () => void; event: ICalendarEvent | Omit; } & DialogProps > = ({ open, onOpenChange, onSubmitEvent, onDelete, onUpdate, onAdd, event, }) => { return ( {event.title} {event.description} {onUpdate && ( )} {onDelete && ( )} {onAdd && !onUpdate && !onDelete && ( )} ); }; export default Planning;