feat(badges): allow public_access to print first-print badges

Badge print kiosks authenticate at the public_access level (site-wide
passcode). Previously the print gate was trusted_access, meaning kiosk
operators had to sign in at the trusted level just to print.

Changed in both the list view and the badge detail controls panel:
- First print: public_access and above (kiosk use case)
- Reprint: still requires trusted_access + edit_mode

ae_comp__badge_obj_li.svelte: added is_public derived; updated
can_print and the print button #if condition.

ae_comp__badge_print_controls.svelte: added is_public derived; updated
can_print comment and logic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-04-13 18:01:47 -04:00
parent ad3b27b747
commit 5826b21821
2 changed files with 10 additions and 5 deletions

View File

@@ -99,6 +99,9 @@ let {
// trusted_access is true for Trusted and every level above it (Administrator,
// Manager, Super). No need to OR in administrator_access — it's already covered.
let is_trusted = $derived($ae_loc.trusted_access === true);
// public_access — site-wide passcode or higher. Badge print kiosks run at this level.
// Sufficient for first-print only; reprints require trusted + edit_mode.
let is_public = $derived($ae_loc.public_access === true);
// Minimum bar to edit any field. Anonymous/public users see values but cannot edit.
let is_auth = $derived($ae_loc.authenticated_access === true);
@@ -200,8 +203,9 @@ function toggle_section(which: 'attendee' | 'staff') {
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));
// Print is available to Public+ for first prints (kiosk use case).
// Reprints require Trusted + global edit mode.
let can_print = $derived((is_public && !is_printed) || (is_trusted && is_global_edit_mode));
type PrintStatus = 'idle' | 'loading' | 'done' | 'error';
let print_status: PrintStatus = $state('idle');

View File

@@ -40,6 +40,7 @@ let copy_status: Record<string, 'idle' | 'copied'> = $state({});
// Access level shortcuts
let is_trusted = $derived($ae_loc.trusted_access === true);
let is_public = $derived($ae_loc.public_access === true); // public passcode or higher — may print first prints
let is_edit_mode = $derived($ae_loc.edit_mode === true);
/**
@@ -140,7 +141,7 @@ let visible_badge_obj_li = $derived(
event_badge_obj?.full_name_override ??
event_badge_obj?.full_name ??
`${event_badge_obj?.given_name ?? ''} ${event_badge_obj?.family_name ?? ''}`.trim()}
{@const can_print = is_trusted && (!is_printed || is_edit_mode)}
{@const can_print = (is_public && !is_printed) || (is_trusted && is_edit_mode)}
{@const print_href = `/events/${event_badge_obj?.event_id}/badges/${event_badge_obj?.event_badge_id}/print`}
{@const review_href = build_review_url(event_badge_obj)}
@@ -242,8 +243,8 @@ let visible_badge_obj_li = $derived(
<!-- Right: up to 4 action buttons -->
<div class="flex shrink-0 flex-row items-center gap-1">
<!-- 1. Print Badge: Trusted+, not yet printed OR in Edit Mode (reprint) -->
{#if is_trusted && (!is_printed || is_edit_mode)}
<!-- 1. Print Badge: Public+ first print; Trusted + Edit Mode for reprint -->
{#if (is_public && !is_printed) || (is_trusted && is_edit_mode)}
<a
href={`/events/${event_badge_obj?.event_id}/badges/${event_badge_obj?.event_badge_id}/print`}
class="hover:text-primary-800-200 hover:bg-primary-200-800 active:bg-surface-200-700 flex items-center gap-1 px-3 py-2 text-base font-bold transition-colors duration-1000 hover:duration-300 min-w-0 preset-tonal-primary rounded-lg border border-primary-200-800