Make the Sleep trend chart follow the selected day
The curves were always computed relative to today regardless of the day picker. Anchor them to selectedDay() instead: a past day shows its full 24h curve against the day before it and the average of the days leading up to it, with no now-cap and no projection. Legend and tooltip labels show the actual dates when viewing a past day.
This commit is contained in:
+23
-12
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user