diff --git a/src/app.js b/src/app.js index 9aec655..237d17a 100644 --- a/src/app.js +++ b/src/app.js @@ -1278,9 +1278,10 @@ } // ---------- sleep trend ---------- - // Cumulative hours slept as the day progresses: today's running total (up to - // now) against yesterday's full curve and the mean of the last N full days, - // where N follows the 7/14/30 chart-days picker. + // Cumulative hours slept as the selected day progresses: that day's running + // total (up to now when it's today, else the full 24h) against the previous + // day's full curve and the mean of the N full days before it, where N + // follows the 7/14/30 chart-days picker. // Each curve is a list of { x: hour-of-day 0..24, y: cumulative hours }. function sleepTrendCurves(events) { const HOUR = 3_600_000; @@ -1294,8 +1295,10 @@ } return total; }; + const day = selectedDay(); + const isToday = ymd(day) === ymd(new Date()); const dayStartTs = (daysAgo) => { - const d = startOfDay(new Date()); + const d = startOfDay(day); d.setDate(d.getDate() - daysAgo); return d.getTime(); }; @@ -1314,7 +1317,8 @@ return pts; }; - const today = curveFor(dayStartTs(0), Date.now()); + // A past day is complete, so its curve runs the full 24h uncapped. + const today = curveFor(dayStartTs(0), isToday ? Date.now() : null); const yesterdayCurve = curveFor(dayStartTs(1)); const yesterday = yesterdayCurve[24].y > 0 ? yesterdayCurve : null; @@ -1339,9 +1343,10 @@ // the average day typically adds between now and midnight. That respects // the time-of-day rhythm (night sleep, nap clusters), unlike a linear // rate extrapolation, which overshoots wildly just after a long night. - // No history → no average → no projection. + // No history → no average → no projection. Past days are already complete, + // so there is nothing to project. let projected = null; - if (avg) { + if (avg && isToday) { const nowPt = today[today.length - 1]; const avgAt = (x) => { const lo = Math.floor(x); @@ -1355,7 +1360,13 @@ } } - return { today, yesterday, avg, avgDays, projected }; + // Labels follow the selection so a past day reads as its date, not "Today". + const fmtDay = (daysAgo) => + new Date(dayStartTs(daysAgo)).toLocaleDateString(undefined, { month: "short", day: "numeric" }); + const dayLabel = isToday ? "Today" : fmtDay(0); + const prevDayLabel = isToday ? "Yesterday" : fmtDay(1); + + return { today, yesterday, avg, avgDays, projected, dayLabel, prevDayLabel }; } function drawSleepTrendChart(curves, target) { @@ -1369,9 +1380,9 @@ const series = [ // Reference lines first so today (and its projected tail) draw on top. { pts: curves.avg, cls: "trend-avg", label: `${curves.avgDays}-day average` }, - { pts: curves.yesterday, cls: "trend-yesterday", label: "Yesterday" }, + { pts: curves.yesterday, cls: "trend-yesterday", label: curves.prevDayLabel }, { pts: curves.projected, cls: "trend-projected", label: "Projected end of day" }, - { pts: curves.today, cls: "trend-today", label: "Today" }, + { pts: curves.today, cls: "trend-today", label: curves.dayLabel }, ].filter(s => s.pts && s.pts.length > 1); // The axis must reach the goal band's top even when the data doesn't yet. @@ -1452,11 +1463,11 @@ // write each curve's slept-hours total into its chip. const chip = (id) => document.getElementById(id); const hrs = (pts) => `${pts[pts.length - 1].y.toFixed(1)}h`; - chip("legend-trend-today-text").textContent = `Today ${hrs(curves.today)}`; + chip("legend-trend-today-text").textContent = `${curves.dayLabel} ${hrs(curves.today)}`; const yLegend = chip("legend-trend-yesterday"); yLegend.hidden = !curves.yesterday; if (curves.yesterday) { - chip("legend-trend-yesterday-text").textContent = `Yesterday ${hrs(curves.yesterday)}`; + chip("legend-trend-yesterday-text").textContent = `${curves.prevDayLabel} ${hrs(curves.yesterday)}`; } const aLegend = chip("legend-trend-avg"); aLegend.hidden = !curves.avg; diff --git a/src/changelog.json b/src/changelog.json index a3620e4..baddd50 100644 --- a/src/changelog.json +++ b/src/changelog.json @@ -1,4 +1,5 @@ [ + { "date": "2026-07-17", "text": "The Sleep trend chart follows the selected day — pick a past day to see its full curve against the day before and the average leading up to it" }, { "date": "2026-07-15", "text": "The Sleep trend y-axis is stretched above 10h, giving the hours around the sleep goal most of the chart" }, { "date": "2026-07-15", "text": "The Sleep trend chart shows the sleep goal for your puppy's age as a shaded band — the projection chip gets a ✓ when today is on track" }, { "date": "2026-07-15", "text": "Logging a training session while viewing another day puts it on that day (the snackbar tells you where it went)" }, diff --git a/src/index.html b/src/index.html index 4245eaf..4c631b0 100644 --- a/src/index.html +++ b/src/index.html @@ -222,7 +222,7 @@

Sleep trend

- +
Today