refactor: v2 badge render display-only + print button to controls panel
- ae_comp__badge_obj_view_v2.svelte: removed all inline edit-mode logic (floating Edit/Save/Cancel panel, placeholder list, input fields, save/cancel functions). V2 is now purely a display component — editing happens in the right panel (ae_comp__badge_print_controls.svelte) via liveQuery reactivity. display_* values are now $derived directly from lq__event_badge_obj. Fixes effective_badge_type_code CSS class (was always empty in previous v2). - ae_comp__badge_print_controls.svelte: added "Print Badge" button at the top of the panel. Increments print_count, fires window.print(), then navigates to badge search. This is now the canonical print action for v2; the header "Print Now" button is a shortcut that calls window.print() only (no count tracking). Clarified $ae_loc.edit_mode comment — global AE Edit Mode is not a badge-specific edit toggle; used here only to gate reprints. - print/+page.svelte: added clarifying comments on is_edit_mode (global vs local) and the header "Print Now" button (shortcut only, no count tracking). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,8 @@
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
|
||||
import { events_func } from '$lib/ae_events_functions';
|
||||
import { Pencil, Check, X, LoaderCircle, ChevronDown } from 'lucide-svelte';
|
||||
import { browser } from '$app/environment';
|
||||
import { Pencil, Check, X, LoaderCircle, ChevronDown, Printer } from 'lucide-svelte';
|
||||
|
||||
interface Props {
|
||||
event_id: string;
|
||||
@@ -55,6 +56,58 @@
|
||||
// professional_title_override, affiliations_override, and location_override.
|
||||
let is_trusted = $derived($ae_loc.trusted_access === true);
|
||||
|
||||
// IMPORTANT: $ae_loc.edit_mode is the GLOBAL AE Edit Mode — a UI preference that
|
||||
// reveals editable fields, debug info, and advanced options across the whole app.
|
||||
// It is NOT the same as the badge-specific edit state (which no longer exists in
|
||||
// the v2 badge render — all badge editing happens here in the controls panel).
|
||||
// This component NEVER writes to $ae_loc.edit_mode. Read-only usage only:
|
||||
// — used here to allow reprinting an already-printed badge when global edit mode is active.
|
||||
let is_global_edit_mode = $derived($ae_loc.edit_mode === true);
|
||||
|
||||
// --- Print ---
|
||||
let print_count = $derived($lq__event_badge_obj?.print_count ?? 0);
|
||||
let is_printed = $derived(print_count >= 1);
|
||||
|
||||
// Print is available to Trusted+ when: not yet printed, OR global edit mode is on (reprint).
|
||||
let can_print = $derived(is_trusted && (!is_printed || is_global_edit_mode));
|
||||
|
||||
type PrintStatus = 'idle' | 'loading' | 'done' | 'error';
|
||||
let print_status: PrintStatus = $state('idle');
|
||||
|
||||
async function handle_print_badge() {
|
||||
if (!$lq__event_badge_obj?.event_badge_id) return;
|
||||
print_status = 'loading';
|
||||
|
||||
const now = new Date().toISOString();
|
||||
const is_first_print = print_count === 0;
|
||||
const data_to_update: key_val = {
|
||||
print_count: print_count + 1,
|
||||
print_last_datetime: now
|
||||
};
|
||||
if (is_first_print) data_to_update.print_first_datetime = now;
|
||||
|
||||
try {
|
||||
await events_func.update_ae_obj__event_badge({
|
||||
api_cfg: $ae_api,
|
||||
event_id,
|
||||
event_badge_id: $lq__event_badge_obj.event_badge_id,
|
||||
data_kv: data_to_update,
|
||||
log_lvl
|
||||
});
|
||||
print_status = 'done';
|
||||
// Trigger browser print dialog after count is recorded
|
||||
if (browser) window.print();
|
||||
// Brief success flash, then return to badge search
|
||||
await new Promise<void>(r => setTimeout(r, 1000));
|
||||
// Full navigation back to badge search — avoids goto() lint rule in child components
|
||||
if (browser) window.location.href = `/events/${event_id}/badges`;
|
||||
} catch (err) {
|
||||
console.error('Badge print controls: print error:', err);
|
||||
print_status = 'error';
|
||||
setTimeout(() => { print_status = 'idle'; }, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Badge type list from template ---
|
||||
// Each item: { code: string, name: string }. Used for the badge type dropdown.
|
||||
let badge_type_code_li = $derived.by((): { code: string; name: string }[] => {
|
||||
@@ -265,6 +318,45 @@
|
||||
<!-- ============================================================
|
||||
Main panel
|
||||
============================================================ -->
|
||||
|
||||
<!-- Print button — canonical print action for v2. Increments print_count, fires
|
||||
window.print(), then navigates back to badge search. Only shown to Trusted+
|
||||
when not yet printed, OR when global AE Edit Mode is active (allows reprints).
|
||||
The header "Print Now" button is a shortcut that calls window.print() only —
|
||||
it does NOT track print count. Always use this button for the official print. -->
|
||||
{#if can_print}
|
||||
<div class="mb-3 pb-3 border-b border-gray-200 dark:border-gray-700">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm w-full flex items-center justify-center gap-2"
|
||||
class:preset-filled-primary={print_status === 'idle'}
|
||||
class:preset-tonal-surface={print_status === 'loading'}
|
||||
class:preset-filled-success={print_status === 'done'}
|
||||
class:preset-tonal-error={print_status === 'error'}
|
||||
onclick={handle_print_badge}
|
||||
disabled={print_status === 'loading' || print_status === 'done'}
|
||||
title={is_printed ? `Reprint badge (printed ${print_count}×)` : 'Print badge now'}
|
||||
data-testid="badge-print-btn"
|
||||
>
|
||||
{#if print_status === 'loading'}
|
||||
<LoaderCircle size="14" class="animate-spin" /> Printing…
|
||||
{:else if print_status === 'done'}
|
||||
<Check size="14" /> Printed!
|
||||
{:else if print_status === 'error'}
|
||||
Error — try again
|
||||
{:else}
|
||||
<Printer size="14" />
|
||||
{is_printed ? `Reprint (${print_count}×)` : 'Print Badge'}
|
||||
{/if}
|
||||
</button>
|
||||
{#if is_printed && print_status === 'idle'}
|
||||
<p class="text-[10px] text-amber-600 dark:text-amber-400 text-center mt-1">
|
||||
Already printed {print_count}×
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="space-y-2 text-sm">
|
||||
|
||||
<!-- === NAME === -->
|
||||
|
||||
@@ -52,6 +52,11 @@
|
||||
|
||||
// Access level shortcuts
|
||||
let is_trusted = $derived($ae_loc.trusted_access === true);
|
||||
|
||||
// IMPORTANT: $ae_loc.edit_mode is the GLOBAL AE Edit Mode — a UI preference that
|
||||
// reveals editable fields, debug info, and advanced options app-wide. It is NOT
|
||||
// a badge-specific edit toggle. Never write to it from badge components.
|
||||
// Used here only to gate the header "Print Now" shortcut (allow reprints in edit mode).
|
||||
let is_edit_mode = $derived($ae_loc.edit_mode === true);
|
||||
|
||||
// Print state derived from badge
|
||||
@@ -186,7 +191,11 @@
|
||||
{use_v2 ? 'v2' : 'v1'}
|
||||
</button>
|
||||
|
||||
<!-- 1. Print Now: Trusted+, not printed OR Edit Mode (reprint) -->
|
||||
<!-- 1. Print Now (header shortcut): calls window.print() only — does NOT track
|
||||
print_count. The canonical "Print Badge" button in the right panel controls
|
||||
increments the count, fires window.print(), then redirects to badge search.
|
||||
Use this header button only as a quick re-trigger of the print dialog. -->
|
||||
<!-- Trusted+, not printed OR global Edit Mode active (reprint) -->
|
||||
{#if is_trusted && (!is_printed || is_edit_mode)}
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user