Commit Graph

204 Commits

Author SHA1 Message Date
Scott Idem
3fd6b33d6f fix(events): prune stale event_file records from Dexie after list refresh
bulkPut only upserts — files deleted on the server stayed in Dexie forever,
showing in the Launcher and Manage Files UI until the browser cache was cleared.

After each _refresh_file_li_background call, deleted records are now pruned
from Dexie. Scope-guarded so we only remove records that would have appeared
in the query (e.g. hidden files are not pruned after a hidden='not_hidden' fetch).
Also covers the disable (enable=false) case the same way.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 10:02:40 -04:00
Scott Idem
29c5a9fa82 fix(pres_mgmt): hidden files now visible in Manage Files without manual refresh
Background file loads for session, presentation, and presenter were using the
default hidden='not_hidden', so hidden files never reached Dexie. The Manage
Files liveQuery reads straight from Dexie, making hidden files completely
invisible until the Refresh button was clicked (which already used hidden='all').

The Launcher is unaffected — it has always had a render-time guard that hides
files with event_file_obj.hide unless show_content__hidden_files is enabled.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 01:54:54 -04:00
Scott Idem
ae00ddffb0 fix(badges): fix Printed/Not Printed filter visibility and API query
Two bugs:

1. visible_badge_obj_li gated on trusted+edit_mode, but the filter
   dropdown is also accessible to manager+ without edit_mode. Changed
   gate to (trusted+edit) || manager_access to match the filter's own
   access condition.

2. not_printed API query used print_count eq 0, which does not match
   NULL in SQL. Unprinted badges have print_count = NULL, so the API
   was returning 0 results and overwriting the correct IDB fast-path
   results. Removed the not_printed condition from the API query —
   IDB fast path (print_count ?? 0) < 1 and visible_badge_obj_li
   both handle NULL correctly and are the authoritative filter for
   that case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 19:39:58 -04:00
Scott Idem
c7fa75afc7 ui(badges): add background image bleed support (cfg_json, PVC layout)
- Add `bleed` field to BadgeTemplateCfg (CSS length, e.g. "0.125in")
- Badge view: derive bleed_offset, move bg-image to absolute positioned div
  that extends past card edges; add isolation:isolate to badge_front stacking context
- Template form: add bleed input in Advanced > Appearance; wire to cfg_json save/load
- PVC layout CSS: change overflow:hidden → overflow:visible in print rule to allow
  bleed div to render at physical card boundary (Zebra driver clips at card edge)
- Prevents white borders on PVC cards when printer has slight alignment variance.
  Screen preview shows bleed visually extending past the card outline.
2026-04-10 14:25:08 -04:00
Scott Idem
c9e2284758 Badges: per-badge locked font sizes via cfg_json
Allows coordinators to pre-tune font sizes for attendees with long names
and have those sizes apply automatically on every kiosk, not just one machine.

- ae_types.ts: add cfg_json to ae_EventBadge interface
- db_events.ts: add cfg_json to Badge Dexie interface
- ae_events__event_badge.ts: add cfg_json to properties_to_save so it is
  persisted to IndexedDB on load and returned by the API
- print/+page.svelte: on first load per badge, read cfg_json.font_sizes and
  initialize font_size_name/title/affiliations/location state from saved values
  (guarded by _font_sizes_loaded_for to avoid clobbering user adjustments on
  background liveQuery refreshes)
- ae_comp__badge_print_controls.svelte: add lock_font_sizes() and
  reset_font_sizes_to_auto() functions; add Lock Sizes / Auto reset UI in the
  Staff adjustments section (trusted-only); button shows warning style when
  sizes are unsaved vs success when locked; status indicator shows what is
  currently locked

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:47:34 -04:00
Scott Idem
b02843e467 feat(badges): cfg_json body_text_color applied in renderer 2026-04-08 12:32:13 -04:00
Scott Idem
ae9cdaf9f1 badges: per-tier search limits — result cap + min chars, config UI
Add anonymous/auth/trusted search constraints to BadgesRemoteCfg with
conservative defaults (anon: 15 results / 3 chars, auth: 25 / 2,
trusted+: 150 / 1). Configurable per event via mod_badges_json.

- BadgesRemoteCfg + BadgesLocState: 6 new fields with defaults
- sync_config__event_badges: mirrors new fields from mod_badges_json
- +page.svelte: effective_search_limits derived by tier using $ae_loc
  cumulative flags; enforces min_chars guard and result cap on both
  local IDB path and API call
- ae_comp__badge_search: effective_min_chars derived same way; blocks
  search trigger below threshold; shows dynamic hint text
- Fallback broad search (SCENARIO 2) suppressed for non-trusted users
  so no results show on page load without a query
- config/+page.svelte: Search Limits section with 3-column number
  inputs (Anonymous / Auth / Trusted+) for result limit and min chars

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 18:08:10 -04:00
Scott Idem
93fea0d165 Making custom changes just for Axonius badge printing next week 2026-04-07 14:59:23 -04:00
Scott Idem
34bf823987 chore(badges): save in-progress changes — background_image_path, cfg_json support, template form TS fix, view boolean fixes 2026-04-07 13:57:02 -04:00
Scott Idem
d340bbbe94 test: seed ae_leads_loc; update badge tests and helpers; docs: note Leads migration 2026-04-03 17:47:10 -04:00
Scott Idem
5971ca6143 fix: use file_count_all + is_null for sessions-without-files query
Two corrections to the qry_files filter:
1. Switch from file_count to file_count_all — covers files on presentations
   and presenters under the session, not just direct session files.
2. Switch "without files" from eq:0 to is_null — the view uses a LEFT JOIN
   so sessions with no files get NULL, never 0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:08:43 -04:00
Scott Idem
cf7203daaf fix: implement qry_files filter in search__event_session (sessions with/without files)
qry_files was accepted as a parameter but never applied to the search query,
causing the "Sessions With/Without Files" report toggle to always return all
sessions regardless of the setting.

When qry_files !== null, automatically switch to the 'alt' view
(v_event_session_w_file_count) which exposes file_count, then add:
  true  → file_count > 0  (sessions with files)
  false → file_count = 0  (sessions without files)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 18:58:39 -04:00
Scott Idem
c198ca2454 chore(badges): remove legacy badge_id_only_search; sync remote badges config into badges_loc; docs update 2026-04-02 18:03:23 -04:00
Scott Idem
fface58751 fix: add default_qry_str to db_events Event interface, remove incorrect global augment
The field exists on the DB object but was missing from the TypeScript interface,
causing a false error in recovery_meetings search. Added it to db_events.ts where
it belongs. Removed the incorrect global DOM Event augment from the temp augments
file (was patching the wrong interface).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 16:04:49 -04:00
Scott Idem
4a1b0dac86 pres_mgmt config: remove legacy launcher option, add back button + dirty state to config UI
- Remove show__launcher_link_legacy from PressMgmtRemoteCfg, PresMgmtLocState, and
  pres_mgmt_loc_defaults — the Flask/legacy launcher is retired
- Sync function now hardcodes hide__launcher_link_legacy=true (always hidden)
- Config page: back button to pres_mgmt, save buttons disabled until changes made
- Fix {#each} key expressions in config page
- Migrate e_app_access_type and element_manage_event_file_li to pres_mgmt_loc store
- Add temporary svelte type augments file (src/types/)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 15:53:55 -04:00
Scott Idem
fd9e5f6dc0 pres_mgmt: migrate to typed PersistedState store, canonical config schema
Replaces untyped $events_loc.pres_mgmt (svelte-persisted-store) with a
dedicated pres_mgmt_loc (runed PersistedState) backed by a fully typed
PresMgmtLocState interface and PressMgmtRemoteCfg for the server-side JSON.

Key changes:
- ae_events_stores__pres_mgmt_defaults.ts: canonical interfaces + defaults
  covering all hide__/show__ fields, labels, report prefs, query filters,
  and lock_config sync fields; qry_enabled uses 'not_enabled' (matches API)
- ae_events_stores__pres_mgmt.svelte.ts: new PersistedState store
- ae_events__event.ts: sync_config__event_pres_mgmt() rewired to write
  directly to pres_mgmt_loc.current; launcher link inversion preserved
- All 26+ pres_mgmt templates migrated from $events_loc.pres_mgmt.* to
  pres_mgmt_loc.current.*
- New config UI at (pres_mgmt)/pres_mgmt/config/ — manager + edit mode only
- Event settings page: removed embedded pres_mgmt form, links to config page
- event_page_menu: Config button visible only when manager_access + edit_mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 15:27:12 -04:00
Scott Idem
75664ad2e1 feat(pres_mgmt): restore location and description editing in session view
Event location (FK lookup) and description were both visible in the session
view but had no edit controls — lost during V3 migration. Restored both:

- event_location_id: select dropdown populated from this event's location list
  (liveQuery on db_events.location filtered by event_id from the session object)
- description: textarea editor shown directly in edit_mode (no collapse needed
  when actively editing)

Also added event_location_id to editable_fields__event_session, which was
missing and would have caused backend rejections on PATCH.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 13:44:00 -04:00
Scott Idem
d12a4bf71f feat(events): restore inc_file_counts opt-in, session list layout + button polish
- Add `inc_file_counts` flag to `load_ae_obj_id__event_session` — maps to
  backend alt view (v_event_session_w_file_count) when true; default stays
  lightweight. Callers never pass raw view names.
- Preserve-on-write fallback in `_refresh_session_id_background` keeps
  cached file_count/file_count_all if API response omits them.
- Session detail +page.ts uses `inc_file_counts: true` so SvelteKit prefetch
  no longer clobbers counts via bulkPut on hover.
- Remove explicit `view: 'alt'` from launcher +page.ts (now invalid param).
- Session list link: flex-1 + min-w-0 for full-row width; name flex-1 pushes
  badge group right; code + file_count stacked in flex-col items-end.
- Hover styling: button-like appearance with slow fade-out (duration-500) /
  fast snap-in (hover:duration-150).
- Session +page.svelte: use url_session_id (string) for link_to_id props and
  auth__kv.session[] index — fixes TS type error from number|undefined.
- IDAA layout: dormant tech notice banner (guarded by 1==3, remove when ready).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 16:38:13 -04:00
Scott Idem
ae4b94f1b2 fix(idaa): expand recovery_meetings search to use default_qry_str from API
Backend updated (2026-03-31) to return default_qry_str in event API responses.
Frontend now stores it via properties_to_save and searches it in both the local
Dexie fast-path filter and the secondary post-API client filter. Previously, the
server searched default_qry_str (e.g. day-of-week, recurring_text) while the
client only checked name/description/location_text -- causing local results to
drop valid matches on revalidation (e.g. searching 'Thursday').

Also adds TODO note to audit other event search pages for the same mismatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 16:16:43 -04:00
Scott Idem
9d44b9341c Now with the ability to actually create a badge. We still need to make this look nicer. Buttons should look more like button and consistent with the other areas of AE Events Badges. Also take a look at the trigger updated fields. 2026-03-27 11:51:42 -04:00
Scott Idem
f87ab10251 feat(badges): add manual one-off badge create modal
Two-step creation: POST event_person first, then event_badge linked to it.
Badge create route (event_person parent) pending backend fix — frontend is
ready and passing event_person_id + event_badge_template_id in payload.

- ae_events__event_person.ts: new create function (nested under event)
- ae_events_functions.ts: export create_ae_obj__event_person
- ae_comp__badge_create_form.svelte: modal form with live name preview,
  conditional display-name override, template selector (auto-selects when
  only one template), badge_type_code_li derived from selected template's
  badge_type_list JSON, two-step submit status labels
- +page.svelte: load template list via liveQuery, wire Create Badge button
  (edit_mode only), native <dialog> modal with backdrop, remote-first
  refresh on success

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 09:59:46 -04:00
Scott Idem
a8f3c29b9f Last round of prettier: npx prettier --write src/ 2026-03-24 13:27:40 -04:00
Scott Idem
94849137f0 I think pretty much all references to v1 and v2 have been removed. All files have been renamed from _v3 to just the function/var name with out the appended version. Assume no _vX is the current version. 2026-03-24 11:32:06 -04:00
Scott Idem
512e5ef87c Saving more code clean up and removal 2026-03-24 11:15:01 -04:00
Scott Idem
d27ec58fe9 More code clean up 2026-03-24 10:56:31 -04:00
Scott Idem
42358efe7d More code clean up 2026-03-24 10:54:40 -04:00
Scott Idem
0bc71391fc Cleaning up and removing old legacy code and files 2026-03-24 10:28:54 -04:00
Scott Idem
6662e82f40 feat: leads re-enable flow — detect removed leads on scan + Remove/Restore buttons
- QR scanner (single + multi): detect previously-removed leads via IDB enable flag;
  route to 'reenable' state instead of duplicate error; offer Re-activate button
- API fallback: if create fails and no IDB record, search API for disabled tracking
  record by event_exhibit_id + event_badge_id (adds qry_badge_id param to
  search__exhibit_tracking)
- Lead detail page: Replace raw enable checkbox with Remove Lead (two-click confirm,
  navigates back after) and Restore Lead card (shown when enable is falsy)
- Fix flash of disabled records in leads list: filter !enable in both filtered_lead_li
  derived and local IDB fast-path in handle_search_refresh
- eslint.config.js: disable svelte/no-navigation-without-resolve (no base path configured)
- Also includes _random field annotation cleanup (db_events, ae_types), iframe layout
  fixes, badge view tweaks, test updates, and doc updates from prior session

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 18:18:10 -04:00
Scott Idem
519f5b949c chore: move ae_events_functions.ts into ae_events/ module
Relocates the functions file from lib root into its module directory,
matching the pattern used by all other modules (ae_journals, ae_archives, etc.).
Updated all 85 import paths from \$lib/ae_events_functions → \$lib/ae_events/ae_events_functions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 09:52:13 -04:00
Scott Idem
621a637b85 feat: badge print UX improvements — chrome toggle, banner width, overlap fix, header centering
- Replace ae_comp__badge_obj_view_v2 with ae_comp__badge_obj_view (consolidated component)
- Add hide-chrome toggle ([H] shortcut + button) to hide site nav/footer/sys bar for clean print workspace
  — syncs $ae_loc.sys_menu.hide + $ae_sess.disable_sys_nav/footer with restore-on-unmount
- Add banner_full_width toggle (default true=100% width, false=natural pixel size for calibration)
- Center badge header image (display:block; margin:0 auto) — was left-aligned when narrower than badge
- Fix controls panel overlap: move from bottom-0 to bottom-24 to clear sys bar (84px tall)
- Add [H] keyboard shortcut for chrome toggle (guards against focus in inputs)
- Persist hide_chrome and banner_full_width in ae_badge_print_tweaks localStorage key
- Add sample header image assets (calibration SVG/PNG, hex blue SVG/PNG, demo PNG)
- Update badge PVC CSS layout and module docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 15:42:22 -04:00
Scott Idem
464b63c1a3 refactor(leads): export function → V3 action endpoint
Updated download_export__event_exhibit_tracking to call
/v3/action/event_exhibit/{exhibit_id}/tracking_export instead of the
legacy /event/exhibit/{exhibit_id}/tracking/export (V1 path).

Added doc comment listing the expected export columns so the backend
agent has the full field spec when implementing the endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 16:05:18 -04:00
Scott Idem
6ca2314472 Badges: fix print page svelte-check error — extract print CSS to static file
Svelte 5 does not support <style> or conditional {#if} blocks wrapping
<style> tags inside <svelte:head>. The parser treats them as raw-text
elements and reports '<script> was left open' at EOF.

Fix:
- Print media CSS moved to static/ae-print-badge.css (plain static file,
  no framework magic needed — all selectors target global elements).
- svelte:head now uses a simple <link> to that file.
- $effect injects the @page size dynamically per template layout field,
  avoiding the Svelte 5 parser limitation for conditional style injection.
- Badge_template interface in db_events.ts: added cfg_json / data_json
  (standard Aether object fields that were missing from the type).
2026-03-16 13:50:28 -04:00
Scott Idem
b4ab60ebba Badges: PVC wrapper hugs card tightly; hide 'Front of badge' label when single-sided 2026-03-12 16:05:08 -04:00
Scott Idem
fde3801ea6 refactor: clean up try_cache defaults and add SWR to sponsorship loaders
- Remove vestigial try_cache param from generate_qr_code (never used in body)
- Remove vestigial try_cache from ae_core_functions: load_ae_obj_id__site_domain,
  update_ae_obj_id_crud, update_ae_obj_id_crud_v2 (none referenced it in body)
- Add proper SWR pattern to load_ae_obj_id__sponsorship_cfg and
  load_ae_obj_id__sponsorship; change defaults from false to true
- Change load_ae_obj_id__event_file default try_cache from false to true
  (consistent with load_ae_obj_li__event_file)
- Change load_ae_obj_id__hosted_file default try_cache from false to true
  (consistent with load_ae_obj_li__hosted_file)
- Remove stale try_cache arg from element_ae_crud.svelte caller
2026-03-11 14:57:23 -04:00
Scott Idem
04a8edc6d1 [Perf] Fix liveQuery reactivity, silence debug logs, add performance guidelines
- launcher/+layout.svelte: convert lq__event_session_obj from $derived to
  $derived.by() so Svelte tracks event_session_id as a dependency; the old
  pattern read the store inside the Dexie async callback where Svelte's
  tracking is off, so the liveQuery never updated on session change
- ae_events__event_file.ts: fix hardcoded log_lvl: 2 in SWR fire-and-forget
  background refresh (always-on debug logging on every cache hit) → 0
- e_app_sign_in_out.svelte: lower 6 call-site log levels (1×log_lvl:2,
  5×log_lvl:1) to 0; sign-in runs on every page load
- element_manage_hosted_file_li.svelte: log_lvl:2 → 0 in refresh call;
  remove log_lvl=1 assignment + debug block inside click handler; log_lvl:1
  → 0 in delete call
- AE__Performance_Guidelines.md: add 5 Svelte 5 runes rules covering
  $derived.by() for reactive liveQuery, liveQuery purity, cheap equality
  guards ($id+updated_on, ID-join, shallow_equal), untrack() requirement,
  and log_lvl discipline

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 15:01:42 -04:00
Scott Idem
46c2d2da12 Launcher: preserve legacy address fields in IDB; add file_sync to loop_info
ae_events__event.ts: Add legacy flat address fields (address_name,
address_line_1, address_city, etc.) to properties_to_save. Events
predating location_address_json still return these flat fields from
the API; they must survive an IDB round-trip without being stripped
by _process_generic_props, or the edit form's fallback reads return
undefined.

launcher_background_sync.svelte:
- Move file_sync interval into loop_info $state alongside other
  intervals; load from cfg/device config with fallback (30 s). Keeps
  all intervals in one place for UI display consistency.
- Align onMount fallback values to match loop_info defaults.
- Add sync_paused mid-loop break: long sync cycles now honour a pause
  request per-iteration rather than waiting for the entire batch.
2026-03-10 14:21:37 -04:00
Scott Idem
73597cb8b4 chore: svelte-check cleanup — fix Svelte 5 patterns in events/pres_mgmt, badges, launcher, and tests
Source changes (0 errors, 175 warnings after):
- api_post__crud_obj_v3: add backward-compat migration aliases (for_obj_type/id, obj_type/id) to nested CRUD funcs
- ae_events__event_device/presenter/session: make event_id/presentation_id optional; fall back to store value
- element_ae_obj_field_editor_v3: import type Snippet properly; mark current_value as $bindable()
- ae_comp__badge_obj_view: fix $derived(() => false) → $derived(false) for show_receipt/show_tickets
- badge templates: pass explicit event_id param to delete/update calls
- launcher/+page: capture URL params as stable consts; pass event_id to update_ae_obj__event_device
- ae_comp__event_device_obj_li: wrap setInterval in $effect; onDestroy cleanup always registered
- ae_comp__event_device_obj_li_wrapper: move console.log to $effect; fix self-closing tag
- presenter form/menu/view/list: add missing event_presentation_id to all update/delete calls
- reports/locations/presenter/+page: move store assignments into $effect + untrack; ae_acct → $derived
- session/+page: add Comp_event_presenter_form_agree import; cast for type compat
- session_view: wrap <img onclick> in <button> for accessibility/validity
- ae_comp__event_presentation_obj_li: remove unneeded event_id/session_id from create_ae_obj__event_presenter
- ae_comp__event_session_obj_li: make lq prop optional; add plain-array fallback prop
- location/+page: refactor to $derived ae_acct, $effect+untrack for stores, simplified session/file sections
- location_page_menu: add optional data prop; export interface

Tests:
- Rename ae_events__event_badge.spec.ts → ae_events__event_badge.test.ts (extended coverage)
- All test files: 'warn' → 'warning' (Playwright API), addInitScript array-destructure pattern, import type fixes
- ae_defaults: remove duplicate hide_app_cfg key; meaningful sponsorship cfg_id placeholder
- create_event_badge.spec: fix import path to use $lib alias
- event_presenter.test: fix test URL to use /presenter/:id route

NOTE: location/+page.svelte — Element_manage_event_file_li_wrap no longer receives
allow_basic/allow_moderator (now default false); file list shows but management
actions may be restricted. Follow-up needed to restore auth__kv-based access.
2026-03-05 20:05:35 -05:00
Scott Idem
b064d8c235 feat(leads): V3 API migration, QR Scanner v3, and Exhibitor Leads UI overhaul
- Migrate event_exhibit and event_exhibit_tracking CRUD to V3 API (parent_type/child_type params).
- Implement Element_qr_scanner_v3.svelte: A Svelte 5 / Runes component using html5-qrcode with auto-start and unique viewfinder IDs.
- Integrate QR Scanner v3 into ae_comp__badge_search.svelte and lead capture.
- Refactor Exhibitor Leads UI:
  - Add 'Rapid Scan' vs 'Qualify Mode' toggles for efficient lead capture.
  - Upgrade ae_comp__lead_detail_form.svelte to support new question/response schema with backward compatibility.
  - Implement 'Sign Out of Booth' functionality in exhibit management.
  - Optimize lead detail layout for mobile readability and high information density.
  - Fix component prop sync for event_id and exhibit_id.
- UI/UX refinements: standardizing icons (SquarePen), cleaning up unused imports, and improving responsive states.
2026-03-03 18:49:57 -05:00
Scott Idem
5c3823f41a feat(badges): implement badge print controls panel and refine badge overrides
- Create ae_comp__badge_print_controls.svelte: A fixed-right-edge panel for per-field accordion controls, font size adjustments, and inline editing.
- Refactor print/+page.svelte to integrate the new controls panel and standardize font size state management via $bindable() props.
- Update ae_comp__badge_obj_view.svelte and ae_comp__badge_review_form.svelte to correctly sync badge_type_code_override and badge_type_override.
- Improve badge_type_name derivation logic to prioritize staff overrides.
- Hide unused receipt/ticket sections in badge view pending future redesign.
- Update documentation (PROJECT and TODO) to reflect completion of Task 3.
2026-03-02 19:47:11 -05:00
Scott Idem
32e9550ca2 feat(badges): layout CSS system — data-layout attribute, @page injection, style_href
Two compiled layout CSS files in src/lib/ae_events/badges/css/:
  - badge_layout_epson_4x5_fanfold.css — 4"×5" per side, Epson ColorWorks C3500
    fanfold duplex; preferred for general conference use (ISHLT, demos)
  - badge_layout_zebra_zc10l_pvc.css — 3.5"×5.5" PVC card, Zebra ZC10L,
    single-sided (pair with duplex=0 on template)

Rules scoped under [data-layout="..."] on the wrapper — beats Tailwind utility
class specificity without !important. Vite hot-reloads these in dev.

Badge component: add data-layout attribute from template.layout field; import
both layout CSS files (falls back to Tailwind 4"×6" defaults if layout unset).

Print page svelte:head: inject @page paper-size rule per layout code
(@page cannot use attribute selectors so it must be dynamic). Also wire
style_href as a <link> for per-event external client branding CSS.

db_events.ts Badge_template interface: add style_href and duplex fields.
MODULE doc: update layout codes table with badge_4x5_fanfold entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 16:53:32 -05:00
Scott Idem
51cfcbf2d6 feat(badges): wire duplex field — hide badge back for single-sided templates
- Add duplex + style_href to properties_to_save so they're cached in IDB
- Derive show_badge_back: true when duplex is null/unset (safe default for
  existing templates) or 1; false when duplex=0 (single-sided, e.g. Axonius
  NYC using Zebra ZC10L PVC cards)
- Wrap entire badge_back section in {#if show_badge_back} so the DOM node
  is fully removed rather than just hidden — cleaner than a CSS class approach

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 16:06:51 -05:00
Scott Idem
9939d94970 feat(badges): badge review form + expand properties_to_save
ae_comp__badge_review_form.svelte:
- Full implementation of the badge review form (Task 1)
- Editable fields gated by access level (attendee / trusted / admin)
- Save/cancel with change detection, override revert buttons
- QR code display (hover zoom + click expand)
- Print status section, options/tickets, T&C block
- HTML rendering for name/title/affiliations/location fields
- Accessibility font-size toggle (text-2xl ↔ text-4xl)
- Help modal (Flowbite) with 6 sections
- Local edit mode — never writes to $ae_loc.edit_mode

ae_events__event_badge.ts:
- Add missing fields to properties_to_save so they are persisted to IDB:
  pronouns_override, phone, phone_override, registration_type(_code/_override),
  allow_tracking, agree_to_tc, other_1-8_code, ticket_1-8_code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 19:02:56 -05:00
Scott Idem
dc0f3066b3 fix(badges): support multi-word fulltext search
- Split search query by spaces
- Apply AND logic: all words must match
- Single word: LIKE '%word%'
- Multi-word: LIKE '%word1%' AND LIKE '%word2%'

Example: 'scott idem' now searches for both 'scott' AND 'idem'
Previously searched for literal 'scott idem' phrase which failed.

Fixes search bug discovered during Playwright test development.
2026-02-26 17:08:27 -05:00
Scott Idem
b28595dad8 fix(badges): return processed data from all badge API functions
CRITICAL FIX (same pattern as event_file fix):
- search__event_badge(): Now returns processed_obj_li instead of unprocessed result_li
- load_ae_obj_id__event_badge(): Returns processed object after IDB save
- load_ae_obj_li__event_badge(): Returns processed list after IDB save
- create_ae_obj__event_badge(): Returns processed object after IDB save
- update_ae_obj__event_badge(): Returns processed object after IDB save

Pattern: All functions now return what was actually saved to IDB (processed data)
This ensures consistency between API return values and IDB cached data.

TEST IMPROVEMENTS:
- Add full_name field to badge mock data (not just full_name_override)
- Ensures mock data matches real API structure
2026-02-26 15:59:25 -05:00
Scott Idem
9547da6da6 fix(events): Fix pres mgmt reports data loading and field mapping
- Fix session detail page params not being passed to component (causing undefined session_id)
- Fix wrapper components discarding API enriched data by re-fetching from IDB
- Fix event_file, event_session, event_presenter wrappers to preserve API data
- Add optional chaining for hash_sha256 field to prevent undefined crashes
- Fix search__event_file to always process API results before returning
- Ensures hosted_file_size -> file_size field mapping for reports
- All pres mgmt reports (files, sessions, presenters) now work on cold-start
2026-02-26 14:36:46 -05:00
Scott Idem
3849118fec Fix: Event session cold-start bug - presentations/presenters now load on first render
CRITICAL BUG FIX: Session view required 1-2 manual refreshes to display
presentations and presenters when IndexedDB was empty.

Root Cause:
- Nested loaders passed try_cache: false, preventing IDB writes
- Missing microtask yields caused race conditions between IDB writes
  and liveQuery subscriptions

Changes:
- ae_events__event_session.ts: Preserve try_cache in nested loads
- ae_events__event_presentation.ts: Block on presenter loads with await
  Promise.all() + preserve try_cache
- ae_events__event_presenter.ts: Add microtask yield after IDB write

Result: Presentations AND presenters now render correctly on first
navigation without requiring manual page refresh.
2026-02-26 13:40:36 -05:00
Scott Idem
7b5c7528b6 All of the changes from today (Wednesday February 25, 2026) need to be reviewed. We spent over 6 hours trying to fix the page loading when viewing a fresh Session ID and Presentation ID. OpenAI and Gemini failed hard!!! I am at a lost and frustrated. I will probably need to deal with this myself. :-/ 2026-02-25 18:34:21 -05:00
Scott Idem
17620b6fbc refactor(events): enforce hierarchy consistency and id standardization 2026-02-25 17:53:20 -05:00
Scott Idem
197adff33b tests: add Playwright event badge CRUD + interaction tests; add minimal V3 mocks and env helper; update presenter/badge smoke tests to use helpers; convert test locals to snake_case 2026-02-24 17:49:43 -05:00
Scott Idem
f2c426b595 test: combine and modernize private-network checks; remove legacy disabled variants 2026-02-24 16:38:36 -05:00