Remediate the 2026-09-03 feature-test findings

This commit is contained in:
2026-09-03 17:15:03 -04:00
parent cf95daf3bb
commit fd513c08eb
112 changed files with 5182 additions and 857 deletions

View File

@@ -7,10 +7,31 @@
</button>
</header>
<div v-if="error" class="kiosk-error">{{ error }}</div>
<div v-if="error" class="kiosk-error">
{{ error }}
<p v-if="misses >= 3" class="kiosk-hint">
Several scans in a row have found nothing. The kiosk may have been
switched off, or this screen's setup link may have been replaced - ask
an administrator to check Settings &gt; 3D Printed Parts.
</p>
</div>
<!-- This screen was never provisioned. The SERVER cannot say so - the
routes answer a bare 404 on purpose, so a caller without the token
does not learn the door exists - but the browser knows whether it
holds one, and that is not a disclosure. Without this the kiosk drew
its normal scan prompt and answered "Not found" to every scan, which
reads as "we do not stock that part". -->
<section v-if="!provisioned" class="kiosk-step kiosk-unprovisioned">
<p class="kiosk-prompt">This screen is not set up yet</p>
<p class="kiosk-hint">
An administrator opens it once using the kiosk link from
Settings &gt; 3D Printed Parts. The screen remembers it after that.
</p>
</section>
<!-- step 1: the bin label -->
<section v-if="step === 'item'" class="kiosk-step">
<section v-if="provisioned && step === 'item'" class="kiosk-step">
<p class="kiosk-prompt">Scan the barcode on the bin</p>
<!-- one visible field: keyboard-wedge scanners, a plugged-in keyboard or
numpad, and the on-screen keypad all type into it. -->
@@ -108,6 +129,13 @@ const item = ref(null)
const badge = ref('')
const quantity = ref('')
const error = ref('')
// Whether THIS browser holds the kiosk's device token. The server will not say
// (see the template), and it does not need to: an unprovisioned screen should
// say so rather than pretending to be a working kiosk with an empty catalog.
const provisioned = ref(true)
// Consecutive lookups that found nothing. Every scan missing usually means the
// kiosk was switched off, not that no bin is known.
const misses = ref(0)
const doneMessage = ref('')
const submitting = ref(false)
const manualCode = ref('')
@@ -118,6 +146,14 @@ let resetTimer = null
onMounted(async () => {
claimKioskToken(KIOSK_TOKEN_KEYS['/printedparts/kiosk/'])
try {
provisioned.value = Boolean(
localStorage.getItem(KIOSK_TOKEN_KEYS['/printedparts/kiosk/']))
} catch {
// A browser refusing localStorage cannot be provisioned at all, and
// saying so is more use than a scan box that answers nothing.
provisioned.value = false
}
// A kiosk left running for weeks reads this once at load, which is fine: the
// label format is a property of the site's physical tags, not something that
// changes during a shift.
@@ -153,11 +189,17 @@ async function lookupItem(itemcode) {
try {
const response = await printedpartsApi.kioskItem(code)
item.value = response.data.data
misses.value = 0
step.value = 'badge'
manualCode.value = ''
} catch (lookupError) {
error.value = lookupError.response?.data?.data?.error?.message ||
'No part matches that barcode'
// The gate and a genuine miss both answer 404, deliberately, so the client
// cannot tell them apart from one response. What it CAN say is that
// repeated misses may mean the kiosk was switched off rather than that
// every bin is unknown.
misses.value += 1
}
focusEntry()
}
@@ -215,6 +257,14 @@ function reset() {
</script>
<style scoped>
.kiosk-unprovisioned {
text-align: center;
}
.kiosk-hint {
color: var(--text-light);
font-size: 1rem;
margin-top: 0.6rem;
}
.parts-kiosk {
min-height: 100vh;
background: var(--bg);