import { useState, useEffect, useRef } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { Camera, CheckCircle, ChevronDown, ChevronUp, BookOpen } from 'lucide-react'
import { api } from '../utils/api'
import { calcBodyFat, METHOD_POINTS } from '../utils/calc'
import { CIRCUMFERENCE_POINTS, CALIPER_POINTS, CALIPER_METHODS } from '../utils/guideData'
import dayjs from 'dayjs'
function Section({ title, open, onToggle, children, hint }) {
return (
{title}
{hint && !open &&
{hint}
}
{open ?
:
}
{open &&
{children}
}
)
}
function NumInput({ label, sub, value, onChange, unit, min, max, step=0.1, guideText }) {
return (
onChange(e.target.value==='' ? null : parseFloat(e.target.value))}/>
{unit}
)
}
export default function NewMeasurement() {
const { id } = useParams()
const nav = useNavigate()
const fileRef = useRef()
const [profile, setProfile] = useState(null)
const [saving, setSaving] = useState(false)
const [saved, setSaved] = useState(false)
const [photoPreview, setPhotoPreview] = useState(null)
const [photoFile, setPhotoFile] = useState(null)
const [openSections, setOpenSections] = useState({ basic:true, circum:true, caliper:false, notes:false })
const isEdit = !!id
const [form, setForm] = useState({
date: dayjs().format('YYYY-MM-DD'),
weight: null,
c_neck:null, c_chest:null, c_waist:null, c_belly:null,
c_hip:null, c_thigh:null, c_calf:null, c_arm:null,
sf_method:'jackson3',
sf_chest:null, sf_axilla:null, sf_triceps:null, sf_subscap:null,
sf_suprailiac:null, sf_abdomen:null, sf_thigh:null,
sf_calf_med:null, sf_lowerback:null, sf_biceps:null,
notes:''
})
useEffect(() => {
api.getProfile().then(setProfile)
if (id) {
api.getMeasurement(id).then(m => {
setForm(f => ({...f, ...m}))
})
}
}, [id])
const toggle = s => setOpenSections(o => ({...o,[s]:!o[s]}))
const set = (k,v) => setForm(f => ({...f,[k]:v}))
const sex = profile?.sex || 'm'
const age = profile?.dob ? Math.floor((Date.now()-new Date(profile.dob))/(365.25*24*3600*1000)) : 30
const height = profile?.height || 178
const weight = form.weight || 80
const sfPoints = METHOD_POINTS[form.sf_method]?.[sex] || []
const sfVals = {}
sfPoints.forEach(k => { if (form[`sf_${k}`]) sfVals[k] = form[`sf_${k}`] })
const bfPct = Object.keys(sfVals).length===sfPoints.length
? Math.round(calcBodyFat(form.sf_method, sfVals, sex, age)*10)/10 : null
const handlePhoto = e => {
const file = e.target.files[0]; if(!file) return
setPhotoFile(file); setPhotoPreview(URL.createObjectURL(file))
}
const handleSave = async () => {
setSaving(true)
try {
const payload = {...form}
if (bfPct) {
payload.body_fat_pct = bfPct
payload.lean_mass = Math.round(weight*(1-bfPct/100)*10)/10
payload.fat_mass = Math.round(weight*(bfPct/100)*10)/10
}
let mid = id
if (id) { await api.updateMeasurement(id, payload) }
else { const r = await api.createMeasurement(payload); mid = r.id }
if (photoFile && mid) {
const pr = await api.uploadPhoto(photoFile, mid)
await api.updateMeasurement(mid, {photo_id: pr.id})
}
setSaved(true); setTimeout(()=>nav('/'), 1200)
} catch(e) { alert('Fehler beim Speichern: '+e.message) }
finally { setSaving(false) }
}
return (
{isEdit ? 'Messung bearbeiten' : 'Neue Messung'}
{/* Grunddaten */}
{/* Umfänge */}
toggle('circum')}
hint="Hals, Brust, Taille, Bauch, HĂĽfte, Oberschenkel, Wade, Oberarm">
{CIRCUMFERENCE_POINTS.map(p => (
50 ? p.where.substring(0,48)+'…' : p.where}
value={form[p.id]} onChange={v=>set(p.id,v)} unit="cm" min={10} max={200}/>
))}
{/* Caliper */}
toggle('caliper')}
hint="Optional – für präzise Körperfett-Messung">
Immer rechte Körperseite · Falte 1 cm abheben · 3× messen, Mittelwert nehmen
nav('/guide')}>→ Anleitung
{sfPoints.map(k => {
const p = CALIPER_POINTS[k]
return p ? (
50 ? p.where.substring(0,48)+'…' : p.where}
value={form[`sf_${k}`]} onChange={v=>set(`sf_${k}`,v)} unit="mm" min={2} max={80}/>
) : null
})}
{bfPct !== null && (
{bfPct} %
Körperfett ({CALIPER_METHODS[form.sf_method]?.label})
{form.weight &&
Magermasse: {Math.round(form.weight*(1-bfPct/100)*10)/10} kg ·{' '}
Fettmasse: {Math.round(form.weight*(bfPct/100)*10)/10} kg
}
)}
{/* Foto */}
Fortschrittsfoto
{photoPreview &&

}
{/* Notizen */}