From 0f6c48b0a8023d34f5a208965ad8c4276096f86e Mon Sep 17 00:00:00 2001 From: alma Date: Thu, 15 Jan 2026 17:59:17 +0100 Subject: [PATCH] Agenda refactor --- components/calendar/calendar-client.tsx | 297 +++++++++++++++--------- 1 file changed, 181 insertions(+), 116 deletions(-) diff --git a/components/calendar/calendar-client.tsx b/components/calendar/calendar-client.tsx index 80ff6fa..9dc17c0 100644 --- a/components/calendar/calendar-client.tsx +++ b/components/calendar/calendar-client.tsx @@ -783,6 +783,8 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend const [visibleCalendarIds, setVisibleCalendarIds] = useState([]); const [selectedDate, setSelectedDate] = useState(null); + const clickTimerRef = useRef(null); + const lastClickDateRef = useRef(null); // Update useEffect to initialize visible calendars and fetch events useEffect(() => { @@ -793,6 +795,15 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend } }, [calendars]); + // Cleanup timer on unmount + useEffect(() => { + return () => { + if (clickTimerRef.current) { + clearTimeout(clickTimerRef.current); + } + }; + }, []); + const updateStatistics = () => { const now = new Date(); const stats = { @@ -941,14 +952,70 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend }; const handleDateClick = (clickInfo: any) => { - // Set the selected date to show events for that day const clickedDate = new Date(clickInfo.date); - // Reset time to start of day for comparison clickedDate.setHours(0, 0, 0, 0); - setSelectedDate(clickedDate); + + // Check if this is a double click (same date clicked within 300ms) + const now = new Date(); + const isDoubleClick = lastClickDateRef.current && + lastClickDateRef.current.getTime() === clickedDate.getTime() && + now.getTime() - (lastClickDateRef.current as any).clickTime < 300; + + // Clear any pending single click timer + if (clickTimerRef.current) { + clearTimeout(clickTimerRef.current); + clickTimerRef.current = null; + } + + if (isDoubleClick) { + // Double click: Open event form + const startDate = new Date(clickInfo.date); + startDate.setHours(new Date().getHours(), 0, 0, 0); + const endDate = new Date(startDate); + endDate.setHours(startDate.getHours() + 1); + + // If no calendar is selected, use the first available calendar + if (!selectedCalendarId && calendars.length > 0) { + const firstCalendar = calendars[0]; + setSelectedCalendarId(firstCalendar.id); + + setEventForm({ + title: "", + description: null, + start: startDate.toISOString(), + end: endDate.toISOString(), + allDay: false, + location: null, + calendarId: firstCalendar.id + }); + } else { + setEventForm({ + title: "", + description: null, + start: startDate.toISOString(), + end: endDate.toISOString(), + allDay: false, + location: null, + calendarId: selectedCalendarId + }); + } + + setIsEventModalOpen(true); + lastClickDateRef.current = null; + } else { + // Single click: Show events column (with a small delay to allow double click detection) + lastClickDateRef.current = clickedDate; + (lastClickDateRef.current as any).clickTime = now.getTime(); + + clickTimerRef.current = setTimeout(() => { + setSelectedDate(clickedDate); + clickTimerRef.current = null; + }, 300); + } }; const handleDateSelect = (selectInfo: any) => { + // Double click or drag selection: Open event form const startDate = new Date(selectInfo.start); const endDate = new Date(selectInfo.end); @@ -958,7 +1025,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend availableCalendars: calendars.length }); - // Set selected date to show events for the selected day + // Also set selected date to show events for the selected day const selectDate = new Date(startDate); selectDate.setHours(0, 0, 0, 0); setSelectedDate(selectDate); @@ -1320,115 +1387,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend - {/* Middle column for day events */} - {selectedDate && ( -
- -
-

- {selectedDate.toLocaleDateString('fr-FR', { - weekday: 'long', - day: 'numeric', - month: 'long', - year: 'numeric' - })} -

- -
- - {dayEvents.length === 0 ? ( -
- -

Aucun événement ce jour

-
- ) : ( -
- {dayEvents.map((event) => { - const calendar = event.calendar as CalendarWithMission; - const startDate = new Date(event.start); - const endDate = new Date(event.end); - const isAllDay = event.isAllDay; - - return ( - handleEventClick({ event: { - title: event.title, - start: startDate, - end: endDate, - isAllDay: isAllDay, - extendedProps: { - description: event.description, - location: event.location, - calendarId: event.calendarId, - originalEvent: event, - color: calendar.color - } - }})} - > -
-
-
-
-

- {event.title} -

-
-
-
- - - {isAllDay - ? "Toute la journée" - : `${startDate.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })} - ${endDate.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })}` - } - -
- {event.location && ( -
- - {event.location} -
- )} -
- - {getCalendarDisplayName(calendar)} - -
-
-
- - ); - })} -
- )} - - -
- )} - - {/* Right column for calendar view */} + {/* Middle column for calendar view */}
@@ -1693,12 +1652,10 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend ); }} locale={frLocale} - selectable={true} - selectMirror={true} + selectable={false} dayMaxEventRows={false} dayMaxEvents={false} weekends={true} - select={handleDateSelect} eventClick={handleEventClick} height="auto" aspectRatio={1.8} @@ -1727,6 +1684,114 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
+ {/* Right column for day events */} + {selectedDate && ( +
+ +
+

+ {selectedDate.toLocaleDateString('fr-FR', { + weekday: 'long', + day: 'numeric', + month: 'long', + year: 'numeric' + })} +

+ +
+ + {dayEvents.length === 0 ? ( +
+ +

Aucun événement ce jour

+
+ ) : ( +
+ {dayEvents.map((event) => { + const calendar = event.calendar as CalendarWithMission; + const startDate = new Date(event.start); + const endDate = new Date(event.end); + const isAllDay = event.isAllDay; + + return ( + handleEventClick({ event: { + title: event.title, + start: startDate, + end: endDate, + isAllDay: isAllDay, + extendedProps: { + description: event.description, + location: event.location, + calendarId: event.calendarId, + originalEvent: event, + color: calendar.color + } + }})} + > +
+
+
+
+

+ {event.title} +

+
+
+
+ + + {isAllDay + ? "Toute la journée" + : `${startDate.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })} - ${endDate.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })}` + } + +
+ {event.location && ( +
+ + {event.location} +
+ )} +
+ + {getCalendarDisplayName(calendar)} + +
+
+
+ + ); + })} +
+ )} + + +
+ )} + {/* Calendar dialog */}