From df7cc4cd58b34bc7c1052a83e4d3ffbb12d42f21 Mon Sep 17 00:00:00 2001 From: Erik Thorelli Date: Mon, 21 Sep 2026 13:07:11 -0700 Subject: [PATCH] fix: show event media in event heroes --- app/src/components/event-details.tsx | 25 +++++++++--------- app/src/lib/event-hero.ts | 26 +++++++++++++++++++ app/tests/event-hero.test.ts | 38 ++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 13 deletions(-) create mode 100644 app/src/lib/event-hero.ts create mode 100644 app/tests/event-hero.test.ts diff --git a/app/src/components/event-details.tsx b/app/src/components/event-details.tsx index 65e2010..b429718 100644 --- a/app/src/components/event-details.tsx +++ b/app/src/components/event-details.tsx @@ -25,6 +25,7 @@ import { Button } from "@/components/ui/button"; import type { ExpandedEvent, Talk, Sponsor } from "@/lib/expanded-events"; import type { Image } from "@/lib/events"; import { SocialsList } from "@/components/profile-card"; +import { getEventHeroImage } from "@/lib/event-hero"; export function HeroSectionTitle({ event, @@ -118,17 +119,21 @@ export function HeroSectionTitle({ export function HeroSectionImage({ imgSrc, imgAlt, + image, }: { imgSrc: string; imgAlt: string; + image?: Image; }) { return ( ); @@ -145,6 +150,7 @@ export function HeroSection({ children?: React.ReactNode; className?: string; }) { + const heroImage = getEventHeroImage(event); return (
@@ -158,16 +164,9 @@ export function HeroSection({
diff --git a/app/src/lib/event-hero.ts b/app/src/lib/event-hero.ts new file mode 100644 index 0000000..aab8213 --- /dev/null +++ b/app/src/lib/event-hero.ts @@ -0,0 +1,26 @@ +import type { Image } from "./events"; + +export function getEventHeroImage(event: { + previewImage: Image | null; + images: Image[]; + isHackathon: boolean; +}): Image { + // The event loader supplies this generic preview when no cover is stored. + if ( + event.previewImage && + event.previewImage.url !== "/hero-image-rocket.png" + ) { + return event.previewImage; + } + if (event.images.length > 0) return event.images[0]; + return { + url: event.isHackathon + ? "/hero-image-hackathon.png" + : "/hero-image-meetup.png", + alt: event.isHackathon + ? "Illustration of developers celebrating at a hackathon" + : "Illustration of developers chatting at a meetup", + width: 1200, + height: 1200, + }; +} diff --git a/app/tests/event-hero.test.ts b/app/tests/event-hero.test.ts new file mode 100644 index 0000000..9c56a6e --- /dev/null +++ b/app/tests/event-hero.test.ts @@ -0,0 +1,38 @@ +import { expect, test } from "bun:test"; +import { getEventHeroImage } from "../src/lib/event-hero"; +const cover = { + url: "/cover.png", + alt: "Event poster", + width: 800, + height: 400, +}; +const photo = { url: "/photo.png", alt: "People building together" }; +test("uses the event cover, retaining its description and dimensions", () => { + expect( + getEventHeroImage({ + previewImage: cover, + images: [photo], + isHackathon: false, + }), + ).toEqual(cover); +}); +test("uses an event photo when the cover is absent or the loader's generic placeholder", () => { + for (const previewImage of [ + null, + { url: "/hero-image-rocket.png", alt: "Fallback" }, + ]) { + expect( + getEventHeroImage({ previewImage, images: [photo], isHackathon: false }), + ).toEqual(photo); + } +}); +test("retains distinct meetup and hackathon fallbacks without inventing event media", () => { + expect( + getEventHeroImage({ previewImage: null, images: [], isHackathon: false }) + .url, + ).toBe("/hero-image-meetup.png"); + expect( + getEventHeroImage({ previewImage: null, images: [], isHackathon: true }) + .url, + ).toBe("/hero-image-hackathon.png"); +});