fix: focus areas slider NaN values and validation
Fixed multiple issues with relative weight sliders: 1. Sanitize focusData on load (ensure all 6 fields are numeric) 2. Sync focusTemp when clicking "Anpassen" button 3. Robust sum calculation filtering only *_pct fields 4. Convert NaN/undefined to 0 in all calculations 5. Safe Number() coercion before normalization Fixes errors: - "Gewichtung gesamt: NaN" - "Input should be a valid integer, input: null" - Prozent always showing 0% Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
92cc309489
commit
2f51b26418
|
|
@ -92,8 +92,21 @@ export default function GoalsPage() {
|
|||
])
|
||||
setGoalMode(modeData.goal_mode)
|
||||
setGoals(goalsData)
|
||||
setFocusAreas(focusData)
|
||||
setFocusTemp(focusData) // Initialize temp state
|
||||
|
||||
// Ensure all focus fields are present and numeric
|
||||
const sanitizedFocus = {
|
||||
weight_loss_pct: focusData?.weight_loss_pct ?? 0,
|
||||
muscle_gain_pct: focusData?.muscle_gain_pct ?? 0,
|
||||
strength_pct: focusData?.strength_pct ?? 0,
|
||||
endurance_pct: focusData?.endurance_pct ?? 0,
|
||||
flexibility_pct: focusData?.flexibility_pct ?? 0,
|
||||
health_pct: focusData?.health_pct ?? 0,
|
||||
custom: focusData?.custom,
|
||||
updated_at: focusData?.updated_at
|
||||
}
|
||||
|
||||
setFocusAreas(sanitizedFocus)
|
||||
setFocusTemp(sanitizedFocus)
|
||||
|
||||
// Convert types array to map for quick lookup
|
||||
const typesMap = {}
|
||||
|
|
@ -278,7 +291,10 @@ export default function GoalsPage() {
|
|||
{!focusEditing && focusAreas && (
|
||||
<button
|
||||
className="btn-secondary"
|
||||
onClick={() => setFocusEditing(true)}
|
||||
onClick={() => {
|
||||
setFocusTemp(focusAreas) // Sync temp state before editing
|
||||
setFocusEditing(true)
|
||||
}}
|
||||
style={{ padding: '6px 12px' }}
|
||||
>
|
||||
<Pencil size={14} /> Anpassen
|
||||
|
|
@ -306,9 +322,12 @@ export default function GoalsPage() {
|
|||
{ key: 'flexibility_pct', label: 'Beweglichkeit', icon: '🤸', color: '#E67E22' },
|
||||
{ key: 'health_pct', label: 'Gesundheit', icon: '❤️', color: '#F59E0B' }
|
||||
].map(area => {
|
||||
const weight = Math.round(focusTemp[area.key] / 10)
|
||||
const sum = Object.values(focusTemp).reduce((a, b) => a + b, 0)
|
||||
const actualPercent = sum > 0 ? Math.round(focusTemp[area.key] / sum * 100) : 0
|
||||
const rawValue = Number(focusTemp[area.key]) || 0
|
||||
const weight = Math.round(rawValue / 10)
|
||||
const sum = Object.entries(focusTemp)
|
||||
.filter(([k]) => k.endsWith('_pct'))
|
||||
.reduce((acc, [k, v]) => acc + (Number(v) || 0), 0)
|
||||
const actualPercent = sum > 0 ? Math.round(rawValue / sum * 100) : 0
|
||||
|
||||
return (
|
||||
<div key={area.key}>
|
||||
|
|
@ -361,7 +380,12 @@ export default function GoalsPage() {
|
|||
Gewichtung gesamt:
|
||||
</span>
|
||||
<span style={{ fontSize: 18, fontWeight: 600, color: 'var(--text1)' }}>
|
||||
{Object.values(focusTemp).reduce((a, b) => a + b, 0) / 10}
|
||||
{(() => {
|
||||
const total = Object.entries(focusTemp)
|
||||
.filter(([k]) => k.endsWith('_pct'))
|
||||
.reduce((acc, [k, v]) => acc + (Number(v) || 0), 0)
|
||||
return (total / 10).toFixed(1)
|
||||
})()}
|
||||
</span>
|
||||
</div>
|
||||
<div style={{ fontSize: 12, marginTop: 4, color: 'var(--text3)' }}>
|
||||
|
|
@ -374,18 +398,25 @@ export default function GoalsPage() {
|
|||
<button
|
||||
className="btn-primary"
|
||||
onClick={async () => {
|
||||
const sum = Object.values(focusTemp).reduce((a, b) => a + b, 0)
|
||||
// Calculate sum (filter out NaN/undefined)
|
||||
const sum = Object.entries(focusTemp)
|
||||
.filter(([k]) => k.endsWith('_pct'))
|
||||
.reduce((acc, [k, v]) => acc + (Number(v) || 0), 0)
|
||||
|
||||
if (sum === 0) {
|
||||
if (sum === 0 || isNaN(sum)) {
|
||||
setError('Mindestens ein Bereich muss gewichtet sein')
|
||||
return
|
||||
}
|
||||
|
||||
// Normalize to percentages
|
||||
const normalized = {}
|
||||
Object.keys(focusTemp).forEach(key => {
|
||||
normalized[key] = Math.round(focusTemp[key] / sum * 100)
|
||||
})
|
||||
// Normalize to percentages (ensure no NaN values)
|
||||
const normalized = {
|
||||
weight_loss_pct: Math.round((Number(focusTemp.weight_loss_pct) || 0) / sum * 100),
|
||||
muscle_gain_pct: Math.round((Number(focusTemp.muscle_gain_pct) || 0) / sum * 100),
|
||||
strength_pct: Math.round((Number(focusTemp.strength_pct) || 0) / sum * 100),
|
||||
endurance_pct: Math.round((Number(focusTemp.endurance_pct) || 0) / sum * 100),
|
||||
flexibility_pct: Math.round((Number(focusTemp.flexibility_pct) || 0) / sum * 100),
|
||||
health_pct: Math.round((Number(focusTemp.health_pct) || 0) / sum * 100)
|
||||
}
|
||||
|
||||
// Ensure sum is exactly 100 (adjust largest value if needed due to rounding)
|
||||
const normalizedSum = Object.values(normalized).reduce((a, b) => a + b, 0)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user