diff --git a/frontend/static/app.js b/frontend/static/app.js index 4b21646..c8a97b8 100644 --- a/frontend/static/app.js +++ b/frontend/static/app.js @@ -152,10 +152,27 @@ async function runGrade() { updateHash(); placeholder.hidden = true; results.hidden = false; - // Omit the date when it's today, so the URL (and cache key) matches the prefetch - // fired from the other views — a same-tab navigation then reuses the response. - const q = `lat=${selected.lat}&lon=${selected.lon}`; - const url = dateInput.value === todayISO() ? uv(`grade?${q}`) : uv(`grade?${q}&date=${dateInput.value}`); + // Always send the target date, even when it's "today" — the backend only + // falls back to its own UTC today (api_grade's `date` param default; see + // backend/web/app.py) when the param is omitted or empty, a day behind local + // midnight for any viewer east of UTC (reported from Kaunas, UTC+3: asking + // for 7/26 rendered 7/25). The comment this replaces claimed omitting the + // date kept this URL matching the cross-view prefetch — but that match was + // the other half of the bug: cache.js's viewFetches() seeds the grade view's + // cache entry under this exact dateless URL too, tagged fresh for the + // viewer's local day no matter which day the server actually resolved, so a + // same-tab nav that had already prefetched this cell (e.g. via the Day page) + // could serve that stale, server-resolved slice straight out of IndexedDB + // with no live request ever going out. Sending the real date makes every + // load self-consistent with the viewer's own clock instead of aliasing onto + // whatever "today" the server or an earlier prefetch resolved. + // dateInput.value can also come back empty (a cleared native date field — + // day.js guards the same input for the same reason), so fall back to the + // viewer's local today rather than ever send `date=` empty, which hits that + // same server fallback. + const date = dateInput.value || todayISO(); + const q = `lat=${selected.lat}&lon=${selected.lon}&date=${date}`; + const url = uv(`grade?${q}`); await loadView({ url, ttl: TTL.grade, seq: ++gradeSeq, current: () => gradeSeq, spinner: () => { results.innerHTML = `

Fetching decades of climate history…

`; },