Membership-System und Bug Fixing (inkl. Nutrition) #8
|
|
@ -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() {
|
|||
<div className="card" style={{marginBottom:16,borderColor:'var(--accent)',borderWidth:2}}>
|
||||
<div style={{display:'flex',alignItems:'flex-start',gap:12}}>
|
||||
<div style={{flex:1}}>
|
||||
<div style={{fontWeight:700,fontSize:15,color:'var(--accent)'}}>🔬 Mehrstufige Gesamtanalyse</div>
|
||||
<div style={{fontWeight:700,fontSize:15,color:'var(--accent)'}}>
|
||||
🔬 Mehrstufige Gesamtanalyse
|
||||
{aiUsage && <UsageBadge {...aiUsage} />}
|
||||
</div>
|
||||
<div style={{fontSize:12,color:'var(--text2)',marginTop:3,lineHeight:1.5}}>
|
||||
3 spezialisierte KI-Calls parallel (Körper + Ernährung + Aktivität),
|
||||
dann Synthese + Zielabgleich. Detaillierteste Auswertung.
|
||||
|
|
@ -282,7 +295,10 @@ export default function Analysis() {
|
|||
<div key={p.id} className="card section-gap">
|
||||
<div style={{display:'flex',alignItems:'flex-start',gap:12}}>
|
||||
<div style={{flex:1}}>
|
||||
<div style={{fontWeight:600,fontSize:15}}>{SLUG_LABELS[p.slug]||p.name}</div>
|
||||
<div style={{fontWeight:600,fontSize:15}}>
|
||||
{SLUG_LABELS[p.slug]||p.name}
|
||||
{aiUsage && <UsageBadge {...aiUsage} />}
|
||||
</div>
|
||||
{p.description && <div style={{fontSize:12,color:'var(--text3)',marginTop:2}}>{p.description}</div>}
|
||||
{existing && (
|
||||
<div style={{fontSize:11,color:'var(--text3)',marginTop:3}}>
|
||||
|
|
|
|||
|
|
@ -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() {
|
|||
<button className="btn btn-primary btn-full"
|
||||
onClick={()=>api.exportZip()}>
|
||||
<Download size={14}/> ZIP exportieren
|
||||
{exportUsage && <UsageBadge {...exportUsage} />}
|
||||
<span style={{fontSize:11,opacity:0.8,marginLeft:6}}>— je eine CSV pro Kategorie</span>
|
||||
</button>
|
||||
<button className="btn btn-secondary btn-full"
|
||||
onClick={()=>api.exportJson()}>
|
||||
<Download size={14}/> JSON exportieren
|
||||
{exportUsage && <UsageBadge {...exportUsage} />}
|
||||
<span style={{fontSize:11,opacity:0.8,marginLeft:6}}>— maschinenlesbar, alles in einer Datei</span>
|
||||
</button>
|
||||
</>}
|
||||
|
|
|
|||
|
|
@ -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 */}
|
||||
<div className="card section-gap">
|
||||
<div className="card-title">Eintrag hinzufügen</div>
|
||||
<div className="card-title">
|
||||
Eintrag hinzufügen
|
||||
{weightUsage && <UsageBadge {...weightUsage} />}
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label className="form-label">Datum</label>
|
||||
<input type="date" className="form-input" style={{width:140}}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user