feat(executive-meetings): replace native window.confirm with in-app AlertDialog (#342)

Native window.confirm exposes the Repl hostname and ignores the app's
RTL/branding. The user (Arabic-speaking) flagged it as visually jarring
inside Executive Meetings.

Changes (artifacts/tx-os/src/pages/executive-meetings.tsx):
- Add a small ConfirmProvider + useConfirm() backed by the existing
  shadcn AlertDialog (`@/components/ui/alert-dialog`). The hook returns
  Promise<boolean> so call sites stay one-liners:
    if (!(await confirm({ message, destructive: true }))) return;
- Single-flight guard: if a second confirm() arrives while the first is
  still pending, the previous Promise resolves to false (no orphaned
  resolvers).
- Mount the provider once around the page (split the default export
  into a thin wrapper + ExecutiveMeetingsPageInner so the inner tree
  can call useConfirm()).
- Centered title + description, destructive-styled confirm button,
  mobile-safe sizing (max-w-md, w-[calc(100%-2rem)], max-h-[90vh],
  overflow-y-auto). Explicit `dir` on AlertDialogContent so the
  portal-rendered dialog always inherits the page's RTL/LTR.
- Footer renders Action first then Cancel: in LTR Confirm sits on the
  left and Cancel on the right; RTL flips automatically (Confirm right,
  Cancel left). Mobile stacks Cancel on top, destructive at the bottom.
- Replace all 5 window.confirm sites:
  1. Schedule single-row delete (deleteMeeting)
  2. Schedule bulk delete
  3. Manage bulk delete
  4. Manage single delete (confirmDelete)
  5. MeetingFormDialog "remove all attendees" (function turned async)
- Add `confirm` to the relevant useCallback deps (deleteMeeting,
  bulk delete) and inject useConfirm() inside ScheduleSection,
  ManageSection, MeetingFormDialog (all rendered inside the provider).
- New i18n keys: executiveMeetings.common.confirm and .confirmTitle in
  both ar.json and en.json (used as default title / non-destructive
  confirm label).

`pnpm -C artifacts/tx-os exec tsc --noEmit` clean. Pre-existing
api-server / test workflow failures are unrelated to this UI change
(also failing before the task started).
This commit is contained in:
riyadhafraa
2026-05-03 12:15:58 +00:00
parent 7f5b662a28
commit db6b835f75
3 changed files with 21 additions and 8 deletions
+3 -1
View File
@@ -1256,7 +1256,9 @@
"yes": "نعم",
"no": "لا",
"all": "الكل",
"filter": "تصفية"
"filter": "تصفية",
"confirm": "تأكيد",
"confirmTitle": "تأكيد"
},
"manage": {
"heading": "إدارة الاجتماعات",
+3 -1
View File
@@ -1122,7 +1122,9 @@
"yes": "Yes",
"no": "No",
"all": "All",
"filter": "Filter"
"filter": "Filter",
"confirm": "Confirm",
"confirmTitle": "Confirm"
},
"manage": {
"heading": "Manage Meetings",
@@ -684,13 +684,16 @@ function ConfirmProvider({ children }: { children: ReactNode }) {
{opts?.message ?? ""}
</AlertDialogDescription>
</AlertDialogHeader>
{/*
Render the confirm/destructive action FIRST in the JSX so
that the default `flex-row` (LTR) places it on the left and
Cancel on the right (English spec), while in RTL the visual
order flips automatically and Confirm sits on the right with
Cancel on the left (Arabic spec). On mobile the
`flex-col-reverse` from AlertDialogFooter naturally stacks
the destructive action at the bottom and Cancel on top.
*/}
<AlertDialogFooter className="sm:justify-center gap-2">
<AlertDialogCancel
data-testid="em-confirm-cancel"
onClick={() => settle(false)}
>
{cancelLabel}
</AlertDialogCancel>
<AlertDialogAction
data-testid="em-confirm-ok"
onClick={() => settle(true)}
@@ -702,6 +705,12 @@ function ConfirmProvider({ children }: { children: ReactNode }) {
>
{confirmLabel}
</AlertDialogAction>
<AlertDialogCancel
data-testid="em-confirm-cancel"
onClick={() => settle(false)}
>
{cancelLabel}
</AlertDialogCancel>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>