fix(cash-in): prevent cancel after bills inserted in insertingBills state

The cancel button was still accessible during insertingBills after a bill
had been stacked (physically irreversible). Now CANCEL in insertingBills
is guarded: no bills → idle, bills present → confirmAbandon warning.
The UI also hides the cancel button once bills are detected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-02-25 19:35:34 -05:00
commit 13ac74ab86
2 changed files with 23 additions and 4 deletions

View file

@ -20,8 +20,9 @@ const isElectron = typeof window !== 'undefined' && window.electronAPI !== undef
const showCancelButton = computed(() => {
const state = atmStore.nestedState
const hasBills = (atmStore.context?.billsInserted.length ?? 0) > 0
// Always show in insertingBills (before bills) and error (without bills)
if (state === 'insertingBills' || state === 'fetchingRate') return true
// Show in fetchingRate (no bills yet) and insertingBills only before bills are in
if (state === 'fetchingRate') return true
if (state === 'insertingBills' && !hasBills) return true
if (state === 'error' && !hasBills) return true
// Hide when bills are in the cash box
return false

View file

@ -426,8 +426,26 @@ export function createATMMachine(
guard: 'hasInsertedBills',
target: 'generatingNdebit',
},
CANCEL: '#atm.idle',
TIMEOUT: '#atm.idle',
CANCEL: [
{
// No bills inserted yet: safe to cancel
guard: ({ context }) => context.billsInserted.length === 0,
target: '#atm.idle',
},
{
// Bills already stacked: warn user before abandoning
target: 'confirmAbandon',
},
],
TIMEOUT: [
{
guard: ({ context }) => context.billsInserted.length === 0,
target: '#atm.idle',
},
{
target: 'confirmAbandon',
},
],
},
},
generatingNdebit: {