diff --git a/backend/data_layer/nutrition_interpretation.py b/backend/data_layer/nutrition_interpretation.py index 74e0283..a014576 100644 --- a/backend/data_layer/nutrition_interpretation.py +++ b/backend/data_layer/nutrition_interpretation.py @@ -103,6 +103,7 @@ def build_nutrition_history_kpi_tiles( "sublabel": "Referenzgewicht fehlt", "status": "warn", "verdict": _verdict("warn"), + "hint": "Ohne aktuelles Körpergewicht lässt sich das Protein-Ziel (g/kg) nicht bewerten.", "hoverTop": "Protein-Ziel nicht berechenbar", "hoverBody": "Für 1,6–2,2 g/kg wird ein aktuelles Körpergewicht benötigt.", "keys": ["protein_adequacy"], @@ -119,6 +120,10 @@ def build_nutrition_history_kpi_tiles( "sublabel": f"Unterversorgung: {avg_protein}g/Tag (Ziel {pt_low}–{pt_high}g)", "status": "bad", "verdict": _verdict("bad"), + "hint": ( + f"Es fehlen rund {miss} g Protein pro Tag – bei Kaloriendefizit " + "steigt das Risiko für Muskelerhalt." + ), "hoverTop": f"Unterversorgung: {avg_protein}g/Tag (Ziel {pt_low}–{pt_high}g)", "hoverBody": ( f"1,6–2,2g/kg KG. Fehlend: ~{miss}g täglich. " @@ -153,6 +158,10 @@ def build_nutrition_history_kpi_tiles( "sublabel": f"Protein-Anteil niedrig: {prot_pct}% der Kalorien", "status": "warn", "verdict": _verdict("warn"), + "hint": ( + f"Viele Kalorien kommen aus KH/Fett; Proteinanteil oft sinnvoll bei 25–35 % " + f"(aktuell P {prot_pct} % / KH {kh_pct} % / F {fat_pct} %)." + ), "hoverTop": f"Protein-Anteil niedrig: {prot_pct}% der Kalorien", "hoverBody": ( f"Empfehlung oft 25–35%. Aktuell: {prot_pct}% P / {kh_pct}% KH / {fat_pct}% F" diff --git a/frontend/src/components/KpiTilesOverview.jsx b/frontend/src/components/KpiTilesOverview.jsx index 96150f9..e6fead0 100644 --- a/frontend/src/components/KpiTilesOverview.jsx +++ b/frontend/src/components/KpiTilesOverview.jsx @@ -28,6 +28,7 @@ export function buildKpiTileTitleString(t) { * - `value` (ReactNode) — Hauptwert * - `status` — für Farbstreifen: `good` | `warn` | `bad` * - optional: `icon`, `sublabel`, `verdict`, `valueColor`, `hoverTop`, `hoverBody`, `keys` + * - optional: `hint` — Kurz-Hinweis/Warnung direkt auf der Kachel (z. B. Ernährung bei warn/bad) */ export default function KpiTilesOverview({ tiles, @@ -82,6 +83,7 @@ export default function KpiTilesOverview({ {tiles.map(t => { const accent = getStatusColor(t.status) const tip = buildKpiTileTitleString(t) + const cardHint = t.hint ? String(t.hint) : null return (
) : null}
+ {cardHint ? ( +
+ {cardHint} +
+ ) : null} ) })} diff --git a/frontend/src/pages/History.jsx b/frontend/src/pages/History.jsx index 2587293..99be26c 100644 --- a/frontend/src/pages/History.jsx +++ b/frontend/src/pages/History.jsx @@ -700,6 +700,70 @@ function BodySection({ profile, insights, onRequest, loadingSlug, filterActiveSl ) } +/** Legende unter dem Chart: Linien + ggf. TDEE-Referenz (gestrichelt). */ +function KcalVsWeightLegend({ showTdee }) { + const line = (color) => ({ + display: 'inline-block', + width: 22, + height: 3, + background: color, + borderRadius: 1, + verticalAlign: 'middle', + marginRight: 6, + }) + return ( +
+ + + Ø Kalorien (7-Tage-Mittel) + + + + Gewicht (kg) + + {showTdee ? ( + + + TDEE-Referenz (geschätzt) + + ) : null} +
+ ) +} + /** Kalorien (Ø 7T) vs. Gewicht — Daten aus Layer-2b-Bundle (nutrition_metrics / TDEE wie Data Layer). */ function KcalVsWeightChart({ vizKcalWeight, corrData: corrRows, profile, cutoffDate, allTime }) { if (vizKcalWeight?.points?.length >= 5) { @@ -716,7 +780,7 @@ function KcalVsWeightChart({ vizKcalWeight, corrData: corrRows, profile, cutoffD Kalorien (Ø 7 Tage) vs. Gewicht
- Gleitender 7-Tage-Mittelwert der Kalorien vs. tägliches Gewicht (gemeinsame Tage). Orange: kcal · Blau: Gewicht. + Nur Tage mit Kalorien- und Gewichtsdaten. Linke Achse: kcal (Ø 7 Tage), rechte Achse: kg.
@@ -735,9 +799,10 @@ function KcalVsWeightChart({ vizKcalWeight, corrData: corrRows, profile, cutoffD -
+ +
{tdeeLabel != null - ? `Referenz TDEE ~${tdeeLabel} kcal (Data Layer, gestrichelt) · ${n} gemeinsame Tage` + ? `TDEE ~${tdeeLabel} kcal · ${n} gemeinsame Tage` : `Keine TDEE-Referenz (Gewicht/Demografie) · ${n} gemeinsame Tage`}
@@ -765,7 +830,7 @@ function KcalVsWeightChart({ vizKcalWeight, corrData: corrRows, profile, cutoffD Kalorien (Ø 7 Tage) vs. Gewicht
- Gleitender 7-Tage-Mittelwert der Kalorien vs. tägliches Gewicht (gemeinsame Tage). Orange: kcal · Blau: Gewicht. + Nur Tage mit Kalorien- und Gewichtsdaten. Linke Achse: kcal (Ø 7 Tage), rechte Achse: kg.
@@ -782,8 +847,9 @@ function KcalVsWeightChart({ vizKcalWeight, corrData: corrRows, profile, cutoffD -
- Referenz TDEE ~{tdee} kcal (Fallback Mifflin ×1,4) · {raw.length} gemeinsame Tage + +
+ TDEE ~{tdee} kcal (Fallback Mifflin ×1,4) · {raw.length} gemeinsame Tage
)