@@ -1,5 +1,4 @@
|
|||||||
import confetti from "canvas-confetti";
|
import { useState } from "react";
|
||||||
import { useEffect, useRef, useState } from "react";
|
|
||||||
import { REGISTRATION_OPENS_AT } from "@/lib/opening";
|
import { REGISTRATION_OPENS_AT } from "@/lib/opening";
|
||||||
import { useRegistrationOpen } from "@/lib/useRegistrationOpen";
|
import { useRegistrationOpen } from "@/lib/useRegistrationOpen";
|
||||||
import { client } from "@/utils/orpc";
|
import { client } from "@/utils/orpc";
|
||||||
@@ -26,34 +25,6 @@ function UnitBox({ value, label }: UnitBoxProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function fireConfetti() {
|
|
||||||
const colors = ["#d82560", "#52979b", "#d09035", "#214e51", "#ffffff"];
|
|
||||||
|
|
||||||
// Three bursts from different origins
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reminder opt-in form — sits at the very bottom of the banner
|
// Reminder opt-in form — sits at the very bottom of the banner
|
||||||
function ReminderForm() {
|
function ReminderForm() {
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
@@ -231,18 +202,9 @@ function ReminderForm() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Shown in place of the registration form while registration is not yet open.
|
* Shown in place of the registration form while registration is not yet open.
|
||||||
* Fires confetti the moment the gate opens (without a page reload).
|
|
||||||
*/
|
*/
|
||||||
export function CountdownBanner() {
|
export function CountdownBanner() {
|
||||||
const { isOpen, days, hours, minutes, seconds } = useRegistrationOpen();
|
const { isOpen, days, hours, minutes, seconds } = useRegistrationOpen();
|
||||||
const confettiFired = useRef(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isOpen && !confettiFired.current) {
|
|
||||||
confettiFired.current = true;
|
|
||||||
fireConfetti();
|
|
||||||
}
|
|
||||||
}, [isOpen]);
|
|
||||||
|
|
||||||
// Once open the parent component will unmount this — but render nothing just in case
|
// Once open the parent component will unmount this — but render nothing just in case
|
||||||
if (isOpen) return null;
|
if (isOpen) return null;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Link } from "@tanstack/react-router";
|
import { Link } from "@tanstack/react-router";
|
||||||
import { useState } from "react";
|
import confetti from "canvas-confetti";
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { CountdownBanner } from "@/components/homepage/CountdownBanner";
|
import { CountdownBanner } from "@/components/homepage/CountdownBanner";
|
||||||
import { PerformerForm } from "@/components/registration/PerformerForm";
|
import { PerformerForm } from "@/components/registration/PerformerForm";
|
||||||
import { SuccessScreen } from "@/components/registration/SuccessScreen";
|
import { SuccessScreen } from "@/components/registration/SuccessScreen";
|
||||||
@@ -8,6 +9,33 @@ import { WatcherForm } from "@/components/registration/WatcherForm";
|
|||||||
import { authClient } from "@/lib/auth-client";
|
import { authClient } from "@/lib/auth-client";
|
||||||
import { useRegistrationOpen } from "@/lib/useRegistrationOpen";
|
import { useRegistrationOpen } from "@/lib/useRegistrationOpen";
|
||||||
|
|
||||||
|
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";
|
type RegistrationType = "performer" | "watcher";
|
||||||
|
|
||||||
interface SuccessState {
|
interface SuccessState {
|
||||||
@@ -19,6 +47,15 @@ interface SuccessState {
|
|||||||
export default function EventRegistrationForm() {
|
export default function EventRegistrationForm() {
|
||||||
const { data: session } = authClient.useSession();
|
const { data: session } = authClient.useSession();
|
||||||
const { isOpen } = useRegistrationOpen();
|
const { isOpen } = useRegistrationOpen();
|
||||||
|
const confettiFired = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isOpen && !confettiFired.current) {
|
||||||
|
confettiFired.current = true;
|
||||||
|
fireConfetti();
|
||||||
|
}
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
const [selectedType, setSelectedType] = useState<RegistrationType | null>(
|
const [selectedType, setSelectedType] = useState<RegistrationType | null>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user