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.
This commit is contained in:
Scott Idem
2026-03-03 18:49:57 -05:00
parent 5c3823f41a
commit b064d8c235
14 changed files with 605 additions and 227 deletions

View File

@@ -10,16 +10,14 @@
import {
Library,
RemoveFormatting,
X,
QrCode,
Search,
Check,
LoaderCircle
} from 'lucide-svelte';
import { ae_loc, ae_api } from '$lib/stores/ae_stores';
import { events_loc, events_sess } from '$lib/stores/ae_events_stores';
import Element_qr_scanner_v2 from '$lib/element_qr_scanner_v2.svelte';
import Element_qr_scanner_v3 from '$lib/element_qr_scanner_v3.svelte';
import { ae_util } from '$lib/ae_utils/ae_utils';
// ISHLT 2024 badge type codes
@@ -53,7 +51,7 @@
};
}
function handle_qr_scan_result(event: CustomEvent) {
function handle_qr_scan_result(event: { detail: { result: string; entry_method: string } }) {
let qr_scan_result = event.detail.result;
let obj = ae_util.process_data_string(qr_scan_result);
@@ -202,9 +200,9 @@
<div
class="w-full max-w-2xl mx-auto p-4 bg-surface-100-900 rounded-lg shadow-lg"
>
<Element_qr_scanner_v2
<Element_qr_scanner_v3
bind:start_qr_scanner={$events_sess.badges.qr_scan_start}
on:qr_scan_result={handle_qr_scan_result}
on_qr_scan_result={handle_qr_scan_result}
/>
</div>
{/if}
@@ -240,24 +238,7 @@
</button>
{/if}
<button
type="button"
onclick={() => {
$events_loc.badges.use_id_li = !$events_loc.badges.use_id_li;
handle_search_trigger();
}}
class="btn btn-sm preset-tonal-secondary border border-secondary-500"
title="Toggle using the ID list or not."
>
{#if $events_loc.badges.use_id_li}
<Check size="1.2em" class="text-green-600 mr-1" />
{:else}
<X size="1.2em" class="text-red-600 mr-1" />
{/if}
Use ID List
</button>
{#if $ae_loc.edit_mode}
{#if $ae_loc.edit_mode}
<label
class="flex items-center gap-1 cursor-pointer bg-surface-200-800 px-2 py-1 rounded-token text-xs font-semibold"
>