barcode scan: add confirmation step before auto check-in

- Existing assets now show a confirm card with machine ID + ✓ Confirm & Check In / ✏️ Edit buttons
- Confirm triggers auto check-in then shows the result card
- Edit opens inline machine ID editor with Re-lookup
- Cancel button returns to original confirmation
- New asset flow unchanged (form already editable)
This commit is contained in:
2026-05-21 14:03:59 -04:00
parent 04544603ea
commit 7331b4e1aa
+73 -2
View File
@@ -3080,8 +3080,7 @@
try {
const asset = await api(`/api/assets/search?machine_id=${encodeURIComponent(machineId)}`);
autoCheckin(asset.id);
showScannedAsset(asset);
showScanConfirm(asset, machineId);
} catch (e) {
if (e.message === 'Asset not found' || e.message.includes('404')) {
showNewAssetForm(machineId);
@@ -3112,6 +3111,78 @@
`;
}
function showScanConfirm(asset, machineId) {
AppState.currentAssetId = asset.id;
setScanStatus('Confirm machine ID', 'info');
const el = document.getElementById('scanResult');
el.style.display = 'block';
el.innerHTML = `
<div class="sr-name">${esc(asset.name)}</div>
<div class="sr-meta">
Machine ID: <strong>${esc(machineId)}</strong> · ${esc(asset.category || 'Other')} ·
<span class="status-tag ${asset.status}">${asset.status || 'active'}</span>
</div>
<div class="sr-actions" style="flex-wrap:wrap;">
<button class="btn btn-primary btn-sm" onclick="confirmScanCheckin(${asset.id})" style="flex:1;">✓ Confirm & Check In</button>
<button class="btn btn-outline btn-sm" onclick="showMachineIdEditor('${esc(machineId)}')">✏️ Edit</button>
</div>
`;
}
async function confirmScanCheckin(assetId) {
setScanStatus('Checking in...', 'working');
await autoCheckin(assetId);
const asset = await api(`/api/assets/${assetId}`);
showScannedAsset(asset);
}
function showMachineIdEditor(currentId) {
const el = document.getElementById('scanResult');
el.innerHTML = `
<div style="font-size:13px;color:var(--text2);margin-bottom:6px;">Edit machine ID:</div>
<div style="display:flex;gap:6px;">
<input type="text" id="editMachineIdInput" value="${esc(currentId)}"
style="flex:1;border:1px solid var(--border);border-radius:6px;padding:8px;font-size:16px;background:var(--bg1);color:var(--text1);"
onkeydown="if(event.key==='Enter')relookupMachineId()">
<button class="btn btn-primary btn-sm" onclick="relookupMachineId()">Re-lookup</button>
</div>
<div id="editMachineIdError" style="color:var(--err);font-size:12px;margin-top:4px;display:none;"></div>
<div style="margin-top:8px;">
<button class="btn btn-outline btn-sm" onclick="showScanConfirmFromEdit()">← Cancel</button>
</div>
`;
document.getElementById('editMachineIdInput').focus();
document.getElementById('editMachineIdInput').select();
}
async function relookupMachineId() {
const newId = document.getElementById('editMachineIdInput').value.trim();
if (!newId) return;
setScanStatus('Re-looking up...', 'working');
try {
const asset = await api(`/api/assets/search?machine_id=${encodeURIComponent(newId)}`);
showScanConfirm(asset, newId);
} catch (e) {
if (e.message === 'Asset not found' || e.message.includes('404')) {
showNewAssetForm(newId);
} else {
document.getElementById('editMachineIdError').textContent = 'Lookup error: ' + e.message;
document.getElementById('editMachineIdError').style.display = 'block';
}
}
}
function showScanConfirmFromEdit() {
const assetId = AppState.currentAssetId;
if (!assetId) return;
api(`/api/assets/${assetId}`).then(asset => {
showScanConfirm(asset, asset.machine_id);
}).catch(() => {
setScanStatus('Could not reload asset', 'error');
});
}
function showNewAssetForm(machineId) {
currentScannedMachineId = machineId;
setScanStatus('Machine ID not in database — create asset below', 'error');