""" Dashboard: zusammengefasste Kennzahlen (ein Roundtrip statt mehrerer Listen). """ from __future__ import annotations from datetime import date from typing import Any, Dict, List from fastapi import APIRouter, Depends from tenant_context import TenantContext, get_tenant_context from routers.exercises import list_exercises_like_get from routers.training_planning import list_training_units router = APIRouter(prefix="/api", tags=["dashboard"]) def _slice_training_home_notes(planned_pool: List[Dict[str, Any]], max_notes: int = 5) -> List[Dict[str, Any]]: out = [] for u in planned_pool: tn = (u.get("trainer_notes") or "").strip() n = (u.get("notes") or "").strip() if tn or n: out.append(u) if len(out) >= max_notes: break return out @router.get("/dashboard/kpis") def get_dashboard_kpis(tenant: TenantContext = Depends(get_tenant_context)): """ Kurzüberblick: Übungs-KPIs + YTD-Einheiten + Trainings-Home (nächste Termine, Vermerke, offene Rückschau) in einem Roundtrip — gleiche Filter wie zuvor im Dashboard (mehrere Client-Calls). """ year = date.today().year year_start = f"{year}-01-01" year_end = f"{year}-12-31" today = date.today().isoformat() draft_list = list_exercises_like_get( tenant, created_by_me=True, status="draft", limit=100 ) mine_list = list_exercises_like_get( tenant, created_by_me=True, status=None, limit=100 ) ytd_completed = list_training_units( group_id=None, club_id=None, start_date=year_start, end_date=year_end, status="completed", assigned_to_me=True, debrief_pending=False, sort="desc", limit=250, tenant=tenant, ) planned_pool = list_training_units( group_id=None, club_id=None, start_date=today, end_date=None, status="planned", assigned_to_me=True, debrief_pending=False, sort="asc", limit=40, tenant=tenant, ) review_pending = list_training_units( group_id=None, club_id=None, start_date=None, end_date=None, status=None, assigned_to_me=True, debrief_pending=True, sort="desc", limit=8, tenant=tenant, ) draft_preview = [ {"id": int(ex["id"]), "title": ex.get("title") or f"Übung #{ex['id']}"} for ex in draft_list[:8] ] return { "year": year, "draft_count": len(draft_list), "draft_capped": len(draft_list) >= 100, "draft_preview": draft_preview, "mine_count": len(mine_list), "mine_capped": len(mine_list) >= 100, "ytd_completed_count": len(ytd_completed), "ytd_capped": len(ytd_completed) >= 250, "training_home": { "upcoming": planned_pool[:8], "planned_with_notes": _slice_training_home_notes(planned_pool), "review_pending": review_pending, }, }