Skip to content

Commit 56b10c7

Browse files
committed
WIT
1 parent a46c389 commit 56b10c7

File tree

3 files changed

+73
-38
lines changed

3 files changed

+73
-38
lines changed

next.config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ const nextConfig = {
7070
destination: "/?socraticaW25=true",
7171
permanent: false,
7272
},
73+
{
74+
source: "/wit",
75+
destination: "/?wit=true",
76+
permanent: false,
77+
},
7378
{
7479
source: "/repo",
7580
destination: "https://github.com/jaspermayone/website",

public/images/wit.png

70.3 KB
Loading

src/components/ConfettiWrapper.tsx

Lines changed: 68 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -186,23 +186,48 @@ const ImageConfetti = ({ imagePath, duration = 3000 }) => {
186186
};
187187

188188
export default function ConfettiWrapper() {
189+
enum confettiTrigger {
190+
wit = "wit",
191+
socraticaW25 = "socraticaW25",
192+
}
193+
194+
const images = [
195+
{
196+
trigger: confettiTrigger.wit,
197+
imagePath: "/images/wit.png",
198+
invertedImagePath: "/images/wit.png",
199+
urlParam: "wit",
200+
trackingEvent: "Wit_Confetti",
201+
},
202+
{
203+
trigger: confettiTrigger.socraticaW25,
204+
imagePath: "/images/ss.png",
205+
invertedImagePath: "/images/ss-inverted.png",
206+
urlParam: "socraticaW25",
207+
trackingEvent: "SocraticaSymposiumW25_Confetti",
208+
},
209+
];
210+
189211
const pathname = usePathname();
190212
const [showConfetti, setShowConfetti] = useState(false);
191213
const [isDarkMode, setIsDarkMode] = useState(false);
214+
const [activeImage, setActiveImage] = useState<(typeof images)[0] | null>(
215+
null,
216+
);
192217

193218
// Use a ref to track if we've already shown confetti in this page load
194219
const [hasShownThisSession, setHasShownThisSession] = useState(false);
195220

196-
// Preload both images
221+
// Preload all images
197222
useEffect(() => {
198223
if (typeof window === "undefined") return;
199224

200-
// Preload both versions of the image
201-
const regularImg = new Image();
202-
regularImg.src = "/images/ss.png";
203-
204-
const invertedImg = new Image();
205-
invertedImg.src = "/images/ss-inverted.png";
225+
images.forEach((imageConfig) => {
226+
const regularImg = new Image();
227+
const invertedImg = new Image();
228+
regularImg.src = imageConfig.imagePath;
229+
invertedImg.src = imageConfig.invertedImagePath;
230+
});
206231
}, []);
207232

208233
useEffect(() => {
@@ -230,53 +255,58 @@ export default function ConfettiWrapper() {
230255
// Check if browser environment
231256
if (typeof window === "undefined") return;
232257

233-
// Check URL parameters for ss trigger
258+
// Check URL parameters for any configured triggers
234259
const searchParams = new URLSearchParams(window.location.search);
235-
const ssParam = searchParams.get("socraticaW25");
236260

237-
// Only run once on page load when ss=true and not shown yet
238-
if (ssParam === "true" && !hasShownThisSession && !showConfetti) {
261+
// Find which image config matches the current URL params (homepage only)
262+
const matchedConfig =
263+
pathname === "/"
264+
? images.find((config) => {
265+
const paramValue = searchParams.get(config.urlParam);
266+
return paramValue === "true";
267+
})
268+
: null;
269+
270+
// Only run once on page load when matched and not shown yet
271+
if (matchedConfig && !hasShownThisSession && !showConfetti) {
239272
// Mark that we've shown it this session
240273
setHasShownThisSession(true);
274+
setActiveImage(matchedConfig);
241275

242276
// Show confetti
243277
setShowConfetti(true);
244278

245279
// Track confetti display with Umami
246-
if (
247-
pathname === "/socraticaW25" ||
248-
pathname.startsWith("/socraticaW25/")
249-
) {
250-
// Create a tracking element if it doesn't exist
251-
const trackingElement = document.createElement("div");
252-
trackingElement.setAttribute(
253-
"data-umami-event",
254-
"SocraticaSymposiumW25_Confetti",
255-
);
256-
trackingElement.setAttribute("data-umami-event-path", pathname);
257-
trackingElement.setAttribute(
258-
"data-umami-event-triggered-by",
259-
"url-param",
260-
);
261-
trackingElement.style.display = "none";
262-
document.body.appendChild(trackingElement);
263-
264-
// Clean up the tracking element after a brief delay
265-
setTimeout(() => {
266-
if (document.body.contains(trackingElement)) {
267-
document.body.removeChild(trackingElement);
268-
}
269-
}, 100);
270-
}
280+
const trackingElement = document.createElement("div");
281+
trackingElement.setAttribute(
282+
"data-umami-event",
283+
matchedConfig.trackingEvent,
284+
);
285+
trackingElement.setAttribute("data-umami-event-path", pathname);
286+
trackingElement.setAttribute(
287+
"data-umami-event-triggered-by",
288+
"url-param",
289+
);
290+
trackingElement.style.display = "none";
291+
document.body.appendChild(trackingElement);
292+
293+
// Clean up the tracking element after a brief delay
294+
setTimeout(() => {
295+
if (document.body.contains(trackingElement)) {
296+
document.body.removeChild(trackingElement);
297+
}
298+
}, 100);
271299

272300
// Hide confetti after it finishes (4 seconds total: 2.5s active + 1.5s fade out)
273301
setTimeout(() => setShowConfetti(false), 4000);
274302
}
275303
}, [pathname, showConfetti, hasShownThisSession]);
276304

277-
return showConfetti ? (
305+
return showConfetti && activeImage ? (
278306
<ImageConfetti
279-
imagePath={isDarkMode ? "/images/ss-inverted.png" : "/images/ss.png"}
307+
imagePath={
308+
isDarkMode ? activeImage.invertedImagePath : activeImage.imagePath
309+
}
280310
duration={2500}
281311
/>
282312
) : null;

0 commit comments

Comments
 (0)