General clean up and making things a least look real.
This commit is contained in:
488
src/routes/events_leads/exhibit/[slug]/leads_add_scan.svelte
Normal file
488
src/routes/events_leads/exhibit/[slug]/leads_add_scan.svelte
Normal file
@@ -0,0 +1,488 @@
|
||||
<script lang="ts">
|
||||
// export let data;
|
||||
// console.log(`ae_events_leads exhibit [slug] leads_manage.svelte data:`, data);
|
||||
|
||||
import { ae_util } from '$lib/ae_utils';
|
||||
import { liveQuery } from "dexie";
|
||||
import { db_events } from "$lib/db_events";
|
||||
import { ae_loc, ae_sess, ae_api, slct, slct_trigger } from '$lib/ae_stores';
|
||||
import { events_loc, events_sess, events_slct, events_trigger } from '$lib/ae_events_stores';
|
||||
|
||||
import Element_qr_scanner from '$lib/element_qr_scanner.svelte';
|
||||
|
||||
// let param_slug_event_exhibit_id = data.params.slug;
|
||||
|
||||
let event_exhibit_obj = liveQuery(
|
||||
() => db_events.exhibits.get($events_slct.exhibit_id)
|
||||
);
|
||||
|
||||
let search_submit_results: Promise<any>|key_val;
|
||||
let scan_submit_results: Promise<any>|key_val;
|
||||
|
||||
function handle_submit_form_search(event) {
|
||||
console.log('*** handle_submit_form_search() ***');
|
||||
console.log(event);
|
||||
|
||||
$events_sess.leads.submit_status__search = 'submitting';
|
||||
|
||||
let search_str = $events_sess.leads.entered_search_str;
|
||||
console.log(search_str);
|
||||
|
||||
// search_submit_results = handle_search_for_person(search_str);
|
||||
console.log(search_submit_results);
|
||||
}
|
||||
|
||||
function handle_qr_scan_result(event) {
|
||||
console.log('*** handle_qr_scan_result() ***');
|
||||
|
||||
let qr_scan_result = event.detail.result;
|
||||
console.log(qr_scan_result);
|
||||
let qr_scan_obj = ae_util.process_data_string(qr_scan_result);
|
||||
|
||||
if (qr_scan_obj.qr_type == 'OBJ') {
|
||||
console.log(`Got a QR type of OBJ. Type ${qr_scan_obj.type}; ID ${qr_scan_obj.id}`);
|
||||
|
||||
if (qr_scan_obj.type && qr_scan_obj.id && qr_scan_obj.type == 'event_badge') {
|
||||
console.log(`Found an Event Badge object type and ID.`);
|
||||
let event_badge_id = qr_scan_obj.id
|
||||
|
||||
$events_sess.leads.qr_scan_result = `Found a badge type with ID: ${event_badge_id}`;
|
||||
|
||||
// event_exhibit_tracking_obj_create_promise = await handle_create_event_exhibit_tracking_obj($slct.event_exhibit_id, event_badge_id);
|
||||
// console.log(event_exhibit_tracking_obj_create_promise);
|
||||
// if (event_exhibit_tracking_obj_create_promise) {
|
||||
// console.log('Created new log entry for this badge.');
|
||||
// console.log(event_exhibit_tracking_obj_create_promise);
|
||||
|
||||
// handle_load_event_exhibit_obj({event_exhibit_id: $slct.event_exhibit_id, try_cache: false});
|
||||
|
||||
// $slct.event_exhibit_tracking_obj = event_exhibit_tracking_obj_create_promise;
|
||||
// $slct.event_exhibit_tracking_id = $slct.event_exhibit_tracking_obj.event_exhibit_tracking_id_random;
|
||||
// // $slct.event_badge_obj = $slct.event_exhibit_tracking_obj.event_badge;
|
||||
// // $slct.event_badge_id = $slct.event_badge_obj.event_badge_id_random;
|
||||
// show_add_qr = false;
|
||||
// qr_scan_result = '';
|
||||
// qr_scan_obj = {};
|
||||
// show_tracking_entry = true;
|
||||
// } else if (event_exhibit_tracking_obj_create_promise === null) {
|
||||
// console.log('A matching log entry probably exists for this person!');
|
||||
// } else {
|
||||
// console.log('Something unexpected happened???');
|
||||
// }
|
||||
|
||||
} else if (qr_scan_obj.type && qr_scan_obj.id && qr_scan_obj.type == 'event_exhibit') {
|
||||
console.log(`Ignoring.`);
|
||||
} else if (qr_scan_obj.type && qr_scan_obj.id && qr_scan_obj.type == 'event_person') {
|
||||
console.log(`Ignoring.`);
|
||||
} else if (qr_scan_obj.type && qr_scan_obj.id && qr_scan_obj.type == 'event_session') {
|
||||
console.log(`Ignoring.`);
|
||||
} else {
|
||||
console.log(`Ignoring. The object returned was unexpected or not valid.`);
|
||||
console.log(qr_scan_obj);
|
||||
}
|
||||
} else if (qr_scan_obj.qr_type == 'MECARD') {
|
||||
console.log(`Got a QR type of MECARD. This was not expected, but we will at least display it???`);
|
||||
|
||||
// https://github.com/ertant/vCard
|
||||
// vcard = vCardParser.parse(qr_scan_obj.str); // vCard
|
||||
// console.log(vcard);
|
||||
|
||||
mecard = qr_scan_obj.str.split(';'); // vCard
|
||||
// NOTE: Next we need to loop through the values and split each again on ":".
|
||||
// NOTE: Then probably do a second check based on the known key values (N, EMAIL, ADR).
|
||||
console.log(mecard);
|
||||
|
||||
show_mecard = true;
|
||||
} else {
|
||||
console.log(`Got a QR type of ${qr_scan_obj.qr_type}. Display warning to user, but otherwise ignoring.`);
|
||||
console.log(qr_scan_obj);
|
||||
}
|
||||
}
|
||||
|
||||
function handle_qr_camera(event) {
|
||||
console.log('*** handle_qr_camera() ***', event.detail);
|
||||
|
||||
if (!$ae_loc.hub.qr) {
|
||||
$ae_loc.hub.qr = {};
|
||||
}
|
||||
|
||||
if (event.detail.status == 'allowed') {
|
||||
// console.log('Camera access allowed');
|
||||
$ae_loc.hub.qr.camera_status = 'allowed';
|
||||
} else if (event.detail.status == 'denied') {
|
||||
console.log('Camera access denied!?');
|
||||
$ae_loc.hub.qr.camera_status = 'denied';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section class="tab__add_section min-w-full flex flex-col wrap justify-center items-center space-y-4 ae_h_scrollfix">
|
||||
|
||||
{#if $events_loc?.leads.auth_exhibit_kv && $events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id]}
|
||||
|
||||
{#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
|
||||
<div>Leads for:
|
||||
{$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="variant-soft-warning">Please go to the Main tab and select a license to use.</div>
|
||||
{/if}
|
||||
|
||||
<div class="variant-soft-warning">This section is not fully enabled for ISHLT 2024 at this time. The ability to add a lead by scanning the attendee's QR code or by searching for their name, will be enabled before the ISHLT 2024 Annual Meeting in Prague.</div>
|
||||
|
||||
<p>
|
||||
<!-- This page is used to test QR scanning with your device. -->
|
||||
{#if $ae_loc.hub.qr.camera_status == 'unknown'}
|
||||
<strong>You will need to allow access to your device's camera when asked.</strong>
|
||||
{:else if $ae_loc.hub.qr.camera_status == 'denied'}
|
||||
<strong>You need to allow access to your device's camera. Currently this seems to be blocked or denied for this site.</strong>
|
||||
Please check your browser's permissions.
|
||||
{/if}
|
||||
</p>
|
||||
|
||||
|
||||
<span class="flex flex-col md:flex-row wrap justify-center items-center">
|
||||
<button
|
||||
class="btn btn-xl variant-soft-primary m-2 w-64 add_person_qr_btn"
|
||||
on:click={() => {
|
||||
// $slct.event_exhibit_tracking_id = null;
|
||||
// $slct.event_exhibit_tracking_obj = null;
|
||||
// show_add_qr = true;
|
||||
// qr_scan_obj = null;
|
||||
// event_exhibit_tracking_obj_create_promise = null;
|
||||
$events_sess.leads.show_form__scan = true;
|
||||
$events_sess.leads.qr_scan_start = true;
|
||||
}}
|
||||
disabled={!$ae_loc.trusted_access && 2==4}
|
||||
title="Scan a QR code to add a person to the leads list."
|
||||
>
|
||||
<span class="fas fa-qrcode mx-1"></span>
|
||||
Scan to Add Person
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="btn btn-xl variant-soft-primary m-2 w-64 add_person_search_btn"
|
||||
on:click={() => {
|
||||
// $slct.event_exhibit_tracking_id = null;
|
||||
// $slct.event_exhibit_tracking_obj = null;
|
||||
// show_add_search = true;
|
||||
// qr_scan_obj = null;
|
||||
// event_exhibit_tracking_obj_create_promise = null;
|
||||
$events_sess.leads.show_form__search = true;
|
||||
}}
|
||||
disabled={!$ae_loc.trusted_access && 2==4}
|
||||
title="Search for a person to add to the leads list."
|
||||
>
|
||||
<span class="fas fa-search mx-1"></span>
|
||||
Search to Add Person
|
||||
</button>
|
||||
</span>
|
||||
|
||||
<span class="">
|
||||
{#if ($events_loc.leads.show_content__scan_requirements)}
|
||||
<button class="btn btn-sm variant-soft-secondary" on:click={() => $events_loc.leads.show_content__scan_requirements=false}><span class="fas fa-info mx-1"></span> Hide Requirements</button>
|
||||
{:else if (!$events_loc.leads.show_content__scan_requirements)}
|
||||
<button class="btn btn-sm variant-soft-secondary" on:click={() => $events_loc.leads.show_content__scan_requirements=true}><span class="fas fa-info mx-1"></span> Requirements</button>
|
||||
{/if}
|
||||
</span>
|
||||
|
||||
{#if $events_loc.leads.show_content__scan_requirements}
|
||||
<div class="border-2 border-primary p-2 variant-soft-secondary">
|
||||
<p>You will need a device with a camera to scan the QR codes. You will also of course need one or more valid QR codes to scan.
|
||||
<!-- <button class="ae_btn btn_sm" on:click={() => show='qr_codes'}><span class="fas fa-qrcode"></span> Example QR Codes</button> -->
|
||||
</p>
|
||||
<ul class="list-disc list-inside">
|
||||
<li>Most laptops, workstations, Android phones/tablets, iPhones, and iPads are compatible</li>
|
||||
<li>The device must have a current (within the last 4 years) web browser such as Google Chrome, Mozilla Firefox, Apple's Safari, or Microsoft Edge. Opera is not yet fully supported.</li>
|
||||
<li>There is no Android or Apple app that needs to be installed!</li>
|
||||
<li>The device must have a camera for scanning or you will need to manually enter attendee badge IDs.</li>
|
||||
<li>The only permission you need to allow is access to your device's camera when asked.</li>
|
||||
</ul>
|
||||
</div>
|
||||
{:else}
|
||||
<!-- <button class="ae_btn btn_sm btn_info" on:click={() => show_requirements=true}><span class="fas fa-eye"></span> Requirements</button> -->
|
||||
{/if}
|
||||
|
||||
<!-- <div class=""> -->
|
||||
<!-- <Element_qr_scanner start_qr_scanner={false} show_qr_scan_result={true} show_qr_manual_badge_id_entry_option={true} on:qr_scan_result={handle_qr_scan_result} on:qr_camera={handle_qr_camera} /> -->
|
||||
<!-- </div> -->
|
||||
|
||||
<!-- <div class="qr_quick_results variant-soft-secondary font-bold p-4">
|
||||
{@html $events_sess.leads.qr_scan_result ?? 'No results yet'}
|
||||
</div> -->
|
||||
|
||||
{:else}
|
||||
<div class="variant-soft-error">Not logged in. Please log in and select a user license.</div>
|
||||
{/if} <!-- $events_loc?.leads.auth_exhibit_kv && $events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] -->
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
{#if $events_sess.leads.show_form__search}
|
||||
<div class="ae_quick_modal_container">
|
||||
<section
|
||||
class="
|
||||
ae_quick_popover
|
||||
events__leads__search
|
||||
z-50
|
||||
flex
|
||||
flex-col
|
||||
gap-4
|
||||
justify-stretch
|
||||
min-h-full
|
||||
min-w-full
|
||||
"
|
||||
>
|
||||
<header class="popover__header flex gap-1 justify-between items-center p-1 border-b">
|
||||
<h2 class="h3">Search</h2>
|
||||
|
||||
<div class="popover__actions">
|
||||
<button
|
||||
type="button"
|
||||
class="btn variant-soft-primary"
|
||||
on:click={() => {
|
||||
$events_sess.leads.show_form__search = false;
|
||||
}}
|
||||
>
|
||||
<span class="fas fa-times mx-1"></span>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="popover__content grow flex flex-col gap-4 items-center">
|
||||
<form
|
||||
id="form__search_text"
|
||||
class="form flex flex-row gap-2 justify-center items-center w-full"
|
||||
on:submit|preventDefault={handle_submit_form_search}
|
||||
>
|
||||
|
||||
<!-- This is the plain text search field for looking up attendees based on their name, email, etc. -->
|
||||
<input
|
||||
type="text"
|
||||
name="entered_search_string"
|
||||
placeholder="Search for attendee"
|
||||
bind:value={$events_sess.leads.entered_search_str}
|
||||
required
|
||||
class="input max-w-56"
|
||||
/>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="btn variant-ghost-primary"
|
||||
>
|
||||
<span class="fas fa-search mx-1"></span>
|
||||
Search
|
||||
</button>
|
||||
|
||||
</form>
|
||||
</section> <!-- .popover__content -->
|
||||
|
||||
<footer class="popover__footer flex gap-1 justify-between items-center p-1 border-t">
|
||||
<div class="popover__content__actions">
|
||||
<button
|
||||
type="submit"
|
||||
form="form__search_text"
|
||||
class="btn variant-soft-primary"
|
||||
disabled={search_submit_results instanceof Promise && !search_submit_results}
|
||||
on:click={() => {
|
||||
// trigger = 'save__ds__code';
|
||||
// $slct_trigger = 'save__ds__code';
|
||||
}}
|
||||
>
|
||||
<span class="fas fa-search mx-1"></span>
|
||||
Search
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="popover__status">
|
||||
<!-- Something text -->
|
||||
{#await search_submit_results}
|
||||
<div class="modal-loading">
|
||||
<span class="fas fa-spinner fa-spin"></span>
|
||||
<span class="loading-text">
|
||||
Searching...
|
||||
</span>
|
||||
</div>
|
||||
{:then search_submit_results}
|
||||
{#if search_submit_results}
|
||||
<div>
|
||||
<span class="fas fa-check text-green-500"></span>
|
||||
<span class="saved-text">
|
||||
Complete
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
<div
|
||||
class="ae_debug"
|
||||
class:hidden={!$ae_loc?.debug}
|
||||
>
|
||||
submit: {$events_sess?.leads.submit_status__search}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="popover__actions">
|
||||
<button
|
||||
type="button"
|
||||
class="btn variant-soft-primary"
|
||||
on:click={() => {
|
||||
$events_sess.leads.show_form__search = false;
|
||||
}}
|
||||
>
|
||||
<span class="fas fa-times mx-1"></span>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</footer> <!-- .popover__footer -->
|
||||
|
||||
</section> <!-- .ae_quick_popover -->
|
||||
</div> <!-- .ae_quick_modal_container -->
|
||||
{/if}
|
||||
|
||||
|
||||
{#if $events_sess.leads.show_form__scan}
|
||||
<div class="ae_quick_modal_container">
|
||||
<section
|
||||
class="
|
||||
ae_quick_popover
|
||||
events__leads__scan
|
||||
z-50
|
||||
flex
|
||||
flex-col
|
||||
gap-4
|
||||
justify-stretch
|
||||
min-h-full
|
||||
min-w-full
|
||||
"
|
||||
>
|
||||
<header class="popover__header flex gap-1 justify-between items-center p-1 border-b">
|
||||
<h2 class="h3">Scan</h2>
|
||||
|
||||
<div class="popover__actions">
|
||||
<button
|
||||
type="button"
|
||||
class="btn variant-soft-primary"
|
||||
on:click={() => {
|
||||
$events_sess.leads.show_form__scan = false;
|
||||
$events_sess.leads.qr_scan_start = false;
|
||||
}}
|
||||
>
|
||||
<span class="fas fa-times mx-1"></span>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="popover__content grow flex flex-col gap-4 items-center">
|
||||
|
||||
|
||||
<!-- <div class=""> -->
|
||||
<Element_qr_scanner start_qr_scanner={$events_sess.leads.qr_scan_start} show_qr_scan_result={true} show_qr_manual_badge_id_entry_option={true} on:qr_scan_result={handle_qr_scan_result} on:qr_camera={handle_qr_camera} />
|
||||
<!-- </div> -->
|
||||
|
||||
<div class="qr_quick_results variant-soft-secondary font-bold p-4">
|
||||
{@html $events_sess.leads.qr_scan_result ?? 'No results yet'}
|
||||
</div>
|
||||
|
||||
|
||||
</section> <!-- .popover__content -->
|
||||
|
||||
<footer class="popover__footer flex gap-1 justify-between items-center p-1 border-t">
|
||||
<div class="popover__content__actions">
|
||||
<button
|
||||
type="submit"
|
||||
form="form__scan_text"
|
||||
class="btn variant-soft-primary"
|
||||
disabled={scan_submit_results instanceof Promise && !scan_submit_results}
|
||||
on:click={() => {
|
||||
// trigger = 'save__ds__code';
|
||||
// $slct_trigger = 'save__ds__code';
|
||||
}}
|
||||
>
|
||||
<span class="fas fa-search mx-1"></span>
|
||||
Scan
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="popover__status">
|
||||
<!-- Something text -->
|
||||
{#await scan_submit_results}
|
||||
<div class="modal-loading">
|
||||
<span class="fas fa-spinner fa-spin"></span>
|
||||
<span class="loading-text">
|
||||
Scanning...
|
||||
</span>
|
||||
</div>
|
||||
{:then scan_submit_results}
|
||||
{#if scan_submit_results}
|
||||
<div>
|
||||
<span class="fas fa-check text-green-500"></span>
|
||||
<span class="saved-text
|
||||
">
|
||||
Complete
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
<div
|
||||
class="ae_debug"
|
||||
class:hidden={!$ae_loc?.debug}
|
||||
>
|
||||
submit: {$events_sess?.leads.submit_status__scan}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="popover__actions">
|
||||
<button
|
||||
type="button"
|
||||
class="btn variant-soft-primary"
|
||||
on:click={() => {
|
||||
|
||||
$events_sess.leads.show_form__scan = false;
|
||||
}}
|
||||
>
|
||||
<span class="fas fa-times mx-1"></span>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</footer> <!-- .popover__footer -->
|
||||
|
||||
</section> <!-- .ae_quick_popover -->
|
||||
</div> <!-- .ae_quick_modal_container -->
|
||||
{/if}
|
||||
|
||||
|
||||
<style lang="postcss">
|
||||
/* Use the div.ae_quick_modal_container to block background clicks when using the section.ae_quick_popover. */
|
||||
div.ae_quick_modal_container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 100;
|
||||
background-color: hsla(0, 0%, 0%, .5);
|
||||
}
|
||||
|
||||
/* The section.ae_quick_popover should be above the rest of the content and centered on the page. */
|
||||
section.ae_quick_popover {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 100;
|
||||
background-color: hsla(0, 0%, 100%, .95);
|
||||
padding: 1rem;
|
||||
border-radius: .5rem;
|
||||
box-shadow: 0 0 1rem hsla(0, 0%, 0%, .5);
|
||||
|
||||
min-height: 98%;
|
||||
min-width: 98%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user