vision refactor
This commit is contained in:
parent
607f762a40
commit
b185c130c9
@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { ResponsiveIframe } from "@/app/components/responsive-iframe";
|
import { ResponsiveIframe } from "@/app/components/responsive-iframe";
|
||||||
@ -197,23 +197,43 @@ export default function VisionPage() {
|
|||||||
return meetings;
|
return meetings;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Load meetings from database (events from group and mission calendars)
|
// Function to fetch and refresh meetings from database
|
||||||
useEffect(() => {
|
const fetchMeetings = useCallback(async (showLoading = true) => {
|
||||||
const fetchMeetings = async () => {
|
|
||||||
if (status !== "authenticated" || !session?.user?.id) {
|
if (status !== "authenticated" || !session?.user?.id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (showLoading) {
|
||||||
setMeetingsLoading(true);
|
setMeetingsLoading(true);
|
||||||
// Fetch calendars with events
|
}
|
||||||
const calendarsResponse = await fetch("/api/calendars");
|
// Fetch calendars with events, use refresh=true to bypass cache
|
||||||
|
const calendarsResponse = await fetch("/api/calendars?refresh=true");
|
||||||
if (!calendarsResponse.ok) {
|
if (!calendarsResponse.ok) {
|
||||||
throw new Error("Impossible de charger les calendriers");
|
throw new Error("Impossible de charger les calendriers");
|
||||||
}
|
}
|
||||||
const calendarsData = await calendarsResponse.json();
|
const calendarsData = await calendarsResponse.json();
|
||||||
|
|
||||||
const meetings = convertCalendarsToMeetings(calendarsData);
|
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);
|
setScheduledMeetings(meetings);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error loading meetings:", error);
|
console.error("Error loading meetings:", error);
|
||||||
@ -223,13 +243,24 @@ export default function VisionPage() {
|
|||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
|
if (showLoading) {
|
||||||
setMeetingsLoading(false);
|
setMeetingsLoading(false);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
fetchMeetings();
|
|
||||||
}, [session, status, groups, missions, toast]);
|
}, [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
|
// Fetch user groups and missions
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
@ -321,10 +352,25 @@ export default function VisionPage() {
|
|||||||
|
|
||||||
// Check if meeting can be joined (5 minutes before start until end)
|
// Check if meeting can be joined (5 minutes before start until end)
|
||||||
const canJoinMeeting = (meeting: ScheduledMeeting): boolean => {
|
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 now = new Date();
|
||||||
const start = new Date(meeting.start);
|
const start = new Date(meeting.start);
|
||||||
const end = new Date(meeting.end);
|
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
|
// Calculate 5 minutes before start
|
||||||
const fiveMinutesBeforeStart = new Date(start);
|
const fiveMinutesBeforeStart = new Date(start);
|
||||||
fiveMinutesBeforeStart.setMinutes(fiveMinutesBeforeStart.getMinutes() - 5);
|
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
|
// Can join if now is between 5 minutes before start and end
|
||||||
const canJoin = now >= fiveMinutesBeforeStart && now <= end;
|
const canJoin = now >= fiveMinutesBeforeStart && now <= end;
|
||||||
|
|
||||||
// Debug log
|
// Debug log for today's meetings
|
||||||
if (meeting.date === formatDateLocal(now)) {
|
const today = formatDateLocal(now);
|
||||||
|
if (meeting.date === today) {
|
||||||
console.log('[Vision] canJoinMeeting check:', {
|
console.log('[Vision] canJoinMeeting check:', {
|
||||||
meetingId: meeting.id,
|
meetingId: meeting.id,
|
||||||
title: meeting.title,
|
title: meeting.title,
|
||||||
|
date: meeting.date,
|
||||||
|
time: meeting.time,
|
||||||
now: now.toISOString(),
|
now: now.toISOString(),
|
||||||
|
nowLocal: now.toString(),
|
||||||
start: start.toISOString(),
|
start: start.toISOString(),
|
||||||
|
startLocal: start.toString(),
|
||||||
end: end.toISOString(),
|
end: end.toISOString(),
|
||||||
|
endLocal: end.toString(),
|
||||||
fiveMinutesBeforeStart: fiveMinutesBeforeStart.toISOString(),
|
fiveMinutesBeforeStart: fiveMinutesBeforeStart.toISOString(),
|
||||||
|
fiveMinutesBeforeStartLocal: fiveMinutesBeforeStart.toString(),
|
||||||
canJoin,
|
canJoin,
|
||||||
nowVsFiveMinBefore: now >= fiveMinutesBeforeStart,
|
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);
|
await Promise.all(eventPromises);
|
||||||
|
|
||||||
// Refresh meetings from database after creation
|
// Refresh meetings from database after creation
|
||||||
// Use refresh=true to bypass cache and ensure immediate update
|
await fetchMeetings(false); // Don't show loading spinner
|
||||||
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);
|
|
||||||
}
|
|
||||||
setShowMeetingDialog(false);
|
setShowMeetingDialog(false);
|
||||||
setMeetingForm({
|
setMeetingForm({
|
||||||
type: "",
|
type: "",
|
||||||
@ -652,13 +684,7 @@ export default function VisionPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Refresh meetings from database after deletion
|
// Refresh meetings from database after deletion
|
||||||
// Use refresh=true to bypass cache and ensure immediate update
|
await fetchMeetings(false); // Don't show loading spinner
|
||||||
const refreshCalendarsResponse = await fetch("/api/calendars?refresh=true");
|
|
||||||
if (refreshCalendarsResponse.ok) {
|
|
||||||
const calendarsData = await refreshCalendarsResponse.json();
|
|
||||||
const meetings = convertCalendarsToMeetings(calendarsData);
|
|
||||||
setScheduledMeetings(meetings);
|
|
||||||
}
|
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: "Succès",
|
title: "Succès",
|
||||||
@ -773,7 +799,7 @@ export default function VisionPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{canJoinMeeting(meeting) && (
|
{canJoinMeeting(meeting) && meeting.location ? (
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
className="bg-blue-600 hover:bg-blue-700 text-white"
|
className="bg-blue-600 hover:bg-blue-700 text-white"
|
||||||
@ -782,6 +808,10 @@ export default function VisionPage() {
|
|||||||
<Video className="h-4 w-4 mr-1" />
|
<Video className="h-4 w-4 mr-1" />
|
||||||
Rejoindre
|
Rejoindre
|
||||||
</Button>
|
</Button>
|
||||||
|
) : (
|
||||||
|
<span className="text-xs text-gray-400">
|
||||||
|
{!meeting.location ? 'Pas de lien' : 'Bientôt disponible'}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -988,8 +1018,7 @@ export default function VisionPage() {
|
|||||||
{groups.map((group) => (
|
{groups.map((group) => (
|
||||||
<div
|
<div
|
||||||
key={group.id}
|
key={group.id}
|
||||||
className="bg-white rounded-lg border border-gray-200 p-4 hover:shadow-md transition-shadow cursor-pointer"
|
className="bg-white rounded-lg border border-gray-200 p-4 hover:shadow-md transition-shadow"
|
||||||
onClick={() => handleConferenceClick("group", group.id, group.name)}
|
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-3 flex-1">
|
<div className="flex items-center gap-3 flex-1">
|
||||||
@ -1058,8 +1087,7 @@ export default function VisionPage() {
|
|||||||
{missions.map((mission) => (
|
{missions.map((mission) => (
|
||||||
<div
|
<div
|
||||||
key={mission.id}
|
key={mission.id}
|
||||||
className="bg-white rounded-lg border border-gray-200 p-4 hover:shadow-md transition-shadow cursor-pointer"
|
className="bg-white rounded-lg border border-gray-200 p-4 hover:shadow-md transition-shadow"
|
||||||
onClick={() => handleConferenceClick("mission", mission.id, mission.name)}
|
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-3 flex-1">
|
<div className="flex items-center gap-3 flex-1">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user