From 227dd2b73f04e3ec914316e770b5ac0a4c0a25bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?=
Date: Thu, 4 Jun 2026 18:20:10 +0200
Subject: [PATCH] fix(settings): show a pending state on the danger-zone
confirm buttons
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The data-reset and account-delete confirmations fired their mutation
from an uncontrolled AlertDialog, so the action dismissed the dialog
the instant it was clicked and the only spinner lived on the now-hidden
trigger. A user on a slow link saw no feedback and could re-open and
re-submit a destructive, irreversible action.
Drive both dialogs from controlled open state and add an in-dialog
pending treatment to the confirm button — disabled, aria-busy, and a
spinner — mirroring the bulk-delete confirmation in the medication
intake history. The dialog now holds open while the request is in
flight; the data-reset closes on success, the account-delete keeps its
pending state through the post-delete redirect.
---
src/components/settings/advanced-section.tsx | 60 +++++++++++++++++---
1 file changed, 53 insertions(+), 7 deletions(-)
diff --git a/src/components/settings/advanced-section.tsx b/src/components/settings/advanced-section.tsx
index 279af5388..ef993b414 100644
--- a/src/components/settings/advanced-section.tsx
+++ b/src/components/settings/advanced-section.tsx
@@ -235,10 +235,12 @@ function DataResetCard() {
const { t } = useTranslations();
const queryClient = useQueryClient();
const [deleting, setDeleting] = useState(false);
+ const [confirmOpen, setConfirmOpen] = useState(false);
const [msg, setMsg] = useState(null);
const [msgType, setMsgType] = useState<"success" | "error" | null>(null);
async function handleDeleteAllData() {
+ if (deleting) return;
setDeleting(true);
setMsg(null);
setMsgType(null);
@@ -258,6 +260,7 @@ function DataResetCard() {
await queryClient.invalidateQueries();
setMsg(t("settings.dangerZoneSuccess"));
setMsgType("success");
+ setConfirmOpen(false);
} catch {
setMsg(t("settings.dangerZoneDeleteFailed"));
setMsgType("error");
@@ -285,7 +288,16 @@ function DataResetCard() {
{t("settings.dangerZoneDescription")}
-
+ {
+ // Hold the dialog open while the destructive mutation is in
+ // flight so the in-dialog pending state stays visible and a
+ // stray backdrop tap can't dismiss it mid-request.
+ if (deleting) return;
+ setConfirmOpen(open);
+ }}
+ >