Fix: Align IDAA Event Search with proven Session Search logic

- Backend: Updated `search__event` in `ae_events__event.ts` to populate `params['lk_qry']`.
- Logic: Used `like` operator with wildcards for `default_qry_str` in `search_query` to match `event_session` pattern.
- Context: This fixes the text search in IDAA Recovery Meetings by ensuring the backend receives the expected V3 search parameters.
This commit is contained in:
Scott Idem
2026-01-21 18:45:47 -05:00
parent c782d2273a
commit 6624773d43

View File

@@ -444,73 +444,77 @@ export async function search__event({
}): Promise<ae_Event[]> {
if (log_lvl) console.log('*** search__event() *** [V3]');
const search_query: any = {
and: []
};
let result_li: ae_Event[] | null = null;
if (qry_str) {
// V3 Standard Full-text Search
search_query.q = qry_str;
// Also add to the explicit V3 search body for the event table specifically (legacy behavior support)
if (qry_str && qry_str.trim().length > 0) {
// Option A: Active Text Search
const search_query: any = {
and: []
};
const params: key_val = {};
// Use default_qry_str for searching as requested
// Using 'like' with wildcards and populating params['lk_qry'] to match working event_session logic
search_query.and.push({ field: 'default_qry_str', op: 'like', value: `%${qry_str.trim()}%` });
}
params['lk_qry'] = { 'default_qry_str': qry_str.trim() };
// Use raw field name to bypass backend mapping conflicts
if (for_obj_id) {
search_query.and.push({ field: 'account_id_random', op: 'eq', value: for_obj_id });
}
// Handle conference filter
if (qry_conference !== null) {
search_query.and.push({ field: 'conference', op: 'eq', value: qry_conference ? 1 : 0 });
}
// Location Filtering (Inclusive OR logic)
if (qry_physical === true || qry_virtual === true) {
const or_filters = [];
if (qry_physical === true) or_filters.push({ field: 'physical', op: 'eq', value: 1 });
if (qry_virtual === true) or_filters.push({ field: 'virtual', op: 'eq', value: 1 });
if (or_filters.length > 0) {
// If only one is selected, we can just add it to AND. If both, we'd need OR logic which V3 search body might not fully support nested yet.
// For now, if both are true, we essentially want events that are EITHER physical OR virtual (which is basically all events usually).
// However, the client-side filter in existing logic implies specific filtering.
// Let's rely on the client-side filter for this specific complex OR logic for now to be safe,
// OR if V3 supports 'or' at the top level we could use it, but mixing AND and OR groups in simple search is tricky.
// STRATEGY: Pass through to client-side filtering for these specific flags to match legacy behavior perfectly.
// Use raw field name to bypass backend mapping conflicts
if (for_obj_id) {
search_query.and.push({ field: 'account_id_random', op: 'eq', value: for_obj_id });
}
if (enabled === 'enabled') search_query.and.push({ field: 'enable', op: 'eq', value: 1 });
else if (enabled === 'not_enabled') search_query.and.push({ field: 'enable', op: 'eq', value: 0 });
if (hidden === 'hidden') search_query.and.push({ field: 'hide', op: 'eq', value: 1 });
else if (hidden === 'not_hidden') search_query.and.push({ field: 'hide', op: 'eq', value: 0 });
result_li = await api.search_ae_obj_v3({
api_cfg,
obj_type: 'event',
// Inject header context for Auth but keep body context for Filtering
headers: { 'x-account-id': for_obj_id },
search_query,
params,
enabled,
hidden,
view,
limit: (qry_person_id || qry_conference !== null || qry_physical !== null || qry_virtual !== null || qry_type !== null) ? 500 : limit,
offset,
order_by_li,
log_lvl
});
} else {
// Option B: List All (No text search active)
// Fallback to standard list retrieval to ensure we get results when the search bar is empty.
result_li = await api.get_ae_obj_li_v3({
api_cfg,
obj_type: 'event',
for_obj_type,
for_obj_id,
enabled,
hidden,
view,
limit: (qry_person_id || qry_conference !== null || qry_physical !== null || qry_virtual !== null || qry_type !== null) ? 500 : limit,
offset,
order_by_li,
log_lvl
});
}
// Handle type filter
if (qry_type != null && qry_type !== 'all' && qry_type !== '') {
search_query.and.push({ field: 'type', op: 'eq', value: qry_type });
// Handle potential V3 API envelope { data: [], meta: ... } or direct array
let valid_result_li: ae_Event[] = [];
if (Array.isArray(result_li)) {
valid_result_li = result_li;
} else if (result_li && typeof result_li === 'object' && Array.isArray((result_li as any).data)) {
valid_result_li = (result_li as any).data;
} else {
// If null, undefined, or unknown format, return empty list to prevent iteration errors
return [];
}
if (enabled === 'enabled') search_query.and.push({ field: 'enable', op: 'eq', value: 1 });
else if (enabled === 'not_enabled') search_query.and.push({ field: 'enable', op: 'eq', value: 0 });
if (hidden === 'hidden') search_query.and.push({ field: 'hide', op: 'eq', value: 1 });
else if (hidden === 'not_hidden') search_query.and.push({ field: 'hide', op: 'eq', value: 0 });
const result_li = await api.search_ae_obj_v3({
api_cfg,
obj_type: 'event',
// Inject header context for Auth but keep body context for Filtering
headers: { 'x-account-id': for_obj_id },
search_query,
enabled,
hidden,
view,
limit: (qry_person_id || qry_conference !== null || qry_physical !== null || qry_virtual !== null || qry_type !== null) ? 500 : limit,
offset,
order_by_li,
log_lvl
});
if (!result_li) return [];
const processed_obj_li = await process_ae_obj__event_props({
obj_li: result_li,
obj_li: valid_result_li,
log_lvl: log_lvl
});
@@ -526,15 +530,26 @@ export async function search__event({
// Client-side Filter Layer (Retained for complex OR logic and Person ID checks)
const filtered_obj_li = processed_obj_li.filter((ev: any) => {
// Handle conference filter
if (qry_conference != null) {
const ev_conf = ev.conference === true || ev.conference === 1 || ev.conference === '1';
if (ev_conf !== !!qry_conference) return false;
}
// Handle type filter
if (qry_type != null && qry_type !== 'all' && qry_type !== '') {
if (ev.type !== qry_type) return false;
}
// Location Filtering (Inclusive OR logic)
if (qry_physical === true || qry_virtual === true) {
const ev_physical = ev.physical === true || ev.physical === 1 || ev.physical === '1';
const ev_virtual = ev.virtual === true || ev.virtual === 1 || ev.virtual === '1';
let match = false;
if (qry_physical === true && ev_physical) match = true;
if (qry_virtual === true && ev_virtual) match = true;
if (!match) return false;
}
@@ -653,16 +668,16 @@ export async function qry_ae_obj_li__event_v2({
}
// Location Filtering (Inclusive OR logic)
// If either filter is explicitly true, we restrict results.
// If either filter is explicitly true, we restrict results.
// If both are false or null, we show everything.
if (qry_physical === true || qry_virtual === true) {
const ev_physical = ev.physical === true || ev.physical === 1 || ev.physical === '1';
const ev_virtual = ev.virtual === true || ev.virtual === 1 || ev.virtual === '1';
let match = false;
if (qry_physical === true && ev_physical) match = true;
if (qry_virtual === true && ev_virtual) match = true;
if (!match) return false;
}