""" Öffentlicher Widget-Katalog (Dashboard-Lab / später Produkt-Dashboard). Single Source für: erlaubte IDs, Standard-Reihenfolge, Anzeige-Metadaten für API/GUI. Frontend-Komponenten registrieren dieselben IDs lokal (siehe widgetSystem/registerPilotLabWidgets). """ from __future__ import annotations from typing import Any, NotRequired, TypedDict class WidgetCatalogEntry(TypedDict): """requires_feature: optional features.id; fehlt oder leer → Widget immer sichtbar (nur Auth).""" id: str title: str description: str requires_feature: NotRequired[str] # Reihenfolge = Default-Layout-Reihenfolge. Aktiv-Flags: DEFAULT_LAB_WIDGET_IDS (Rest zunächst aus). WIDGET_CATALOG: list[WidgetCatalogEntry] = [ { "id": "welcome", "title": "Willkommen", "description": "Begrüßung und Kurzkontext", }, { "id": "quick_capture", "title": "Schnelleingabe", "description": "Gewicht + Baseline-Vitals; optional show_weight / show_resting_hr / show_hrv / show_vo2_max (false = aus); Feature weight_entries", "requires_feature": "weight_entries", }, { "id": "kpi_board", "title": "KPI-Kacheln", "description": "Referenzwerte, KF%, Ø-Kalorien — optional Kacheln & Reihenfolge (config.tiles, max. 9)", }, { "id": "body_overview", "title": "Körper (Chart)", "description": "Gewicht & Kennzahlen (optional: config chart_days 7–90); Feature weight_entries", "requires_feature": "weight_entries", }, { "id": "activity_overview", "title": "Aktivität", "description": "Trainingstyp-Verteilung (Kuchen) + Konsistenz — Zeitraum über config chart_days 7–90; Feature activity_entries", "requires_feature": "activity_entries", }, { "id": "dashboard_greeting", "title": "Begrüßung (Produkt)", "description": "Hallo, Datum & letztes Gewicht-Update", }, { "id": "quick_weight_today", "title": "Gewicht heute", "description": "Tagesgewicht erfassen (wie Produkt-Dashboard); Feature weight_entries", "requires_feature": "weight_entries", }, { "id": "body_stat_strip", "title": "Kennzahlen-Kacheln", "description": "Gewicht, KF, Magermasse, Ø-kcal — Oberreihe; u. a. nutrition_entries (Ø-kcal)", "requires_feature": "nutrition_entries", }, { "id": "status_pills", "title": "Indikatoren (Pills)", "description": "WHR, WHtR, Protein, KF; Feature nutrition_entries", "requires_feature": "nutrition_entries", }, { "id": "profile_goals_progress", "title": "Profil-Ziele", "description": "Fortschritt Gewicht/Körperfett aus Profilfeldern", }, { "id": "trend_kcal_weight", "title": "Trend Kalorien + Gewicht", "description": "Linienchart (optional config chart_days 7–90, Default 30); Feature nutrition_entries", "requires_feature": "nutrition_entries", }, { "id": "nutrition_activity_summary", "title": "Ernährung & Aktivität Kurz", "description": "Ø 7T Kacheln; Feature nutrition_entries", "requires_feature": "nutrition_entries", }, { "id": "nutrition_detail_charts", "title": "Ernährung — Detaillierte Charts", "description": "Phase-0c NutritionCharts (optional chart_days 7–90, Default 30); Feature nutrition_entries", "requires_feature": "nutrition_entries", }, { "id": "recovery_charts_panel", "title": "Erholung — Charts R1–R5", "description": "RecoveryCharts wie Verlauf (optional chart_days 7–90, Default 28)", }, { "id": "progress_photos", "title": "Fortschrittsfotos", "description": "Galerie der hochgeladenen Fotos; Feature photos", "requires_feature": "photos", }, { "id": "recovery_sleep_rest", "title": "Erholung", "description": "Schlaf-Widget & Ruhetage", }, { "id": "goals_focus_teaser", "title": "Ziele Teaser", "description": "Kurzlink zur Ziele-Seite", }, { "id": "ai_pipeline_insight", "title": "KI Pipeline & letzte Analyse", "description": "Pipeline starten + Gesamt-Insight; Feature ai_pipeline", "requires_feature": "ai_pipeline", }, ] DEFAULT_LAB_WIDGET_IDS: frozenset[str] = frozenset( { "welcome", "quick_capture", "kpi_board", "body_overview", "activity_overview", } ) # Produkt-Übersicht (/): Default wenn Nutzer kein dashboard_layout in der DB hat (Physisch: nur Profil-JSON). DEFAULT_PRODUCT_DASHBOARD_WIDGET_IDS: frozenset[str] = frozenset( { "dashboard_greeting", "quick_weight_today", "body_stat_strip", "status_pills", "trend_kcal_weight", "nutrition_activity_summary", "activity_overview", "recovery_sleep_rest", "goals_focus_teaser", "profile_goals_progress", "ai_pipeline_insight", } ) ALLOWED_WIDGET_IDS: frozenset[str] = frozenset(e["id"] for e in WIDGET_CATALOG)