From e60d61e90a845da07176ca66cd2d531072ed4203 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Thu, 10 Sep 2026 13:26:54 -0500 Subject: [PATCH] Fix admin modals replaying old action results after create or edit --- .../admin/license-keys/+page.svelte | 27 ++++++-- .../proclamation-categories/+page.svelte | 34 ++++++---- .../admin/proclamation-groups/+page.svelte | 34 ++++++---- .../admin/proclamations/+page.svelte | 48 ++++++++++---- .../admin/profiles/CreateProfileModal.svelte | 20 +++++- .../admin/profiles/EditProfileModal.svelte | 5 +- .../admin/solfeggio-frequencies/+page.svelte | 37 +++++++---- .../(protected)/admin/user-roles/+page.svelte | 34 ++++++---- .../(protected)/admin/users/+page.svelte | 40 ++++++++---- .../admin/users/page.svelte.spec.ts | 64 +++++++++++++++++++ 10 files changed, 265 insertions(+), 78 deletions(-) create mode 100644 src/routes/(protected)/admin/users/page.svelte.spec.ts diff --git a/src/routes/(protected)/admin/license-keys/+page.svelte b/src/routes/(protected)/admin/license-keys/+page.svelte index 9371cc3..62ecd77 100644 --- a/src/routes/(protected)/admin/license-keys/+page.svelte +++ b/src/routes/(protected)/admin/license-keys/+page.svelte @@ -38,6 +38,18 @@ let lastCreateForm = $state(null); let lastReplaceForm = $state(null); + let createTimer: ReturnType | undefined; + let replaceTimer: ReturnType | undefined; + + function clearTimer(timer: 'create' | 'replace') { + const current = timer === 'create' ? createTimer : replaceTimer; + if (current) { + clearTimeout(current); + if (timer === 'create') createTimer = undefined; + else replaceTimer = undefined; + } + } + $effect(() => { if (!form) return; @@ -48,9 +60,10 @@ email = ''; createError = ''; createSuccess = 'License key created and emailed'; - setTimeout(() => { + createTimer = setTimeout(() => { createOpen = false; createSuccess = ''; + createTimer = undefined; }, 1200); } else { createSuccess = ''; @@ -62,9 +75,10 @@ if (form.success) { replaceError = ''; replaceSuccess = 'License key replaced'; - setTimeout(() => { + replaceTimer = setTimeout(() => { replaceOpen = false; replaceSuccess = ''; + replaceTimer = undefined; }, 1200); } else { replaceSuccess = ''; @@ -74,25 +88,30 @@ }); function openCreate() { - lastCreateForm = null; + clearTimer('create'); + lastCreateForm = form; + email = ''; createError = ''; createSuccess = ''; createOpen = true; } function openReplace(record: Record) { + clearTimer('replace'); replaceRecord = record; - lastReplaceForm = null; + lastReplaceForm = form; replaceError = ''; replaceSuccess = ''; replaceOpen = true; } function closeCreate() { + clearTimer('create'); createOpen = false; } function closeReplace() { + clearTimer('replace'); replaceOpen = false; replaceRecord = null; } diff --git a/src/routes/(protected)/admin/proclamation-categories/+page.svelte b/src/routes/(protected)/admin/proclamation-categories/+page.svelte index 93710b2..53fe52d 100644 --- a/src/routes/(protected)/admin/proclamation-categories/+page.svelte +++ b/src/routes/(protected)/admin/proclamation-categories/+page.svelte @@ -26,15 +26,21 @@ let successMessage = $state(''); let lastForm = $state(null); - $effect(() => { - const rec = editingRecord ?? {}; - name = String(rec.name ?? ''); - if (!editingRecord) { - formError = ''; - fieldErrors = {}; - successMessage = ''; + let closeTimer: ReturnType | undefined; + + function clearCloseTimer() { + if (closeTimer) { + clearTimeout(closeTimer); + closeTimer = undefined; } - }); + } + + function resetModalState() { + clearCloseTimer(); + formError = ''; + fieldErrors = {}; + successMessage = ''; + } $effect(() => { if (!form || form === lastForm) return; @@ -44,9 +50,10 @@ formError = ''; fieldErrors = {}; successMessage = editingRecord ? 'Category updated' : 'Category created'; - setTimeout(() => { + closeTimer = setTimeout(() => { modalOpen = false; successMessage = ''; + closeTimer = undefined; }, 1200); } else { successMessage = ''; @@ -63,18 +70,23 @@ } function openCreate() { + resetModalState(); editingRecord = null; - lastForm = null; + name = ''; + lastForm = form; modalOpen = true; } function openEdit(record: Record) { + resetModalState(); editingRecord = record; - lastForm = null; + name = String(record.name ?? ''); + lastForm = form; modalOpen = true; } function closeModal() { + clearCloseTimer(); modalOpen = false; editingRecord = null; } diff --git a/src/routes/(protected)/admin/proclamation-groups/+page.svelte b/src/routes/(protected)/admin/proclamation-groups/+page.svelte index e12d0ca..faf3e57 100644 --- a/src/routes/(protected)/admin/proclamation-groups/+page.svelte +++ b/src/routes/(protected)/admin/proclamation-groups/+page.svelte @@ -26,15 +26,21 @@ let successMessage = $state(''); let lastForm = $state(null); - $effect(() => { - const rec = editingRecord ?? {}; - name = String(rec.name ?? ''); - if (!editingRecord) { - formError = ''; - fieldErrors = {}; - successMessage = ''; + let closeTimer: ReturnType | undefined; + + function clearCloseTimer() { + if (closeTimer) { + clearTimeout(closeTimer); + closeTimer = undefined; } - }); + } + + function resetModalState() { + clearCloseTimer(); + formError = ''; + fieldErrors = {}; + successMessage = ''; + } $effect(() => { if (!form || form === lastForm) return; @@ -44,9 +50,10 @@ formError = ''; fieldErrors = {}; successMessage = editingRecord ? 'Group updated' : 'Group created'; - setTimeout(() => { + closeTimer = setTimeout(() => { modalOpen = false; successMessage = ''; + closeTimer = undefined; }, 1200); } else { successMessage = ''; @@ -63,18 +70,23 @@ } function openCreate() { + resetModalState(); editingRecord = null; - lastForm = null; + name = ''; + lastForm = form; modalOpen = true; } function openEdit(record: Record) { + resetModalState(); editingRecord = record; - lastForm = null; + name = String(record.name ?? ''); + lastForm = form; modalOpen = true; } function closeModal() { + clearCloseTimer(); modalOpen = false; editingRecord = null; } diff --git a/src/routes/(protected)/admin/proclamations/+page.svelte b/src/routes/(protected)/admin/proclamations/+page.svelte index 2b562d9..b1ea52e 100644 --- a/src/routes/(protected)/admin/proclamations/+page.svelte +++ b/src/routes/(protected)/admin/proclamations/+page.svelte @@ -53,19 +53,21 @@ let contentKey = $derived(editingRecord?.id ?? 'new'); - $effect(() => { - const record = editingRecord ?? {}; - name = String(record.name ?? ''); - solfeggioFrequencyId = String(record.solfeggioFrequencyId ?? ''); - categoryId = String(record.categoryId ?? ''); - groupId = String(record.groupId ?? ''); - content = typeof record.content === 'string' ? record.content : ''; - if (!editingRecord) { - formError = ''; - fieldErrors = {}; - successMessage = ''; + let closeTimer: ReturnType | undefined; + + function clearCloseTimer() { + if (closeTimer) { + clearTimeout(closeTimer); + closeTimer = undefined; } - }); + } + + function resetModalState() { + clearCloseTimer(); + formError = ''; + fieldErrors = {}; + successMessage = ''; + } $effect(() => { if (!form || form === lastForm) return; @@ -75,6 +77,11 @@ formError = ''; fieldErrors = {}; successMessage = editingRecord ? 'Proclamation updated' : 'Proclamation created'; + closeTimer = setTimeout(() => { + modalOpen = false; + successMessage = ''; + closeTimer = undefined; + }, 1200); } else { successMessage = ''; formError = form.error ?? ''; @@ -133,18 +140,31 @@ } function openCreate() { + resetModalState(); editingRecord = null; - lastForm = null; + name = ''; + solfeggioFrequencyId = ''; + categoryId = ''; + groupId = ''; + content = ''; + lastForm = form; modalOpen = true; } function openEdit(record: Record) { + resetModalState(); editingRecord = record; - lastForm = null; + name = String(record.name ?? ''); + solfeggioFrequencyId = String(record.solfeggioFrequencyId ?? ''); + categoryId = String(record.categoryId ?? ''); + groupId = String(record.groupId ?? ''); + content = typeof record.content === 'string' ? record.content : ''; + lastForm = form; modalOpen = true; } function closeModal() { + clearCloseTimer(); modalOpen = false; editingRecord = null; } diff --git a/src/routes/(protected)/admin/profiles/CreateProfileModal.svelte b/src/routes/(protected)/admin/profiles/CreateProfileModal.svelte index 21ff92a..d4f5300 100644 --- a/src/routes/(protected)/admin/profiles/CreateProfileModal.svelte +++ b/src/routes/(protected)/admin/profiles/CreateProfileModal.svelte @@ -25,7 +25,17 @@ let successMessage = $state(''); let lastForm = $state(null); + let closeTimer: ReturnType | undefined; + + function clearCloseTimer() { + if (closeTimer) { + clearTimeout(closeTimer); + closeTimer = undefined; + } + } + $effect(() => { + clearCloseTimer(); if (open) { formError = ''; fieldErrors = {}; @@ -37,11 +47,19 @@ if (!form || form === lastForm) return; lastForm = form; + // Consume results even while closed so a stale result is never + // replayed when the modal is next opened, but only show feedback + // while this modal is actually open. + if (!open) return; + if (form.success) { formError = ''; fieldErrors = {}; successMessage = 'Profile created'; - setTimeout(() => onClose?.(), 1200); + closeTimer = setTimeout(() => { + closeTimer = undefined; + onClose?.(); + }, 1200); } else { successMessage = ''; formError = form.error ?? ''; diff --git a/src/routes/(protected)/admin/profiles/EditProfileModal.svelte b/src/routes/(protected)/admin/profiles/EditProfileModal.svelte index b4b5442..a2b1f7b 100644 --- a/src/routes/(protected)/admin/profiles/EditProfileModal.svelte +++ b/src/routes/(protected)/admin/profiles/EditProfileModal.svelte @@ -1,4 +1,5 @@