2026-04-07 11:47:16 +02:00
|
|
|
|
"""
|
|
|
|
|
|
Ö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, TypedDict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WidgetCatalogEntry(TypedDict):
|
|
|
|
|
|
id: str
|
|
|
|
|
|
title: str
|
|
|
|
|
|
description: str
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-04-07 14:19:45 +02:00
|
|
|
|
# Reihenfolge = Default-Layout-Reihenfolge. Aktiv-Flags: DEFAULT_LAB_WIDGET_IDS (Rest zunächst aus).
|
2026-04-07 11:47:16 +02:00
|
|
|
|
WIDGET_CATALOG: list[WidgetCatalogEntry] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "welcome",
|
|
|
|
|
|
"title": "Willkommen",
|
|
|
|
|
|
"description": "Begrüßung und Kurzkontext",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "quick_capture",
|
|
|
|
|
|
"title": "Schnelleingabe",
|
2026-04-07 18:02:18 +02:00
|
|
|
|
"description": "Gewicht + Baseline-Vitals; optional show_weight / show_resting_hr / show_hrv / show_vo2_max (false = aus)",
|
2026-04-07 11:47:16 +02:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "kpi_board",
|
|
|
|
|
|
"title": "KPI-Kacheln",
|
2026-04-07 12:46:18 +02:00
|
|
|
|
"description": "Referenzwerte, KF%, Ø-Kalorien — optional Kacheln & Reihenfolge (config.tiles, max. 9)",
|
2026-04-07 11:47:16 +02:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "body_overview",
|
|
|
|
|
|
"title": "Körper (Chart)",
|
2026-04-07 11:58:07 +02:00
|
|
|
|
"description": "Gewicht & Kennzahlen (optional: config chart_days 7–90)",
|
2026-04-07 11:47:16 +02:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "activity_overview",
|
|
|
|
|
|
"title": "Aktivität",
|
2026-04-07 18:02:18 +02:00
|
|
|
|
"description": "Trainingstyp-Verteilung (Kuchen) + Konsistenz — Zeitraum über config chart_days 7–90",
|
2026-04-07 11:47:16 +02:00
|
|
|
|
},
|
2026-04-07 14:19:45 +02:00
|
|
|
|
{
|
|
|
|
|
|
"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)",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "body_stat_strip",
|
|
|
|
|
|
"title": "Kennzahlen-Kacheln",
|
|
|
|
|
|
"description": "Gewicht, KF, Magermasse, Ø-kcal — Oberreihe",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "status_pills",
|
|
|
|
|
|
"title": "Indikatoren (Pills)",
|
|
|
|
|
|
"description": "WHR, WHtR, Protein, KF",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"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)",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "nutrition_activity_summary",
|
|
|
|
|
|
"title": "Ernährung & Aktivität Kurz",
|
|
|
|
|
|
"description": "Ø 7T Kacheln",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"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",
|
|
|
|
|
|
},
|
2026-04-07 11:47:16 +02:00
|
|
|
|
]
|
|
|
|
|
|
|
2026-04-07 14:19:45 +02:00
|
|
|
|
DEFAULT_LAB_WIDGET_IDS: frozenset[str] = frozenset(
|
|
|
|
|
|
{
|
|
|
|
|
|
"welcome",
|
|
|
|
|
|
"quick_capture",
|
|
|
|
|
|
"kpi_board",
|
|
|
|
|
|
"body_overview",
|
|
|
|
|
|
"activity_overview",
|
|
|
|
|
|
}
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-04-07 11:47:16 +02:00
|
|
|
|
ALLOWED_WIDGET_IDS: frozenset[str] = frozenset(e["id"] for e in WIDGET_CATALOG)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def catalog_response() -> dict[str, Any]:
|
|
|
|
|
|
"""Payload für GET /api/app/widgets/catalog."""
|
|
|
|
|
|
return {
|
|
|
|
|
|
"catalog_version": 1,
|
|
|
|
|
|
"widgets": list(WIDGET_CATALOG),
|
|
|
|
|
|
}
|