From 8d2f139e9d9336c71d8d0c751d9d3e6e2109631c Mon Sep 17 00:00:00 2001 From: alma Date: Thu, 15 Jan 2026 16:54:14 +0100 Subject: [PATCH] Agenda refactor --- components/calendar.tsx | 10 ++++--- lib/services/microsoft-calendar-sync.ts | 40 +++++++++++++++++++++---- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/components/calendar.tsx b/components/calendar.tsx index b0397e1..7fa2d5a 100644 --- a/components/calendar.tsx +++ b/components/calendar.tsx @@ -54,9 +54,10 @@ 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 seenEventKeys = new Set(); // For events without externalEventId, use title+start+calendar as key const deduplicatedEvents = allEvents.filter((event: any) => { if (event.externalEventId) { + // For events with externalEventId, deduplicate strictly by externalEventId if (seenExternalIds.has(event.externalEventId)) { console.log('Calendar Widget - Skipping duplicate by externalEventId:', { title: event.title, @@ -67,10 +68,11 @@ export function Calendar() { } 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]}`; + // For events without externalEventId, use title + start date + calendar as key + // This prevents false positives when same title/date appears in different calendars + const eventKey = `${event.title}|${new Date(event.start).toISOString().split('T')[0]}|${event.calendar}`; if (seenEventKeys.has(eventKey)) { - console.log('Calendar Widget - Skipping duplicate by title+date:', { + console.log('Calendar Widget - Skipping duplicate by title+date+calendar:', { title: event.title, start: event.start, calendar: event.calendar, diff --git a/lib/services/microsoft-calendar-sync.ts b/lib/services/microsoft-calendar-sync.ts index e4e4ee4..25333b7 100644 --- a/lib/services/microsoft-calendar-sync.ts +++ b/lib/services/microsoft-calendar-sync.ts @@ -1091,9 +1091,17 @@ export async function syncMicrosoftCalendar( } } + // Re-fetch existing events to get any that were just created/updated + const allExistingEvents = await prisma.event.findMany({ + where: { + calendarId: syncConfig.calendarId, + }, + }); + // Find events in DB that have externalEventId but are not in the synced list // Only delete events that have an externalEventId (to avoid deleting manually created events) - for (const existingEvent of existingEvents) { + // This ensures events deleted in Microsoft are also deleted locally + for (const existingEvent of allExistingEvents) { const externalId = (existingEvent as any).externalEventId; if (externalId && !syncedMicrosoftIds.has(externalId)) { // This event exists in DB but not in Microsoft - it was deleted in Microsoft @@ -1101,15 +1109,35 @@ export async function syncMicrosoftCalendar( eventId: existingEvent.id, title: existingEvent.title, externalEventId: externalId, + calendarId: syncConfig.calendarId, }); - await prisma.event.delete({ - where: { id: existingEvent.id }, - }); - - deleted++; + try { + await prisma.event.delete({ + where: { id: existingEvent.id }, + }); + + deleted++; + logger.debug('Successfully deleted event', { + eventId: existingEvent.id, + title: existingEvent.title, + }); + } catch (deleteError) { + logger.error('Error deleting event', { + eventId: existingEvent.id, + error: deleteError instanceof Error ? deleteError.message : String(deleteError), + }); + // Continue with other deletions + } } } + + if (deleted > 0) { + logger.info('Deleted events that no longer exist in Microsoft', { + calendarSyncId, + deletedCount: deleted, + }); + } // Update sync timestamp await prisma.calendarSync.update({