Red-team frontend clusters (a11y + UX + code quality), three coordinated passes:
Accessibility:
- DataTable clickable rows keyboard-operable (role=button, tabindex, Enter/Space).
- <main> landmark + skip link; icon-only buttons get aria-labels; inputs relying
on placeholder alone get aria-labels; AWS-ranking link is a real <button>;
Login fields wrapped in a <form> so Enter submits from either field; toasts
role=alert for errors (urgency not by color alone).
UX safety:
- 'Notify all' and reminder 'Send' now behind ConfirmDialogs naming the count/
client; document action bar disables while an action is in flight (no
double-submit dupes); SendDialog surfaces why a send is blocked instead of
failing silently; client search + ticket search debounced (~300ms); inline
Client-360 edit failures surface via toast, not an off-screen banner; LivePreview
gets a real Retry; destructive client-status transitions confirm first.
Code quality:
- ErrorBoundary wraps the app (a render throw no longer white-screens).
- useData clears stale data on dep change (no record flashing under a new id).
- Shared ErrorBoundary/SecretField/Pager components extracted; Pager adopted in
Documents; write-call api types tightened off Record<string,unknown>.
typecheck clean (root + both workspaces), web build clean, web tests 4/4, full
suite 388 green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- /reminders page: Queued/Sent/Failed/Dismissed chips mapping to ?status=,
managerial-only Mine/All toggle via ?owner= (staff are server-forced to
their own rows), kind/client/doc/due/status table with Send/Preview/
Dismiss on open rows, honest server-driven pager (rule 8).
- Extract the Dashboard queue actions into shared
components/ReminderQueue.tsx (QueueActions, RULE_LABEL, reminderTone)
with a re-entry guard on Send/Dismiss; Dashboard queue card links
"View all" to /reminders.
- api.ts: getReminders now takes { status, owner, page, pageSize } and
returns the full QueueItem rows + page metadata; login stores the
staff id (hq.id) so Mine can narrow by owner.
- Nav item under WORK + route; no backend changes. A contract test pins
the sent/dismissed chips, ?owner= narrowing and cross-chip staff scope
at HTTP level (apps/hq/test/reminders-page.test.ts).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>