Home: watch-time heatmap in the stats area

- extract the 365d fetch+render into heatSection() so ?stats and the
  home stats widget share it (no duplicated async loader)
- home order: stats cards + top 3 -> watch-time heatmap (past year,
  month labels, scrollable) -> history widget
This commit is contained in:
jozamudi committed 2026-08-25 21:10:22 +00:00
1 parent df8307bf49
commit 59df3c37c8
1 file changed
+19 -12
+19 -12
View File
@@ -185,6 +185,8 @@ function showHome() {
const ta = topAnime(d, 3);
if (ta) sw.append(ta);
}).catch(() => load.remove());
// 5b. watch-time heatmap (past year, shared with ?stats)
main.append(heatSection());
// 6. history widget (data already loaded, capped at 6)
const hh = el("div", "sec-head");
hh.append(el("h2", null, "History"), link(`all ${history.length} \u2192`, "?history"));
@@ -531,24 +533,29 @@ function heatMap(byDay, days) {
return [lbl, grid, lg];
}
function heatSection() {
const sec = el("section", null);
const h = el("div", "sec-head");
h.append(el("h2", null, "Watch time by day"), el("span", "muted", "past year"));
const load = el("p", "muted", "loading\u2026");
sec.append(h, load);
api("/api/stats?days=365").then(d2 => {
load.remove();
const [l, g, leg] = heatMap(d2.by_day, 365);
const w = el("div", "heat-wrap");
w.append(l, g);
sec.append(w, leg);
}).catch(() => load.remove());
return sec;
}
async function showStats() {
skel(5);
const d = await api("/api/stats?days=30");
main.innerHTML = "";
main.append(el("h2", null, "Stats \u2014 last 30 days"));
main.append(statsCards(d));
const hm = el("section", null);
const hmh = el("div", "sec-head");
hmh.append(el("h2", null, "Watch time by day"), el("span", "muted", "past year"));
hm.append(hmh, el("p", "muted", "loading\u2026"));
main.append(hm);
api("/api/stats?days=365").then(d2 => {
hm.querySelector("p.muted")?.remove();
const [l, g, leg] = heatMap(d2.by_day, 365);
const w = el("div", "heat-wrap");
w.append(l, g);
hm.append(w, leg);
}).catch(() => hm.querySelector("p.muted")?.remove());
main.append(heatSection());
const ta = topAnime(d);
if (ta) main.append(ta);
if (d.top_searches.length) {