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:
1 parent
ce366b1604
commit
b4ae42326a
3 files changed
+26
-10
No files matched your search
@@ -213,7 +213,7 @@ templ Header(user User, currentPath string) {
|
|||||||
</header>
|
</header>
|
||||||
<!-- module bundle; ?v=<commit-ish stamp> busts stale intermediate
|
<!-- module bundle; ?v=<commit-ish stamp> busts stale intermediate
|
||||||
builds across app restarts (browser caches are keyed by URL) -->
|
builds across app restarts (browser caches are keyed by URL) -->
|
||||||
<script type="module" src="/static/main.js?v=4"></script>
|
<script type="module" src="/static/main.js?v=5"></script>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -631,7 +631,7 @@ func Header(user User, currentPath string) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "</span> <input type=\"text\" id=\"header-search\" placeholder=\"Search your library…\" class=\"input pl-10\" autocomplete=\"off\"></div></div></header><!-- module bundle; ?v=<commit-ish stamp> busts stale intermediate\n\t\t builds across app restarts (browser caches are keyed by URL) --><script type=\"module\" src=\"/static/main.js?v=4\"></script></div>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "</span> <input type=\"text\" id=\"header-search\" placeholder=\"Search your library…\" class=\"input pl-10\" autocomplete=\"off\"></div></div></header><!-- module bundle; ?v=<commit-ish stamp> busts stale intermediate\n\t\t builds across app restarts (browser caches are keyed by URL) --><script type=\"module\" src=\"/static/main.js?v=5\"></script></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-8
@@ -244,8 +244,12 @@ async function loadSummary(): Promise<void> {
|
|||||||
// Rendering ----------------------------------------------------------------
|
// Rendering ----------------------------------------------------------------
|
||||||
|
|
||||||
function fmtDay(iso: string): string {
|
function fmtDay(iso: string): string {
|
||||||
const parts = iso.split("-");
|
// "2026-10-15" → "Oct 15" — a bare "10-15" x-label reads like a NUMBER
|
||||||
return parts.length >= 3 ? `${parts[1]}-${parts[2]}` : iso;
|
// 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 {
|
function themeVar(name: string, fallback: string): string {
|
||||||
@@ -335,15 +339,27 @@ async function renderDailyCharts(daily: DailyEntry[]): Promise<void> {
|
|||||||
const accent = themeVar("--accent", "#7aa2f7");
|
const accent = themeVar("--accent", "#7aa2f7");
|
||||||
const secondary = themeVar("--text-secondary", "#9aa0b5");
|
const secondary = themeVar("--text-secondary", "#9aa0b5");
|
||||||
const labels = daily.map((d) => fmtDay(d.date));
|
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,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
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: {
|
scales: {
|
||||||
x: { grid: { display: false }, ticks: { color: secondary, maxTicksLimit: 10 } },
|
x: { grid: { display: false }, ticks: { color: secondary, maxTicksLimit: 10 } },
|
||||||
y: { grid: { color: "rgba(128,128,128,.15)" }, ticks: { color: secondary }, beginAtZero: true },
|
y: { grid: { color: "rgba(128,128,128,.15)" }, ticks: { color: secondary }, beginAtZero: true },
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
|
||||||
minutesChart?.destroy();
|
minutesChart?.destroy();
|
||||||
pagesChart?.destroy();
|
pagesChart?.destroy();
|
||||||
@@ -360,7 +376,7 @@ async function renderDailyCharts(daily: DailyEntry[]): Promise<void> {
|
|||||||
labels,
|
labels,
|
||||||
datasets: [{ data: daily.map((d) => d.minutes), backgroundColor: accent, borderRadius: 4 }],
|
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"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user