refactor(search): standardize debounced reactive search across modules

- Standardized the search pattern using Svelte 5 debounced $effects in Recovery Meetings, Badge Search, and Journals to eliminate manual triggers and stuttering.
- Fixed a bug in 'ae_idaa_comp__event_obj_li.svelte' where the Results count was inconsistent with the displayed list by implementing a derived 'visible_event_obj_li' state.
- Hardened 'ae_idaa_comp__event_obj_li_wrapper.svelte' to filter out 'undefined' entries from database 'bulkGet' calls.
- Cleaned up legacy search handling code in 'ae_idaa_comp__event_obj_qry.svelte'.
- Updated 'TODO.md' and 'GEMINI.md' to reflect search logic hardening accomplishments.
This commit is contained in:
Scott Idem
2026-01-27 13:08:11 -05:00
parent b837e6d0f8
commit 055d8e7816
8 changed files with 258 additions and 787 deletions

View File

@@ -68,56 +68,76 @@
} from '$lib/ae_journals/ae_journals_stores';
import { journals_func } from '$lib/ae_journals/ae_journals_functions';
// Trigger doing a search query for journal entries
$effect(async () => {
if ($journals_trig.journal_entry_qry) {
$journals_trig.journal_entry_qry = false;
// Debounced Search Logic (Refactored 2026-01-27)
let search_debounce_timer: any = null;
let last_search_id = 0;
log_lvl = 1;
$effect(() => {
// Reactive dependencies
const s_search_text = $journals_loc.entry.qry__search_text;
const s_category_code = $journals_loc.entry.qry__category_code;
const s_enabled = $journals_loc.entry.qry__enabled;
const s_hidden = $journals_loc.entry.qry__hidden;
const s_journal_id = $lq__journal_obj?.journal_id;
const s_trigger = $journals_trig.journal_entry_qry;
if (log_lvl) {
console.log(
`Triggered: $journals_trig.journal_entry_qry: text="${$journals_loc.entry.qry__search_text}" cat="${$journals_loc.entry.qry__category_code}"`
);
}
if (search_debounce_timer) clearTimeout(search_debounce_timer);
// $journals_prom.load__journal_entry_obj_qry = journals_func.qry__journal_entry({
$journals_prom.load__journal_entry_obj_li = await journals_func.qry__journal_entry({
// Auto-search if text is cleared or long enough, or if category changes
const should_search = s_trigger ||
s_search_text.length === 0 ||
s_search_text.length >= 3 ||
s_category_code !== '';
if (should_search && s_journal_id) {
search_debounce_timer = setTimeout(() => {
$journals_trig.journal_entry_qry = false;
handle_search_refresh();
}, 400);
}
return () => {
if (search_debounce_timer) clearTimeout(search_debounce_timer);
};
});
async function handle_search_refresh() {
const current_search_id = ++last_search_id;
const qry_str = $journals_loc.entry.qry__search_text;
const category_code = $journals_loc.entry.qry__category_code;
if (log_lvl) console.log(`[Journal Search #${current_search_id}] text="${qry_str}" cat="${category_code}"`);
try {
const results = await journals_func.qry__journal_entry({
api_cfg: $ae_api,
journal_id: $lq__journal_obj?.journal_id ?? '',
qry_str: $journals_loc.entry.qry__search_text,
qry_category_code: $journals_loc.entry.qry__category_code,
// qry_created_on: null,
// qry_alert: null,
// qry_priority: null,
// qry_type: and_type,
qry_str: qry_str,
qry_category_code: category_code,
enabled: $journals_loc.entry.qry__enabled ?? 'enabled',
hidden: $journals_loc.entry.qry__hidden ?? 'not_hidden',
// order_by_li: $journals_loc.entry.qry__order_by_li,
// limit: $journals_loc.entry.qry__limit,
// try_cache: try_cache,
log_lvl: log_lvl
log_lvl: 0
});
if (!$journals_loc.entry.qry__search_text && !$journals_loc.entry.qry__category_code) {
// If search text and category were cleared or empty, reset to default view (null)
$journals_sess.entry_li = null;
} else if ($journals_prom.load__journal_entry_obj_li && $journals_prom.load__journal_entry_obj_li.length > 0) {
$journals_sess.entry_li = $journals_prom.load__journal_entry_obj_li;
$journals_sess = { ...$journals_sess }; // ensure session is updated
} else {
console.log('Clear the search results: no entries found for that query.');
// Explicitly set to empty array to indicate "0 results found" (vs null which is "default view")
$journals_sess.entry_li = [];
}
if (current_search_id === last_search_id) {
$journals_prom.load__journal_entry_obj_li = results;
if (log_lvl) {
console.log(`$journals_sess.entry_li = `, $journals_sess.entry_li);
if (!qry_str && !category_code) {
// Reset to default view if everything cleared
$journals_sess.entry_li = null;
} else {
$journals_sess.entry_li = results || [];
$journals_sess = { ...$journals_sess };
}
if (log_lvl) console.log(`[Journal Search #${current_search_id}] Done. Found ${results?.length ?? 0} results.`);
}
} catch (error) {
if (current_search_id === last_search_id) {
console.error('Journal search failed:', error);
}
}
});
}
</script>
<!-- Search input form -->
@@ -130,7 +150,6 @@
bind:value={$journals_loc.entry.qry__search_text}
onkeyup={(event) => {
if (event.key === 'Enter') {
// $journals_loc.entry.qry__search_text = (event.target as HTMLInputElement).value;
$journals_trig.journal_entry_qry = true;
}
}}
@@ -208,9 +227,7 @@
"
bind:value={$journals_loc.entry.qry__category_code}
onchange={(event) => {
// WARNING: This will cause pages to reset if the journal entry list is being filtered by category. This is a bug that should be fixed.
$journals_loc.entry.qry__category_code = (event.target as HTMLInputElement).value;
// Trigger the query search instead of the full list load
$journals_trig.journal_entry_qry = true;
console.log('Selected category:', $journals_loc.entry.qry__category_code);
}}