Compare commits
No commits in common. "888b5c3e408d586cf8e1dde7bbb73431958a33bf" and "770a49b5f378e85e3b3624d7185d40ab3f5c20ee" have entirely different histories.
888b5c3e40
...
770a49b5f3
|
|
@ -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/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user