'use client'; import { Calendar as RBCalendar, momentLocalizer } from 'react-big-calendar'; import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop'; import moment from 'moment'; import '@/components/react-big-calendar.css'; import 'react-big-calendar/lib/addons/dragAndDrop/styles.css'; import CustomToolbar from '@/components/custom-toolbar'; import React from 'react'; import { useGetApiUserUserCalendar } from '@/generated/api/user/user'; import { useRouter } from 'next/navigation'; import { usePatchApiEventEventID } from '@/generated/api/event/event'; import { useSession } from 'next-auth/react'; import { UserCalendarSchemaItem } from '@/generated/api/meetup.schemas'; import { QueryErrorResetBoundary } from '@tanstack/react-query'; import { ErrorBoundary } from 'react-error-boundary'; import { Button } from '@/components/ui/button'; import { fromZodIssue } from 'zod-validation-error/v4'; import type { $ZodIssue } from 'zod/v4/core'; moment.updateLocale('en', { week: { dow: 1, doy: 4, }, }); const DaDRBCalendar = withDragAndDrop< { id: string; start: Date; end: Date; type: UserCalendarSchemaItem['type']; }, { id: string; title: string; type: UserCalendarSchemaItem['type']; } >(RBCalendar); const localizer = momentLocalizer(moment); export default function Calendar({ userId }: { userId?: string }) { return ( {({ reset }) => ( (
There was an error!

{typeof error === 'string' ? error : error.errors .map((e: $ZodIssue) => fromZodIssue(e).toString()) .join(', ')}

)} > {userId ? ( ) : ( )}
)}
); } function CalendarWithUserEvents({ userId }: { userId: string }) { const sesstion = useSession(); const [currentView, setCurrentView] = React.useState< 'month' | 'week' | 'day' | 'agenda' | 'work_week' >('week'); const [currentDate, setCurrentDate] = React.useState(new Date()); const router = useRouter(); const { data, refetch, error, isError } = useGetApiUserUserCalendar( userId, { start: moment(currentDate) .startOf( currentView === 'agenda' ? 'month' : currentView === 'work_week' ? 'week' : currentView, ) .toISOString(), end: moment(currentDate) .endOf( currentView === 'agenda' ? 'month' : currentView === 'work_week' ? 'week' : currentView, ) .toISOString(), }, { query: { refetchOnWindowFocus: true, refetchOnReconnect: true, refetchOnMount: true, }, }, ); if (isError) { throw error.response?.data || 'Failed to fetch calendar data'; } const { mutate: patchEvent } = usePatchApiEventEventID({ mutation: { throwOnError(error) { throw error.response?.data || 'Failed to update event'; }, }, }); return ( { setCurrentDate(date); }} events={ data?.data.calendar.map((event) => ({ id: event.id, title: event.type === 'event' ? event.title : 'Blocker', start: new Date(event.start_time), end: new Date(event.end_time), type: event.type, })) ?? [] } onSelectEvent={(event) => { router.push(`/events/${event.id}`); }} onSelectSlot={(slotInfo) => { router.push( `/events/new?start=${slotInfo.start.toISOString()}&end=${slotInfo.end.toISOString()}`, ); }} resourceIdAccessor={(event) => event.id} resourceTitleAccessor={(event) => event.title} startAccessor={(event) => event.start} endAccessor={(event) => event.end} selectable={sesstion.data?.user?.id === userId} onEventDrop={(event) => { const { start, end, event: droppedEvent } = event; if (droppedEvent.type === 'blocked_private') return; const startISO = new Date(start).toISOString(); const endISO = new Date(end).toISOString(); patchEvent( { eventID: droppedEvent.id, data: { start_time: startISO, end_time: endISO, }, }, { onSuccess: () => { refetch(); }, onError: (error) => { console.error('Error updating event:', error); }, }, ); }} onEventResize={(event) => { const { start, end, event: resizedEvent } = event; if (resizedEvent.type === 'blocked_private') return; const startISO = new Date(start).toISOString(); const endISO = new Date(end).toISOString(); if (startISO === endISO) { console.warn('Start and end times are the same, skipping resize.'); return; } patchEvent( { eventID: resizedEvent.id, data: { start_time: startISO, end_time: endISO, }, }, { onSuccess: () => { refetch(); }, onError: (error) => { console.error('Error resizing event:', error); }, }, ); }} /> ); } function CalendarWithoutUserEvents() { const [currentView, setCurrentView] = React.useState< 'month' | 'week' | 'day' | 'agenda' | 'work_week' >('week'); const [currentDate, setCurrentDate] = React.useState(new Date()); return ( { setCurrentDate(date); }} /> ); }