Fondation

This commit is contained in:
alma 2026-01-17 03:02:10 +01:00
parent 1e00c2da4e
commit 32e757b3e7

View File

@ -13,8 +13,8 @@ import { useWidgetNotification } from "@/hooks/use-widget-notification";
type Event = { type Event = {
id: string; id: string;
title: string; title: string;
start: Date; start: string | Date;
end: Date; end: string | Date;
isAllDay: boolean; isAllDay: boolean;
calendarId: string; calendarId: string;
calendarName?: string; calendarName?: string;
@ -22,7 +22,7 @@ type Event = {
}; };
export function CalendarWidget() { export function CalendarWidget() {
const { data: session, status: sessionStatus } = useSession(); const { data: session } = useSession();
const [events, setEvents] = useState<Event[]>([]); const [events, setEvents] = useState<Event[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
@ -30,52 +30,32 @@ export function CalendarWidget() {
const lastEventCountRef = useRef<number>(-1); const lastEventCountRef = useRef<number>(-1);
useEffect(() => { useEffect(() => {
console.log("Calendar Widget - Session Status:", sessionStatus); // Ne charger les événements que si l'utilisateur est connecté
console.log("Calendar Widget - Session Data:", session); if (!session) return;
if (sessionStatus === "loading") {
console.log("Calendar Widget - Session is loading");
return;
}
if (sessionStatus !== "authenticated" || !session) {
console.log("Calendar Widget - Not authenticated, skipping fetch");
setLoading(false);
return;
}
const fetchUpcomingEvents = async () => { const fetchUpcomingEvents = async () => {
try { try {
console.log("Calendar Widget - Starting to fetch events");
setLoading(true); setLoading(true);
// Fetch calendars with events
console.log("Calendar Widget - Making API request to /api/calendars");
const response = await fetch('/api/calendars');
if (!response.ok) { // Récupérer d'abord les calendriers de l'utilisateur
console.error("Calendar Widget - API response not OK:", response.status, response.statusText); const calendarsRes = await fetch("/api/calendars");
throw new Error("Impossible de charger les événements");
if (!calendarsRes.ok) {
throw new Error("Impossible de charger les calendriers");
} }
const calendarsData = await response.json(); const calendars = await calendarsRes.json();
console.log("Calendar Widget - Raw calendars data:", calendarsData);
console.log("Calendar Widget - Calendars count:", calendarsData.length); if (calendars.length === 0) {
console.log("Calendar Widget - Events per calendar:", calendarsData.map((cal: any) => ({ setEvents([]);
name: cal.name, setLoading(false);
eventCount: cal.events?.length || 0, return;
events: cal.events?.map((e: any) => ({ id: e.id, title: e.title, start: e.start })) || []
})));
if (!Array.isArray(calendarsData)) {
console.error("Calendar Widget - Calendars data is not an array:", calendarsData);
throw new Error("Format de données invalide");
} }
// Get current date at the start of the day // Date actuelle et date dans 7 jours
const now = new Date(); const now = new Date();
now.setHours(0, 0, 0, 0); const nextWeek = addDays(now, 7);
// Helper function to get display name for calendar // Helper function to get display name for calendar
const getCalendarDisplayName = (calendar: any) => { const getCalendarDisplayName = (calendar: any) => {
// If calendar is synced to an external account, use the account name // If calendar is synced to an external account, use the account name
@ -87,47 +67,57 @@ export function CalendarWidget() {
return calendar.name; return calendar.name;
}; };
// Extract all events and add calendar info // Récupérer les événements pour chaque calendrier
const allEvents = calendarsData.flatMap((calendar) => { const allEventsPromises = calendars.map(async (calendar: any) => {
const displayName = getCalendarDisplayName(calendar); const eventsRes = await fetch(
console.log("Calendar Widget - Processing calendar:", displayName, "Events:", calendar.events?.length || 0); `/api/calendars/${
return (calendar.events || []).map((event: { id: string; title: string; start: string | Date; end: string | Date; isAllDay: boolean; calendarId: string }) => { calendar.id
const startDate = new Date(event.start); }/events?start=${now.toISOString()}&end=${nextWeek.toISOString()}`
const endDate = new Date(event.end); );
return {
id: event.id, if (!eventsRes.ok) {
title: event.title, console.warn(
start: startDate, `Impossible de charger les événements du calendrier ${calendar.id}`
end: endDate, );
isAllDay: event.isAllDay, return [];
calendarId: event.calendarId, }
calendarColor: calendar.color,
calendarName: displayName const events = await eventsRes.json();
};
}); // Ajouter les informations du calendrier à chaque événement
return events.map((event: any) => ({
...event,
calendarName: getCalendarDisplayName(calendar),
calendarColor: calendar.color,
}));
}); });
// Filter for upcoming events (next 7 days, like the old widget) // Attendre toutes les requêtes d'événements
const nextWeek = addDays(now, 7); const allEventsArrays = await Promise.all(allEventsPromises);
const upcomingEvents = allEvents
.filter(event => event.start >= now && event.start <= nextWeek)
.sort((a, b) => a.start.getTime() - b.start.getTime())
.slice(0, 10);
console.log("Calendar Widget - Final upcoming events:", upcomingEvents); // Fusionner tous les événements en un seul tableau
const allEvents = allEventsArrays.flat();
// Trier par date de début
const sortedEvents = allEvents.sort(
(a, b) => new Date(a.start).getTime() - new Date(b.start).getTime()
);
// Limiter à 5 événements pour l'affichage
const upcomingEvents = sortedEvents.slice(0, 5);
// Calculate current event count (all events, not just displayed)
const currentEventCount = sortedEvents.length;
// Calculate current event count // Prepare notification items for all upcoming events
const currentEventCount = upcomingEvents.length; const notificationItems = sortedEvents.map(event => ({
// Always prepare notification items
const notificationItems = upcomingEvents.map(event => ({
id: event.id, id: event.id,
title: event.title, title: event.title,
message: event.isAllDay message: event.isAllDay
? `Aujourd'hui (toute la journée)` ? `Aujourd'hui (toute la journée)`
: `Le ${format(event.start, 'dd/MM à HH:mm', { locale: fr })}`, : `Le ${format(new Date(event.start), 'dd/MM à HH:mm', { locale: fr })}`,
link: '/agenda', link: '/agenda',
timestamp: event.start, timestamp: new Date(event.start),
metadata: { metadata: {
calendarId: event.calendarId, calendarId: event.calendarId,
calendarName: event.calendarName, calendarName: event.calendarName,
@ -136,7 +126,6 @@ export function CalendarWidget() {
})); }));
// Always trigger notification update to keep count fresh in Redis // Always trigger notification update to keep count fresh in Redis
// This ensures the count doesn't expire even if it hasn't changed
await triggerNotification({ await triggerNotification({
source: 'calendar', source: 'calendar',
count: currentEventCount, count: currentEventCount,
@ -148,39 +137,27 @@ export function CalendarWidget() {
lastEventCountRef.current = currentEventCount; lastEventCountRef.current = currentEventCount;
} }
setEvents(upcomingEvents.slice(0, 5)); // Keep only 5 for display setEvents(upcomingEvents);
// Dispatch event for Outlook-style notifications (when events start) // Dispatch event for Outlook-style notifications
// Always dispatch, not just when count changes, so the hook can track events const eventsForNotification = sortedEvents.map(evt => ({
const eventsForNotification = upcomingEvents.map(evt => ({
id: evt.id, id: evt.id,
title: evt.title, title: evt.title,
start: evt.start instanceof Date ? evt.start : new Date(evt.start), start: new Date(evt.start),
end: evt.end instanceof Date ? evt.end : new Date(evt.end), end: new Date(evt.end),
isAllDay: evt.isAllDay, isAllDay: evt.isAllDay,
calendarName: evt.calendarName, calendarName: evt.calendarName,
calendarColor: evt.calendarColor, calendarColor: evt.calendarColor,
})); }));
console.log('[Calendar Widget] 📅 Dispatching calendar events update', {
eventsCount: eventsForNotification.length,
events: eventsForNotification.map(e => ({
id: e.id,
title: e.title,
start: e.start instanceof Date ? e.start.toISOString() : e.start,
isAllDay: e.isAllDay,
})),
});
try { try {
window.dispatchEvent(new CustomEvent('calendar-events-updated', { window.dispatchEvent(new CustomEvent('calendar-events-updated', {
detail: { detail: {
events: eventsForNotification, events: eventsForNotification,
} }
})); }));
console.log('[Calendar Widget] ✅ Event dispatched successfully');
} catch (error) { } catch (error) {
console.error('[Calendar Widget] Error dispatching event', error); console.error('[Calendar Widget] Error dispatching event', error);
} }
setError(null); setError(null);
@ -192,30 +169,23 @@ export function CalendarWidget() {
} }
}; };
// Initial fetch
fetchUpcomingEvents(); fetchUpcomingEvents();
}, [session]);
// Set up an interval to refresh events every 5 minutes const formatEventDate = (date: string | Date, isAllDay: boolean) => {
const intervalId = setInterval(() => { const eventDate = new Date(date);
fetchUpcomingEvents();
}, 300000);
return () => clearInterval(intervalId);
}, [session, sessionStatus, triggerNotification]);
const formatEventDate = (date: Date, isAllDay: boolean) => {
let dateString = ""; let dateString = "";
if (isToday(eventDate)) {
if (isToday(date)) {
dateString = "Aujourd'hui"; dateString = "Aujourd'hui";
} else if (isTomorrow(date)) { } else if (isTomorrow(eventDate)) {
dateString = "Demain"; dateString = "Demain";
} else { } else {
dateString = format(date, "EEEE d MMMM", { locale: fr }); dateString = format(eventDate, "EEEE d MMMM", { locale: fr });
} }
if (!isAllDay) { if (!isAllDay) {
dateString += ` · ${format(date, "HH:mm", { locale: fr })}`; dateString += ` · ${format(eventDate, "HH:mm", { locale: fr })}`;
} }
return dateString; return dateString;