import { useState, useEffect } from "react"; import { useSession } from "next-auth/react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Label } from "@/components/ui/label"; import { Checkbox } from "@/components/ui/checkbox"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { format, parseISO } from "date-fns"; import { fr } from "date-fns/locale"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Calendar as CalendarType } from "@prisma/client"; interface EventDialogProps { open: boolean; event?: any; onClose: () => void; onSave: (eventData: any) => Promise; onDelete?: (eventId: string) => Promise; calendars: CalendarType[]; } export function EventDialog({ open, event, onClose, onSave, onDelete, calendars, }: EventDialogProps) { const [title, setTitle] = useState(event?.title || ""); const [description, setDescription] = useState(event?.description || ""); const [location, setLocation] = useState(event?.location || ""); const [start, setStart] = useState(event?.start || ""); const [end, setEnd] = useState(event?.end || ""); const [allDay, setAllDay] = useState(event?.allDay || false); const [calendarId, setCalendarId] = useState(event?.calendarId || ""); const [confirmDelete, setConfirmDelete] = useState(false); const [isVideoConference, setIsVideoConference] = useState(!!event?.location?.includes('vision.slm-lab.net') || !!event?.location?.includes('jitsi')); const { data: session } = useSession(); const [groups, setGroups] = useState>([]); const [missions, setMissions] = useState>([]); // Reset form when event changes useEffect(() => { if (event) { setTitle(event.title || ""); setDescription(event.description || ""); setLocation(event.location || ""); setStart(event.start || ""); setEnd(event.end || ""); setAllDay(event.allDay || false); setCalendarId(event.calendarId || ""); setIsVideoConference(!!event.location?.includes('vision.slm-lab.net') || !!event.location?.includes('jitsi')); } else { // Reset form for new event setTitle(""); setDescription(""); setLocation(""); setStart(""); setEnd(""); setAllDay(false); setCalendarId(""); setIsVideoConference(false); } }, [event]); // Fetch groups and missions when dialog opens useEffect(() => { if (open && session?.user?.id) { const fetchData = async () => { try { // Fetch groups const groupsRes = await fetch(`/api/users/${session.user.id}/groups`); if (groupsRes.ok) { const groupsData = await groupsRes.json(); setGroups(Array.isArray(groupsData) ? groupsData : []); } // Fetch 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 === session.user.id; const isMember = mission.missionUsers?.some( (mu: any) => mu.user?.id === session.user.id ); return isCreator || isMember; }); setMissions(userMissions); } } catch (error) { console.error("Error fetching groups/missions:", error); } }; fetchData(); } }, [open, session]); // Formater les dates pour l'affichage const formatDate = (dateStr: string) => { if (!dateStr) return ""; try { // @ts-ignore const date = parseISO(dateStr); // @ts-ignore return format(date, allDay ? "yyyy-MM-dd" : "yyyy-MM-dd'T'HH:mm", { // @ts-ignore locale: fr, }); } catch (e) { return dateStr; } }; // Gérer le changement de l'option "Toute la journée" const handleAllDayChange = (checked: boolean) => { setAllDay(checked); // Ajuster les dates si nécessaire if (checked && start) { // @ts-ignore const startDate = parseISO(start); // @ts-ignore setStart(format(startDate, "yyyy-MM-dd")); if (end) { // @ts-ignore const endDate = parseISO(end); // @ts-ignore setEnd(format(endDate, "yyyy-MM-dd")); } } }; // Generate Jitsi URL based on calendar type const generateJitsiUrl = (): string => { const selectedCalendar = calendars.find(cal => cal.id === calendarId); if (!selectedCalendar) return ""; const baseUrl = process.env.NEXT_PUBLIC_IFRAME_CONFERENCE_URL || 'https://vision.slm-lab.net'; const calendarName = selectedCalendar.name || ""; // Check if it's a Group calendar if (calendarName.startsWith("Groupe:")) { const groupName = calendarName.replace("Groupe: ", ""); // Find matching group by name to get the real ID const matchingGroup = groups.find((g: { id: string; name: string }) => g.name === groupName); if (matchingGroup) { return `${baseUrl}/Groupe-${matchingGroup.id}`; } // Fallback: use group name as ID (same as vision page fallback) const groupId = groupName.toLowerCase().replace(/\s+/g, '-'); return `${baseUrl}/Groupe-${groupId}`; } // Check if it's a Mission calendar if (calendarName.startsWith("Mission:")) { // Use missionId from calendar if available (most reliable) const missionId = (selectedCalendar as any).missionId; if (missionId) { return `${baseUrl}/${missionId}`; } // Fallback: find matching mission by name const missionName = calendarName.replace("Mission: ", ""); const matchingMission = missions.find((m: { id: string; name: string }) => m.name === missionName); if (matchingMission) { return `${baseUrl}/${matchingMission.id}`; } // Last fallback: use mission name as ID const missionIdFromName = missionName.toLowerCase().replace(/\s+/g, '-'); return `${baseUrl}/${missionIdFromName}`; } // For "Mon Calendrier" or Microsoft calendars, generate a generic Jitsi room // Use a combination of user ID and timestamp for uniqueness const userId = session?.user?.id || 'user'; const timestamp = Date.now(); const randomId = Math.random().toString(36).substring(2, 9); return `${baseUrl}/${randomId}-${timestamp}`; }; // Handle video conference checkbox change const handleVideoConferenceChange = (checked: boolean) => { setIsVideoConference(checked); if (checked) { // Generate Jitsi URL and set it in location const jitsiUrl = generateJitsiUrl(); setLocation(jitsiUrl); } else { // Clear location if unchecking setLocation(""); } }; // Update location when calendar changes and video conference is checked useEffect(() => { if (isVideoConference && calendarId) { const jitsiUrl = generateJitsiUrl(); setLocation(jitsiUrl); } }, [calendarId, isVideoConference]); // Update location when groups/missions are loaded (to get correct IDs for groups/missions) useEffect(() => { if (isVideoConference && calendarId) { const selectedCalendar = calendars.find(cal => cal.id === calendarId); if (selectedCalendar) { const calendarName = selectedCalendar.name || ""; const isGroup = calendarName.startsWith("Groupe:"); const isMission = calendarName.startsWith("Mission:"); // Only update if it's a group/mission and we now have the data if ((isGroup && groups.length > 0) || (isMission && missions.length > 0)) { const jitsiUrl = generateJitsiUrl(); setLocation(jitsiUrl); } } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [groups.length, missions.length]); // Enregistrer l'événement const handleSave = () => { onSave({ id: event?.id, title, description, location, start, end, calendarId, isAllDay: allDay, }); }; // Supprimer l'événement const handleDelete = () => { if (onDelete && event?.id) { onDelete(event.id); } }; return ( <> {event?.id ? "Modifier l'événement" : "Nouvel événement"}
setTitle(e.target.value)} placeholder='Ajouter un titre' required />
{/* Sélection du calendrier */}
setStart(e.target.value)} required />
setEnd(e.target.value)} required />
setLocation(e.target.value)} placeholder={isVideoConference ? 'Lien Jitsi généré automatiquement' : 'Ajouter un lieu'} disabled={isVideoConference} />