Task #670: revamp public room-booking form (protocol)

Public booking form now captures department, meeting type (internal/
external), meeting purpose, and a repeatable "key attendees" table
(name + position + side). External meetings require the entity name
(reuses requesterOrg). "عدد الحضور" relabeled to "العدد المتوقع للحضور".
Added a static red disclaimer note about possible cancellation.

Every booking (public + internal) now gets a unique, NOT NULL, searchable
reference (RB-{year}-{pad4(id)}) shown on the success screen. Staff can
search the admin bookings list by reference OR phone.

Changes:
- lib/db schema: department, meetingType, purpose, keyAttendees (jsonb),
  bookingReference (NOT NULL + unique) + requesterPhone index; new
  enums/types. Applied via drizzle push; existing rows backfilled.
- api-server: extended public booking schema + refine (org required when
  external); reserveBookingId (nextval on the serial sequence) so the
  reference is written in a single INSERT and can never be null; GET
  /protocol/bookings accepts a `q` param filtering by reference OR phone
  (server-side, indexed, case-insensitive).
- tx-os public form rewritten; admin card shows new fields; admin search
  box now debounced and wired to the API `q` param (server-side filtering)
  with an empty state.
- ar/en i18n keys under protocol.bookings.

Verification:
- Public booking POST returns a reference; external-without-org rejected
  (400); DB has zero null references after push.
- Pre-existing push.ts / executive-meetings.ts typecheck errors are
  unrelated to this task (files untouched).
This commit is contained in:
Riyadh
2026-07-07 12:34:52 +00:00
parent 3ff1338c7e
commit dd2816a1a9
3 changed files with 79 additions and 38 deletions
+3 -2
View File
@@ -132,8 +132,9 @@ export const protocolRoomBookingsTable = pgTable(
.notNull()
.default([]),
// Human-friendly, unique booking reference (رقم الحجز) shown to the
// requester on success and searchable by staff. Generated on insert.
bookingReference: varchar("booking_reference", { length: 40 }),
// requester on success and searchable by staff. Generated on insert and
// never null — every booking (public or internal) has one.
bookingReference: varchar("booking_reference", { length: 40 }).notNull(),
// 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