From 2a194de12cb0a4d52fd181b0d8984786e7d945a8 Mon Sep 17 00:00:00 2001 From: Replit Agent Date: Mon, 6 Jul 2026 11:33:58 +0000 Subject: [PATCH] Add attendee count field to booking requests and display it Updates API schemas and database to include attendee count for bookings, modifies the public request form to accept this new optional field, and displays the attendee count on the booking details. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 9c655ed7-866c-454d-b646-e458df854c65 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/OsTuUKE Replit-Helium-Checkpoint-Created: true --- artifacts/api-server/src/routes/protocol.ts | 8 ++++++++ artifacts/tx-os/src/locales/ar.json | 1 + artifacts/tx-os/src/locales/en.json | 1 + .../tx-os/src/pages/protocol-request.tsx | 19 +++++++++++++++++++ artifacts/tx-os/src/pages/protocol.tsx | 6 ++++++ lib/db/src/schema/protocol.ts | 3 +++ 6 files changed, 38 insertions(+) diff --git a/artifacts/api-server/src/routes/protocol.ts b/artifacts/api-server/src/routes/protocol.ts index 7e077651..d70bf6d3 100644 --- a/artifacts/api-server/src/routes/protocol.ts +++ b/artifacts/api-server/src/routes/protocol.ts @@ -161,6 +161,7 @@ const bookingCreateSchema = z roomId: z.number().int().positive(), title: z.string().trim().min(1).max(500), requesterName: z.string().trim().max(300).nullable().optional(), + attendeeCount: z.number().int().positive().max(100000).nullable().optional(), startsAt: isoDateTime, endsAt: isoDateTime, notes: z.string().trim().max(5000).nullable().optional(), @@ -175,6 +176,7 @@ const bookingPatchSchema = z roomId: z.number().int().positive().optional(), title: z.string().trim().min(1).max(500).optional(), requesterName: z.string().trim().max(300).nullable().optional(), + attendeeCount: z.number().int().positive().max(100000).nullable().optional(), startsAt: isoDateTime.optional(), endsAt: isoDateTime.optional(), notes: z.string().trim().max(5000).nullable().optional(), @@ -191,6 +193,7 @@ const publicBookingRequestSchema = z requesterName: z.string().trim().min(1).max(300), requesterPhone: z.string().trim().min(3).max(40), requesterOrg: z.string().trim().max(300).nullable().optional(), + attendeeCount: z.number().int().positive().max(100000).nullable().optional(), startsAt: isoDateTime, endsAt: isoDateTime, notes: z.string().trim().max(5000).nullable().optional(), @@ -458,6 +461,7 @@ router.post( requesterName: body.requesterName, requesterPhone: body.requesterPhone, requesterOrg: body.requesterOrg ?? null, + attendeeCount: body.attendeeCount ?? null, startsAt, endsAt, status: "pending", @@ -687,6 +691,7 @@ router.post( roomId: body.roomId, title: body.title, requesterName: body.requesterName ?? null, + attendeeCount: body.attendeeCount ?? null, startsAt, endsAt, status: canApprove ? "approved" : "pending", @@ -773,6 +778,9 @@ router.patch( ...(body.requesterName !== undefined ? { requesterName: body.requesterName } : {}), + ...(body.attendeeCount !== undefined + ? { attendeeCount: body.attendeeCount } + : {}), startsAt, endsAt, ...(body.notes !== undefined ? { notes: body.notes } : {}), diff --git a/artifacts/tx-os/src/locales/ar.json b/artifacts/tx-os/src/locales/ar.json index a8850c39..34907262 100644 --- a/artifacts/tx-os/src/locales/ar.json +++ b/artifacts/tx-os/src/locales/ar.json @@ -1714,6 +1714,7 @@ "requester": "مقدّم الطلب", "org": "الجهة", "phone": "الهاتف", + "attendeeCount": "عدد الحضور", "publicRequest": "طلب عام", "roomLabel": "القاعة", "titleLabel": "عنوان الحجز", diff --git a/artifacts/tx-os/src/locales/en.json b/artifacts/tx-os/src/locales/en.json index 9d19c8fd..fa7af018 100644 --- a/artifacts/tx-os/src/locales/en.json +++ b/artifacts/tx-os/src/locales/en.json @@ -1587,6 +1587,7 @@ "requester": "Requester", "org": "Organization", "phone": "Phone", + "attendeeCount": "Attendees", "publicRequest": "Public request", "roomLabel": "Room", "titleLabel": "Booking title", diff --git a/artifacts/tx-os/src/pages/protocol-request.tsx b/artifacts/tx-os/src/pages/protocol-request.tsx index af477b52..e52ba837 100644 --- a/artifacts/tx-os/src/pages/protocol-request.tsx +++ b/artifacts/tx-os/src/pages/protocol-request.tsx @@ -22,6 +22,7 @@ type FormState = { title: string; requesterPhone: string; requesterOrg: string; + attendeeCount: string; roomId: string; startsAt: string; endsAt: string; @@ -34,6 +35,7 @@ const EMPTY: FormState = { title: "", requesterPhone: "", requesterOrg: "", + attendeeCount: "", roomId: "", startsAt: "", endsAt: "", @@ -105,6 +107,10 @@ export default function ProtocolRequestPage() { requesterName: form.requesterName.trim(), requesterPhone: form.requesterPhone.trim(), requesterOrg: form.requesterOrg.trim() || null, + attendeeCount: + form.attendeeCount.trim() === "" + ? null + : Number(form.attendeeCount), startsAt: localToIso(form.startsAt), endsAt: localToIso(form.endsAt), notes: form.notes.trim() || null, @@ -249,6 +255,19 @@ export default function ProtocolRequestPage() { /> +
+ + set("attendeeCount", e.target.value)} + placeholder="العدد المتوقع للحضور (اختياري)" + /> +
+
)} + {b.attendeeCount != null && ( +
+ {t("protocol.bookings.attendeeCount")}: {b.attendeeCount} +
+ )}
{b.source === "public" && ( diff --git a/lib/db/src/schema/protocol.ts b/lib/db/src/schema/protocol.ts index c2156a5d..d90d484b 100644 --- a/lib/db/src/schema/protocol.ts +++ b/lib/db/src/schema/protocol.ts @@ -94,6 +94,9 @@ export const protocolRoomBookingsTable = pgTable( // The requester's organization / entity (الجهة). Optional even for // public requests; always null for internal bookings unless set. requesterOrg: varchar("requester_org", { length: 300 }), + // Expected number of attendees (عدد الحضور). Optional; supplied by the + // guest on a public request or by staff on an internal booking. + attendeeCount: integer("attendee_count"), // Provenance marker. "internal" for bookings created by authenticated // protocol staff through the app; "public" for guest requests coming in // via the no-login booking-request link. Defaults to "internal" so all