forked from schulze/bam
		
	disable sign-up on event day
This commit is contained in:
		
							
								
								
									
										44
									
								
								EVENT_DATES_GUIDE.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								EVENT_DATES_GUIDE.md
									
									
									
									
									
										Normal file
									
								
							@@ -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!
 | 
				
			||||||
@@ -14,6 +14,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover
 | 
				
			|||||||
import { cn } from "@/lib/utils";
 | 
					import { cn } from "@/lib/utils";
 | 
				
			||||||
import { signupFormSubmit } from "@/lib/actions";
 | 
					import { signupFormSubmit } from "@/lib/actions";
 | 
				
			||||||
import { useState } from "react";
 | 
					import { useState } from "react";
 | 
				
			||||||
 | 
					import { isSignupBlocked } from "@/lib/signup-time-check";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const signupFormSchema = z.object({
 | 
					export const signupFormSchema = z.object({
 | 
				
			||||||
  name: z.string().min(2, { error: "Name is required" }).max(50, { error: "Name is too long" }),
 | 
					  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() {
 | 
					export default function SignUp() {
 | 
				
			||||||
  const [submitted, setSubmitted] = useState(false);
 | 
					  const [submitted, setSubmitted] = useState(false);
 | 
				
			||||||
  const [response, setResponse] = useState<string | null>(null);
 | 
					  const [response, setResponse] = useState<string | null>(null);
 | 
				
			||||||
 | 
					  const signupStatus = isSignupBlocked();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const form = useForm<z.infer<typeof signupFormSchema>>({
 | 
					  const form = useForm<z.infer<typeof signupFormSchema>>({
 | 
				
			||||||
    resolver: zodResolver(signupFormSchema),
 | 
					    resolver: zodResolver(signupFormSchema),
 | 
				
			||||||
    defaultValues: {
 | 
					    defaultValues: {
 | 
				
			||||||
@@ -35,6 +38,12 @@ export default function SignUp() {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  async function onSubmit(values: z.infer<typeof signupFormSchema>) {
 | 
					  async function onSubmit(values: z.infer<typeof signupFormSchema>) {
 | 
				
			||||||
 | 
					    // 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);
 | 
					    setSubmitted(true);
 | 
				
			||||||
    setResponse(await signupFormSubmit(values));
 | 
					    setResponse(await signupFormSubmit(values));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -109,12 +118,22 @@ export default function SignUp() {
 | 
				
			|||||||
              </FormItem>
 | 
					              </FormItem>
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
          <Button type="submit" disabled={submitted}>
 | 
					          <Button type="submit" disabled={submitted || signupStatus.blocked}>
 | 
				
			||||||
            Submit
 | 
					            Submit
 | 
				
			||||||
          </Button>
 | 
					          </Button>
 | 
				
			||||||
        </form>
 | 
					        </form>
 | 
				
			||||||
      </Form>
 | 
					      </Form>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  // If signup is blocked, show the message
 | 
				
			||||||
 | 
					  if (signupStatus.blocked && !response) {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <div className="rounded-lg border bg-orange-50 p-6 text-center">
 | 
				
			||||||
 | 
					        <p className="text-lg font-semibold text-orange-900 mb-2">Sign-ups Temporarily Closed</p>
 | 
				
			||||||
 | 
					        <p className="text-orange-800">{signupStatus.message}</p>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return response ?? SignupForm();
 | 
					  return response ?? SignupForm();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										7
									
								
								event-dates.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								event-dates.json
									
									
									
									
									
										Normal file
									
								
							@@ -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."
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								lib/signup-time-check.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/signup-time-check.ts
									
									
									
									
									
										Normal file
									
								
							@@ -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 };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -22,6 +22,6 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "target": "ES2023"
 | 
					    "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"]
 | 
					  "exclude": ["node_modules"]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user