"use client"; import { useState, useEffect } from "react"; import { useSession } from "next-auth/react"; import { redirect } from "next/navigation"; import { ResponsiveIframe } from "@/app/components/responsive-iframe"; import { Users, FolderKanban, Video, ArrowLeft, Loader2, Calendar, Clock, Plus, X } from "lucide-react"; import { Button } from "@/components/ui/button"; import { useToast } from "@/components/ui/use-toast"; import { Calendar as CalendarComponent } from "@/components/ui/calendar"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Badge } from "@/components/ui/badge"; interface Group { id: string; name: string; path: string; } interface Mission { id: string; name: string; logoUrl?: string | null; } interface ScheduledMeeting { id: string; type: "group" | "mission"; entityId: string; entityName: string; date: string; // ISO date string time: string; // HH:mm format title?: string; } type ConferenceType = "group" | "mission" | null; export default function VisionPage() { const { data: session, status } = useSession(); const { toast } = useToast(); const [groups, setGroups] = useState([]); const [missions, setMissions] = useState([]); const [loading, setLoading] = useState(true); const [selectedConference, setSelectedConference] = useState<{ type: ConferenceType; id: string; name: string; } | null>(null); const [jitsiUrl, setJitsiUrl] = useState(null); const [scheduledMeetings, setScheduledMeetings] = useState([]); const [showMeetingDialog, setShowMeetingDialog] = useState(false); const [selectedDate, setSelectedDate] = useState(new Date()); const [meetingForm, setMeetingForm] = useState<{ type: "group" | "mission" | ""; entityId: string; entityName: string; date: string; time: string; title: string; }>({ type: "", entityId: "", entityName: "", date: "", time: "", title: "", }); // Redirect if not authenticated useEffect(() => { if (status === "unauthenticated") { redirect("/signin"); } }, [status]); // Load scheduled meetings from localStorage useEffect(() => { if (status === "authenticated" && session?.user?.id) { const stored = localStorage.getItem(`meetings_${session.user.id}`); if (stored) { try { setScheduledMeetings(JSON.parse(stored)); } catch (e) { console.error("Error loading meetings:", e); } } } }, [session, status]); // Save scheduled meetings to localStorage useEffect(() => { if (status === "authenticated" && session?.user?.id && scheduledMeetings.length >= 0) { localStorage.setItem(`meetings_${session.user.id}`, JSON.stringify(scheduledMeetings)); } }, [scheduledMeetings, session, status]); // Fetch user groups and missions useEffect(() => { const fetchData = async () => { if (status !== "authenticated" || !session?.user?.id) { return; } try { setLoading(true); const userId = session.user.id; // Fetch user groups const groupsRes = await fetch(`/api/users/${userId}/groups`); if (groupsRes.ok) { const groupsData = await groupsRes.json(); setGroups(Array.isArray(groupsData) ? groupsData : []); } else { console.error("Failed to fetch groups"); } // Fetch all missions and filter for user's missions const missionsRes = await fetch("/api/missions?limit=1000"); if (missionsRes.ok) { const missionsData = await missionsRes.json(); const allMissions = missionsData.missions || []; // Filter missions where user is creator or member const userMissions = allMissions.filter((mission: any) => { const isCreator = mission.creator?.id === userId; const isMember = mission.missionUsers?.some( (mu: any) => mu.user?.id === userId ); return isCreator || isMember; }); setMissions(userMissions); } else { console.error("Failed to fetch missions"); } } catch (error) { console.error("Error fetching data:", error); toast({ title: "Erreur", description: "Impossible de charger les données", variant: "destructive", }); } finally { setLoading(false); } }; fetchData(); }, [session, status, toast]); // Handle conference selection const handleConferenceClick = (type: ConferenceType, id: string, name: string) => { const baseUrl = process.env.NEXT_PUBLIC_IFRAME_CONFERENCE_URL || 'https://vision.slm-lab.net'; let url: string; if (type === "group") { // URL format: https://vision.slm-lab.net/Groupe-{groupId} url = `${baseUrl}/Groupe-${id}`; } else { // URL format: https://vision.slm-lab.net/{missionId} url = `${baseUrl}/${id}`; } setSelectedConference({ type, id, name }); setJitsiUrl(url); }; // Handle back to list const handleBack = () => { setSelectedConference(null); setJitsiUrl(null); }; // Get today's meetings const getTodayMeetings = (): ScheduledMeeting[] => { const today = new Date(); const todayStr = today.toISOString().split('T')[0]; return scheduledMeetings.filter(meeting => meeting.date === todayStr); }; // Get meetings for a specific date const getMeetingsForDate = (date: Date): ScheduledMeeting[] => { const dateStr = date.toISOString().split('T')[0]; return scheduledMeetings.filter(meeting => meeting.date === dateStr); }; // Handle open meeting dialog const handleOpenMeetingDialog = (type: "group" | "mission", id: string, name: string) => { setMeetingForm({ type, entityId: id, entityName: name, date: selectedDate ? selectedDate.toISOString().split('T')[0] : new Date().toISOString().split('T')[0], time: "", title: "", }); setShowMeetingDialog(true); }; // Handle save meeting const handleSaveMeeting = () => { if (!meetingForm.type || !meetingForm.entityId || !meetingForm.date || !meetingForm.time) { toast({ title: "Erreur", description: "Veuillez remplir tous les champs requis", variant: "destructive", }); return; } const newMeeting: ScheduledMeeting = { id: `${Date.now()}-${Math.random()}`, type: meetingForm.type, entityId: meetingForm.entityId, entityName: meetingForm.entityName, date: meetingForm.date, time: meetingForm.time, title: meetingForm.title || `${meetingForm.type === "group" ? "Groupe" : "Mission"}: ${meetingForm.entityName}`, }; setScheduledMeetings([...scheduledMeetings, newMeeting]); setShowMeetingDialog(false); setMeetingForm({ type: "", entityId: "", entityName: "", date: "", time: "", title: "", }); toast({ title: "Succès", description: "Réunion planifiée avec succès", }); }; // Handle delete meeting const handleDeleteMeeting = (meetingId: string) => { setScheduledMeetings(scheduledMeetings.filter(m => m.id !== meetingId)); toast({ title: "Succès", description: "Réunion supprimée", }); }; // Format date for display const formatDate = (dateStr: string): string => { const date = new Date(dateStr); return date.toLocaleDateString('fr-FR', { weekday: 'long', day: 'numeric', month: 'long' }); }; // Show loading state if (status === "loading" || loading) { return (

Chargement...

); } // Show Jitsi iframe if conference is selected if (selectedConference && jitsiUrl) { return (
{/* Header with back button */}

{selectedConference.type === "group" ? "Groupe" : "Mission"}: {selectedConference.name}

{/* Jitsi iframe */}
); } // Show list of groups and missions const todayMeetings = getTodayMeetings(); return (
{/* Header */}

Espaces de réunion

Sélectionnez un groupe ou une mission pour accéder à son espace de réunion Jitsi

{/* Today's Meetings Section */} {todayMeetings.length > 0 && (

Réunions du jour ({todayMeetings.length})

{todayMeetings.map((meeting) => (

{meeting.title || `${meeting.type === "group" ? "Groupe" : "Mission"}: ${meeting.entityName}`}

{meeting.time} - {formatDate(meeting.date)}

))}
)} {/* Calendar Section */}

Calendrier des réunions

{/* Colonne calendrier (étroite) */}