Add 70-person capacity limit for watchers with real-time availability checks. Update drink card pricing to €5 per person (was €5 base + €2 per guest). Add feature flag to bypass registration countdown. Show under-review notice for performer registrations. Update FAQ performance duration from 5-7 to 5 minutes.
118 lines
3.0 KiB
TypeScript
118 lines
3.0 KiB
TypeScript
import { useQuery } from "@tanstack/react-query";
|
|
import confetti from "canvas-confetti";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { CountdownBanner } from "@/components/homepage/CountdownBanner";
|
|
import { PerformerForm } from "@/components/registration/PerformerForm";
|
|
import { TypeSelector } from "@/components/registration/TypeSelector";
|
|
import { WatcherForm } from "@/components/registration/WatcherForm";
|
|
import { useRegistrationOpen } from "@/lib/useRegistrationOpen";
|
|
import { orpc } from "@/utils/orpc";
|
|
|
|
function fireConfetti() {
|
|
const colors = ["#d82560", "#52979b", "#d09035", "#214e51", "#ffffff"];
|
|
|
|
confetti({
|
|
particleCount: 120,
|
|
spread: 80,
|
|
origin: { x: 0.3, y: 0.6 },
|
|
colors,
|
|
});
|
|
setTimeout(() => {
|
|
confetti({
|
|
particleCount: 120,
|
|
spread: 80,
|
|
origin: { x: 0.7, y: 0.6 },
|
|
colors,
|
|
});
|
|
}, 200);
|
|
setTimeout(() => {
|
|
confetti({
|
|
particleCount: 80,
|
|
spread: 100,
|
|
origin: { x: 0.5, y: 0.5 },
|
|
colors,
|
|
});
|
|
}, 400);
|
|
}
|
|
|
|
type RegistrationType = "performer" | "watcher";
|
|
|
|
function redirectToSignup(email: string) {
|
|
const params = new URLSearchParams({
|
|
signup: "1",
|
|
email,
|
|
next: "/account",
|
|
});
|
|
window.location.href = `/login?${params.toString()}`;
|
|
}
|
|
|
|
export default function EventRegistrationForm() {
|
|
const { isOpen } = useRegistrationOpen();
|
|
const confettiFired = useRef(false);
|
|
|
|
const { data: capacity } = useQuery(orpc.getWatcherCapacity.queryOptions());
|
|
|
|
useEffect(() => {
|
|
if (isOpen && !confettiFired.current) {
|
|
confettiFired.current = true;
|
|
fireConfetti();
|
|
}
|
|
}, [isOpen]);
|
|
|
|
const [selectedType, setSelectedType] = useState<RegistrationType | null>(
|
|
null,
|
|
);
|
|
|
|
if (!isOpen) {
|
|
return (
|
|
<section
|
|
id="registration"
|
|
className="relative z-30 w-full bg-[#214e51]/96 px-6 py-16 md:px-12"
|
|
>
|
|
<div className="mx-auto w-full max-w-6xl">
|
|
<CountdownBanner />
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<section
|
|
id="registration"
|
|
className="relative z-30 w-full bg-[#214e51]/96 px-6 py-16 md:px-12"
|
|
>
|
|
<div className="mx-auto w-full max-w-6xl">
|
|
<h2 className="mb-2 font-['Intro',sans-serif] text-3xl text-white md:text-4xl">
|
|
Schrijf je nu in!
|
|
</h2>
|
|
<p className="mb-2 max-w-3xl text-lg text-white/80 md:text-xl">
|
|
De Kunstenkamp jaarwerking organiseert een Open Mic
|
|
</p>
|
|
<p className="mb-8 max-w-3xl text-lg text-white/80 md:text-xl">
|
|
Doe je mee of kom je kijken? Kies je rol en vul het formulier in.
|
|
</p>
|
|
|
|
{!selectedType && (
|
|
<TypeSelector
|
|
onSelect={setSelectedType}
|
|
watcherIsFull={capacity?.isFull ?? false}
|
|
watcherAvailable={capacity?.available ?? null}
|
|
/>
|
|
)}
|
|
{selectedType === "performer" && (
|
|
<PerformerForm
|
|
onBack={() => setSelectedType(null)}
|
|
onSuccess={(_token, email, _name) => redirectToSignup(email)}
|
|
/>
|
|
)}
|
|
{selectedType === "watcher" && (
|
|
<WatcherForm
|
|
onBack={() => setSelectedType(null)}
|
|
onSuccess={(_token, email, _name) => redirectToSignup(email)}
|
|
/>
|
|
)}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|