import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { toast } from 'sonner'; import FullCalendar from '@fullcalendar/react'; import dayGridPlugin from '@fullcalendar/daygrid'; import timeGridPlugin from '@fullcalendar/timegrid'; import interactionPlugin from '@fullcalendar/interaction'; import type { EventClickArg, DateSelectArg, EventDropArg } from '@fullcalendar/core'; import api, { getErrorMessage } from '@/lib/api'; import type { CalendarEvent } from '@/types'; import EventForm from './EventForm'; export default function CalendarPage() { const queryClient = useQueryClient(); const [showForm, setShowForm] = useState(false); const [editingEvent, setEditingEvent] = useState(null); const [selectedDate, setSelectedDate] = useState(null); const { data: events = [] } = useQuery({ queryKey: ['calendar-events'], queryFn: async () => { const { data } = await api.get('/events'); return data; }, }); const eventDropMutation = useMutation({ mutationFn: async ({ id, start, end, allDay }: { id: number; start: string; end: string; allDay: boolean }) => { const response = await api.put(`/events/${id}`, { start_datetime: start, end_datetime: end, all_day: allDay, }); return response.data; }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['calendar-events'] }); toast.success('Event moved'); }, onError: (error) => { queryClient.invalidateQueries({ queryKey: ['calendar-events'] }); toast.error(getErrorMessage(error, 'Failed to move event')); }, }); const calendarEvents = events.map((event) => ({ id: event.id.toString(), title: event.title, start: event.start_datetime, end: event.end_datetime || undefined, allDay: event.all_day, backgroundColor: event.color || 'hsl(var(--accent-color))', borderColor: event.color || 'hsl(var(--accent-color))', })); const handleEventClick = (info: EventClickArg) => { const event = events.find((e) => e.id.toString() === info.event.id); if (event) { setEditingEvent(event); setShowForm(true); } }; const toLocalDatetime = (d: Date): string => { const pad = (n: number) => n.toString().padStart(2, '0'); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`; }; const handleEventDrop = (info: EventDropArg) => { const id = parseInt(info.event.id); const start = info.event.allDay ? info.event.startStr : info.event.start ? toLocalDatetime(info.event.start) : info.event.startStr; const end = info.event.allDay ? info.event.endStr || info.event.startStr : info.event.end ? toLocalDatetime(info.event.end) : start; eventDropMutation.mutate({ id, start, end, allDay: info.event.allDay }); }; const handleDateSelect = (selectInfo: DateSelectArg) => { setSelectedDate(selectInfo.startStr); setShowForm(true); }; const handleCloseForm = () => { setShowForm(false); setEditingEvent(null); setSelectedDate(null); }; return (

Calendar

{showForm && ( )}
); }