diff --git a/peopleportal/server/src/controllers/EventController.ts b/peopleportal/server/src/controllers/EventController.ts index 59ed209..5b4b416 100644 --- a/peopleportal/server/src/controllers/EventController.ts +++ b/peopleportal/server/src/controllers/EventController.ts @@ -815,6 +815,14 @@ export class EventController extends Controller { throw new CustomValidationError(404, `No event with id ${eventId}`); } + // RSVPs close when the event starts. + if (event.startTime.getTime() <= Date.now()) { + throw new CustomValidationError( + 400, + "RSVPs are closed because this event has already started.", + ); + } + // Ensure email is available through session or tempsession const email = req.session.authorizedUser?.email ?? diff --git a/peopleportal/webui/src/components/fabric/EventAttendance.tsx b/peopleportal/webui/src/components/fabric/EventAttendance.tsx index 6619dd9..bdcca6c 100644 --- a/peopleportal/webui/src/components/fabric/EventAttendance.tsx +++ b/peopleportal/webui/src/components/fabric/EventAttendance.tsx @@ -454,6 +454,10 @@ export const EventAttendance = () => { setDialogOpen(true); }; + // RSVPs close when the event starts (the server enforces this too). + const rsvpClosed = + event !== null && new Date(event.startTime).getTime() <= Date.now(); + const submitRsvp = async (acceptRsvp: boolean) => { const res = await fetch( `${PEOPLEPORTAL_SERVER_ENDPOINT}/api/events/${eventId}/rsvp`, @@ -468,7 +472,10 @@ export const EventAttendance = () => { ); if (!res.ok) { - toast.error(`Failed to RSVP to event: ${res.statusText}`); + const body = await res.json().catch(() => null); + toast.error( + `Failed to RSVP to event: ${body?.message ?? res.statusText}`, + ); return; } @@ -700,6 +707,18 @@ export const EventAttendance = () => {
+ RSVPs closed when this event started. +
+