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>
This commit is contained in:
@@ -535,8 +535,8 @@ Button has `data-testid="badge-print-btn"` and shows loading/done/error states w
|
||||
**Indexed Fields:**
|
||||
```typescript
|
||||
badge: `
|
||||
event_badge_id_random, event_badge_id, id,
|
||||
event_id, event_id_random,
|
||||
event_badge_id, id,
|
||||
event_id,
|
||||
full_name, full_name_override, email, email_override,
|
||||
affiliations, affiliations_override,
|
||||
badge_type, badge_type_code, badge_type_code_override, badge_type_override,
|
||||
|
||||
@@ -132,7 +132,7 @@ One exhibitor's presence at an event.
|
||||
|
||||
| Field | Purpose |
|
||||
|---|---|
|
||||
| `event_exhibit_id` / `event_exhibit_id_random` | Primary / URL-safe ID |
|
||||
| `event_exhibit_id` | Primary / URL-safe ID |
|
||||
| `name` | Exhibitor display name |
|
||||
| `code` | Booth number |
|
||||
| `staff_passcode` | Shared sign-in code |
|
||||
@@ -232,4 +232,4 @@ Guard in [ae_tab__manage.svelte](src/routes/events/[event_id]/(leads)/leads/exhi
|
||||
- `license_max` controls how many licensed staff slots an exhibit can have
|
||||
- Export endpoint: `GET /v3/action/event_exhibit/{id}/tracking_export` — requires `leads_api_access`
|
||||
- Custom questions are stored per-exhibit in `leads_custom_questions_json` (not global)
|
||||
- The exhibitor landing page link format: `/events/[event_id]/leads/exhibit/[exhibit_exhibit_id_random]/`
|
||||
- The exhibitor landing page link format: `/events/[event_id]/leads/exhibit/[exhibit_exhibit_id]/`
|
||||
|
||||
@@ -106,7 +106,7 @@ V3 returns detailed error metadata in the `meta.details` object.
|
||||
**Symptom:** Providing a string ID in a search body that the backend maps to an integer can result in **Zero Results** if the underlying view expects a string.
|
||||
|
||||
**Final Solution (Body + Header Injection):**
|
||||
1. **Body:** Inject the raw field name (e.g. `account_id_random`) into the `search_query.and` array to bypass automatic backend mapping.
|
||||
1. **Body:** Inject the raw field name (e.g. `account_id`) into the `search_query.and` array to bypass automatic backend mapping.
|
||||
2. **Headers:** Pass `headers: { 'x-account-id': ... }` manually to provide context for Auth validation.
|
||||
3. **Isolation (IDAA):** Due to specific bugs in the IDAA module, it has been temporarily isolated to a legacy V2 search function (`qry_ae_obj_li__event_v2`) using `default_qry_str` for text searching, while the main module continues to use the V3 implementation.
|
||||
|
||||
|
||||
@@ -32,7 +32,9 @@ export default tseslint.config(
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': 'warn'
|
||||
'@typescript-eslint/no-unused-vars': 'warn',
|
||||
// No base path configured — this rule is not applicable to this project
|
||||
'svelte/no-navigation-without-resolve': 'off'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -458,6 +458,7 @@ export async function search__exhibit_tracking({
|
||||
fulltext_search_qry_str = null,
|
||||
qry_group = null,
|
||||
qry_external_person_id = null,
|
||||
qry_badge_id = null,
|
||||
enabled = 'enabled',
|
||||
hidden = 'all',
|
||||
view = 'default',
|
||||
@@ -473,6 +474,7 @@ export async function search__exhibit_tracking({
|
||||
fulltext_search_qry_str?: string | null;
|
||||
qry_group?: string | null;
|
||||
qry_external_person_id?: string | null;
|
||||
qry_badge_id?: string | null;
|
||||
enabled?: 'enabled' | 'all' | 'not_enabled';
|
||||
hidden?: 'hidden' | 'all' | 'not_hidden';
|
||||
view?: string;
|
||||
@@ -498,6 +500,7 @@ export async function search__exhibit_tracking({
|
||||
|
||||
if (qry_group) search_query.and.push({ field: 'group', op: 'eq', value: qry_group });
|
||||
if (qry_external_person_id) search_query.and.push({ field: 'external_person_id', op: 'eq', value: qry_external_person_id });
|
||||
if (qry_badge_id) search_query.and.push({ field: 'event_badge_id', op: 'eq', value: qry_badge_id });
|
||||
|
||||
if (enabled === 'enabled') search_query.and.push({ field: 'enable', op: 'eq', value: 1 });
|
||||
else if (enabled === 'not_enabled') search_query.and.push({ field: 'enable', op: 'eq', value: 0 });
|
||||
|
||||
@@ -16,12 +16,12 @@ export interface Event {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
code: string;
|
||||
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
conference: boolean;
|
||||
type: string;
|
||||
@@ -114,7 +114,7 @@ export interface Badge {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
event_badge_id: string;
|
||||
event_badge_id_random: string;
|
||||
event_badge_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
@@ -210,10 +210,10 @@ export interface Badge_template {
|
||||
// id_random: string;
|
||||
|
||||
event_badge_template_id?: null | string;
|
||||
event_badge_template_id_random?: null | string;
|
||||
event_badge_template_id_random?: null | string; // NO LONGER USE "_random"
|
||||
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
name: string;
|
||||
description?: null | string;
|
||||
@@ -274,14 +274,14 @@ export interface Badge_template {
|
||||
// Updated 2024-10-16
|
||||
export interface Device {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
// id_random: string; // NO LONGER USE "_random"
|
||||
event_device_id: string;
|
||||
// event_device_id_random: string;
|
||||
// event_device_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
event_id: string;
|
||||
// event_id_random: string;
|
||||
// event_id_random: string; // NO LONGER USE "_random"
|
||||
event_location_id?: string;
|
||||
// event_location_id_random?: string;
|
||||
// event_location_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
code?: string;
|
||||
name: string;
|
||||
@@ -342,12 +342,12 @@ export interface Device {
|
||||
|
||||
export interface Exhibit {
|
||||
id: string;
|
||||
id_random: string;
|
||||
id_random: string; // NO LONGER USE "_random"
|
||||
event_exhibit_id: string;
|
||||
event_exhibit_id_random: string;
|
||||
event_exhibit_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
code: string;
|
||||
name: string;
|
||||
@@ -380,16 +380,16 @@ export interface Exhibit {
|
||||
|
||||
export interface Exhibit_tracking {
|
||||
id: string;
|
||||
id_random: string;
|
||||
id_random: string; // NO LONGER USE "_random"
|
||||
event_exhibit_tracking_id: string;
|
||||
event_exhibit_tracking_id_random: string;
|
||||
event_exhibit_tracking_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
event_exhibit_id: string;
|
||||
event_exhibit_id_random: string;
|
||||
event_exhibit_id_random: string; // NO LONGER USE "_random"
|
||||
event_badge_id: string;
|
||||
event_badge_id_random: string;
|
||||
event_badge_id_random: string; // NO LONGER USE "_random"
|
||||
event_person_id: string;
|
||||
event_person_id_random?: string;
|
||||
event_person_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
@@ -442,28 +442,28 @@ export interface Exhibit_tracking {
|
||||
|
||||
export interface EventFile {
|
||||
id: string;
|
||||
id_random: string;
|
||||
id_random: string; // NO LONGER USE "_random"
|
||||
event_file_id: string;
|
||||
event_file_id_random?: string;
|
||||
event_file_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
hosted_file_id: string;
|
||||
hosted_file_id_random?: string;
|
||||
hosted_file_id_random?: string; // NO LONGER USE "_random"
|
||||
hash_sha256: string;
|
||||
|
||||
for_type?: string;
|
||||
for_id?: string;
|
||||
for_id_random?: string;
|
||||
for_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
event_id: string;
|
||||
event_id_random?: string;
|
||||
event_id_random?: string; // NO LONGER USE "_random"
|
||||
event_session_id?: string;
|
||||
event_session_id_random?: string;
|
||||
event_session_id_random?: string; // NO LONGER USE "_random"
|
||||
event_presentation_id?: string;
|
||||
event_presentation_id_random?: string;
|
||||
event_presentation_id_random?: string; // NO LONGER USE "_random"
|
||||
event_presenter_id?: string;
|
||||
event_presenter_id_random?: string;
|
||||
event_presenter_id_random?: string; // NO LONGER USE "_random"
|
||||
event_location_id?: string;
|
||||
event_location_id_random?: string;
|
||||
event_location_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
filename: string;
|
||||
extension: string;
|
||||
@@ -517,7 +517,7 @@ export interface Location {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
event_location_id: string;
|
||||
event_location_id_random: string;
|
||||
event_location_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
external_id?: null | string;
|
||||
code?: null | string;
|
||||
@@ -525,7 +525,7 @@ export interface Location {
|
||||
type_code?: string;
|
||||
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
name: string;
|
||||
description?: null | string;
|
||||
@@ -571,23 +571,23 @@ export interface Presentation {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
event_presentation_id: string;
|
||||
event_presentation_id_random: string;
|
||||
event_presentation_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
external_id?: null | string;
|
||||
code?: null | string;
|
||||
|
||||
for_type?: string;
|
||||
for_id?: string;
|
||||
for_id_random?: string;
|
||||
for_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
type_code?: string;
|
||||
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
event_session_id: string;
|
||||
event_session_id_random: string;
|
||||
event_session_id_random: string; // NO LONGER USE "_random"
|
||||
event_abstract_id?: null | string;
|
||||
event_abstract_id_random?: null | string;
|
||||
event_abstract_id_random?: null | string; // NO LONGER USE "_random"
|
||||
|
||||
abstract_code?: null | string;
|
||||
|
||||
@@ -630,23 +630,23 @@ export interface Presenter {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
event_presenter_id: string;
|
||||
event_presenter_id_random: string;
|
||||
event_presenter_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
external_id?: string;
|
||||
code?: string;
|
||||
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
event_session_id: string;
|
||||
event_session_id_random: string;
|
||||
event_session_id_random: string; // NO LONGER USE "_random"
|
||||
event_person_id?: null | string;
|
||||
event_person_id_random?: null | string;
|
||||
event_person_id_random?: null | string; // NO LONGER USE "_random"
|
||||
event_presentation_id: string;
|
||||
event_presentation_id_random: string;
|
||||
event_presentation_id_random: string; // NO LONGER USE "_random"
|
||||
person_id?: null | string;
|
||||
person_id_random?: null | string;
|
||||
person_profile_id?: null | string;
|
||||
person_profile_id_random?: null | string; // The new table person_profile will be used soon...
|
||||
person_id_random?: null | string; // NO LONGER USE "_random"
|
||||
person_profile_id?: null | string; // The new table person_profile will be used soon...
|
||||
person_profile_id_random?: null | string; // NO LONGER USE "_random"
|
||||
|
||||
pronouns?: null | string;
|
||||
informal_name?: null | string;
|
||||
@@ -731,24 +731,24 @@ export interface Session {
|
||||
id: string;
|
||||
// id_random: string;
|
||||
event_session_id: string;
|
||||
event_session_id_random: string;
|
||||
event_session_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
external_id: null | string;
|
||||
code: null | string;
|
||||
|
||||
for_type: string;
|
||||
for_id: string;
|
||||
for_id_random: string;
|
||||
for_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
type_code?: string;
|
||||
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
event_location_id?: null | string;
|
||||
event_location_id_random?: null | string;
|
||||
event_location_id_random?: null | string; // NO LONGER USE "_random"
|
||||
|
||||
poc_person_id?: null | string;
|
||||
poc_person_id_random?: null | string;
|
||||
poc_person_id_random?: null | string; // NO LONGER USE "_random"
|
||||
poc_agree?: null | boolean; // General catchall for agreement or consent by the POC
|
||||
poc_kv_json?: null | key_val; // Key value list of the POC by type (examples: 'advocate', 'chair', 'champion', 'moderator', 'organizer')
|
||||
|
||||
@@ -829,6 +829,7 @@ export class MySubClassedDexie extends Dexie {
|
||||
constructor() {
|
||||
super('ae_events_db');
|
||||
this.version(6).stores({
|
||||
// NO LONGER USE "_random"
|
||||
event: `
|
||||
id, event_id, event_id_random,
|
||||
code,
|
||||
@@ -841,7 +842,6 @@ export class MySubClassedDexie extends Dexie {
|
||||
tmp_sort_1, tmp_sort_2,
|
||||
enable, hide, priority, sort, group, notes, created_on, updated_on`,
|
||||
|
||||
// badge: '++id, full_name, email' // Primary key and indexed props
|
||||
badge: `
|
||||
event_badge_id_random, event_badge_id, id,
|
||||
event_id, event_id_random,
|
||||
|
||||
@@ -42,7 +42,7 @@ export interface ae_BaseObj {
|
||||
*/
|
||||
export interface ae_Account extends ae_BaseObj {
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
account_cfg?: ae_AccountCfg;
|
||||
}
|
||||
@@ -52,7 +52,7 @@ export interface ae_Account extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_AccountCfg {
|
||||
id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
modules_enabled?: any;
|
||||
default_no_reply_email?: string;
|
||||
@@ -70,9 +70,9 @@ export interface ae_AccountCfg {
|
||||
*/
|
||||
export interface ae_Site extends ae_BaseObj {
|
||||
site_id: string;
|
||||
site_id_random: string;
|
||||
site_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
url_root?: string;
|
||||
site_cfg_json?: any;
|
||||
@@ -94,11 +94,11 @@ export interface ae_Site extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_SiteDomain extends ae_BaseObj {
|
||||
site_domain_id: string;
|
||||
site_domain_id_random: string;
|
||||
site_domain_id_random: string; // NO LONGER USE "_random"
|
||||
site_id: string;
|
||||
site_id_random: string;
|
||||
site_id_random: string; // NO LONGER USE "_random"
|
||||
account_id?: string;
|
||||
account_id_random?: string;
|
||||
account_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
fqdn: string;
|
||||
is_primary?: boolean;
|
||||
@@ -125,15 +125,15 @@ export interface ae_SiteDomain extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_Journal extends ae_BaseObj {
|
||||
journal_id: string;
|
||||
journal_id_random: string;
|
||||
journal_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
person_id?: string;
|
||||
person_id_random?: string;
|
||||
person_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
for_type?: string;
|
||||
for_id?: string;
|
||||
for_id_random?: string;
|
||||
for_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
type_code?: string;
|
||||
tags?: string;
|
||||
@@ -163,12 +163,12 @@ export interface ae_Journal extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_JournalEntry extends ae_BaseObj {
|
||||
journal_entry_id: string;
|
||||
// journal_entry_id_random: string;
|
||||
// journal_entry_id_random: string; // NO LONGER USE "_random"
|
||||
journal_id: string;
|
||||
// journal_id_random: string;
|
||||
// journal_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
person_id?: string;
|
||||
person_id_random?: string;
|
||||
person_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
template?: boolean;
|
||||
|
||||
@@ -235,12 +235,12 @@ export interface ae_JournalEntry extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_Person extends ae_BaseObj {
|
||||
person_id: string;
|
||||
person_id_random: string;
|
||||
person_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
user_id?: string;
|
||||
user_id_random?: string;
|
||||
user_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
prefix?: string;
|
||||
title_names?: string;
|
||||
@@ -282,11 +282,11 @@ export interface ae_Person extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_User extends ae_BaseObj {
|
||||
user_id: string;
|
||||
user_id_random: string;
|
||||
user_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
person_id?: string;
|
||||
person_id_random?: string;
|
||||
person_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
username: string;
|
||||
email?: string;
|
||||
@@ -309,10 +309,10 @@ export interface ae_User extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_UserRole {
|
||||
id: string;
|
||||
user_id_random: string;
|
||||
user_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
for_type?: string;
|
||||
for_id_random?: string;
|
||||
for_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
code?: string;
|
||||
name?: string;
|
||||
@@ -327,12 +327,12 @@ export interface ae_UserRole {
|
||||
*/
|
||||
export interface ae_Address extends ae_BaseObj {
|
||||
address_id: string;
|
||||
address_id_random: string;
|
||||
address_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
for_type?: string;
|
||||
for_id_random?: string;
|
||||
for_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
attention_to?: string;
|
||||
organization_name?: string;
|
||||
@@ -356,13 +356,13 @@ export interface ae_Address extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_Contact extends ae_BaseObj {
|
||||
contact_id: string;
|
||||
contact_id_random: string;
|
||||
contact_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
address_id_random?: string;
|
||||
address_id_random?: string; // NO LONGER USE "_random"
|
||||
for_type?: string;
|
||||
for_id_random?: string;
|
||||
for_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
title?: string;
|
||||
tagline?: string;
|
||||
@@ -382,9 +382,9 @@ export interface ae_Contact extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_ActivityLog extends ae_BaseObj {
|
||||
activity_log_id: string;
|
||||
activity_log_id_random: string;
|
||||
activity_log_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
person_id_random?: string;
|
||||
user_id_random?: string;
|
||||
@@ -408,9 +408,9 @@ export interface ae_ActivityLog extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_Event extends ae_BaseObj {
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
conference: boolean;
|
||||
type?: string;
|
||||
@@ -453,7 +453,7 @@ export interface ae_Event extends ae_BaseObj {
|
||||
* EventCfg - Advanced configuration for an event
|
||||
*/
|
||||
export interface ae_EventCfg extends ae_BaseObj {
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
enable_comments?: boolean;
|
||||
unauthenticated_access?: boolean;
|
||||
@@ -468,16 +468,16 @@ export interface ae_EventCfg extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventBadge extends ae_BaseObj {
|
||||
event_badge_id: string;
|
||||
event_badge_id_random: string;
|
||||
event_badge_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
person_id: string;
|
||||
person_id_random: string;
|
||||
person_id_random: string; // NO LONGER USE "_random"
|
||||
event_person_id?: string | null;
|
||||
event_person_id_random?: string | null;
|
||||
event_person_id_random?: string | null; // NO LONGER USE "_random"
|
||||
|
||||
event_badge_template_id?: string | null;
|
||||
event_badge_template_id_random?: string | null;
|
||||
event_badge_template_id_random?: string | null; // NO LONGER USE "_random"
|
||||
|
||||
badge_type_code?: string | null;
|
||||
badge_type?: string | null;
|
||||
@@ -516,9 +516,9 @@ export interface ae_EventBadge extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventBadgeTemplate extends ae_BaseObj {
|
||||
event_badge_template_id: string;
|
||||
event_badge_template_id_random: string;
|
||||
event_badge_template_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
logo_path?: string | null;
|
||||
header_path?: string | null;
|
||||
@@ -541,9 +541,9 @@ export interface ae_EventBadgeTemplate extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventLocation extends ae_BaseObj {
|
||||
event_location_id: string;
|
||||
event_location_id_random: string;
|
||||
event_location_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
location_type?: string | null;
|
||||
location_type_code?: string | null;
|
||||
@@ -561,13 +561,13 @@ export interface ae_EventLocation extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventSession extends ae_BaseObj {
|
||||
event_session_id: string;
|
||||
event_session_id_random: string;
|
||||
event_session_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
event_location_id?: string | null;
|
||||
event_location_id_random?: string | null;
|
||||
event_location_id_random?: string | null; // NO LONGER USE "_random"
|
||||
event_track_id?: string | null;
|
||||
event_track_id_random?: string | null;
|
||||
event_track_id_random?: string | null; // NO LONGER USE "_random"
|
||||
|
||||
type_code?: string | null;
|
||||
start_datetime?: string | Date | null;
|
||||
@@ -610,13 +610,13 @@ export interface ae_EventSession extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventPresentation extends ae_BaseObj {
|
||||
event_presentation_id: string;
|
||||
event_presentation_id_random: string;
|
||||
event_presentation_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
event_session_id: string;
|
||||
event_session_id_random: string;
|
||||
event_session_id_random: string; // NO LONGER USE "_random"
|
||||
event_abstract_id?: string | null;
|
||||
event_abstract_id_random?: string | null;
|
||||
event_abstract_id_random?: string | null; // NO LONGER USE "_random"
|
||||
|
||||
abstract_code?: string | null;
|
||||
type_code?: string | null;
|
||||
@@ -639,11 +639,11 @@ export interface ae_EventPresentation extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventPresenter extends ae_BaseObj {
|
||||
event_presenter_id: string;
|
||||
event_presenter_id_random: string;
|
||||
event_presenter_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
person_id?: string | null;
|
||||
person_id_random?: string | null;
|
||||
person_id_random?: string | null; // NO LONGER USE "_random"
|
||||
|
||||
pronouns?: string | null;
|
||||
informal_name?: string | null;
|
||||
@@ -666,9 +666,9 @@ export interface ae_EventPresenter extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventTrack extends ae_BaseObj {
|
||||
event_track_id: string;
|
||||
event_track_id_random: string;
|
||||
event_track_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
track_type?: string;
|
||||
track_type_code?: string;
|
||||
@@ -682,9 +682,9 @@ export interface ae_EventTrack extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_HostedFile extends ae_BaseObj {
|
||||
hosted_file_id: string;
|
||||
hosted_file_id_random: string;
|
||||
hosted_file_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
hash_sha256?: string;
|
||||
subdirectory_path?: string;
|
||||
@@ -701,10 +701,10 @@ export interface ae_HostedFile extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_HostedFileLink {
|
||||
id: string;
|
||||
account_id_random: string;
|
||||
hosted_file_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
hosted_file_id_random: string; // NO LONGER USE "_random"
|
||||
link_to_type: string;
|
||||
link_to_id_random: string;
|
||||
link_to_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
created_on: string | Date;
|
||||
updated_on: string | Date;
|
||||
@@ -715,16 +715,16 @@ export interface ae_HostedFileLink {
|
||||
*/
|
||||
export interface ae_DataStore extends ae_BaseObj {
|
||||
data_store_id: string;
|
||||
data_store_id_random: string;
|
||||
data_store_id_random: string; // NO LONGER USE "_random"
|
||||
account_id?: null | string;
|
||||
account_id_random?: null | string;
|
||||
account_id_random?: null | string; // NO LONGER USE "_random"
|
||||
|
||||
for_type?: null | string;
|
||||
for_id_random?: null | string;
|
||||
for_id_random?: null | string; // NO LONGER USE "_random"
|
||||
for_id?: null | string;
|
||||
|
||||
person_id_random?: null | string;
|
||||
user_id_random?: null | string;
|
||||
person_id_random?: null | string; // NO LONGER USE "_random"
|
||||
user_id_random?: null | string; // NO LONGER USE "_random"
|
||||
|
||||
type?: null | string;
|
||||
|
||||
@@ -747,9 +747,9 @@ export interface ae_DataStore extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_Post extends ae_BaseObj {
|
||||
post_id: string;
|
||||
// post_id_random: string;
|
||||
// post_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
// account_id_random: string;
|
||||
// account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
title: string;
|
||||
content: string;
|
||||
@@ -769,9 +769,9 @@ export interface ae_Post extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_PostComment extends ae_BaseObj {
|
||||
post_comment_id: string;
|
||||
// post_comment_id_random: string;
|
||||
// post_comment_id_random: string; // NO LONGER USE "_random"
|
||||
post_id: string;
|
||||
// post_id_random: string;
|
||||
// post_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
content: string;
|
||||
anonymous: boolean;
|
||||
@@ -783,9 +783,9 @@ export interface ae_PostComment extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_Page extends ae_BaseObj {
|
||||
page_id: string;
|
||||
page_id_random: string;
|
||||
page_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
alias: string;
|
||||
title: string;
|
||||
@@ -801,9 +801,9 @@ export interface ae_Page extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_Archive extends ae_BaseObj {
|
||||
archive_id: string;
|
||||
archive_id_random: string;
|
||||
archive_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
archive_type?: string;
|
||||
topic_id?: string;
|
||||
@@ -824,8 +824,8 @@ export interface ae_Archive extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_ArchiveContent extends ae_BaseObj {
|
||||
archive_content_id: string;
|
||||
archive_content_id_random: string;
|
||||
archive_id_random: string;
|
||||
archive_content_id_random: string; // NO LONGER USE "_random"
|
||||
archive_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
archive_content_type?: string;
|
||||
content_html?: string;
|
||||
@@ -833,7 +833,7 @@ export interface ae_ArchiveContent extends ae_BaseObj {
|
||||
|
||||
duration?: string;
|
||||
|
||||
hosted_file_id_random?: string;
|
||||
hosted_file_id_random?: string; // NO LONGER USE "_random"
|
||||
filename?: string;
|
||||
subdirectory_path?: string;
|
||||
}
|
||||
@@ -843,15 +843,15 @@ export interface ae_ArchiveContent extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventFile extends ae_BaseObj {
|
||||
event_file_id: string;
|
||||
event_file_id_random?: string;
|
||||
event_file_id_random?: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random?: string;
|
||||
event_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
hosted_file_id: string;
|
||||
hosted_file_id_random?: string;
|
||||
hosted_file_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
for_type?: string | null;
|
||||
for_id_random?: string | null;
|
||||
for_id_random?: string | null; // NO LONGER USE "_random"
|
||||
|
||||
filename?: string;
|
||||
filename_no_ext?: string;
|
||||
@@ -868,10 +868,10 @@ export interface ae_EventFile extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventDevice extends ae_BaseObj {
|
||||
event_device_id: string;
|
||||
event_device_id_random: string;
|
||||
event_device_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_location_id_random?: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
event_location_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
app_mode?: string;
|
||||
status?: string;
|
||||
@@ -886,9 +886,9 @@ export interface ae_EventDevice extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventAbstract extends ae_BaseObj {
|
||||
event_abstract_id: string;
|
||||
event_abstract_id_random: string;
|
||||
event_abstract_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
external_id?: string;
|
||||
abstract?: string;
|
||||
@@ -901,9 +901,9 @@ export interface ae_EventAbstract extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_Organization extends ae_BaseObj {
|
||||
organization_id: string;
|
||||
organization_id_random: string;
|
||||
organization_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
tagline?: string;
|
||||
logo_path?: string;
|
||||
@@ -915,14 +915,14 @@ export interface ae_Organization extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventRegistration extends ae_BaseObj {
|
||||
event_registration_id: string;
|
||||
event_registration_id_random: string;
|
||||
event_registration_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
person_id: string;
|
||||
person_id_random: string;
|
||||
person_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
organization_id_random?: string;
|
||||
contact_id_random?: string;
|
||||
organization_id_random?: string; // NO LONGER USE "_random"
|
||||
contact_id_random?: string; // NO LONGER USE "_random"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -930,13 +930,13 @@ export interface ae_EventRegistration extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventExhibit extends ae_BaseObj {
|
||||
event_exhibit_id: string;
|
||||
event_exhibit_id_random: string;
|
||||
event_exhibit_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
organization_id_random?: string;
|
||||
contact_id_random?: string;
|
||||
person_id_random?: string;
|
||||
organization_id_random?: string; // NO LONGER USE "_random"
|
||||
contact_id_random?: string; // NO LONGER USE "_random"
|
||||
person_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
tagline?: string;
|
||||
logo_path?: string;
|
||||
@@ -948,13 +948,13 @@ export interface ae_EventExhibit extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventExhibitTracking extends ae_BaseObj {
|
||||
event_exhibit_tracking_id: string;
|
||||
event_exhibit_tracking_id_random: string;
|
||||
event_exhibit_tracking_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_exhibit_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
event_exhibit_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
event_person_id_random?: string;
|
||||
event_badge_id_random?: string;
|
||||
event_person_id_random?: string; // NO LONGER USE "_random"
|
||||
event_badge_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
external_person_id?: string | null;
|
||||
|
||||
@@ -968,14 +968,14 @@ export interface ae_EventExhibitTracking extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventPerson extends ae_BaseObj {
|
||||
event_person_id: string;
|
||||
event_person_id_random: string;
|
||||
event_person_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
person_id: string;
|
||||
person_id_random: string;
|
||||
person_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
event_badge_id_random?: string;
|
||||
event_registration_id_random?: string;
|
||||
event_badge_id_random?: string; // NO LONGER USE "_random"
|
||||
event_registration_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
passcode?: string;
|
||||
agree_to_tc?: boolean;
|
||||
@@ -986,10 +986,10 @@ export interface ae_EventPerson extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_EventPersonProfile extends ae_BaseObj {
|
||||
event_person_profile_id: string;
|
||||
event_person_profile_id_random: string;
|
||||
event_person_profile_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_person_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
event_person_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
tagline?: string;
|
||||
biography?: string;
|
||||
@@ -1003,11 +1003,11 @@ export interface ae_EventPersonProfile extends ae_BaseObj {
|
||||
* EventPersonTracking - Attendance and session interaction tracking
|
||||
*/
|
||||
export interface ae_EventPersonTracking extends ae_BaseObj {
|
||||
event_person_id_random: string;
|
||||
event_person_id_random: string; // NO LONGER USE "_random"
|
||||
event_id: string;
|
||||
event_id_random: string;
|
||||
event_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
event_session_id_random?: string;
|
||||
event_session_id_random?: string; // NO LONGER USE "_random"
|
||||
|
||||
check_in_out?: boolean;
|
||||
in_datetime?: string | Date;
|
||||
@@ -1019,11 +1019,11 @@ export interface ae_EventPersonTracking extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_Sponsorship extends ae_BaseObj {
|
||||
sponsorship_id: string;
|
||||
sponsorship_id_random: string;
|
||||
sponsorship_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
sponsorship_cfg_id_random: string;
|
||||
sponsorship_cfg_id_random: string; // NO LONGER USE "_random"
|
||||
amount?: number;
|
||||
paid?: boolean;
|
||||
}
|
||||
@@ -1033,9 +1033,9 @@ export interface ae_Sponsorship extends ae_BaseObj {
|
||||
*/
|
||||
export interface ae_SponsorshipCfg extends ae_BaseObj {
|
||||
sponsorship_cfg_id: string;
|
||||
sponsorship_cfg_id_random: string;
|
||||
sponsorship_cfg_id_random: string; // NO LONGER USE "_random"
|
||||
account_id: string;
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
|
||||
level_li_json?: any;
|
||||
start_datetime?: string | Date;
|
||||
@@ -1046,7 +1046,7 @@ export interface ae_SponsorshipCfg extends ae_BaseObj {
|
||||
* LogClientViewing - Playback and interaction tracking for media
|
||||
*/
|
||||
export interface ae_LogClientViewing extends ae_BaseObj {
|
||||
account_id_random: string;
|
||||
account_id_random: string; // NO LONGER USE "_random"
|
||||
external_client_id: string;
|
||||
|
||||
object_type: string;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts">
|
||||
/** @type {import('./$types').LayoutData} */
|
||||
// /** @type {import('./$types').LayoutProps} */
|
||||
|
||||
let log_lvl: number = 0;
|
||||
|
||||
@@ -11,13 +10,6 @@
|
||||
import '../app.css';
|
||||
|
||||
// *** Import other supporting libraries
|
||||
// import {
|
||||
// ArrowBigRight,
|
||||
// CircleX,
|
||||
// RefreshCw,
|
||||
// RefreshCcw,
|
||||
// RefreshCcwDot
|
||||
// } from '@lucide/svelte';
|
||||
|
||||
// Highlight JS
|
||||
import hljs from 'highlight.js/lib/core';
|
||||
@@ -39,13 +31,10 @@
|
||||
// import Analytics from '$lib/app_components/e_app_analytics.svelte';
|
||||
import { ae_loc, ae_sess, ae_api, slct, slct_trigger, ae_auth_error } from '$lib/stores/ae_stores';
|
||||
import { LoaderCircle } from '@lucide/svelte';
|
||||
// import { events_loc, events_slct } from '$lib/stores/ae_events_stores';
|
||||
|
||||
// import MyClipboard from '$lib/app_components/e_app_clipboard.svelte';
|
||||
import E_app_debug_menu from '$lib/app_components/e_app_debug_menu.svelte';
|
||||
import E_app_sys_bar from '$lib/app_components/e_app_sys_bar.svelte';
|
||||
import { pwa_install } from '$lib/pwa/pwa_install.svelte';
|
||||
// import E_app_sys_menu from '$lib/app_components/e_app_sys_menu.svelte'; // replaced by E_app_sys_bar
|
||||
|
||||
interface Props {
|
||||
data: any;
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
text-gray-800 dark:text-gray-200
|
||||
"
|
||||
>
|
||||
{#if !$ae_sess?.disable_sys_nav}
|
||||
{#if !$ae_sess?.disable_sys_nav && !$ae_loc?.iframe}
|
||||
<nav
|
||||
bind:clientHeight={nav_y_height}
|
||||
class:hidden={yTop > 600}
|
||||
@@ -263,8 +263,8 @@
|
||||
|
||||
<section
|
||||
class:iframe={$ae_loc?.iframe}
|
||||
class:pt-0={!!$ae_sess?.disable_sys_nav}
|
||||
class:pt-12={!$ae_sess?.disable_sys_nav && nav_y_height <= 50}
|
||||
class:pt-0={!!$ae_sess?.disable_sys_nav || $ae_loc?.iframe}
|
||||
class:pt-12={!$ae_sess?.disable_sys_nav && nav_y_height > 0 && nav_y_height <= 50}
|
||||
class:pt-20={!$ae_sess?.disable_sys_nav && nav_y_height > 50 && nav_y_height <= 100}
|
||||
class:pt-32={!$ae_sess?.disable_sys_nav && nav_y_height > 100 && nav_y_height <= 150}
|
||||
class:pt-40={!$ae_sess?.disable_sys_nav && nav_y_height > 150 && nav_y_height <= 200}
|
||||
|
||||
@@ -378,7 +378,7 @@
|
||||
<!-- *** badge_front section start *** -->
|
||||
<section
|
||||
class="badge_front badge_type__{effective_badge_type_code.toLowerCase()}
|
||||
flex flex-col gap-1
|
||||
flex flex-col gap-0
|
||||
items-stretch justify-between
|
||||
min-h-[6.0in]
|
||||
max-h-[6.0in]
|
||||
@@ -394,12 +394,12 @@
|
||||
>
|
||||
<span
|
||||
class="
|
||||
print:hidden absolute top-1 left-4
|
||||
text-xs italic
|
||||
text-gray-500 group-hover:text-red-800
|
||||
transition-all
|
||||
"
|
||||
>
|
||||
print:hidden absolute top-1 left-4
|
||||
text-xs italic
|
||||
text-gray-500 group-hover:text-red-800
|
||||
transition-all
|
||||
"
|
||||
>
|
||||
{#if show_badge_back}Front of badge{:else}Badge preview{/if}
|
||||
</span>
|
||||
|
||||
@@ -443,7 +443,8 @@
|
||||
<div
|
||||
class="badge_body
|
||||
grow
|
||||
max-h-[4in] m-0 p-0
|
||||
m-0 p-0
|
||||
px-1
|
||||
overflow-clip
|
||||
flex flex-col gap-1
|
||||
items-stretch justify-between
|
||||
@@ -578,7 +579,7 @@
|
||||
{:then result}
|
||||
{#if result}
|
||||
<img
|
||||
class="qr_code mecard_qr w-[0.75in] max-w-[0.75in]"
|
||||
class="qr_code w-[1.10in] max-w-[1.10in] m-0 p-0"
|
||||
src={result}
|
||||
alt="Badge QR code"
|
||||
/>
|
||||
@@ -597,6 +598,7 @@
|
||||
max-w-full
|
||||
m-0 p-0
|
||||
overflow-hidden
|
||||
border-t-2 border-blue-500/75
|
||||
flex flex-row gap-1 items-center justify-center
|
||||
hover:outline-2 hover:outline-dashed hover:outline-gray-500/75
|
||||
"
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
const local_ids = local_results
|
||||
.map((e) => String(e.id || e.event_exhibit_id))
|
||||
.filter(Boolean);
|
||||
|
||||
|
||||
if (current_search_id === last_search_id) {
|
||||
if (log_lvl) console.log(`✅ [Trace] Exhibit Search #${current_search_id}: Local path found ${local_ids.length} items.`);
|
||||
untrack(() => {
|
||||
@@ -202,9 +202,9 @@
|
||||
const api_ids = results
|
||||
.map((e: any) => String(e.id || e.event_exhibit_id))
|
||||
.filter(Boolean);
|
||||
|
||||
|
||||
if (log_lvl) console.log(`📦 [Trace] Exhibit Search #${current_search_id}: API revalidation found ${api_ids.length} items.`);
|
||||
|
||||
|
||||
untrack(() => {
|
||||
exhibit_id_li = api_ids;
|
||||
$events_sess.leads.submit_status__search = 'done';
|
||||
@@ -241,9 +241,10 @@
|
||||
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 w-full max-w-6xl"
|
||||
>
|
||||
{#each $lq__event_exhibit_obj_li as exhibit_obj (exhibit_obj.event_exhibit_id)}
|
||||
<!-- Force iframe mode (hides header/footer and passes exhibit_id via URL param) so the exhibit view can optimize for lead capture and hide irrelevant info. -->
|
||||
<a
|
||||
href="/events/{page.params
|
||||
.event_id}/leads/exhibit/{exhibit_obj.event_exhibit_id}"
|
||||
.event_id}/leads/exhibit/{exhibit_obj.event_exhibit_id}?iframe=true"
|
||||
class="card card-hover p-4 flex flex-col items-center justify-center text-center space-y-2 preset-tonal"
|
||||
>
|
||||
<Store size="2em" />
|
||||
|
||||
@@ -79,6 +79,8 @@
|
||||
const show_hidden = search_params.show_hidden;
|
||||
|
||||
return raw_lead_li.filter(lead => {
|
||||
// Never show disabled (removed) leads — enable=0/false means the exhibitor deleted them
|
||||
if (lead.enable === 0 || lead.enable === false) return false;
|
||||
// Exclude hidden leads unless show_hidden is toggled on
|
||||
if (!show_hidden && lead.hide) return false;
|
||||
if (licensee_filter === 'all') return true;
|
||||
@@ -211,6 +213,8 @@
|
||||
.where('event_exhibit_id')
|
||||
.equals(target_exhibit_id)
|
||||
.filter((tracking) => {
|
||||
// 0. Never include disabled (removed) records — they're soft-deleted
|
||||
if (!tracking.enable) return false;
|
||||
// 1. Hide filter — exclude hidden records unless show_hidden is on
|
||||
if (!params.show_hidden && tracking.hide) return false;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
.where('event_exhibit_id')
|
||||
.equals(exhibit_id)
|
||||
.toArray();
|
||||
|
||||
|
||||
// Map badge_id -> tracking_id
|
||||
const map = new Map();
|
||||
leads.forEach(l => {
|
||||
@@ -68,6 +68,7 @@
|
||||
|
||||
async function add_as_lead(badge: ae_EventBadge) {
|
||||
// Use id or id_random — whichever is populated from search results
|
||||
// NO LONGER USE "_random"
|
||||
const badge_id = badge.event_badge_id_random || badge.event_badge_id;
|
||||
if (!badge_id) {
|
||||
console.warn('[add_as_lead] badge missing event_badge_id_random and event_badge_id', badge);
|
||||
@@ -117,23 +118,23 @@
|
||||
</script>
|
||||
|
||||
<div class="lead-manual-search space-y-4 w-full">
|
||||
<form
|
||||
class="search_form flex flex-row flex-wrap gap-1 items-center justify-center w-full px-2 py-2 preset-tonal-primary rounded-lg shadow-sm"
|
||||
<form
|
||||
class="search_form flex flex-row flex-wrap gap-1 items-center justify-center w-full px-2 py-2 preset-tonal-primary rounded-lg shadow-sm"
|
||||
onsubmit={(e) => { e.preventDefault(); handle_search(); }}
|
||||
>
|
||||
<div class="flex flex-col md:flex-row items-center justify-center gap-1 grow">
|
||||
<input
|
||||
type="search"
|
||||
<input
|
||||
type="search"
|
||||
bind:value={search_query}
|
||||
placeholder="Attendee name, email, or badge ID..."
|
||||
placeholder="Attendee name, email, or badge ID..."
|
||||
class="input text-lg font-mono grow transition-all w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row items-center justify-center gap-1">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-lg preset-tonal-primary border border-primary-500 hover:preset-tonal-primary text-2xl font-bold w-48 transition-all"
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-lg preset-tonal-primary border border-primary-500 hover:preset-tonal-primary text-2xl font-bold w-48 transition-all"
|
||||
disabled={searching}
|
||||
>
|
||||
{#if searching}
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { liveQuery } from 'dexie';
|
||||
import { db_events } from '$lib/ae_events/db_events';
|
||||
import { ae_api } from '$lib/stores/ae_stores';
|
||||
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
|
||||
import { events_loc } from '$lib/stores/ae_events_stores';
|
||||
import { events_func } from '$lib/ae_events/ae_events_functions';
|
||||
import Element_qr_scanner_v3 from '$lib/elements/element_qr_scanner_v3.svelte';
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import { Camera, CircleAlert, CircleCheck, Eye, LoaderCircle, RefreshCw, ShieldOff, UserPlus, X } from '@lucide/svelte';
|
||||
import { Camera, CircleAlert, CircleCheck, Eye, LoaderCircle, RefreshCw, RotateCcw, ShieldOff, UserPlus, X } from '@lucide/svelte';
|
||||
import { SvelteMap } from 'svelte/reactivity';
|
||||
import type { ae_EventBadge } from '$lib/types/ae_types';
|
||||
|
||||
interface Props {
|
||||
@@ -27,7 +28,8 @@
|
||||
|
||||
let { exhibit_id, scan_qualify = 'rapid', on_lead_added }: Props = $props();
|
||||
|
||||
// Track existing leads to prevent duplicates
|
||||
// Track existing leads to detect duplicates and previously-removed records.
|
||||
// Value includes tracking_id AND enabled status so we can offer re-activation.
|
||||
let existing_leads_map = $derived(
|
||||
liveQuery(async () => {
|
||||
const leads = await db_events.exhibit_tracking
|
||||
@@ -35,17 +37,21 @@
|
||||
.equals(exhibit_id)
|
||||
.toArray();
|
||||
|
||||
const map = new Map();
|
||||
const map = new SvelteMap<string, { tracking_id: string; enabled: boolean }>();
|
||||
leads.forEach(l => {
|
||||
const b_id = l.event_badge_id_random || l.event_badge_id?.toString();
|
||||
if (b_id) map.set(b_id, l.event_exhibit_tracking_id_random || l.event_exhibit_tracking_id?.toString());
|
||||
const b_id = l.event_badge_id?.toString();
|
||||
if (b_id) map.set(b_id, {
|
||||
tracking_id: l.event_exhibit_tracking_id?.toString() ?? '',
|
||||
// enable stored as 1/0 or true/false — !! normalises all falsy values
|
||||
enabled: !!l.enable
|
||||
});
|
||||
});
|
||||
return map;
|
||||
})
|
||||
);
|
||||
|
||||
let start_qr_scanner = $state(true);
|
||||
let scanning_status = $state('idle'); // idle, scanning, found, adding, success, error, already_added, tracking_blocked
|
||||
let scanning_status = $state('idle'); // idle, scanning, found, adding, success, error, already_added, tracking_blocked, reenable
|
||||
let found_badge: ae_EventBadge | null = $state(null);
|
||||
let existing_tracking_id = $state('');
|
||||
let new_tracking_id = $state(''); // ID of the lead just created — used for "View Details" link
|
||||
@@ -58,10 +64,12 @@
|
||||
if (obj && obj.type === 'event_badge' && obj.id) {
|
||||
start_qr_scanner = false;
|
||||
|
||||
// Check if already exists
|
||||
// Check if already exists (enabled or disabled/removed)
|
||||
if ($existing_leads_map?.has(obj.id)) {
|
||||
scanning_status = 'already_added';
|
||||
existing_tracking_id = $existing_leads_map.get(obj.id);
|
||||
const existing = $existing_leads_map.get(obj.id)!;
|
||||
existing_tracking_id = existing.tracking_id;
|
||||
// Distinguish: active lead vs previously-removed lead
|
||||
scanning_status = existing.enabled ? 'already_added' : 'reenable';
|
||||
} else {
|
||||
scanning_status = 'found';
|
||||
}
|
||||
@@ -95,7 +103,10 @@
|
||||
}
|
||||
|
||||
async function confirm_add_lead() {
|
||||
if (!found_badge || !found_badge.event_badge_id_random) return;
|
||||
if (!found_badge || !found_badge.event_badge_id) {
|
||||
console.warn('[leads] Guard failed — event_badge_id missing. found_badge:', found_badge);
|
||||
return;
|
||||
}
|
||||
|
||||
scanning_status = 'adding';
|
||||
|
||||
@@ -106,14 +117,14 @@
|
||||
const result = await events_func.create_ae_obj__exhibit_tracking({
|
||||
api_cfg: $ae_api,
|
||||
exhibit_id: exhibit_id,
|
||||
event_badge_id: found_badge.event_badge_id_random,
|
||||
event_badge_id: found_badge.event_badge_id,
|
||||
external_person_id: user_email,
|
||||
group: user_email
|
||||
});
|
||||
|
||||
if (result) {
|
||||
// Capture the new tracking ID so we can link to it
|
||||
new_tracking_id = result.event_exhibit_tracking_id_random || String(result.event_exhibit_tracking_id || '');
|
||||
new_tracking_id = String(result.event_exhibit_tracking_id || '');
|
||||
scanning_status = 'success';
|
||||
if (on_lead_added) on_lead_added(found_badge);
|
||||
|
||||
@@ -125,17 +136,68 @@
|
||||
setTimeout(reset_scanner, 2000);
|
||||
}
|
||||
} else {
|
||||
// API returned false/null — network error, API down, auth failure, or duplicate.
|
||||
// Surface the error rather than leaving the scanner frozen at 'adding'.
|
||||
scanning_status = 'error';
|
||||
error_msg = 'Failed to add lead. Check your connection and try again.';
|
||||
// API returned false/null — could be a duplicate of a previously-removed record
|
||||
// that isn't in the local IDB cache (e.g. after IDB clear or on a second device).
|
||||
// Search the API for a disabled tracking record for this badge before surfacing an error.
|
||||
try {
|
||||
const disabled_li = await events_func.search__exhibit_tracking({
|
||||
api_cfg: $ae_api,
|
||||
event_id: page.params.event_id,
|
||||
event_exhibit_id: exhibit_id,
|
||||
qry_badge_id: found_badge.event_badge_id,
|
||||
enabled: 'not_enabled',
|
||||
log_lvl: 1
|
||||
});
|
||||
if (disabled_li.length > 0) {
|
||||
// Found a disabled record — offer to re-activate instead of showing an error
|
||||
existing_tracking_id = String(disabled_li[0].event_exhibit_tracking_id || '');
|
||||
scanning_status = 'reenable';
|
||||
} else {
|
||||
scanning_status = 'error';
|
||||
error_msg = 'Failed to add lead. Check your connection and try again.';
|
||||
}
|
||||
} catch {
|
||||
scanning_status = 'error';
|
||||
error_msg = 'Failed to add lead. Check your connection and try again.';
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
scanning_status = 'error';
|
||||
error_msg = 'Failed to add lead. They might already be added.';
|
||||
}
|
||||
}
|
||||
|
||||
async function confirm_reenable_lead() {
|
||||
// Re-activate a lead that was previously removed (enable=false).
|
||||
// existing_tracking_id is already set from the map or the API fallback search.
|
||||
if (!existing_tracking_id) return;
|
||||
scanning_status = 'adding';
|
||||
|
||||
try {
|
||||
const result = await events_func.update_ae_obj__exhibit_tracking({
|
||||
api_cfg: $ae_api,
|
||||
exhibit_id,
|
||||
exhibit_tracking_id: existing_tracking_id,
|
||||
data: { enable: true }
|
||||
});
|
||||
|
||||
if (result) {
|
||||
new_tracking_id = existing_tracking_id;
|
||||
scanning_status = 'success';
|
||||
if (on_lead_added && found_badge) on_lead_added(found_badge);
|
||||
// Re-enabled lead: success card shows "View Details" link — user navigates manually.
|
||||
// Auto-reset after 2s so the scanner is ready for the next badge.
|
||||
setTimeout(reset_scanner, 2000);
|
||||
} else {
|
||||
scanning_status = 'error';
|
||||
error_msg = 'Failed to restore lead. Please try again.';
|
||||
}
|
||||
} catch {
|
||||
scanning_status = 'error';
|
||||
error_msg = 'Failed to restore lead. Please try again.';
|
||||
}
|
||||
}
|
||||
|
||||
function reset_scanner() {
|
||||
scanning_status = 'idle';
|
||||
found_badge = null;
|
||||
@@ -176,6 +238,43 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{:else if scanning_status === 'reenable'}
|
||||
<div class="card p-6 w-full max-w-md space-y-4 preset-tonal-warning shadow-xl border-2 border-warning-500 animate-in zoom-in">
|
||||
<div class="text-center space-y-2">
|
||||
<RotateCcw size="3em" class="mx-auto text-warning-500" />
|
||||
<h3 class="h3 font-bold">Previously Removed</h3>
|
||||
<p class="text-xl font-bold">{found_badge?.full_name || 'Attendee'}</p>
|
||||
<p class="opacity-70 text-sm">This lead was removed. Re-activate to restore their record including any saved notes and responses.</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="w-full rounded-xl py-5 font-bold text-base flex items-center justify-center gap-2 bg-warning-500 text-white shadow-md hover:brightness-110 active:brightness-90 transition-all cursor-pointer"
|
||||
onclick={confirm_reenable_lead}
|
||||
>
|
||||
<RotateCcw size="1.5em" />
|
||||
Re-activate Lead
|
||||
</button>
|
||||
|
||||
<a
|
||||
href={`/events/${page.params.event_id}/leads/exhibit/${exhibit_id}/lead/${existing_tracking_id}`}
|
||||
class="btn btn-sm w-full preset-outlined-warning"
|
||||
class:hidden={!$ae_loc.trusted_access}
|
||||
>
|
||||
<Eye size="1em" />
|
||||
View Existing Record
|
||||
</a>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="w-full rounded-lg py-3 text-sm font-medium flex items-center justify-center gap-2 border border-surface-500/40 hover:bg-surface-200-800 transition-colors cursor-pointer opacity-70"
|
||||
onclick={reset_scanner}
|
||||
>
|
||||
<X size="1em" />
|
||||
Cancel / Scan Again
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{:else if scanning_status === 'already_added'}
|
||||
<div class="card p-6 w-full max-w-md space-y-4 preset-tonal-secondary shadow-xl border-2 border-secondary-500 animate-in zoom-in">
|
||||
<div class="text-center space-y-2">
|
||||
|
||||
@@ -21,9 +21,10 @@
|
||||
import { events_func } from '$lib/ae_events/ae_events_functions';
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import type { ae_EventBadge } from '$lib/types/ae_types';
|
||||
import { SvelteMap } from 'svelte/reactivity';
|
||||
import {
|
||||
CircleCheck, Eye, Layers, LoaderCircle,
|
||||
RefreshCw, ScanLine, ShieldOff, UserPlus, X
|
||||
RefreshCw, RotateCcw, ScanLine, ShieldOff, UserPlus, X
|
||||
} from '@lucide/svelte';
|
||||
|
||||
interface Props {
|
||||
@@ -38,7 +39,7 @@
|
||||
const is_supported = typeof window !== 'undefined' && 'BarcodeDetector' in window;
|
||||
|
||||
// --- Types ---
|
||||
type BatchStatus = 'loading' | 'ready' | 'blocked' | 'already_added' | 'adding' | 'added' | 'error';
|
||||
type BatchStatus = 'loading' | 'ready' | 'blocked' | 'already_added' | 'reenable' | 'adding' | 'added' | 'error';
|
||||
|
||||
interface BatchItem {
|
||||
id: string; // badge id_random from QR
|
||||
@@ -49,14 +50,18 @@
|
||||
}
|
||||
|
||||
// --- Existing leads (duplicate detection) ---
|
||||
// Value includes tracking_id AND enabled status so we can offer re-activation for removed leads.
|
||||
let existing_leads_map = $derived(
|
||||
liveQuery(async () => {
|
||||
const leads = await db_events.exhibit_tracking
|
||||
.where('event_exhibit_id').equals(exhibit_id).toArray();
|
||||
const map = new Map<string, string>();
|
||||
const map = new SvelteMap<string, { tracking_id: string; enabled: boolean }>();
|
||||
leads.forEach(l => {
|
||||
const b_id = l.event_badge_id_random || l.event_badge_id?.toString();
|
||||
if (b_id) map.set(b_id, l.event_exhibit_tracking_id_random || l.event_exhibit_tracking_id?.toString() || '');
|
||||
const b_id = l.event_badge_id?.toString();
|
||||
if (b_id) map.set(b_id, {
|
||||
tracking_id: l.event_exhibit_tracking_id?.toString() || '',
|
||||
enabled: !!l.enable
|
||||
});
|
||||
});
|
||||
return map;
|
||||
})
|
||||
@@ -158,8 +163,10 @@
|
||||
item.badge = badge;
|
||||
|
||||
if ($existing_leads_map?.has(item.id)) {
|
||||
item.status = 'already_added';
|
||||
item.existing_tracking_id = $existing_leads_map.get(item.id) ?? '';
|
||||
const existing = $existing_leads_map.get(item.id)!;
|
||||
item.existing_tracking_id = existing.tracking_id;
|
||||
// Distinguish: active lead vs previously-removed lead
|
||||
item.status = existing.enabled ? 'already_added' : 'reenable';
|
||||
} else if (badge?.allow_tracking !== true) {
|
||||
// Attendee has opted out — show card so staff can inform them
|
||||
item.status = 'blocked';
|
||||
@@ -172,7 +179,7 @@
|
||||
}
|
||||
|
||||
async function add_lead(item: BatchItem) {
|
||||
if (item.status !== 'ready' || !item.badge?.event_badge_id_random) return;
|
||||
if (item.status !== 'ready' || !item.badge?.event_badge_id) return;
|
||||
item.status = 'adding';
|
||||
|
||||
const user_email = $events_loc.leads.auth_exhibit_kv?.[exhibit_id]?.key || 'shared_passcode';
|
||||
@@ -180,7 +187,7 @@
|
||||
const result = await events_func.create_ae_obj__exhibit_tracking({
|
||||
api_cfg: $ae_api,
|
||||
exhibit_id,
|
||||
event_badge_id: item.badge.event_badge_id_random,
|
||||
event_badge_id: item.badge.event_badge_id,
|
||||
external_person_id: user_email,
|
||||
group: user_email
|
||||
});
|
||||
@@ -198,6 +205,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function reenable_lead(item: BatchItem) {
|
||||
if (!item.existing_tracking_id) return;
|
||||
item.status = 'adding';
|
||||
|
||||
try {
|
||||
const result = await events_func.update_ae_obj__exhibit_tracking({
|
||||
api_cfg: $ae_api,
|
||||
exhibit_id,
|
||||
exhibit_tracking_id: item.existing_tracking_id,
|
||||
data: { enable: true }
|
||||
});
|
||||
if (result) {
|
||||
item.status = 'added';
|
||||
if (on_lead_added && item.badge) on_lead_added(item.badge);
|
||||
setTimeout(() => dismiss_item(item), 1000);
|
||||
} else {
|
||||
item.status = 'error';
|
||||
}
|
||||
} catch {
|
||||
item.status = 'error';
|
||||
}
|
||||
}
|
||||
|
||||
async function add_all() {
|
||||
const to_add = batch.filter(i => i.status === 'ready' && !i.dismissing);
|
||||
await Promise.all(to_add.map(add_lead));
|
||||
@@ -359,6 +389,33 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{:else if item.status === 'reenable'}
|
||||
<div class="flex items-start gap-2">
|
||||
<RotateCcw size="1.2em" class="text-warning-500 shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<p class="font-bold text-sm leading-tight">{item.badge?.full_name || 'Attendee'}</p>
|
||||
<p class="text-xs opacity-60 mt-0.5">Previously removed</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="flex-1 rounded-lg py-2 text-xs font-bold flex items-center justify-center gap-1.5 bg-warning-500 text-white hover:brightness-110 transition-all cursor-pointer"
|
||||
onclick={() => reenable_lead(item)}
|
||||
>
|
||||
<RotateCcw size="0.9em" />
|
||||
Re-activate
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="flex-none rounded-lg px-3 py-2 flex items-center justify-center border border-surface-500/40 hover:bg-surface-200-800 transition-colors cursor-pointer opacity-60"
|
||||
title="Skip"
|
||||
onclick={() => dismiss_item(item)}
|
||||
>
|
||||
<X size="1em" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{:else if item.status === 'ready'}
|
||||
<div>
|
||||
<p class="font-bold text-sm leading-tight">{item.badge?.full_name || 'Badge Found'}</p>
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
* Lead Detail View - Basic Read-Only version.
|
||||
*/
|
||||
import { page } from '$app/state';
|
||||
import { goto } from '$app/navigation';
|
||||
import { liveQuery } from 'dexie';
|
||||
import { db_events } from '$lib/ae_events/db_events';
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
|
||||
import { events_func } from '$lib/ae_events/ae_events_functions';
|
||||
import Element_ae_obj_field_editor_v3 from '$lib/elements/element_ae_obj_field_editor_v3.svelte';
|
||||
import Comp_lead_detail_form from './ae_comp__lead_detail_form.svelte';
|
||||
import { Briefcase, CalendarDays, ChevronLeft, Eye, FileText, ListTodo, LoaderCircle, Mail, MapPin, ShieldCheck, SquarePen, Star, Store, User } from '@lucide/svelte';
|
||||
import { Briefcase, CalendarDays, ChevronLeft, Eye, FileText, ListTodo, LoaderCircle, Mail, MapPin, RotateCcw, ShieldCheck, SquarePen, Star, Store, Trash2, User } from '@lucide/svelte';
|
||||
const exhibit_tracking_id = $derived(page.params.exhibit_tracking_id);
|
||||
|
||||
let lq__lead_obj = $derived(
|
||||
@@ -30,6 +32,46 @@
|
||||
|
||||
let is_edit_mode = $state(false);
|
||||
|
||||
// Remove / Restore flow.
|
||||
// Two-click confirm for remove: idle → confirm → removing → (navigate back).
|
||||
let remove_status = $state<'idle' | 'confirm' | 'removing' | 'restoring'>('idle');
|
||||
|
||||
async function remove_lead() {
|
||||
const eid = page.params.exhibit_id ?? '';
|
||||
if (!exhibit_tracking_id || !eid) return;
|
||||
remove_status = 'removing';
|
||||
try {
|
||||
await events_func.update_ae_obj__exhibit_tracking({
|
||||
api_cfg: $ae_api,
|
||||
exhibit_id: eid,
|
||||
exhibit_tracking_id,
|
||||
data: { enable: false }
|
||||
});
|
||||
// Navigate back to exhibit leads list after removal
|
||||
goto(`/events/${page.params.event_id}/leads/exhibit/${eid}`);
|
||||
} catch {
|
||||
// If update fails, reset so user can try again
|
||||
remove_status = 'idle';
|
||||
}
|
||||
}
|
||||
|
||||
async function restore_lead() {
|
||||
const eid = page.params.exhibit_id ?? '';
|
||||
if (!exhibit_tracking_id || !eid) return;
|
||||
remove_status = 'restoring';
|
||||
try {
|
||||
await events_func.update_ae_obj__exhibit_tracking({
|
||||
api_cfg: $ae_api,
|
||||
exhibit_id: eid,
|
||||
exhibit_tracking_id,
|
||||
data: { enable: true }
|
||||
});
|
||||
remove_status = 'idle';
|
||||
} catch {
|
||||
remove_status = 'idle';
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to format date using Aether utility
|
||||
function format_date(date: any) {
|
||||
if (!date) return '';
|
||||
@@ -57,11 +99,11 @@
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
{#if $lq__lead_obj}
|
||||
<button
|
||||
<button
|
||||
class="btn btn-sm"
|
||||
class:preset-filled-primary={is_edit_mode}
|
||||
class:preset-outlined-surface={!is_edit_mode}
|
||||
onclick={() => is_edit_mode = !is_edit_mode}
|
||||
onclick={() => { is_edit_mode = !is_edit_mode; remove_status = 'idle'; }}
|
||||
>
|
||||
{#if is_edit_mode}
|
||||
<Eye size="1.2em" class="mr-1" /> View
|
||||
@@ -69,6 +111,40 @@
|
||||
<SquarePen size="1.2em" class="mr-1" /> Edit
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<!-- Remove Lead — two-click confirm to prevent accidental removal.
|
||||
Removing only sets enable=false (soft-delete); the record can be restored. -->
|
||||
{#if $lq__lead_obj.enable}
|
||||
{#if remove_status === 'confirm'}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm preset-filled-error font-bold"
|
||||
onclick={remove_lead}
|
||||
>
|
||||
<Trash2 size="1em" />
|
||||
Confirm Remove?
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm preset-outlined-surface opacity-60"
|
||||
onclick={() => remove_status = 'idle'}
|
||||
>Cancel</button>
|
||||
{:else}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm preset-outlined-error opacity-70"
|
||||
disabled={remove_status === 'removing'}
|
||||
onclick={() => remove_status = 'confirm'}
|
||||
>
|
||||
{#if remove_status === 'removing'}
|
||||
<LoaderCircle size="1em" class="animate-spin" />
|
||||
{:else}
|
||||
<Trash2 size="1em" />
|
||||
{/if}
|
||||
Remove
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if $lq__lead_obj?.priority}
|
||||
@@ -238,28 +314,33 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status Indicator -->
|
||||
<div class="card p-4 flex items-center gap-3 preset-tonal-surface shadow-sm">
|
||||
{#if is_edit_mode}
|
||||
<div class="flex-1 flex items-center justify-between">
|
||||
<div class="font-bold text-sm">Enabled</div>
|
||||
<Element_ae_obj_field_editor_v3
|
||||
object_type="event_exhibit_tracking"
|
||||
object_id={exhibit_tracking_id ?? ''}
|
||||
field_name="enable"
|
||||
field_type="checkbox"
|
||||
current_value={$lq__lead_obj.enable}
|
||||
object_reload={true}
|
||||
/>
|
||||
<!-- Restore Lead card — only shown when lead has been removed (enable=false/0).
|
||||
Removing sets enable=false rather than deleting so notes/responses are preserved. -->
|
||||
{#if !$lq__lead_obj.enable}
|
||||
<div class="card p-4 space-y-3 preset-tonal-error border border-error-500/50 shadow-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<ShieldCheck size="1.4em" class="text-error-500 shrink-0" />
|
||||
<div>
|
||||
<div class="font-bold text-sm">Lead Removed</div>
|
||||
<div class="text-[10px] opacity-60 uppercase font-black">Not visible in leads list</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<ShieldCheck size="1.5em" class={$lq__lead_obj.enable ? 'text-success-500' : 'text-error-500'} />
|
||||
<div>
|
||||
<div class="font-bold">{$lq__lead_obj.enable ? 'Record Enabled' : 'Record Disabled'}</div>
|
||||
<div class="text-[10px] opacity-50 uppercase font-black">Visibility Status</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm w-full preset-filled-success font-bold"
|
||||
disabled={remove_status === 'restoring'}
|
||||
onclick={restore_lead}
|
||||
>
|
||||
{#if remove_status === 'restoring'}
|
||||
<LoaderCircle size="1em" class="animate-spin" />
|
||||
Restoring...
|
||||
{:else}
|
||||
<RotateCcw size="1em" />
|
||||
Restore Lead
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -22,11 +22,11 @@ const template_id = 'jgfixEpYp1B';
|
||||
const mock_badge = {
|
||||
id: badge_id,
|
||||
event_badge_id: badge_id,
|
||||
event_badge_id_random: badge_id,
|
||||
event_badge_id_random: badge_id, // NO LONGER USE "_random"
|
||||
event_id: event_id,
|
||||
event_id_random: event_id,
|
||||
event_badge_template_id: template_id,
|
||||
event_badge_template_id_random: template_id,
|
||||
event_badge_template_id_random: template_id, // NO LONGER USE "_random"
|
||||
full_name_override: 'Scott Idem',
|
||||
given_name: 'Scott',
|
||||
family_name: 'Idem',
|
||||
@@ -41,7 +41,7 @@ const mock_badge = {
|
||||
|
||||
const mock_template = {
|
||||
id: template_id,
|
||||
id_random: template_id,
|
||||
id_random: template_id, // NO LONGER USE "_random"
|
||||
event_badge_template_id: template_id,
|
||||
badge_template_id: template_id,
|
||||
event_id: event_id,
|
||||
|
||||
@@ -42,11 +42,11 @@ function make_badge(badge_id: string, template_id: string, overrides: Record<str
|
||||
return {
|
||||
id: badge_id,
|
||||
event_badge_id: badge_id,
|
||||
event_badge_id_random: badge_id,
|
||||
event_badge_id_random: badge_id,// NO LONGER USE "_random"
|
||||
event_id: event_id,
|
||||
event_id_random: event_id,
|
||||
event_id_random: event_id,// NO LONGER USE "_random"
|
||||
event_badge_template_id: template_id,
|
||||
event_badge_template_id_random: template_id,
|
||||
event_badge_template_id_random: template_id,// NO LONGER USE "_random"
|
||||
full_name: 'Jane Doe',
|
||||
full_name_override: null,
|
||||
given_name: 'Jane',
|
||||
|
||||
Reference in New Issue
Block a user