From db45b386fa3bd3e82e91ee9503a957fd57859e9e Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 25 May 2026 20:48:20 -0400 Subject: [PATCH] fix: reset flow now fetches photo before deleting, shows preview + manual entry - resetPhoto() now downloads the photo blob before calling the reset endpoint, then re-shows it in the detail view with preview and manual entry - resetAndReupload() same treatment, with fallback to server fetch - Added Reset button to ALL server results (not just duplicates) - Preview in Previous Photos cards with lightbox (prev-thumb + openLightbox) --- static/index.html | 66 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/static/index.html b/static/index.html index c0ef646..dd6dc5f 100644 --- a/static/index.html +++ b/static/index.html @@ -604,11 +604,37 @@ function renderPrevCard(p) { } async function resetPhoto(photoId) { - if (!confirm('Reset this entry? The photo will be deleted from the database and can be re-uploaded as new.')) return; + if (!confirm('Reset this entry and re-process from scratch?')) return; + + // Find the card to get the original filename + const card = document.querySelector(`#reEng${photoId}`)?.closest('.prev-photo-card'); + const filename = card?.querySelector('.prev-filename')?.textContent?.trim() || 'photo.jpg'; + try { - const resp = await fetch(`/api/photos/${photoId}/reset`, { method: 'POST' }); - if (!resp.ok) throw new Error('Reset failed'); - loadPreviousPhotos(); + // 1. Fetch the original file BEFORE reset deletes it + const fileResp = await fetch(`/api/photos/${photoId}/file`); + if (!fileResp.ok) throw new Error('Could not load photo file'); + const blob = await fileResp.blob(); + + // 2. Reset in DB (deletes DB record + file from disk) + const resetResp = await fetch(`/api/photos/${photoId}/reset`, { method: 'POST' }); + if (!resetResp.ok) throw new Error('Reset failed'); + + // 3. Rebuild a File object and scan it like a fresh upload + const file = new File([blob], filename, { type: blob.type || 'image/jpeg' }); + const photoData = await scanPhoto(file); + photoData.file = file; + + // 4. Clear current state and add to gallery + resetAll(); + allPhotos = [photoData]; + updateSummary(); + renderGallery(); + + // 5. Show the detail view with preview image + manual entry + showDetail(0); + document.getElementById('serverSection').style.display = 'none'; + document.getElementById('detail').scrollIntoView({ behavior: 'smooth' }); } catch (e) { alert('Reset failed: ' + e.message); } @@ -618,9 +644,31 @@ async function resetAndReupload(photoId) { if (!photoId) { alert('No photo ID available'); return; } if (!confirm('Reset this entry and re-process as fresh?')) return; try { + // Try to use local file first, fall back to fetching from server + let file = null; + if (selectedIdx >= 0 && allPhotos[selectedIdx]?.file) { + file = allPhotos[selectedIdx].file; + } else { + const fileResp = await fetch(`/api/photos/${photoId}/file`); + if (fileResp.ok) { + const blob = await fileResp.blob(); + file = new File([blob], 'photo.jpg', { type: blob.type || 'image/jpeg' }); + } + } + if (!file) throw new Error('No photo file available'); + await fetch(`/api/photos/${photoId}/reset`, { method: 'POST' }); - // Re-trigger the upload - uploadSelected(); + + // Scan and show in detail view + const photoData = await scanPhoto(file); + photoData.file = file; + resetAll(); + allPhotos = [photoData]; + updateSummary(); + renderGallery(); + showDetail(0); + document.getElementById('serverSection').style.display = 'none'; + document.getElementById('detail').scrollIntoView({ behavior: 'smooth' }); } catch (e) { alert('Reset failed: ' + e.message); } @@ -905,6 +953,12 @@ async function uploadSelected() { '
' + ''; + // Reset button — always available to start fresh + html += '
' + + '' + + '
Clears DB entry and lets you re-analyze with manual entry
' + + '
'; + div.innerHTML = html; } catch (e) { div.innerHTML = '
❌ Upload failed: ' + esc(e.message) + '
';