|
|
@@ -75,6 +75,15 @@ export function bannersForWeek(week, spans) {
|
|
|
const weekEnd = week[6];
|
|
|
const banners = [];
|
|
|
|
|
|
+ // Timestamps of span ends that fall within the week (these banners have rightBleed=0.8).
|
|
|
+ // Used to detect same-day checkout/checkin at the week-end boundary, where the normal
|
|
|
+ // rightBleed+leftInset gap collapses to ~4px because both banners share the same column.
|
|
|
+ const endsInWeek = new Set(
|
|
|
+ spans
|
|
|
+ .filter(s => s.end >= weekStart && s.end <= weekEnd)
|
|
|
+ .map(s => +s.end)
|
|
|
+ );
|
|
|
+
|
|
|
for (const span of spans) {
|
|
|
if (span.end < weekStart || span.start > weekEnd) continue;
|
|
|
|
|
|
@@ -83,11 +92,19 @@ export function bannersForWeek(week, spans) {
|
|
|
|
|
|
const startCol = daysBetween(weekStart, clipStart);
|
|
|
const spanCols = daysBetween(clipStart, clipEnd) + 1;
|
|
|
- const leftInset = span.start >= weekStart ? 0.2 : 0;
|
|
|
- const rightBleed = span.end <= weekEnd ? 0.8 : 0;
|
|
|
+ const rightBleed = span.end <= weekEnd ? 0.8 : 0;
|
|
|
+
|
|
|
+ // A clipped banner (rightBleed=0) that starts on the same day a non-clipped banner
|
|
|
+ // ends would normally share the same pixel column boundary, leaving only a 4px gap.
|
|
|
+ // Shift it right by an extra 0.8 columns so the gap matches a normal transition.
|
|
|
+ const sameDayAfterCheckout =
|
|
|
+ rightBleed === 0 && span.start >= weekStart && endsInWeek.has(+clipStart);
|
|
|
+ const leftInset = span.start >= weekStart ? (sameDayAfterCheckout ? 1.0 : 0.2) : 0;
|
|
|
|
|
|
- const leftPct = ((startCol + leftInset) / 7) * 100;
|
|
|
const widthPct = ((spanCols - leftInset - rightBleed) / 7) * 100;
|
|
|
+ if (widthPct <= 0) continue; // degenerate (e.g. single-col clipped same-day): skip, shows in next row
|
|
|
+
|
|
|
+ const leftPct = ((startCol + leftInset) / 7) * 100;
|
|
|
|
|
|
banners.push({
|
|
|
...span,
|