From 7304d8f67f3ce6b18971836acaa4e5d418e57254 Mon Sep 17 00:00:00 2001 From: Max Wofford Date: Wed, 7 Jan 2026 09:27:50 -0500 Subject: [PATCH] Setup announcement section rotation based on expirations (#1768) --- pages/index.js | 68 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/pages/index.js b/pages/index.js index fd8e1318..54e8954e 100644 --- a/pages/index.js +++ b/pages/index.js @@ -49,6 +49,38 @@ import Shipwrecked from '../components/index/cards/shipwrecked' import CTAS from '../components/index/ctas' /** @jsxImportSource theme-ui */ +const ANNOUNCEMENTS = [ + { + id: 'blueprint', + expiresAt: new Date('2026-01-31'), + copy: 'Get up to $400 to make a hardware project!', + caption: 'Design a project and get a grant to make it real with Blueprint, Hack Club\'s largest hardware program', + href: 'https://blueprint.hackclub.com/?utm_source=site-announcement', + imgSrc: 'https://hc-cdn.hel1.your-objectstorage.com/s/v3/db8d0fd43bb664a8b07431b0262a7ca13c1602c7_blueprint_logo__img_.png' + }, + { + id: 'moonshot', + expiresAt: new Date('2025-01-01'), + copy: 'Moonshot: 4-day hackathon in Orlando', + caption: 'Join us — free NASA & Universal Studios trips', + href: 'https://moonshot.hackclub.com?t=webt', + imgSrc: 'https://hc-cdn.hel1.your-objectstorage.com/s/v3/20dccaf98bc294f15d07534c407c56debcb6ec8d_favicon.png' + }, + { + id: 'flavortown', + expiresAt: new Date('2026-12-31'), + copy: 'Build projects, earn cookies, get free tech!', + caption: 'Make a website, game, or hardware project and exchange cookies for iPads, MacBooks, and more', + href: 'https://flavortown.hackclub.com/?ref=site-announcement', + imgSrc: 'https://hc-cdn.hel1.your-objectstorage.com/s/v3/0256e44f53eb79e4_logo-b28e0e8b.avif' + } +] + +function getActiveAnnouncements() { + const now = new Date() + return ANNOUNCEMENTS.filter(a => a.expiresAt > now) +} + function Page({ hackathonsData, bankData, @@ -74,8 +106,7 @@ function Page({ let [github, setGithub] = useState(0) let [slackKey, setSlackKey] = useState(0) let [key, setKey] = useState(0) - const [announcementVariant, setAnnouncementVariant] = useState('blueprint') - const [ctaVariant, setCtaVariant] = useState('blueprint') + const [announcement, setAnnouncement] = useState(null) const { asPath } = useRouter() @@ -88,16 +119,13 @@ function Page({ window.paper = `Welcome, intrepid hacker! We'd love to have you in our community. Get your invite at hack.af/slack. Under "Why do you want to join the Hack Club Slack?" add a 🦄 and we'll ship you some exclusive stickers! ` }, []) - // Decide which announcement to show on the client to avoid hydration mismatches + // Pick a random active announcement on client to avoid hydration mismatches useEffect(() => { - const roll = Math.floor(Math.random() * 2) + 1 // 1d2 - if (roll === 2) setAnnouncementVariant('moonshot') - }, []) - - // Decide which CTA to show on the client (default to Blueprint on SSR) - useEffect(() => { - const roll = Math.floor(Math.random() * 2) + 1 // 1d2 - if (roll === 2) setCtaVariant('moonshot') + const active = getActiveAnnouncements() + if (active.length > 0) { + const randomIndex = Math.floor(Math.random() * active.length) + setAnnouncement(active[randomIndex]) + } }, []) const easterEgg = () => { @@ -224,21 +252,13 @@ function Page({ priority gradient="linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.45))" /> - {announcementVariant === 'blueprint' ? ( + {announcement && ( - ) : ( - )}