feat(ui): Dashboard ↔ Metriken — klickbare Charts + kuratierte „Deine Metriken"-Leiste + Verwandte-Metriken-Block#179
Merged
Conversation
- Chart-Cards am Dashboard zu Detailseiten verlinken (Block-Link: Titel als echter <a> + ganze Card per Maus-Klick), bevorzugt eigene Custom-Metriken statt Garmin-Rohwerte (body-battery-custom, stress-score-custom, sleep-score-custom, hrv-status-custom) - Kein Canvas-Overlay → Chart.js-Hover-Tooltips bleiben erhalten - battery-pattern + correlations in /metrics-Übersicht aufgenommen (waren funktionsfähig, nur nicht gelistet — keine toten Routen) - Briefing-Doc docs/dashboard-metrics-redesign.md (Faktenlage, UX-Recherche, 3-Phasen-Plan) https://claude.ai/code/session_012tUMV4UZ5AB6mLNjA85LRr
…k (Phase 2+3) Phase 2 — kuratierte Eigen-Metriken am Dashboard sichtbar machen: - Neue Sektion „Deine Metriken" zwischen Hero und Tabs mit 5 berechneten Metriken, die die Hero NICHT zeigt (Training Monotony, Schlaf-Konsistenz, HRV Recovery, SpO₂ Trend, Running Economy) — kuratiert statt alle 22 (Few/Tufte). - buildCuratedMetrics() in dashboard-hero.js rendert aus bereits geladenem _heroData.ml (/api/ml-insights) + _evidence → KEIN zusätzlicher Request. Verdrahtet in loadMlInsights() und nach loadEvidence(). Phase 3 — Detailseiten vernetzen: - „Verwandte Metriken"-Block (RELATED-Mapping) am Ende jeder Detailseite, gerendert in metrics.js nach dem KPI-Block. Macht u. a. battery-pattern/ correlations natürlich auffindbar. Styling (DRY): geteilte .metric-overview-*/.metrics-section-heading aus dem metrics_overview-Inline-<style> in die globale style.css verschoben (jetzt von Dashboard + Übersicht genutzt); neue .related-*-Klassen nur über Design-Tokens → kein make tailwind-build nötig. Secure/A11y: keine Inline-Handler, keine neuen Endpunkte/CSP-Änderung, innerHTML nur mit eigenen Werten + eigenem Evidence-Katalog (alles via esc()); echte <a>-Links, semantische <section>/<nav> mit aria-labelledby, globaler :focus-visible. Tests: 262/262 Vitest grün, node --check grün. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… pool) Die DB-Funktionen save_ml_feedback/get_ml_feedback wurden bisher nur über gemockte Endpoint-Tests (Route-Layer-Patch) + E2E berührt — ihre Bodies liefen nie im Unit-Test (Cover 44%, Z. 15-16/29-35 ungetestet). Drei direkte Unit-Tests via vorhandenem _pool_mock-Helper: - save: Upsert-SQL (ON CONFLICT) + Bind-Params (user_id/model/helpful) - get: Row→dict-Mapping über beide FEEDBACK_MODELS - get: leeres dict bei keinen Rows → src/db/ml_feedback.py 100% (Stmts 9/9). 102 Tests in test_db.py grün. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
JS (Vitest, 12-Modul-Gate jetzt aggregat Branch 100 %, vorher 95.07): - metrics-activity/sleep/energy/ml/readiness: Null-Daten-Fixtures decken die Chart `?? null`-Mappings, `|| []`-History-Fallbacks, leeren Sub-Branches und Recommendation-Mittelbänder ab (rein verhaltensbasiert — echte Daten mit Lücken). - epilepsy: DOM-Guard- + Delegations-Defensiv-Branches (fehlende Elemente, delBtn-null, pendingDeleteId==null) via Element-Removal-Muster. - dashboard-status: die zwei unerreichbaren Defensiv-False-Branches (if (_mlPollTimer)/if (_syncPollTimer) — Poll läuft nur via gesetztem Timer) mit /* v8 ignore */ + Begründung annotiert statt Hohl-Test. Python (full-suite je Service): - pool.py 94→100 %: create_pool-Fehlerpfad (loggt nur Exception-Typ, nie die DSN). - logging_config.py 94→100 % in ALLEN drei Services (api/sync/ml): _release() APP_VERSION-Override + "unknown"-Fallback. Verifikation: JS 284 grün (Branch 100), API 438 / Sync 194 / ML 300 Python grün, ruff sauber. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gerfru
added a commit
that referenced
this pull request
Jun 12, 2026
… Metriken"-Leiste + Verwandte-Metriken-Block (#179) * Dashboard: Charts klickbar → Metrik-Detailseite (Phase 1) - Chart-Cards am Dashboard zu Detailseiten verlinken (Block-Link: Titel als echter <a> + ganze Card per Maus-Klick), bevorzugt eigene Custom-Metriken statt Garmin-Rohwerte (body-battery-custom, stress-score-custom, sleep-score-custom, hrv-status-custom) - Kein Canvas-Overlay → Chart.js-Hover-Tooltips bleiben erhalten - battery-pattern + correlations in /metrics-Übersicht aufgenommen (waren funktionsfähig, nur nicht gelistet — keine toten Routen) - Briefing-Doc docs/dashboard-metrics-redesign.md (Faktenlage, UX-Recherche, 3-Phasen-Plan) https://claude.ai/code/session_012tUMV4UZ5AB6mLNjA85LRr * feat(ui): Dashboard „Deine Metriken"-Leiste + Verwandte-Metriken-Block (Phase 2+3) Phase 2 — kuratierte Eigen-Metriken am Dashboard sichtbar machen: - Neue Sektion „Deine Metriken" zwischen Hero und Tabs mit 5 berechneten Metriken, die die Hero NICHT zeigt (Training Monotony, Schlaf-Konsistenz, HRV Recovery, SpO₂ Trend, Running Economy) — kuratiert statt alle 22 (Few/Tufte). - buildCuratedMetrics() in dashboard-hero.js rendert aus bereits geladenem _heroData.ml (/api/ml-insights) + _evidence → KEIN zusätzlicher Request. Verdrahtet in loadMlInsights() und nach loadEvidence(). Phase 3 — Detailseiten vernetzen: - „Verwandte Metriken"-Block (RELATED-Mapping) am Ende jeder Detailseite, gerendert in metrics.js nach dem KPI-Block. Macht u. a. battery-pattern/ correlations natürlich auffindbar. Styling (DRY): geteilte .metric-overview-*/.metrics-section-heading aus dem metrics_overview-Inline-<style> in die globale style.css verschoben (jetzt von Dashboard + Übersicht genutzt); neue .related-*-Klassen nur über Design-Tokens → kein make tailwind-build nötig. Secure/A11y: keine Inline-Handler, keine neuen Endpunkte/CSP-Änderung, innerHTML nur mit eigenen Werten + eigenem Evidence-Katalog (alles via esc()); echte <a>-Links, semantische <section>/<nav> mit aria-labelledby, globaler :focus-visible. Tests: 262/262 Vitest grün, node --check grün. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(db): ml_feedback.py 44% → 100% — Unit-Tests für save/get (mocked pool) Die DB-Funktionen save_ml_feedback/get_ml_feedback wurden bisher nur über gemockte Endpoint-Tests (Route-Layer-Patch) + E2E berührt — ihre Bodies liefen nie im Unit-Test (Cover 44%, Z. 15-16/29-35 ungetestet). Drei direkte Unit-Tests via vorhandenem _pool_mock-Helper: - save: Upsert-SQL (ON CONFLICT) + Bind-Params (user_id/model/helpful) - get: Row→dict-Mapping über beide FEEDBACK_MODELS - get: leeres dict bei keinen Rows → src/db/ml_feedback.py 100% (Stmts 9/9). 102 Tests in test_db.py grün. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: JS branch coverage → 100% (gate) + pool/logging_config → 100% JS (Vitest, 12-Modul-Gate jetzt aggregat Branch 100 %, vorher 95.07): - metrics-activity/sleep/energy/ml/readiness: Null-Daten-Fixtures decken die Chart `?? null`-Mappings, `|| []`-History-Fallbacks, leeren Sub-Branches und Recommendation-Mittelbänder ab (rein verhaltensbasiert — echte Daten mit Lücken). - epilepsy: DOM-Guard- + Delegations-Defensiv-Branches (fehlende Elemente, delBtn-null, pendingDeleteId==null) via Element-Removal-Muster. - dashboard-status: die zwei unerreichbaren Defensiv-False-Branches (if (_mlPollTimer)/if (_syncPollTimer) — Poll läuft nur via gesetztem Timer) mit /* v8 ignore */ + Begründung annotiert statt Hohl-Test. Python (full-suite je Service): - pool.py 94→100 %: create_pool-Fehlerpfad (loggt nur Exception-Typ, nie die DSN). - logging_config.py 94→100 % in ALLEN drei Services (api/sync/ml): _release() APP_VERSION-Override + "unknown"-Fallback. Verifikation: JS 284 grün (Branch 100), API 438 / Sync 194 / ML 300 Python grün, ruff sauber. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Jun 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Kontext
Eigene, berechnete Metriken waren bisher nur unter
/metrics(22 Kacheln) sichtbar — am Dashboard liefen fast nur Garmin-Rohwerte. Diese PR macht die Eigen-Metriken am Haupt-Screen sichtbar und vernetzt die Detailseiten. Drilldown-Modell nach Shneiderman („overview first → details on demand"), kuratiert nach Few/Tufte (nicht alle 22).Umfasst die komplette Feature-Arbeit (Phase 1 war auf dem Vorgänger-Branch, hier mit enthalten, da
mainsie noch nicht hat).Phase 1 — Charts klickbar → Detailseite
Block-Link-Pattern: Card-Titel als echter
<a>+ ganze Card per JS-Maus-Klick (.card[data-href], ignorierta,button). Mapping bevorzugt die eigene Metrik (Body Battery →body-battery-custom, Stress →stress-score-custom, …).battery-pattern+correlationsin die/metrics-Übersicht aufgenommen.Phase 2 — Kuratierte „Deine Metriken"-Leiste am Dashboard
buildCuratedMetrics()rendert aus bereits geladenem_heroData.ml(/api/ml-insights) +_evidence→ kein zusätzlicher Request.Phase 3 — „Verwandte Metriken"-Block auf Detailseiten
RELATED-Mapping je Metrik → 2–3 verwandte Metriken, gerendert nach dem KPI-Block. Macht u. a.battery-pattern/correlationsnatürlich auffindbar.Design / Secure / Styling
innerHTMLnur mit eigenen Werten + eigenem Evidence-Katalog, alle Interpolationen viaesc()..metric-overview-*aus demmetrics_overview-Inline-<style>in die globalestyle.cssverschoben (jetzt von Dashboard + Übersicht genutzt); neue.related-*-Klassen nur über Design-Tokens → keinmake tailwind-build.<a>-Links, semantische<section>/<nav>mitaria-labelledby, globaler:focus-visible. Canvas-a11y unverändert (makeChart/buildChartDataTable).Tests / Verifikation
node --checkgrün.make dashboard: Containerhealthy,/health→{"status":"ok"}, ausgelieferte Assets enthalten die Änderungen.🤖 Generated with Claude Code