diff --git a/app/vision/page.tsx b/app/vision/page.tsx index e0af7f3..3515d53 100644 --- a/app/vision/page.tsx +++ b/app/vision/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useEffect } from "react"; +import { useState, useEffect, useCallback } from "react"; import { useSession } from "next-auth/react"; import { redirect } from "next/navigation"; import { ResponsiveIframe } from "@/app/components/responsive-iframe"; @@ -197,39 +197,70 @@ export default function VisionPage() { return meetings; }; - // Load meetings from database (events from group and mission calendars) - useEffect(() => { - const fetchMeetings = async () => { - if (status !== "authenticated" || !session?.user?.id) { - return; - } + // Function to fetch and refresh meetings from database + const fetchMeetings = useCallback(async (showLoading = true) => { + if (status !== "authenticated" || !session?.user?.id) { + return; + } - try { + try { + if (showLoading) { setMeetingsLoading(true); - // Fetch calendars with events - const calendarsResponse = await fetch("/api/calendars"); - if (!calendarsResponse.ok) { - throw new Error("Impossible de charger les calendriers"); - } - const calendarsData = await calendarsResponse.json(); + } + // Fetch calendars with events, use refresh=true to bypass cache + const calendarsResponse = await fetch("/api/calendars?refresh=true"); + if (!calendarsResponse.ok) { + throw new Error("Impossible de charger les calendriers"); + } + const calendarsData = await calendarsResponse.json(); - const meetings = convertCalendarsToMeetings(calendarsData); - setScheduledMeetings(meetings); - } catch (error) { - console.error("Error loading meetings:", error); - toast({ - title: "Erreur", - description: "Impossible de charger les réunions", - variant: "destructive", - }); - } finally { + const meetings = convertCalendarsToMeetings(calendarsData); + + // Debug log + console.log('[Vision] Loaded meetings:', { + totalMeetings: meetings.length, + todayMeetings: meetings.filter(m => m.date === formatDateLocal(new Date())).length, + meetings: meetings.map(m => ({ + id: m.id, + title: m.title, + date: m.date, + time: m.time, + type: m.type, + entityId: m.entityId, + entityName: m.entityName, + start: m.start, + end: m.end, + location: m.location + })) + }); + + setScheduledMeetings(meetings); + } catch (error) { + console.error("Error loading meetings:", error); + toast({ + title: "Erreur", + description: "Impossible de charger les réunions", + variant: "destructive", + }); + } finally { + if (showLoading) { setMeetingsLoading(false); } - }; - - fetchMeetings(); + } }, [session, status, groups, missions, toast]); + // Load meetings from database (events from group and mission calendars) + useEffect(() => { + fetchMeetings(); + + // Refresh meetings every minute to update "Rejoindre" button status + const interval = setInterval(() => { + fetchMeetings(false); // Don't show loading spinner on auto-refresh + }, 60000); // Every minute + + return () => clearInterval(interval); + }, [fetchMeetings]); + // Fetch user groups and missions useEffect(() => { const fetchData = async () => { @@ -321,10 +352,25 @@ export default function VisionPage() { // Check if meeting can be joined (5 minutes before start until end) const canJoinMeeting = (meeting: ScheduledMeeting): boolean => { + if (!meeting.start || !meeting.end) { + console.warn('[Vision] canJoinMeeting: missing start or end', meeting); + return false; + } + const now = new Date(); const start = new Date(meeting.start); const end = new Date(meeting.end); + // Validate dates + if (isNaN(start.getTime()) || isNaN(end.getTime())) { + console.warn('[Vision] canJoinMeeting: invalid dates', { + meetingId: meeting.id, + start: meeting.start, + end: meeting.end + }); + return false; + } + // Calculate 5 minutes before start const fiveMinutesBeforeStart = new Date(start); fiveMinutesBeforeStart.setMinutes(fiveMinutesBeforeStart.getMinutes() - 5); @@ -332,18 +378,27 @@ export default function VisionPage() { // Can join if now is between 5 minutes before start and end const canJoin = now >= fiveMinutesBeforeStart && now <= end; - // Debug log - if (meeting.date === formatDateLocal(now)) { + // Debug log for today's meetings + const today = formatDateLocal(now); + if (meeting.date === today) { console.log('[Vision] canJoinMeeting check:', { meetingId: meeting.id, title: meeting.title, + date: meeting.date, + time: meeting.time, now: now.toISOString(), + nowLocal: now.toString(), start: start.toISOString(), + startLocal: start.toString(), end: end.toISOString(), + endLocal: end.toString(), fiveMinutesBeforeStart: fiveMinutesBeforeStart.toISOString(), + fiveMinutesBeforeStartLocal: fiveMinutesBeforeStart.toString(), canJoin, nowVsFiveMinBefore: now >= fiveMinutesBeforeStart, - nowVsEnd: now <= end + nowVsEnd: now <= end, + timeDiff: (now.getTime() - fiveMinutesBeforeStart.getTime()) / 1000 / 60, // minutes + location: meeting.location }); } @@ -589,30 +644,7 @@ export default function VisionPage() { await Promise.all(eventPromises); // Refresh meetings from database after creation - // Use refresh=true to bypass cache and ensure immediate update - const refreshCalendarsResponse = await fetch("/api/calendars?refresh=true"); - if (refreshCalendarsResponse.ok) { - const calendarsData = await refreshCalendarsResponse.json(); - const meetings = convertCalendarsToMeetings(calendarsData); - - // Debug log - console.log('[Vision] Refreshed meetings after creation:', { - totalMeetings: meetings.length, - meetings: meetings.map(m => ({ - id: m.id, - title: m.title, - date: m.date, - time: m.time, - type: m.type, - entityId: m.entityId, - entityName: m.entityName, - start: m.start, - end: m.end - })) - }); - - setScheduledMeetings(meetings); - } + await fetchMeetings(false); // Don't show loading spinner setShowMeetingDialog(false); setMeetingForm({ type: "", @@ -652,13 +684,7 @@ export default function VisionPage() { } // Refresh meetings from database after deletion - // Use refresh=true to bypass cache and ensure immediate update - const refreshCalendarsResponse = await fetch("/api/calendars?refresh=true"); - if (refreshCalendarsResponse.ok) { - const calendarsData = await refreshCalendarsResponse.json(); - const meetings = convertCalendarsToMeetings(calendarsData); - setScheduledMeetings(meetings); - } + await fetchMeetings(false); // Don't show loading spinner toast({ title: "Succès", @@ -773,7 +799,7 @@ export default function VisionPage() {