From cfb1b2ce5a730b11305509be3d58d356f9e8df0a Mon Sep 17 00:00:00 2001 From: Leo Vasanko Date: Wed, 27 Aug 2025 09:15:08 -0600 Subject: [PATCH] Use hard ends on event bars when they cross between weeks. --- src/components/EventOverlay.vue | 41 ++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/components/EventOverlay.vue b/src/components/EventOverlay.vue index f77d7bf..2cd3756 100644 --- a/src/components/EventOverlay.vue +++ b/src/components/EventOverlay.vue @@ -11,7 +11,10 @@ :key="span.id + '-' + (span.n != null ? span.n : 0)" class="event-span" dir="auto" - :class="[`event-color-${span.colorId}`]" + :class="[ + `event-color-${span.colorId}`, + { 'cont-prev': span.hasPrevWeek, 'cont-next': span.hasNextWeek }, + ]" :data-id="span.id" :data-n="span.n != null ? span.n : 0" :style="{ @@ -58,8 +61,21 @@ const eventSegments = computed(() => { props.week.days.forEach((day, di) => { day.events.forEach((ev) => { const key = ev.id + '|' + (ev.n ?? 0) - if (!spanMap.has(key)) spanMap.set(key, { ...ev, startIdx: di, endIdx: di }) - else spanMap.get(key).endIdx = Math.max(spanMap.get(key).endIdx, di) + if (!spanMap.has(key)) { + // Track min/max nDay (offset inside the occurrence) to know if the span is clipped by week boundaries + spanMap.set(key, { + ...ev, + startIdx: di, + endIdx: di, + minNDay: ev.nDay, + maxNDay: ev.nDay, + }) + } else { + const sp = spanMap.get(key) + sp.endIdx = Math.max(sp.endIdx, di) + if (ev.nDay < sp.minNDay) sp.minNDay = ev.nDay + if (ev.nDay > sp.maxNDay) sp.maxNDay = ev.nDay + } }) }) const spans = Array.from(spanMap.values()) @@ -67,6 +83,15 @@ const eventSegments = computed(() => { spans.forEach((sp) => { sp.startDate = props.week.days[sp.startIdx].date sp.endDate = props.week.days[sp.endIdx].date + // Determine if this span actually continues beyond the visible week on either side. + // If it begins on the first day column but its first occurrence day offset (minNDay) > 0, the event started earlier. + sp.hasPrevWeek = sp.startIdx === 0 && sp.minNDay > 0 + // If it ends on the last day column but we have not yet reached the final day of the occurrence (maxNDay < days-1), it continues. + if (sp.days != null) { + sp.hasNextWeek = sp.endIdx === 6 && sp.maxNDay < sp.days - 1 + } else { + sp.hasNextWeek = false + } }) // Sort so longer multi-day first, then earlier, then id for stability spans.sort((a, b) => { @@ -490,6 +515,16 @@ function applyRangeDuringDrag(st, startDate, endDate) { touch-action: none; } +.event-span.cont-prev { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.event-span.cont-next { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + /* Inner title wrapper ensures proper ellipsis within flex/grid constraints */ .event-title { display: block;