mitai-jinkendo/frontend/src/pages/CaptureHub.jsx
Lars 4191c52298
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
feat: implement Vitals module (Ruhepuls + HRV)
Backend:
- New router: vitals.py with CRUD endpoints
- GET /api/vitals (list)
- GET /api/vitals/by-date/{date}
- POST /api/vitals (upsert)
- PUT /api/vitals/{id}
- DELETE /api/vitals/{id}
- GET /api/vitals/stats (7d/30d averages, trends)
- Registered in main.py

Frontend:
- VitalsPage.jsx with manual entry form
- List with inline editing
- Stats overview (averages, trend indicators)
- Added to CaptureHub (❤️ icon)
- Route /vitals in App.jsx

API:
- Added vitals methods to api.js

v9d Phase 2d - Vitals tracking complete

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 14:52:09 +01:00

120 lines
3.0 KiB
JavaScript

import { useNavigate } from 'react-router-dom'
import { ChevronRight } from 'lucide-react'
const ENTRIES = [
{
icon: '⚖️',
label: 'Gewicht',
sub: 'Tägliche Gewichtseingabe',
to: '/weight',
color: '#378ADD',
},
{
icon: '🪄',
label: 'Assistent',
sub: 'Schritt-für-Schritt Messung (Umfänge & Caliper)',
to: '/wizard',
color: '#7F77DD',
highlight: true,
},
{
icon: '📏',
label: 'Umfänge',
sub: 'Hals, Brust, Taille, Bauch, Hüfte, Oberschenkel, Wade, Arm',
to: '/circum',
color: '#1D9E75',
},
{
icon: '📐',
label: 'Caliper',
sub: 'Körperfett per Hautfaltenmessung',
to: '/caliper',
color: '#D85A30',
},
{
icon: '🍽️',
label: 'Ernährung',
sub: 'FDDB CSV importieren',
to: '/nutrition',
color: '#EF9F27',
},
{
icon: '🏋️',
label: 'Aktivität',
sub: 'Training manuell oder Apple Health importieren',
to: '/activity',
color: '#D4537E',
},
{
icon: '🌙',
label: 'Schlaf',
sub: 'Schlafdaten erfassen oder Apple Health importieren',
to: '/sleep',
color: '#7B68EE',
},
{
icon: '🛌',
label: 'Ruhetage',
sub: 'Kraft-, Cardio-, oder Entspannungs-Ruhetag erfassen',
to: '/rest-days',
color: '#9B59B6',
},
{
icon: '❤️',
label: 'Vitalwerte',
sub: 'Ruhepuls und HRV morgens erfassen',
to: '/vitals',
color: '#E74C3C',
},
{
icon: '📖',
label: 'Messanleitung',
sub: 'Wie und wo genau messen?',
to: '/guide',
color: '#888780',
},
]
export default function CaptureHub() {
const nav = useNavigate()
return (
<div>
<h1 className="page-title">Erfassen</h1>
<div style={{display:'flex',flexDirection:'column',gap:10}}>
{ENTRIES.map(e => (
<button key={e.to} onClick={()=>nav(e.to)}
style={{
display:'flex', alignItems:'center', gap:14,
padding:'14px 16px', borderRadius:14,
border: e.highlight ? `2px solid ${e.color}` : '1.5px solid var(--border)',
background: e.highlight ? e.color+'14' : 'var(--surface)',
cursor:'pointer', fontFamily:'var(--font)', textAlign:'left',
transition:'all 0.15s',
}}>
<div style={{
width:44, height:44, borderRadius:12,
background: e.color+'22',
display:'flex', alignItems:'center', justifyContent:'center',
fontSize:22, flexShrink:0,
}}>
{e.icon}
</div>
<div style={{flex:1}}>
<div style={{
fontSize:15, fontWeight:600,
color: e.highlight ? e.color : 'var(--text1)',
}}>
{e.label}
</div>
<div style={{fontSize:12, color:'var(--text3)', marginTop:2}}>
{e.sub}
</div>
</div>
<ChevronRight size={18} style={{color:'var(--text3)',flexShrink:0}}/>
</button>
))}
</div>
</div>
)
}