diff --git a/backend/routes.py b/backend/routes.py index bb1edb0..793f3e8 100644 --- a/backend/routes.py +++ b/backend/routes.py @@ -1,4 +1,5 @@ import asyncio +import json import shutil import uuid from datetime import datetime, timezone @@ -45,6 +46,38 @@ async def get_topics(): return db_topics + sorted(derived - set(db_topics)) +@router.get("/stats") +async def get_stats(): + """Tracker: Themen-Anzahl + pro Format erstellt/absolviert (alle Kapitel abgehakt).""" + guides = await list_guides() + themen = set(await db_list_topics()) | {g["topic"] for g in guides} | set(bausteine_topics()) + if PROJECTS_DIR.is_dir(): + themen |= {e.name for e in PROJECTS_DIR.iterdir() if e.is_dir()} + + formate = {} + for fmt in ("MiniGuide", "Guide", "FullGuide"): + # Pro Thema zählt nur der neueste fertige Guide (Altläufe teilen die Content-Datei) + neueste: dict[str, dict] = {} + for g in guides: + if g["format"] == fmt and g["status"] == "done": + if g["topic"] not in neueste or g["created_at"] > neueste[g["topic"]]["created_at"]: + neueste[g["topic"]] = g + absolviert = 0 + for g in neueste.values(): + path = guide_content_path(g["topic"], fmt) + if not path.exists(): + continue + try: + chapters = json.loads(path.read_text(encoding="utf-8")).get("chapters", []) + except ValueError: + continue + titles = {c.get("title") for c in chapters} + if titles and titles <= set(await list_progress(g["id"])): + absolviert += 1 + formate[fmt] = {"erstellt": len(neueste), "absolviert": absolviert} + return {"themen": len(themen), "formate": formate} + + @router.post("/topics") async def add_topic(req: TopicCreateRequest): await create_topic(req.name.strip()) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index f665dd9..94e38e5 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,6 +1,6 @@