There have been a lot of changes. For some reason the commit is not working? Trying again.
This commit is contained in:
@@ -11,14 +11,14 @@
|
||||
// import { goto } from '$app/navigation';
|
||||
|
||||
// *** Import other supporting libraries
|
||||
// import { browser } from '$app/environment';
|
||||
import { browser } from '$app/environment';
|
||||
import { liveQuery } from 'dexie';
|
||||
|
||||
// *** Import Aether specific variables and functions
|
||||
// import type { key_val } from '$lib/ae_stores';
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
// import { core_func } from '$lib/ae_core_functions';
|
||||
// import { ae_snip, ae_loc, ae_sess, ae_api, ae_trig, slct, slct_trigger } from '$lib/ae_stores';
|
||||
import { ae_loc } from '$lib/stores/ae_stores';
|
||||
|
||||
// import Element_ae_crud from '$lib/element_ae_crud
|
||||
// import Element_data_store from '$lib/element_data_store_v2.svelte';
|
||||
@@ -58,14 +58,31 @@
|
||||
})
|
||||
);
|
||||
|
||||
let is_review_mode: boolean = $state(false);
|
||||
|
||||
// *** Functions and Logic
|
||||
|
||||
// if (browser) {
|
||||
// console.log('Browser environment detected.');
|
||||
import { onMount } from 'svelte';
|
||||
let lq__event_obj = $state(null);
|
||||
|
||||
// let url_test_val = data.url.searchParams.get('test_val');
|
||||
// console.log(`URL test_val = ${url_test_val}`);
|
||||
// }
|
||||
onMount(() => {
|
||||
const observable = liveQuery(() => db_events.event.get($events_slct?.event_id ?? ''));
|
||||
const subscription = observable.subscribe((value) => {
|
||||
lq__event_obj = value;
|
||||
});
|
||||
|
||||
if (browser && window.location.hash === '#review') {
|
||||
is_review_mode = true;
|
||||
$ae_loc.edit_mode = true;
|
||||
} else {
|
||||
is_review_mode = false;
|
||||
$ae_loc.edit_mode = false;
|
||||
}
|
||||
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -116,6 +133,7 @@
|
||||
event_id={$lq__event_badge_obj.event_id}
|
||||
{event_badge_id}
|
||||
{lq__event_badge_obj}
|
||||
{is_review_mode}
|
||||
/>
|
||||
<!-- {/if} -->
|
||||
{:else}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
lq__event_badge_obj?: any;
|
||||
update_status?: string;
|
||||
update_complete?: boolean;
|
||||
is_review_mode?: boolean;
|
||||
log_lvl?: number;
|
||||
}
|
||||
|
||||
@@ -14,6 +15,7 @@
|
||||
lq__event_badge_obj,
|
||||
update_status = $bindable('idle'),
|
||||
update_complete = $bindable(true),
|
||||
is_review_mode = false,
|
||||
log_lvl = 0
|
||||
}: Props = $props();
|
||||
|
||||
@@ -23,27 +25,7 @@
|
||||
// *** Import other supporting libraries
|
||||
import { liveQuery } from 'dexie';
|
||||
|
||||
// import {
|
||||
// ArrowDown01, ArrowDown10, ArrowDownUp,
|
||||
// BetweenVerticalEnd, BetweenVerticalStart,
|
||||
// BookHeart, BookImage, Bookmark, BookOpenText, BriefcaseBusiness,
|
||||
// Check, Copy,
|
||||
// Expand, Eye, EyeOff,
|
||||
// Flag, FlagOff, FilePlus, Fingerprint,
|
||||
// Globe,
|
||||
// Library,
|
||||
// MessageSquareWarning, Minus,
|
||||
// Notebook,
|
||||
// Pencil, Plus,
|
||||
// RemoveFormatting,
|
||||
// SquareLibrary,
|
||||
// Shapes, Share2, ShieldCheck, ShieldMinus, Siren, Skull,
|
||||
// Tags, Target, ToggleLeft, ToggleRight, Trash2, TypeOutline,
|
||||
// X
|
||||
// } from '@lucide/svelte';
|
||||
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
// import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import { core_func } from '$lib/ae_core/ae_core_functions';
|
||||
import {
|
||||
ae_snip,
|
||||
@@ -100,90 +82,57 @@
|
||||
let show_event_badge_tools_modal: boolean = $state(false);
|
||||
let show_restricted_fields: boolean = $state(false);
|
||||
|
||||
let allow_tracking: null | boolean = $state(null);
|
||||
let show_allow_tracking: boolean = $state(false);
|
||||
// Editable fields
|
||||
let editable_full_name_override: string | null = $state(null);
|
||||
let editable_professional_title_override: string | null = $state(null);
|
||||
let editable_affiliations_override: string | null = $state(null);
|
||||
let editable_location_override: string | null = $state(null);
|
||||
let editable_allow_tracking: boolean | null = $state(null);
|
||||
let editable_email: string | null = $state(null);
|
||||
let editable_badge_type_code: string | null = $state(null);
|
||||
|
||||
let edit_full_name_override = $state(false);
|
||||
let edit_professional_title_override = $state(false);
|
||||
let edit_affiliations_override = $state(false);
|
||||
let edit_location_override = $state(false);
|
||||
// Manage edit state locally
|
||||
let edit_mode_active: boolean = $state(false);
|
||||
|
||||
// Initialize editable fields when lq__event_badge_obj changes
|
||||
$effect(() => {
|
||||
if (lq__event_badge_obj) {
|
||||
editable_full_name_override = 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;
|
||||
editable_location_override = 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;
|
||||
|
||||
if (is_review_mode) {
|
||||
edit_mode_active = true;
|
||||
$ae_loc.edit_mode = true;
|
||||
} else {
|
||||
edit_mode_active = false; // Ensure it starts off if not in review mode
|
||||
$ae_loc.edit_mode = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let show_print_msg: null | boolean = $state(null);
|
||||
let hide_qr: null | boolean = $state(null);
|
||||
|
||||
let use_badge_type = $state(null);
|
||||
let use_badge_type_code = $state('');
|
||||
// let use_badge_type_code_list = [];
|
||||
// use_badge_type_code_list.push({code: 'current_member', name: 'Member'});
|
||||
// use_badge_type_code_list.push({code: 'inactive_member', name: 'Non-Member'});
|
||||
|
||||
// use_badge_type_code_list.push({code: 'MBR', name: 'Member'});
|
||||
// use_badge_type_code_list.push({code: 'AHMB', name: 'Member'});
|
||||
|
||||
// use_badge_type_code_list.push({code: 'SNMB', name: 'Student/Trainee Non-Member'});
|
||||
// use_badge_type_code_list.push({code: 'SMBR', name: 'Student/Trainee Member'});
|
||||
|
||||
// use_badge_type_code_list.push({code: 'NMBR', name: 'Non-Member'});
|
||||
// use_badge_type_code_list.push({code: 'ANHM', name: 'Non-Member'});
|
||||
// use_badge_type_code_list.push({code: 'INMB', name: 'Non-Member'});
|
||||
|
||||
// use_badge_type_code_list.push({code: 'EXO', name: 'Exhibitor Booth Staff'});
|
||||
// use_badge_type_code_list.push({code: 'EXALL', name: 'Exhibitor All Access'});
|
||||
|
||||
// use_badge_type_code_list.push({code: 'GUEST', name: 'Guest'});
|
||||
|
||||
// use_badge_type_code_list.push({code: 'HEART', name: 'HFTX Core'});
|
||||
// use_badge_type_code_list.push({code: 'LUNG', name: 'LTX Core'});
|
||||
|
||||
// use_badge_type_code_list.push({code: 'STAFF', name: 'Staff'});
|
||||
// use_badge_type_code_list.push({code: 'VIP', name: 'VIP'});
|
||||
// use_badge_type_code_list.push({code: 'VOL', name: 'Volunteer'});
|
||||
|
||||
let full_name_override = $state(null); // Usually set by the person or similar
|
||||
let longest_full_name_override_part = 0;
|
||||
let full_name = $state(null); // Usually auto generated
|
||||
|
||||
let professional_title_override = $state(null);
|
||||
let longest_professional_title_override_part = 0;
|
||||
|
||||
let affiliations_override = $state(null);
|
||||
let longest_affiliations_override_part = 0;
|
||||
|
||||
let location_override = $state(null);
|
||||
let longest_location_override_part = 0;
|
||||
|
||||
let option_other_1_display_opt: any = $state(null);
|
||||
let option_other_1_override: any = $state(null);
|
||||
let option_other_2_display_opt: any = $state(null);
|
||||
let option_other_2_override: any = $state(null);
|
||||
|
||||
let option_ticket_1_display_opt: any = $state(null);
|
||||
let option_ticket_1_override: any = $state(null);
|
||||
let option_ticket_2_display_opt: any = $state(null);
|
||||
let option_ticket_2_override: any = $state(null);
|
||||
let option_ticket_3_display_opt: any = $state(null);
|
||||
let option_ticket_3_override: any = $state(null);
|
||||
// let option_ticket_4_display_opt = $state(null);
|
||||
// let option_ticket_5_display_opt = $state(null);
|
||||
// let option_ticket_6_display_opt = $state(null);
|
||||
// let option_ticket_7_display_opt = $state(null);
|
||||
// let option_ticket_8_display_opt = $state(null);
|
||||
// These variables seem unused or redundant now with editable_ fields
|
||||
// let use_badge_type = $state(null);
|
||||
// let use_badge_type_code = $state('');
|
||||
|
||||
let slct_badge_type = '';
|
||||
|
||||
// let qr_type = 'mecard';
|
||||
// let qr_img_src = $state(null);
|
||||
// let img_obj_url = $state(null);
|
||||
|
||||
/* *** BEGIN *** This should be moved out */
|
||||
// display options: 'front_bool', 'front_html', 'back_bool', 'back_html'
|
||||
|
||||
option_ticket_1_display_opt = 'front_bool';
|
||||
option_ticket_2_display_opt = 'front_bool';
|
||||
option_ticket_3_display_opt = 'front_bool';
|
||||
let option_ticket_1_display_opt = 'front_bool';
|
||||
let option_ticket_2_display_opt = 'front_bool';
|
||||
let option_ticket_3_display_opt = 'front_bool';
|
||||
|
||||
option_other_1_display_opt = 'back_html';
|
||||
option_other_2_display_opt = 'back_html';
|
||||
let option_other_1_display_opt = 'back_html';
|
||||
let option_other_2_display_opt = 'back_html';
|
||||
|
||||
let code_to_html: any = { option_1: {}, option_2: {} };
|
||||
code_to_html.option_1['1'] = '<span class="fas fa-biohazard"></span>';
|
||||
@@ -203,12 +152,6 @@
|
||||
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['1-5'] = '<span class="fas fa-grimace"></span>';
|
||||
// code_to_html.option_2['6-10'] = '<span class="fas fa-grimace"></span>';
|
||||
// code_to_html.option_2['11-15'] = '<span class="fas fa-grimace"></span>';
|
||||
// code_to_html.option_2['16-29'] = '<span class="fas fa-grimace"></span>';
|
||||
// code_to_html.option_2['30+'] = '<span class="fas fa-grimace"></span>';
|
||||
// code_to_html.option_2['Unknown'] = '<span class="fas fa-radiation"></span>';
|
||||
/* *** END *** This should be moved out */
|
||||
|
||||
let full_name_class_size: string = $state('text-[.60in]');
|
||||
@@ -227,10 +170,14 @@
|
||||
$lq__event_badge_obj?.event_badge_template_id
|
||||
);
|
||||
|
||||
full_name_override =
|
||||
$lq__event_badge_obj?.full_name_override ?? $lq__event_badge_obj?.full_name;
|
||||
longest_full_name_override_part = longest_str_part(full_name_override ?? '');
|
||||
// Re-calculate font sizes based on potentially edited values
|
||||
const current_full_name = editable_full_name_override ?? lq__event_badge_obj?.full_name ?? '';
|
||||
const current_professional_title = editable_professional_title_override ?? lq__event_badge_obj?.professional_title ?? '';
|
||||
const current_affiliations = editable_affiliations_override ?? lq__event_badge_obj?.affiliations ?? '';
|
||||
const current_location = editable_location_override ?? lq__event_badge_obj?.location ?? '';
|
||||
|
||||
|
||||
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) {
|
||||
@@ -239,12 +186,7 @@
|
||||
full_name_class_size = 'text-[.75in]';
|
||||
}
|
||||
|
||||
professional_title_override =
|
||||
$lq__event_badge_obj?.professional_title_override ??
|
||||
$lq__event_badge_obj?.professional_title;
|
||||
longest_professional_title_override_part = longest_str_part(
|
||||
professional_title_override ?? ''
|
||||
);
|
||||
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) {
|
||||
@@ -255,9 +197,7 @@
|
||||
professional_title_class_size = 'text-[.35in]';
|
||||
}
|
||||
|
||||
affiliations_override =
|
||||
$lq__event_badge_obj?.affiliations_override ?? $lq__event_badge_obj?.affiliations;
|
||||
longest_affiliations_override_part = longest_str_part(affiliations_override ?? '');
|
||||
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) {
|
||||
@@ -277,9 +217,7 @@
|
||||
affiliations_class_size = full_name_class_size;
|
||||
}
|
||||
|
||||
location_override =
|
||||
$lq__event_badge_obj?.location_override ?? $lq__event_badge_obj?.location;
|
||||
longest_location_override_part = longest_str_part(location_override ?? '');
|
||||
longest_location_override_part = longest_str_part(current_location);
|
||||
if (longest_location_override_part >= 55) {
|
||||
location_class_size = 'text-[.30in]';
|
||||
} else if (longest_location_override_part >= 45) {
|
||||
@@ -301,27 +239,12 @@
|
||||
professional_title_class_size = location_class_size;
|
||||
}
|
||||
|
||||
option_other_1_override =
|
||||
$lq__event_badge_obj?.option_other_1_override ??
|
||||
$lq__event_badge_obj?.option_other_1;
|
||||
option_other_2_override =
|
||||
$lq__event_badge_obj?.option_other_2_override ??
|
||||
$lq__event_badge_obj?.option_other_2;
|
||||
|
||||
option_ticket_1_override =
|
||||
$lq__event_badge_obj?.option_ticket_1_override ??
|
||||
$lq__event_badge_obj?.option_ticket_1;
|
||||
option_ticket_2_override =
|
||||
$lq__event_badge_obj?.option_ticket_2_override ??
|
||||
$lq__event_badge_obj?.option_ticket_2;
|
||||
option_ticket_3_override =
|
||||
$lq__event_badge_obj?.option_ticket_3_override ??
|
||||
$lq__event_badge_obj?.option_ticket_3;
|
||||
// option_ticket_4_override = $lq__event_badge_obj?.option_ticket_4_override ?? $lq__event_badge_obj?.option_ticket_4;
|
||||
// option_ticket_5_override = $lq__event_badge_obj?.option_ticket_5_override ?? $lq__event_badge_obj?.option_ticket_5;
|
||||
// option_ticket_6_override = $lq__event_badge_obj?.option_ticket_6_override ?? $lq__event_badge_obj?.option_ticket_6;
|
||||
// option_ticket_7_override = $lq__event_badge_obj?.option_ticket_7_override ?? $lq__event_badge_obj?.option_ticket_7;
|
||||
// option_ticket_8_override = $lq__event_badge_obj?.option_ticket_8_override ?? $lq__event_badge_obj?.option_ticket_8;
|
||||
// These are no longer needed as we use the editable fields directly
|
||||
// option_other_1_override = $lq__event_badge_obj?.option_other_1_override ?? $lq__event_badge_obj?.option_other_1;
|
||||
// option_other_2_override = $lq__event_badge_obj?.option_other_2_override ?? $lq__event_badge_obj?.option_other_2;
|
||||
// option_ticket_1_override = $lq__event_badge_obj?.option_ticket_1_override ?? $lq__event_badge_obj?.option_ticket_1;
|
||||
// option_ticket_2_override = $lq__event_badge_obj?.option_ticket_2_override ?? $lq__event_badge_obj?.option_ticket_2;
|
||||
// option_ticket_3_override = $lq__event_badge_obj?.option_ticket_3_override ?? $lq__event_badge_obj?.option_ticket_3;
|
||||
|
||||
return results;
|
||||
})
|
||||
@@ -411,6 +334,90 @@
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function handle_save_changes() {
|
||||
if (!lq__event_badge_obj?.event_badge_id_random) {
|
||||
console.error('Cannot save changes: event_badge_id_random is missing.');
|
||||
return;
|
||||
}
|
||||
|
||||
update_status = 'loading';
|
||||
update_complete = false;
|
||||
|
||||
const data_to_update: key_val = {};
|
||||
|
||||
// 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)) {
|
||||
data_to_update.full_name_override = editable_full_name_override;
|
||||
}
|
||||
if (editable_professional_title_override !== (lq__event_badge_obj.professional_title_override ?? lq__event_badge_obj.professional_title)) {
|
||||
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)) {
|
||||
data_to_update.affiliations_override = editable_affiliations_override;
|
||||
}
|
||||
if (editable_location_override !== (lq__event_badge_obj.location_override ?? lq__event_badge_obj.location)) {
|
||||
data_to_update.location_override = editable_location_override;
|
||||
}
|
||||
if (editable_allow_tracking !== lq__event_badge_obj.allow_tracking) {
|
||||
data_to_update.allow_tracking = editable_allow_tracking;
|
||||
}
|
||||
if (editable_email !== lq__event_badge_obj.email) {
|
||||
data_to_update.email = editable_email;
|
||||
}
|
||||
if (editable_badge_type_code !== lq__event_badge_obj.badge_type_code) {
|
||||
data_to_update.badge_type_code = editable_badge_type_code;
|
||||
}
|
||||
|
||||
if (Object.keys(data_to_update).length === 0) {
|
||||
console.log('No changes to save.');
|
||||
update_status = 'done';
|
||||
update_complete = true;
|
||||
if (!is_review_mode) {
|
||||
edit_mode_active = false;
|
||||
$ae_loc.edit_mode = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await events_func.update_ae_obj__event_badge({
|
||||
api_cfg: $ae_api,
|
||||
event_badge_id: lq__event_badge_obj.event_badge_id_random,
|
||||
data_kv: data_to_update,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
update_status = 'done';
|
||||
update_complete = true;
|
||||
if (!is_review_mode) {
|
||||
edit_mode_active = false;
|
||||
$ae_loc.edit_mode = false;
|
||||
}
|
||||
// Optionally, refresh the lq__event_badge_obj if needed, though Dexie might handle it
|
||||
} catch (error) {
|
||||
console.error('Error saving changes:', error);
|
||||
update_status = 'error';
|
||||
update_complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
editable_location_override = 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;
|
||||
}
|
||||
if (!is_review_mode) {
|
||||
edit_mode_active = false;
|
||||
$ae_loc.edit_mode = false;
|
||||
}
|
||||
update_status = 'idle';
|
||||
update_complete = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!--
|
||||
@@ -482,42 +489,77 @@ onkeypress={() => {
|
||||
transition-all group
|
||||
flex flex-col gap-1 items-center justify-center
|
||||
"
|
||||
class:preset-outlined-warning-200-800={$ae_loc.edit_mode}
|
||||
class:preset-tonal-warning={$ae_loc.edit_mode}
|
||||
class:preset-outlined-warning-200-800={edit_mode_active}
|
||||
class:preset-tonal-warning={edit_mode_active}
|
||||
>
|
||||
<button
|
||||
class="
|
||||
btn btn-sm text-xs
|
||||
preset-tonal-warning preset-outlined-warning-100-900 hover:preset-filled-secondary-500
|
||||
transition-all group
|
||||
"
|
||||
onclick={() => {
|
||||
show_event_badge_tools_modal = true;
|
||||
$ae_loc.edit_mode = !$ae_loc.edit_mode;
|
||||
}}
|
||||
title="Edit Badge Information"
|
||||
>
|
||||
{#if $ae_loc.edit_mode}
|
||||
<span class="fas fa-times m-1"></span>
|
||||
{:else}
|
||||
<span class="fas fa-edit m-1"></span>
|
||||
{/if}
|
||||
<span
|
||||
{#if edit_mode_active}
|
||||
<button
|
||||
class="
|
||||
hidden
|
||||
group-hover:inline-block
|
||||
text-xs
|
||||
btn btn-sm text-xs
|
||||
preset-tonal-success preset-outlined-success-100-900 hover:preset-filled-success-500
|
||||
transition-all group
|
||||
"
|
||||
onclick={handle_save_changes}
|
||||
title="Save Changes"
|
||||
>
|
||||
{#if $ae_loc.edit_mode}
|
||||
Close Edit
|
||||
{:else}
|
||||
<span class="fas fa-save m-1"></span>
|
||||
<span
|
||||
class="
|
||||
hidden
|
||||
group-hover:inline-block
|
||||
text-xs
|
||||
"
|
||||
>
|
||||
Save Changes
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="
|
||||
btn btn-sm text-xs
|
||||
preset-tonal-tertiary preset-outlined-tertiary-100-900 hover:preset-filled-tertiary-500
|
||||
transition-all group
|
||||
"
|
||||
onclick={handle_cancel_changes}
|
||||
title="Cancel Editing"
|
||||
>
|
||||
<span class="fas fa-times m-1"></span>
|
||||
<span
|
||||
class="
|
||||
hidden
|
||||
group-hover:inline-block
|
||||
text-xs
|
||||
"
|
||||
>
|
||||
Cancel
|
||||
</span>
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
class="
|
||||
btn btn-sm text-xs
|
||||
preset-tonal-warning preset-outlined-warning-100-900 hover:preset-filled-secondary-500
|
||||
transition-all group
|
||||
"
|
||||
onclick={() => {
|
||||
edit_mode_active = true;
|
||||
$ae_loc.edit_mode = true;
|
||||
}}
|
||||
title="Edit Badge Information"
|
||||
>
|
||||
<span class="fas fa-edit m-1"></span>
|
||||
<span
|
||||
class="
|
||||
hidden
|
||||
group-hover:inline-block
|
||||
text-xs
|
||||
"
|
||||
>
|
||||
Edit Badge Information
|
||||
{/if}
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<div class="w-md max-w-lg m-1 p-1" class:hidden={!$ae_loc.edit_mode}>
|
||||
<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.
|
||||
@@ -599,78 +641,97 @@ onkeypress={() => {
|
||||
<!-- <span class="float-right text-sm italic m-2">
|
||||
{longest_full_name_override_part}× char
|
||||
</span> -->
|
||||
<!-- {#if $lq__event_badge_obj.title_names}<span class="title_names">{$lq__event_badge_obj.title_names}</span>{/if} -->
|
||||
|
||||
<span class="full_name_override">
|
||||
{#if full_name_override}
|
||||
{@html full_name_override.trim()}
|
||||
{:else}
|
||||
-- no name --
|
||||
{/if}
|
||||
</span>
|
||||
|
||||
<!-- {#if $lq__event_badge_obj.designations}<span class="designations">{$lq__event_badge_obj.designations}</span>{/if} -->
|
||||
{#if edit_mode_active}
|
||||
<input type="text" bind:value={editable_full_name_override} class="input w-full text-center" />
|
||||
{:else}
|
||||
<span class="full_name_override">
|
||||
{#if editable_full_name_override}
|
||||
{@html editable_full_name_override.trim()}
|
||||
{:else}
|
||||
-- no name --
|
||||
{/if}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if professional_title_override}
|
||||
{#if editable_professional_title_override || edit_mode_active}
|
||||
<div
|
||||
class="professional_title
|
||||
{professional_title_class_size} leading-none
|
||||
italic
|
||||
"
|
||||
>
|
||||
{@html professional_title_override}
|
||||
{#if edit_mode_active}
|
||||
<input type="text" bind:value={editable_professional_title_override} class="input w-full text-center" />
|
||||
{:else}
|
||||
{@html editable_professional_title_override}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- {#if $lq__event_badge_obj.pronouns}
|
||||
<div class="pronouns">
|
||||
<span class="pronouns">{@html $lq__event_badge_obj.pronouns}</span>
|
||||
</div>
|
||||
{/if} -->
|
||||
|
||||
<!-- {#if $lq__event_badge_obj.professional_title}
|
||||
<div class="professional_title">
|
||||
<span class="professional_title" class:str_25={$lq__event_badge_obj.professional_title.length>25}>{@html $lq__event_badge_obj.professional_title}</span>
|
||||
</div>
|
||||
{/if} -->
|
||||
|
||||
{#if affiliations_override || location_override}
|
||||
{#if editable_affiliations_override || editable_location_override || edit_mode_active || editable_email || edit_mode_active || editable_allow_tracking !== null || edit_mode_active}
|
||||
<div
|
||||
class="affiliations_location
|
||||
max-h-[3.0in] m-0 p-0
|
||||
hover:outline-2 hover:outline-dashed hover:outline-gray-500/75
|
||||
"
|
||||
>
|
||||
{#if affiliations_override}
|
||||
{#if editable_affiliations_override || edit_mode_active}
|
||||
<div
|
||||
class="affiliations
|
||||
{affiliations_class_size} leading-none
|
||||
"
|
||||
>
|
||||
{@html affiliations_override}
|
||||
{#if edit_mode_active}
|
||||
<textarea bind:value={editable_affiliations_override} class="textarea w-full text-center" rows="2"></textarea>
|
||||
{:else}
|
||||
{@html editable_affiliations_override}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if location_override}
|
||||
{#if editable_location_override || edit_mode_active}
|
||||
<div
|
||||
class="location
|
||||
{location_class_size} leading-none
|
||||
"
|
||||
>
|
||||
<span class="city state_province country"
|
||||
>{@html location_override}</span
|
||||
>
|
||||
{#if edit_mode_active}
|
||||
<input type="text" bind:value={editable_location_override} class="input w-full text-center" />
|
||||
{:else}
|
||||
<span class="city state_province country"
|
||||
>{@html editable_location_override}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if editable_email || edit_mode_active}
|
||||
<div class="email-field text-sm">
|
||||
{#if edit_mode_active}
|
||||
<label>Email: <input type="email" bind:value={editable_email} class="input w-full" /></label>
|
||||
{:else}
|
||||
Email: {editable_email}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if editable_allow_tracking !== null || edit_mode_active}
|
||||
<div class="allow-tracking-field text-sm flex items-center justify-center gap-2">
|
||||
{#if edit_mode_active}
|
||||
<label>Allow Tracking: <input type="checkbox" bind:checked={editable_allow_tracking} class="checkbox" /></label>
|
||||
{:else}
|
||||
Allow Tracking: {editable_allow_tracking ? 'Yes' : 'No'}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if ['front_bool', 'front_back_bool'].includes(option_ticket_1_display_opt) || ['front_bool', 'front_back_bool'].includes(option_ticket_2_display_opt) || ['front_bool', 'front_back_bool'].includes(option_ticket_3_display_opt) || $lq__event_badge_template_obj.show_qr_front}
|
||||
{#if ['front_bool', 'front_back_bool'].includes(option_ticket_1_display_opt) || ['front_bool', 'front_back_bool'].includes(option_ticket_2_display_opt) || ['front_bool', 'front_back_bool'].includes(option_ticket_3_display_opt) || $lq__event_badge_template_obj.show_qr_front || edit_mode_active}
|
||||
<div class="special">
|
||||
<span class="badge_body_special_left">
|
||||
<!-- {#if option_ticket_1_override}<span class="ticket_1_code fg_red fas fa-star"></span>{/if} -->
|
||||
{#if option_ticket_1_override}<span
|
||||
class="ticket_1_code fg_green fas fa-star"
|
||||
></span>{/if}
|
||||
@@ -678,7 +739,6 @@ onkeypress={() => {
|
||||
<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_gold fas fa-star"></span> -->
|
||||
{/if}
|
||||
{#if option_ticket_3_override}
|
||||
<span class="ticket_3_code fg_blue fas fa-star"></span>
|
||||
@@ -704,7 +764,7 @@ onkeypress={() => {
|
||||
|
||||
<div
|
||||
class="badge_footer
|
||||
{use_badge_type_code.toLowerCase()}
|
||||
{editable_badge_type_code?.toLowerCase()}
|
||||
justify-self-end
|
||||
min-h-[.25in]
|
||||
max-h-[.50in]
|
||||
@@ -714,34 +774,41 @@ onkeypress={() => {
|
||||
flex flex-row gap-1 items-center justify-center
|
||||
hover:outline-2 hover:outline-dashed hover:outline-gray-500/75
|
||||
"
|
||||
title={use_badge_type_code}
|
||||
title={editable_badge_type_code}
|
||||
>
|
||||
THE FOOTER
|
||||
{#if option_other_1_override && ['front_bool', 'front_back_bool'].includes(option_other_1_display_opt)}
|
||||
<span class="badge_footer_special_left"
|
||||
><span class="fas fa-biohazard"></span></span
|
||||
{#if edit_mode_active && badge_type_code_li}
|
||||
<label>Badge Type:
|
||||
<select bind:value={editable_badge_type_code} class="select text-xs px-1 max-w-fit">
|
||||
{#each badge_type_code_li as badge_type_code_item}
|
||||
<option value={badge_type_code_item.code}>{badge_type_code_item.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
{:else}
|
||||
THE FOOTER
|
||||
{#if option_other_1_override && ['front_bool', 'front_back_bool'].includes(option_other_1_display_opt)}
|
||||
<span class="badge_footer_special_left"
|
||||
><span class="fas fa-biohazard"></span></span
|
||||
>
|
||||
{:else if option_other_1_override && ['front_html', 'front_back_html'].includes(option_other_1_display_opt)}
|
||||
<span class="badge_footer_special_left">{@html option_other_1_override}</span>
|
||||
{/if}
|
||||
|
||||
<span class="badge_footer_center {editable_badge_type_code?.toLowerCase()}"
|
||||
>{editable_badge_type_code}</span
|
||||
>
|
||||
{:else if option_other_1_override && ['front_html', 'front_back_html'].includes(option_other_1_display_opt)}
|
||||
<span class="badge_footer_special_left">{@html option_other_1_override}</span>
|
||||
{/if}
|
||||
|
||||
<span class="badge_footer_center {use_badge_type_code.toLowerCase()}"
|
||||
>{@html use_badge_type}</span
|
||||
>
|
||||
|
||||
<!-- {#if $lq__event_badge_obj.other_2}
|
||||
<span class="badge_footer_special_right"><span class="fas fa-star-of-life"></span></span>
|
||||
{/if} -->
|
||||
|
||||
{#if option_other_2_override && ['front_bool', 'front_back_bool'].includes(option_other_2_display_opt)}
|
||||
<span class="badge_footer_special_right"
|
||||
><span class="fas fa-star-of-life"></span></span
|
||||
>
|
||||
{:else if option_other_2_override && ['front_html', 'front_back_html'].includes(option_other_2_display_opt)}
|
||||
<span class="badge_footer_special_right">{@html option_other_2_override}</span>
|
||||
{#if option_other_2_override && ['front_bool', 'front_back_bool'].includes(option_other_2_display_opt)}
|
||||
<span class="badge_footer_special_right"
|
||||
><span class="fas fa-star-of-life"></span></span
|
||||
>
|
||||
{:else if option_other_2_override && ['front_html', 'front_back_html'].includes(option_other_2_display_opt)}
|
||||
<span class="badge_footer_special_right">{@html option_other_2_override}</span>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
<!-- {#if $lq__event_badge_template_obj.show_qr_front}
|
||||
<div class="container qr_code">
|
||||
{#await initial_loading_promise}
|
||||
|
||||
@@ -53,72 +53,114 @@
|
||||
|
||||
<ul class="list-disc list-inside">
|
||||
{#each $lq__event_badge_obj_li as event_badge_obj (event_badge_obj.event_badge_id_random)}
|
||||
<li
|
||||
class="
|
||||
border-b border-gray-300 dark:border-gray-600 py-0.5
|
||||
flex flex-row gap-1 items-center justify-between w-full
|
||||
"
|
||||
>
|
||||
<a
|
||||
href={`/events/${event_badge_obj.event_id}/badges/${event_badge_obj.event_badge_id}`}
|
||||
class="flex flex-row gap-1 items-center justify-start min-w-fit"
|
||||
title={`Badge: ${event_badge_obj.full_name ?? event_badge_obj.given_name ?? '-- no name --'}\nID: ${event_badge_obj.event_badge_id}`}
|
||||
{#if !event_badge_obj.hide || trusted_access}
|
||||
<li
|
||||
class="
|
||||
border-b border-gray-300 dark:border-gray-600 py-0.5
|
||||
flex flex-row gap-1 items-center justify-between w-full
|
||||
"
|
||||
>
|
||||
<span>
|
||||
{#if event_badge_obj.hide}
|
||||
<span class="fas fa-eye-slash mx-1"></span>
|
||||
{:else}
|
||||
<span class="fas fa-id-badge mx-1"></span>
|
||||
{/if}
|
||||
{#if event_badge_obj.print_count >= 1}
|
||||
<!-- Show a green checkmark -->
|
||||
<span class="fas fa-check text-green-500"></span>
|
||||
{#if event_badge_obj.print_count < 1 || trusted_access}
|
||||
<a
|
||||
href={`/events/${event_badge_obj.event_id}/badges/${event_badge_obj.event_badge_id}`}
|
||||
class="flex flex-row gap-1 items-center justify-start min-w-fit"
|
||||
title={`Badge: ${event_badge_obj.full_name ?? event_badge_obj.given_name ?? '-- no name --'}\nID: ${event_badge_obj.event_badge_id}`}
|
||||
>
|
||||
<span>
|
||||
{#if event_badge_obj.hide}
|
||||
<span class="fas fa-eye-slash mx-1"></span>
|
||||
{:else}
|
||||
<span class="fas fa-id-badge mx-1"></span>
|
||||
{/if}
|
||||
{#if event_badge_obj.print_count >= 1}
|
||||
<!-- Show a green checkmark -->
|
||||
<span class="fas fa-check text-green-500"></span>
|
||||
|
||||
<span class="print_count px-1"
|
||||
>{event_badge_obj.print_count}×</span
|
||||
> {/if}
|
||||
</span>
|
||||
|
||||
<span class="font-bold">
|
||||
{#if event_badge_obj.full_name_override}
|
||||
{event_badge_obj.full_name_override}
|
||||
{:else if event_badge_obj.full_name}
|
||||
{event_badge_obj.full_name}
|
||||
{:else if event_badge_obj.given_name}
|
||||
{event_badge_obj.given_name} {event_badge_obj.family_name}
|
||||
{:else}
|
||||
-- no name --
|
||||
{/if}
|
||||
</span>
|
||||
</a>
|
||||
{:else}
|
||||
<span
|
||||
class="flex flex-row gap-1 items-center justify-start min-w-fit"
|
||||
title={`Badge: ${event_badge_obj.full_name ?? event_badge_obj.given_name ?? '-- no name --'}\nID: ${event_badge_obj.event_badge_id}`}
|
||||
>
|
||||
<span>
|
||||
{#if event_badge_obj.hide}
|
||||
<span class="fas fa-eye-slash mx-1"></span>
|
||||
{:else}
|
||||
<span class="fas fa-id-badge mx-1"></span>
|
||||
{/if}
|
||||
{#if event_badge_obj.print_count >= 1}
|
||||
<!-- Show a green checkmark -->
|
||||
<span class="fas fa-check text-green-500"></span>
|
||||
|
||||
<span class="print_count px-1"
|
||||
>{event_badge_obj.print_count}×</span
|
||||
> {/if}
|
||||
</span>
|
||||
|
||||
<span class="font-bold">
|
||||
{#if event_badge_obj.full_name_override}
|
||||
{event_badge_obj.full_name_override}
|
||||
{:else if event_badge_obj.full_name}
|
||||
{event_badge_obj.full_name}
|
||||
{:else if event_badge_obj.given_name}
|
||||
{event_badge_obj.given_name} {event_badge_obj.family_name}
|
||||
{:else}
|
||||
-- no name --
|
||||
{/if}
|
||||
</span>
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
{#if show_sensitive_fields}
|
||||
-
|
||||
<span class="min-w-fit">
|
||||
<span class="fas fa-envelope"></span>
|
||||
{#if trusted_access}
|
||||
<span class="print_count preset-tonal-warning px-1"
|
||||
>{event_badge_obj.print_count}×</span
|
||||
>
|
||||
{event_badge_obj.email}
|
||||
{:else}
|
||||
{event_badge_obj.email
|
||||
? event_badge_obj.email.replace(/^(.{3}).*@/, '$1...@')
|
||||
: ''}
|
||||
{/if}
|
||||
{/if}
|
||||
</span>
|
||||
</span>
|
||||
{/if}
|
||||
{#if !hide_affiliations}
|
||||
-
|
||||
{event_badge_obj?.affiliations ?? '-- no affiliations --'}
|
||||
{/if}
|
||||
{#if !hide_location}
|
||||
-
|
||||
{event_badge_obj?.location ?? '-- no location --'}
|
||||
{/if}
|
||||
{#if !hide_badge_type}
|
||||
-
|
||||
<span class="italic">{event_badge_obj?.badge_type}</span>
|
||||
{/if}
|
||||
|
||||
<span class="font-bold">
|
||||
{#if event_badge_obj.full_name_override}
|
||||
{event_badge_obj.full_name_override}
|
||||
{:else if event_badge_obj.full_name}
|
||||
{event_badge_obj.full_name}
|
||||
{:else if event_badge_obj.given_name}
|
||||
{event_badge_obj.given_name} {event_badge_obj.family_name}
|
||||
{:else}
|
||||
-- no name --
|
||||
{/if}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{#if show_sensitive_fields}
|
||||
-
|
||||
<span class="min-w-fit">
|
||||
<!-- The email should only be the first 3 chars and then @domain name. -->
|
||||
<!-- Example: original: scott.idem@oneskyit.com obscured: sco...@oneskyit.com -->
|
||||
<span class="fas fa-envelope"></span>
|
||||
{event_badge_obj.email
|
||||
? event_badge_obj.email.replace(/^(.{3}).*@/, '$1...@')
|
||||
: ''}
|
||||
</span>
|
||||
{/if}
|
||||
{#if !hide_affiliations}
|
||||
-
|
||||
{event_badge_obj?.affiliations ?? '-- no affiliations --'}
|
||||
{/if}
|
||||
{#if !hide_location}
|
||||
-
|
||||
{event_badge_obj?.location ?? '-- no location --'}
|
||||
{/if}
|
||||
{#if !hide_badge_type}
|
||||
-
|
||||
<span class="italic">{event_badge_obj?.badge_type}</span>
|
||||
{/if}
|
||||
</li>
|
||||
{#if trusted_access}
|
||||
<a
|
||||
href={`/events/${event_badge_obj.event_id}/badges/${event_badge_obj.event_badge_id}#review`}
|
||||
class="btn btn-sm variant-soft-primary">Review</a
|
||||
>
|
||||
{/if}
|
||||
</li>
|
||||
{/if}
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
<script lang="ts">
|
||||
import { liveQuery } from 'dexie';
|
||||
import { events_func } from '$lib/ae_events_functions';
|
||||
import { ae_api } from '$lib/stores/ae_stores';
|
||||
import { events_slct } from '$lib/stores/ae_events_stores';
|
||||
import Comp_badge_obj_view from '../[badge_id]/ae_comp__badge_obj_view.svelte';
|
||||
|
||||
interface Props {
|
||||
data: any; // PageData from SvelteKit
|
||||
}
|
||||
|
||||
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 lq__filtered_badges = $derived(
|
||||
liveQuery(async () => {
|
||||
const filters: { printed_status?: string; type_code?: string } = {};
|
||||
if (printed_status_filter) filters.printed_status = printed_status_filter;
|
||||
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({
|
||||
api_cfg: $ae_api,
|
||||
event_id: event_id,
|
||||
limit: 5000, // A high limit to fetch all relevant badges for printing
|
||||
...filters,
|
||||
log_lvl: 0
|
||||
});
|
||||
return result || [];
|
||||
})
|
||||
);
|
||||
|
||||
// Function to trigger browser print
|
||||
function trigger_print() {
|
||||
window.print();
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Bulk Print Badges for Event {event_id}</title>
|
||||
<style>
|
||||
/* Print-specific styles */
|
||||
@media print {
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.print-button {
|
||||
display: none;
|
||||
}
|
||||
/* Customize how badges are laid out for printing */
|
||||
.badge-print-container {
|
||||
page-break-after: always; /* Each badge on a new page or arrange multiple per page */
|
||||
/* Adjust width/height for optimal badge size on print media */
|
||||
width: 4in; /* Example width */
|
||||
height: 6in; /* Example height */
|
||||
margin: 0.25in; /* Example margin */
|
||||
border: 1px solid #ccc; /* Optional: for visual separation on print */
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</svelte:head>
|
||||
|
||||
<section class="p-4">
|
||||
<h1 class="h1">Bulk Print Badges</h1>
|
||||
|
||||
<div class="print-button my-4">
|
||||
<button class="btn btn-primary" onclick={trigger_print}>
|
||||
<span class="fas fa-print mr-2"></span> Print Badges
|
||||
</button>
|
||||
<a href={`/events/${event_id}/badges`} class="btn btn-tertiary ml-2">
|
||||
<span class="fas fa-arrow-left mr-2"></span> Back to Search
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{#await lq__filtered_badges}
|
||||
<p>Loading badges for printing...</p>
|
||||
{:then badges_to_print}
|
||||
{#if badges_to_print.length > 0}
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{#each badges_to_print as badge_obj (badge_obj.event_badge_id_random)}
|
||||
<div class="badge-print-container">
|
||||
<Comp_badge_obj_view
|
||||
event_id={event_id}
|
||||
event_badge_id={badge_obj.event_badge_id_random}
|
||||
lq__event_badge_obj={badge_obj}
|
||||
is_review_mode={false}
|
||||
log_lvl={0}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<p>No badges found matching your criteria for printing.</p>
|
||||
{/if}
|
||||
{:catch error}
|
||||
<p class="text-error-500">Error loading badges: {error.message}</p>
|
||||
{/await}
|
||||
</section>
|
||||
136
src/routes/events/[event_id]/(badges)/templates/+page.svelte
Normal file
136
src/routes/events/[event_id]/(badges)/templates/+page.svelte
Normal file
@@ -0,0 +1,136 @@
|
||||
<script lang="ts">
|
||||
import { liveQuery } from 'dexie';
|
||||
import { events_func } from '$lib/ae_events_functions';
|
||||
import { ae_api } from '$lib/stores/ae_stores';
|
||||
import { events_slct } from '$lib/stores/ae_events_stores';
|
||||
import { Modal } from '@skeletonlabs/skeleton';
|
||||
import Comp_badge_template_form from './ae_comp__badge_template_form.svelte';
|
||||
|
||||
interface Props {
|
||||
data: any; // PageData from SvelteKit
|
||||
}
|
||||
|
||||
let { data }: Props = $props();
|
||||
|
||||
let event_id: string = data.params.event_id;
|
||||
|
||||
let show_create_template_modal: boolean = $state(false);
|
||||
let selected_template_id: string | null = $state(null);
|
||||
let show_edit_template_modal: boolean = $state(false);
|
||||
|
||||
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
|
||||
});
|
||||
return result || [];
|
||||
})
|
||||
);
|
||||
|
||||
function handle_create_success() {
|
||||
show_create_template_modal = false;
|
||||
// Trigger a refresh of the list (by updating a store or re-fetching)
|
||||
// For now, relying on liveQuery to react to DB changes
|
||||
}
|
||||
|
||||
function handle_edit_success() {
|
||||
show_edit_template_modal = false;
|
||||
selected_template_id = null;
|
||||
// Trigger a refresh of the list
|
||||
}
|
||||
|
||||
function handle_cancel() {
|
||||
show_create_template_modal = false;
|
||||
show_edit_template_modal = false;
|
||||
selected_template_id = null;
|
||||
}
|
||||
|
||||
function edit_template(template_id: string) {
|
||||
selected_template_id = template_id;
|
||||
show_edit_template_modal = true;
|
||||
}
|
||||
|
||||
async function delete_template(template_id: string) {
|
||||
if (confirm('Are you sure you want to delete this badge template? This action cannot be undone.')) {
|
||||
try {
|
||||
await events_func.delete_ae_obj_id__event_badge_template({
|
||||
api_cfg: $ae_api,
|
||||
event_badge_template_id: template_id
|
||||
});
|
||||
// Rely on liveQuery to refresh list
|
||||
} catch (error) {
|
||||
console.error('Error deleting template:', error);
|
||||
alert('Failed to delete template.');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Badge Templates - Event {event_id}</title>
|
||||
</svelte:head>
|
||||
|
||||
<section class="p-4">
|
||||
<h1 class="h1">Badge Templates</h1>
|
||||
|
||||
<div class="my-4 flex justify-end">
|
||||
<button class="btn btn-primary" onclick={() => show_create_template_modal = true}>
|
||||
<span class="fas fa-plus mr-2"></span> Add New Template
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#await lq__badge_templates}
|
||||
<p>Loading badge templates...</p>
|
||||
{:then templates}
|
||||
{#if templates.length > 0}
|
||||
<div class="card p-4">
|
||||
<ul class="list-group">
|
||||
{#each templates as template (template.event_badge_template_id_random)}
|
||||
<li class="list-group-item flex justify-between items-center">
|
||||
<span>{template.name}</span>
|
||||
<div>
|
||||
<button class="btn btn-sm variant-filled-primary" onclick={() => edit_template(template.event_badge_template_id_random)}>
|
||||
<span class="fas fa-edit"></span> Edit
|
||||
</button>
|
||||
<button class="btn btn-sm variant-filled-error ml-2" onclick={() => delete_template(template.event_badge_template_id_random)}>
|
||||
<span class="fas fa-trash"></span> Delete
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
{:else}
|
||||
<p>No badge templates found for this event. Click "Add New Template" to create one.</p>
|
||||
{/if}
|
||||
{:catch error}
|
||||
<p class="text-error-500">Error loading templates: {error.message}</p>
|
||||
{/await}
|
||||
</section>
|
||||
|
||||
{#if show_create_template_modal}
|
||||
<Modal bind:show={show_create_template_modal}>
|
||||
<div class="card p-4">
|
||||
<Comp_badge_template_form
|
||||
event_id={event_id}
|
||||
on:success={handle_create_success}
|
||||
on:cancel={handle_cancel}
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
{/if}
|
||||
|
||||
{#if show_edit_template_modal}
|
||||
<Modal bind:show={show_edit_template_modal}>
|
||||
<div class="card p-4">
|
||||
<Comp_badge_template_form
|
||||
event_id={event_id}
|
||||
template_id={selected_template_id}
|
||||
on:success={handle_edit_success}
|
||||
on:cancel={handle_cancel}
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
{/if}
|
||||
@@ -0,0 +1,204 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { events_func } from '$lib/ae_events_functions';
|
||||
import { ae_api } from '$lib/stores/ae_stores';
|
||||
|
||||
interface Props {
|
||||
event_id: string;
|
||||
template_id?: string | null; // Null for creation, string for editing
|
||||
}
|
||||
|
||||
let { event_id, template_id = null }: Props = $props();
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
// Form fields
|
||||
let name: string = '';
|
||||
let header_path: string = '';
|
||||
let logo_path: string = '';
|
||||
let header_row_1: string = '';
|
||||
let header_row_2: string = '';
|
||||
let secondary_header_path: string = '';
|
||||
let footer_text: string = '';
|
||||
let show_qr_front: boolean = true;
|
||||
let show_qr_back: boolean = true;
|
||||
let wireless_ssid: string = '';
|
||||
let wireless_password: string = '';
|
||||
let ticket_1_text: string = '';
|
||||
let ticket_2_text: string = '';
|
||||
let ticket_3_text: string = '';
|
||||
|
||||
let submit_status: string = 'idle'; // idle, loading, success, error
|
||||
|
||||
// Load template data if in edit mode
|
||||
$effect(async () => {
|
||||
if (template_id) {
|
||||
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: template_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 || '';
|
||||
footer_text = template_obj.footer_text || '';
|
||||
show_qr_front = template_obj.show_qr_front ?? true;
|
||||
show_qr_back = template_obj.show_qr_back ?? true;
|
||||
wireless_ssid = template_obj.wireless_ssid || '';
|
||||
wireless_password = template_obj.wireless_password || '';
|
||||
ticket_1_text = template_obj.ticket_1_text || '';
|
||||
ticket_2_text = template_obj.ticket_2_text || '';
|
||||
ticket_3_text = template_obj.ticket_3_text || '';
|
||||
submit_status = 'idle';
|
||||
} else {
|
||||
submit_status = 'error';
|
||||
console.error('Template not found for editing.');
|
||||
}
|
||||
} catch (error) {
|
||||
submit_status = 'error';
|
||||
console.error('Error loading template for editing:', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
async function handle_submit() {
|
||||
submit_status = 'loading';
|
||||
const data_to_save: key_val = {
|
||||
name,
|
||||
header_path,
|
||||
logo_path,
|
||||
header_row_1,
|
||||
header_row_2,
|
||||
secondary_header_path,
|
||||
footer_text,
|
||||
show_qr_front,
|
||||
show_qr_back,
|
||||
wireless_ssid,
|
||||
wireless_password,
|
||||
ticket_1_text,
|
||||
ticket_2_text,
|
||||
ticket_3_text
|
||||
};
|
||||
|
||||
try {
|
||||
let result;
|
||||
if (template_id) {
|
||||
result = await events_func.update_ae_obj__event_badge_template({
|
||||
api_cfg: $ae_api,
|
||||
event_badge_template_id: template_id,
|
||||
data_kv: data_to_save
|
||||
});
|
||||
} else {
|
||||
result = await events_func.create_ae_obj__event_badge_template({
|
||||
api_cfg: $ae_api,
|
||||
event_id: event_id,
|
||||
data_kv: data_to_save
|
||||
});
|
||||
}
|
||||
|
||||
if (result) {
|
||||
submit_status = 'success';
|
||||
dispatch('success', result);
|
||||
} else {
|
||||
submit_status = 'error';
|
||||
dispatch('error', 'Failed to save template');
|
||||
}
|
||||
} catch (error) {
|
||||
submit_status = 'error';
|
||||
console.error('Error saving template:', error);
|
||||
dispatch('error', error);
|
||||
}
|
||||
}
|
||||
|
||||
function handle_cancel() {
|
||||
dispatch('cancel');
|
||||
}
|
||||
</script>
|
||||
|
||||
<form onsubmit|preventDefault={handle_submit} class="p-4 space-y-4">
|
||||
<h3 class="h3">{template_id ? 'Edit' : 'Create New'} Badge Template</h3>
|
||||
|
||||
<label class="label">
|
||||
<span>Template Name</span>
|
||||
<input type="text" bind:value={name} class="input" required />
|
||||
</label>
|
||||
|
||||
<label class="label">
|
||||
<span>Header Path (URL)</span>
|
||||
<input type="text" bind:value={header_path} class="input" />
|
||||
</label>
|
||||
<label class="label">
|
||||
<span>Logo Path (URL, if no Header Path)</span>
|
||||
<input type="text" bind:value={logo_path} class="input" />
|
||||
</label>
|
||||
<label class="label">
|
||||
<span>Header Row 1 Text (HTML allowed)</span>
|
||||
<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>
|
||||
</label>
|
||||
<label class="label">
|
||||
<span>Secondary Header Path (URL, back of badge)</span>
|
||||
<input type="text" bind:value={secondary_header_path} class="input" />
|
||||
</label>
|
||||
|
||||
<label class="label">
|
||||
<span>Footer Text (HTML allowed)</span>
|
||||
<textarea bind:value={footer_text} class="textarea" rows="2"></textarea>
|
||||
</label>
|
||||
|
||||
<label class="label flex items-center gap-2">
|
||||
<input type="checkbox" bind:checked={show_qr_front} class="checkbox" />
|
||||
<span>Show QR Code on Front</span>
|
||||
</label>
|
||||
<label class="label flex items-center gap-2">
|
||||
<input type="checkbox" bind:checked={show_qr_back} class="checkbox" />
|
||||
<span>Show QR Code on Back</span>
|
||||
</label>
|
||||
|
||||
<label class="label">
|
||||
<span>Wireless SSID</span>
|
||||
<input type="text" bind:value={wireless_ssid} class="input" />
|
||||
</label>
|
||||
<label class="label">
|
||||
<span>Wireless Password</span>
|
||||
<input type="text" bind:value={wireless_password} class="input" />
|
||||
</label>
|
||||
|
||||
<label class="label">
|
||||
<span>Ticket 1 Text (HTML allowed)</span>
|
||||
<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>
|
||||
</label>
|
||||
<label class="label">
|
||||
<span>Ticket 3 Text (HTML allowed)</span>
|
||||
<textarea bind:value={ticket_3_text} class="textarea" rows="2"></textarea>
|
||||
</label>
|
||||
|
||||
<div class="flex justify-end gap-2">
|
||||
<button type="button" class="btn variant-filled-tertiary" onclick={handle_cancel} disabled={submit_status === 'loading'}>Cancel</button>
|
||||
<button type="submit" class="btn variant-filled-primary" disabled={submit_status === 'loading'}>
|
||||
{#if submit_status === 'loading'}
|
||||
<span class="fas fa-spinner fa-spin mr-2"></span>
|
||||
{/if}
|
||||
{template_id ? 'Save Changes' : 'Create Template'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{#if submit_status === 'success'}
|
||||
<p class="text-green-500">Template saved successfully!</p>
|
||||
{:else if submit_status === 'error'}
|
||||
<p class="text-red-500">Error saving template. Please try again.</p>
|
||||
{/if}
|
||||
@@ -1331,7 +1331,7 @@
|
||||
bodyClass="p-0 space-y-0 overflow-y-auto flex flex-col gap-1 items-center justify-center"
|
||||
headerClass={`fixed top-0 right-0 left-0 p-1 md:p-2 flex flex-row items-center ${$events_loc.launcher.controller == 'remote' ? 'hidden' : ''} bg-white dark:bg-gray-800 opacity-50 ${$events_loc.launcher.hide__modal_header_title ? 'justify-center' : 'justify-between'}`}
|
||||
footerClass="text-center hidden"
|
||||
onclose={async () => {
|
||||
on:close={async () => {
|
||||
$events_sess.launcher.modal__open_event_file_id = null;
|
||||
if (
|
||||
$events_loc.launcher.controller == 'local_push' &&
|
||||
|
||||
Reference in New Issue
Block a user