feat: scan existing asset redirects to detail view instead of scan result card
When a user scans a barcode that matches an existing asset: - Redirect directly to the asset detail view (Assets tab) - Auto-checkin still runs in background if GPS available - Show a toast notification with the asset name When scanning a barcode not in database: - Switch back to Add Asset tab and show the create form - Deferred status update survives async startScanning No backend changes needed. Closes #39
This commit is contained in:
+37
-5
@@ -416,6 +416,10 @@
|
||||
.asset-item .ai-icon.cat-Other { background: #1a1b26; }
|
||||
.asset-item .ai-info { flex: 1; min-width: 0; }
|
||||
.asset-item .ai-name { font-weight: 600; font-size: 15px; line-height: 1.35; white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
||||
.asset-item .ai-company { font-weight: 600; font-size: 14px; line-height: 1.3; }
|
||||
.asset-item .ai-location-line { font-size: 12px; color: var(--text2); margin-top: 1px; display: flex; gap: 4px; flex-wrap: wrap; }
|
||||
.asset-item .ai-location-line .tag { background: rgba(255,255,255,0.06); padding: 1px 6px; border-radius: 4px; }
|
||||
.asset-item .ai-building { font-size: 12px; color: var(--text1); margin-top: 2px; }
|
||||
.asset-item .ai-address { font-size: 12px; color: var(--text2); margin-top: 2px; }
|
||||
.asset-item .ai-location { font-size: 13px; color: var(--text1); font-weight: 500; margin-top: 3px; }
|
||||
.asset-item .ai-meta { font-size: 12px; color: var(--text2); margin-top: 3px; }
|
||||
@@ -2431,7 +2435,14 @@
|
||||
|
||||
try {
|
||||
const asset = await api(`/api/assets/search?machine_id=${encodeURIComponent(machineId)}`);
|
||||
showScannedAsset(asset);
|
||||
// Asset exists — go directly to its detail view
|
||||
showToast(`${esc(asset.name)} — showing details`, false);
|
||||
// Auto-checkin if GPS available (background, non-blocking)
|
||||
if (AppState.gpsLat != null) {
|
||||
doAutoCheckin(asset.id);
|
||||
}
|
||||
switchTab('tabAssets');
|
||||
viewAsset(asset.id);
|
||||
} catch (e) {
|
||||
if (e.message === 'Asset not found' || e.message.includes('404')) {
|
||||
showNewAssetForm(machineId);
|
||||
@@ -2498,7 +2509,12 @@
|
||||
|
||||
function showNewAssetForm(machineId) {
|
||||
currentScannedMachineId = machineId;
|
||||
setScanStatus('Machine ID not in database — create asset below', 'error');
|
||||
switchTab('tabAddAsset');
|
||||
// Defer status update so it runs after async startScanning completes
|
||||
setTimeout(() => {
|
||||
setScanStatus('Machine ID not in database — create asset below', 'error');
|
||||
}, 50);
|
||||
|
||||
|
||||
document.getElementById('newMachineId').value = machineId;
|
||||
document.getElementById('newName').value = '';
|
||||
@@ -3702,9 +3718,7 @@
|
||||
<div class="asset-item" onclick="viewAsset(${a.id})">
|
||||
<div class="ai-icon${iconWide}" style="background:${catColor}22;color:${catColor}">${icon}</div>
|
||||
<div class="ai-info">
|
||||
<div class="ai-name">${esc(a.name)}</div>
|
||||
${a.address ? `<div class="ai-address">📍 ${esc(a.address)}</div>` : ''}
|
||||
${(a.floor || a.building_number || a.building_name || a.room) ? `<div class="ai-location">${[a.floor, a.building_number, a.building_name, a.room].filter(Boolean).join(' · ')}</div>` : ''}
|
||||
${renderAssetCardContent(a)}
|
||||
<div class="ai-meta">
|
||||
${esc(a.machine_id)}${a.serial_number ? ' · S/N: ' + esc(a.serial_number) : ''}
|
||||
${a.make ? ' · ' + esc(a.make) : ''}
|
||||
@@ -3717,6 +3731,24 @@
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function renderAssetCardContent(a) {
|
||||
const parts = [];
|
||||
const company = a.company || a.name;
|
||||
parts.push(`<div class="ai-company">${esc(company)}</div>`);
|
||||
const locParts = [];
|
||||
if (a.location_area) locParts.push(`<span class="tag">${esc(a.location_area)}</span>`);
|
||||
if (a.place) locParts.push(esc(a.place));
|
||||
if (locParts.length) parts.push(`<div class="ai-location-line">${locParts.join(' · ')}</div>`);
|
||||
const bldParts = [];
|
||||
if (a.building_number) bldParts.push(`Bldg ${esc(a.building_number)}`);
|
||||
if (a.trailer_number) bldParts.push(`Trailer ${esc(a.trailer_number)}`);
|
||||
if (a.floor) bldParts.push(esc(a.floor));
|
||||
if (a.room) bldParts.push(`Room ${esc(a.room)}`);
|
||||
if (bldParts.length) parts.push(`<div class="ai-building">${bldParts.join(' · ')}</div>`);
|
||||
if (a.address) parts.push(`<div class="ai-address">📍 ${esc(a.address)}</div>`);
|
||||
return parts.join('');
|
||||
}
|
||||
|
||||
function setFilter(category, status, make, disney_park) {
|
||||
assetFilters.category = category;
|
||||
assetFilters.status = status;
|
||||
|
||||
Reference in New Issue
Block a user