From a4fed750fa1a9d2dbf6a8b97459f307cbe7b8ae5 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Wed, 3 Jun 2026 17:54:05 -0400 Subject: [PATCH] fix(idaa-recovery-meetings): fix priority sort, stale account_id gate, and cache clear MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three fixes for the IDAA Recovery Meetings load/display issues: 1. Sort direction: events use legacy encoding (priority ? 1 : 0), not build_tmp_sort. priority=true→'1' requires DESCENDING sort to put priority items first. The prior commit (ee79e33a2) incorrectly applied the build_tmp_sort-compatible ASC comparator to the events module, which does not use that encoding. Reverted in +page.svelte (both fast-path and API-results sort) and ae_idaa_comp__event_obj_li_wrapper.svelte. 2. Stale account_id gate: search $effect and handle_search_refresh now read $slct.account_id (set only by the bootstrap Sync Effect, reliable) instead of $ae_loc.account_id (persisted localStorage, may be stale from a prior session). Follows the mistake #14 pattern from BOOTSTRAP__AI_Agent_Quickstart.md. 3. Clear Cache & Reload: now enumerates and deletes ALL IDB databases via indexedDB.databases() (not just db_events.event), clears all localStorage and sessionStorage (not just two keys), and preserves the iframe reload URL for Novi re-authentication — matching the Full Reset pattern in e_app_help_tech.svelte. 4. IDB version bump: events.event → v3 (precautionary; flushes any stale cached event records on next user load in case prior deploys missed a bump). Co-Authored-By: Claude Sonnet 4.6 --- src/lib/stores/store_versions.ts | 2 +- .../(idaa)/recovery_meetings/+page.svelte | 48 ++++++++++++------- .../ae_idaa_comp__event_obj_li_wrapper.svelte | 9 ++-- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/lib/stores/store_versions.ts b/src/lib/stores/store_versions.ts index 2bda9dcf..d26d6c3e 100644 --- a/src/lib/stores/store_versions.ts +++ b/src/lib/stores/store_versions.ts @@ -86,7 +86,7 @@ export const IDB_CONTENT_VERSIONS = { journal_entry: 3 // 2026-05-14: removed content_md_html + history_md_html from properties_to_save }, events: { - event: 2, // Bumped 2026-05-16: force-clear stale IDB data causing "no meetings found" on IDAA + event: 3, // Bumped 2026-06-03: precautionary clear after sort-direction and account_id gate fixes event_session: 1, event_presenter: 1, event_badge: 1, diff --git a/src/routes/idaa/(idaa)/recovery_meetings/+page.svelte b/src/routes/idaa/(idaa)/recovery_meetings/+page.svelte index 9ccb59bf..848958c6 100644 --- a/src/routes/idaa/(idaa)/recovery_meetings/+page.svelte +++ b/src/routes/idaa/(idaa)/recovery_meetings/+page.svelte @@ -20,7 +20,7 @@ import { idaa_slct, idaa_trig } from '$lib/stores/ae_idaa_stores'; -import { ae_loc, ae_api } from '$lib/stores/ae_stores'; +import { ae_loc, ae_api, slct } from '$lib/stores/ae_stores'; import { events_func } from '$lib/ae_events/ae_events_functions'; import Element_data_store from '$lib/elements/element_data_store.svelte'; @@ -135,8 +135,10 @@ function clear_filters() { // This effect manages the orchestration between UI state and data fetching. $effect(() => { // 1. Reactive Dependencies - const account_id = $ae_loc.account_id; - if (!account_id) return; // Wait for account context + // Use $slct (non-persisted, set only by bootstrap Sync Effect) not $ae_loc + // (persisted, may hold stale account_id from a previous session in localStorage). + const account_id = $slct.account_id; + if (!account_id) return; // Wait for bootstrap to set account context // Auth gate: do not fetch IDAA events for unauthenticated users. // WHY $effect and not +layout.ts: layout load functions fire on SvelteKit link prefetch, @@ -180,7 +182,7 @@ async function handle_search_refresh(qry_key: string) { last_executed_key = qry_key; const current_search_id = ++last_search_id; - const account_id = $ae_loc.account_id; + const account_id = $slct.account_id; const remote_first = $idaa_loc.recovery_meetings.qry__remote_first; if (!account_id) return; @@ -253,11 +255,11 @@ async function handle_search_refresh(qry_key: string) { (b.name ?? '').localeCompare(a.name ?? '') ); } else { - // Robust Chronological Sort using pre-computed tmp_sort_1 - // Handles Priority, Manual Sort, and the updated_on/created_on fallback - // tmp_sort_1 built by build_tmp_sort(): priority=true→'0', so ASC puts priority first. + // Events use legacy tmp_sort_1 encoding (ae_events__event.ts: priority ? 1 : 0), + // NOT build_tmp_sort's inverted encoding. priority=true→'1' > priority=false→'0', + // so DESCENDING sort puts priority items first. local_results.sort((a, b) => - (a.tmp_sort_1 ?? '').localeCompare(b.tmp_sort_1 ?? '') + (b.tmp_sort_1 ?? '').localeCompare(a.tmp_sort_1 ?? '') ); } @@ -336,9 +338,10 @@ async function handle_search_refresh(qry_key: string) { (b.name ?? '').localeCompare(a.name ?? '') ); } else { - // tmp_sort_1 built by build_tmp_sort(): priority=true→'0', so ASC puts priority first. + // Events use legacy tmp_sort_1 encoding (ae_events__event.ts: priority ? 1 : 0). + // DESCENDING sort puts priority=true ('1') items first. api_results.sort((a, b) => - (a.tmp_sort_1 ?? '').localeCompare(b.tmp_sort_1 ?? '') + (b.tmp_sort_1 ?? '').localeCompare(a.tmp_sort_1 ?? '') ); } @@ -465,7 +468,7 @@ if (browser) { {:else} @@ -508,14 +511,25 @@ if (browser) { type="button" class="btn btn-sm preset-tonal-surface preset-outlined-warning-100-900 hover:preset-filled-warning-200-800 transition-all" onclick={async () => { - localStorage.removeItem('ae_loc'); - localStorage.removeItem('ae_idaa_loc'); - try { await db_events.event.clear(); } catch { /* ignore */ } + // Save the iframe reload URL first — it carries the Novi UUID + key + // params needed to re-authenticate after the cache wipe. + let reload_url: string | null = null; + try { reload_url = sessionStorage.getItem('idaa_iframe_reload_url'); } catch { /* ignore */ } + + // Delete every IDB database on this origin (not just db_events.event). try { - const saved_url = sessionStorage.getItem('idaa_iframe_reload_url'); - if (saved_url) { location.href = saved_url; return; } + const db_list = await indexedDB.databases(); + for (const db of db_list) { + if (db.name) indexedDB.deleteDatabase(db.name); + } } catch { /* ignore */ } - location.reload(); + + // Clear all localStorage and sessionStorage. IDAA auth comes from + // the Novi UUID in the URL, not localStorage, so a full clear is safe. + localStorage.clear(); + sessionStorage.clear(); + + if (reload_url) { location.href = reload_url; } else { location.reload(); } }}> Clear Cache & Reload diff --git a/src/routes/idaa/(idaa)/recovery_meetings/ae_idaa_comp__event_obj_li_wrapper.svelte b/src/routes/idaa/(idaa)/recovery_meetings/ae_idaa_comp__event_obj_li_wrapper.svelte index 57dafd5e..ada0a5c4 100644 --- a/src/routes/idaa/(idaa)/recovery_meetings/ae_idaa_comp__event_obj_li_wrapper.svelte +++ b/src/routes/idaa/(idaa)/recovery_meetings/ae_idaa_comp__event_obj_li_wrapper.svelte @@ -93,12 +93,11 @@ let lq__event_obj_li = $derived.by(() => { (b.name ?? '').localeCompare(a.name ?? '') ); } else { - // Robust Chronological Sort using pre-computed tmp_sort_1 (Refactored 2026-02-16) - // This handles Group > Priority > Manual Sort > Date (with updated_on fallback) - // tmp_sort_1 is built by build_tmp_sort() for ascending comparison: - // priority=true encodes as '0', priority=false as '1', so ASC puts priority first. + // Events use legacy tmp_sort_1 encoding (ae_events__event.ts: priority ? 1 : 0), + // NOT build_tmp_sort's inverted encoding. priority=true→'1' > priority=false→'0', + // so DESCENDING sort puts priority items first. results.sort((a, b) => - (a.tmp_sort_1 ?? '').localeCompare(b.tmp_sort_1 ?? '') + (b.tmp_sort_1 ?? '').localeCompare(a.tmp_sort_1 ?? '') ); } return results;