diff --git a/app/vision/page.tsx b/app/vision/page.tsx index e70424d..8b01049 100644 --- a/app/vision/page.tsx +++ b/app/vision/page.tsx @@ -12,6 +12,20 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from " import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Badge } from "@/components/ui/badge"; +import { Textarea } from "@/components/ui/textarea"; +import { Checkbox } from "@/components/ui/checkbox"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import DatePicker, { registerLocale } from "react-datepicker"; +import "react-datepicker/dist/react-datepicker.css"; +import { fr } from "date-fns/locale"; + +registerLocale('fr', fr); interface Group { id: string; @@ -56,16 +70,24 @@ export default function VisionPage() { type: "group" | "mission" | ""; entityId: string; entityName: string; - date: string; - time: string; title: string; + start: string; + end: string; + allDay: boolean; + location: string; + description: string; + recurrence: "none" | "daily" | "weekly" | "monthly"; }>({ type: "", entityId: "", entityName: "", - date: "", - time: "", title: "", + start: "", + end: "", + allDay: false, + location: "", + description: "", + recurrence: "none", }); // Redirect if not authenticated @@ -186,22 +208,42 @@ export default function VisionPage() { return scheduledMeetings.filter(meeting => meeting.date === dateStr); }; + // Helper function to get date from string + const getDateFromString = (dateString: string): Date | null => { + if (!dateString) return null; + try { + return new Date(dateString); + } catch { + return null; + } + }; + // Handle open meeting dialog const handleOpenMeetingDialog = (type: "group" | "mission", id: string, name: string) => { + const defaultDate = selectedDate || new Date(); + const startDate = new Date(defaultDate); + startDate.setHours(new Date().getHours(), 0, 0, 0); + const endDate = new Date(startDate); + endDate.setHours(startDate.getHours() + 1); + setMeetingForm({ type, entityId: id, entityName: name, - date: selectedDate ? selectedDate.toISOString().split('T')[0] : new Date().toISOString().split('T')[0], - time: "", title: "", + start: startDate.toISOString().slice(0, 16), + end: endDate.toISOString().slice(0, 16), + allDay: false, + location: "", + description: "", + recurrence: "none", }); setShowMeetingDialog(true); }; // Handle save meeting const handleSaveMeeting = () => { - if (!meetingForm.type || !meetingForm.entityId || !meetingForm.date || !meetingForm.time) { + if (!meetingForm.type || !meetingForm.entityId || !meetingForm.start || !meetingForm.end) { toast({ title: "Erreur", description: "Veuillez remplir tous les champs requis", @@ -210,29 +252,74 @@ export default function VisionPage() { 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}`, - }; + const startDate = new Date(meetingForm.start); + const endDate = new Date(meetingForm.end); + + // Create meetings based on recurrence + const meetings: ScheduledMeeting[] = []; + + if (meetingForm.recurrence === "none") { + // Single meeting + const dateStr = startDate.toISOString().split('T')[0]; + const timeStr = meetingForm.allDay ? "" : startDate.toTimeString().slice(0, 5); + + meetings.push({ + id: `${Date.now()}-${Math.random()}`, + type: meetingForm.type, + entityId: meetingForm.entityId, + entityName: meetingForm.entityName, + date: dateStr, + time: timeStr, + title: meetingForm.title || `${meetingForm.type === "group" ? "Groupe" : "Mission"}: ${meetingForm.entityName}`, + }); + } else { + // Recurring meetings - create for next 12 occurrences + const recurrenceCount = 12; + let currentDate = new Date(startDate); + const timeDiff = endDate.getTime() - startDate.getTime(); + + for (let i = 0; i < recurrenceCount; i++) { + const dateStr = currentDate.toISOString().split('T')[0]; + const timeStr = meetingForm.allDay ? "" : currentDate.toTimeString().slice(0, 5); + + meetings.push({ + id: `${Date.now()}-${i}-${Math.random()}`, + type: meetingForm.type, + entityId: meetingForm.entityId, + entityName: meetingForm.entityName, + date: dateStr, + time: timeStr, + title: meetingForm.title || `${meetingForm.type === "group" ? "Groupe" : "Mission"}: ${meetingForm.entityName}`, + }); + + // Calculate next occurrence + if (meetingForm.recurrence === "daily") { + currentDate.setDate(currentDate.getDate() + 1); + } else if (meetingForm.recurrence === "weekly") { + currentDate.setDate(currentDate.getDate() + 7); + } else if (meetingForm.recurrence === "monthly") { + currentDate.setMonth(currentDate.getMonth() + 1); + } + } + } - setScheduledMeetings([...scheduledMeetings, newMeeting]); + setScheduledMeetings([...scheduledMeetings, ...meetings]); setShowMeetingDialog(false); setMeetingForm({ type: "", entityId: "", entityName: "", - date: "", - time: "", title: "", + start: "", + end: "", + allDay: false, + location: "", + description: "", + recurrence: "none", }); toast({ title: "Succès", - description: "Réunion planifiée avec succès", + description: `${meetings.length} réunion${meetings.length > 1 ? 's' : ''} planifiée${meetings.length > 1 ? 's' : ''} avec succès`, }); }; @@ -706,43 +793,177 @@ export default function VisionPage() { {/* Meeting Dialog */} - + - Planifier une réunion + Planifier une réunion
-
- +
+ setMeetingForm({ ...meetingForm, title: e.target.value })} placeholder={`Réunion ${meetingForm.type === "group" ? "du groupe" : "de la mission"}`} - className="mt-1 bg-black text-white border-gray-700 placeholder-gray-400" + className="bg-white text-gray-900" />
-
- + +
+
+ +
+
+ { + if (date) { + const newStart = new Date(date); + if (!meetingForm.allDay) { + const currentStart = getDateFromString(meetingForm.start); + if (currentStart) { + newStart.setHours(currentStart.getHours(), currentStart.getMinutes()); + } + } + setMeetingForm({ ...meetingForm, start: newStart.toISOString().slice(0, 16) }); + } + }} + dateFormat="dd/MM/yyyy" + locale="fr" + className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary bg-white text-gray-900" + placeholderText="Date" + customInput={} + /> +
+ {!meetingForm.allDay && ( + { + if (date) { + const currentStart = getDateFromString(meetingForm.start) || new Date(); + const newStart = new Date(currentStart); + newStart.setHours(date.getHours(), date.getMinutes()); + setMeetingForm({ ...meetingForm, start: newStart.toISOString().slice(0, 16) }); + } + }} + showTimeSelect + showTimeSelectOnly + timeIntervals={15} + timeCaption="Heure" + dateFormat="HH:mm" + className="w-32 bg-white text-gray-900" + customInput={} + /> + )} +
+
+ +
+ +
+
+ { + if (date) { + const newEnd = new Date(date); + if (!meetingForm.allDay) { + const currentEnd = getDateFromString(meetingForm.end); + if (currentEnd) { + newEnd.setHours(currentEnd.getHours(), currentEnd.getMinutes()); + } + } + setMeetingForm({ ...meetingForm, end: newEnd.toISOString().slice(0, 16) }); + } + }} + dateFormat="dd/MM/yyyy" + locale="fr" + className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary bg-white text-gray-900" + placeholderText="Date" + customInput={} + minDate={getDateFromString(meetingForm.start)} + /> +
+ {!meetingForm.allDay && ( + { + if (date) { + const currentEnd = getDateFromString(meetingForm.end) || new Date(); + const newEnd = new Date(currentEnd); + newEnd.setHours(date.getHours(), date.getMinutes()); + setMeetingForm({ ...meetingForm, end: newEnd.toISOString().slice(0, 16) }); + } + }} + showTimeSelect + showTimeSelectOnly + timeIntervals={15} + timeCaption="Heure" + dateFormat="HH:mm" + className="w-32 bg-white text-gray-900" + customInput={} + /> + )} +
+
+
+ +
+ + setMeetingForm({ ...meetingForm, allDay: checked as boolean }) + } + /> + +
+ +
+ setMeetingForm({ ...meetingForm, date: e.target.value })} - className="mt-1 bg-black text-white border-gray-700" - required + value={meetingForm.location} + onChange={(e) => + setMeetingForm({ ...meetingForm, location: e.target.value }) + } + placeholder="Ajouter un lieu" + className="bg-white text-gray-900" />
-
- - setMeetingForm({ ...meetingForm, time: e.target.value })} - className="mt-1 bg-black text-white border-gray-700" - required + +
+ +