fix(stats): unambiguous chart x-labels + unit-carrying tooltips

The daily charts' x-axis labels were bare MM-DD ('10-15', '10-16') — on
the Listening per Day chart (y in hours) those read as hour values, which
is exactly the '10-16 hours a day' misread that prompted this. Labels now
spell the month ('Oct 15') and every chart's tooltip carries its unit
(min / pages / hrs). main.js?v=5
This commit is contained in:
John O'Keefe committed 2026-10-16 11:53:56 -04:00
1 parent ce366b1604
commit b4ae42326a
3 files changed
+26 -10

No files matched your search

+24 -8
View File
@@ -244,8 +244,12 @@ async function loadSummary(): Promise<void> {
// Rendering ----------------------------------------------------------------
function fmtDay(iso: string): string {
const parts = iso.split("-");
return parts.length >= 3 ? `${parts[1]}-${parts[2]}` : iso;
// "2026-10-15" → "Oct 15" — a bare "10-15" x-label reads like a NUMBER
// RANGE next to hour values (it was mistaken for "10-15 hours" on the
// listening chart), so spell the month out.
const d = new Date(iso + "T00:00:00");
if (isNaN(d.getTime())) return iso;
return d.toLocaleDateString(undefined, { month: "short", day: "numeric" });
}
function themeVar(name: string, fallback: string): string {
@@ -335,15 +339,27 @@ async function renderDailyCharts(daily: DailyEntry[]): Promise<void> {
const accent = themeVar("--accent", "#7aa2f7");
const secondary = themeVar("--text-secondary", "#9aa0b5");
const labels = daily.map((d) => fmtDay(d.date));
const baseOptions: ChartConfiguration["options"] = {
// Unit-carrying tooltips: a bare number next to "hrs"/"min"/"pages"
// invites misreading (the x-axis date confusion happened exactly once).
const chartOptions = (unit: string): ChartConfiguration["options"] => ({
responsive: true,
maintainAspectRatio: false,
plugins: { legend: { display: false } },
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: (ctx) => {
const v = typeof ctx.parsed === "number" ? ctx.parsed : ctx.parsed.y;
return `${Math.round(v * 10) / 10} ${unit}`;
},
},
},
},
scales: {
x: { grid: { display: false }, ticks: { color: secondary, maxTicksLimit: 10 } },
y: { grid: { color: "rgba(128,128,128,.15)" }, ticks: { color: secondary }, beginAtZero: true },
},
};
});
minutesChart?.destroy();
pagesChart?.destroy();
@@ -360,7 +376,7 @@ async function renderDailyCharts(daily: DailyEntry[]): Promise<void> {
labels,
datasets: [{ data: daily.map((d) => d.minutes), backgroundColor: accent, borderRadius: 4 }],
},
options: baseOptions,
options: chartOptions("min"),
});
}
@@ -381,7 +397,7 @@ async function renderDailyCharts(daily: DailyEntry[]): Promise<void> {
},
],
},
options: baseOptions,
options: chartOptions("pages"),
});
}
@@ -402,7 +418,7 @@ async function renderDailyCharts(daily: DailyEntry[]): Promise<void> {
},
],
},
options: baseOptions,
options: chartOptions("hrs"),
});
}
}