From c59c71a1c72375ed2918086fe9676f2b0107dd45 Mon Sep 17 00:00:00 2001 From: Lars Date: Sat, 21 Mar 2026 06:43:10 +0100 Subject: [PATCH] feat: add UsageBadge to action buttons (Phase 3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Weight page: badge on "Eintrag hinzufĂĽgen" heading - Settings: badges on export buttons (ZIP/JSON) - Analysis: badges on pipeline and individual analysis titles - Shows real-time usage status (e.g., "7/5" with red color) Phase 3: Frontend Display complete Co-Authored-By: Claude Opus 4.6 --- frontend/src/pages/Analysis.jsx | 22 +++++++++++++++++++--- frontend/src/pages/SettingsPage.jsx | 14 +++++++++++++- frontend/src/pages/WeightScreen.jsx | 17 +++++++++++++++-- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/frontend/src/pages/Analysis.jsx b/frontend/src/pages/Analysis.jsx index 128b34f..6cf29aa 100644 --- a/frontend/src/pages/Analysis.jsx +++ b/frontend/src/pages/Analysis.jsx @@ -3,6 +3,7 @@ import { Brain, Pencil, Trash2, ChevronDown, ChevronUp, Check, X } from 'lucide- import { api } from '../utils/api' import { useAuth } from '../context/AuthContext' import Markdown from '../utils/Markdown' +import UsageBadge from '../components/UsageBadge' import dayjs from 'dayjs' import 'dayjs/locale/de' dayjs.locale('de') @@ -114,6 +115,7 @@ export default function Analysis() { const [tab, setTab] = useState('run') const [newResult, setNewResult] = useState(null) const [pipelineLoading, setPipelineLoading] = useState(false) + const [aiUsage, setAiUsage] = useState(null) // Phase 3: Usage badge const loadAll = async () => { const [p, i] = await Promise.all([ @@ -123,7 +125,15 @@ export default function Analysis() { setPrompts(Array.isArray(p)?p:[]) setAllInsights(Array.isArray(i)?i:[]) } - useEffect(()=>{ loadAll() },[]) + + useEffect(()=>{ + loadAll() + // Load feature usage for badges + api.getFeatureUsage().then(features => { + const aiFeature = features.find(f => f.feature_id === 'ai_calls') + setAiUsage(aiFeature) + }).catch(err => console.error('Failed to load usage:', err)) + },[]) const runPipeline = async () => { setPipelineLoading(true); setError(null); setNewResult(null) @@ -230,7 +240,10 @@ export default function Analysis() {
-
🔬 Mehrstufige Gesamtanalyse
+
+ 🔬 Mehrstufige Gesamtanalyse + {aiUsage && } +
3 spezialisierte KI-Calls parallel (Körper + Ernährung + Aktivität), dann Synthese + Zielabgleich. Detaillierteste Auswertung. @@ -282,7 +295,10 @@ export default function Analysis() {
-
{SLUG_LABELS[p.slug]||p.name}
+
+ {SLUG_LABELS[p.slug]||p.name} + {aiUsage && } +
{p.description &&
{p.description}
} {existing && (
diff --git a/frontend/src/pages/SettingsPage.jsx b/frontend/src/pages/SettingsPage.jsx index 704d84a..e893f46 100644 --- a/frontend/src/pages/SettingsPage.jsx +++ b/frontend/src/pages/SettingsPage.jsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useState, useEffect } from 'react' import { Save, Download, Upload, Trash2, Plus, Check, Pencil, X, LogOut, Shield, Key, BarChart3 } from 'lucide-react' import { useProfile } from '../context/ProfileContext' import { useAuth } from '../context/AuthContext' @@ -6,6 +6,7 @@ import { Avatar } from './ProfileSelect' import { api } from '../utils/api' import AdminPanel from './AdminPanel' import FeatureUsageOverview from '../components/FeatureUsageOverview' +import UsageBadge from '../components/UsageBadge' const COLORS = ['#1D9E75','#378ADD','#D85A30','#EF9F27','#7F77DD','#D4537E','#639922','#888780'] @@ -100,6 +101,15 @@ export default function SettingsPage() { const [pinOpen, setPinOpen] = useState(false) const [newPin, setNewPin] = useState('') const [pinMsg, setPinMsg] = useState(null) + const [exportUsage, setExportUsage] = useState(null) // Phase 3: Usage badge + + // Load feature usage for export badges + useEffect(() => { + api.getFeatureUsage().then(features => { + const exportFeature = features.find(f => f.feature_id === 'data_export') + setExportUsage(exportFeature) + }).catch(err => console.error('Failed to load usage:', err)) + }, []) const handleLogout = async () => { if (!confirm('Ausloggen?')) return @@ -372,11 +382,13 @@ export default function SettingsPage() { } diff --git a/frontend/src/pages/WeightScreen.jsx b/frontend/src/pages/WeightScreen.jsx index 10dd81c..f2e82e3 100644 --- a/frontend/src/pages/WeightScreen.jsx +++ b/frontend/src/pages/WeightScreen.jsx @@ -2,6 +2,7 @@ import { useState, useEffect, useRef } from 'react' import { Pencil, Trash2, Check, X } from 'lucide-react' import { api } from '../utils/api' import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, CartesianGrid, ReferenceLine } from 'recharts' +import UsageBadge from '../components/UsageBadge' import dayjs from 'dayjs' import 'dayjs/locale/de' dayjs.locale('de') @@ -21,9 +22,18 @@ export default function WeightScreen() { const [newNote, setNewNote] = useState('') const [saving, setSaving] = useState(false) const [saved, setSaved] = useState(false) + const [weightUsage, setWeightUsage] = useState(null) // Phase 3: Usage badge const load = () => api.listWeight(365).then(data => setEntries(data)) - useEffect(()=>{ load() },[]) + + useEffect(()=>{ + load() + // Load feature usage for badge + api.getFeatureUsage().then(features => { + const weightFeature = features.find(f => f.feature_id === 'weight_entries') + setWeightUsage(weightFeature) + }).catch(err => console.error('Failed to load usage:', err)) + },[]) const handleSave = async () => { if (!newWeight) return @@ -59,7 +69,10 @@ export default function WeightScreen() { {/* Eingabe */}
-
Eintrag hinzufĂĽgen
+
+ Eintrag hinzufĂĽgen + {weightUsage && } +