feat(badges): goto() after print with per-device fallback toggle
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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<void>((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<void>((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<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`;
|
||||
nav_to_badges();
|
||||
} catch (err) {
|
||||
console.error('Badge print controls: print error:', err);
|
||||
print_status = 'error';
|
||||
if (browser) window.print();
|
||||
await new Promise<void>((r) => setTimeout(r, 4000));
|
||||
if (browser) window.location.href = `/events/${event_id}/badges`;
|
||||
nav_to_badges();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
<h1 class="text-xl font-bold">Badges Config</h1>
|
||||
</div>
|
||||
<a href="/events/{event_id}/templates"
|
||||
class="btn btn-sm preset-tonal-surface"
|
||||
class="btn btn-sm preset-tonal-surface border border-surface-300-700"
|
||||
title="Manage Badge Templates">
|
||||
<FileText size="1em" class="mr-1" /> Templates
|
||||
<FileText size="1em" /> Templates
|
||||
</a>
|
||||
<div class="flex items-center gap-2">
|
||||
{#if save_status === 'success'}
|
||||
@@ -555,6 +557,35 @@ function toggle(key: string) {
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<!-- ================================================================ -->
|
||||
<!-- LOCAL DEVICE SETTINGS (localStorage only — not saved to event) -->
|
||||
<!-- ================================================================ -->
|
||||
<section class="border-surface-200-800 rounded-xl border">
|
||||
<div class="flex w-full items-center justify-between px-4 py-3">
|
||||
<span class="flex items-center gap-2 font-semibold">
|
||||
<Monitor size="1em" class="text-surface-400" />
|
||||
Local Device Settings
|
||||
</span>
|
||||
<span class="text-xs text-surface-400 italic">saved to this browser only · not synced</span>
|
||||
</div>
|
||||
<div class="border-surface-200-800 space-y-3 border-t px-4 py-3">
|
||||
<label class="flex items-start gap-3">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox mt-0.5 shrink-0"
|
||||
bind:checked={badges_loc.current.print_nav_use_goto} />
|
||||
<div>
|
||||
<p class="text-sm font-medium">Use fast navigation after print</p>
|
||||
<p class="text-xs text-surface-400 italic">
|
||||
On by default. Uses SvelteKit client-side navigation to return to Badge Search
|
||||
after printing — faster and avoids a full page reload. Turn off to fall back to
|
||||
a hard page reload if the print loop behaves unexpectedly on this device.
|
||||
</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Bottom save button -->
|
||||
<div class="flex justify-end">
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user