From e3db35060903ed88074547418b843d36e0751f1c Mon Sep 17 00:00:00 2001 From: Jon Seager Date: Tue, 3 Feb 2026 19:25:19 +0000 Subject: [PATCH] feat(ui): show waiting state during AI extraction Hide input controls and display a spinner with "Waiting for response..." while LLM extraction requests are in-flight. Controls are restored on completion or failure. Applied consistently across scan, roaster, and roast forms. --- templates/roasters.html | 16 +++++++++++----- templates/roasts.html | 16 +++++++++++----- templates/scan.html | 16 +++++++++++----- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/templates/roasters.html b/templates/roasters.html index 0d935b0..086dd80 100644 --- a/templates/roasters.html +++ b/templates/roasters.html @@ -32,9 +32,11 @@ if (_extracting) return; _extracting = true; var errorEl = document.getElementById(formId + '-extract-error'); - var spinnerEl = document.getElementById(formId + '-extract-spinner'); + var controlsEl = document.getElementById(formId + '-extract-controls'); + var waitingEl = document.getElementById(formId + '-extract-waiting'); errorEl.classList.add('hidden'); - spinnerEl.classList.remove('hidden'); + controlsEl.classList.add('hidden'); + waitingEl.classList.remove('hidden'); try { var resp = await fetch(endpoint, { @@ -53,7 +55,8 @@ errorEl.textContent = 'Extraction failed: ' + e.message; errorEl.classList.remove('hidden'); } finally { - spinnerEl.classList.add('hidden'); + waitingEl.classList.add('hidden'); + controlsEl.classList.remove('hidden'); _extracting = false; } } @@ -114,7 +117,7 @@ > {% if has_ai_extract %}
-
+
-
+
diff --git a/templates/roasts.html b/templates/roasts.html index a3d3268..ddf0615 100644 --- a/templates/roasts.html +++ b/templates/roasts.html @@ -32,9 +32,11 @@ if (_extracting) return; _extracting = true; var errorEl = document.getElementById(formId + '-extract-error'); - var spinnerEl = document.getElementById(formId + '-extract-spinner'); + var controlsEl = document.getElementById(formId + '-extract-controls'); + var waitingEl = document.getElementById(formId + '-extract-waiting'); errorEl.classList.add('hidden'); - spinnerEl.classList.remove('hidden'); + controlsEl.classList.add('hidden'); + waitingEl.classList.remove('hidden'); try { var resp = await fetch(endpoint, { @@ -53,7 +55,8 @@ errorEl.textContent = 'Extraction failed: ' + e.message; errorEl.classList.remove('hidden'); } finally { - spinnerEl.classList.add('hidden'); + waitingEl.classList.add('hidden'); + controlsEl.classList.remove('hidden'); _extracting = false; } } @@ -143,7 +146,7 @@ > {% if has_ai_extract %}
-
+
-
+
diff --git a/templates/scan.html b/templates/scan.html index 8658d7f..9e2759e 100644 --- a/templates/scan.html +++ b/templates/scan.html @@ -32,9 +32,11 @@ if (_extracting) return; _extracting = true; var errorEl = document.getElementById('scan-extract-error'); - var spinnerEl = document.getElementById('scan-extract-spinner'); + var controlsEl = document.getElementById('scan-extract-controls'); + var waitingEl = document.getElementById('scan-extract-waiting'); errorEl.classList.add('hidden'); - spinnerEl.classList.remove('hidden'); + controlsEl.classList.add('hidden'); + waitingEl.classList.remove('hidden'); try { var resp = await fetch('/api/v1/extract-bag-scan', { @@ -55,7 +57,8 @@ errorEl.textContent = 'Extraction failed: ' + e.message; errorEl.classList.remove('hidden'); } finally { - spinnerEl.classList.add('hidden'); + waitingEl.classList.add('hidden'); + controlsEl.classList.remove('hidden'); _extracting = false; } } @@ -136,7 +139,7 @@
-
+
-
+