mitai-jinkendo/frontend/src/pages/GuidePage.jsx

115 lines
6.7 KiB
React
Raw Normal View History

import { useState } from 'react'
import { ChevronDown, ChevronUp } from 'lucide-react'
import { CIRCUMFERENCE_POINTS, CALIPER_POINTS, CALIPER_METHODS } from '../utils/guideData'
function PointCard({ point, index }) {
const [open, setOpen] = useState(false)
return (
<div style={{border:`1px solid ${open ? point.color : 'var(--border)'}`,borderRadius:10,marginBottom:8,overflow:'hidden',transition:'border-color 0.15s'}}>
<div style={{display:'flex',alignItems:'center',gap:10,padding:'11px 14px',cursor:'pointer',background: open ? 'var(--surface2)' : 'var(--surface)'}}
onClick={() => setOpen(o => !o)}>
<div style={{width:28,height:28,borderRadius:'50%',background:point.color,display:'flex',alignItems:'center',justifyContent:'center',flexShrink:0}}>
<span style={{fontSize:12,fontWeight:700,color:'white'}}>{index+1}</span>
</div>
<span style={{flex:1,fontSize:14,fontWeight:500}}>{point.label}</span>
{open ? <ChevronUp size={16} color="var(--text3)"/> : <ChevronDown size={16} color="var(--text3)"/>}
</div>
{open && (
<div style={{padding:'12px 14px',borderTop:'1px solid var(--border)',background:'var(--surface)'}}>
{[['📍 Wo', point.where], ['🧍 Haltung', point.posture], ['📏 Band', point.how], ['💡 Tipp', point.tip]].map(([label, val]) => (
<div key={label} style={{display:'grid',gridTemplateColumns:'90px 1fr',gap:'4px 8px',marginBottom:8}}>
<span style={{fontSize:11,fontWeight:600,color:'var(--text3)',textTransform:'uppercase',letterSpacing:'0.04em',paddingTop:2}}>{label}</span>
<span style={{fontSize:13,color:'var(--text2)',lineHeight:1.55}}>{val}</span>
</div>
))}
</div>
)}
</div>
)
}
export default function GuidePage() {
const [tab, setTab] = useState('circum')
const [caliperMethod, setCaliperMethod] = useState('jackson3')
const sex = 'm' // could read from profile
const methodPoints = CALIPER_METHODS[caliperMethod]?.points_m || []
return (
<div className="capture-page">
<h1 className="page-title">Messanleitung</h1>
<div className="tabs">
<button className={'tab' + (tab === 'circum' ? ' active' : '')} onClick={() => setTab('circum')}>Umfänge</button>
<button className={'tab' + (tab === 'caliper' ? ' active' : '')} onClick={() => setTab('caliper')}>Caliper</button>
<button className={'tab' + (tab === 'tips' ? ' active' : '')} onClick={() => setTab('tips')}>Allgemein</button>
</div>
{tab === 'circum' && (
<div>
<div style={{padding:'10px 14px',background:'var(--accent-light)',borderRadius:10,marginBottom:14,fontSize:13,color:'var(--accent-dark)',lineHeight:1.6}}>
Klicke auf einen Messpunkt für genaue Anleitung zu Körperhaltung und Messung.
</div>
{CIRCUMFERENCE_POINTS.map((p, i) => <PointCard key={p.id} point={p} index={i}/>)}
</div>
)}
{tab === 'caliper' && (
<div>
<div style={{marginBottom:14}}>
<div style={{fontSize:13,fontWeight:600,color:'var(--text3)',marginBottom:6}}>METHODE WÄHLEN</div>
<div style={{display:'flex',flexDirection:'column',gap:6}}>
{Object.entries(CALIPER_METHODS).map(([key, m]) => (
<button key={key} onClick={() => setCaliperMethod(key)}
style={{padding:'9px 14px',borderRadius:10,border:`1.5px solid ${caliperMethod===key?'var(--accent)':'var(--border2)'}`,
background: caliperMethod===key?'var(--accent-light)':'var(--surface)',
color: caliperMethod===key?'var(--accent-dark)':'var(--text2)',
fontFamily:'var(--font)',fontSize:13,fontWeight:500,textAlign:'left',cursor:'pointer',
display:'flex',justifyContent:'space-between',alignItems:'center'}}>
<span>{m.label}</span>
<span style={{fontSize:11,opacity:0.7}}>{m.points_m.length} Punkte</span>
</button>
))}
</div>
</div>
<div style={{padding:'10px 14px',background:'var(--warn-bg)',borderRadius:10,marginBottom:14,fontSize:13,color:'var(--warn-text)',lineHeight:1.6}}>
<strong>Caliper-Grundregel:</strong> Immer rechte Körperseite · Falte 1 cm neben dem Punkt abheben · Caliper 1 cm neben Fingern ansetzen · 2 Sek. warten · 3× messen, Mittelwert nehmen
</div>
{methodPoints.map((id, i) => {
const p = CALIPER_POINTS[id]
if (!p) return null
return <PointCard key={id} point={p} index={i}/>
})}
</div>
)}
{tab === 'tips' && (
<div>
{[
{ icon:'🌅', title:'Zeitpunkt', text:'Immer morgens nüchtern messen – vor dem Frühstück und vor dem Sport. Zu festen Zeiten messen für vergleichbare Werte.' },
{ icon:'👗', title:'Kleidung', text:'Immer in vergleichbarer Unterwäsche oder ohne Kleidung messen. Kleidung kann die Werte verfälschen.' },
{ icon:'📏', title:'Maßband', text:'Maßband flach und waagerecht anlegen – parallel zum Boden. Weder spannen noch locker lassen. 1 Finger Luft bei Hals-Messungen.' },
{ icon:'🔢', title:'Wiederholungen', text:'Jeden Wert 2× messen und den Durchschnitt notieren. Bei Abweichungen über 1 cm eine dritte Messung machen.' },
{ icon:'💧', title:'Wassereinlagerungen', text:'Nicht nach dem Sport, nach Alkohol, oder bei Krankheit messen. Beine schwellen gegen Abend an – Wade morgens messen.' },
{ icon:'📅', title:'Intervall', text:'Wöchentliche oder zweiwöchentliche Messungen reichen. Tägliche Schwankungen von 1–2 kg sind normal und nicht aussagekräftig.' },
{ icon:'📸', title:'Fortschrittsfotos', text:'Fotos bei gleicher Beleuchtung und gleichem Hintergrund machen. Morgendlich nüchtern, gleiche Pose, gleiche Kamera-Distanz.' },
{ icon:'🔬', title:'Caliper vs. Maßband', text:'Caliper misst Unterhautfett direkt – genauer als Umfänge allein. Umfänge erfassen die Gesamtgröße inklusive Muskeln. Beide Werte kombiniert geben das vollständigste Bild.' },
].map(item => (
<div key={item.title} className="card section-gap">
<div style={{display:'flex',gap:12,alignItems:'flex-start'}}>
<span style={{fontSize:22,flexShrink:0}}>{item.icon}</span>
<div>
<div style={{fontWeight:600,fontSize:14,marginBottom:4}}>{item.title}</div>
<div style={{fontSize:13,color:'var(--text2)',lineHeight:1.6}}>{item.text}</div>
</div>
</div>
</div>
))}
</div>
)}
</div>
)
}