Compare commits

..

No commits in common. "888b5c3e408d586cf8e1dde7bbb73431958a33bf" and "770a49b5f378e85e3b3624d7185d40ab3f5c20ee" have entirely different histories.

View File

@ -598,62 +598,26 @@ function OverviewCards({ data }) {
// Chart: Kalorien vs Gewicht // Chart: Kalorien vs Gewicht
function CaloriesVsWeight({ data }) { function CaloriesVsWeight({ data }) {
// BUG-003 fix: Show all weight data, extrapolate kcal if missing const filtered = data.filter(d => d.kcal && d.weight)
const filtered = data.filter(d => d.kcal || d.weight) const withAvg = rollingAvg(filtered.map(d=>({...d,date:dayjs(d.date).format('DD.MM')})), 'kcal')
if (filtered.length < 3) return ( if (filtered.length < 3) return (
<div style={{padding:20,textAlign:'center',color:'var(--text3)',fontSize:13}}> <div style={{padding:20,textAlign:'center',color:'var(--text3)',fontSize:13}}>
Zu wenig Daten für diese Auswertung Zu wenig gemeinsame Daten (Gewicht + Kalorien am selben Tag nötig)
</div> </div>
) )
// Find last real kcal value
const lastKcalIndex = filtered.findLastIndex(d => d.kcal)
const lastKcal = lastKcalIndex >= 0 ? filtered[lastKcalIndex].kcal : null
// Extrapolate missing kcal values at the end
const withExtrapolated = filtered.map((d, i) => ({
...d,
kcal: d.kcal || (i > lastKcalIndex && lastKcal ? lastKcal : null),
isKcalExtrapolated: !d.kcal && i > lastKcalIndex && lastKcal
}))
// Format dates and calculate rolling average
const formatted = withExtrapolated.map(d => ({
...d,
date: dayjs(d.date).format('DD.MM')
}))
const withAvg = rollingAvg(formatted, 'kcal')
// Split into real and extrapolated segments for dashed lines
const realData = withAvg.map(d => ({
...d,
kcal_extrap: d.isKcalExtrapolated ? d.kcal : null,
kcal_avg_extrap: d.isKcalExtrapolated ? d.kcal_avg : null,
kcal: d.isKcalExtrapolated ? null : d.kcal,
kcal_avg: d.isKcalExtrapolated ? null : d.kcal_avg
}))
return ( return (
<ResponsiveContainer width="100%" height={220}> <ResponsiveContainer width="100%" height={220}>
<LineChart data={realData} margin={{top:4,right:8,bottom:0,left:-16}}> <LineChart data={withAvg} margin={{top:4,right:8,bottom:0,left:-16}}>
<CartesianGrid stroke="var(--border)" strokeDasharray="3 3"/> <CartesianGrid stroke="var(--border)" strokeDasharray="3 3"/>
<XAxis dataKey="date" tick={{fontSize:9,fill:'var(--text3)'}} tickLine={false} <XAxis dataKey="date" tick={{fontSize:9,fill:'var(--text3)'}} tickLine={false}
interval={Math.max(0,Math.floor(realData.length/6)-1)}/> interval={Math.max(0,Math.floor(withAvg.length/6)-1)}/>
<YAxis yAxisId="kcal" tick={{fontSize:9,fill:'var(--text3)'}} tickLine={false} domain={['auto','auto']}/> <YAxis yAxisId="kcal" tick={{fontSize:9,fill:'var(--text3)'}} tickLine={false} domain={['auto','auto']}/>
<YAxis yAxisId="weight" orientation="right" tick={{fontSize:9,fill:'var(--text3)'}} tickLine={false} domain={['auto','auto']}/> <YAxis yAxisId="weight" orientation="right" tick={{fontSize:9,fill:'var(--text3)'}} tickLine={false} domain={['auto','auto']}/>
<Tooltip contentStyle={{background:'var(--surface)',border:'1px solid var(--border)',borderRadius:8,fontSize:11}} <Tooltip contentStyle={{background:'var(--surface)',border:'1px solid var(--border)',borderRadius:8,fontSize:11}}
formatter={(v,n)=>[`${Math.round(v)} ${n==='weight'?'kg':'kcal'}`, n.includes('avg')?'Ø 7T Kalorien':n==='weight'?'Gewicht':'Kalorien']}/> formatter={(v,n)=>[`${Math.round(v)} ${n==='weight'?'kg':'kcal'}`, n==='kcal_avg'?'Ø 7T Kalorien':n==='weight'?'Gewicht':'Kalorien']}/>
<Line yAxisId="kcal" type="monotone" dataKey="kcal" stroke="#EF9F2744" strokeWidth={1} dot={false}/>
{/* Real kcal values - solid lines */} <Line yAxisId="kcal" type="monotone" dataKey="kcal_avg" stroke="#EF9F27" strokeWidth={2} dot={false} name="kcal_avg"/>
<Line yAxisId="kcal" type="monotone" dataKey="kcal" stroke="#EF9F2744" strokeWidth={1} dot={false} connectNulls={false}/> <Line yAxisId="weight" type="monotone" dataKey="weight" stroke="#378ADD" strokeWidth={2} dot={{r:3,fill:'#378ADD'}} name="weight"/>
<Line yAxisId="kcal" type="monotone" dataKey="kcal_avg" stroke="#EF9F27" strokeWidth={2} dot={false} name="kcal_avg" connectNulls={false}/>
{/* Extrapolated kcal values - dashed lines */}
<Line yAxisId="kcal" type="monotone" dataKey="kcal_extrap" stroke="#EF9F2744" strokeWidth={1} strokeDasharray="3 3" dot={false} connectNulls={false}/>
<Line yAxisId="kcal" type="monotone" dataKey="kcal_avg_extrap" stroke="#EF9F27" strokeWidth={2} strokeDasharray="3 3" dot={false} connectNulls={false}/>
{/* Weight - always solid */}
<Line yAxisId="weight" type="monotone" dataKey="weight" stroke="#378ADD" strokeWidth={2} dot={{r:3,fill:'#378ADD'}} name="weight" connectNulls={true}/>
</LineChart> </LineChart>
</ResponsiveContainer> </ResponsiveContainer>
) )
@ -779,7 +743,6 @@ export default function NutritionPage() {
const [profile, setProf] = useState(null) const [profile, setProf] = useState(null)
const [loading, setLoad] = useState(true) const [loading, setLoad] = useState(true)
const [hasData, setHasData]= useState(false) const [hasData, setHasData]= useState(false)
const [importHistoryKey, setImportHistoryKey] = useState(Date.now()) // BUG-004 fix
const load = async () => { const load = async () => {
setLoad(true) setLoad(true)
@ -821,8 +784,8 @@ export default function NutritionPage() {
{/* Import Panel + History */} {/* Import Panel + History */}
{inputTab==='import' && ( {inputTab==='import' && (
<> <>
<ImportPanel onImported={() => { load(); setImportHistoryKey(Date.now()) }}/> <ImportPanel onImported={load}/>
<ImportHistory key={importHistoryKey}/> <ImportHistory/>
</> </>
)} )}