feat: add date picker as first field in measurement form
This commit is contained in:
parent
d2e8f4444f
commit
ad108b3b16
4 changed files with 66 additions and 2 deletions
3
app.json
3
app.json
|
|
@ -23,7 +23,8 @@
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"expo-sqlite",
|
"expo-sqlite",
|
||||||
"expo-secure-store"
|
"expo-secure-store",
|
||||||
|
"@react-native-community/datetimepicker"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
package-lock.json
generated
24
package-lock.json
generated
|
|
@ -8,6 +8,7 @@
|
||||||
"name": "weegschaal-app",
|
"name": "weegschaal-app",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@react-native-community/datetimepicker": "8.4.4",
|
||||||
"@react-navigation/native": "^7.3.4",
|
"@react-navigation/native": "^7.3.4",
|
||||||
"@react-navigation/native-stack": "^7.17.6",
|
"@react-navigation/native-stack": "^7.17.6",
|
||||||
"expo": "~54.0.0",
|
"expo": "~54.0.0",
|
||||||
|
|
@ -2780,6 +2781,29 @@
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@react-native-community/datetimepicker": {
|
||||||
|
"version": "8.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-native-community/datetimepicker/-/datetimepicker-8.4.4.tgz",
|
||||||
|
"integrity": "sha512-bc4ZixEHxZC9/qf5gbdYvIJiLZ5CLmEsC3j+Yhe1D1KC/3QhaIfGDVdUcid0PdlSoGOSEq4VlB93AWyetEyBSQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"invariant": "^2.2.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": ">=52.0.0",
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*",
|
||||||
|
"react-native-windows": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"expo": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-native-windows": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@react-native/assets-registry": {
|
"node_modules/@react-native/assets-registry": {
|
||||||
"version": "0.81.5",
|
"version": "0.81.5",
|
||||||
"resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.5.tgz",
|
"resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.5.tgz",
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"main": "index.ts",
|
"main": "index.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@react-native-community/datetimepicker": "8.4.4",
|
||||||
"@react-navigation/native": "^7.3.4",
|
"@react-navigation/native": "^7.3.4",
|
||||||
"@react-navigation/native-stack": "^7.17.6",
|
"@react-navigation/native-stack": "^7.17.6",
|
||||||
"expo": "~54.0.0",
|
"expo": "~54.0.0",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { View, Text, TextInput, TouchableOpacity, StyleSheet, KeyboardAvoidingView, Platform, ScrollView } from 'react-native'
|
import { View, Text, TextInput, TouchableOpacity, StyleSheet, KeyboardAvoidingView, Platform, ScrollView } from 'react-native'
|
||||||
|
import DateTimePicker, { DateTimePickerEvent } from '@react-native-community/datetimepicker'
|
||||||
import { Measurement } from '../types'
|
import { Measurement } from '../types'
|
||||||
import { generateId } from '../utils/uuid'
|
import { generateId } from '../utils/uuid'
|
||||||
|
|
||||||
|
|
@ -20,6 +21,11 @@ const fields: { key: keyof Measurement; label: string; placeholder: string; keyb
|
||||||
]
|
]
|
||||||
|
|
||||||
export default function MeasurementForm({ onSubmit, initialValues }: Props) {
|
export default function MeasurementForm({ onSubmit, initialValues }: Props) {
|
||||||
|
const [pickerOpen, setPickerOpen] = useState(false)
|
||||||
|
const [measurementDate, setMeasurementDate] = useState<Date>(() => {
|
||||||
|
if (initialValues?.measuredAt) return new Date(initialValues.measuredAt)
|
||||||
|
return new Date()
|
||||||
|
})
|
||||||
const [values, setValues] = useState<Record<string, string>>(() => {
|
const [values, setValues] = useState<Record<string, string>>(() => {
|
||||||
const init: Record<string, string> = {}
|
const init: Record<string, string> = {}
|
||||||
for (const f of fields) {
|
for (const f of fields) {
|
||||||
|
|
@ -40,7 +46,7 @@ export default function MeasurementForm({ onSubmit, initialValues }: Props) {
|
||||||
muscleMass: parseFloat(values.muscleMass) || 0,
|
muscleMass: parseFloat(values.muscleMass) || 0,
|
||||||
visceralFat: parseInt(values.visceralFat, 10) || 0,
|
visceralFat: parseInt(values.visceralFat, 10) || 0,
|
||||||
bmr: parseFloat(values.bmr) || 0,
|
bmr: parseFloat(values.bmr) || 0,
|
||||||
measuredAt: now,
|
measuredAt: measurementDate.toISOString(),
|
||||||
createdAt: now,
|
createdAt: now,
|
||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
syncStatus: 'local',
|
syncStatus: 'local',
|
||||||
|
|
@ -52,9 +58,39 @@ export default function MeasurementForm({ onSubmit, initialValues }: Props) {
|
||||||
setValues(prev => ({ ...prev, [key]: value }))
|
setValues(prev => ({ ...prev, [key]: value }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onDateChange = (_event: DateTimePickerEvent, selectedDate?: Date) => {
|
||||||
|
setPickerOpen(false)
|
||||||
|
if (selectedDate) {
|
||||||
|
setMeasurementDate(selectedDate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : undefined} style={styles.container}>
|
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : undefined} style={styles.container}>
|
||||||
<ScrollView contentContainerStyle={styles.scroll}>
|
<ScrollView contentContainerStyle={styles.scroll}>
|
||||||
|
<View style={styles.field}>
|
||||||
|
<Text style={styles.label}>Datum</Text>
|
||||||
|
<TouchableOpacity style={styles.dateButton} onPress={() => setPickerOpen(true)}>
|
||||||
|
<Text style={styles.dateButtonText}>
|
||||||
|
{measurementDate.toLocaleDateString('nl-NL', {
|
||||||
|
weekday: 'long',
|
||||||
|
day: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{pickerOpen && (
|
||||||
|
<DateTimePicker
|
||||||
|
value={measurementDate}
|
||||||
|
mode="date"
|
||||||
|
display="default"
|
||||||
|
onChange={onDateChange}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{fields.map(f => (
|
{fields.map(f => (
|
||||||
<View key={f.key} style={styles.field}>
|
<View key={f.key} style={styles.field}>
|
||||||
<Text style={styles.label}>{f.label}</Text>
|
<Text style={styles.label}>{f.label}</Text>
|
||||||
|
|
@ -82,6 +118,8 @@ const styles = StyleSheet.create({
|
||||||
field: { marginBottom: 12 },
|
field: { marginBottom: 12 },
|
||||||
label: { fontSize: 14, fontWeight: '600', color: '#333', marginBottom: 4 },
|
label: { fontSize: 14, fontWeight: '600', color: '#333', marginBottom: 4 },
|
||||||
input: { backgroundColor: '#fff', borderRadius: 8, padding: 12, fontSize: 16, borderWidth: 1, borderColor: '#ddd' },
|
input: { backgroundColor: '#fff', borderRadius: 8, padding: 12, fontSize: 16, borderWidth: 1, borderColor: '#ddd' },
|
||||||
|
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', marginTop: 8 },
|
button: { backgroundColor: '#4CAF50', padding: 16, borderRadius: 8, alignItems: 'center', marginTop: 8 },
|
||||||
buttonText: { color: '#fff', fontSize: 16, fontWeight: '700' },
|
buttonText: { color: '#fff', fontSize: 16, fontWeight: '700' },
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue