refactor(badges): standardize helpers and apply batch formatting

- Standardized 'prevent_default' helper names across badges module.
- Corrected native 'event.preventDefault()' calls in view and template components.
- Applied batch formatting (printWidth: 80) to all badges files.
This commit is contained in:
Scott Idem
2026-02-06 14:55:43 -05:00
parent 67752ccdfe
commit 5385eacc0f
11 changed files with 648 additions and 290 deletions

View File

@@ -36,9 +36,13 @@
let lq__event_obj = $derived(
liveQuery(async () => {
if (log_lvl) {
console.log(`*** LiveQuery: lq__event_obj *** event_id=${$events_slct.event_id}`);
console.log(
`*** LiveQuery: lq__event_obj *** event_id=${$events_slct.event_id}`
);
}
let results = await db_events.event.get($events_slct?.event_id ?? '');
let results = await db_events.event.get(
$events_slct?.event_id ?? ''
);
return results;
})

View File

@@ -15,10 +15,7 @@
// *** Import Aether specific variables and functions
import { ae_util } from '$lib/ae_utils/ae_utils';
import {
ae_loc,
ae_api
} from '$lib/stores/ae_stores';
import { ae_loc, ae_api } from '$lib/stores/ae_stores';
import { db_events } from '$lib/ae_events/db_events';
import {
@@ -39,13 +36,20 @@
// *** Initialization & Store Guard ***
// Ensure all search fields are initialized to prevent circular undefined triggers
if ($events_loc.badges) {
if (typeof $events_loc.badges.search_version === 'undefined') $events_loc.badges.search_version = 0;
if (typeof $events_loc.badges.qry__remote_first === 'undefined') $events_loc.badges.qry__remote_first = false;
if (typeof $events_loc.badges.fulltext_search_qry_str === 'undefined') $events_loc.badges.fulltext_search_qry_str = '';
if (typeof $events_loc.badges.search_badge_type_code === 'undefined') $events_loc.badges.search_badge_type_code = '';
if (typeof $events_loc.badges.qry_printed_status === 'undefined') $events_loc.badges.qry_printed_status = 'all';
if (typeof $events_loc.badges.qry_affiliations === 'undefined') $events_loc.badges.qry_affiliations = '';
if (typeof $events_loc.badges.qry_sort_order === 'undefined') $events_loc.badges.qry_sort_order = '';
if (typeof $events_loc.badges.search_version === 'undefined')
$events_loc.badges.search_version = 0;
if (typeof $events_loc.badges.qry__remote_first === 'undefined')
$events_loc.badges.qry__remote_first = false;
if (typeof $events_loc.badges.fulltext_search_qry_str === 'undefined')
$events_loc.badges.fulltext_search_qry_str = '';
if (typeof $events_loc.badges.search_badge_type_code === 'undefined')
$events_loc.badges.search_badge_type_code = '';
if (typeof $events_loc.badges.qry_printed_status === 'undefined')
$events_loc.badges.qry_printed_status = 'all';
if (typeof $events_loc.badges.qry_affiliations === 'undefined')
$events_loc.badges.qry_affiliations = '';
if (typeof $events_loc.badges.qry_sort_order === 'undefined')
$events_loc.badges.qry_sort_order = '';
}
// Variables
@@ -61,18 +65,28 @@
let lq__event_badge_obj_li = $derived.by(() => {
const ids = event_badge_id_li;
const event_id = $events_slct?.event_id;
return liveQuery(async () => {
// SCENARIO 1: Specific IDs provided (Search Results)
if (Array.isArray(ids) && ids.length > 0) {
if (log_lvl) console.log(`Badge Page LQ: bulkGet ${ids.length} IDs`);
if (log_lvl)
console.log(`Badge Page LQ: bulkGet ${ids.length} IDs`);
const results = await db_events.badge.bulkGet(ids);
return results.filter(item => item !== undefined);
return results.filter((item) => item !== undefined);
}
// SCENARIO 2: Fallback broad search (Only if no active filters)
if (event_id && !$events_loc.badges.fulltext_search_qry_str && $events_loc.badges.qry_printed_status === 'all' && !$events_loc.badges.qry_affiliations && !$events_loc.badges.search_badge_type_code) {
if (log_lvl) console.log(`Badge Page LQ: Fallback search for event: ${event_id}`);
if (
event_id &&
!$events_loc.badges.fulltext_search_qry_str &&
$events_loc.badges.qry_printed_status === 'all' &&
!$events_loc.badges.qry_affiliations &&
!$events_loc.badges.search_badge_type_code
) {
if (log_lvl)
console.log(
`Badge Page LQ: Fallback search for event: ${event_id}`
);
return await db_events.badge
.where('event_id_random')
.equals(event_id)
@@ -88,7 +102,9 @@
// 1. Isolate dependencies into a stable derived object
let search_params = $derived({
v: $events_loc.badges.search_version,
str: ($events_loc.badges.fulltext_search_qry_str ?? '').toLowerCase().trim(),
str: ($events_loc.badges.fulltext_search_qry_str ?? '')
.toLowerCase()
.trim(),
type: $events_loc.badges.search_badge_type_code,
printed: $events_loc.badges.qry_printed_status,
aff: ($events_loc.badges.qry_affiliations ?? '').toLowerCase().trim(),
@@ -122,9 +138,12 @@
const current_search_id = ++last_search_id;
const event_id = params.event_id;
const remote_first = params.remote_first;
if (log_lvl) console.log(`[Badge Search #${current_search_id}] Refreshing (remote=${remote_first}, event=${event_id}, str=${params.str})...`);
if (log_lvl)
console.log(
`[Badge Search #${current_search_id}] Refreshing (remote=${remote_first}, event=${event_id}, str=${params.str})...`
);
untrack(() => {
$events_sess.badges.search_status = 'loading';
$events_sess.badges.search_complete = false;
@@ -142,36 +161,56 @@
let local_results = await db_events.badge
.where('event_id_random')
.equals(event_id)
.filter(badge => {
if (type_code && badge.badge_type_code !== type_code) return false;
.filter((badge) => {
if (
type_code &&
badge.badge_type_code !== type_code
)
return false;
if (printed_status !== 'all') {
const is_printed = (badge.print_count ?? 0) > 0;
if (printed_status === 'printed' && !is_printed) return false;
if (printed_status === 'not_printed' && is_printed) return false;
if (printed_status === 'printed' && !is_printed)
return false;
if (
printed_status === 'not_printed' &&
is_printed
)
return false;
}
if (qry_str) {
const given_name = (badge.given_name ?? '').toLowerCase();
const family_name = (badge.family_name ?? '').toLowerCase();
const full_name = `${given_name} ${family_name}`.toLowerCase();
const given_name = (
badge.given_name ?? ''
).toLowerCase();
const family_name = (
badge.family_name ?? ''
).toLowerCase();
const full_name =
`${given_name} ${family_name}`.toLowerCase();
const email = (badge.email ?? '').toLowerCase();
const qry_string = (badge.default_qry_str ?? '').toLowerCase();
const match = full_name.includes(qry_str) ||
given_name.includes(qry_str) ||
family_name.includes(qry_str) ||
email.includes(qry_str) ||
qry_string.includes(qry_str);
const qry_string = (
badge.default_qry_str ?? ''
).toLowerCase();
const match =
full_name.includes(qry_str) ||
given_name.includes(qry_str) ||
family_name.includes(qry_str) ||
email.includes(qry_str) ||
qry_string.includes(qry_str);
if (!match) return false;
}
if (aff_str) {
const affiliations = (badge.affiliations ?? '').toLowerCase();
if (!affiliations.includes(aff_str)) return false;
const affiliations = (
badge.affiliations ?? ''
).toLowerCase();
if (!affiliations.includes(aff_str))
return false;
}
return true;
})
.toArray();
@@ -180,27 +219,57 @@
local_results.sort((a, b) => {
switch (params.sort) {
case 'name_asc':
return (a.given_name ?? '').localeCompare(b.given_name ?? '') || (a.family_name ?? '').localeCompare(b.family_name ?? '');
return (
(a.given_name ?? '').localeCompare(
b.given_name ?? ''
) ||
(a.family_name ?? '').localeCompare(
b.family_name ?? ''
)
);
case 'name_desc':
return (b.given_name ?? '').localeCompare(a.given_name ?? '') || (b.family_name ?? '').localeCompare(a.family_name ?? '');
return (
(b.given_name ?? '').localeCompare(
a.given_name ?? ''
) ||
(b.family_name ?? '').localeCompare(
a.family_name ?? ''
)
);
case 'updated_desc':
return new Date(b.updated_on || 0).getTime() - new Date(a.updated_on || 0).getTime();
return (
new Date(b.updated_on || 0).getTime() -
new Date(a.updated_on || 0).getTime()
);
case 'updated_asc':
return new Date(a.updated_on || 0).getTime() - new Date(b.updated_on || 0).getTime();
return (
new Date(a.updated_on || 0).getTime() -
new Date(b.updated_on || 0).getTime()
);
case 'print_count_desc':
return (b.print_count ?? 0) - (a.print_count ?? 0);
return (
(b.print_count ?? 0) - (a.print_count ?? 0)
);
default:
return (a.given_name ?? '').localeCompare(b.given_name ?? '');
return (a.given_name ?? '').localeCompare(
b.given_name ?? ''
);
}
});
const local_ids = local_results.map(b => b.id || b.event_badge_id_random).filter(Boolean);
const local_ids = local_results
.map((b) => b.id || b.event_badge_id_random)
.filter(Boolean);
if (current_search_id === last_search_id) {
if (log_lvl) console.log(`[Badge Search #${current_search_id}] Fast Path found ${local_ids.length} items locally.`);
if (log_lvl)
console.log(
`[Badge Search #${current_search_id}] Fast Path found ${local_ids.length} items locally.`
);
untrack(() => {
event_badge_id_li = local_ids;
if (local_ids.length > 0) $events_sess.badges.search_status = 'done';
if (local_ids.length > 0)
$events_sess.badges.search_status = 'done';
});
}
}
@@ -218,12 +287,23 @@
// Map sort param to API order_by_li
let order_by_li: any = {};
switch (params.sort) {
case 'name_asc': order_by_li = { given_name: 'ASC', family_name: 'ASC' }; break;
case 'name_desc': order_by_li = { given_name: 'DESC', family_name: 'DESC' }; break;
case 'updated_desc': order_by_li = { updated_on: 'DESC' }; break;
case 'updated_asc': order_by_li = { updated_on: 'ASC' }; break;
case 'print_count_desc': order_by_li = { print_count: 'DESC' }; break;
default: order_by_li = { given_name: 'ASC' };
case 'name_asc':
order_by_li = { given_name: 'ASC', family_name: 'ASC' };
break;
case 'name_desc':
order_by_li = { given_name: 'DESC', family_name: 'DESC' };
break;
case 'updated_desc':
order_by_li = { updated_on: 'DESC' };
break;
case 'updated_asc':
order_by_li = { updated_on: 'ASC' };
break;
case 'print_count_desc':
order_by_li = { print_count: 'DESC' };
break;
default:
order_by_li = { given_name: 'ASC' };
}
const results = await events_func.search__event_badge({
@@ -240,15 +320,20 @@
if (current_search_id === last_search_id) {
const api_results = results || [];
const api_ids = api_results.map((b: any) => b.id || b.event_badge_id_random).filter(Boolean);
const api_ids = api_results
.map((b: any) => b.id || b.event_badge_id_random)
.filter(Boolean);
untrack(() => {
$events_sess.badge_li = api_results;
event_badge_id_li = api_ids;
$events_sess.badges.search_status = 'done';
$events_sess.badges.search_complete = true;
});
if (log_lvl) console.log(`[Badge Search #${current_search_id}] Revalidation Complete. Found ${api_ids.length} items.`);
if (log_lvl)
console.log(
`[Badge Search #${current_search_id}] Revalidation Complete. Found ${api_ids.length} items.`
);
}
} catch (error) {
if (current_search_id === last_search_id) {
@@ -265,24 +350,24 @@
<svelte:head>
<title>
Badges -
{ae_util.shorten_string({ string: $events_slct?.event_obj?.name ?? '-- not set --', max_length: 12 })}
{ae_util.shorten_string({
string: $events_slct?.event_obj?.name ?? '-- not set --',
max_length: 12
})}
- OSIT's &AElig; Events
</title>
</svelte:head>
<Comp_badge_search
event_id={$events_slct?.event_id ?? ''}
log_lvl={1}
<Comp_badge_search event_id={$events_slct?.event_id ?? ''} log_lvl={1}
></Comp_badge_search>
{#if $events_sess?.badges?.search_status === 'loading' && event_badge_id_li.length === 0}
<div class="flex flex-col items-center justify-center p-10 opacity-50 text-center">
<div
class="flex flex-col items-center justify-center p-10 opacity-50 text-center"
>
<LoaderCircle size="3em" class="animate-spin mb-4 mx-auto" />
<p class="text-xl">Loading badges...</p>
</div>
{:else}
<Comp_badge_obj_li
lq__event_badge_obj_li={lq__event_badge_obj_li}
log_lvl={1}
></Comp_badge_obj_li>
{/if}
<Comp_badge_obj_li {lq__event_badge_obj_li} log_lvl={1}></Comp_badge_obj_li>
{/if}

View File

@@ -48,7 +48,10 @@
}
let results = await db_events.badge.get(event_badge_id);
if (log_lvl) {
console.log(`*** LiveQuery: lq__event_badge_obj *** results=`, results);
console.log(
`*** LiveQuery: lq__event_badge_obj *** results=`,
results
);
}
return results;
})
@@ -56,7 +59,9 @@
let lq__event_badge_template_obj = $derived(
liveQuery(async () => {
let results = await db_events.badge_template.get($lq__event_badge_obj?.event_badge_template_id ?? ''); // null or undefined does not reset things like '' does
let results = await db_events.badge_template.get(
$lq__event_badge_obj?.event_badge_template_id ?? ''
); // null or undefined does not reset things like '' does
if (log_lvl) {
console.log(
@@ -86,7 +91,9 @@
let lq__event_obj: any = $state(undefined);
onMount(() => {
const observable = liveQuery(() => db_events.event.get($events_slct?.event_id ?? ''));
const observable = liveQuery(() =>
db_events.event.get($events_slct?.event_id ?? '')
);
const subscription = observable.subscribe((value) => {
lq__event_obj = value;
});
@@ -109,7 +116,9 @@
<title>
&AElig;: Badge -
{$lq__event_badge_obj?.given_name ?? '-- not set --'}
{$lq__event_badge_obj?.family_name ? $lq__event_badge_obj?.family_name.charAt(0) + '.' : ''}
{$lq__event_badge_obj?.family_name
? $lq__event_badge_obj?.family_name.charAt(0) + '.'
: ''}
- Badges v3 -
{$events_loc?.title}
</title>
@@ -149,13 +158,13 @@
</header>
{#if $lq__event_badge_obj}
<Comp_badge_obj_view
event_id={$lq__event_badge_obj.event_id}
{event_badge_id}
lq__event_badge_obj={lq__event_badge_obj}
{is_review_mode}
lq__event_badge_template_obj={lq__event_badge_template_obj}
/>
<Comp_badge_obj_view
event_id={$lq__event_badge_obj.event_id}
{event_badge_id}
{lq__event_badge_obj}
{is_review_mode}
{lq__event_badge_template_obj}
/>
{/if}
{:else}
<p>No IDB record found for ID: {event_badge_id}</p>

View File

@@ -100,20 +100,27 @@
$effect(() => {
if ($lq__event_badge_obj) {
if (log_lvl) {
console.log('Initializing editable fields from lq__event_badge_obj');
console.log(
'Initializing editable fields from lq__event_badge_obj'
);
}
editable_full_name_override =
$lq__event_badge_obj.full_name_override ?? $lq__event_badge_obj.full_name;
$lq__event_badge_obj.full_name_override ??
$lq__event_badge_obj.full_name;
editable_professional_title_override =
$lq__event_badge_obj.professional_title_override ??
$lq__event_badge_obj.professional_title;
editable_affiliations_override =
$lq__event_badge_obj.affiliations_override ?? $lq__event_badge_obj.affiliations;
$lq__event_badge_obj.affiliations_override ??
$lq__event_badge_obj.affiliations;
editable_location_override =
$lq__event_badge_obj.location_override ?? $lq__event_badge_obj.location;
editable_allow_tracking = $lq__event_badge_obj.allow_tracking ?? null;
$lq__event_badge_obj.location_override ??
$lq__event_badge_obj.location;
editable_allow_tracking =
$lq__event_badge_obj.allow_tracking ?? null;
editable_email = $lq__event_badge_obj.email ?? null;
editable_badge_type_code = $lq__event_badge_obj.badge_type_code ?? null;
editable_badge_type_code =
$lq__event_badge_obj.badge_type_code ?? null;
if (is_review_mode) {
edit_mode_active = true;
@@ -137,7 +144,6 @@
let option_other_1_override = $state('');
let option_other_2_override = $state('');
let slct_badge_type = '';
/* *** BEGIN *** This should be moved out */
@@ -154,8 +160,10 @@
code_to_html.option_1['1'] = '<span class="fas fa-biohazard"></span>';
code_to_html.option_1['true'] = '<span class="fas fa-biohazard"></span>';
code_to_html.option_1['True'] = '<span class="fas fa-biohazard"></span>';
code_to_html.option_1['Dairy Free'] = '<span class="fas fa-utensils"></span>';
code_to_html.option_1['Gluten Free'] = '<span class="fas fa-utensils"></span>';
code_to_html.option_1['Dairy Free'] =
'<span class="fas fa-utensils"></span>';
code_to_html.option_1['Gluten Free'] =
'<span class="fas fa-utensils"></span>';
code_to_html.option_1['Halal'] = '<span class="fas fa-utensils"></span>';
code_to_html.option_1['Kosher'] = '<span class="fas fa-utensils"></span>';
code_to_html.option_1['Meat'] = '<span class="fas fa-bone"></span>';
@@ -167,7 +175,8 @@
code_to_html.option_2['true'] = '<span class="fas fa-star-of-life"></span>';
code_to_html.option_2['True'] = '<span class="fas fa-star-of-life"></span>';
code_to_html.option_2['First Time '] = '<span class="fas fa-hand-paper"></span>';
code_to_html.option_2['First Time '] =
'<span class="fas fa-hand-paper"></span>';
/* *** END *** This should be moved out */
let full_name_class_size: string = $state('text-[.60in]');
@@ -177,7 +186,6 @@
// WARNING: This does not currently take into account the total lengths of the strings, only the longest part when split by spaces. This help with wrapping in the tighter spaces of the badge.
$effect(() => {
// Re-calculate font sizes based on potentially edited values
// Only run if we have the badge object
@@ -190,11 +198,14 @@
$lq__event_badge_obj.professional_title ??
'';
const current_affiliations =
editable_affiliations_override ?? $lq__event_badge_obj.affiliations ?? '';
editable_affiliations_override ??
$lq__event_badge_obj.affiliations ??
'';
const current_location =
editable_location_override ?? $lq__event_badge_obj.location ?? '';
let longest_full_name_override_part = longest_str_part(current_full_name);
let longest_full_name_override_part =
longest_str_part(current_full_name);
if (longest_full_name_override_part >= 9) {
full_name_class_size = 'text-[.45in]';
} else if (longest_full_name_override_part >= 7) {
@@ -203,7 +214,9 @@
full_name_class_size = 'text-[.75in]';
}
let longest_professional_title_override_part = longest_str_part(current_professional_title);
let longest_professional_title_override_part = longest_str_part(
current_professional_title
);
if (longest_professional_title_override_part >= 13) {
professional_title_class_size = 'text-[.35in]';
} else if (longest_professional_title_override_part >= 10) {
@@ -214,7 +227,8 @@
professional_title_class_size = 'text-[.35in]';
}
let longest_affiliations_override_part = longest_str_part(current_affiliations);
let longest_affiliations_override_part =
longest_str_part(current_affiliations);
if (longest_affiliations_override_part >= 55) {
affiliations_class_size = 'text-[.30in]';
} else if (longest_affiliations_override_part >= 45) {
@@ -260,7 +274,7 @@
// *** Functions and Logic
function prevent_default<T extends Event>(fn: (event: T) => void) {
return function (event: T) {
event.prevent_default();
event.preventDefault();
fn(event);
};
}
@@ -334,7 +348,10 @@
qr_data_url = '';
try {
// Use 'vcard' as the qr_type, passing all required params
const dataUrl = await core_func.js_generate_qr_code('vcard', qrParams);
const dataUrl = await core_func.js_generate_qr_code(
'vcard',
qrParams
);
qr_data_url = dataUrl;
} catch (error) {
qr_error_message = error.message;
@@ -356,7 +373,8 @@
// Only include fields that have actually changed
if (
editable_full_name_override !==
($lq__event_badge_obj.full_name_override ?? $lq__event_badge_obj.full_name)
($lq__event_badge_obj.full_name_override ??
$lq__event_badge_obj.full_name)
) {
data_to_update.full_name_override = editable_full_name_override;
}
@@ -365,17 +383,21 @@
($lq__event_badge_obj.professional_title_override ??
$lq__event_badge_obj.professional_title)
) {
data_to_update.professional_title_override = editable_professional_title_override;
data_to_update.professional_title_override =
editable_professional_title_override;
}
if (
editable_affiliations_override !==
($lq__event_badge_obj.affiliations_override ?? $lq__event_badge_obj.affiliations)
($lq__event_badge_obj.affiliations_override ??
$lq__event_badge_obj.affiliations)
) {
data_to_update.affiliations_override = editable_affiliations_override;
data_to_update.affiliations_override =
editable_affiliations_override;
}
if (
editable_location_override !==
($lq__event_badge_obj.location_override ?? $lq__event_badge_obj.location)
($lq__event_badge_obj.location_override ??
$lq__event_badge_obj.location)
) {
data_to_update.location_override = editable_location_override;
}
@@ -425,17 +447,22 @@
function handle_cancel_changes() {
if ($lq__event_badge_obj) {
editable_full_name_override =
$lq__event_badge_obj.full_name_override ?? $lq__event_badge_obj.full_name;
$lq__event_badge_obj.full_name_override ??
$lq__event_badge_obj.full_name;
editable_professional_title_override =
$lq__event_badge_obj.professional_title_override ??
$lq__event_badge_obj.professional_title;
editable_affiliations_override =
$lq__event_badge_obj.affiliations_override ?? $lq__event_badge_obj.affiliations;
$lq__event_badge_obj.affiliations_override ??
$lq__event_badge_obj.affiliations;
editable_location_override =
$lq__event_badge_obj.location_override ?? $lq__event_badge_obj.location;
editable_allow_tracking = $lq__event_badge_obj.allow_tracking ?? null;
$lq__event_badge_obj.location_override ??
$lq__event_badge_obj.location;
editable_allow_tracking =
$lq__event_badge_obj.allow_tracking ?? null;
editable_email = $lq__event_badge_obj.email ?? null;
editable_badge_type_code = $lq__event_badge_obj.badge_type_code ?? null;
editable_badge_type_code =
$lq__event_badge_obj.badge_type_code ?? null;
}
if (!is_review_mode) {
edit_mode_active = false;
@@ -479,8 +506,7 @@ onkeypress={() => {
max-w-[8.5in] overflow-visible
"
>
<!-- <pre>
<!-- <pre>
{$lq__event_badge_obj?.event_id}
{$lq__event_badge_obj?.event_badge_id}
{$lq__event_badge_obj?.event_badge_template_id}
@@ -528,7 +554,8 @@ onkeypress={() => {
class:preset-tonal-warning={edit_mode_active}
>
{#if edit_mode_active}
<button type="button"
<button
type="button"
class="
btn btn-sm text-xs
preset-tonal-success preset-outlined-success-100-900 hover:preset-filled-success-500
@@ -548,7 +575,8 @@ onkeypress={() => {
Save Changes
</span>
</button>
<button type="button"
<button
type="button"
class="
btn btn-sm text-xs
preset-tonal-tertiary preset-outlined-tertiary-100-900 hover:preset-filled-tertiary-500
@@ -569,7 +597,8 @@ onkeypress={() => {
</span>
</button>
{:else}
<button type="button"
<button
type="button"
class="
btn btn-sm text-xs
preset-tonal-warning preset-outlined-warning-100-900 hover:preset-filled-secondary-500
@@ -594,10 +623,14 @@ onkeypress={() => {
</button>
{/if}
<div class="w-md max-w-lg m-1 p-1" class:hidden={!edit_mode_active}>
<div
class="w-md max-w-lg m-1 p-1"
class:hidden={!edit_mode_active}
>
<p class="text-xs italic text-gray-500">
Show list of fields that they can edit here. This may need to broken down in
to sections that can be collapsed.
Show list of fields that they can edit here. This may
need to broken down in to sections that can be
collapsed.
</p>
<ul class="text-left list-disc list-inside text-sm">
<li>Full Name</li>
@@ -672,7 +705,9 @@ onkeypress={() => {
<!-- NOTE: Need to add some logic if any part of the name is 9 characters or more to reduce the font size OR if the total length is more than 15ish to reduce the font size :NOTE -->
<!-- Examples: mSC-tTzL_OA, QLddtYl8sfo -->
<div class="full_name_override_all {full_name_class_size} leading-none">
<div
class="full_name_override_all {full_name_class_size} leading-none"
>
<!-- <span class="float-right text-sm italic m-2">
{longest_full_name_override_part}&times; char
</span> -->
@@ -703,7 +738,9 @@ onkeypress={() => {
{#if edit_mode_active}
<input
type="text"
bind:value={editable_professional_title_override}
bind:value={
editable_professional_title_override
}
class="input w-full text-center"
/>
{:else}
@@ -728,7 +765,9 @@ onkeypress={() => {
>
{#if edit_mode_active}
<textarea
bind:value={editable_affiliations_override}
bind:value={
editable_affiliations_override
}
class="textarea w-full text-center"
rows="2"
></textarea>
@@ -782,12 +821,16 @@ onkeypress={() => {
<label
>Allow Tracking: <input
type="checkbox"
bind:checked={editable_allow_tracking}
bind:checked={
editable_allow_tracking
}
class="checkbox"
/></label
>
{:else}
Allow Tracking: {editable_allow_tracking ? 'Yes' : 'No'}
Allow Tracking: {editable_allow_tracking
? 'Yes'
: 'No'}
{/if}
</div>
{/if}
@@ -803,10 +846,12 @@ onkeypress={() => {
</span>
<span class="badge_body_special_right">
{#if option_ticket_2_override}
<span class=" ticket_2_code fg_red fas fa-star"></span>
<span class=" ticket_2_code fg_red fas fa-star"
></span>
{/if}
{#if option_ticket_3_override}
<span class="ticket_3_code fg_blue fas fa-star"></span>
<span class="ticket_3_code fg_blue fas fa-star"
></span>
{/if}
</span>
{#if lq__event_badge_template_obj.show_qr_front}
@@ -866,7 +911,8 @@ onkeypress={() => {
>
{/if}
<span class="badge_footer_center {editable_badge_type_code?.toLowerCase()}"
<span
class="badge_footer_center {editable_badge_type_code?.toLowerCase()}"
>{editable_badge_type_code}</span
>
@@ -1015,17 +1061,27 @@ onkeypress={() => {
"
>
{#if $lq__event_badge_template_obj.wireless_ssid}
<div class="grow flex flex-col gap-0 items-center justify-end">
<span class="w-full flex flex-row gap-1 items-center justify-start">
<span class="w-20 text-gray-500 italic"> Signal Name </span>
<div
class="grow flex flex-col gap-0 items-center justify-end"
>
<span
class="w-full flex flex-row gap-1 items-center justify-start"
>
<span class="w-20 text-gray-500 italic">
Signal Name
</span>
<strong
class="wifi_ssid font-bold font-mono text-lg tracking-widest leading-none"
>
{$lq__event_badge_template_obj.wireless_ssid}
</strong>
</span>
<span class="w-full flex flex-row gap-1 items-center justify-start">
<span class="w-20 text-gray-500 italic"> Access Code </span>
<span
class="w-full flex flex-row gap-1 items-center justify-start"
>
<span class="w-20 text-gray-500 italic">
Access Code
</span>
<strong
class="wifi_code font-bold font-mono text-lg tracking-widest leading-none"
>
@@ -1042,8 +1098,10 @@ onkeypress={() => {
{/if}
<div class="network_username_password hidden">
Username = <span class="network_username">username</span><br />
Password = <span class="network_password">password</span>
Username = <span class="network_username">username</span
><br />
Password =
<span class="network_password">password</span>
</div>
</div>
@@ -1052,7 +1110,9 @@ onkeypress={() => {
<!-- <img style="width: .75in; float: right;" src="/event/qr_image/testing123" alt="missing person information QR code"> -->
<ol style="margin: 0; padding-top: 0; padding-bottom: 0;">
<li style="">
Use QR code or search your app store for "<strong>App Name</strong>"
Use QR code or search your app store for "<strong
>App Name</strong
>"
</li>
<li style="">
Once downloaded, use the search feature to find "<strong
@@ -1060,7 +1120,9 @@ onkeypress={() => {
>" guide
</li>
<li style="">
You may also go to <a href="https://oneskyit.com/">OneSkyIT.com</a>
You may also go to <a href="https://oneskyit.com/"
>OneSkyIT.com</a
>
</li>
</ol>
</div>
@@ -1072,19 +1134,29 @@ onkeypress={() => {
<!-- <strong>Attendee Info:</strong> -->
<ul>
{#if $lq__event_badge_obj.ticket_1_code}
<li>{@html $lq__event_badge_template_obj.ticket_1_text}</li>
<li>
{@html $lq__event_badge_template_obj.ticket_1_text}
</li>
{/if}
{#if $lq__event_badge_obj.ticket_2_code}
<li>{@html $lq__event_badge_template_obj.ticket_2_text}</li>
<li>
{@html $lq__event_badge_template_obj.ticket_2_text}
</li>
{/if}
{#if $lq__event_badge_obj.ticket_3_code}
<li>{@html $lq__event_badge_template_obj.ticket_3_text}</li>
<li>
{@html $lq__event_badge_template_obj.ticket_3_text}
</li>
{/if}
{#if $lq__event_badge_obj.ticket_4_code}
<li>{@html $lq__event_badge_template_obj.ticket_4_text}</li>
<li>
{@html $lq__event_badge_template_obj.ticket_4_text}
</li>
{/if}
{#if $lq__event_badge_obj.ticket_5_code}
<li>{@html $lq__event_badge_template_obj.ticket_5_text}</li>
<li>
{@html $lq__event_badge_template_obj.ticket_5_text}
</li>
{/if}
</ul>
@@ -1192,7 +1264,9 @@ onkeypress={() => {
alt="badge QR code"
ondblclick={() => {
// (hide_qr) ? hide_qr = !hide_qr : hide_qr;
hide_qr ? (hide_qr = false) : (hide_qr = true);
hide_qr
? (hide_qr = false)
: (hide_qr = true);
}}
/>
<div
@@ -1203,22 +1277,28 @@ onkeypress={() => {
>
{#if $lq__event_badge_obj.allow_tracking}
<p>
This was <strong>allowed</strong> at the time your badge
was printed. You may opt-out at anytime.
This was <strong>allowed</strong
> at the time your badge was printed.
You may opt-out at anytime.
</p>
<p>
By allowing this QR code to be scanned by an
exhibitor or staff, you understand and agree that
they may use your personal information.
By allowing this QR code to be
scanned by an exhibitor or
staff, you understand and agree
that they may use your personal
information.
</p>
{:else}
<p>
Tracking was <strong>not</strong> allowed at the time
your badge was printed. You may opt-in at anytime.
Tracking was <strong>not</strong
> allowed at the time your badge was
printed. You may opt-in at anytime.
</p>
<p>
If this QR code is scanned by an exhibitor or staff,
they will <strong>not</strong> have access to your information.
If this QR code is scanned by an
exhibitor or staff, they will <strong
>not</strong
> have access to your information.
</p>
{/if}
</div>
@@ -1252,8 +1332,12 @@ onkeypress={() => {
alt="check badge logo"
/>
<div class="banner_text">
<div class="row_one">{$lq__event_badge_template_obj.header_row_1}</div>
<div class="row_two">{$lq__event_badge_template_obj.header_row_2}</div>
<div class="row_one">
{$lq__event_badge_template_obj.header_row_1}
</div>
<div class="row_two">
{$lq__event_badge_template_obj.header_row_2}
</div>
</div>
</div>
@@ -1261,17 +1345,21 @@ onkeypress={() => {
<!-- receipt_content class div start -->
<div>
<span style="display: none;"
>Invoice Number: <span class="Invoice_Number">Invoice_Number</span><br
/></span
>Invoice Number: <span class="Invoice_Number"
>Invoice_Number</span
><br /></span
>
Account Number: <span class="BT_ID">BT_ID</span><br />
Order Number: <span class="Order_Number">Order_Number</span><br />
Order Number:
<span class="Order_Number">Order_Number</span><br />
</div>
<hr />
<div>
Name: <span class="Orders_Full_Name">Full Name</span> (ID:
<span class="Member_ID">Member_ID</span>)<br />
<address><span class="Orders_Full_Address">Full Address</span></address>
<address>
<span class="Orders_Full_Address">Full Address</span>
</address>
Email:<span class="Orders_Email">No Email</span>
</div>
<hr />
@@ -1288,34 +1376,49 @@ onkeypress={() => {
</thead>
<tbody>
<tr class="roweven"
><td>1</td><td>Registration for Meeting</td><td>1</td><td>$300.00</td
><td>$300.00</td></tr
><td>1</td><td>Registration for Meeting</td><td
>1</td
><td>$300.00</td><td>$300.00</td></tr
>
<tr class="rowodd"
><td>2</td><td>Printed Program</td><td>1</td><td>$25.00</td><td
><td>2</td><td>Printed Program</td><td>1</td><td
>$25.00</td
></tr
><td>$25.00</td></tr
>
<tr class="roweven"
><td>3</td><td>Opening Reception</td><td>1</td><td>$0.00</td><td
><td>3</td><td>Opening Reception</td><td>1</td><td
>$0.00</td
></tr
><td>$0.00</td></tr
>
<tr class="rowodd"
><td>4</td><td>Closing Banquet</td><td>1</td><td>$85.00</td><td
><td>4</td><td>Closing Banquet</td><td>1</td><td
>$85.00</td
><td>$85.00</td></tr
>
<tr
><th colspan="4">Total Charges:</th><th colspan="2"
>$410.00</th
></tr
>
<tr
><th colspan="4">Total Payments:</th><th colspan="2"
>$410.00</th
></tr
>
<tr
><th colspan="4">Balance:</th><th colspan="2"
>$0.00</th
></tr
>
<tr><th colspan="4">Total Charges:</th><th colspan="2">$410.00</th></tr>
<tr><th colspan="4">Total Payments:</th><th colspan="2">$410.00</th></tr>
<tr><th colspan="4">Balance:</th><th colspan="2">$0.00</th></tr>
</tbody>
</table>
</div>
<!-- receipt_content class div end -->
<div class="receipt_footer">
<p class="printed">Receipt Printed: January 23, 2019 03:18 PM</p>
<p class="printed">
Receipt Printed: January 23, 2019 03:18 PM
</p>
</div>
</section>
<!-- receipt class div end -->
@@ -1392,22 +1495,21 @@ onkeypress={() => {
<!-- End if for $lq__event_badge_template_obj -->
</section>
<div>
<h1 class="text-lg font-bold mt-4">Debug Information</h1>
<pre
class="whitespace-pre-wrap break-words text-xs max-h-32 overflow-auto p-2 bg-surface-200 border border-surface-300 rounded
<h1 class="text-lg font-bold mt-4">Debug Information</h1>
<pre
class="whitespace-pre-wrap break-words text-xs max-h-32 overflow-auto p-2 bg-surface-200 border border-surface-300 rounded
mt-4
print:hidden
">
{JSON.stringify($lq__event_badge_obj, null, 2)}
</pre>
<pre
class="whitespace-pre-wrap break-words text-xs max-h-32 overflow-auto p-2 bg-surface-200 border border-surface-300 rounded
<pre
class="whitespace-pre-wrap break-words text-xs max-h-32 overflow-auto p-2 bg-surface-200 border border-surface-300 rounded
mt-4
print:hidden
">
{JSON.stringify($lq__event_badge_template_obj, null, 2)}
</pre>
</div>
</div>

View File

@@ -40,7 +40,7 @@
];
async function handle_submit(event: Event) {
event.preventDefault();
event.prevent_default();
submit_status = 'loading';
const data_to_create: key_val = {
full_name_override,
@@ -84,11 +84,16 @@
</label>
<label class="label">
<span>Professional Title Override</span>
<input type="text" bind:value={professional_title_override} class="input" />
<input
type="text"
bind:value={professional_title_override}
class="input"
/>
</label>
<label class="label">
<span>Affiliations Override</span>
<textarea bind:value={affiliations_override} class="textarea" rows="2"></textarea>
<textarea bind:value={affiliations_override} class="textarea" rows="2"
></textarea>
</label>
<label class="label">
<span>Location Override</span>
@@ -107,14 +112,18 @@
<select bind:value={badge_type_code} class="select">
<option value="">-- Select Badge Type --</option>
{#each badge_type_code_li as type_code_item}
<option value={type_code_item.code}>{type_code_item.name}</option>
<option value={type_code_item.code}
>{type_code_item.name}</option
>
{/each}
</select>
</label>
<div class="flex justify-end gap-2">
<button type="button" class="btn variant-filled-tertiary" onclick={handle_cancel}
>Cancel</button
<button
type="button"
class="btn variant-filled-tertiary"
onclick={handle_cancel}>Cancel</button
>
<button
type="submit"

View File

@@ -22,39 +22,61 @@
import { type Badge as BadgeType } from '$lib/ae_events/db_events';
import { ae_loc } from '$lib/stores/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils';
import { LoaderCircle, Badge, Check, EyeOff, Mail, MapPin, Tags, FileSearch } from 'lucide-svelte';
import {
LoaderCircle,
Badge,
Check,
EyeOff,
Mail,
MapPin,
Tags,
FileSearch
} from 'lucide-svelte';
// Derived list of visible items (Standardized Pattern 2026-01-27)
let visible_badge_obj_li = $derived((() => {
const list = $lq__event_badge_obj_li;
let visible_badge_obj_li = $derived(
(() => {
const list = $lq__event_badge_obj_li;
if (list === undefined || list === null) return null;
if (!Array.isArray(list)) return [];
if (list === undefined || list === null) return null;
if (!Array.isArray(list)) return [];
const filtered = list.filter((item: any) => {
if (!item) return false;
// ADMIN/TRUSTED: See everything
if ($ae_loc.trusted_access) return true;
// PUBLIC: Filter hidden
return !item.hide;
});
const filtered = list.filter((item: any) => {
if (!item) return false;
// ADMIN/TRUSTED: See everything
if ($ae_loc.trusted_access) return true;
// PUBLIC: Filter hidden
return !item.hide;
});
if (log_lvl) console.log(`visible_badge_obj_li: Input=${list.length}, Output=${filtered.length}`);
return filtered;
})());
if (log_lvl)
console.log(
`visible_badge_obj_li: Input=${list.length}, Output=${filtered.length}`
);
return filtered;
})()
);
</script>
<section class="px-1 flex flex-col gap-1 items-center justify-center space-y-1 w-full max-w-7xl mx-auto">
<section
class="px-1 flex flex-col gap-1 items-center justify-center space-y-1 w-full max-w-7xl mx-auto"
>
{#if visible_badge_obj_li === null}
<div class="flex flex-col items-center justify-center p-10 opacity-50">
<LoaderCircle size="2em" class="animate-spin mb-2" />
<p>Loading badges...</p>
</div>
{:else if visible_badge_obj_li.length > 0}
<header class="w-full flex flex-row gap-2 items-center justify-start mb-2 px-2">
<h2 class="text-sm text-gray-500 font-normal"> Results: </h2>
<span class="badge preset-tonal-success font-bold text-lg px-3 py-1">
{visible_badge_obj_li.length}<span class="text-gray-400 dark:text-gray-600">&times;</span>
<header
class="w-full flex flex-row gap-2 items-center justify-start mb-2 px-2"
>
<h2 class="text-sm text-gray-500 font-normal">Results:</h2>
<span
class="badge preset-tonal-success font-bold text-lg px-3 py-1"
>
{visible_badge_obj_li.length}<span
class="text-gray-400 dark:text-gray-600">&times;</span
>
</span>
</header>
@@ -68,14 +90,21 @@
hover:border-primary-500 transition-colors
"
>
<div class="flex flex-row flex-wrap gap-2 items-center justify-between w-full">
<div class="flex flex-row flex-wrap gap-2 items-center justify-start grow">
<div
class="flex flex-row flex-wrap gap-2 items-center justify-between w-full"
>
<div
class="flex flex-row flex-wrap gap-2 items-center justify-start grow"
>
<a
href={`/events/${event_badge_obj?.event_id}/badges/${event_badge_obj?.event_badge_id}`}
class="flex flex-row gap-2 items-center justify-start min-w-fit font-bold text-lg hover:text-primary-500"
>
{#if event_badge_obj?.hide}
<EyeOff size="1.2em" class="text-gray-400" />
<EyeOff
size="1.2em"
class="text-gray-400"
/>
{:else}
<Badge size="1.2em" />
{/if}
@@ -86,12 +115,15 @@
{:else if event_badge_obj?.full_name}
{event_badge_obj?.full_name}
{:else}
{event_badge_obj?.given_name} {event_badge_obj?.family_name}
{event_badge_obj?.given_name}
{event_badge_obj?.family_name}
{/if}
</span>
{#if event_badge_obj?.print_count >= 1}
<span class="badge preset-filled-success-500 flex items-center gap-1 text-xs py-0 px-1">
<span
class="badge preset-filled-success-500 flex items-center gap-1 text-xs py-0 px-1"
>
<Check size="1em" />
{event_badge_obj.print_count}
</span>
@@ -99,25 +131,34 @@
</a>
{#if show_sensitive_fields}
<span class="text-xs text-surface-400 flex items-center gap-1">
<span
class="text-xs text-surface-400 flex items-center gap-1"
>
<Mail size="1em" />
{#if $ae_loc.trusted_access}
{event_badge_obj?.email}
{:else}
{event_badge_obj?.email?.replace(/^(.{3}).*@/, '$1...@') ?? ''}
{event_badge_obj?.email?.replace(
/^(.{3}).*@/,
'$1...@'
) ?? ''}
{/if}
</span>
{/if}
{#if !hide_affiliations && event_badge_obj.affiliations}
<span class="text-xs text-surface-400 flex items-center gap-1">
<span
class="text-xs text-surface-400 flex items-center gap-1"
>
<MapPin size="1em" />
{event_badge_obj.affiliations}
</span>
{/if}
{#if !hide_badge_type && event_badge_obj.badge_type}
<span class="text-xs italic text-primary-500 bg-primary-500/10 px-2 rounded-token flex items-center gap-1">
<span
class="text-xs italic text-primary-500 bg-primary-500/10 px-2 rounded-token flex items-center gap-1"
>
<Tags size="1em" />
{event_badge_obj.badge_type}
</span>
@@ -138,14 +179,45 @@
<div
class="flex flex-row flex-wrap gap-x-4 gap-y-1 items-center justify-start w-full mt-1 p-1.5 bg-surface-200/50 dark:bg-surface-800/50 rounded text-[10px] font-mono border border-surface-300 dark:border-surface-700 opacity-80"
>
<span class="flex items-center gap-1"><span class="font-bold opacity-50">ID:</span> {event_badge_obj?.event_badge_id}</span>
<span class="flex items-center gap-1"><span class="font-bold opacity-50">CR:</span> {ae_util.iso_datetime_formatter(event_badge_obj.created_on, 'datetime_iso_12_no_seconds')}</span>
<span class="flex items-center gap-1"><span class="font-bold opacity-50">UP:</span> {ae_util.iso_datetime_formatter(event_badge_obj.updated_on, 'datetime_iso_12_no_seconds')}</span>
<span class="flex items-center gap-1"
><span class="font-bold opacity-50">ID:</span>
{event_badge_obj?.event_badge_id}</span
>
<span class="flex items-center gap-1"
><span class="font-bold opacity-50">CR:</span>
{ae_util.iso_datetime_formatter(
event_badge_obj.created_on,
'datetime_iso_12_no_seconds'
)}</span
>
<span class="flex items-center gap-1"
><span class="font-bold opacity-50">UP:</span>
{ae_util.iso_datetime_formatter(
event_badge_obj.updated_on,
'datetime_iso_12_no_seconds'
)}</span
>
{#if event_badge_obj.print_first_datetime}
<span class="flex items-center gap-1"><span class="font-bold opacity-50">FP:</span> {ae_util.iso_datetime_formatter(event_badge_obj.print_first_datetime, 'datetime_iso_12_no_seconds')}</span>
<span class="flex items-center gap-1"
><span class="font-bold opacity-50"
>FP:</span
>
{ae_util.iso_datetime_formatter(
event_badge_obj.print_first_datetime,
'datetime_iso_12_no_seconds'
)}</span
>
{/if}
{#if event_badge_obj.print_last_datetime}
<span class="flex items-center gap-1"><span class="font-bold opacity-50">LP:</span> {ae_util.iso_datetime_formatter(event_badge_obj.print_last_datetime, 'datetime_iso_12_no_seconds')}</span>
<span class="flex items-center gap-1"
><span class="font-bold opacity-50"
>LP:</span
>
{ae_util.iso_datetime_formatter(
event_badge_obj.print_last_datetime,
'datetime_iso_12_no_seconds'
)}</span
>
{/if}
</div>
{/if}
@@ -153,9 +225,14 @@
{/each}
</ul>
{:else}
<div class="flex flex-col items-center justify-center p-20 opacity-50 text-center">
<div
class="flex flex-col items-center justify-center p-20 opacity-50 text-center"
>
<FileSearch size="3em" class="mb-2 opacity-20 mx-auto" />
<p>No badges found matching your criteria. Try adjusting your filters.</p>
<p>
No badges found matching your criteria. Try adjusting your
filters.
</p>
</div>
{/if}
</section>
</section>

View File

@@ -4,10 +4,7 @@
log_lvl?: number;
}
let {
event_id,
log_lvl = 0
}: Props = $props();
let { event_id, log_lvl = 0 }: Props = $props();
// *** Import other supporting libraries
import {
@@ -20,14 +17,8 @@
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 { 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 { ae_util } from '$lib/ae_utils/ae_utils';
@@ -77,7 +68,9 @@
}
</script>
<div class="ae_group filters_and_search flex flex-col items-center justify-center gap-2 w-full">
<div
class="ae_group filters_and_search flex flex-col items-center justify-center gap-2 w-full"
>
{#if $events_sess.badges.show_form__search}
<form
onsubmit={prevent_default(() => {
@@ -86,7 +79,9 @@
autocomplete="off"
class="search_form flex flex-row flex-wrap gap-1 items-center justify-center w-full max-w-7xl px-2 md:px-12 py-2 preset-tonal-success rounded-lg shadow-sm"
>
<div class="flex flex-col md:flex-row items-center justify-center gap-1 grow">
<div
class="flex flex-col md:flex-row items-center justify-center gap-1 grow"
>
{#if $ae_loc.trusted_access}
<select
bind:value={$events_loc.badges.search_badge_type_code}
@@ -95,7 +90,9 @@
>
<option value="">-- All Badge Types --</option>
{#each badge_type_code_li as badge_type_code}
<option value={badge_type_code.code}>{badge_type_code.name}</option>
<option value={badge_type_code.code}
>{badge_type_code.name}</option
>
{/each}
</select>
@@ -119,11 +116,19 @@
<option value="name_desc">Name DESC</option>
<option value="updated_desc">Updated DESC</option>
<option value="updated_asc">Updated ASC</option>
<option value="print_count_desc">Print Count DESC</option>
<option value="print_first_desc">First Printed DESC</option>
<option value="print_last_desc">Last Printed DESC</option>
<option value="print_count_desc"
>Print Count DESC</option
>
<option value="print_first_desc"
>First Printed DESC</option
>
<option value="print_last_desc"
>Last Printed DESC</option
>
<option value="badge_type_asc">Badge Type ASC</option>
<option value="affiliations_asc">Affiliations ASC</option>
<option value="affiliations_asc"
>Affiliations ASC</option
>
</select>
<input
@@ -131,7 +136,11 @@
placeholder="affiliations"
bind:value={$events_loc.badges.qry_affiliations}
onkeyup={(e) => {
if (e.key === 'Enter' || ($events_loc.badges.qry_affiliations?.length ?? 0) >= 3) {
if (
e.key === 'Enter' ||
($events_loc.badges.qry_affiliations?.length ??
0) >= 3
) {
handle_search_trigger();
}
}}
@@ -169,8 +178,11 @@
Search
</button>
<button type="button"
class:hidden={!$events_loc.badges.fulltext_search_qry_str && !$events_loc.badges.search_badge_type_code && $events_loc.badges.qry_printed_status === 'all'}
<button
type="button"
class:hidden={!$events_loc.badges.fulltext_search_qry_str &&
!$events_loc.badges.search_badge_type_code &&
$events_loc.badges.qry_printed_status === 'all'}
onclick={() => {
$events_loc.badges.fulltext_search_qry_str = '';
$events_loc.badges.search_badge_type_code = '';
@@ -187,7 +199,9 @@
</div>
</form>
{:else if $events_sess.badges.show_form__scan}
<div class="w-full max-w-2xl mx-auto p-4 bg-surface-100-900 rounded-lg shadow-lg">
<div
class="w-full max-w-2xl mx-auto p-4 bg-surface-100-900 rounded-lg shadow-lg"
>
<Element_qr_scanner_v2
bind:start_qr_scanner={$events_sess.badges.qr_scan_start}
on:qr_scan_result={handle_qr_scan_result}
@@ -195,9 +209,12 @@
</div>
{/if}
<div class="flex flex-row flex-wrap items-center justify-center gap-2 opacity-70 hover:opacity-100 transition-all">
<div
class="flex flex-row flex-wrap items-center justify-center gap-2 opacity-70 hover:opacity-100 transition-all"
>
{#if $events_sess.badges.show_form__search}
<button type="button"
<button
type="button"
onclick={() => {
$events_sess.badges.show_form__search = false;
$events_sess.badges.show_form__scan = true;
@@ -209,7 +226,8 @@
QR Scan
</button>
{:else}
<button type="button"
<button
type="button"
onclick={() => {
$events_sess.badges.show_form__search = true;
$events_sess.badges.show_form__scan = false;
@@ -222,7 +240,8 @@
</button>
{/if}
<button type="button"
<button
type="button"
onclick={() => {
$events_loc.badges.use_id_li = !$events_loc.badges.use_id_li;
handle_search_trigger();
@@ -239,7 +258,9 @@
</button>
{#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">
<label
class="flex items-center gap-1 cursor-pointer bg-surface-200-800 px-2 py-1 rounded-token text-xs font-semibold"
>
<span> Remote First </span>
<input
type="checkbox"
@@ -250,4 +271,4 @@
</label>
{/if}
</div>
</div>
</div>

View File

@@ -48,7 +48,7 @@
}
async function handle_upload(event: Event) {
event.preventDefault();
event.prevent_default();
if (!selected_file) {
upload_message = 'Please select a file first.';
upload_status = 'error';
@@ -72,9 +72,12 @@
for (const data_kv of badge_data_li) {
// Simple mapping, customize as needed
const badge_payload: key_val = {
full_name_override: data_kv.full_name || data_kv.name || null,
professional_title_override: data_kv.professional_title || null,
affiliations_override: data_kv.affiliations || data_kv.company || null,
full_name_override:
data_kv.full_name || data_kv.name || null,
professional_title_override:
data_kv.professional_title || null,
affiliations_override:
data_kv.affiliations || data_kv.company || null,
location_override: data_kv.location || null,
email: data_kv.email || null,
allow_tracking:
@@ -118,11 +121,17 @@
<form onsubmit={handle_upload} class="p-4 space-y-4">
<h3 class="h3">Upload Badge List (CSV)</h3>
<p>Upload a CSV file containing badge data. The first row should be headers.</p>
<p>
Supported headers (case-sensitive): <code>full_name</code>, <code>name</code>,
<code>professional_title</code>, <code>affiliations</code>, <code>company</code>,
<code>location</code>, <code>email</code>, <code>allow_tracking</code> (true/false or 1/0),
Upload a CSV file containing badge data. The first row should be
headers.
</p>
<p>
Supported headers (case-sensitive): <code>full_name</code>,
<code>name</code>,
<code>professional_title</code>, <code>affiliations</code>,
<code>company</code>,
<code>location</code>, <code>email</code>, <code>allow_tracking</code>
(true/false or 1/0),
<code>badge_type_code</code>.
</p>
@@ -142,21 +151,32 @@
{/if}
{#if upload_status !== 'idle'}
<div class="alert variant-soft-{upload_status === 'error' ? 'error' : 'info'}">
<div
class="alert variant-soft-{upload_status === 'error'
? 'error'
: 'info'}"
>
<p>{upload_message}</p>
{#if upload_status === 'processing' || upload_status === 'loading'}
<progress class="progress" value={processed_badges_count} max={total_badges_in_file}
<progress
class="progress"
value={processed_badges_count}
max={total_badges_in_file}
></progress>
<p>Processed: {processed_badges_count} / {total_badges_in_file}</p>
<p>
Processed: {processed_badges_count} / {total_badges_in_file}
</p>
{/if}
</div>
{/if}
<div class="flex justify-end gap-2">
<button type="button"
<button
type="button"
class="btn variant-filled-tertiary"
onclick={handle_cancel}
disabled={upload_status === 'loading' || upload_status === 'processing'}>Cancel</button
disabled={upload_status === 'loading' ||
upload_status === 'processing'}>Cancel</button
>
<button
type="submit"

View File

@@ -13,14 +13,21 @@
let { data }: Props = $props();
let event_id: string = data.params.event_id;
let printed_status_filter: string | null = data.url.searchParams.get('printed_status');
let badge_type_code_filter: string | null = data.url.searchParams.get('badge_type_code');
let printed_status_filter: string | null =
data.url.searchParams.get('printed_status');
let badge_type_code_filter: string | null =
data.url.searchParams.get('badge_type_code');
let lq__filtered_badges = $derived(
liveQuery(async () => {
const filters: { printed_status?: "all" | "printed" | "not_printed"; type_code?: string } = {};
if (printed_status_filter) filters.printed_status = printed_status_filter as any;
if (badge_type_code_filter) filters.type_code = badge_type_code_filter;
const filters: {
printed_status?: 'all' | 'printed' | 'not_printed';
type_code?: string;
} = {};
if (printed_status_filter)
filters.printed_status = printed_status_filter as any;
if (badge_type_code_filter)
filters.type_code = badge_type_code_filter;
// Fetch badges using the search function, with a high limit for bulk printing
const result = await events_func.search__event_badge({

View File

@@ -20,11 +20,12 @@
let lq__badge_templates = $derived(
liveQuery(async () => {
const result = await events_func.load_ae_obj_li__event_badge_template({
api_cfg: $ae_api,
event_id: event_id,
log_lvl: 0
});
const result =
await events_func.load_ae_obj_li__event_badge_template({
api_cfg: $ae_api,
event_id: event_id,
log_lvl: 0
});
return result || [];
})
);
@@ -80,7 +81,11 @@
<h1 class="h1">Badge Templates</h1>
<div class="my-4 flex justify-end">
<button type="button" class="btn btn-primary" onclick={() => (show_create_template_modal = true)}>
<button
type="button"
class="btn btn-primary"
onclick={() => (show_create_template_modal = true)}
>
<span class="fas fa-plus mr-2"></span> Add New Template
</button>
</div>
@@ -90,20 +95,28 @@
<div class="card p-4">
<ul class="list-group">
{#each $lq__badge_templates as template (template.event_badge_template_id_random)}
<li class="list-group-item flex justify-between items-center">
<li
class="list-group-item flex justify-between items-center"
>
<span>{template.name}</span>
<div>
<button type="button"
<button
type="button"
class="btn btn-sm variant-filled-primary"
onclick={() =>
edit_template(template.event_badge_template_id_random)}
edit_template(
template.event_badge_template_id_random
)}
>
<span class="fas fa-edit"></span> Edit
</button>
<button type="button"
<button
type="button"
class="btn btn-sm variant-filled-error ml-2"
onclick={() =>
delete_template(template.event_badge_template_id_random)}
delete_template(
template.event_badge_template_id_random
)}
>
<span class="fas fa-trash"></span> Delete
</button>
@@ -113,7 +126,10 @@
</ul>
</div>
{:else}
<p>No badge templates found for this event. Click "Add New Template" to create one.</p>
<p>
No badge templates found for this event. Click "Add New
Template" to create one.
</p>
{/if}
{:else}
<p>Loading badge templates...</p>

View File

@@ -12,8 +12,8 @@
oncancel?: () => void;
}
let {
event_id,
let {
event_id,
template_id = null,
onsuccess,
onerror,
@@ -22,7 +22,7 @@
function prevent_default(fn: () => void) {
return function (event: Event) {
event.prevent_default();
event.preventDefault();
fn();
};
}
@@ -57,17 +57,19 @@
async function load_template(id: string) {
submit_status = 'loading';
try {
const template_obj = await events_func.load_ae_obj_id__event_badge_template({
api_cfg: $ae_api,
event_badge_template_id: id
});
const template_obj =
await events_func.load_ae_obj_id__event_badge_template({
api_cfg: $ae_api,
event_badge_template_id: id
});
if (template_obj) {
name = template_obj.name || '';
header_path = template_obj.header_path || '';
logo_path = template_obj.logo_path || '';
header_row_1 = template_obj.header_row_1 || '';
header_row_2 = template_obj.header_row_2 || '';
secondary_header_path = template_obj.secondary_header_path || '';
secondary_header_path =
template_obj.secondary_header_path || '';
footer_text = template_obj.footer_text || '';
show_qr_front = template_obj.show_qr_front ?? true;
show_qr_back = template_obj.show_qr_back ?? true;
@@ -159,11 +161,13 @@
</label>
<label class="label">
<span>Header Row 1 Text (HTML allowed)</span>
<textarea bind:value={header_row_1} class="textarea" rows="2"></textarea>
<textarea bind:value={header_row_1} class="textarea" rows="2"
></textarea>
</label>
<label class="label">
<span>Header Row 2 Text (HTML allowed)</span>
<textarea bind:value={header_row_2} class="textarea" rows="2"></textarea>
<textarea bind:value={header_row_2} class="textarea" rows="2"
></textarea>
</label>
<label class="label">
<span>Secondary Header Path (URL, back of badge)</span>
@@ -195,19 +199,23 @@
<label class="label">
<span>Ticket 1 Text (HTML allowed)</span>
<textarea bind:value={ticket_1_text} class="textarea" rows="2"></textarea>
<textarea bind:value={ticket_1_text} class="textarea" rows="2"
></textarea>
</label>
<label class="label">
<span>Ticket 2 Text (HTML allowed)</span>
<textarea bind:value={ticket_2_text} class="textarea" rows="2"></textarea>
<textarea bind:value={ticket_2_text} class="textarea" rows="2"
></textarea>
</label>
<label class="label">
<span>Ticket 3 Text (HTML allowed)</span>
<textarea bind:value={ticket_3_text} class="textarea" rows="2"></textarea>
<textarea bind:value={ticket_3_text} class="textarea" rows="2"
></textarea>
</label>
<div class="flex justify-end gap-2">
<button type="button"
<button
type="button"
class="btn variant-filled-tertiary"
onclick={handle_cancel}
disabled={submit_status === 'loading'}>Cancel</button