From cd2609da7c7e7fc6e5991ae363103a4e67b5e594 Mon Sep 17 00:00:00 2001 From: Lars Date: Thu, 26 Mar 2026 15:12:39 +0100 Subject: [PATCH] feat: Feature Request #49 - Prompt-Zuordnung zu Verlaufsseiten MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UX Enhancement: Kontextbezogene KI-Analysen Features: - Prompts auf Verlaufsseiten verfΓΌgbar machen - Mehrfachauswahl: Prompt auf mehreren Seiten - Inline-Analyse via Modal - Wiederverwendbare PagePrompts Komponente Technisch: - DB: available_on JSONB column - API: GET /api/prompts/for-page/{page_slug} - UI: Page-Auswahl im Prompt-Editor Aufwand: 6-8h, Priority: Medium Gitea: Issue #49 --- .../issues/issue-51-prompt-page-assignment.md | 425 ++++++++++++++++++ 1 file changed, 425 insertions(+) create mode 100644 docs/issues/issue-51-prompt-page-assignment.md diff --git a/docs/issues/issue-51-prompt-page-assignment.md b/docs/issues/issue-51-prompt-page-assignment.md new file mode 100644 index 0000000..4fc7c72 --- /dev/null +++ b/docs/issues/issue-51-prompt-page-assignment.md @@ -0,0 +1,425 @@ +# Feature: Prompt-Zuordnung zu Verlaufsseiten + +**Labels:** feature, ux, enhancement +**Priority:** Medium (Phase 1-2) +**Related:** Issue #28 (Unified Prompt System - Complete) + +## Beschreibung +KI-Prompts sollen flexibel auf verschiedenen Verlaufsseiten verfΓΌgbar gemacht werden kΓΆnnen. Jeder Prompt kann auf mehreren Seiten gleichzeitig angeboten werden (Mehrfachauswahl). + +## Problem (aktueller Stand) + +**Aktuell:** +- Prompts sind nur ΓΌber die zentrale Analyse-Seite (πŸ“Š Analyse) verfΓΌgbar +- Kein kontextbezogener Zugriff auf relevante Analysen +- User muss immer zur Analyse-Seite navigieren + +**Beispiel-Szenario:** +``` +User ist auf: Gewicht β†’ Verlauf +Will: Gewichtstrend analysieren +Muss: Zur Analyse-Seite β†’ Prompt auswΓ€hlen β†’ ZurΓΌck +``` + +**WΓΌnschenswert:** +``` +User ist auf: Gewicht β†’ Verlauf +Sieht: "πŸ€– KI-Analyse" Button mit relevanten Prompts +Kann: Direkt "Gewichtstrend-Analyse" starten +``` + +## GewΓΌnschtes Verhalten + +### 1. Prompt-Konfiguration erweitern + +**Admin β†’ KI-Prompts β†’ Prompt bearbeiten:** + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Prompt bearbeiten: Gewichtstrend-Analyse β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Name: Gewichtstrend-Analyse β”‚ +β”‚ Slug: weight_trend β”‚ +β”‚ Type: Pipeline β”‚ +β”‚ β”‚ +β”‚ πŸ“ VerfΓΌgbar auf Seiten: β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β˜‘ Analyse (Hauptseite) β”‚ β”‚ +β”‚ β”‚ β˜‘ Gewicht β†’ Verlauf β”‚ β”‚ +β”‚ β”‚ ☐ UmfΓ€nge β†’ Verlauf β”‚ β”‚ +β”‚ β”‚ ☐ Caliper β†’ Verlauf β”‚ β”‚ +β”‚ β”‚ ☐ AktivitΓ€t β†’ Verlauf β”‚ β”‚ +β”‚ β”‚ ☐ ErnΓ€hrung β†’ Verlauf β”‚ β”‚ +β”‚ β”‚ ☐ Schlaf β†’ Verlauf β”‚ β”‚ +β”‚ β”‚ ☐ Vitalwerte β†’ Verlauf β”‚ β”‚ +β”‚ β”‚ ☐ Dashboard β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ [Speichern] [Abbrechen] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Mehrfachauswahl:** +- Ein Prompt kann auf mehreren Seiten gleichzeitig verfΓΌgbar sein +- Mindestens eine Seite muss ausgewΓ€hlt sein +- Default: "Analyse (Hauptseite)" ist immer vorausgewΓ€hlt + +### 2. UI auf Verlaufsseiten + +**Gewicht β†’ Verlauf:** + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ πŸ“Š Gewicht - Verlauf β”‚ +β”‚ [Filter: 7d] [30d] [90d] [Alle] β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ [Chart: Gewichtsverlauf] β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ πŸ€– KI-Analysen β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Gewichtstrend-Analyse [β–Ά Starten]β”‚ β”‚ +β”‚ β”‚ KΓΆrperkomposition-Check [β–Ά Starten]β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ [EintrΓ€ge-Tabelle...] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Features:** +- Kompaktes Widget unterhalb des Charts +- Nur relevante Prompts werden angezeigt +- Button startet Analyse inline (Modal oder expandierend) +- Ergebnis wird direkt auf der Seite angezeigt + +### 3. Inline-Analyse Anzeige + +**Option A: Modal (empfohlen fΓΌr MVP):** +``` +Click auf [β–Ά Starten] + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ βœ• Gewichtstrend-Analyse β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ [Spinner] Analysiere Gewichtsdaten... β”‚ +β”‚ β”‚ +β”‚ [Nach Abschluss:] β”‚ +β”‚ Analyse-Text... β”‚ +β”‚ β”‚ +β”‚ πŸ“Š Verwendete Werte (12) [πŸ”¬ Experten] β”‚ +β”‚ [Value Table...] β”‚ +β”‚ β”‚ +β”‚ [Schließen] [In Verlauf speichern] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Option B: Expandierend (spΓ€ter):** +``` +Click auf [β–Ά Starten] + ↓ +Widget expandiert nach unten +Zeigt Analyse-Ergebnis inline +[β–³ Einklappen] Button +``` + +## Technische Umsetzung + +### 1. Datenbankschema erweitern + +**Tabelle: `ai_prompts`** +```sql +ALTER TABLE ai_prompts ADD COLUMN available_on JSONB DEFAULT '["analysis"]'; + +COMMENT ON COLUMN ai_prompts.available_on IS + 'Array of page slugs where prompt is available. + Values: analysis, weight_history, circ_history, caliper_history, + activity_history, nutrition_history, sleep_history, vitals_history, dashboard'; + +-- Migration 022 +``` + +**Beispiel-Werte:** +```json +{ + "slug": "weight_trend", + "name": "Gewichtstrend-Analyse", + "available_on": ["analysis", "weight_history"] +} + +{ + "slug": "pipeline_master", + "name": "VollstΓ€ndige Analyse", + "available_on": ["analysis", "dashboard"] +} + +{ + "slug": "nutrition_check", + "name": "ErnΓ€hrungs-Check", + "available_on": ["analysis", "nutrition_history", "activity_history"] +} +``` + +### 2. Backend API erweitern + +**Neuer Endpoint: GET /api/prompts/for-page/{page_slug}** + +```python +@router.get("/for-page/{page_slug}") +def get_prompts_for_page(page_slug: str, session: dict = Depends(require_auth)): + """Get all prompts available for a specific page. + + Args: + page_slug: Page identifier (e.g., 'weight_history', 'analysis') + + Returns: + List of prompts with available_on containing page_slug + """ + with get_db() as conn: + cur = get_cursor(conn) + cur.execute( + """SELECT id, name, slug, type, description, available_on + FROM ai_prompts + WHERE available_on @> %s + ORDER BY name""", + (json.dumps([page_slug]),) + ) + return [r2d(row) for row in cur.fetchall()] +``` + +**Beispiel-Aufruf:** +```javascript +// In WeightPage.jsx +const prompts = await api.getPromptsForPage('weight_history') +// Returns: [{slug: 'weight_trend', name: 'Gewichtstrend-Analyse', ...}] +``` + +**Prompt CRUD erweitern:** +```python +@router.put("/unified/{id}") +def update_unified_prompt(id: str, p: UnifiedPromptCreate, session=Depends(require_admin)): + # ... existing code ... + cur.execute( + """UPDATE ai_prompts + SET name=%s, slug=%s, template=%s, ..., available_on=%s + WHERE id=%s""", + (..., json.dumps(p.available_on), id) + ) +``` + +### 3. Frontend: Prompt-Editor erweitern + +**UnifiedPromptModal.jsx:** + +```javascript +const PAGE_OPTIONS = [ + { value: 'analysis', label: 'πŸ“Š Analyse (Hauptseite)', default: true }, + { value: 'weight_history', label: 'βš–οΈ Gewicht β†’ Verlauf' }, + { value: 'circ_history', label: 'πŸ“ UmfΓ€nge β†’ Verlauf' }, + { value: 'caliper_history', label: 'πŸ“ Caliper β†’ Verlauf' }, + { value: 'activity_history', label: 'πŸƒ AktivitΓ€t β†’ Verlauf' }, + { value: 'nutrition_history', label: '🍎 ErnΓ€hrung β†’ Verlauf' }, + { value: 'sleep_history', label: '😴 Schlaf β†’ Verlauf' }, + { value: 'vitals_history', label: '❀️ Vitalwerte β†’ Verlauf' }, + { value: 'dashboard', label: '🏠 Dashboard' }, +] + +// In form: +
+ +
+ {PAGE_OPTIONS.map(opt => ( + + ))} +
+
+``` + +### 4. Frontend: Verlaufsseiten erweitern + +**WeightPage.jsx (Beispiel):** + +```javascript +function WeightPage() { + const [prompts, setPrompts] = useState([]) + const [runningAnalysis, setRunningAnalysis] = useState(null) + const [analysisResult, setAnalysisResult] = useState(null) + + useEffect(() => { + loadPrompts() + }, []) + + const loadPrompts = async () => { + try { + const data = await api.getPromptsForPage('weight_history') + setPrompts(data) + } catch(e) { + console.error('Failed to load prompts:', e) + } + } + + const runAnalysis = async (promptSlug) => { + setRunningAnalysis(promptSlug) + try { + const result = await api.executePrompt(promptSlug, {save: true}) + setAnalysisResult(result) + } catch(e) { + setError(e.message) + } finally { + setRunningAnalysis(null) + } + } + + return ( +
+

Gewicht - Verlauf

+ + {/* Chart */} + + + {/* AI Prompts Widget */} + {prompts.length > 0 && ( +
+

πŸ€– KI-Analysen

+ {prompts.map(p => ( + + ))} +
+ )} + + {/* Analysis Result Modal */} + {analysisResult && ( + setAnalysisResult(null)} + /> + )} + + {/* Data Table */} + +
+ ) +} +``` + +**Wiederverwendbare Komponente:** +```javascript +// components/PagePrompts.jsx +export function PagePrompts({ pageSlug }) { + // ... logic ... + return ( +
+

πŸ€– KI-Analysen

+ {prompts.map(p => ( + + ))} +
+ ) +} + +// Usage in any page: + +``` + +## Akzeptanzkriterien + +- [ ] DB-Migration: `available_on` JSONB column in ai_prompts +- [ ] Backend: `GET /api/prompts/for-page/{page_slug}` Endpoint +- [ ] Backend: CRUD operations unterstΓΌtzen available_on +- [ ] Frontend: Prompt-Editor zeigt Page-Auswahl (Mehrfachauswahl) +- [ ] Frontend: Mindestens 1 Page muss ausgewΓ€hlt sein +- [ ] Frontend: Wiederverwendbare PagePrompts Komponente +- [ ] Frontend: Integration in mind. 2 Verlaufsseiten (Weight, Nutrition) +- [ ] UI: Inline-Analyse via Modal mit Value Table +- [ ] UI: Loading-State wΓ€hrend Analyse lΓ€uft +- [ ] Dokumentation: API-Dokumentation aktualisiert + +## AbschΓ€tzung + +**Aufwand:** 6-8 Stunden +- 1h: DB-Migration + Backend Endpoint +- 2h: Prompt-Editor erweitern (Page-Auswahl) +- 2h: PagePrompts Komponente + Modal +- 2h: Integration in Verlaufsseiten (2-3 Seiten) +- 1h: Testing + Feintuning + +**PrioritΓ€t:** Medium +- Verbessert UX erheblich (kontextbezogene Analysen) +- Nutzt bestehendes Prompt-System (Issue #28) +- Relativ einfach zu implementieren (kein neues Backend-System) + +## Use Cases + +### UC1: Gewichtstrend auf Gewicht-Seite +``` +User: Navigiert zu "Gewicht β†’ Verlauf" +System: Zeigt Gewichts-Chart + verfΓΌgbare Prompts +User: Click "Gewichtstrend-Analyse β–Ά" +System: Startet Analyse, zeigt Modal mit Ergebnis +User: Click "In Verlauf speichern" +System: Speichert in ai_insights, zeigt in Analyse-Verlauf +``` + +### UC2: ErnΓ€hrungs-Check auf ErnΓ€hrung-Seite +``` +User: Navigiert zu "ErnΓ€hrung β†’ Verlauf" +System: Zeigt ErnΓ€hrungs-Charts + verfΓΌgbare Prompts +User: Click "ErnΓ€hrungs-Check β–Ά" +System: Analysiert Makros + Kalorien der letzten 7 Tage +User: Sieht Empfehlungen direkt auf ErnΓ€hrungs-Seite +``` + +### UC3: Multi-Page Prompt (z.B. "VollstΓ€ndige Analyse") +``` +Admin: Konfiguriert "VollstΓ€ndige Analyse" + - VerfΓΌgbar auf: [Analyse, Dashboard, Gewicht, ErnΓ€hrung] +User: Sieht denselben Prompt auf 4 verschiedenen Seiten +User: Kann von ΓΌberall die gleiche umfassende Analyse starten +``` + +## Notizen + +- **RΓΌckwΓ€rtskompatibilitΓ€t:** Bestehende Prompts ohne `available_on` β†’ Default `["analysis"]` +- **Migration:** Alle existierenden Prompts bekommen `["analysis"]` gesetzt +- **Permissions:** Prompts respektieren weiterhin Feature-Enforcement (ai_calls) +- **Caching:** Prompts kΓΆnnten gecacht werden (selten geΓ€ndert) +- **Mobile:** PagePrompts sollte auch auf Mobile gut aussehen (Stack-Layout) +- **Performance:** Lazy-Loading der Prompts (nur laden wenn Seite besucht) + +## Erweiterungen (Future) + +- **Conditional Display:** Prompts nur anzeigen wenn Daten vorhanden + - Beispiel: "Gewichtstrend" nur wenn min. 3 Gewichts-EintrΓ€ge +- **Quick Actions:** Direkt-Buttons im Chart (ohne separates Widget) +- **Page-spezifische Variablen:** Automatisch aktuelle Filter ΓΌbergeben + - Beispiel: Wenn "30d" Filter aktiv β†’ `{{timeframe}}` = 30 +- **Prompt-Templates pro Page:** Vordefinierte Vorlagen fΓΌr jede Seite +- **Favoriten:** User kann Prompts auf Seiten favorisieren (User-spezifisch) + +## Verwandte Issues + +- #28: Unified Prompt System (Basis fΓΌr dieses Feature) +- #45: KI Prompt-Optimierer (kΓΆnnte Page-Kontext nutzen) +- #46: KI Prompt-Ersteller (sollte Page-Auswahl anbieten)