From 09d9d38c12a50c6432e3c68580d3c205eeb8a8ee Mon Sep 17 00:00:00 2001 From: Alexander Heldt Date: Sun, 2 Aug 2026 13:26:38 +0000 Subject: [PATCH] Add metric checkboxes to the daily counts chart The Daily counts legend is now a Pees/Poos/Meals checkbox group, so you can hide metrics and focus on just the ones you care about. The choice is persisted per device, at least one metric is always kept visible, and the y-axis and bar widths adapt to the selected metrics. --- src/app.js | 49 ++++++++++++++++++++++++++++++++++++++-------- src/changelog.json | 1 + src/index.html | 8 ++++---- src/style.css | 9 +++++++++ 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/app.js b/src/app.js index 5b0dc20..fbc4480 100644 --- a/src/app.js +++ b/src/app.js @@ -927,6 +927,27 @@ render(); } + // Which metrics the daily-counts chart shows. Device-global, toggled via the + // checkboxes under the chart. At least one is always kept on so the chart is + // never empty; an invalid/empty stored value falls back to all three. + const COUNTS_METRICS_KEY = "puppy-tracker:counts-metrics:v1"; + const COUNTS_METRIC_KEYS = ["pees", "poos", "meals"]; + function countsMetrics() { + let stored; + try { stored = JSON.parse(localStorage.getItem(COUNTS_METRICS_KEY)); } catch { /* ignore */ } + const on = Array.isArray(stored) + ? COUNTS_METRIC_KEYS.filter(k => stored.includes(k)) + : []; + return on.length ? on : COUNTS_METRIC_KEYS.slice(); + } + function setCountsMetrics(keys) { + // Never let the user hide everything โ€” keep at least one metric visible. + const on = COUNTS_METRIC_KEYS.filter(k => keys.includes(k)); + if (!on.length) { renderChartWindow(); return; } // restore the checkbox we just rejected + try { localStorage.setItem(COUNTS_METRICS_KEY, JSON.stringify(on)); } catch { /* ignore */ } + render(); + } + // Sync every "(last N days)" header and the picker's active button. function renderChartWindow() { const n = chartDays(); @@ -938,6 +959,10 @@ document.querySelectorAll(".chart-days-picker button").forEach(b => { b.classList.toggle("active", Number(b.dataset.days) === n); }); + const on = countsMetrics(); + document.querySelectorAll("#counts-metrics input[data-metric]").forEach(cb => { + cb.checked = on.includes(cb.dataset.metric); + }); } // ---------- daily charts ---------- @@ -1094,13 +1119,19 @@ const innerW = W - ML - MR; const innerH = H - MT - MB; - const rawMax = Math.max(...days.flatMap(d => [d.pees, d.poos, d.meals])); + const series = [ + { key: "pees", label: "Pees", cls: "bar-pee" }, + { key: "poos", label: "Poos", cls: "bar-poo" }, + { key: "meals", label: "Meals", cls: "bar-eat" }, + ].filter(s => countsMetrics().includes(s.key)); + + const rawMax = Math.max(0, ...days.flatMap(d => series.map(s => d[s.key]))); const { yMax, steps: ySteps } = niceAxis(rawMax); const groupGap = days.length > 14 ? 2 : 4; const innerBarGap = days.length > 14 ? 0.5 : 1.5; const groupW = (innerW - (days.length - 1) * groupGap) / days.length; - const barW = (groupW - 2 * innerBarGap) / 3; + const barW = (groupW - (series.length - 1) * innerBarGap) / series.length; const parts = []; for (let i = 0; i <= ySteps; i++) { @@ -1110,12 +1141,6 @@ parts.push(`${v}`); } - const series = [ - { key: "pees", label: "Pees", cls: "bar-pee" }, - { key: "poos", label: "Poos", cls: "bar-poo" }, - { key: "meals", label: "Meals", cls: "bar-eat" }, - ]; - const selYmd = ymd(selectedDay()); days.forEach((d, i) => { const isToday = i === days.length - 1; @@ -3296,6 +3321,14 @@ b.addEventListener("click", () => setChartDays(Number(b.dataset.days))); }); + document.querySelectorAll("#counts-metrics input[data-metric]").forEach(cb => { + cb.addEventListener("change", () => { + const on = [...document.querySelectorAll("#counts-metrics input[data-metric]:checked")] + .map(el => el.dataset.metric); + setCountsMetrics(on); + }); + }); + // Swap the timer pill in/out of the frozen bar as the big card scrolls // past. rAF-throttled: scroll events fire far more often than we can paint. { diff --git a/src/changelog.json b/src/changelog.json index 5aa63b9..a109b2f 100644 --- a/src/changelog.json +++ b/src/changelog.json @@ -1,4 +1,5 @@ [ + { "date": "2026-08-02", "text": "The Daily counts chart now has Pees / Poos / Meals checkboxes so you can focus on just the metrics you care about โ€” untick the rest to see, say, only poos; your choice is remembered" }, { "date": "2026-08-01", "text": "Logging a pee or poo now sets off ๐Ÿ’ง/๐Ÿ’ฉ fireworks that shoot up from the bottom of the screen โ€” a little celebration you can switch off in Settings (and it honours a reduced-motion preference)" }, { "date": "2026-08-01", "text": "Tidied the header on long names and ages โ€” the name now truncates instead of shoving the buttons, and the age reads as a compact \"16 wk ยท 3 mo 3 wk\"; weight-log rows are a single line again (\"Aug 1 ยท 16 wk\")" }, { "date": "2026-07-26", "text": "Added a fan-chart view of the pedigree (toggle it in the header): your dog at the centre with each generation fanning outward as a ring, so many generations fit at once without the tree sprawling sideways โ€” tap a wedge for that dog, and repeated ancestors keep their colour" }, diff --git a/src/index.html b/src/index.html index 005f2ce..d57e449 100644 --- a/src/index.html +++ b/src/index.html @@ -203,10 +203,10 @@
Daily counts
-
- Pees - Poos - Meals +
+ + +