diff --git a/src/lib/ae_events/ae_events__event_presentation.ts b/src/lib/ae_events/ae_events__event_presentation.ts index 355694b9..4f6c7b7d 100644 --- a/src/lib/ae_events/ae_events__event_presentation.ts +++ b/src/lib/ae_events/ae_events__event_presentation.ts @@ -680,6 +680,20 @@ export async function process_ae_obj__event_presentation_props({ if (obj.event_session_id_random) obj.event_session_id = obj.event_session_id_random; if (obj.event_id_random) obj.event_id = obj.event_id_random; + + // Override generic tmp_sort_* with presentation-specific encoding. + // WHY: Generic _process_generic_props encodes priority as 0/1 ASC (backwards) + // and sort as an unpadded string ("10" < "2"). Presentations also need + // start_datetime and code in the sort chain, which are not generic fields. + // Desired order: priority DESC → sort ASC → start_datetime ASC → code ASC → name ASC + // Encoding trick: invert priority so true→'0' sorts before false→'1' ascending. + const p = obj.priority ? '0' : '1'; + const s = String(Number(obj.sort ?? 0)).padStart(8, '0'); + const dt = obj.start_datetime ?? ''; + const code = obj.code ?? ''; + const name = obj.name ?? ''; + obj.tmp_sort_1 = `${p}_${s}_${dt}_${code}`; + obj.tmp_sort_2 = `${p}_${s}_${dt}_${code}_${name}`; return obj; } }); diff --git a/src/routes/events/[event_id]/(launcher)/launcher_session_view.svelte b/src/routes/events/[event_id]/(launcher)/launcher_session_view.svelte index 332165c1..9dbe0c55 100644 --- a/src/routes/events/[event_id]/(launcher)/launcher_session_view.svelte +++ b/src/routes/events/[event_id]/(launcher)/launcher_session_view.svelte @@ -91,9 +91,8 @@ let lq__event_file_obj_li = $derived.by(() => { // Event Presentation // WHY: $derived.by — captures id in the outer closure so a new Observable is -// created whenever the session changes. Multi-field sort requires toArray() + JS -// comparator since Dexie's sortBy() is single-field only. -// Order: priority DESC → sort ASC → start_datetime ASC → code ASC → name ASC +// created whenever the session changes. tmp_sort_2 encodes the full sort chain: +// priority DESC → sort ASC → start_datetime ASC → code ASC → name ASC let lq__event_presentation_obj_li = $derived.by(() => { const id = slct__event_session_id; return liveQuery(async () => { @@ -103,32 +102,10 @@ let lq__event_presentation_obj_li = $derived.by(() => { console.log(`[LQ] Fetching presentations for session: ${id}`); } - const results = await db_events.presentation + return await db_events.presentation .where('event_session_id') .equals(id) - .toArray(); - return results.sort((a, b) => { - // priority DESC (true first) - const pa = a.priority ? 1 : 0; - const pb = b.priority ? 1 : 0; - if (pb !== pa) return pb - pa; - // sort ASC - const sa = a.sort ?? 0; - const sb = b.sort ?? 0; - if (sa !== sb) return sa - sb; - // start_datetime ASC - const da = a.start_datetime ?? ''; - const db_val = b.start_datetime ?? ''; - if (da !== db_val) return da < db_val ? -1 : 1; - // code ASC - const ca = a.code ?? ''; - const cb = b.code ?? ''; - if (ca !== cb) return ca < cb ? -1 : 1; - // name ASC - const na = a.name ?? ''; - const nb = b.name ?? ''; - return na < nb ? -1 : na > nb ? 1 : 0; - }); + .sortBy('tmp_sort_2'); }); }); diff --git a/src/routes/events/[event_id]/(pres_mgmt)/session/[session_id]/+page.svelte b/src/routes/events/[event_id]/(pres_mgmt)/session/[session_id]/+page.svelte index 47e61413..23575726 100644 --- a/src/routes/events/[event_id]/(pres_mgmt)/session/[session_id]/+page.svelte +++ b/src/routes/events/[event_id]/(pres_mgmt)/session/[session_id]/+page.svelte @@ -67,40 +67,18 @@ let lq__event_session_obj = $derived( ); // 2. Presentation List Observable -// WHY: Dexie sortBy() is single-field only. Multi-field sort requires toArray() + JS comparator. -// Desired order: priority DESC → sort ASC → start_datetime ASC → code ASC → name ASC +// WHY: tmp_sort_2 encodes priority DESC → sort ASC → start_datetime ASC → code ASC → name ASC +// as a lexicographically correct string. See process_ae_obj__event_presentation_props. let lq__event_presentation_obj_li = $derived( liveQuery(async () => { if (log_lvl) console.log( `[LQ] Querying Presentations for Session: ${url_session_id}` ); - const results = await db_events.presentation + return await db_events.presentation .where('event_session_id') .equals(url_session_id) - .toArray(); - return results.sort((a, b) => { - // priority DESC (true first) - const pa = a.priority ? 1 : 0; - const pb = b.priority ? 1 : 0; - if (pb !== pa) return pb - pa; - // sort ASC - const sa = a.sort ?? 0; - const sb = b.sort ?? 0; - if (sa !== sb) return sa - sb; - // start_datetime ASC - const da = a.start_datetime ?? ''; - const db_val = b.start_datetime ?? ''; - if (da !== db_val) return da < db_val ? -1 : 1; - // code ASC - const ca = a.code ?? ''; - const cb = b.code ?? ''; - if (ca !== cb) return ca < cb ? -1 : 1; - // name ASC - const na = a.name ?? ''; - const nb = b.name ?? ''; - return na < nb ? -1 : na > nb ? 1 : 0; - }); + .sortBy('tmp_sort_2'); }) );