From 358dc77e5ae925425c9a096b33c88e7d111c89ca Mon Sep 17 00:00:00 2001 From: Felix Schulze Date: Tue, 15 Jul 2025 16:28:02 +0200 Subject: [PATCH] disable sign-up on event day --- EVENT_DATES_GUIDE.md | 44 ++++++++++++++++++++++++++++++++++++++++ app/sign-up-form.tsx | 21 ++++++++++++++++++- event-dates.json | 7 +++++++ lib/signup-time-check.ts | 23 +++++++++++++++++++++ tsconfig.json | 2 +- 5 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 EVENT_DATES_GUIDE.md create mode 100644 event-dates.json create mode 100644 lib/signup-time-check.ts diff --git a/EVENT_DATES_GUIDE.md b/EVENT_DATES_GUIDE.md new file mode 100644 index 0000000..33e0e3e --- /dev/null +++ b/EVENT_DATES_GUIDE.md @@ -0,0 +1,44 @@ +# Event Dates Management Guide + +## How to Block Sign-ups on Event Days + +The sign-up form automatically closes at 3pm on specified event dates to prevent last-minute registrations. + +### Managing Event Dates + +1. Open the `event-dates.json` file in the project root +2. Add or remove dates in the `eventDates` array +3. Use the format `YYYY-MM-DD` (e.g., "2024-12-25" for December 25, 2024) + +### Example Configuration + +```json +{ + "eventDates": ["2025-09-05", "1999-01-01"], + "cutoffTime": "15:00", + "message": "Sign-ups are closed for today's event. Please come back tomorrow." +} +``` + +### Important Notes + +- The cutoff time is set to 3pm (15:00) by default +- Sign-ups will automatically reopen at midnight after an event day +- Users will see a friendly message when sign-ups are closed +- The time zone follows the server's local time + +### Adding New Event Dates + +Simply add a new date to the array: + +```json +"eventDates": [ + "2024-12-25", + "2024-12-31", + "2025-01-15", + "2025-02-14", + "2025-03-20" // <- New date added +] +``` + +Remember to save the file after making changes! diff --git a/app/sign-up-form.tsx b/app/sign-up-form.tsx index 93a6f18..ca0a5b8 100644 --- a/app/sign-up-form.tsx +++ b/app/sign-up-form.tsx @@ -14,6 +14,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover import { cn } from "@/lib/utils"; import { signupFormSubmit } from "@/lib/actions"; import { useState } from "react"; +import { isSignupBlocked } from "@/lib/signup-time-check"; export const signupFormSchema = z.object({ name: z.string().min(2, { error: "Name is required" }).max(50, { error: "Name is too long" }), @@ -26,6 +27,8 @@ export const oldestDate = new Date(new Date().setFullYear(new Date().getFullYear export default function SignUp() { const [submitted, setSubmitted] = useState(false); const [response, setResponse] = useState(null); + const signupStatus = isSignupBlocked(); + const form = useForm>({ resolver: zodResolver(signupFormSchema), defaultValues: { @@ -35,6 +38,12 @@ export default function SignUp() { }, }); async function onSubmit(values: z.infer) { + // Double-check signup isn't blocked before submitting + const currentStatus = isSignupBlocked(); + if (currentStatus.blocked) { + setResponse(currentStatus.message || "Sign-ups are currently closed."); + return; + } setSubmitted(true); setResponse(await signupFormSubmit(values)); } @@ -109,12 +118,22 @@ export default function SignUp() { )} /> - ); } + // If signup is blocked, show the message + if (signupStatus.blocked && !response) { + return ( +
+

Sign-ups Temporarily Closed

+

{signupStatus.message}

+
+ ); + } + return response ?? SignupForm(); } diff --git a/event-dates.json b/event-dates.json new file mode 100644 index 0000000..ac27ab5 --- /dev/null +++ b/event-dates.json @@ -0,0 +1,7 @@ +{ + "eventDates": ["2025-09-05", "1999-01-01"], + "cutoffTime": "15:00", + "message": "Sign-ups are closed for today's event. Please come back tomorrow.", + + "internalComment": "Add event dates in YYYY-MM-DD format. Signups will be disabled after 3pm (15:00) on these dates by default." +} diff --git a/lib/signup-time-check.ts b/lib/signup-time-check.ts new file mode 100644 index 0000000..db93342 --- /dev/null +++ b/lib/signup-time-check.ts @@ -0,0 +1,23 @@ +import eventConfig from "@/event-dates.json"; + +export function isSignupBlocked(): { blocked: boolean; message?: string } { + const now = new Date(); + const currentDate = now.toISOString().split("T")[0]; // YYYY-MM-DD format + const currentTime = now.toTimeString().slice(0, 5); // HH:MM format + + // Check if today is an event date + const isEventDay = eventConfig.eventDates.includes(currentDate); + + if (isEventDay) { + // Check if current time is after the cutoff time (default 15:00 / 3pm) + const cutoffTime = eventConfig.cutoffTime || "15:00"; + if (currentTime >= cutoffTime) { + return { + blocked: true, + message: eventConfig.message, + }; + } + } + + return { blocked: false }; +} diff --git a/tsconfig.json b/tsconfig.json index 4909585..dd21ba8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,6 +22,6 @@ }, "target": "ES2023" }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "event-dates.json"], "exclude": ["node_modules"] }