From 043cc4bcce87556c778373da1cf260b4770aa942 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Mon, 13 Jul 2026 11:22:15 -0700 Subject: [PATCH] fix: handle fetch failures and stop keying UI logic off display text - refreshStatus()/observe() now check response.ok and catch fetch errors, showing a clear "Connection problem" state instead of silently rendering blank/undefined status on a non-2xx response. - Track session state in a currentState variable (set in refreshStatus) and branch the trigger button's click handler on currentState === "book_complete" instead of parsing statusEl's displayed text, so future copy changes can't silently break the next-book/manual-trigger branch. --- bookmark/static/app.js | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/bookmark/static/app.js b/bookmark/static/app.js index d13aca6..8f4d00a 100644 --- a/bookmark/static/app.js +++ b/bookmark/static/app.js @@ -10,9 +10,33 @@ const STATE_COPY = { book_complete: { status: "Book complete!", hint: "Tap Next Book to continue." }, }; +const CONNECTION_ERROR_COPY = { + status: "Connection problem — get a volunteer", + hint: "The intake station couldn't reach the server. Try again, or ask for help.", +}; + +let currentState = null; + +function showConnectionError() { + currentState = null; + statusEl.textContent = CONNECTION_ERROR_COPY.status; + hintEl.textContent = CONNECTION_ERROR_COPY.hint; +} + async function refreshStatus() { - const response = await fetch("/api/session-state"); + let response; + try { + response = await fetch("/api/session-state"); + } catch (err) { + showConnectionError(); + return; + } + if (!response.ok) { + showConnectionError(); + return; + } const body = await response.json(); + currentState = body.state; const copy = STATE_COPY[body.state] || { status: body.state, hint: "" }; statusEl.textContent = copy.status; hintEl.textContent = copy.hint; @@ -24,12 +48,21 @@ function refreshPreview() { } async function observe() { - await fetch("/api/observe", { method: "POST" }); + try { + const response = await fetch("/api/observe", { method: "POST" }); + if (!response.ok) { + showConnectionError(); + return; + } + } catch (err) { + showConnectionError(); + return; + } await refreshStatus(); } triggerButton.addEventListener("click", async () => { - if (statusEl.textContent === "Book complete!") { + if (currentState === "book_complete") { await fetch("/api/next-book", { method: "POST" }); } else { await fetch("/api/manual-trigger", { method: "POST" });