build_tmp_sort() encodes priority=true as '0' for ascending sort. JS comparators were using b.localeCompare(a) (descending), inverting the encoding so priority=false items sorted first. Fixed to a.localeCompare(b) in ae_journals_search_helpers.ts (3 sites in recovery_meetings +page.svelte and wrapper component). Also fixes a Dexie anti-pattern in bb/[post_id]: .reverse() before .sortBy() is a no-op in Dexie; moved array .reverse() to after the await. Documents the encoding rule and legacy inverted-encoding modules in GUIDE__SvelteKit2_Svelte5_DexieJS.md and adds mistake #15 to BOOTSTRAP quickstart. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
107 lines
3.3 KiB
TypeScript
107 lines
3.3 KiB
TypeScript
export interface JournalEntrySearchParams {
|
|
str?: string;
|
|
cat?: string | null;
|
|
enabled?: 'enabled' | 'all' | 'not_enabled';
|
|
hidden?: 'hidden' | 'all' | 'not_hidden';
|
|
limit?: number;
|
|
}
|
|
|
|
function normalize_search_value(value: unknown): string {
|
|
if (value === null || value === undefined) return '';
|
|
|
|
if (typeof value === 'string') return value.toLowerCase();
|
|
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
return String(value).toLowerCase();
|
|
}
|
|
|
|
try {
|
|
return JSON.stringify(value).toLowerCase();
|
|
} catch {
|
|
return String(value).toLowerCase();
|
|
}
|
|
}
|
|
|
|
function build_journal_entry_search_blob(entry: any): string {
|
|
return [
|
|
entry?.code,
|
|
entry?.name,
|
|
entry?.short_name,
|
|
entry?.summary,
|
|
entry?.outline,
|
|
entry?.content,
|
|
entry?.history,
|
|
entry?.notes,
|
|
entry?.tags,
|
|
entry?.activity_code,
|
|
entry?.category_code,
|
|
entry?.type_code,
|
|
entry?.topic_code,
|
|
entry?.group,
|
|
entry?.journal_code,
|
|
entry?.journal_name,
|
|
entry?.alert_msg,
|
|
entry?.default_qry_str
|
|
]
|
|
.map(normalize_search_value)
|
|
.filter(Boolean)
|
|
.join(' ');
|
|
}
|
|
|
|
export function journal_entry_matches_search(
|
|
entry: any,
|
|
params: JournalEntrySearchParams
|
|
): boolean {
|
|
if (!entry) return false;
|
|
|
|
const qry_str = (params.str ?? '').toLowerCase().trim();
|
|
const category_code = params.cat ?? '';
|
|
const enabled_mode = params.enabled ?? 'all';
|
|
const hidden_mode = params.hidden ?? 'all';
|
|
|
|
const is_hidden = entry.hide === true || entry.hide === 1;
|
|
const is_disabled = entry.enable === false || entry.enable === 0;
|
|
|
|
if (category_code && entry.category_code !== category_code) return false;
|
|
|
|
if (enabled_mode === 'enabled' && is_disabled) return false;
|
|
if (enabled_mode === 'not_enabled' && !is_disabled) return false;
|
|
|
|
if (hidden_mode === 'hidden' && !is_hidden) return false;
|
|
if (hidden_mode === 'not_hidden' && is_hidden) return false;
|
|
|
|
if (!qry_str) return true;
|
|
|
|
return build_journal_entry_search_blob(entry).includes(qry_str);
|
|
}
|
|
|
|
export function journal_entry_compare_for_list(a: any, b: any): number {
|
|
// 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.
|
|
return (
|
|
(a?.tmp_sort_1 ?? '').localeCompare(b?.tmp_sort_1 ?? '') ||
|
|
(b?.updated_on ?? '').localeCompare(a?.updated_on ?? '') ||
|
|
(b?.journal_entry_id ?? '').localeCompare(a?.journal_entry_id ?? '')
|
|
);
|
|
}
|
|
|
|
export function journal_entry_filter_list(
|
|
list: any[] | null | undefined,
|
|
params: JournalEntrySearchParams
|
|
): any[] | null {
|
|
if (list === undefined || list === null) return null;
|
|
if (!Array.isArray(list)) return [];
|
|
|
|
const has_text_search = Boolean((params.str ?? '').trim());
|
|
|
|
const filtered = list
|
|
.filter((entry) => journal_entry_matches_search(entry, params))
|
|
.sort(journal_entry_compare_for_list);
|
|
|
|
// Broad views should show the full local result set; only text searches
|
|
// should be sliced to a page-sized window.
|
|
if (has_text_search && params.limit && params.limit > 0) {
|
|
return filtered.slice(0, params.limit);
|
|
}
|
|
|
|
return filtered;
|
|
} |