Commit Graph

925 Commits

Author SHA1 Message Date
Scott Idem
de8b85bb05 fix(events): refresh file list on mount to populate event_session_type_code in Dexie
The presenter detail page loads files with try_cache:false, which fetches
fresh data from the API but does NOT write it to Dexie (by design in the
SWR implementation). The file list's liveQuery then reads stale Dexie
records that lack event_session_type_code, causing the PDF→image convert
button condition to silently fail for presenter files in poster sessions.

Fix: trigger a try_cache:true background refresh on mount in the direct
wrapper so fresh API data (with event_session_type_code='poster') is
persisted to Dexie and the liveQuery re-renders with the correct field.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 13:33:31 -04:00
Scott Idem
b2fa1a59dc feat(events): add PDF→webp convert button to event file list view
Mirrors the convert button added to the table view (ae_comp__event_file_obj_tbl).
The list view (element_manage_event_file_li) is the primary Pres Mgmt UI
for managing event files per object (session, presenter, location, etc.).

Same conditions: edit_mode on, extension=pdf, event_session_type_code=poster.
Per-row status: idle → converting → done | error with retry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 13:24:41 -04:00
Scott Idem
241e05bc79 feat: add store_versions.ts — localStorage schema versioning for ae_loc and ae_events_loc
Persistent stores grow and change over time. svelte-persisted-store deep-merges
old localStorage values with new defaults, so stale values (e.g. hash_prefix_length: 1)
silently survive schema changes and cause subtle bugs.

- src/lib/stores/store_versions.ts:
  Single source of truth for AE_LOC_VERSION / AE_EVENTS_LOC_VERSION.
  Side-effect on import: reads raw localStorage and wipes if __version mismatches.
  Must be imported first in ae_stores.ts and ae_events_stores.ts so the wipe
  happens before persisted() hydrates from localStorage.

- ae_stores.ts + ae_events_stores.ts:
  Import store_versions as first import; add __version to persisted store defaults.

- documentation/TODO__Agents.md:
  Added stores refactor task — both store files need a cleanup pass.

Bump AE_LOC_VERSION or AE_EVENTS_LOC_VERSION by 1 on breaking schema changes.
Non-breaking changes (new optional fields, default value tweaks) do not need a bump.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 12:43:05 -04:00
Scott Idem
93efabdf00 docs(electron): fix cross-repo confusion, remove misplaced file, update integration docs
- Remove tmp_shell_handlers.ts from SvelteKit repo — this was a draft of the
  Electron main-process shell handler that was placed in the wrong repo. It used
  ipcMain (Electron main-process only) and could never run in SvelteKit. Was not
  imported anywhere but was misleading.

- Fix src/lib/electron/README.md:
  - Correct broken doc link (was AE_EVENTS_LAUNCHER_NATIVE_INTEGRATION.md,
    actual filename is PROJECT__AE_Events_Launcher_Native_integration.md)
  - Mark electron_native.js as DEPRECATED — do not import (was described as
    active "Bridge Logic", which was incorrect and confusion-causing)
  - Add clear bridge architecture diagram showing the three-layer flow
  - Note that aether_app_native_electron/ is the active Electron repo

- Update PROJECT__AE_Events_Launcher_Native_integration.md:
  - Fix Layer 1 file path: aether_app_native/ → aether_app_native_electron/
  - Section 5.3: Phase 5 actuators are all implemented, not "planned" — update
    recording, display layout, power control, window control, wallpaper to reflect
    actual implementation status; note update_app is a stub
  - Section 7: Expand IPC whitelist to cover all relay functions including new
    cleanup_tmp_files, system handlers, and full parameter signatures
  - Document get_seed_config / get_jwt as intentionally not relayed to UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 11:59:29 -04:00
Scott Idem
f6344008ea security: use bootstrap key in manifest, add .tmp cache cleanup
- manifest.webmanifest/+server.ts: swap PUBLIC_AE_API_SECRET_KEY →
  PUBLIC_AE_BOOTSTRAP_KEY (least privilege; endpoint only needs a
  site-domain lookup, same as the bootstrap use case)
- electron_relay.ts: add cleanup_tmp_files() — runs `find ... -name
  "*.tmp" -mmin +N -delete` via native run_cmd bridge
- launcher_background_sync.svelte: call cleanup_tmp_files() on mount
  when is_native && cache_root are present (once per startup)
- AE__Permissions_and_Security.md: close Sev-1 audit language
- TODO__Agents.md: mark PUBLIC_AE_API_SECRET_KEY audit as complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 10:54:17 -04:00
Scott Idem
9646f7fec2 fix: remove dead PUBLIC_TESTING import from ae_stores.ts 2026-03-10 16:40:21 -04:00
Scott Idem
a3d7ea7a78 [Cleanup] Guard remaining unguarded console.log calls
- core__crud_generic.ts: guard patch result logs (lines 246/252) with
  if (log_lvl) — these fired on every successful patch call
- e_app_sign_in_out.svelte: already committed in previous round
- element_manage_hosted_file_li.svelte: already committed in previous round

All other console.log calls in launcher/lib files confirmed already guarded
via $B2 context check. Remaining unguarded logs are in event handlers
(fire on user action only, not hot render paths) or testing/admin pages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 15:07:01 -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
206faf0c71 fix: resolve TS errors and Svelte 5 state_referenced_locally warnings
- e_app_sign_in_out: type user_id/person_id as string|null (TS errors)
- archives/[archive_id]/+page.svelte: move if(browser) block to onMount
- ae_idaa_comp__archive_obj_id_edit: wrap timezone loader in onMount
- ae_idaa_comp__archive_content_obj_id_edit: wrap timezone loader in onMount
- bb/[post_id]/+page.svelte: move if(browser) block to onMount
- TODO: add completed entries, note remaining recovery_meetings warnings
2026-03-09 19:40:36 -04:00
Scott Idem
9b7832ee55 feat(themes): Add AE_Firefly variant themes — SteelBlue, Indigo, Rainbow
Three new Firefly-family themes following the AE_Firefly design system:
- AE_Firefly_SteelBlue: metallic steel blue primary (~214°), burnished gold
  secondary, cobalt navy tertiary, chrome silver surfaces
- AE_Firefly_Indigo: deep indigo primary (~266°), violet secondary, dusty
  rose tertiary, velvet slate surfaces
- AE_Firefly_Rainbow: coral-red primary (~15°), emerald green secondary,
  rich violet tertiary, sunrise cream surfaces (spans the visible spectrum)

All variants share consistent semantic colors (success/warning/error) with
AE_Firefly for cross-theme recognizability. All WCAG 2.1 AA compliant.

Also adds URL param support for theme switching:
- ?theme=AE_Firefly_SteelBlue&theme_mode=dark
- Params applied to ae_loc (persisted), then silently removed via replaceState
2026-03-09 19:22:17 -04:00
Scott Idem
37e7a93617 fix(api): suppress send_email() in test/Playwright environments
Add a guard at the top of send_email() that checks globalThis.__ae_test_mode.
If truthy, logs a suppression message and returns null immediately so no HTTP
request is made. This prevents real emails being sent when Playwright tests
exercise components that call send_staff_notification_email() after a successful
save. Activate by setting window.__ae_test_mode = true in addInitScript.
2026-03-09 17:53:45 -04:00
Scott Idem
eb0dcb17f8 fix(idaa): upgrade Novi UUID verification to server-side API call
Previously, IDAA iframe access relied on trusting URL params (uuid, email,
full_name) passed from Novi — any 36-char string granted authenticated access
with no actual verification.

The (idaa)/+layout.svelte now performs an async Novi API call on every UUID
load to verify the UUID exists, fetches name/email directly from Novi (cannot
be spoofed via URL), and sets $idaa_loc.novi_verified on success.
All-or-nothing: if novi_idaa_api_key is absent or the call fails, access denied.

- ae_idaa_stores.ts: add novi_verified boolean field to idaa_loc
- (idaa)/+layout.svelte: async UUID verification with spinner to prevent
  Access Denied flash; permission upgrade-only strategy preserved
- video_conferences/+page.svelte: skip duplicate Novi member details call if
  layout already verified ($idaa_loc.novi_verified check)
- iframe HTML files: remove browser-side Novi API fetch and email/full_name
  params; pass only uuid; add README/START/STOP/WARNING comments for client
  staff; fix iframe-before-script DOM ordering bug
- documentation: CLIENT__IDAA_and_customized_mods.md updated with full
  verification flow, site_cfg_json fields, permission table, access gate

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 14:48:49 -04:00
Scott Idem
e7ac5168f6 fix: person lookup failing due to legacy person_id_random field name
V3 CRUD returns 'id' as the random identifier, not 'person_id_random'.
The person check and assignment were using the old field name, causing
the 'no person record' alert even when the lookup returned valid data.

Now checks person_rec.id ?? person_rec.person_id_random as a fallback
for backwards compatibility.
2026-03-06 22:51:29 -05:00
Scott Idem
0dab64a8d6 fix: improve sign-in error messages for both auth flows
- Check user_response?.detail (FastAPI standard) before user_response?.error
- Distinguish null response (network/server error) from bad credentials
- Remove silent console.error-only path; user now always sees a message
- Fix misleading 'auth_ae_obj__username_password' label in user_id+key flow
- Clarify 'no person record' message to suggest contacting administrator
- Simplify success log messages (remove dead commented-out code)
2026-03-06 22:42:15 -05:00
Scott Idem
79457103de fix: sign-in broken due to wrong field name on auth response
The /user/authenticate endpoint returns 'user_id' not 'user_id_random'.
Both auth flows (user_id+auth_key and username+password) were checking
user_response?.user_id_random, which was always undefined, causing the
user_id to never be set and falling through to the email lookup fallback.

Fixed both .then() handlers to check user_response?.user_id and assign
user_obj.user_id.
2026-03-06 22:39:16 -05:00
Scott Idem
95508458f6 ui: hide Session Search nav on its own page, dark mode file list, font size cycler
- event_page_menu: set events__session_search=false — the Session Search nav
  link was redundantly appearing on the Session Search page itself

- element_manage_event_file_li: replace hardcoded gray hover colors with
  theme-aware surface tokens (hover:bg-surface-100-900, border-surface-200-800)
  and add transition-colors; fixes light-on-light in dark mode for the file
  list table rows and Event File Purpose select element

- font size cycler (default → larger → smaller → default):
  - ae_stores: add font_size_mode: 'default' to ae_loc defaults
  - app.css: html.font-size-larger (112.5%) and html.font-size-smaller (87.5%)
  - +layout.svelte: DOM effect applies/removes font-size-* class on <html>
  - e_app_sys_menu: compact A / A+ / A− button cycles the mode
2026-03-06 21:35:06 -05:00
Scott Idem
b39ce19fdc feat(theme): add AE Firefly theme — 'Shiny serenity, like a firefly.'
New custom Skeleton v4 theme for One Sky IT, LLC.
Design vision: Scott Idem, 2026-03-06.

Color system:
  Primary   — Luminescent teal (bioluminescent shimmer, hue ~184°)
  Secondary — Warm amber-gold (firefly body glow, hue ~90°)
  Tertiary  — Night-sky indigo (depth + serenity, hue ~277°)
  Surface   — Moonlit slate (barely-cool neutral; crisp in light,
              deep midnight in dark)

Section 508 / WCAG 2.1 AA compliance embedded in contrast assignments.
Set as new app default (replacing nouveau).

Files:
  src/ae-firefly.css                        — theme definition
  src/app.css                               — @import registered
  src/lib/app_components/e_app_theme.svelte — 'Firefly ✦' in selector
  src/lib/stores/ae_stores.ts               — default theme_name updated
2026-03-06 21:05:08 -05:00
Scott Idem
3ca9503b88 fix: resolve svelte-check warnings (non-IDAA batch)
- Remove dead .field_editing_wrapper CSS rules from element_ae_crud_v2.svelte
  (template migrated to field_editing_wrapper_v2 with Tailwind)
- Fix TS error: use optional chaining on person_obj key in ae_comp__person_obj_tbl.svelte
- Fix state_referenced_locally: wrap data.user init with untrack() in users/[user_id]/+page.svelte
- Replace misused <label> with <span> for visual section headings (a11y) in:
  launcher_cfg_native_os.svelte, launcher_cfg_health.svelte,
  launcher_cfg_local_actions.svelte, launcher_cfg_template.svelte
2026-03-06 18:15:31 -05:00
Scott Idem
48d5fe8995 fix: add missing each-block keys (svelte/require-each-key)
Fixed all 27 remaining instances across 19 files. Keys used:
- Object ID fields where available (e.g. account_id_random, event_file_id)
- index for logger lists with no reliable unique key
- Property name for Object.entries() loops
2026-03-06 17:54:50 -05:00
Scott Idem
dd5cf9b63b chore: minor updates across events, journals, elements, and shared components
Miscellaneous small changes to events (badges, launcher, leads, pres_mgmt,
settings), journals, reusable elements (crud, field editor), app components,
core components, and test README. Mostly 1-2 line changes per file.
2026-03-06 17:32:53 -05:00
Scott Idem
0c9b6a9f5b fix: IDAA auth — harden novi_admin_li/trusted_li and remove iframe gate
- ae_idaa_stores.ts: update default novi_admin_li UUID; add staff UUID to
  novi_trusted_li hardcoded defaults.
- +layout.svelte (idaa): only overwrite admin/trusted lists from site_cfg_json
  when the list is non-empty, so hardcoded defaults are never silently cleared.
  Remove $ae_loc.iframe requirement for 'authenticated' access level — the
  presence of a valid Novi UUID in the URL is sufficient proof regardless of
  whether the iframe flag is set yet.
2026-03-06 17:32:47 -05:00
Scott Idem
9fc72b4671 feat: wire up class-based dark mode for Tailwind v4
- app.css: add @custom-variant dark so Tailwind v4 respects .dark class
  on <html> instead of always following OS prefers-color-scheme.
- app.html: remove hardcoded class="light" (now set dynamically).
- +layout.svelte: toggle .dark/.light on <html> when ae_loc.theme_mode changes.
- e_app_theme.svelte: related theme toggle changes.
2026-03-06 17:32:30 -05:00
Scott Idem
fdd4020267 fix: reduce svelte-check warnings from 175 to 95 (80 eliminated)
Svelte 5 reactivity pattern fixes:
- Convert prop/data captures to $derived where used in reactive contexts
- Wrap store assignments in $effect + untrack for ae_acct pattern
- Move sign_in_out URL param processing to onMount (from top-level if(browser))
- Wrap debug console.log blocks in $effect instead of top-level if(log_lvl)
- Fix $state initializers reading props directly ($state(link_to_id) → $state(''))
- Fix box = $state(null) in journals layout

CSS fixes:
- TipTap scss: change :global(.tiptap){nested} to :global{.tiptap{nested}} so
  Svelte does not scope-hash dynamic content selectors (latent CSS bug fixed)
- element_manage_hosted/event: dq__where vars → $derived for reactive liveQuery

Config:
- svelte.config.js: add onwarn (suppresses a11y/CSS in Vite pipeline; note:
  svelte-check 4.x does not read onwarn so CLI count unchanged)

Remaining 95 warnings (acceptable baseline):
- 70x a11y_label: form labels need for/id attributes (proper a11y fix deferred)
- 12x lu_* false positives in IDAA async callbacks (correct code)
- 8x CSS dynamic selectors Svelte cannot detect at compile time
- 5x other intentional patterns (autofocus, form state, log_lvl callbacks)
2026-03-05 20:50:39 -05: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
fdd1c88b35 fix(field-editor-v3): show edit buttons dimmed in edit mode, bright on hover
Previously buttons were opacity-0 until hover — invisible even in edit mode.
Changed to opacity-20 base so users can see which fields are editable, opacity-100 on hover.
Matches the behavior in element_data_store_v3.svelte.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 18:00:56 -05:00
Scott Idem
d846a39677 refactor: migrate Element_ae_crud v1/v2 usages to element_ae_obj_field_editor_v3
Replace all active Element_ae_crud (v1) and Element_ae_crud_v2 usages across
22 files with Element_ae_obj_field_editor_v3. Also remove 9 commented-out v1
imports that were dead code.

Key changes:
- Remove trigger_patch pattern; replace with direct api.update_ae_obj_v3() calls
- Replace field_value prop with current_value, on:ae_crud_updated with on_success
- Remove legacy props: api_cfg, hide_edit_btn, outline_element, show_crud,
  display_inline, display_block_edit (→ display_block), class_li
- field_type 'boolean' → 'checkbox', 'email' → 'text' (v3 has no email type)
- Replace core_func.update_ae_obj_id_crud_v2() with api.update_ae_obj_v3()
- Keep core_func where still used (QR code generation, person create)

Files: presenter_view, person_view, location_view, device_obj_li,
presentation_obj_li, session_view, launcher_file_cont, session_alert,
event/session/location/presenter page menus, leads exhibit tracking page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 17:38:02 -05:00
Scott Idem
cdf56aadcd refactor(crud): migrate v2 component usages to field-editor-v3
Replaces all active Element_ae_crud_v2 usages with Element_ae_obj_field_editor_v3,
and direct core_func.update_ae_obj_id_crud_v2 calls with api.update_ae_obj_v3.
Adds 'number' field_type to v3 editor. All on_success callbacks trigger SWR
refresh via events_func load functions so liveQuery updates Dexie correctly.

- element_ae_obj_field_editor_v3: add 'number' input type
- ae_comp__event_session_obj_li: replace core_func v2 API calls + dead import
- ae_comp__event_location_obj_li: migrate 2x Element_ae_crud_v2 (name, description)
- ae_tab__manage: migrate 7x Element_ae_crud_v2 (priority/checkbox, numbers, text, tiptap)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 16:39:29 -05:00
Scott Idem
c3ec0f88ee fix(field-editor-v3): layout shift, bindable crash, and optimistic display
- Fix layout shift on edit_mode toggle: always render the edit button
  (using invisible/pointer-events-none) so the flex container doesn't
  reflow when edit_mode is toggled on/off.

- Fix 'store.set is not a function' crash: remove $bindable() from
  current_value. The component is SWR-first; after a successful PATCH
  liveQuery updates the prop from Dexie. Trying to write back to a
  readonly liveQuery-derived prop caused the crash.

- Fix stale display after save: add has_optimistic flag + display_value
  derived. After a successful PATCH, display_value shows draft_value
  immediately without waiting for liveQuery. Cleared automatically when
  current_value catches up, or on cancel/re-open of edit mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 20:05:43 -05:00
Scott Idem
29093c45df fix(auth+ds): passcode re-entry bug and Data Store v3 business logic
- e_app_access_type: reset checked_passcode on clear so same passcode
  can be re-entered without a page refresh (guard was blocking re-entry)
- element_data_store_v3: wire display prop to wrapper CSS style;
  gate "not found" diagnostic to administrator+ or trusted+edit_mode;
  public/anonymous visitors no longer see missing block warnings
- +page.svelte: add manager_access exception to header/content class_li
  so managers can see "not found" diagnostics (matches footer pattern)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 14:31:29 -05:00
Scott Idem
fb78293fdf Bug fix for signing out with a passcode and then trying to sign back in with the same passcode without refreshing the page. 2026-03-04 13:31:43 -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
32f8a75373 Refactor: Add microtask yields to journals module for consistency
Added await Promise.resolve() yields after IndexedDB writes to ensure
Dexie observers fire before function returns. Aligns with pattern
established in event loaders fix.

Journals module was already working correctly (preserved try_cache),
but adding yields ensures consistent timing behavior across all
nested data loading patterns.
2026-02-26 13:42:27 -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
95a56d25bf test: stabilize cold-start Playwright tests; fix editor bind:new_content fallback 2026-02-25 20:15:09 -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
Scott Idem
2dfc8a5034 Implemented 'only_priority' filtering for V3 Lookups.
- Updated V3 lookup API and core timezone loader to support the 'only_priority' flag.
- Enabled high-priority timezone filtering in IDAA Recovery Meeting and Archive editors to streamline selection lists.
2026-02-20 17:17:09 -05:00
Scott Idem
52c9e765a0 Implemented Aether API V3 Lookup integration for standardized tables.
- Created 'src/lib/ae_api/api_get__lookup_v3.ts' to handle the new '/v3/lookup/{lu_type}/list' endpoint.
- Refactored 'get_ae_obj_li_for_lu' in 'api.ts' to prioritize the V3 system for countries, subdivisions, and time zones, with V2 fallback for legacy types.
- Ensured lookups use the 'x-no-account-id' bypass for unauthenticated site bootstrapping.
- Updated core country, subdivision, and time zone loaders to use the refined API interface.
2026-02-20 16:12:06 -05:00
Scott Idem
e2e120456e Enhanced Events Launcher Location loading and instructions.
Implemented explicit 'enabled' and 'hidden' parameter support in the Event data layer ('load_ae_obj_id__event').

Updated the Events Launcher layout and background sync engine to proactively fetch all enabled locations (including hidden ones), ensuring the room select list is complete and stays updated.

Refined 'launcher_file_cont.svelte' to only display native-specific file opening instructions when 'app_mode' is 'native'.

Updated AGENT_TODO.md to reflect task completion and new priorities.
2026-02-19 17:54:21 -05:00
Scott Idem
0a689be25d Implemented 'inc_hosted_file' support and expanded data mapping for Event Files.
Updated the Event File data layer to support the 'inc_hosted_file' flag in load and search functions, enabling on-demand retrieval of joined Hosted File metadata.

Refined the data mapping in 'process_ae_obj__event_file_props' to include 'content_type' and strictly controlled which properties are persisted to IndexedDB, adhering to the 'Bite-Sized Data' principle by excluding unneeded backend fields like subdirectory paths.

Enhanced 'get_ae_obj_li_v3' to support generic parameter pass-through for V3 CRUD operations.
2026-02-19 17:15:12 -05:00