diff --git a/components/calendar/calendar-client.tsx b/components/calendar/calendar-client.tsx
index c29215b0..36cf1e09 100644
--- a/components/calendar/calendar-client.tsx
+++ b/components/calendar/calendar-client.tsx
@@ -9,12 +9,35 @@ import frLocale from "@fullcalendar/core/locales/fr";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { Loader2, Plus, Calendar as CalendarIcon, Check, X } from "lucide-react";
+import {
+ Loader2,
+ Plus,
+ Calendar as CalendarIcon,
+ Check,
+ X,
+ User,
+ Clock,
+ BarChart2,
+ Settings,
+ ChevronRight,
+ ChevronLeft,
+ Bell,
+ Users,
+ MapPin,
+ Tag,
+ ChevronDown,
+ ChevronUp
+} from "lucide-react";
import { Calendar, Event } from "@prisma/client";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
+import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
+import { Badge } from "@/components/ui/badge";
+import { ScrollArea } from "@/components/ui/scroll-area";
+import { Separator } from "@/components/ui/separator";
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
// Predefined professional color palette
const colorPalette = [
@@ -35,6 +58,11 @@ const colorPalette = [
interface CalendarClientProps {
initialCalendars: (Calendar & { events: Event[] })[];
userId: string;
+ userProfile: {
+ name: string;
+ email: string;
+ avatar?: string;
+ };
}
interface EventFormData {
@@ -233,7 +261,136 @@ function CalendarDialog({ open, onClose, onSave, initialData }: CalendarDialogPr
);
}
-export function CalendarClient({ initialCalendars, userId }: CalendarClientProps) {
+function StatisticsPanel({ statistics }: {
+ statistics: {
+ totalEvents: number;
+ upcomingEvents: number;
+ completedEvents: number;
+ meetingHours: number;
+ };
+}) {
+ return (
+
+
+
+
+
+
+
+
Total Événements
+
{statistics.totalEvents}
+
+
+
+
+
+
+
+
+
+
Heures de Réunion
+
{statistics.meetingHours}h
+
+
+
+
+
+
+
+
+
+
Prochains Événements
+
{statistics.upcomingEvents}
+
+
+
+
+
+
+
+
+
+
Événements Terminés
+
{statistics.completedEvents}
+
+
+
+
+ );
+}
+
+function EventPreview({ event, calendar }: { event: Event; calendar: Calendar }) {
+ const [isExpanded, setIsExpanded] = useState(false);
+
+ return (
+
+
+
+
{event.title}
+
+
+
+ {new Date(event.start).toLocaleDateString('fr-FR', {
+ weekday: 'long',
+ day: 'numeric',
+ month: 'long',
+ hour: '2-digit',
+ minute: '2-digit'
+ })}
+
+
+
+
+
+
+
+
+
+ {isExpanded && (
+
+ {event.description && (
+
{event.description}
+ )}
+
+
+ {event.location && (
+
+
+ {event.location}
+
+ )}
+ {event.calendarId && (
+
+
+ {calendar.name}
+
+ )}
+
+
+
+
+
+
+
+ )}
+
+ );
+}
+
+export function CalendarClient({ initialCalendars, userId, userProfile }: CalendarClientProps) {
const [calendars, setCalendars] = useState(initialCalendars);
const [selectedCalendarId, setSelectedCalendarId] = useState(
initialCalendars[0]?.id || ""
@@ -254,6 +411,29 @@ export function CalendarClient({ initialCalendars, userId }: CalendarClientProps
location: null,
});
+ const [selectedEventPreview, setSelectedEventPreview] = useState(null);
+ const [statistics, setStatistics] = useState({
+ totalEvents: initialCalendars.reduce((acc, cal) => acc + cal.events.length, 0),
+ upcomingEvents: initialCalendars.reduce((acc, cal) =>
+ acc + cal.events.filter(e => new Date(e.start) > new Date()).length, 0
+ ),
+ completedEvents: initialCalendars.reduce((acc, cal) =>
+ acc + cal.events.filter(e => new Date(e.end) < new Date()).length, 0
+ ),
+ meetingHours: initialCalendars.reduce((acc, cal) =>
+ acc + cal.events.reduce((hours, e) => {
+ const duration = (new Date(e.end).getTime() - new Date(e.start).getTime()) / (1000 * 60 * 60);
+ return hours + duration;
+ }, 0)
+ , 0)
+ });
+
+ const upcomingEvents = initialCalendars
+ .flatMap(cal => cal.events)
+ .filter(event => new Date(event.start) > new Date())
+ .sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime())
+ .slice(0, 5);
+
const calendarRef = useRef(null);
const handleCalendarSave = async (calendarData: Partial) => {
@@ -412,114 +592,161 @@ export function CalendarClient({ initialCalendars, userId }: CalendarClientProps
return (
- {error && (
-
- {error}
-
- )}
-
- {/* Calendar management */}
-
-
- {calendars.map((calendar) => (
-
- ))}
-
-
-
-
+
- {/* View selector */}
-
-
- handleViewChange("dayGridMonth")}
- >
- Mois
-
- handleViewChange("timeGridWeek")}
- >
- Semaine
-
- handleViewChange("timeGridDay")}
- >
- Jour
-
-
+
+
+
+
+
+
+
+
- {/* Calendar display */}
-
- {loading ? (
-
-
- Chargement des événements...
+
+
+ handleViewChange("dayGridMonth")}
+ >
+ Mois
+
+ handleViewChange("timeGridWeek")}
+ >
+ Semaine
+
+ handleViewChange("timeGridDay")}
+ >
+ Jour
+
+
+
- ) : (
-
- cal.events.map(event => ({
- id: event.id,
- title: event.title,
- start: event.start,
- end: event.end,
- allDay: event.isAllDay,
- description: event.description,
- location: event.location,
- calendarId: event.calendarId,
- originalEvent: event,
- backgroundColor: cal.color,
- }))
- )}
- locale={frLocale}
- selectable={true}
- selectMirror={true}
- dayMaxEvents={true}
- weekends={true}
- select={handleDateSelect}
- eventClick={handleEventClick}
- height="auto"
- aspectRatio={1.8}
+
+ {loading ? (
+
+
+ Chargement des événements...
+
+ ) : (
+
+ cal.events.map(event => ({
+ id: event.id,
+ title: event.title,
+ start: event.start,
+ end: event.end,
+ allDay: event.isAllDay,
+ description: event.description,
+ location: event.location,
+ calendarId: event.calendarId,
+ originalEvent: event,
+ backgroundColor: cal.color,
+ textColor: '#ffffff',
+ borderColor: cal.color,
+ }))
+ )}
+ locale={frLocale}
+ selectable={true}
+ selectMirror={true}
+ dayMaxEvents={true}
+ weekends={true}
+ select={handleDateSelect}
+ eventClick={(clickInfo) => {
+ handleEventClick(clickInfo);
+ setSelectedEventPreview(clickInfo.event.extendedProps.originalEvent);
+ }}
+ height="auto"
+ aspectRatio={1.8}
+ />
+ )}
+
+
+
+
+ {selectedEventPreview ? (
+
c.id === selectedEventPreview.calendarId)!}
/>
+ ) : (
+
+
+
Mini-calendrier
+
+ cal.events.map(event => ({
+ id: event.id,
+ title: event.title,
+ start: event.start,
+ end: event.end,
+ backgroundColor: cal.color,
+ }))
+ )}
+ locale={frLocale}
+ />
+
+
)}
-
-
+
+
+ Calendriers
+
+ {calendars.map((calendar) => (
+
+ ))}
+
+
+
+
{/* Calendar dialog */}