From db6b835f75d173e603c208ca17fae6769ff434e2 Mon Sep 17 00:00:00 2001 From: riyadhafraa <49757212-riyadhafraa@users.noreply.replit.com> Date: Sun, 3 May 2026 12:15:58 +0000 Subject: [PATCH] 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 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). --- artifacts/tx-os/src/locales/ar.json | 4 +++- artifacts/tx-os/src/locales/en.json | 4 +++- .../tx-os/src/pages/executive-meetings.tsx | 21 +++++++++++++------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/artifacts/tx-os/src/locales/ar.json b/artifacts/tx-os/src/locales/ar.json index 92c532db..9286f3d8 100644 --- a/artifacts/tx-os/src/locales/ar.json +++ b/artifacts/tx-os/src/locales/ar.json @@ -1256,7 +1256,9 @@ "yes": "نعم", "no": "لا", "all": "الكل", - "filter": "تصفية" + "filter": "تصفية", + "confirm": "تأكيد", + "confirmTitle": "تأكيد" }, "manage": { "heading": "إدارة الاجتماعات", diff --git a/artifacts/tx-os/src/locales/en.json b/artifacts/tx-os/src/locales/en.json index 78e749b5..288f4016 100644 --- a/artifacts/tx-os/src/locales/en.json +++ b/artifacts/tx-os/src/locales/en.json @@ -1122,7 +1122,9 @@ "yes": "Yes", "no": "No", "all": "All", - "filter": "Filter" + "filter": "Filter", + "confirm": "Confirm", + "confirmTitle": "Confirm" }, "manage": { "heading": "Manage Meetings", diff --git a/artifacts/tx-os/src/pages/executive-meetings.tsx b/artifacts/tx-os/src/pages/executive-meetings.tsx index c0fedfdf..b8d47114 100644 --- a/artifacts/tx-os/src/pages/executive-meetings.tsx +++ b/artifacts/tx-os/src/pages/executive-meetings.tsx @@ -684,13 +684,16 @@ function ConfirmProvider({ children }: { children: ReactNode }) { {opts?.message ?? ""} + {/* + 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. + */} - settle(false)} - > - {cancelLabel} - settle(true)} @@ -702,6 +705,12 @@ function ConfirmProvider({ children }: { children: ReactNode }) { > {confirmLabel} + settle(false)} + > + {cancelLabel} +