Task #649: complete Public Relations & Protocol module (fix 8 review gaps)

Addresses the 8 spec gaps that blocked prior completion, all additive and
scoped to the protocol_* module / /protocol routes. executive-meetings untouched.

Backend (api-server/routes/protocol.ts, lib/db schema, seed):
- External meetings create as "pending" (status dropped from create schema);
  added approve + reject endpoints with state-conditional WHERE status='pending'
  and 409 on contention; patch status enum restricted to completed/cancelled.
- Added approvedBy/approvedAt/rejectionReason columns + status index; default
  status now "pending".
- Booking reject and gift-issue reject made state-conditional (409 on 0 rows).
- Dashboard: roomsAvailableNow (NOT EXISTS), giftsIssuedThisMonth/Qty;
  upcomingExternal filtered to future pending|approved.
- Reports: added externalMeetings summary counts by status.
- Seed: room names corrected (AR + EN).

Frontend (tx-os/pages/protocol.tsx, App.tsx, locales):
- URL-synced tabs under /protocol/:tab (slug<->tab maps).
- Dedicated Rooms tab (moved out of Gifts); RoomDialog isActive toggle.
- External approve/reject buttons + rejectionReason display; ExternalDialog
  create omits status, edit limited to completed/cancelled.
- Dashboard cards clickable to navigate; reports external section.
- Bookings list/calendar (grouped-by-day) view toggle.
- New i18n keys in ar.json + en.json.

Verification: tx-os + protocol.ts typecheck clean; drizzle push + re-seed done;
both workflows restarted; /api/protocol/me returns 401 unauth; architect
re-review approved. Pre-existing typecheck errors in executive-meetings.ts and
push.ts are unrelated and were not touched.

Note: had to rebuild lib/db declarations (tsc --build --force) so api-server
project references picked up the new schema columns.
This commit is contained in:
Replit Agent
2026-07-06 09:46:12 +00:00
parent 2322b77b8d
commit 5e460920c7
7 changed files with 685 additions and 220 deletions
+14 -5
View File
@@ -1545,7 +1545,8 @@
"gifts": "Gifts & Shields",
"issues": "Issuance Requests",
"reports": "Reports",
"audit": "Activity Log"
"audit": "Activity Log",
"rooms": "Rooms"
},
"status": {
"pending": "Pending",
@@ -1575,7 +1576,9 @@
"pendingBookings": "Bookings awaiting approval",
"upcomingExternal": "Upcoming external meetings",
"giftStock": "Total gift stock",
"pendingIssues": "Pending issuance requests"
"pendingIssues": "Pending issuance requests",
"roomsAvailableNow": "Rooms available now",
"giftsIssuedThisMonth": "Gifts issued this month"
},
"bookings": {
"new": "New booking",
@@ -1585,7 +1588,9 @@
"roomLabel": "Room",
"titleLabel": "Booking title",
"startsAt": "From",
"endsAt": "To"
"endsAt": "To",
"viewList": "List",
"viewCalendar": "Calendar"
},
"external": {
"new": "New meeting",
@@ -1613,7 +1618,10 @@
"nameAr": "Name (Arabic)",
"nameEn": "Name (English)",
"capacity": "Capacity",
"location": "Location"
"location": "Location",
"active": "Active",
"isActive": "Active",
"empty": "No rooms."
},
"issues": {
"new": "Issuance request",
@@ -1632,7 +1640,8 @@
"requests": "Requests",
"issued": "Issued",
"issuedQty": "Issued qty",
"empty": "No data."
"empty": "No data.",
"byExternal": "External meetings by status"
},
"audit": {
"empty": "No activity yet."