Neah version calendar fix 3 debuger ????

This commit is contained in:
alma 2025-04-16 21:59:33 +02:00
parent 1198883064
commit 0b19056473

View File

@ -28,7 +28,7 @@ import {
ChevronDown, ChevronDown,
ChevronUp ChevronUp
} from "lucide-react"; } from "lucide-react";
import { Calendar, Event } from "@prisma/client"; import { Calendar as CalendarType, Event as EventType } from "@prisma/client";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
@ -62,8 +62,16 @@ const colorPalette = [
"#2563eb", // Blue "#2563eb", // Blue
]; ];
interface Calendar extends CalendarType {
events: Event[];
}
interface Event extends EventType {
// No additional fields needed as we're extending from Prisma's Event type
}
interface CalendarClientProps { interface CalendarClientProps {
initialCalendars: (Calendar & { events: Event[] })[]; initialCalendars: Calendar[];
userId: string; userId: string;
userProfile: { userProfile: {
name: string; name: string;
@ -431,164 +439,67 @@ function EventPreview({ event, calendar }: { event: Event; calendar: Calendar })
} }
export function CalendarClient({ initialCalendars, userId, userProfile }: CalendarClientProps) { export function CalendarClient({ initialCalendars, userId, userProfile }: CalendarClientProps) {
const [calendars, setCalendars] = useState(initialCalendars.map(cal => ({ const [calendars, setCalendars] = useState<Calendar[]>(initialCalendars);
...cal, const [selectedCalendarId, setSelectedCalendarId] = useState<string | null>(null);
events: cal.events || []
})));
const [selectedCalendarId, setSelectedCalendarId] = useState<string>(
initialCalendars[0]?.id || ""
);
const [view, setView] = useState<"dayGridMonth" | "timeGridWeek" | "timeGridDay">("dayGridMonth"); const [view, setView] = useState<"dayGridMonth" | "timeGridWeek" | "timeGridDay">("dayGridMonth");
const [isEventModalOpen, setIsEventModalOpen] = useState(false);
const [isCalendarModalOpen, setIsCalendarModalOpen] = useState(false);
const [selectedEvent, setSelectedEvent] = useState<Event | null>(null);
const [selectedCalendar, setSelectedCalendar] = useState<Calendar | null>(null);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [eventForm, setEventForm] = useState<EventFormData>({ const [selectedEvent, setSelectedEvent] = useState<Event | null>(null);
title: "", const [isEventDialogOpen, setIsEventDialogOpen] = useState(false);
description: null, const [isCalendarDialogOpen, setIsCalendarDialogOpen] = useState(false);
start: "", const [selectedDate, setSelectedDate] = useState<Date | null>(null);
end: "",
allDay: false,
location: null,
calendarId: selectedCalendarId
});
const [selectedEventPreview, setSelectedEventPreview] = useState<Event | null>(null);
const [upcomingEvents, setUpcomingEvents] = useState<Event[]>([]);
const [statistics, setStatistics] = useState({
totalEvents: 0,
upcomingEvents: 0,
completedEvents: 0,
meetingHours: 0
});
const [visibleCalendarIds, setVisibleCalendarIds] = useState<string[]>([]);
// Update useEffect to initialize visible calendars and fetch events
useEffect(() => {
if (calendars.length > 0) {
setVisibleCalendarIds(calendars.map(cal => cal.id));
updateStatistics();
updateUpcomingEvents();
}
}, [calendars]);
const updateStatistics = () => {
const now = new Date();
const stats = {
totalEvents: 0,
upcomingEvents: 0,
completedEvents: 0,
meetingHours: 0
};
calendars.forEach(cal => {
cal.events.forEach(event => {
stats.totalEvents++;
const eventStart = new Date(event.start);
const eventEnd = new Date(event.end);
if (eventStart > now) {
stats.upcomingEvents++;
} else if (eventEnd < now) {
stats.completedEvents++;
}
const duration = (eventEnd.getTime() - eventStart.getTime()) / (1000 * 60 * 60);
stats.meetingHours += duration;
});
});
setStatistics(stats);
};
const updateUpcomingEvents = () => {
const now = new Date();
const upcoming = calendars
.flatMap(cal => cal.events)
.filter(event => new Date(event.start) > now)
.sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime())
.slice(0, 5);
setUpcomingEvents(upcoming);
};
const fetchCalendars = async () => { const fetchCalendars = async () => {
try { try {
setLoading(true); setLoading(true);
const response = await fetch("/api/calendars", { const response = await fetch('/api/calendars', {
credentials: 'include' credentials: 'include'
}); });
if (!response.ok) throw new Error("Failed to fetch calendars");
const data = await response.json();
console.log("Raw calendars data:", data);
// Process calendars and events if (!response.ok) {
const processedCalendars = data.map((cal: Calendar & { events: Event[] }) => ({ throw new Error('Failed to fetch calendars');
...cal,
events: Array.isArray(cal.events) ? cal.events.map(event => ({
...event,
start: new Date(event.start),
end: new Date(event.end)
})) : []
}));
console.log("Setting calendars with processed events:", processedCalendars);
setCalendars(processedCalendars);
// Update statistics and upcoming events
updateStatistics();
updateUpcomingEvents();
// Force calendar refresh
if (calendarRef.current) {
const calendarApi = calendarRef.current.getApi();
calendarApi.refetchEvents();
} }
} catch (error) {
console.error("Error fetching calendars:", error); const data = await response.json();
setError(error instanceof Error ? error.message : "Failed to fetch calendars"); setCalendars(data);
setError(null);
} catch (err) {
setError('Failed to load calendars');
console.error('Error fetching calendars:', err);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
const calendarRef = useRef<any>(null);
const handleCalendarSelect = (calendarId: string) => { const handleCalendarSelect = (calendarId: string) => {
console.log("Calendar selected:", calendarId);
setSelectedCalendarId(calendarId); setSelectedCalendarId(calendarId);
setEventForm(prev => ({
...prev,
calendarId: calendarId
}));
}; };
const handleCalendarSave = async (calendarData: Partial<Calendar>) => { const handleCalendarSave = async (calendarData: Partial<Calendar>) => {
try { try {
setLoading(true); setLoading(true);
const response = await fetch("/api/calendars", { const response = await fetch('/api/calendars', {
method: calendarData.id ? "PUT" : "POST", method: 'POST',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
}, },
credentials: 'include',
body: JSON.stringify({ body: JSON.stringify({
...calendarData, ...calendarData,
userId, userId,
}), }),
credentials: 'include'
}); });
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to save calendar"); throw new Error('Failed to save calendar');
} }
await fetchCalendars(); const newCalendar = await response.json();
setIsCalendarModalOpen(false); setCalendars(prev => [...prev, newCalendar]);
} catch (error) { setError(null);
console.error("Error saving calendar:", error); } catch (err) {
setError(error instanceof Error ? error.message : "Failed to save calendar"); setError('Failed to save calendar');
console.error('Error saving calendar:', err);
} finally { } finally {
setLoading(false); setLoading(false);
} }
@ -598,212 +509,100 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
try { try {
setLoading(true); setLoading(true);
const response = await fetch(`/api/calendars/${calendarId}`, { const response = await fetch(`/api/calendars/${calendarId}`, {
method: "DELETE", method: 'DELETE',
credentials: 'include' credentials: 'include'
}); });
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete calendar"); throw new Error('Failed to delete calendar');
} }
await fetchCalendars(); setCalendars(prev => prev.filter(cal => cal.id !== calendarId));
setIsCalendarModalOpen(false); setError(null);
} catch (err) {
// If the deleted calendar was selected, select another one setError('Failed to delete calendar');
if (selectedCalendarId === calendarId) { console.error('Error deleting calendar:', err);
const remainingCalendars = calendars.filter(cal => cal.id !== calendarId);
setSelectedCalendarId(remainingCalendars[0]?.id || "");
}
} catch (error) {
console.error("Error deleting calendar:", error);
setError(error instanceof Error ? error.message : "Failed to delete calendar");
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
const handleDateSelect = (selectInfo: any) => { const handleDateSelect = (selectInfo: any) => {
const startDate = new Date(selectInfo.start); setSelectedDate(selectInfo.start);
const endDate = new Date(selectInfo.end); setIsEventDialogOpen(true);
console.log("Date select handler - Current state:", {
calendars: calendars.map(c => ({ id: c.id, name: c.name })),
selectedCalendarId,
availableCalendars: calendars.length
});
// If no calendar is selected, use the first available calendar
if (!selectedCalendarId && calendars.length > 0) {
const firstCalendar = calendars[0];
console.log("No calendar selected, selecting first calendar:", firstCalendar);
setSelectedCalendarId(firstCalendar.id);
setEventForm({
title: "",
description: null,
start: startDate.toISOString(),
end: endDate.toISOString(),
allDay: selectInfo.allDay,
location: null,
calendarId: firstCalendar.id
});
} else {
setEventForm({
title: "",
description: null,
start: startDate.toISOString(),
end: endDate.toISOString(),
allDay: selectInfo.allDay,
location: null,
calendarId: selectedCalendarId
});
}
setIsEventModalOpen(true);
}; };
const handleEventClick = (clickInfo: any) => { const handleEventClick = (clickInfo: any) => {
const event = clickInfo.event; setSelectedEvent(clickInfo.event);
const startDate = new Date(event.start); setIsEventDialogOpen(true);
const endDate = new Date(event.end || event.start);
setSelectedEvent(event.extendedProps.originalEvent);
setEventForm({
title: event.title,
description: event.extendedProps.description,
start: startDate.toISOString().slice(0, 16),
end: endDate.toISOString().slice(0, 16),
allDay: event.isAllDay,
location: event.extendedProps.location,
calendarId: event.extendedProps.calendarId,
});
setIsEventModalOpen(true);
}; };
const handleEventSubmit = async () => { const handleEventSubmit = async (event: React.MouseEvent<HTMLButtonElement>) => {
try { try {
// Validate required fields including calendar setLoading(true);
if (!eventForm.title || !eventForm.start || !eventForm.end || !eventForm.calendarId) { if (!selectedEvent) {
console.log("Form validation failed:", { throw new Error('No event selected');
title: eventForm.title,
start: eventForm.start,
end: eventForm.end,
calendarId: eventForm.calendarId
});
setError("Veuillez remplir tous les champs obligatoires et sélectionner un calendrier");
return;
} }
setLoading(true);
const eventData = { const eventData = {
...eventForm, ...selectedEvent,
start: new Date(eventForm.start).toISOString(), start: selectedEvent.start ? new Date(selectedEvent.start).toISOString() : null,
end: new Date(eventForm.end).toISOString(), end: selectedEvent.end ? new Date(selectedEvent.end).toISOString() : null,
userId, userId,
...(selectedEvent ? { id: selectedEvent.id } : {}), // Include ID for updates
allDay: eventForm.allDay // Use allDay instead of isAllDay
}; };
console.log("Submitting event with data:", eventData); const response = await fetch('/api/events', {
method: 'POST',
const response = await fetch("/api/events", {
method: selectedEvent ? "PUT" : "POST",
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
}, },
body: JSON.stringify(eventData), body: JSON.stringify(eventData),
credentials: 'include'
}); });
const responseData = await response.json();
console.log("Response from server:", responseData);
if (!response.ok) { if (!response.ok) {
console.error("Error response:", responseData); throw new Error('Failed to save event');
throw new Error(responseData.error || "Failed to save event");
} }
// Reset form and close modal first const newEvent = await response.json();
setIsEventModalOpen(false); setCalendars(prev => prev.map(cal => {
setEventForm({ if (cal.id === newEvent.calendarId) {
title: "",
description: null,
start: "",
end: "",
allDay: false,
location: null,
calendarId: selectedCalendarId
});
setSelectedEvent(null);
setError(null);
// Update calendars state with the new event
const updatedCalendars = calendars.map(cal => {
if (cal.id === eventData.calendarId) {
return { return {
...cal, ...cal,
events: [...cal.events, responseData] events: [...cal.events, newEvent],
}; };
} }
return cal; return cal;
}); }));
setCalendars(updatedCalendars); setError(null);
} catch (err) {
// Fetch fresh data to ensure all calendars are up to date setError('Failed to save event');
await fetchCalendars(); console.error('Error saving event:', err);
} catch (error) {
console.error("Error saving event:", error);
setError(error instanceof Error ? error.message : "Failed to save event");
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
const handleEventDelete = async () => { const handleEventDelete = async (eventId: string) => {
if (!selectedEvent?.id) return;
if (!confirm("Êtes-vous sûr de vouloir supprimer cet événement ?")) {
return;
}
try { try {
setLoading(true); setLoading(true);
const response = await fetch(`/api/events/${selectedEvent.id}`, { const response = await fetch(`/api/events/${eventId}`, {
method: "DELETE", method: 'DELETE',
credentials: 'include'
}); });
if (!response.ok) { if (!response.ok) {
const error = await response.json(); throw new Error('Failed to delete event');
throw new Error(error.message || "Failed to delete event");
} }
// Remove the event from local state setCalendars(prev => prev.map(cal => ({
const updatedCalendars = calendars.map(cal => ({
...cal, ...cal,
events: cal.events.filter(e => e.id !== selectedEvent.id) events: cal.events.filter(event => event.id !== eventId),
})); })));
setCalendars(updatedCalendars); setError(null);
} catch (err) {
// Close modal and reset form setError('Failed to delete event');
setIsEventModalOpen(false); console.error('Error deleting event:', err);
setSelectedEvent(null);
setEventForm({
title: "",
description: null,
start: "",
end: "",
allDay: false,
location: null,
calendarId: selectedCalendarId
});
// Force calendar refresh
if (calendarRef.current) {
const calendarApi = calendarRef.current.getApi();
calendarApi.refetchEvents();
}
} catch (error) {
console.error("Error deleting event:", error);
setError(error instanceof Error ? error.message : "Failed to delete event");
} finally { } finally {
setLoading(false); setLoading(false);
} }
@ -811,112 +610,6 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
const handleViewChange = (newView: "dayGridMonth" | "timeGridWeek" | "timeGridDay") => { const handleViewChange = (newView: "dayGridMonth" | "timeGridWeek" | "timeGridDay") => {
setView(newView); setView(newView);
if (calendarRef.current) {
const calendarApi = calendarRef.current.getApi();
calendarApi.changeView(newView);
}
};
// Update CalendarSelector to handle visibility
const CalendarSelector = () => (
<div className="flex flex-wrap items-center gap-2 mb-4">
{calendars.map((calendar) => (
<div key={calendar.id} className="relative group">
<Button
variant={visibleCalendarIds.includes(calendar.id) ? "secondary" : "ghost"}
className="flex items-center gap-2 pr-8"
onClick={() => {
if (visibleCalendarIds.includes(calendar.id)) {
setVisibleCalendarIds(visibleCalendarIds.filter(id => id !== calendar.id));
} else {
setVisibleCalendarIds([...visibleCalendarIds, calendar.id]);
}
}}
>
<div
className="w-3 h-3 rounded-full"
style={{ backgroundColor: calendar.color }}
/>
<span>{calendar.name}</span>
<div className="ml-2">
{visibleCalendarIds.includes(calendar.id) ? (
<Check className="h-4 w-4" />
) : null}
</div>
</Button>
{calendar.name !== "Calendrier principal" && (
<Button
variant="ghost"
size="icon"
className="absolute right-0 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity"
onClick={(e) => {
e.stopPropagation();
setSelectedCalendar(calendar);
setIsCalendarModalOpen(true);
}}
>
<Settings className="h-4 w-4" />
</Button>
)}
</div>
))}
</div>
);
// Add these helper functions for date handling
const getDateFromString = (dateString: string) => {
return dateString ? new Date(dateString) : new Date();
};
const handleStartDateChange = (date: Date | null) => {
if (!date) return;
const endDate = getDateFromString(eventForm.end);
if (date > endDate) {
// If start date is after end date, set end date to start date + 1 hour
const newEndDate = new Date(date);
newEndDate.setHours(date.getHours() + 1);
setEventForm({
...eventForm,
start: date.toISOString(),
end: newEndDate.toISOString(),
});
} else {
setEventForm({
...eventForm,
start: date.toISOString(),
});
}
};
const handleEndDateChange = (date: Date | null) => {
if (!date) return;
const startDate = getDateFromString(eventForm.start);
if (date < startDate) {
// If end date is before start date, set start date to end date - 1 hour
const newStartDate = new Date(date);
newStartDate.setHours(date.getHours() - 1);
setEventForm({
...eventForm,
start: newStartDate.toISOString(),
end: date.toISOString(),
});
} else {
setEventForm({
...eventForm,
end: date.toISOString(),
});
}
};
// Update the date handlers to maintain consistent time format
const formatTimeForInput = (date: Date) => {
return date.toLocaleTimeString('fr-FR', {
hour: '2-digit',
minute: '2-digit',
hour12: false
});
}; };
return ( return (
@ -927,8 +620,8 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<Button <Button
variant="outline" variant="outline"
onClick={() => { onClick={() => {
setSelectedCalendar(null); setSelectedCalendarId(null);
setIsCalendarModalOpen(true); setIsCalendarDialogOpen(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"
> >
@ -938,16 +631,8 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<Button <Button
onClick={() => { onClick={() => {
setSelectedEvent(null); setSelectedEvent(null);
setEventForm({ setSelectedDate(new Date());
title: "", setIsEventDialogOpen(true);
description: null,
start: new Date().toISOString(),
end: new Date(new Date().setHours(new Date().getHours() + 1)).toISOString(),
allDay: false,
location: null,
calendarId: selectedCalendarId
});
setIsEventModalOpen(true);
}} }}
className="bg-primary hover:bg-primary/90 text-white" className="bg-primary hover:bg-primary/90 text-white"
> >
@ -980,8 +665,6 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
</Tabs> </Tabs>
</div> </div>
<CalendarSelector />
<style jsx global>{` <style jsx global>{`
/* Fixed height and scrolling for day cells only */ /* Fixed height and scrolling for day cells only */
.fc .fc-daygrid-day-frame { .fc .fc-daygrid-day-frame {
@ -1030,7 +713,6 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
</div> </div>
) : ( ) : (
<FullCalendar <FullCalendar
ref={calendarRef}
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]} plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
initialView={view} initialView={view}
headerToolbar={{ headerToolbar={{
@ -1039,7 +721,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
right: "", right: "",
}} }}
events={calendars events={calendars
.filter(cal => visibleCalendarIds.includes(cal.id)) .filter(cal => selectedCalendarId === cal.id)
.flatMap(cal => .flatMap(cal =>
(cal.events || []).map(event => ({ (cal.events || []).map(event => ({
id: event.id, id: event.id,
@ -1150,26 +832,18 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
{/* Calendar dialog */} {/* Calendar dialog */}
<CalendarDialog <CalendarDialog
open={isCalendarModalOpen} open={isCalendarDialogOpen}
onClose={() => setIsCalendarModalOpen(false)} onClose={() => setIsCalendarDialogOpen(false)}
onSave={handleCalendarSave} onSave={handleCalendarSave}
onDelete={handleCalendarDelete} onDelete={handleCalendarDelete}
initialData={selectedCalendar || undefined} initialData={calendars.find(cal => cal.id === selectedCalendarId) || undefined}
/> />
{/* Event dialog */} {/* Event dialog */}
<Dialog open={isEventModalOpen} onOpenChange={(open) => { <Dialog open={isEventDialogOpen} onOpenChange={(open) => {
if (!open) { if (!open) {
setIsEventModalOpen(false); setIsEventDialogOpen(false);
setEventForm({ setSelectedDate(null);
title: "",
description: null,
start: "",
end: "",
allDay: false,
location: null,
calendarId: selectedCalendarId || calendars[0]?.id
});
setSelectedEvent(null); setSelectedEvent(null);
setError(null); setError(null);
} }
@ -1194,8 +868,12 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<Input <Input
id="title" id="title"
placeholder="Titre de l'événement" placeholder="Titre de l'événement"
value={eventForm.title} value={selectedEvent?.title || ""}
onChange={(e) => setEventForm({ ...eventForm, title: e.target.value })} onChange={(e) => {
if (selectedEvent) {
setSelectedEvent({ ...selectedEvent, title: e.target.value });
}
}}
/> />
</div> </div>
@ -1207,13 +885,10 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
key={cal.id} key={cal.id}
type="button" type="button"
onClick={() => { onClick={() => {
setEventForm(prev => ({ setSelectedCalendarId(cal.id);
...prev,
calendarId: cal.id
}));
}} }}
className={`flex items-center gap-2 px-3 py-2 rounded-lg transition-all ${ className={`flex items-center gap-2 px-3 py-2 rounded-lg transition-all ${
eventForm.calendarId === cal.id selectedCalendarId === cal.id
? 'bg-white ring-2 ring-primary' ? 'bg-white ring-2 ring-primary'
: 'bg-gray-900 hover:bg-gray-800' : 'bg-gray-900 hover:bg-gray-800'
}`} }`}
@ -1223,7 +898,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
style={{ backgroundColor: cal.color }} style={{ backgroundColor: cal.color }}
/> />
<span className={`text-sm ${ <span className={`text-sm ${
eventForm.calendarId === cal.id selectedCalendarId === cal.id
? 'font-medium text-gray-900' ? 'font-medium text-gray-900'
: 'text-gray-100' : 'text-gray-100'
}`}> }`}>
@ -1240,8 +915,13 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<div className="flex gap-2"> <div className="flex gap-2">
<div className="flex-1"> <div className="flex-1">
<DatePicker <DatePicker
selected={getDateFromString(eventForm.start)} selected={selectedDate ? new Date(selectedDate) : undefined}
onChange={handleStartDateChange} onChange={(date) => {
if (date && selectedEvent) {
setSelectedDate(date);
setSelectedEvent({ ...selectedEvent, start: date });
}
}}
dateFormat="dd/MM/yyyy" dateFormat="dd/MM/yyyy"
locale="fr" 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" className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary"
@ -1250,8 +930,13 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
/> />
</div> </div>
<DatePicker <DatePicker
selected={getDateFromString(eventForm.start)} selected={selectedDate ? new Date(selectedDate) : undefined}
onChange={handleStartDateChange} onChange={(date) => {
if (date && selectedEvent) {
setSelectedDate(date);
setSelectedEvent({ ...selectedEvent, start: date });
}
}}
showTimeSelect showTimeSelect
showTimeSelectOnly showTimeSelectOnly
timeIntervals={15} timeIntervals={15}
@ -1268,19 +953,29 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<div className="flex gap-2"> <div className="flex gap-2">
<div className="flex-1"> <div className="flex-1">
<DatePicker <DatePicker
selected={getDateFromString(eventForm.end)} selected={selectedDate ? new Date(selectedDate) : undefined}
onChange={handleEndDateChange} onChange={(date) => {
if (date && selectedEvent) {
setSelectedDate(date);
setSelectedEvent({ ...selectedEvent, end: date });
}
}}
dateFormat="dd/MM/yyyy" dateFormat="dd/MM/yyyy"
locale="fr" 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" className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary"
placeholderText="Date" placeholderText="Date"
customInput={<Input />} customInput={<Input />}
minDate={getDateFromString(eventForm.start)} minDate={selectedDate}
/> />
</div> </div>
<DatePicker <DatePicker
selected={getDateFromString(eventForm.end)} selected={selectedDate ? new Date(selectedDate) : undefined}
onChange={handleEndDateChange} onChange={(date) => {
if (date && selectedEvent) {
setSelectedDate(date);
setSelectedEvent({ ...selectedEvent, end: date });
}
}}
showTimeSelect showTimeSelect
showTimeSelectOnly showTimeSelectOnly
timeIntervals={15} timeIntervals={15}
@ -1297,10 +992,12 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Checkbox <Checkbox
id="allDay" id="allDay"
checked={eventForm.allDay} checked={selectedEvent?.isAllDay || false}
onCheckedChange={(checked) => onCheckedChange={(checked) => {
setEventForm({ ...eventForm, allDay: checked as boolean }) if (selectedEvent) {
setSelectedEvent({ ...selectedEvent, isAllDay: checked as boolean });
} }
}}
/> />
<Label htmlFor="allDay">Toute la journée</Label> <Label htmlFor="allDay">Toute la journée</Label>
</div> </div>
@ -1308,10 +1005,12 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<div className="space-y-2"> <div className="space-y-2">
<Label>Lieu</Label> <Label>Lieu</Label>
<Input <Input
value={eventForm.location || ""} value={selectedEvent?.location || ""}
onChange={(e) => onChange={(e) => {
setEventForm({ ...eventForm, location: e.target.value }) if (selectedEvent) {
setSelectedEvent({ ...selectedEvent, location: e.target.value });
} }
}}
placeholder="Ajouter un lieu" placeholder="Ajouter un lieu"
/> />
</div> </div>
@ -1319,10 +1018,12 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<div className="space-y-2"> <div className="space-y-2">
<Label>Description</Label> <Label>Description</Label>
<Textarea <Textarea
value={eventForm.description || ""} value={selectedEvent?.description || ""}
onChange={(e) => onChange={(e) => {
setEventForm({ ...eventForm, description: e.target.value }) if (selectedEvent) {
setSelectedEvent({ ...selectedEvent, description: e.target.value });
} }
}}
placeholder="Ajouter une description" placeholder="Ajouter une description"
/> />
</div> </div>
@ -1332,7 +1033,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
{selectedEvent && ( {selectedEvent && (
<Button <Button
variant="destructive" variant="destructive"
onClick={handleEventDelete} onClick={() => handleEventDelete(selectedEvent.id)}
disabled={loading} disabled={loading}
> >
{loading ? ( {loading ? (
@ -1348,22 +1049,16 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
<div className="flex space-x-2"> <div className="flex space-x-2">
<Button <Button
variant="outline" variant="outline"
onClick={() => setIsEventModalOpen(false)} onClick={() => setIsEventDialogOpen(false)}
disabled={loading} disabled={loading}
> >
Annuler Annuler
</Button> </Button>
<Button onClick={handleEventSubmit} disabled={loading}> <Button
{loading ? ( onClick={handleEventSubmit}
<> disabled={loading}
<Loader2 className="mr-2 h-4 w-4 animate-spin" /> >
Enregistrement... {loading ? 'Enregistrement...' : 'Enregistrer'}
</>
) : selectedEvent ? (
"Mettre à jour"
) : (
"Créer"
)}
</Button> </Button>
</div> </div>
</DialogFooter> </DialogFooter>