diff --git a/src/components/events/HappeningNow.astro b/src/components/events/HappeningNow.astro index 230ecbe..aef1c71 100644 --- a/src/components/events/HappeningNow.astro +++ b/src/components/events/HappeningNow.astro @@ -79,13 +79,16 @@ const startTimeFmt = new Intl.DateTimeFormat("en-US", {
{sections.map((section, sectionIndex) => ( -
+

{section.heading}

-
- {section.items.length > 0 ? ( - section.items.map((item, itemIndex) => { +
+ {section.items.map((item, itemIndex) => { const status = item.isLive ? "live" : "soon"; const relative = item.isLive ? formatTimeLeft(item.endsAt.getTime() - nowMs) @@ -102,41 +105,37 @@ const startTimeFmt = new Intl.DateTimeFormat("en-US", { >
- {item.isLive ? ( - <> -
))} @@ -457,6 +456,96 @@ const startTimeFmt = new Intl.DateTimeFormat("en-US", { }); } + function getLocalDateKey(date: Date): string { + return new Intl.DateTimeFormat("en-CA", { + year: "numeric", + month: "2-digit", + day: "2-digit", + }).format(date); + } + + function setStatus(card: HTMLElement, mode: "live" | "soon", label: string) { + card.classList.toggle("now-card--live", mode === "live"); + card.classList.toggle("now-card--soon", mode === "soon"); + + const liveIcon = card.querySelector("[data-status-live-icon]"); + const soonIcon = card.querySelector("[data-status-soon-icon]"); + const labelEl = card.querySelector("[data-status-label]"); + const rel = card.querySelector("[data-relative]"); + + liveIcon?.toggleAttribute("hidden", mode !== "live"); + soonIcon?.toggleAttribute("hidden", mode === "live"); + if (labelEl) labelEl.textContent = label; + if (rel) rel.dataset.relativeMode = mode; + } + + function regroupNowStrip() { + const now = Date.now(); + const todayKey = getLocalDateKey(new Date(now)); + const weekEndsAt = now + 7 * 24 * 60 * 60 * 1000; + const sections = new Map( + Array.from(document.querySelectorAll("[data-now-section]")).map( + (section) => [section.dataset.nowSection, section], + ), + ); + const buckets = { + now: [] as HTMLElement[], + today: [] as HTMLElement[], + week: [] as HTMLElement[], + }; + + document.querySelectorAll(".now-card").forEach((card) => { + const startsAt = card.dataset.eventStartsAt; + const endsAt = card.dataset.eventEndsAt; + if (!startsAt || !endsAt) return; + + const start = new Date(startsAt).getTime(); + const end = new Date(endsAt).getTime(); + if (end <= now) return; + + if (start <= now) { + buckets.now.push(card); + setStatus(card, "live", "Live"); + } else if (getLocalDateKey(new Date(start)) === todayKey) { + buckets.today.push(card); + setStatus(card, "soon", "Today"); + } else if (start < weekEndsAt) { + buckets.week.push(card); + setStatus(card, "soon", "This week"); + } + }); + + buckets.now.sort( + (a, b) => + new Date(a.dataset.eventEndsAt ?? 0).getTime() - + new Date(b.dataset.eventEndsAt ?? 0).getTime(), + ); + buckets.today.sort( + (a, b) => + new Date(a.dataset.eventStartsAt ?? 0).getTime() - + new Date(b.dataset.eventStartsAt ?? 0).getTime(), + ); + buckets.week.sort( + (a, b) => + new Date(a.dataset.eventStartsAt ?? 0).getTime() - + new Date(b.dataset.eventStartsAt ?? 0).getTime(), + ); + + for (const [id, section] of sections) { + if (!id) continue; + const cards = section.querySelector("[data-now-cards]"); + const empty = section.querySelector("[data-now-empty]"); + const items = buckets[id as keyof typeof buckets] ?? []; + if (!cards || !empty) continue; + + items.forEach((card) => cards.insertBefore(card, empty)); + empty.toggleAttribute("hidden", items.length > 0); + } + } + localizeTimes(); + regroupNowStrip(); + tickNowStrip(); setInterval(tickNowStrip, 30000); + setInterval(regroupNowStrip, 30000);