diff --git a/static/app.js b/static/app.js index b45b532..169fa0d 100644 --- a/static/app.js +++ b/static/app.js @@ -6,6 +6,7 @@ import { getJSON, TTL, prefetchViews } from "./cache.js"; import { initFindButton, setFindLabel } from "./mappicker.js"; import { W, PW, H, PL, PR, plotTop, plotBot, xLabY, setChartWidth, chartPalette, tempChart, precipChart, dryChart, attachChartHover } from "./chart.js"; +import { track } from "./digest.js"; import { TIER_COLORS, SCALE_TEMP, drynessColor, ord, esc, todayISO, placeLabel, fmtPrecip, fmtWind, fmtHumid } from "./shared.js"; @@ -47,6 +48,43 @@ const locLabel = document.getElementById("loc-label"); initFindButton(findBtn, "Find a location", () => selected, (lat, lon) => selectLocation(lat, lon)); +// ---- hero ---- +// The hero's grade card is server-rendered showing the most unusual city we're +// tracking; once the visitor has a place of their own it re-points at that. The +// frame and its text slots already exist in the HTML, so swapping the numbers in +// shifts nothing on the page. +const hero = document.getElementById("hero"); + +document.getElementById("hero-locate")?.addEventListener("click", () => { + track("home.locate"); + if (!navigator.geolocation) return; + navigator.geolocation.getCurrentPosition( + (pos) => selectLocation(pos.coords.latitude, pos.coords.longitude), + () => { /* declined or unavailable: the map picker is still right there */ }, + { enableHighAccuracy: false, timeout: 10000, maximumAge: 600000 }, + ); +}); + +document.getElementById("hero-pick")?.addEventListener("click", () => findBtn.click()); + +/** Re-point the hero card at the place the visitor actually chose. */ +function updateHero(data) { + if (!hero) return; + const card = document.getElementById("hero-grade"); + const targetDay = data.recent.find((d) => d.date === data.target_date); + const g = targetDay && (targetDay.tmax || targetDay.tmin); + if (!card || !g) return; + + document.getElementById("hero-where").textContent = `Today in ${placeLabel(data)}`; + document.getElementById("hero-band").textContent = g.grade; + document.getElementById("hero-detail").textContent = + `${targetDay.tmax === g ? "High temp" : "Low temp"} in the ${ord(Math.round(g.percentile))} percentile`; + // Band colour rides the same token set as everything else; the band word is + // always present too, so colour is never the only signal. + card.style.setProperty("--cat", TIER_COLORS[g.class] || ""); + hero.querySelector(".grade-why")?.remove(); +} + dateInput.addEventListener("change", () => { syncTodayBtn(); selected && runGrade(); }); // ---- grade request + render ---- @@ -116,6 +154,7 @@ const IC = { function render(data) { recentData = data; + updateHero(data); // The place name appears once — as the results heading (