From 27f4fbdce43ab22b2fb9c534853886c3da4dd773 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Wed, 22 Apr 2026 20:53:04 +0200 Subject: [PATCH] feat: optimize layout of overlapping events in calendar --- lib/calendar-utils.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/calendar-utils.ts b/lib/calendar-utils.ts index 2423b7a8..67b7820c 100644 --- a/lib/calendar-utils.ts +++ b/lib/calendar-utils.ts @@ -219,10 +219,26 @@ export function layoutOverlappingEvents( return (b.endMinutes - b.startMinutes) - (a.endMinutes - a.startMinutes); }); - const columns: { event: CalendarEvent; end: number }[][] = []; const result: TimedEventLayout[] = []; + let columns: { event: CalendarEvent; end: number }[][] = []; + let clusterStart = 0; + let clusterMaxEnd = 0; + + const flushCluster = () => { + const total = columns.length; + for (let i = clusterStart; i < result.length; i++) { + result[i].totalColumns = total; + } + }; for (const event of sorted) { + if (columns.length > 0 && event.startMinutes >= clusterMaxEnd) { + flushCluster(); + clusterStart = result.length; + columns = []; + clusterMaxEnd = 0; + } + let placed = false; for (let col = 0; col < columns.length; col++) { if (columns[col].every(e => e.end <= event.startMinutes)) { @@ -236,10 +252,10 @@ export function layoutOverlappingEvents( columns.push([{ event: event.event, end: event.endMinutes }]); result.push({ ...event, column: columns.length - 1, totalColumns: 0 }); } + clusterMaxEnd = Math.max(clusterMaxEnd, event.endMinutes); } - const total = columns.length; - result.forEach(r => r.totalColumns = total); + flushCluster(); return result; }