Creates ae_events_stores__auth.svelte.ts with PersistedState keyed
'ae_events_auth_loc' for auth__person and auth__kv (presenter/session
sign-in state). Migrated 10 component files from $events_loc.auth__* to
events_auth_loc.current.auth__*.
Also fixed stale pres_mgmt stragglers: $events_loc.pres_mgmt.* refs in
presenter_obj_li.svelte, presenter_page_menu.svelte, and [presenter_id]/
+page.svelte now use pres_mgmt_loc.current.* directly.
show_details boolean moved from events_loc to leads_loc (it belongs in
the leads module — one bind in ae_tab__manage.svelte).
auth__person, auth__kv, show_details, events_cfg_json, event_id removed
from events_local_data_struct. events_loc now only carries ver, title,
and qry__* prefs.
svelte-check: 0 errors, 0 warnings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace admin field editor with direct TipTap + Save Notes button for exhibitor notes;
show Add Notes button when notes are empty (no dead placeholder)
- Add one-click priority star toggle in header (always visible, no edit mode required)
- Remove Exhibit Context card (exhibitors don't need to see their own booth name)
- Move Captured By into profile card with human-readable labels
(shared_passcode → "Booth (Shared)", access type codes → Staff/Admin)
- Add location row (city/state + country) to profile card
- Gate Remove button to edit mode only to prevent accidental taps
- Fix button position stability: Edit/View always rightmost (same screen position),
Remove grows in from left — prevents double-tap accidents
- Add unsaved-changes guard (beforeNavigate) covering both notes and custom question form
- Custom questions form: hide Save when no questions configured, show
"Configure in Manage Tab" link instead
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- leads_api_access toggle in Admin Tools (manager only)
- Account Status section for end users (payment/licenses/API badges + CSV export button)
- Sign-out fix: use Object.fromEntries instead of delete on PersistedState proxy
- Shared passcode sign-in redirects directly to Manage tab (their role is config, not capture)
- Manage tab section reorder: Account Status → Lead Retrieval Config → Booth Profile → Access & Security → App Settings
- Filter dropdown: replace abstract "My Leads" with direct identity options (All / Booth (Shared) / per-licensee); auto-resolves and migrates stale 'my' values
- Lead detail: replace Element_ae_obj_field_editor notes with direct TipTap editor + Save Notes button; Add Notes button on empty state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
**Session persistence bug** — leads_loc_defaults was missing __version: 1.
store_versions.ts wipes ae_leads_loc when parsed.__version !== 1 (always true
when the field is absent), so every page reload cleared auth_exhibit_kv and
forced re-login. Adding __version: 1 to both the interface and defaults fixes
this for all auth types.
**Manage tab fixes:**
- Description: collapsed by default with ChevronDown/Up toggle — same pattern
as session_view.svelte. Avoids long promo copy dominating the manage screen.
- Staff Passcode: removed duplicate green plain-text display for admins; the
Element_ae_obj_field_editor already shows the value (was showing twice).
- Booth Identifier: replaced static read-only display with Element_ae_obj_field_editor
so the booth code (exhibit.code) is editable inline.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prevents silent no-op when user clicks submit before lq__exhibit_obj is ready
(exhibit not yet written to Dexie). Button now shows 'Loading...' spinner while
the exhibit record is resolving, eliminating the two-tap workaround needed on
first page load.
Also adds 7 Playwright tests for licensed user sign-in (leads_licensed_signin.test.ts)
covering success path, wrong credentials, email/identity tagging on captured leads,
identity isolation between staff members, and returning-session bypass.
Helpers: attach_leads_routes/setup_leads_test_page now accept exhibit_overrides
(e.g. license_li_json) to inject licensed users into mocked API responses.
seed_leads_loc import added to leads_auth.test.ts multi-exhibit test.
Total leads test coverage: 29 tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New /events/[event_id]/leads/config page: administrator UI for
mod_exhibits_json. Controls leads_require_payment toggle and Stripe
keys (publishable key + buy button IDs per license tier).
- leads_require_payment (mod_exhibits_json) now gates all billing UI:
header CreditCard button in exhibit +page.svelte and Licenses & Billing
accordion in ae_tab__manage.svelte. Default false (client covers costs).
- Stripe keys migrated from site_cfg_json to mod_exhibits_json (per-event).
ae_comp__exhibit_payment accepts them as optional props; falls back to
site_cfg_json for events not yet migrated.
- Fixed "My Leads" bug for shared-passcode users: search_params now maps
licensee_email 'my' → 'shared_passcode' literal (not kv.key passcode
string) so filters correctly match stored external_person_id values.
- Event settings: Exhibits section replaced with config link + raw JSON
fallback, matching pres_mgmt/badges pattern.
- Docs updated: README.md, MODULE__AE_Events_Exhibitor_Leads.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full implementation of ae_comp__exhibit_payment.svelte (was a 9-line stub).
Reads Stripe config from $ae_loc.site_cfg_json per-event. License tier
selector (1/3/6/10 users) uses {#key} remount pattern to work around
stripe-buy-button web component ignoring attribute changes after mount.
Three states: paid confirmation (priority=true), not-configured hint, payment
form. client_reference_id=exhibit_id ties payments to booth records.
TypeScript declaration for stripe-buy-button added to app.d.ts via
svelte/elements augmentation. exhibit_id prop wired in +page.svelte and
ae_tab__manage.svelte.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Merge Rapid + Qualify scan modes into single Confirm mode with two-button card:
"Add & Scan Next" (resets) and "Add & View Lead" (navigates to detail). Same
two-button pattern on the reenable card: "Restore & Scan Next" / "Restore & View Lead".
Stale 'qualify' localStorage values normalized to 'rapid' via $derived.by().
- QR scanner speed: fps 10→25, qrbox 82%→88%, useBarCodeDetectorIfSupported (native
BarcodeDetector API on Chrome/Edge — significantly faster than ZXing JS fallback)
- Fix capture identity stored in external_person_id / group:
licensed exhibit user → their email; shared passcode → 'shared_passcode' label
(not the raw passcode); Aether user bypassing exhibit sign-in → access_type string
('trusted', 'manager', 'super', etc.). Consistent across all three lead capture
components (single scanner, multi scanner, manual search).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
When create_ae_obj__exhibit_tracking returns false/null (API down, network
error, auth failure), the scanner was left frozen at 'adding' indefinitely.
Added else branch to surface an error state in both single and multi scanners.
Also fixes multi scanner which wasn't capturing the API return value at all.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Eye/EyeOff toggle to exhibit tracking search bar; wired to
existing $events_loc.leads.show_hidden store field
- Guard + init the show_hidden field in +page.svelte
- Add show_hidden to search_params so toggling triggers a refresh
- Apply hide filter in local IDB search path (skip hidden unless toggled)
- Pass hidden: 'not_hidden' | 'all' to API search__exhibit_tracking call
- Apply hide filter in filtered_lead_li for the broad liveQuery fallback path
- README: remove stale allow_tracking/PWA/export gaps; add Implemented section;
fix ae_events_functions import path (moved to ae_events/ subdir)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
Export button now only renders when event_exhibit.leads_api_access === true,
preventing a 403 that would always fire otherwise. Endpoint confirmed live on
backend. TODO updated to reflect export + allow_tracking gate both resolved.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- QR scanner: after badge loads, blocks add with 'Tracking Opt-Out' warning
card if allow_tracking !== true; replaced deprecated CheckCircle → CircleCheck
- Manual search: shows ShieldOff 'Opt-Out' label per row for blocked badges;
add_as_lead() also guards against programmatic bypass
- Fix: ae_comp__exhibit_tracking_obj_li — Loader2 from wrong package
@lucide/svelte → LoaderCircle from lucide-svelte
- ae_types.ts: added allow_tracking and agree_to_tc to ae_EventBadge interface
- README.md (leads): full rewrite reflecting actual current state and known gaps
- TODO__Agents.md: updated Leads entry from stale 'NEXT MAJOR FEATURE' to
accurate in-progress status with remaining checklist
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Set log_lvl to 0 in all pages and layouts that had it left at 1 or 2
from development. Also remove two hardcoded `log_lvl = 2` overrides
inside function bodies in reports_files.svelte and
reports_presenters.svelte that were forcing verbose output regardless
of the module-level setting.
Affected: launcher location page, leads pages (2), pres_mgmt reports (2),
presenter +page.ts, IDAA layouts (2), IDAA archives, IDAA recovery
meetings page, journals pages (2).
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.
- Add keyed {#each} to recovery meeting list and exhibit tracking list
to satisfy Svelte's each-block-key lint rule and ensure correct DOM
reconciliation on list updates
- Gate Zoom/Jitsi copy-to-clipboard buttons behind manager_access in
both the recovery meeting list view and single meeting detail view
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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.
- Integrated TipTap rich text editor for Booth Descriptions and Exhibitor Notes.
- Implemented strip_html utility for clean search/preview of rich text fields.
- Renamed exhibit loading functions to follow load_ae_obj_id__event_exhibit* pattern.
- Hardened property processors with 'undefined' string guards and automatic reload triggers.
- Resolved type mismatches and naming inconsistencies across the Leads module.
- Verified zero-error state via svelte-check.
- Hardened 'Comp_exhibit_license_list' to handle both raw JSON and IDB object formats.
- Updated all labels to 'Licensed Leads User' or 'Licensee' for consistency.
- Verified Admin-only restriction for the licensee management section.
- Fixed silent parsing failures that caused empty staff lists.
- Added real-time checking for existing leads in manual search.
- Implemented 'Already Captured' status for QR scanner with direct 'View Lead' link.
- Resolved all remaining TypeScript typing issues in capture components.
- Optimized Dexie lookups for existing lead detection.
- Added 'Comp_lead_detail_form' for editing licensee responses.
- Implemented reactive form generation based on Exhibit question definitions.
- Wired up 'Edit Mode' toggle in Lead Detail page.
- Added CRUD editors for lead notes, priority, and visibility status.
- Refactored Lead List to use direct observable subscription for better reactivity.
- Implemented in-memory 'Hard Guard' filter to ensure licensee selection is strictly enforced.
- Fixed 'TypeError: s.subscribe is not a function' by removing legacy $ prefix from resolved props.
- Resolved TypeScript typing errors in Lead Detail and Search components.
- Migrated Badge Search icons to Lucide.
- Implemented dual-format parsing for 'license_li_json' (handles raw string and IDB objects).
- Added fallback lookup by 'event_exhibit_id_random' for robust record resolution.
- Fixed reactivity for licensee dropdown population.
- Hardened default selection logic based on Aether access levels.
- Renamed all staff-related fields and variables to 'licensee'.
- Implemented correct filtering logic for Aether Admins (default All, hide My).
- Implemented correct filtering for booth users (default My, show colleagues).
- Populated dropdown labels with Full Names from license_li_json.
- Removed 'Shared Passcode' from the Lead List filter.
- Fixed 'Captured initial value' warnings in 65+ components by implementing
proper sync effects with 'untrack' and derived states.
- Hardened Event Settings JSON editors using a temporary string-buffer pattern
to safely decouple object-based data from CodeMirror's string requirements.
- Resolved strict TypeScript mismatches across core routes (Accounts, Sites, etc.)
and improved property indexing safety in views.
- Patched Flowbite-Svelte Drawer transitions for Svelte 5 compatibility using
prop spreading.
- Added comprehensive safety comments to high-risk reactivity blocks.
- Synchronized 'ae_types.ts' with V3 backend models.