From cc04411d23193b31a1ab59c0d627725bb62f352d Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Mon, 8 Jun 2026 20:28:33 -0400 Subject: [PATCH] feat(badges): goto() after print with per-device fallback toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch post-print navigation from window.location.href to goto() for faster SvelteKit client-side transition back to Badge Search (no full reload). A nav_to_badges() helper in print controls branches on badges_loc.print_nav_use_goto (default true). Badges Config page gains a "Local Device Settings" section with a checkbox to disable goto() and fall back to hard reload — stored in localStorage per browser, not synced to the event. Useful as an on-site escape hatch without a code deploy. Also fixes the Templates button on the config page: adds the standard border border-surface-300-700 so it looks like a button. Co-Authored-By: Claude Sonnet 4.6 --- .../ae_events_stores__badges_defaults.ts | 7 +++- .../ae_comp__badge_print_controls.svelte | 23 +++++++++--- .../(badges)/badges/config/+page.svelte | 35 +++++++++++++++++-- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/lib/stores/ae_events_stores__badges_defaults.ts b/src/lib/stores/ae_events_stores__badges_defaults.ts index e8ab0eb3..4a2e9daf 100644 --- a/src/lib/stores/ae_events_stores__badges_defaults.ts +++ b/src/lib/stores/ae_events_stores__badges_defaults.ts @@ -138,6 +138,10 @@ export interface BadgesLocState { trusted_search_min_chars: number; // Timestamp when the remote config was last mirrored locally remote_cfg_last_synced_on: string | null; + // After-print navigation method. true (default) = SvelteKit goto() — faster, no full reload. + // false = window.location.href — full page reload, use as a fallback if goto causes issues. + // Per-device: stored in localStorage, not synced to the event config. + print_nav_use_goto: boolean; } export interface BadgesSessState { @@ -203,7 +207,8 @@ export const badges_loc_defaults: BadgesLocState = { auth_search_min_chars: 2, trusted_search_result_limit: 150, trusted_search_min_chars: 1, - remote_cfg_last_synced_on: null + remote_cfg_last_synced_on: null, + print_nav_use_goto: true }; // In-memory badge state — resets on page load. diff --git a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_print_controls.svelte b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_print_controls.svelte index be69be9f..0e8889f6 100644 --- a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_print_controls.svelte +++ b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_print_controls.svelte @@ -22,6 +22,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/ae_events_functions'; import { browser } from '$app/environment'; +import { goto } from '$app/navigation'; +import { badges_loc } from '$lib/stores/ae_events_stores__badges.svelte'; import { Check, ChevronDown, @@ -211,6 +213,19 @@ let can_print = $derived((is_public && !is_printed) || (is_trusted && is_global_ type PrintStatus = 'idle' | 'loading' | 'done' | 'error'; let print_status: PrintStatus = $state('idle'); +// Navigate back to badge search after print completes. +// goto() is the default: faster SvelteKit client-side navigation, no full reload. +// Falls back to window.location.href if badges_loc.print_nav_use_goto is disabled — +// useful as an on-site escape hatch if the goto() path causes unexpected issues. +function nav_to_badges() { + if (!browser) return; + if (badges_loc.current.print_nav_use_goto) { + goto(`/events/${event_id}/badges`); + } else { + window.location.href = `/events/${event_id}/badges`; + } +} + async function handle_print_badge() { if (!$lq__event_badge_obj?.event_badge_id) return; print_status = 'loading'; @@ -232,7 +247,7 @@ async function handle_print_badge() { if (browser) window.print(); print_status = 'error'; await new Promise((r) => setTimeout(r, 4000)); - if (browser) window.location.href = `/events/${event_id}/badges`; + nav_to_badges(); return; } @@ -258,7 +273,7 @@ async function handle_print_badge() { // Hold the error state long enough for a kiosk operator to notice before // the loop returns to search for the next attendee. await new Promise((r) => setTimeout(r, 4000)); - if (browser) window.location.href = `/events/${event_id}/badges`; + nav_to_badges(); return; } @@ -268,13 +283,13 @@ async function handle_print_badge() { // Brief success flash, then return to badge search await new Promise((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`; + nav_to_badges(); } catch (err) { console.error('Badge print controls: print error:', err); print_status = 'error'; if (browser) window.print(); await new Promise((r) => setTimeout(r, 4000)); - if (browser) window.location.href = `/events/${event_id}/badges`; + nav_to_badges(); } } diff --git a/src/routes/events/[event_id]/(badges)/badges/config/+page.svelte b/src/routes/events/[event_id]/(badges)/badges/config/+page.svelte index 737c376e..19691471 100644 --- a/src/routes/events/[event_id]/(badges)/badges/config/+page.svelte +++ b/src/routes/events/[event_id]/(badges)/badges/config/+page.svelte @@ -28,9 +28,11 @@ import { ChevronUp, FileText, Lock, + Monitor, Save, Settings } from '@lucide/svelte'; +import { badges_loc } from '$lib/stores/ae_events_stores__badges.svelte'; interface Props { data: any; @@ -272,9 +274,9 @@ function toggle(key: string) {

Badges Config

- Templates + Templates
{#if save_status === 'success'} @@ -555,6 +557,35 @@ function toggle(key: string) { {/if} + + + +
+
+ + + Local Device Settings + + saved to this browser only · not synced +
+
+ +
+
+