Commit Graph

93 Commits

Author SHA1 Message Date
riyadhafraa 5a004925d5 Task start baseline checkpoint for code review
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 0117caec-5fc0-49b3-8125-1dc02cfee596
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 12:05:55 +00:00
riyadhafraa 854ec177fc Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 070b6956-c3af-4e4e-97b8-4cb932e22e23
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 12:05:52 +00:00
riyadhafraa 8d0d749d19 Adjust table column alignment for better readability on smaller screens
Align specific table columns to the start to prevent layout issues with long text.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 3b6aa4c0-6f89-44f5-a192-3827f92b1a5e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 11:53:52 +00:00
riyadhafraa bd38bc5ca4 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ccad63cc-87f7-4e83-9089-23ffbe308268
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 11:49:10 +00:00
riyadhafraa f51eba68ed Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 737237cd-13b1-4c39-83f7-0411eb3069af
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 11:33:43 +00:00
riyadhafraa 1923a9ca25 Update screenshot to show correct meeting management tab
Update attached screenshot to reflect the manage meetings tab.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 26502b01-f36d-4ce8-bb8f-64652a15c0ed
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 11:19:56 +00:00
riyadhafraa c9ffb09e36 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 9e3c014c-0bfd-4123-86ce-e5601a120326
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/2VzZgdn
Replit-Helium-Checkpoint-Created: true
2026-05-03 10:51:13 +00:00
riyadhafraa d2dda556d6 #324 Make the Add/Edit Meeting dialog fit on a phone screen
After #322 trimmed the dialog, the Save/Cancel footer slid below
the visible 90vh sheet on phones because the whole DialogContent
was a single overflow-y-auto block.

Changes in artifacts/tx-os/src/pages/executive-meetings.tsx:

MeetingFormDialog
- Rebuilt DialogContent as a flex column: shrink-0 header,
  flex-1 min-h-0 overflow-y-auto middle (the only scroller),
  shrink-0 footer. Save/Cancel now stay pinned at the bottom
  even after many attendees are added.
- Reduced mobile padding/gaps (`p-4 sm:p-6`,
  `gap-3 sm:gap-4`, grid `gap-2 sm:gap-3`). Desktop spacing
  unchanged.
- Switched the field grid from `grid-cols-1 sm:grid-cols-2`
  to a flat `grid-cols-2` so the two short fields (التاريخ,
  الرقم اليومي) share a row even on mobile. Title spans both
  columns; time pickers span both on mobile and one each on
  sm+ via the new mobileFull variant.
- Inner scroll wrapper uses negative margins + matching padding
  so scroll content can extend edge-to-edge without losing the
  dialog's gutter.

FormRow helper
- Broadened `full` from `sm:col-span-2` to `col-span-2`
  (works in both 1-col and 2-col grids; only callers using
  `full` are in this file).
- Added `mobileFull` prop → `col-span-2 sm:col-span-1` for
  the time pickers, so AM/PM controls don't get squeezed on
  phones.

Out of scope (untouched): validation, save logic, attendee
model, removed-field defaults from #322, duplicate dialog,
audit, schedule view, translations.
2026-05-03 10:09:29 +00:00
riyadhafraa cfd2a46d39 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 5123ce28-d8a4-40de-88ed-223d3e32ae49
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/2VzZgdn
Replit-Helium-Checkpoint-Created: true
2026-05-03 10:06:28 +00:00
riyadhafraa 5cb1644300 Update meeting form layout and Arabic title label
Refactor executive meetings form layout in `executive-meetings.tsx` to use a responsive grid, ensuring the Arabic title spans full width and other fields stack appropriately on smaller screens. Update Arabic and English locale files (`ar.json`, `en.json`) to change the Arabic title field label from "العنوان (عربي)" to "العنوان".

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 57375b7d-57d9-4fe3-a745-00a2cad59df8
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/2VzZgdn
Replit-Helium-Checkpoint-Created: true
2026-05-03 10:00:45 +00:00
riyadhafraa fd7c3c6498 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 9a1523d5-dc1f-4906-a63a-b530a5b52d4a
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/fHzEBLA
Replit-Helium-Checkpoint-Created: true
2026-05-03 09:47:11 +00:00
riyadhafraa ea89647264 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ec66417e-470f-4913-a3ff-c38d7c0fc4d5
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/fHzEBLA
Replit-Helium-Checkpoint-Created: true
2026-05-03 09:35:43 +00:00
riyadhafraa 83ee3be884 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 966f071a-6816-4f85-a574-20c5c1ea98f7
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Q5rwhix
Replit-Helium-Checkpoint-Created: true
2026-05-03 08:01:55 +00:00
riyadhafraa 45f3d88ac5 EM time picker: mobile/iPad-friendly layout + touch targets
Follow-up to task #315. The 3-control picker shipped with desktop-
sized inline controls (~22px tall) and a single-row layout that
pushed the end picker out of view on a 375px iPhone, leaving the
user with no obvious way to fill the second time field.

What changed
- src/components/time-picker-12h.tsx: bumped the "inline" size
  from h<22px text-[10px] to h-8 (32px) text-sm/text-xs across
  hour input, minute input, and AM/PM toggle so a finger tap on
  mobile/iPad lands cleanly. Added `gap-1.5` between the
  [hour:minute] group and the AM/PM toggle so a thumb-tap on the
  toggle doesn't accidentally land on the minute input. Added a
  visible focus ring color and lightened the placeholder so the
  empty fields read as "fill me in" rather than already-active.
- src/pages/executive-meetings.tsx (TimeRangeCell wrapper):
  switched from `inline-flex` (single-row, ellipsis on overflow)
  to `flex flex-wrap items-end gap-x-1.5 gap-y-1`. The end picker
  now drops onto a second line when the cell can't fit both
  side-by-side, which is the iPhone case. The "–" separator is
  hidden on narrow widths (`hidden sm:inline`) since wrapping
  makes it visually wrong.
- Bumped Start/End labels from 10px to 11px font-medium for
  better at-a-glance scanability of which time field is which —
  this was the user-reported clarity issue.
- Save/cancel icon buttons grew to 32x32 hit areas (was tiny
  p-0.5 around a 14px icon ≈ 16px clickable).
- tests/executive-meetings-keyboard-editing.spec.mjs: added a
  new test.describe block "Schedule mobile viewport (iPhone 375)"
  with `test.use({ viewport: { width: 375, height: 667 } })`. The
  test asserts: (a) all 8 picker sub-controls + save button are
  visible on iPhone, (b) each interactive control is at least
  28px tall (regression guard against shrinking touch targets),
  (c) a complete tap-driven hour+minute+AM/PM entry on both
  start and end persists 21:30–22:45 to the DB.

Validation
- Unit tests: 22/22 pass (no logic changes — only CSS + layout).
- E2E: Tab walks (desktop) + compact+PM toggle (desktop) +
  new iPhone-375 mobile test all pass.
- TypeScript: clean.
2026-05-03 06:22:54 +00:00
riyadhafraa 79e03053aa Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 4467bc05-db1e-4d31-b5c0-92f5d9c3aa1c
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/GbTNwz8
Replit-Helium-Checkpoint-Created: true
2026-05-02 10:32:39 +00:00
riyadhafraa f7b93aa4e7 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: d8980aeb-a819-4c14-97a6-7384215c51d1
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/GbTNwz8
Replit-Helium-Checkpoint-Created: true
2026-05-02 09:34:57 +00:00
riyadhafraa 4e8beaaa76 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: d9167fa7-ae0a-40cd-8655-0f20384142fe
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/HJW50TH
Replit-Helium-Checkpoint-Created: true
2026-05-02 09:03:03 +00:00
riyadhafraa e4aa4fa280 Improve time input functionality and fix related test cases
Replace native time input with a custom text input and parser, enabling support for various time formats and fixing associated end-to-end tests.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 4ef80303-e96f-4ad0-ba0f-8fce49b7b340
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/HJW50TH
Replit-Helium-Checkpoint-Created: true
2026-05-02 08:39:00 +00:00
riyadhafraa aa0de3c99b Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7471c94c-e508-444f-a1f0-ecf0659e56b6
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/CO2oJgb
Replit-Helium-Checkpoint-Created: true
2026-05-01 22:03:02 +00:00
riyadhafraa 75fa714b25 #302 cascade-shift later meetings on postpone/reschedule (review fixes)
Backend (artifacts/api-server/src/routes/executive-meetings.ts):
- New helpers computeCascadeShift + applyCascadeShift; new schema
  cascadePreviewSchema; cascadeFollowing flag on postpone-minutes
  and reschedule.
- POST /executive-meetings/:id/cascade-preview returns followers +
  blockedBy.
- Writer paths now SELECT followers FOR UPDATE inside the txn so
  concurrent mutations cannot lose updates and audit oldStart/oldEnd
  always reflect the locked-current values (architect feedback).
- Reschedule only cascades when same date AND newStart > oldStart.
- Midnight rejection rolls back the primary too; named offender is
  surfaced verbatim to the UI.
- One meeting_cascade_shift audit per follower (trigger meeting +
  delta in the row for replay).

Frontend (artifacts/tx-os/src/components/executive-meetings/
upcoming-meeting-alert.tsx):
- CascadePromptBlock with loading / blocked / normal variants and
  data-testids cascade-prompt[-blocked|-loading], cascade-keep-times,
  cascade-shift-following, cascade-back, cascade-follower-{id}.
- runCascadePreview helper with in-flight + busy guard against
  duplicate submissions; falls through to single-meeting submit when
  no followers and not blocked.
- rescheduleSubmit extracted; cascade_crosses_midnight from server
  is caught and re-rendered as the blocked variant.

i18n: cascade* keys under executiveMeetings.alert in en.json + ar.json
(Arabic plural zero/one/two/few/many/other for header + shift action).
ALSO added `executiveMeetings.audit.action.meeting_cascade_shift` in
both locales so the History view renders a localized label instead of
falling back to the raw action code (review feedback).

Tests:
- 8 cascade backend tests in executive-meetings.test.mjs (preview
  shape, atomic shift, skip cancelled/completed, midnight rollback,
  reschedule delta + no-op cases) all pass.
- New e2e "Reschedule cascade — opting in shifts all later same-day
  meetings" (API-driven backend contract).
- NEW UI dialog test "Cascade prompt UI: Shift sends
  cascadeFollowing=true; Keep sends false" — opens the postpone
  confirm, mocks cascade-preview to a deterministic single-follower
  response, then verifies (via request interception of
  /postpone-minutes) that Shift sends cascadeFollowing=true and Keep
  sends cascadeFollowing=false (review feedback).
- NEW UI test "Cascade prompt UI: no followers => prompt skipped,
  direct submit with cascadeFollowing=false" — locks in the no-
  followers branch from the second review pass: mocks cascade-
  preview to {followers:[], blockedBy:null} and asserts the prompt
  never renders and the postpone-minutes payload carries
  cascadeFollowing=false. Both UI tests use wildcard regex routes so
  same-day pollution from prior tests cannot misroute requests.
- Made two existing tests (Postpone by 10 minutes, conflict warning)
  pollution-tolerant by polling for either the cascade prompt or the
  meeting-postponed audit row.

Pre-existing flaky tests (notifications fan-out, postpone race, row
color realtime, reorder, status transitions, alert-done/close
realtime, reschedule-different-day visibility, cancel/renumber strict
mode) are not related to this work and were not modified.

Drift note: prior commit picked up an incidental opengraph.jpg byte
diff (25906 -> 25929 bytes) from the tx-os web workflow restart — no
content change visible to this task; left in place as removing it
requires a destructive git operation.
2026-05-01 21:30:16 +00:00
riyadhafraa 471c480824 Task #303: DIN Next LT Arabic site default + working font picker
User report: "the dropdown for changing the site font does not work."
Root cause: FontSettingsSection listed Cairo / Tajawal / Noto Naskh
Arabic / Amiri, but only Tajawal had been registered with @font-face.
Picking the others was a no-op. Site default body font was also not
DIN Next LT Arabic as designed.

Changes:
- artifacts/tx-os/src/index.css: --app-font-sans now starts with
  "DIN Next LT Arabic"; dropped IBM Plex Mono.
- artifacts/tx-os/index.html: removed Google Fonts <link> + preconnect.
- artifacts/tx-os/src/pages/executive-meetings.tsx: FontSettingsSection
  dropdown replaced with the 5 actually-bundled families + system.
- artifacts/api-server/src/routes/executive-meetings.ts: FONT_FAMILIES
  Zod allowlist updated to match.
- artifacts/api-server/src/lib/sanitize.ts: FONT_NAME_PART regex now
  allows the new families (kept IBM Plex Sans Arabic for backward
  compat). Fixes a latent bug from #301 where the rich-text sanitizer
  silently stripped attendee font picks on save.
- artifacts/api-server/src/lib/pdf-renderer.ts: FAMILY_MAP and
  ARABIC_FONT_NAMES updated. Sans-style families map to the bundled
  NotoSansArabic; Naskh-style families to NotoNaskhArabic.
- artifacts/api-server/tests/executive-meetings.test.mjs: PDF
  sans-vs-naskh assertion updated from Cairo/Noto Naskh Arabic to
  DIN Next LT Arabic/Majalla, preserving its semantics. Other
  Cairo/Noto Naskh Arabic occurrences swapped to the new names.
- replit.md: documented site default font + lockstep allowlist rule.

Deviations from plan: kept DEFAULT_FONT.fontFamily = "system" on the
frontend (and the backend Zod default) instead of changing it to
"DIN Next LT Arabic". "system" semantically means "no override → use
the CSS default", which is now DIN Next LT Arabic — same end result
without forcing a migration on existing rows. The sanitizer change
was not in the original plan but was required to make the picker
actually persist.

Verification:
- Frontend tsc clean.
- Backend tsc shows the same pre-existing unrelated errors as before
  (isHighlighted boolean/number; Drizzle scope typing).
- E2E browser test verified all 7 assertions: site default font,
  no Google Fonts requests, exactly 6 dropdown options, font picker
  applies + reverts correctly, attendee font picks persist after save.
- Code review verdict: PASS.
2026-05-01 19:55:39 +00:00
riyadhafraa a79e1e125a Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 09224b88-5f3a-4c5a-bec0-93eaaf66ca08
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/iRjGQNR
Replit-Helium-Checkpoint-Created: true
2026-05-01 18:57:48 +00:00
riyadhafraa 4d290cb10d Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7eff3391-bf57-4f34-b8c2-410f9fa489ca
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/iRjGQNR
Replit-Helium-Checkpoint-Created: true
2026-05-01 18:46:35 +00:00
riyadhafraa 1ac81b7a35 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 70d86683-5d4a-4f99-9ac0-eb156e5defe4
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/GMnW1ol
Replit-Helium-Checkpoint-Created: true
2026-05-01 18:37:16 +00:00
riyadhafraa b60935ed00 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 5b2a9a59-f8a7-4e97-bd4f-ac8cc8a6bd23
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/GMnW1ol
Replit-Helium-Checkpoint-Created: true
2026-05-01 18:23:29 +00:00
riyadhafraa d044496d5e Remove AM/PM indicators from meeting time displays
Remove day period indicators (AM/PM, ص/م) from the 12-hour time display in executive meeting schedules and PDF exports.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: d895acbd-d69d-4d3e-8ded-4cb2be114779
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/0VZWDfs
Replit-Helium-Checkpoint-Created: true
2026-05-01 18:00:00 +00:00
riyadhafraa ab5ec2e2e2 Add shared row highlighting to executive meeting scheduler
Implement shared row highlighting for executive meetings by adding a `rowColor` field to the database schema and API, and migrating existing per-device colors to the new shared field.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 273accfc-a301-41b9-bd20-c121cb4e79c7
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/g7BgHDL
Replit-Helium-Checkpoint-Created: true
2026-05-01 15:24:59 +00:00
riyadhafraa 6c6f9c1848 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 5670060a-d0e8-4cba-bce2-918e04416bb4
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/8gwn7Xm
Replit-Helium-Checkpoint-Created: true
2026-05-01 15:03:18 +00:00
riyadhafraa bb340de455 Git commit prior to merge 2026-05-01 14:58:31 +00:00
riyadhafraa 50627b5b74 Add real-time updates for meeting alerts across user devices
Introduce real-time event listeners and emitters to synchronize meeting alert status changes, such as "Done" or "Dismissed", across a user's multiple open tabs and devices. This update refactors the `executive-meetings.ts` route to trigger a per-user socket event upon state transitions, which is then handled by `use-notifications-socket.ts` to invalidate the alert state query, ensuring near-instantaneous UI updates. New tests in `executive-meetings-upcoming-alert.spec.mjs` verify the cross-tab synchronization for both "Done" and "Dismiss" actions, confirming that only the acting user's alerts are affected.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: b81561d1-3ba4-46fc-96c0-77d50130c061
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/8gwn7Xm
Replit-Helium-Checkpoint-Created: true
2026-05-01 14:23:01 +00:00
riyadhafraa cbda85fc73 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: a686e421-ab75-4435-aa36-9b1065d2a1ed
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/8gwn7Xm
Replit-Helium-Checkpoint-Created: true
2026-05-01 13:12:00 +00:00
riyadhafraa bbf494f2a6 Git commit prior to merge 2026-05-01 11:18:40 +00:00
riyadhafraa 307552317e Task start baseline checkpoint for code review
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 8cdf91f8-56af-4ced-99ad-62723365085e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/zG2WcPi
Replit-Helium-Checkpoint-Created: true
2026-05-01 09:01:21 +00:00
riyadhafraa 21c935064d #262: remove Requests / Approvals / Tasks tabs from Executive Meetings
Full-stack removal of the three retired sections — UI, locales, realtime
invalidations, backend routes, role lists, capability flags, schema
tables, notify lib, and tests.

Backend (artifacts/api-server)
- routes/executive-meetings.ts: deleted /requests* + /tasks* handler
  block, REQUEST_ROLES / TASK_VIEW_ROLES / TASK_BROAD_VIEW_ROLES,
  canSubmitRequest / canViewTasks / canViewAllTasks from /me, retired
  table imports, and dead schemas (detailsByType, requestPayloadSchemas,
  request*Schema, taskCreateSchema, taskPatchSchema, dueAtSchema,
  dateOnly, timeHm). canApprove kept (still used by FontSettings).
- lib/executive-meeting-notify.ts: EXECUTIVE_MEETING_NOTIFICATION_TYPES
  collapsed to ['meeting_created'].

Frontend (artifacts/tx-os)
- pages/executive-meetings.tsx: deleted RequestsSection /
  ApprovalsSection / TasksSection / RequestListRow, pruned SECTIONS,
  MeCapabilities / MeRoles types, isSectionVisible cases, icon imports.
- hooks/use-notifications-socket.ts: dropped the two retired query
  invalidations.
- locales/{ar,en}.json: removed nav.{requests,approvals,tasks},
  executiveMeetings.{requests,approvals,tasks} subtrees, and the 6
  retired notification.type entries.

Schema + DB
- lib/db/src/schema/executive-meetings.ts: tables + relations + types
  for requests/tasks removed.
- artifacts/api-server/scripts/cleanup-em-requests-tasks.sql:
  idempotent BEGIN/COMMIT — deletes orphan prefs / notifications /
  audit rows, then DROP TABLE … CASCADE for both retired tables.
  Applied to dev DB and `db push` re-synced.

Tests
- executive-meetings.test.mjs: deleted 9 retired blocks + 2 covered
  prefs duplicates, rewrote /me capability test to assert flags absent,
  rewrote DELETE-wipe test to use meeting_created via POST
  /api/executive-meetings, removed /requests + /tasks router.param
  entries.
- executive-meetings-notifications.test.mjs: deleted 7 blocks
  (request_*, task_*, cross-event-mute), updated before/after
  cleanup to skip dropped tables, kept setPref/clearPref helpers
  (still used by surviving meeting_created opt-out tests).

Drift / pre-existing
- 3 test failures observed under the parallel `node --test` workflow
  (meeting_created fan-out count, pref opt-out daily-number conflict,
  service-orders JSON-vs-HTML) are pre-existing parallel-file
  pollution between executive-meetings.test.mjs and
  executive-meetings-notifications.test.mjs. Verified by running
  `node --test --test-concurrency=1 'tests/**/*.test.mjs'` →
  226/226 pass. Out of scope for #262.
- Pre-existing tsc warnings at routes/executive-meetings.ts L509/625
  (boolean/number on isHighlighted) and L1594 (font-settings scope
  query) untouched.
2026-05-01 08:18:29 +00:00
riyadhafraa f7ab5e8b08 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: c723ef1f-32f7-4eb8-baaa-d3d4fa9eab8f
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/OwMOjxo
Replit-Helium-Checkpoint-Created: true
2026-05-01 07:43:38 +00:00
riyadhafraa 66787e4fb2 Git commit prior to merge 2026-04-30 18:29:42 +00:00
riyadhafraa 6deed137cf Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 97c9c087-1ae7-4e4c-9f7f-d4b224fc5414
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/opt4zwD
Replit-Helium-Checkpoint-Created: true
2026-04-30 18:07:52 +00:00
riyadhafraa 76f0dfacb4 Restart numbering for individuals after each subheading
Modify attendee numbering logic to reset at each subheading, ensuring proper sequence and display across different views and PDF outputs.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 17c29c3f-e55d-4765-875c-0387b6936812
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/piUNOmy
Replit-Helium-Checkpoint-Created: true
2026-04-30 12:47:50 +00:00
riyadhafraa 968da9cb58 Git commit prior to merge 2026-04-30 12:20:50 +00:00
riyadhafraa 986bb8e7b2 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: b15fc2b0-a0e1-4352-8f61-430259bae26e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/piUNOmy
Replit-Helium-Checkpoint-Created: true
2026-04-30 11:20:30 +00:00
riyadhafraa 7a13e0ae7f Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 0d5bf23d-912c-49e3-b8bb-828bae8fefe3
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/NQjGafC
Replit-Helium-Checkpoint-Created: true
2026-04-30 09:57:18 +00:00
riyadhafraa 162d78ad8b Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ffc65042-01e4-45eb-920e-412828e5c5c0
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/fEDT27c
Replit-Helium-Checkpoint-Created: true
2026-04-30 09:28:56 +00:00
riyadhafraa d72c5cc851 Git commit prior to merge 2026-04-30 07:25:15 +00:00
riyadhafraa 909551d0f6 Git commit prior to merge 2026-04-30 06:39:45 +00:00
riyadhafraa 6949ab1009 Remove unnecessary screenshot files from project assets
Remove untracked screenshot image file from attached_assets directory.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: b5b15c4e-1da9-491c-b4f5-0afd36991df0
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/S0bOBq6
Replit-Helium-Checkpoint-Created: true
2026-04-30 05:58:28 +00:00
riyadhafraa 18aa6bc93d Reduce schedule "Add" buttons to a single "+" icon (Task #190)
The substantive code for this task was already merged earlier in the
session as commit 1df6ba4 (and re-merged as 43a5491 due to a
re-assignment after task #130 went through). When the system handed
the task back to me on the post-#130 base, the working tree already
contained the desired final state — there was nothing further to
change.

What is already in HEAD that satisfies the task:
- artifacts/tx-os/src/pages/executive-meetings.tsx:
  - Add-row button (~line 1533): renders only the <Plus> icon in the
    idle state; "Loading..." stays during creatingRow. Button has
    aria-label={t("executiveMeetings.schedule.addRow")} and
    aria-busy={creatingRow}; <Plus> is aria-hidden.
  - Add-attendee inline button (~line 3008): visible content is the
    literal "+"; aria-label={addLabel} preserved for assistive tech.
- artifacts/tx-os/src/locales/ar.json:
  - executiveMeetings.schedule.addRow      : "أضف اجتماع"
  - executiveMeetings.schedule.addAttendee : "أضف حاضر"
- artifacts/tx-os/src/locales/en.json:
  - executiveMeetings.schedule.addAttendee : "Add attendee"
  - executiveMeetings.schedule.addRow      : unchanged ("Add meeting")

Verification (already performed during the original implementation):
- All 4 cases of executive-meetings-edit-toggle.spec.mjs pass; tests
  reference the buttons via data-testid (em-add-row-button,
  em-add-attendee-*), so no test changes were required.

No deviations from the task brief.
2026-04-30 05:57:40 +00:00
riyadhafraa 1df6ba41d4 Reduce schedule "Add" buttons to a single "+" icon
Task #190.

User wanted both add affordances in the Executive Meetings schedule
to show only the "+" symbol — no accompanying text in either
language.

Changes:
- artifacts/tx-os/src/pages/executive-meetings.tsx:
  - Add-row button: drops the visible label in idle state, renders
    only the <Plus> icon (aria-hidden). Loading state still shows
    "Loading..." for feedback. Added aria-label and aria-busy on
    the <button> so screen readers still announce the action and
    the loading state.
  - Add-attendee inline button: visible content is now the literal
    "+" character. aria-label preserved for assistive tech.
- artifacts/tx-os/src/locales/ar.json:
  - executiveMeetings.schedule.addRow: "أضف اجتماع جديد" → "أضف اجتماع"
  - executiveMeetings.schedule.addAttendee: "+ أضف حاضرًا" → "أضف حاضر"
- artifacts/tx-os/src/locales/en.json:
  - executiveMeetings.schedule.addAttendee: "+ Add attendee" → "Add attendee"

Both locale strings are now used solely as accessible names since
the visible glyph is hard-coded.

Verification: All 4 tests in
executive-meetings-edit-toggle.spec.mjs pass. Tests use
data-testid (em-add-row-button, em-add-attendee-*), not text, so
no test changes were required. Pre-existing TS errors in admin.tsx
and use-notifications-socket.ts are unrelated (api-client-react
codegen out of sync; tracked by other in-flight tasks).
2026-04-30 05:52:39 +00:00
riyadhafraa bb1a696f85 Git commit prior to merge 2026-04-29 19:28:13 +00:00
riyadhafraa 1a2e1302d8 Improve top bar layout and icon sizes for larger screens
Update `home.tsx` to make the top bar larger on medium screens and above, increasing icon sizes and padding for better usability on tablets and desktops.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: f5ae41d0-d8c5-4d0a-bbb0-5918d1b4e4b4
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Y0rzet1
Replit-Helium-Checkpoint-Created: true
2026-04-29 19:13:34 +00:00
riyadhafraa c29632d5a6 Schedule attendees: force number+name onto the same visual line
Task #175. Follow-up to #173. The first fix added `whitespace-nowrap`
on each attendee `<li>`, but users still saw the index span (`1-`,
`2-`) stacked above the name — even with very short names like
"رياض" / "محمد" that obviously fit on one line. Two screenshots
(before and after the merge) showed the same stacked layout, ruling
out narrow-column wrapping.

Root cause: attendee names are saved as tiptap HTML such as
`<p>محمد</p>`. Inside the inline-block EditableCell shell (and even
inside the plain view-mode `<span>`), the default block-level `<p>`
with its 1em top/bottom margins forced the name onto its own visual
row beneath the index span. `whitespace-nowrap` cannot pull a block
child back onto the parent line.

Fix (artifacts/tx-os/src/pages/executive-meetings.tsx):
- Each attendee `<li>` is now `inline-flex items-baseline
  whitespace-nowrap` so the index span and the name wrapper become
  flex children that structurally cannot break apart.
- The view-mode `<span>` (plain dangerouslySetInnerHTML) gets
  `[&_p]:inline [&_p]:m-0` — tiptap `<p>` renders as inline with no
  margins.
- The editable EditableCell wrapper gets the more-scoped
  `[&>span_p]:inline [&>span_p]:m-0`, which matches only the
  view-mode shell `<div> > <span> > <p>` and deliberately does NOT
  match the editing shell `<div> > <div(border)> > EditorContent`,
  so pressing Enter inside the editor still creates a real new
  paragraph.

Tests (artifacts/tx-os/tests/executive-meetings-edit-toggle.spec.mjs):
- New regression spec asserts that the index span and the name
  wrapper share the same vertical center (within 8px) for the first
  attendee in BOTH view mode and edit mode. Without the fix the
  centers differ by a full line height (~20px+).
- All 3 specs in the file pass.

Out of scope (unchanged): grouping/sorting, index format, multi-
group Virtual/Internal/External rows, pending +Add ghost row,
other EditableCell call sites (title, time, notes, manage tab).
2026-04-29 18:57:26 +00:00