Commit Graph

9 Commits

Author SHA1 Message Date
riyadhafraa 7a2ae8434d Update project documentation and code comments to remove platform-specific references
Refactor documentation files and code comments to remove references to Replit, specific task numbers, and other platform-specific identifiers.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: fa18e5d4-a810-4bd5-8cde-2a60d64d9e3f
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/kI0sxlu
Replit-Helium-Checkpoint-Created: true
2026-05-14 06:23:49 +00:00
riyadhafraa 96993df361 Task #234: Show one cell-level "+ عنوان فرعي" chip instead of one per group
Original task: in split-mode meeting cells (cells where 2+ attendance
groups are visible), the trailing "+ عنوان فرعي" chip was being
rendered once per AttendeeGroup. The user reported seeing two chips
(one for the internal group, one for the external group) and asked
"ليش اثنين؟". Per the user's choice in the clarifying interview, we
keep ONE chip at the bottom of the cell, and clicking it adds a new
subheading to the LAST visible attendance group in render order
(virtual → internal → external).

Implementation:
- Added optional `suppressTrailingSubheadingChip` prop to
  `AttendeeFlowSharedProps` (defaults to false, so single-group cells
  are unchanged).
- `AttendeeFlow` skips rendering its trailing per-group "+ عنوان فرعي"
  <li> when the prop is true. The per-group "+" person <li> and all
  after-section chips are unaffected.
- In the `hasSplit` branch of `AttendeesCell`, every per-group
  `AttendeeGroup` is now passed `suppressTrailingSubheadingChip`, and
  one new cell-level chip is rendered after the missing-groups chip
  block with `data-testid="em-add-subheading-cell-${meeting.id}"`. The
  chip is gated by the same `canMutate && !hasAnyPending && startAdd`
  guard as the other add chips. Its onClick computes
  `lastVisibleAddType` at click-time as `external > internal > virtual`
  and calls `startAdd(lastVisibleAddType, "subheading")`.

Tests:
- Updated `Schedule [en|ar]: top "+ subheading" chip is NEVER
  rendered…` so its mixed-meeting cell now asserts the per-group
  `em-add-subheading-{addType}` testids are absent in split mode and
  the new cell-level testid is visible. Per-group "+" person testids
  still prove all three groups mounted.
- Added `Schedule [en|ar]: split-mode cell shows ONE cell-level "+
  subheading" chip and routes to the LAST visible group`. Seeds
  virtual + internal + external attendees, asserts ONE cell-level
  chip + zero per-group subheading chips, clicks it, types a
  subheading, blurs, and verifies the new subheading persists at the
  end of the external group with correct kind / attendance_type /
  sort_order.
- Added `Schedule [en|ar]: split-mode WITHOUT external — cell-level "+
  subheading" chip routes to INTERNAL (last visible)` to lock the
  fallback path of the lastVisibleAddType resolution rule
  (external > internal > virtual). Seeds virtual + internal only and
  verifies the new subheading persists at the end of the internal
  group.

Verification:
- tsc clean for executive-meetings.tsx (admin.tsx errors are
  pre-existing and unrelated).
- All 4 new+modified tests pass (en+ar both for the modified top-chip
  test and the new cell-level chip test).
- The 4 unrelated test failures observed in the full run are
  pre-existing flakes (locale state pollution + dnd-kit RTL drag) and
  not caused by this change.
- Architect review: PASS. No critical findings.

Follow-up:
- Task #235 (PROPOSED) covers the remaining test gap: locking that
  the cell-level chip stays hidden in row B while another row A has
  a pending ghost input open (the in-code guard uses
  `canMutate && !hasAnyPending && startAdd`).
2026-04-30 18:47:29 +00:00
riyadhafraa 27eadae655 Task #234: Show one cell-level "+ عنوان فرعي" chip instead of one per group
Original task: in split-mode meeting cells (cells where 2+ attendance
groups are visible), the trailing "+ عنوان فرعي" chip was being
rendered once per AttendeeGroup. The user reported seeing two chips
(one for the internal group, one for the external group) and asked
"ليش اثنين؟". Per the user's choice in the clarifying interview, we
keep ONE chip at the bottom of the cell, and clicking it adds a new
subheading to the LAST visible attendance group in render order
(virtual → internal → external).

Implementation:
- Added optional `suppressTrailingSubheadingChip` prop to
  `AttendeeFlowSharedProps` (defaults to false, so single-group cells
  are unchanged).
- `AttendeeFlow` skips rendering its trailing per-group "+ عنوان فرعي"
  <li> when the prop is true. The per-group "+" person <li> and all
  after-section chips are unaffected.
- In the `hasSplit` branch of `AttendeesCell`, every per-group
  `AttendeeGroup` is now passed `suppressTrailingSubheadingChip`, and
  one new cell-level chip is rendered after the missing-groups chip
  block with `data-testid="em-add-subheading-cell-${meeting.id}"`. The
  chip is gated by the same `canMutate && !hasAnyPending && startAdd`
  guard as the other add chips. Its onClick computes
  `lastVisibleAddType` at click-time as `external > internal > virtual`
  and calls `startAdd(lastVisibleAddType, "subheading")`.

Tests:
- Updated `Schedule [en|ar]: top "+ subheading" chip is NEVER
  rendered…` so its mixed-meeting cell now asserts the per-group
  `em-add-subheading-{addType}` testids are absent in split mode and
  the new cell-level testid is visible. Per-group "+" person testids
  still prove all three groups mounted.
- Added `Schedule [en|ar]: split-mode cell shows ONE cell-level "+
  subheading" chip and routes to the LAST visible group`. Seeds
  virtual + internal + external attendees, asserts ONE cell-level
  chip + zero per-group subheading chips, clicks it, types a
  subheading, blurs, and verifies the new subheading persists at the
  end of the external group with correct kind / attendance_type /
  sort_order.

Verification:
- tsc clean for executive-meetings.tsx (admin.tsx errors are
  pre-existing and unrelated).
- All 4 new+modified tests pass (en+ar both for the modified top-chip
  test and the new cell-level chip test).
- The 4 unrelated test failures observed in the full run are
  pre-existing flakes (locale state pollution + dnd-kit RTL drag) and
  not caused by this change.
- Architect review: PASS. No critical findings.

Follow-up:
- Task #235 (PROPOSED) covers two test gaps: virtual+internal-only
  fallback locking lastVisibleAddType=internal, and chip-hidden gating
  while a pending ghost is open in another row.
2026-04-30 18:44:02 +00:00
riyadhafraa aaeb0a48a0 Task #230: Remove redundant top "+ subheading" chip in attendee cells
User feedback on Task #227: the top "+ عنوان فرعي" chip is visually
redundant in every state (duplicates the trailing chip on empty /
single-section cells, and feels like noise above the first heading
once a heading exists). The trailing "+ عنوان فرعي" + after-section
chips already cover every insertion point the user actually needs.

Schedule cell (AttendeeFlow):
- Removed the entire top "+ عنوان فرعي" chip JSX block (the gate
  `items.length === 0 || hasAnySubheading`, the testid
  `em-add-subheading-top-{addType}`, and surrounding comment).
- Updated the surviving comments on `hasInlineInsert` and
  `renderPendingSubheadingLi` so they no longer mention the now-gone
  top chip — they reference only the after-section chip flow.
- `hasAnySubheading` is kept (still used by person-row numbering and
  pending-person-ghost numbering). Per-section after-section chips
  (subheading- and person-branch) and the trailing
  "+ عنوان فرعي" / "+" buttons are unchanged.

Tests (executive-meetings-attendee-insert-reorder.spec.mjs):
- Removed the two top-chip tests:
    1. "top chip on EMPTY cell inserts a subheading at slot 0"
    2. "top chip is NOT rendered on a flat list with zero subheadings"
- Replaced them with a single per-locale test:
    "top \"+ subheading\" chip is NEVER rendered (empty /
     person-only / subheading-only / mixed)".
  It seeds two meetings: an empty one (covers EMPTY state) and a
  three-section meeting that spreads attendees across the
  internal/virtual/external attendance-type groups so each
  AttendeeFlow renders in a different state (person-only,
  subheading-only, mixed). Asserts `em-add-subheading-top-*` has
  count 0 across the row, plus a sanity check on the mixed-row
  attendee count so the 0-count is meaningful.
- After-section tests (between two sections / after empty section)
  and manage drag tests are unchanged.
- Updated the file's top-of-file comment to mention #230 alongside
  #227.

Verification:
- 6 schedule tests in executive-meetings-attendee-insert-reorder
  PASS in en + ar (38.7s).
- 6 regression tests in executive-meetings-attendee-subheadings
  PASS in en + ar (34.4s).
- `tsc --noEmit` reports zero errors in executive-meetings.tsx.
- Pre-existing dnd-kit RTL flake (Manage [ar/en]: drag handle
  reorders attendees inside the dialog) bounces locales between
  runs; unrelated to this diff (no changes to manage dialog drag
  flow, SortableAttendeeRow, or dnd-kit wiring).

No deviations from the task spec.
2026-04-30 18:19:13 +00:00
riyadhafraa 40d290fd16 Update how subheading chips are displayed in meeting editor
Refactor the display of subheading chips to correctly render in empty cells and after sections.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 217126f7-0bc2-492b-9f16-a9bdc206d0a4
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:02:58 +00:00
riyadhafraa d3ce0fe157 Task #227: Restructure attendee cell controls around section headings
User feedback on Task #220's UX (in Arabic): per-section "+ شخص هنا"
chips felt redundant; the user wanted the "+ عنوان فرعي" controls
placed at the TOP of each cell and after each section instead, and
the "+ شخص هنا" chips removed entirely.

Schedule cell (AttendeeFlow):
- TOP "+ عنوان فرعي" chip renders BEFORE the first item of each
  AttendeeFlow group when the cell is empty OR when it already
  contains at least one subheading. For cells that only contain
  persons and no subheadings, the chip is intentionally hidden so the
  pre-#227 visual is preserved (per task's "no regression" clause).
  Testid: em-add-subheading-top-{addType}.
  insertAtIndex = items[0].i for non-empty cells, undefined for empty
  (so the commit appends at slot 0).
- After-section "+ عنوان فرعي" chip renders AFTER every section that
  is followed by another section, including:
    * person-tail boundary  (last person whose next item is subheading)
    * empty-section boundary (subheading whose next item is subheading)
  The trailing section is skipped — the trailing "+ عنوان فرعي" button
  below already covers that slot.
  Testid: em-add-subheading-after-{i}; insertAtIndex = i + 1.
- Both "+ شخص هنا" chips removed (subheading-empty branch + person-tail
  branch).
- Added renderPendingSubheadingLi helper for inline subheading ghost
  rendering at the clicked slot. Generalized hasInlineInsert to cover
  both person and subheading pending kinds.
- Removed addPersonHereLabel/addPersonHereAriaLabel from
  AttendeeFlowSharedProps and from the schedule-side flowProps caller.

Manage dialog:
- Removed the per-section "+ شخص هنا" buttons from the SortableContext
  flatMap and the insertAttendeeAt helper. Reverted to plain
  state.attendees.map.

Locales (ar + en):
- Dropped executiveMeetings.schedule.addPersonHere/addPersonHereAria.
- Dropped executiveMeetings.manage.attendees.addPersonHere/
  addPersonHereAria.

Tests (executive-meetings-attendee-insert-reorder.spec.mjs):
- Removed the per-section "+ شخص هنا" chip test.
- Added 4 new schedule tests (en + ar each):
    1. Top chip on an EMPTY cell inserts a subheading at slot 0.
    2. Top chip is NOT rendered on a flat list with zero subheadings
       (preserves the pre-#227 visual).
    3. After-section chip inserts a subheading between two existing
       sections (BEFORE the next-section subheading).
    4. After-section chip renders after an EMPTY section (consecutive
       subheadings) and inserts a subheading at the boundary.
- Pre-existing drag tests #2 and #3 unchanged and still pass.
- Pre-existing #4 (Manage [ar] mixed person+subheading drag) is
  reproducibly red on [ar] but green on [en]. The diff does NOT touch
  the manage dialog drag flow, the SortableAttendeeRow, or dnd-kit
  wiring — pre-existing RTL keyboard-sensor flake from #220.

Architect review: PASS on first run; second-pass code-review verdict
flagged scope alignment which has now been addressed (top chip on
empty cell, no top chip on flat lists, after-section chip on
consecutive subheadings, plus matching tests).
2026-04-30 18:01:30 +00:00
riyadhafraa bd78157781 Task #227: Restructure attendee cell controls around section headings
User feedback on Task #220's UX (in Arabic): the per-section "+ شخص هنا"
chips felt redundant; the user wanted "+ عنوان فرعي" controls placed at
the TOP of each cell and after each section instead, and the "+ شخص هنا"
chips removed entirely.

Schedule cell (AttendeeFlow):
- Added a TOP "+ عنوان فرعي" chip that renders BEFORE the first item of
  each AttendeeFlow group when the group is non-empty
  (testid em-add-subheading-top-{addType}; insertAtIndex=items[0].i).
- Added an after-section "+ عنوان فرعي" chip that renders AFTER the
  last person of each section that is followed by another subheading
  (testid em-add-subheading-after-{i}; insertAtIndex=i+1). The trailing
  section is intentionally skipped — the existing trailing
  "+ subheading" button already covers that slot.
- Removed both "+ شخص هنا" chips (subheading-empty branch + person-tail
  branch).
- Added renderPendingSubheadingLi helper for inline subheading ghost
  rendering at the clicked slot. Generalized hasInlineInsert to cover
  both person and subheading pending kinds.
- Removed addPersonHereLabel/addPersonHereAriaLabel from
  AttendeeFlowSharedProps and from the schedule-side flowProps caller.

Manage dialog:
- Removed the per-section "+ شخص هنا" buttons from the SortableContext
  flatMap and the insertAttendeeAt helper. Reverted to plain
  state.attendees.map.

Locales (ar + en):
- Dropped executiveMeetings.schedule.addPersonHere/addPersonHereAria.
- Dropped executiveMeetings.manage.attendees.addPersonHere/
  addPersonHereAria.

Tests:
- Replaced the old "+ person here" test with two new schedule tests:
  (a) top "+ عنوان فرعي" chip inserts a subheading at slot 0,
  (b) after-section chip inserts a subheading between two existing
      sections (BEFORE the next-section subheading).
- Both new tests run in en + ar.
- Pre-existing drag tests #2 and #3 are unchanged and still pass.
- Pre-existing #4 (Manage [ar] drag-reorder mixed person+subheading) is
  reproducibly red on [ar] but green on [en]. The diff does NOT touch
  the manage dialog drag flow, the SortableAttendeeRow, or dnd-kit
  wiring — this is a pre-existing RTL keyboard-sensor flake from #220.

Architect review: PASS, no blocking issues. Minor optional follow-ups
(extra edge-case test coverage) intentionally not addressed to keep
scope tight to the user's request.
2026-04-30 17:54:57 +00:00
riyadhafraa 6132d2a00a Task #220: insert persons mid-list + drag-reorder attendees
Schedule grid (AttendeeFlow):
- Per-section "+ شخص هنا" chip rendered AFTER the last PERSON of each
  section (a section ends right before the next subheading or at
  end-of-list), gated by hasAnySubheading. Clicking it opens a ghost
  row with insertAtIndex = lastPersonIdx + 1 so the new row lands at
  the TAIL of THAT section, before the next subheading. The chip
  belongs to the section ABOVE it, matching the user's spec.
- Empty-section fallback chip kept on subheading rows: when a
  subheading is followed by another subheading or end-of-list, render
  the chip there so empty sections stay growable.

Manage dialog:
- Added _sid client-only field with genAttendeeSid() so dnd-kit ids
  stay stable across renames; stripped from save projection.
- DnD via dnd-kit (DndContext / SortableContext / SortableAttendeeRow
  with GripVertical handle, keyboard + pointer sensors). New
  reorderAttendeesByDrag + sortableIds memo.
- New insertAttendeeAt(idx) helper + per-section "+ شخص هنا" buttons
  injected as non-sortable siblings inside SortableContext after each
  subheading (sortableIds remains a pure _sid list so the keyboard
  sensor still works).

Locales: addPersonHere + addPersonHereAria in both ar.json and
en.json (schedule + manage scopes).

Tests:
- New e2e spec executive-meetings-attendee-insert-reorder.spec.mjs:
  (1) chip after last person of section inserts BEFORE the next
  subheading; asserts em-add-person-here-2 (subheading idx) does NOT
  exist in [A,B,SUB,C]; (2) keyboard DnD reorders 3 persons;
  (3) mixed person + subheading drag preserves kind. 6/6 pass in
  AR + EN.
- Existing subheading e2e (Task #207): 6/6 still pass.

Process notes:
- First mark_task_complete REJECTED by code review for placing chip
  after subheading instead of after last person of prior section;
  this commit is the corrected pass. Architect re-review approved
  the semantic; only follow-up was the missing manage-scope
  addPersonHereAria locale key, which is added here.
2026-04-30 15:03:29 +00:00
riyadhafraa a0e12a15f7 Task #220: Insert persons mid-list + drag-reorder attendees
Original request: Add a per-section "+ شخص هنا" inline chip in the
attendees cell so users can splice a new person right after a
subheading without opening the manage dialog, and add drag-and-drop
reordering inside the manage dialog (with up/down arrows kept as a
keyboard fallback).

Changes (artifacts/tx-os/src/pages/executive-meetings.tsx):
- Attendee gets an optional client-only `_sid` (stripped by the
  manage-save projection so it never crosses the wire).
- AttendeeFlow now renders a "+ شخص هنا" chip right after every
  subheading row; clicking it opens the pending-add editor anchored
  to that section's tail and threads `insertAtIndex` through to
  `commitAddAttendee`, which splices + renumbers contiguously.
- Manage dialog wraps its attendee list in `DndContext` +
  `SortableContext` (vertical strategy). Each row is now a
  `SortableAttendeeRow` driven by `useSortable`; only the new
  `GripVertical` handle is wired to dnd-kit listeners so inputs,
  selects, chevrons and the delete button stay interactive.
- `reorderAttendeesByDrag(activeSid, overSid)`, memoised
  `sortableIds`, and pointer + keyboard sensors live on the manage
  section. `openEdit` and add-row helpers stamp `_sid` so each row
  has a stable React key.
- AR/EN locale keys for the chip label/aria and drag handle aria
  were already in place from the prior compaction.

Tests (new): artifacts/tx-os/tests/executive-meetings-attendee-insert-reorder.spec.mjs
- 6/6 passing (3 scenarios × AR + EN):
  1) "+ person here" inserts at the right slot after a subheading.
  2) Drag-reorder via keyboard (Space + ArrowDown) inside the manage
     dialog persists the new order.
  3) Mixed person + subheading drag preserves `kind` and order
     across the round-trip (architect-flagged coverage).

Verification:
- 6/6 new e2e pass (45.3s).
- 6/6 existing subheading e2e still pass (Task #207 untouched).
- tx-os typecheck clean for executive-meetings.tsx (admin.tsx errors
  are pre-existing/unrelated codegen drift).
- Architect review: PASS — DnD wiring composed correctly, `_sid`
  properly stripped from save payload, no security findings.

Follow-ups proposed: #221 (assert _sid never leaks to API) and #222
(quick-add chip between any two persons, not just after subheadings).
2026-04-30 14:52:22 +00:00