- Add RestDaysWidget component showing today's rest days with icons & colors - Integrate widget into Dashboard (above training distribution) - Highlight current day in RestDaysPage (accent border + HEUTE badge) - Fix: Improve error handling in api.js (parse JSON detail field) Part of v9d Phase 2 (Vitals & Recovery)
121 lines
3.2 KiB
JavaScript
121 lines
3.2 KiB
JavaScript
import { useState, useEffect } from 'react'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import { api } from '../utils/api'
|
|
import dayjs from 'dayjs'
|
|
import 'dayjs/locale/de'
|
|
dayjs.locale('de')
|
|
|
|
const FOCUS_ICONS = {
|
|
muscle_recovery: '💪',
|
|
cardio_recovery: '🏃',
|
|
mental_rest: '🧘',
|
|
deload: '📉',
|
|
injury: '🩹',
|
|
}
|
|
|
|
const FOCUS_LABELS = {
|
|
muscle_recovery: 'Muskelregeneration',
|
|
cardio_recovery: 'Cardio-Erholung',
|
|
mental_rest: 'Mentale Erholung',
|
|
deload: 'Deload',
|
|
injury: 'Verletzungspause',
|
|
}
|
|
|
|
const FOCUS_COLORS = {
|
|
muscle_recovery: '#D85A30',
|
|
cardio_recovery: '#378ADD',
|
|
mental_rest: '#7B68EE',
|
|
deload: '#E67E22',
|
|
injury: '#E74C3C',
|
|
}
|
|
|
|
export default function RestDaysWidget() {
|
|
const [todayRestDays, setTodayRestDays] = useState([])
|
|
const [loading, setLoading] = useState(true)
|
|
const nav = useNavigate()
|
|
|
|
useEffect(() => {
|
|
loadTodayRestDays()
|
|
}, [])
|
|
|
|
const loadTodayRestDays = async () => {
|
|
try {
|
|
const today = dayjs().format('YYYY-MM-DD')
|
|
const allRestDays = await api.listRestDays(7) // Last 7 days
|
|
const todayOnly = allRestDays.filter(d => d.date === today)
|
|
setTodayRestDays(todayOnly)
|
|
} catch (err) {
|
|
console.error('Failed to load rest days:', err)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="card">
|
|
<div className="card-title">🛌 Ruhetage</div>
|
|
<div style={{ padding: '20px 0', textAlign: 'center', color: 'var(--text3)' }}>
|
|
Lädt...
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="card">
|
|
<div className="card-title">🛌 Ruhetage</div>
|
|
|
|
{todayRestDays.length === 0 ? (
|
|
<div style={{ padding: '12px 0', color: 'var(--text3)', fontSize: 13 }}>
|
|
Heute kein Ruhetag geplant
|
|
</div>
|
|
) : (
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
{todayRestDays.map(day => {
|
|
const focus = day.rest_config?.focus || 'mental_rest'
|
|
const icon = FOCUS_ICONS[focus] || '📅'
|
|
const label = FOCUS_LABELS[focus] || focus
|
|
const color = FOCUS_COLORS[focus] || '#888'
|
|
|
|
return (
|
|
<div
|
|
key={day.id}
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 10,
|
|
padding: '8px 10px',
|
|
borderRadius: 8,
|
|
background: `${color}14`,
|
|
border: `1px solid ${color}`,
|
|
}}
|
|
>
|
|
<div style={{ fontSize: 20 }}>{icon}</div>
|
|
<div style={{ flex: 1 }}>
|
|
<div style={{ fontSize: 13, fontWeight: 600, color }}>
|
|
{label}
|
|
</div>
|
|
{day.note && (
|
|
<div style={{ fontSize: 11, color: 'var(--text3)', marginTop: 2 }}>
|
|
{day.note}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
)}
|
|
|
|
<button
|
|
className="btn btn-secondary btn-full"
|
|
style={{ marginTop: 12, fontSize: 13 }}
|
|
onClick={() => nav('/rest-days')}
|
|
>
|
|
Ruhetage verwalten
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|