Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions app/src/components/event-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -118,17 +119,21 @@ export function HeroSectionTitle({
export function HeroSectionImage({
imgSrc,
imgAlt,
image,
}: {
imgSrc: string;
imgAlt: string;
image?: Image;
}) {
return (
<NextImage
src={imgSrc}
width={1200}
height={1200}
width={image?.width || 1200}
height={image?.height || 1200}
alt={imgAlt}
className="mx-auto aspect-video overflow-hidden rounded-xl object-cover sm:w-full lg:order-last lg:aspect-square"
placeholder={image?.placeholder ? "blur" : undefined}
blurDataURL={image?.placeholder || undefined}
className="mx-auto aspect-video overflow-hidden rounded-xl object-contain sm:w-full lg:order-last lg:aspect-square"
priority
/>
);
Expand All @@ -145,6 +150,7 @@ export function HeroSection({
children?: React.ReactNode;
className?: string;
}) {
const heroImage = getEventHeroImage(event);
return (
<Section variant="big" className={className}>
<div className="container">
Expand All @@ -158,16 +164,9 @@ export function HeroSection({
</div>
<div className="w-full max-w-md lg:max-w-[400px] xl:max-w-[600px] lg:flex-1">
<HeroSectionImage
imgSrc={
event.isHackathon
? "/hero-image-hackathon.png"
: "/hero-image-meetup.png"
}
imgAlt={
event.isHackathon
? "Four cartoon-style developers cheerfully throwing their arms up, surrounded by confetti. In the center, a desk with a laptop displaying code."
: "A group of cartoon-style developers standing in a circle, chatting and laughing together."
}
imgSrc={heroImage.url}
imgAlt={heroImage.alt}
image={heroImage}
/>
</div>
</>
Expand Down
26 changes: 26 additions & 0 deletions app/src/lib/event-hero.ts
Original file line number Diff line number Diff line change
@@ -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,
};
}
38 changes: 38 additions & 0 deletions app/tests/event-hero.test.ts
Original file line number Diff line number Diff line change
@@ -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");
});
Loading