fix(badges): detect and surface PATCH failure in handle_print_badge

update_ae_obj__event_badge returns false on API failure without throwing,
so the old code always treated a failed PATCH as success — badge printed,
count not saved, page navigated away silently.

Now: check the return value explicitly. On failure — still fire window.print()
(physical print must never be blocked) and still navigate back, but show a
visible red error state ('Printed — count NOT saved (see staff)') and hold
for 4s so a kiosk operator can see it before the loop resets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-04-14 16:36:56 -04:00
parent 3d81cb5a83
commit a81d65ce7e

View File

@@ -226,13 +226,31 @@ async function handle_print_badge() {
if (is_first_print) data_to_update.print_first_datetime = now;
try {
await events_func.update_ae_obj__event_badge({
const result = 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
});
// update_ae_obj__event_badge returns false/null on API failure without throwing.
// A falsy result means the PATCH failed (e.g. 400/401/500) — the DB was NOT updated.
// We still print the physical badge (never block the physical print), but show a
// visible error so staff can catch a runaway "already printed" situation and fix
// the count manually via the Admin print count field in the Staff section.
if (!result) {
console.error('Badge print controls: PATCH returned falsy — DB count not updated.');
print_status = 'error';
// Still fire the physical print — the attendee must get their badge.
if (browser) window.print();
// 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`;
return;
}
print_status = 'done';
// Trigger browser print dialog after count is recorded
if (browser) window.print();
@@ -243,9 +261,9 @@ async function handle_print_badge() {
} catch (err) {
console.error('Badge print controls: print error:', err);
print_status = 'error';
setTimeout(() => {
print_status = 'idle';
}, 3000);
if (browser) window.print();
await new Promise<void>((r) => setTimeout(r, 4000));
if (browser) window.location.href = `/events/${event_id}/badges`;
}
}
@@ -924,7 +942,7 @@ let allow_tracking_open = $derived(
{:else if print_status === 'done'}
<Check size="14" /> Printed!
{:else if print_status === 'error'}
Error — try again
Printed — count NOT saved (see staff)
{:else}
<Printer size="14" />
{is_printed ? `Reprint (${print_count}×)` : 'Print Badge'}