Agenda refactor

This commit is contained in:
alma 2026-01-14 21:09:51 +01:00
parent 16e22b50a9
commit 27cf66646e
3 changed files with 65 additions and 12 deletions

View File

@ -556,6 +556,35 @@ export default async function CalendarPage() {
}
}
// Auto-sync Microsoft calendars if needed (background, don't block page load)
const microsoftSyncConfigs = await prisma.calendarSync.findMany({
where: {
provider: 'microsoft',
syncEnabled: true,
calendar: {
userId: session?.user?.id || ''
}
}
});
// Trigger sync for Microsoft calendars that need it (async, don't wait)
for (const syncConfig of microsoftSyncConfigs) {
const needsSync = !syncConfig.lastSyncAt ||
(Date.now() - syncConfig.lastSyncAt.getTime()) / (1000 * 60) >= syncConfig.syncFrequency;
if (needsSync) {
// Trigger sync in background (don't await to avoid blocking page load)
import('@/lib/services/microsoft-calendar-sync').then(({ syncMicrosoftCalendar }) => {
syncMicrosoftCalendar(syncConfig.id, false).catch((error) => {
console.error('Background sync failed for Microsoft calendar', {
calendarSyncId: syncConfig.id,
error: error instanceof Error ? error.message : String(error),
});
});
});
}
}
// Refresh calendars after auto-setup and cleanup
// Exclude "Privée" and "Default" calendars that are not synced
// IMPORTANT: Include all "Privée"/"Default" calendars that have ANY syncConfig (enabled or disabled)

View File

@ -680,8 +680,8 @@ function EventPreview({ event, calendar }: { event: Event; calendar: Calendar })
{isExpanded && (
<div className="space-y-4">
{event.description && (
<p className="text-sm text-gray-600">{event.description}</p>
{cleanDescription(event.description) && (
<p className="text-sm text-gray-600">{cleanDescription(event.description)}</p>
)}
<div className="space-y-2">
@ -995,7 +995,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
setSelectedEvent(event.extendedProps.originalEvent);
setEventForm({
title: event.title,
description: event.extendedProps.description,
description: cleanDescription(event.extendedProps.description),
start: startDate.toISOString().slice(0, 16),
end: endDate.toISOString().slice(0, 16),
allDay: event.isAllDay,
@ -1148,6 +1148,14 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
}
};
// Helper function to clean description by removing Microsoft ID prefix
const cleanDescription = (description: string | null | undefined): string | null => {
if (!description) return null;
// Remove [MS_ID:xxx] prefix if present
const cleaned = description.replace(/^\[MS_ID:[^\]]+\]\n?/, '');
return cleaned.trim() || null;
};
const getCalendarDisplayName = (calendar: CalendarWithMission) => {
// If calendar is synced to an external account, use the same display name as in courrier
if (calendar.syncConfig?.syncEnabled && calendar.syncConfig?.mailCredential) {
@ -1465,7 +1473,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
start: new Date(event.start),
end: new Date(event.end),
allDay: event.isAllDay,
description: event.description,
description: cleanDescription(event.description),
location: event.location,
calendarId: event.calendarId,
backgroundColor: `${cal.color}dd`,
@ -1474,7 +1482,7 @@ export function CalendarClient({ initialCalendars, userId, userProfile }: Calend
extendedProps: {
calendarName: cal.name,
location: event.location,
description: event.description,
description: cleanDescription(event.description),
calendarId: event.calendarId,
originalEvent: event,
color: cal.color

View File

@ -288,16 +288,32 @@ export async function syncMicrosoftCalendar(
// Sync events: create or update
for (const caldavEvent of caldavEvents) {
// Try to find existing event by matching title and start date
const existingEvent = existingEvents.find(
(e) =>
e.title === caldavEvent.summary &&
Math.abs(new Date(e.start).getTime() - caldavEvent.start.getTime()) < 60000 // Within 1 minute
);
// Store Microsoft ID in description with a special prefix for matching
const microsoftId = caldavEvent.uid;
const descriptionWithId = caldavEvent.description
? `[MS_ID:${microsoftId}]\n${caldavEvent.description}`
: `[MS_ID:${microsoftId}]`;
// Try to find existing event by Microsoft ID first (most reliable)
let existingEvent = existingEvents.find((e) => {
if (e.description && e.description.includes(`[MS_ID:${microsoftId}]`)) {
return true;
}
return false;
});
// Fallback: try to find by matching title and start date (for events created before this fix)
if (!existingEvent) {
existingEvent = existingEvents.find(
(e) =>
e.title === caldavEvent.summary &&
Math.abs(new Date(e.start).getTime() - caldavEvent.start.getTime()) < 60000 // Within 1 minute
);
}
const eventData = {
title: caldavEvent.summary,
description: caldavEvent.description || null,
description: descriptionWithId,
start: caldavEvent.start,
end: caldavEvent.end,
location: caldavEvent.location || null,