diff --git a/components/calendar.tsx b/components/calendar.tsx index d46d150..b0397e1 100644 --- a/components/calendar.tsx +++ b/components/calendar.tsx @@ -54,14 +54,38 @@ export function Calendar() { // Deduplicate events by externalEventId (if same event appears in multiple calendars) // Keep the first occurrence of each unique externalEventId const seenExternalIds = new Set(); + const seenEventKeys = new Set(); // For events without externalEventId, use title+start as key const deduplicatedEvents = allEvents.filter((event: any) => { if (event.externalEventId) { if (seenExternalIds.has(event.externalEventId)) { + console.log('Calendar Widget - Skipping duplicate by externalEventId:', { + title: event.title, + externalEventId: event.externalEventId, + calendar: event.calendar, + }); return false; // Skip duplicate } seenExternalIds.add(event.externalEventId); + } else { + // For events without externalEventId, use title + start date as key to avoid duplicates + const eventKey = `${event.title}|${new Date(event.start).toISOString().split('T')[0]}`; + if (seenEventKeys.has(eventKey)) { + console.log('Calendar Widget - Skipping duplicate by title+date:', { + title: event.title, + start: event.start, + calendar: event.calendar, + }); + return false; // Skip duplicate + } + seenEventKeys.add(eventKey); } - return true; // Keep event (either has no externalEventId or is first occurrence) + return true; // Keep event + }); + + console.log('Calendar Widget - Deduplication:', { + totalBefore: allEvents.length, + totalAfter: deduplicatedEvents.length, + duplicatesRemoved: allEvents.length - deduplicatedEvents.length, }); // Filter for upcoming events diff --git a/lib/services/microsoft-calendar-sync.ts b/lib/services/microsoft-calendar-sync.ts index 09a4c04..001b4bb 100644 --- a/lib/services/microsoft-calendar-sync.ts +++ b/lib/services/microsoft-calendar-sync.ts @@ -199,6 +199,10 @@ export async function fetchMicrosoftEvents( eventCount: events.length, hasValue: !!response.data.value, status: response.status, + dateRange: { + start: startDate?.toISOString(), + end: endDate?.toISOString(), + }, // Log first few event IDs and subjects to verify they're being returned eventIds: events.slice(0, 10).map((e: MicrosoftEvent) => ({ id: e.id, @@ -217,6 +221,20 @@ export async function fetchMicrosoftEvents( isAllDay: e.isAllDay, })), }); + + // If test/retest events are not found, log a warning with suggestions + if (testEvents.length === 0 && events.length > 0) { + logger.warn('"test"/"retest" events not found in Microsoft response', { + calendarId, + totalEvents: events.length, + dateRange: { + start: startDate?.toISOString(), + end: endDate?.toISOString(), + }, + suggestion: 'Events might be in a different calendar. Check all calendars in Outlook.', + allEventSubjects: allSubjects, + }); + } // Log if we got fewer events than expected if (events.length === 0 && startDate && endDate) { @@ -349,12 +367,12 @@ export async function syncMicrosoftCalendar( } // Fetch events from Microsoft Graph API - // Sync from 1 month ago to 6 months in the future to catch all events + // Sync from 1 month ago to 1 year in the future to catch all events (including test events) const startDate = new Date(); startDate.setMonth(startDate.getMonth() - 1); startDate.setHours(0, 0, 0, 0); // Start of day const endDate = new Date(); - endDate.setMonth(endDate.getMonth() + 6); + endDate.setFullYear(endDate.getFullYear() + 1); // Extended to 1 year to catch all events endDate.setHours(23, 59, 59, 999); // End of day logger.info('Starting Microsoft calendar sync', {