refactor: mehrstufiger Quality-Filter statt Toggle (#24)
All checks were successful
Deploy Development / deploy (push) Successful in 51s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 14s

Statt einfachem On/Off Toggle jetzt 4 Qualitätsstufen:
- 📊 Alle (kein Filter)
- ✓ Hochwertig (excellent + good + acceptable)
- ✓✓ Sehr gut (excellent + good)
-  Exzellent (nur excellent)

UI:
- Button-Group (Segmented Control) mit 4 Stufen
- Beschreibung welche Labels inkludiert werden
- Anzeige: X von Y Aktivitäten (wenn gefiltert)

User-Feedback: Stufenweiser Filter ist flexibler als binärer Toggle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lars 2026-03-23 22:04:29 +01:00
parent 9ec774e956
commit 848ba0a815

View File

@ -588,16 +588,22 @@ function NutritionSection({ nutrition, weights, profile, insights, onRequest, lo
// Activity Section
function ActivitySection({ activities, insights, onRequest, loadingSlug, filterActiveSlugs }) {
const [period, setPeriod] = useState(30)
const [qualityFilter, setQualityFilter] = useState(false) // Issue #24: Quality-Filter Toggle
const [qualityLevel, setQualityLevel] = useState('all') // Issue #24: Quality-Filter (all, quality, very_good, excellent)
if (!activities?.length) return (
<EmptySection text="Noch keine Aktivitätsdaten." to="/activity" toLabel="Aktivität erfassen"/>
)
const cutoff = dayjs().subtract(period,'day').format('YYYY-MM-DD')
// Issue #24: Filter nach Datum UND Quality-Label
const filtA = activities.filter(d =>
(period===9999 || d.date>=cutoff) &&
(!qualityFilter || ['excellent', 'good', 'acceptable'].includes(d.quality_label))
)
// Issue #24: Mehrstufiger Quality-Filter
const filtA = activities.filter(d => {
if (period !== 9999 && d.date < cutoff) return false
if (qualityLevel === 'all') return true
if (qualityLevel === 'quality') return ['excellent', 'good', 'acceptable'].includes(d.quality_label)
if (qualityLevel === 'very_good') return ['excellent', 'good'].includes(d.quality_label)
if (qualityLevel === 'excellent') return d.quality_label === 'excellent'
return true
})
const byDate={}
filtA.forEach(a=>{ byDate[a.date]=(byDate[a.date]||0)+(a.kcal_active||0) })
@ -626,20 +632,34 @@ function ActivitySection({ activities, insights, onRequest, loadingSlug, filterA
<SectionHeader title="🏋️ Aktivität" to="/activity" toLabel="Alle Einträge" lastUpdated={activities[0]?.date}/>
<PeriodSelector value={period} onChange={setPeriod}/>
{/* Issue #24: Quality-Filter Toggle */}
<div style={{marginBottom:12,display:'flex',alignItems:'center',gap:8}}>
<label style={{display:'flex',alignItems:'center',gap:6,fontSize:12,cursor:'pointer',
padding:'6px 10px',borderRadius:8,background:qualityFilter?'var(--accent-light)':'var(--surface2)',
border:`1px solid ${qualityFilter?'var(--accent)':'var(--border)'}`,
color:qualityFilter?'var(--accent)':'var(--text2)',transition:'all 0.2s'}}>
<input type="checkbox" checked={qualityFilter} onChange={e=>setQualityFilter(e.target.checked)}
style={{width:14,height:14,cursor:'pointer',accentColor:'var(--accent)'}}/>
<span style={{fontWeight:qualityFilter?600:400}}>Nur qualitativ hochwertige Aktivitäten</span>
</label>
{qualityFilter && (
<span style={{fontSize:11,color:'var(--text3)'}}>
({filtA.length} von {activities.filter(d=>period===9999||d.date>=cutoff).length})
</span>
{/* Issue #24: Mehrstufiger Quality-Filter */}
<div style={{marginBottom:12}}>
<div style={{fontSize:11,fontWeight:600,color:'var(--text3)',marginBottom:6}}>QUALITÄTSFILTER</div>
<div style={{display:'flex',gap:4}}>
{[
{v:'all', l:'Alle', icon:'📊'},
{v:'quality', l:'Hochwertig', icon:'✓'},
{v:'very_good', l:'Sehr gut', icon:'✓✓'},
{v:'excellent', l:'Exzellent', icon:'⭐'}
].map(o => (
<button key={o.v} onClick={() => setQualityLevel(o.v)}
style={{flex:1,padding:'6px 8px',borderRadius:8,fontSize:11,fontWeight:500,
border:'1.5px solid',cursor:'pointer',fontFamily:'var(--font)',transition:'all 0.2s',
background:qualityLevel===o.v?'var(--accent)':'transparent',
borderColor:qualityLevel===o.v?'var(--accent)':'var(--border2)',
color:qualityLevel===o.v?'white':'var(--text2)'}}>
<span style={{marginRight:4}}>{o.icon}</span>
{o.l}
</button>
))}
</div>
{qualityLevel !== 'all' && (
<div style={{fontSize:10,color:'var(--text3)',marginTop:6}}>
{filtA.length} von {activities.filter(d=>period===9999||d.date>=cutoff).length} Aktivitäten
{qualityLevel === 'quality' && ' (excellent, good, acceptable)'}
{qualityLevel === 'very_good' && ' (excellent, good)'}
{qualityLevel === 'excellent' && ' (nur excellent)'}
</div>
)}
</div>