calendar 35
This commit is contained in:
parent
9736b05ad4
commit
f53b6556a1
@ -771,7 +771,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
|
|||||||
end: new Date(eventForm.end).toISOString(),
|
end: new Date(eventForm.end).toISOString(),
|
||||||
allDay: eventForm.allDay,
|
allDay: eventForm.allDay,
|
||||||
location: eventForm.location,
|
location: eventForm.location,
|
||||||
calendarId: selectedCalendarId,
|
calendarId: selectedCalendarId,
|
||||||
userId
|
userId
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -897,9 +897,9 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
|
|||||||
// Update CalendarSelector to handle visibility
|
// Update CalendarSelector to handle visibility
|
||||||
const CalendarSelector = () => (
|
const CalendarSelector = () => (
|
||||||
<div className="flex flex-wrap items-center gap-2 mb-4">
|
<div className="flex flex-wrap items-center gap-2 mb-4">
|
||||||
{calendars.map((calendar) => (
|
{calendars.map((calendar) => (
|
||||||
<div key={calendar.id} className="relative group">
|
<div key={calendar.id} className="relative group">
|
||||||
<Button
|
<Button
|
||||||
variant={visibleCalendarIds.includes(calendar.id) ? "secondary" : "ghost"}
|
variant={visibleCalendarIds.includes(calendar.id) ? "secondary" : "ghost"}
|
||||||
className="flex items-center gap-2 pr-8"
|
className="flex items-center gap-2 pr-8"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -920,9 +920,9 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
|
|||||||
<Check className="h-4 w-4" />
|
<Check className="h-4 w-4" />
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
{calendar.name !== "Calendrier principal" && (
|
{calendar.name !== "Calendrier principal" && (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="absolute right-0 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity"
|
className="absolute right-0 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity"
|
||||||
@ -933,7 +933,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Settings className="h-4 w-4" />
|
<Settings className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -988,110 +988,74 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col md:flex-row h-full gap-4 p-4">
|
<div className="space-y-4">
|
||||||
{/* Sidebar */}
|
<Card className="p-4">
|
||||||
<div className="w-full md:w-64 space-y-4">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<Card className="p-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="flex items-center justify-between mb-4">
|
<Button
|
||||||
<div className="flex items-center gap-4">
|
variant="outline"
|
||||||
<Button
|
onClick={() => {
|
||||||
variant="outline"
|
setSelectedCalendar(null);
|
||||||
onClick={() => {
|
setIsCalendarModalOpen(true);
|
||||||
setSelectedCalendar(null);
|
}}
|
||||||
setIsCalendarModalOpen(true);
|
className="bg-white hover:bg-gray-50 text-gray-900 border-gray-200"
|
||||||
}}
|
>
|
||||||
className="bg-white hover:bg-gray-50 text-gray-900 border-gray-200"
|
<Plus className="mr-2 h-4 w-4" />
|
||||||
>
|
<span className="font-medium">Nouveau calendrier</span>
|
||||||
<Plus className="mr-2 h-4 w-4" />
|
</Button>
|
||||||
<span className="font-medium">Nouveau calendrier</span>
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedEvent(null);
|
setSelectedEvent(null);
|
||||||
setEventForm({
|
setEventForm({
|
||||||
title: "",
|
title: "",
|
||||||
description: null,
|
description: null,
|
||||||
start: "",
|
start: "",
|
||||||
end: "",
|
end: "",
|
||||||
allDay: false,
|
allDay: false,
|
||||||
location: null,
|
location: null,
|
||||||
calendarId: selectedCalendarId
|
calendarId: selectedCalendarId
|
||||||
});
|
});
|
||||||
setIsEventModalOpen(true);
|
setIsEventModalOpen(true);
|
||||||
}}
|
}}
|
||||||
className="bg-primary hover:bg-primary/90 text-white"
|
className="bg-primary hover:bg-primary/90 text-white"
|
||||||
>
|
>
|
||||||
<Plus className="mr-2 h-4 w-4" />
|
<Plus className="mr-2 h-4 w-4" />
|
||||||
<span className="font-medium">Nouvel événement</span>
|
<span className="font-medium">Nouvel événement</span>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Tabs value={view} className="w-auto">
|
<Tabs value={view} className="w-auto">
|
||||||
<TabsList>
|
<TabsList>
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="dayGridMonth"
|
value="dayGridMonth"
|
||||||
onClick={() => handleViewChange("dayGridMonth")}
|
onClick={() => handleViewChange("dayGridMonth")}
|
||||||
>
|
>
|
||||||
Mois
|
Mois
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="timeGridWeek"
|
value="timeGridWeek"
|
||||||
onClick={() => handleViewChange("timeGridWeek")}
|
onClick={() => handleViewChange("timeGridWeek")}
|
||||||
>
|
>
|
||||||
Semaine
|
Semaine
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="timeGridDay"
|
value="timeGridDay"
|
||||||
onClick={() => handleViewChange("timeGridDay")}
|
onClick={() => handleViewChange("timeGridDay")}
|
||||||
>
|
>
|
||||||
Jour
|
Jour
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CalendarSelector />
|
<CalendarSelector />
|
||||||
</Card>
|
|
||||||
|
|
||||||
<StatisticsPanel statistics={statistics} />
|
{loading ? (
|
||||||
|
<div className="h-96 flex items-center justify-center">
|
||||||
|
<Loader2 className="h-8 w-8 animate-spin text-primary" />
|
||||||
|
<span className="ml-2">Chargement des événements...</span>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
{/* Calendar */}
|
|
||||||
<div className="flex-1 bg-white rounded-lg shadow">
|
|
||||||
<style jsx global>{`
|
|
||||||
.fc-daygrid-day-events {
|
|
||||||
max-height: 80px;
|
|
||||||
overflow-y: auto;
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fc-daygrid-day-events::-webkit-scrollbar {
|
|
||||||
width: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fc-daygrid-day-events::-webkit-scrollbar-track {
|
|
||||||
background: #f1f1f1;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fc-daygrid-day-events::-webkit-scrollbar-thumb {
|
|
||||||
background: #888;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fc-daygrid-day-events::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fc .fc-daygrid-event-harness {
|
|
||||||
margin-bottom: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fc-daygrid-day-frame {
|
|
||||||
min-height: 100px !important;
|
|
||||||
height: 100px !important;
|
|
||||||
}
|
|
||||||
`}</style>
|
|
||||||
<FullCalendar
|
<FullCalendar
|
||||||
ref={calendarRef}
|
ref={calendarRef}
|
||||||
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
|
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
|
||||||
@ -1101,75 +1065,76 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
|
|||||||
center: "title",
|
center: "title",
|
||||||
right: "",
|
right: "",
|
||||||
}}
|
}}
|
||||||
events={calendars
|
events={calendars
|
||||||
.filter(cal => visibleCalendarIds.includes(cal.id))
|
.filter(cal => visibleCalendarIds.includes(cal.id))
|
||||||
.flatMap(cal =>
|
.flatMap(cal =>
|
||||||
(cal.events || []).map(event => ({
|
(cal.events || []).map(event => ({
|
||||||
id: event.id,
|
id: event.id,
|
||||||
title: event.title,
|
title: event.title,
|
||||||
start: new Date(event.start),
|
start: new Date(event.start),
|
||||||
end: new Date(event.end),
|
end: new Date(event.end),
|
||||||
allDay: event.isAllDay,
|
allDay: event.isAllDay,
|
||||||
description: event.description,
|
description: event.description,
|
||||||
location: event.location,
|
location: event.location,
|
||||||
calendarId: event.calendarId,
|
|
||||||
backgroundColor: cal.color,
|
|
||||||
borderColor: cal.color,
|
|
||||||
textColor: '#ffffff',
|
|
||||||
extendedProps: {
|
|
||||||
location: event.location,
|
|
||||||
description: event.description,
|
|
||||||
calendarId: event.calendarId,
|
calendarId: event.calendarId,
|
||||||
originalEvent: event
|
backgroundColor: cal.color,
|
||||||
}
|
borderColor: cal.color,
|
||||||
}))
|
textColor: '#ffffff',
|
||||||
)}
|
extendedProps: {
|
||||||
eventContent={(arg) => (
|
location: event.location,
|
||||||
<div className="p-1 overflow-hidden">
|
description: event.description,
|
||||||
<div className="font-semibold truncate">{arg.event.title}</div>
|
calendarId: event.calendarId,
|
||||||
{!arg.event.allDay && (
|
originalEvent: event
|
||||||
<div className="text-xs opacity-90">
|
}
|
||||||
{new Date(arg.event.start).toLocaleTimeString('fr-FR', {
|
}))
|
||||||
hour: '2-digit',
|
)}
|
||||||
minute: '2-digit'
|
eventContent={(arg) => (
|
||||||
})}
|
<div className="p-1 overflow-hidden">
|
||||||
{arg.event.end && (
|
<div className="font-semibold truncate">{arg.event.title}</div>
|
||||||
<> - {new Date(arg.event.end).toLocaleTimeString('fr-FR', {
|
{!arg.event.allDay && (
|
||||||
|
<div className="text-xs opacity-90">
|
||||||
|
{new Date(arg.event.start).toLocaleTimeString('fr-FR', {
|
||||||
hour: '2-digit',
|
hour: '2-digit',
|
||||||
minute: '2-digit'
|
minute: '2-digit'
|
||||||
})}</>
|
})}
|
||||||
)}
|
{arg.event.end && (
|
||||||
</div>
|
<> - {new Date(arg.event.end).toLocaleTimeString('fr-FR', {
|
||||||
)}
|
hour: '2-digit',
|
||||||
{arg.event.extendedProps.location && (
|
minute: '2-digit'
|
||||||
<div className="text-xs opacity-75 truncate">
|
})}</>
|
||||||
<MapPin className="inline-block w-3 h-3 mr-1" />
|
)}
|
||||||
{arg.event.extendedProps.location}
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
{arg.event.extendedProps.location && (
|
||||||
</div>
|
<div className="text-xs opacity-75 truncate">
|
||||||
)}
|
<MapPin className="inline-block w-3 h-3 mr-1" />
|
||||||
eventClassNames="rounded-md shadow-sm hover:shadow-md transition-shadow cursor-pointer"
|
{arg.event.extendedProps.location}
|
||||||
locale={frLocale}
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
eventClassNames="rounded-md shadow-sm hover:shadow-md transition-shadow cursor-pointer"
|
||||||
|
locale={frLocale}
|
||||||
selectable={true}
|
selectable={true}
|
||||||
selectMirror={true}
|
selectMirror={true}
|
||||||
dayMaxEvents={false}
|
dayMaxEvents={true}
|
||||||
weekends={true}
|
weekends={true}
|
||||||
select={handleDateSelect}
|
select={handleDateSelect}
|
||||||
eventClick={handleEventClick}
|
eventClick={handleEventClick}
|
||||||
height="auto"
|
height="auto"
|
||||||
aspectRatio={1.8}
|
aspectRatio={1.8}
|
||||||
slotMinTime="06:00:00"
|
slotMinTime="06:00:00"
|
||||||
slotMaxTime="22:00:00"
|
slotMaxTime="22:00:00"
|
||||||
allDaySlot={true}
|
allDaySlot={true}
|
||||||
allDayText="Toute la journée"
|
allDayText="Toute la journée"
|
||||||
slotLabelFormat={{
|
slotLabelFormat={{
|
||||||
hour: '2-digit',
|
hour: '2-digit',
|
||||||
minute: '2-digit',
|
minute: '2-digit',
|
||||||
hour12: false
|
hour12: false
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
)}
|
||||||
|
</Card>
|
||||||
|
|
||||||
{/* Calendar dialog */}
|
{/* Calendar dialog */}
|
||||||
<CalendarDialog
|
<CalendarDialog
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user