feat: gate registration behind 16 March 2026 19:00 opening date
- Add REGISTRATION_OPENS_AT const in lib/opening.ts as single source of truth - Add useRegistrationOpen hook with live 1s countdown ticker - Add CountdownBanner component (DD/HH/MM/SS) with canvas-confetti on open - EventRegistrationForm shows countdown instead of form while closed - Login page hides/disables signup while closed; login always available - WatcherForm AccountModal guards signUp call as defence-in-depth Closes #2
This commit is contained in:
@@ -12,6 +12,8 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { authClient } from "@/lib/auth-client";
|
||||
import { REGISTRATION_OPENS_AT } from "@/lib/opening";
|
||||
import { useRegistrationOpen } from "@/lib/useRegistrationOpen";
|
||||
import { orpc } from "@/utils/orpc";
|
||||
|
||||
export const Route = createFileRoute("/login")({
|
||||
@@ -31,6 +33,7 @@ export const Route = createFileRoute("/login")({
|
||||
function LoginPage() {
|
||||
const navigate = useNavigate();
|
||||
const search = Route.useSearch();
|
||||
const { isOpen } = useRegistrationOpen();
|
||||
const [isSignup, setIsSignup] = useState(() => search.signup === "1");
|
||||
const [email, setEmail] = useState(() => search.email ?? "");
|
||||
const [password, setPassword] = useState("");
|
||||
@@ -204,6 +207,43 @@ function LoginPage() {
|
||||
← Terug naar website
|
||||
</Link>
|
||||
</div>
|
||||
) : isSignup && !isOpen ? (
|
||||
/* Signup is closed until registration opens */
|
||||
<div className="space-y-4">
|
||||
<div className="rounded-lg border border-white/10 bg-white/5 p-5 text-center">
|
||||
<p className="mb-1 font-['Intro',sans-serif] text-white">
|
||||
Registratie nog niet open
|
||||
</p>
|
||||
<p className="text-sm text-white/60">
|
||||
Accounts aanmaken kan vanaf{" "}
|
||||
<span className="text-teal-300">
|
||||
{REGISTRATION_OPENS_AT.toLocaleDateString("nl-BE", {
|
||||
weekday: "long",
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
})}{" "}
|
||||
om{" "}
|
||||
{REGISTRATION_OPENS_AT.toLocaleTimeString("nl-BE", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
})}
|
||||
</span>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 text-center">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsSignup(false)}
|
||||
className="text-sm text-white/60 hover:text-white"
|
||||
>
|
||||
Al een account? Log in
|
||||
</button>
|
||||
<Link to="/" className="text-sm text-white/60 hover:text-white">
|
||||
← Terug naar website
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
{isSignup && (
|
||||
@@ -271,15 +311,29 @@ function LoginPage() {
|
||||
: "Inloggen"}
|
||||
</Button>
|
||||
<div className="flex flex-col gap-2 text-center">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsSignup(!isSignup)}
|
||||
className="text-sm text-white/60 hover:text-white"
|
||||
>
|
||||
{isSignup
|
||||
? "Al een account? Log in"
|
||||
: "Nog geen account? Registreer"}
|
||||
</button>
|
||||
{/* Only show signup toggle when registration is open */}
|
||||
{isOpen && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsSignup(!isSignup)}
|
||||
className="text-sm text-white/60 hover:text-white"
|
||||
>
|
||||
{isSignup
|
||||
? "Al een account? Log in"
|
||||
: "Nog geen account? Registreer"}
|
||||
</button>
|
||||
)}
|
||||
{!isOpen && isSignup === false && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsSignup(true)}
|
||||
className="cursor-not-allowed text-sm text-white/30"
|
||||
disabled
|
||||
title="Registratie opent op 16 maart om 19:00"
|
||||
>
|
||||
Nog geen account? (opent 16 maart)
|
||||
</button>
|
||||
)}
|
||||
<Link to="/" className="text-sm text-white/60 hover:text-white">
|
||||
← Terug naar website
|
||||
</Link>
|
||||
|
||||
Reference in New Issue
Block a user