refactor: mehrstufiger Quality-Filter statt Toggle (#24)
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:
parent
9ec774e956
commit
848ba0a815
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user