- .gitignore: .claude/docs, rules, commands tracken; settings.local weiter ignorieren - DOCUMENTATION.md: verbindliche Ablage functional/technical/working/issues - .claude/README.md: Agent-Einstieg; GITEA_ISSUES_INDEX aus MCP (Stand 2026-04-08) - Arbeitspapiere von docs/ nach .claude/docs/working/ verschoben - docs/MEMBERSHIP_SYSTEM.md als Stub; kanonisch technical/MEMBERSHIP_SYSTEM.md - CLAUDE.md Pflichtlektüre und Links angepasst; docs/README.md vereinfacht Made-with: Cursor
7.6 KiB
Phase 0c – Architecture Cleanup & Refactoring
Datum: 2026-03-28 Voraussetzung: Phase 0b abgeschlossen Geschätzter Aufwand: 12-16 Stunden
Ziele
Phase 0c fokussiert auf Architektur-Verbesserungen und Structured Data, ohne neue Features hinzuzufügen.
Kernprinzip: Von Formatted Strings zu Structured Data → Basis für Phase 0c Refactoring (Charts/Diagramme).
Task 1: Dynamic Aggregation Methods (3-4h)
Problem: Aggregationsmethoden sind im Frontend hardcoded.
Lösung:
Backend
# backend/routers/goal_types.py
@router.get("/aggregation-methods")
def get_aggregation_methods():
"""Return all available aggregation methods with metadata"""
return [
{
"value": "latest",
"label_de": "Letzter Wert",
"label_en": "Latest",
"description": "Aktuellster Wert aus Tabelle",
"compatible_types": ["DECIMAL", "INTEGER", "FLOAT"],
"requires_numeric": False
},
{
"value": "avg_7d",
"label_de": "Durchschnitt 7 Tage",
"label_en": "7-day average",
"description": "Mittelwert über 7 Tage",
"compatible_types": ["DECIMAL", "INTEGER", "FLOAT"],
"requires_numeric": True
},
# ... alle Methoden aus goal_utils.py
]
Implementierung:
- Endpoint erstellen (goal_types.py)
- Auto-Discovery aus goal_utils.py Docstrings oder Introspection
- Frontend anpassen (AdminGoalTypesPage.jsx)
- Migration für Backfill (falls nötig)
Dokumentation: .claude/docs/technical/AGGREGATION_METHODS.md (exists)
Task 2: Dynamic Placeholder Catalog (4-5h)
Problem: Platzhalter sind im Frontend nicht sichtbar/suchbar.
Lösung:
Backend
# backend/routers/prompts.py
@router.get("/placeholders/catalog")
def get_placeholder_catalog(session: dict = Depends(require_auth)):
"""
Return all registered placeholders with metadata.
Enables auto-complete and placeholder selector in frontend.
"""
return {
"categories": [
{
"name": "Profil",
"placeholders": [
{
"key": "name",
"placeholder": "{{name}}",
"description": "Name des Nutzers",
"example": "Lars",
"data_type": "string"
},
# ...
]
},
# ... weitere Kategorien
],
"total_count": 111
}
Frontend
// PlaceholderSelector Component
<PlaceholderSelector
onSelect={(placeholder) => insertAtCursor(placeholder)}
categories={fetchedCatalog.categories}
searchable={true}
showExamples={true}
/>
Implementierung:
- Endpoint erstellen (nutzt PLACEHOLDER_CATALOG aus placeholder_resolver.py)
- React Component: PlaceholderSelector
- Integration in UnifiedPromptModal (Prompt-Editor)
- Keyboard-Shortcuts (Strg+Space für Auto-Complete)
Dokumentation: .claude/docs/technical/PLACEHOLDER_SYSTEM.md (neu erstellen)
Task 3: Calculation Functions → Structured Return (5-7h)
Problem: Calculation Functions returnen formatted strings statt strukturierte Daten.
Lösung: Refactoring aller Calculation Functions zu structured return.
Beispiel-Refactoring
Vorher (Phase 0b):
def calculate_weight_trend(profile_id: str) -> str:
# ... calculation ...
return f"sinkend (-0.9 kg in 28 Tagen)"
Nachher (Phase 0c):
def calculate_weight_trend(profile_id: str) -> Dict:
# ... calculation ...
return {
"raw_value": -0.9,
"unit": "kg",
"period_days": 28,
"direction": "decreasing", # "increasing", "stable"
"confidence": "high", # "high", "medium", "low"
"data_points": 15,
"slope_per_day": -0.032
}
Formatting Layer
# placeholder_resolver.py
def format_weight_trend(data: Dict) -> str:
"""Format structured weight trend for AI prompts"""
direction_de = {"decreasing": "sinkend", "increasing": "steigend", "stable": "stabil"}
return f"{direction_de[data['direction']]} ({data['raw_value']} {data['unit']} in {data['period_days']} Tagen)"
Betroffene Module
calculations/body_metrics.py(~15 Funktionen)calculations/nutrition_metrics.py(~12 Funktionen)calculations/activity_metrics.py(~18 Funktionen)calculations/recovery_metrics.py(~10 Funktionen)calculations/scores.py(~8 Funktionen)
Gesamt: ~63 Funktionen zu refactoren
Strategie
- Phase 0c/1: Body Metrics (Proof of Concept)
- Phase 0c/2: Nutrition + Activity
- Phase 0c/3: Recovery + Scores
- Phase 0c/4: Placeholder Resolver anpassen (Formatter)
Dokumentation:
.claude/docs/technical/CALCULATION_FUNCTIONS.md(neu).claude/docs/functional/mitai_jinkendo_konzept_diagramme_auswertungen_v2.md(exists, Kontext für Chart-System)
Task 4: Stats/Chart Endpoints (Optional, 3-4h)
Voraussetzung: Task 3 abgeschlossen
Lösung: Separate Endpoints für Chart-Daten (nutzen structured calculation returns)
# backend/routers/stats.py (new)
@router.get("/stats/body/weight-trend")
def get_weight_trend_stats(
days: int = 30,
session: dict = Depends(require_auth)
):
"""Return structured weight trend data for charts"""
trend_data = calculate_weight_trend(session['profile_id'])
return {
"trend": trend_data,
"timeseries": [...], # Daily data points
"projections": {...} # Linear projection
}
Implementierung:
- Neuer Router:
stats.py - Endpoints für alle Chart-relevanten Metriken
- OpenAPI Schema (für Frontend Type-Generation)
Abhängigkeiten
Task 1 (Aggregation Methods) ─┐
├─> Unabhängig, parallel möglich
Task 2 (Placeholder Catalog) ─┘
Task 3 (Structured Returns) ──> Voraussetzung für Task 4
Task 4 (Stats Endpoints) ──> Optional, nutzt Task 3 Results
Akzeptanzkriterien Phase 0c
Muss (Must-Have):
- ✅ Aggregation Methods API-gesteuert
- ✅ Placeholder Catalog API verfügbar
- ✅ Mindestens 1 Modul (Body Metrics) zu structured return refactored
- ✅ Dokumentation für alle 3 Tasks
Sollte (Should-Have):
- ✅ Alle Calculation Functions refactored
- ✅ Frontend Placeholder Selector implementiert
- ✅ Stats Endpoints für Body + Nutrition
Kann (Nice-to-Have):
- ⚪ Stats Endpoints für alle Module
- ⚪ Chart-Preview in Admin-Panel
- ⚪ TypeScript Type-Generation aus OpenAPI
Rollback-Plan
Falls Task 3 (Structured Returns) Probleme verursacht:
- Calculation Functions returnen beide Formate:
return { "formatted": "sinkend (-0.9 kg)", # Backward-compat "structured": {...} # New format } - Placeholder Resolver nutzt
formattedweiterhin - Stats Endpoints nutzen
structured - Schrittweise Migration ohne Breaking Changes
Timeline (geschätzt)
Option A (Serial): 12-16 Stunden über 2-3 Tage Option B (Parallel): 8-10 Stunden mit 2 Personen
Empfehlung: Option A, da Tasks eng verzahnt sind.
Nach Phase 0c
Enabler für:
- ✅ Chart/Diagram System (Phase 1)
- ✅ Goal Progress Visualizations
- ✅ Custom Dashboards
- ✅ PDF/Excel Export mit strukturierten Daten
- ✅ API für externe Tools (z.B. Home Assistant)
Nächste Phase (Phase 1):
- Chart Library Integration (Recharts/Victory)
- Interactive Dashboards
- Goal Progress Tracking UI