import React, { useState, useMemo } from 'react' import { View, Text, TextInput, TouchableOpacity, StyleSheet, KeyboardAvoidingView, ScrollView } from 'react-native' import { useSafeAreaInsets } from 'react-native-safe-area-context' import DateTimePicker, { DateTimePickerEvent } from '@react-native-community/datetimepicker' import { Measurement } from '../types' import { generateId } from '../utils/uuid' type Props = { onSubmit: (m: Measurement) => void initialValues?: Partial isEdit?: boolean } type FieldDef = { key: keyof Measurement label: string placeholder: string keyboardType: 'decimal-pad' | 'number-pad' computed?: boolean } const fields: FieldDef[] = [ { key: 'weight', label: 'Gewicht (kg)', placeholder: '75.5', keyboardType: 'decimal-pad' }, { key: 'bmi', label: 'BMI', placeholder: '22.3', keyboardType: 'decimal-pad' }, { key: 'bodyFatPercentage', label: 'Vetpercentage (%)', placeholder: '15.2', keyboardType: 'decimal-pad' }, { key: 'fatMass', label: 'Vetmassa (kg)', placeholder: '11.5', keyboardType: 'decimal-pad', computed: true }, { key: 'musclePercentage', label: 'Spierpercentage (%)', placeholder: '40.1', keyboardType: 'decimal-pad' }, { key: 'muscleMass', label: 'Spiermassa (kg)', placeholder: '30.3', keyboardType: 'decimal-pad', computed: true }, { key: 'visceralFat', label: 'Buikvet (index)', placeholder: '8', keyboardType: 'number-pad' }, { key: 'bmr', label: 'Stofwisseling (kcal)', placeholder: '1650', keyboardType: 'number-pad' }, ] export default function MeasurementForm({ onSubmit, initialValues, isEdit }: Props) { const insets = useSafeAreaInsets() const [pickerOpen, setPickerOpen] = useState(false) const [measurementDate, setMeasurementDate] = useState(new Date()) const [values, setValues] = useState>(() => { const init: Record = {} for (const f of fields) { if (f.computed) continue init[f.key] = initialValues?.[f.key]?.toString() ?? '' } return init }) function toFloat(s: string): number { return parseFloat(s.replace(',', '.')) || 0 } function toInt(s: string): number { return parseInt(s.replace(',', '.'), 10) || 0 } const weight = toFloat(values.weight) const bodyFatPct = toFloat(values.bodyFatPercentage) const musclePct = toFloat(values.musclePercentage) const computed = useMemo(() => ({ fatMass: weight > 0 && bodyFatPct > 0 ? ((weight * bodyFatPct) / 100).toFixed(1) : '', muscleMass: weight > 0 && musclePct > 0 ? ((weight * musclePct) / 100).toFixed(1) : '', }), [weight, bodyFatPct, musclePct]) const handleSubmit = () => { const now = new Date().toISOString() const m: Measurement = { id: isEdit && initialValues?.id ? initialValues.id : generateId(), weight, bmi: toFloat(values.bmi), bodyFatPercentage: bodyFatPct, fatMass: toFloat(computed.fatMass), musclePercentage: musclePct, muscleMass: toFloat(computed.muscleMass), visceralFat: toInt(values.visceralFat), bmr: toFloat(values.bmr), measuredAt: measurementDate.toISOString(), createdAt: isEdit && initialValues?.createdAt ? initialValues.createdAt : now, updatedAt: now, } onSubmit(m) } const setField = (key: string, value: string) => { setValues(prev => ({ ...prev, [key]: value })) } const onDateChange = (_event: DateTimePickerEvent, selectedDate?: Date) => { setPickerOpen(false) if (selectedDate) { setMeasurementDate(selectedDate) } } return ( Datum setPickerOpen(true)}> {measurementDate.toLocaleDateString('nl-NL', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric', })} {pickerOpen && ( )} {fields.map(f => { if (f.computed) { const calcValue = f.key === 'fatMass' ? computed.fatMass : computed.muscleMass return ( {f.label} {calcValue || '—'} ) } return ( {f.label} setField(f.key, v)} placeholderTextColor="#999" /> ) })} Opslaan ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f5f5f5' }, scroll: { padding: 16 }, field: { marginBottom: 12 }, label: { fontSize: 14, fontWeight: '600', color: '#333', marginBottom: 4 }, input: { backgroundColor: '#fff', borderRadius: 8, padding: 12, fontSize: 16, borderWidth: 1, borderColor: '#ddd' }, computedInput: { backgroundColor: '#f0f0f0' }, computedText: { fontSize: 16, color: '#666' }, dateButton: { backgroundColor: '#fff', borderRadius: 8, padding: 12, borderWidth: 1, borderColor: '#ddd' }, dateButtonText: { fontSize: 16, color: '#333' }, button: { backgroundColor: '#4CAF50', padding: 16, borderRadius: 8, alignItems: 'center', margin: 16 }, buttonText: { color: '#fff', fontSize: 16, fontWeight: '700' }, })