diff --git a/src/components/MeasurementRow.tsx b/src/components/MeasurementRow.tsx index 0e4d4d8..4b2a92f 100644 --- a/src/components/MeasurementRow.tsx +++ b/src/components/MeasurementRow.tsx @@ -1,12 +1,12 @@ import React from 'react' -import { View, Text, StyleSheet } from 'react-native' +import { TouchableOpacity, View, Text, StyleSheet } from 'react-native' import { Measurement } from '../types' -type Props = { measurement: Measurement } +type Props = { measurement: Measurement; onPress: () => void } -export default function MeasurementRow({ measurement }: Props) { +export default function MeasurementRow({ measurement, onPress }: Props) { return ( - + {new Date(measurement.measuredAt).toLocaleDateString('nl-NL', { @@ -27,7 +27,7 @@ export default function MeasurementRow({ measurement }: Props) { {measurement.weight.toFixed(1)} kg BMI {measurement.bmi.toFixed(1)} - + ) } diff --git a/src/database/db.ts b/src/database/db.ts index f868e16..77b8fe9 100644 --- a/src/database/db.ts +++ b/src/database/db.ts @@ -77,3 +77,7 @@ export async function getUnsyncedMeasurements(): Promise { ) return rows as Measurement[] } + +export async function deleteMeasurement(id: string): Promise { + await db!.runAsync('DELETE FROM measurements WHERE id = ?', [id]) +} diff --git a/src/screens/HistoryScreen.tsx b/src/screens/HistoryScreen.tsx index c6ec287..e84f507 100644 --- a/src/screens/HistoryScreen.tsx +++ b/src/screens/HistoryScreen.tsx @@ -1,11 +1,13 @@ import React, { useCallback, useState } from 'react' -import { View, FlatList, StyleSheet, Text, RefreshControl } from 'react-native' +import { View, FlatList, StyleSheet, Text, RefreshControl, Alert } from 'react-native' import { useFocusEffect } from '@react-navigation/native' -import { initDatabase, getAllMeasurements } from '../database/db' +import { initDatabase, getAllMeasurements, deleteMeasurement } from '../database/db' import { Measurement } from '../types' import MeasurementRow from '../components/MeasurementRow' -export default function HistoryScreen() { +type Props = { navigation: any } + +export default function HistoryScreen({ navigation }: Props) { const [measurements, setMeasurements] = useState([]) const [refreshing, setRefreshing] = useState(false) @@ -27,13 +29,59 @@ export default function HistoryScreen() { setRefreshing(false) }, [load]) + const handlePress = (m: Measurement) => { + const date = new Date(m.measuredAt).toLocaleDateString('nl-NL') + Alert.alert( + date, + `${m.weight.toFixed(1)} kg ยท BMI ${m.bmi.toFixed(1)}`, + [ + { text: 'Annuleren', style: 'cancel' }, + { + text: 'Wijzigen', + onPress: () => navigation.navigate('NewMeasurement', { measurement: m }), + }, + { + text: 'Verwijderen', + style: 'destructive', + onPress: () => confirmDelete(m), + }, + ] + ) + } + + const confirmDelete = (m: Measurement) => { + const date = new Date(m.measuredAt).toLocaleDateString('nl-NL') + Alert.alert( + 'Verwijderen?', + `Meting van ${date} definitief verwijderen?`, + [ + { text: 'Annuleren', style: 'cancel' }, + { + text: 'Ja, verwijderen', + style: 'destructive', + onPress: async () => { + await initDatabase() + await deleteMeasurement(m.id) + try { + const { syncAll } = await import('../sync/syncService') + await syncAll() + } catch {} + load() + }, + }, + ] + ) + } + return ( {measurements.length} metingen item.id} - renderItem={({ item }) => } + renderItem={({ item }) => ( + handlePress(item)} /> + )} contentContainerStyle={measurements.length === 0 ? styles.empty : undefined} ListEmptyComponent={Nog geen metingen} refreshControl={ diff --git a/src/screens/NewMeasurementScreen.tsx b/src/screens/NewMeasurementScreen.tsx index c1f433a..82eb6f3 100644 --- a/src/screens/NewMeasurementScreen.tsx +++ b/src/screens/NewMeasurementScreen.tsx @@ -1,34 +1,64 @@ -import React, { useCallback, useState } from 'react' +import React, { useCallback, useEffect, useState } from 'react' import { View, Text, Alert } from 'react-native' import { useFocusEffect } from '@react-navigation/native' import MeasurementForm from '../components/MeasurementForm' import { Measurement } from '../types' -import { initDatabase, insertMeasurement, getLatestMeasurement, getMeasurementByDate, upsertMeasurement } from '../database/db' +import { + initDatabase, + insertMeasurement, + getLatestMeasurement, + getMeasurementByDate, + upsertMeasurement, +} from '../database/db' type Props = { navigation: any + route: any } -export default function NewMeasurementScreen({ navigation }: Props) { +export default function NewMeasurementScreen({ navigation, route }: Props) { + const editing = route.params?.measurement as Measurement | undefined const [latest, setLatest] = useState | undefined>(undefined) + const [loaded, setLoaded] = useState(false) useFocusEffect( useCallback(() => { let cancelled = false const load = async () => { await initDatabase() - const m = await getLatestMeasurement() - if (!cancelled) { - setLatest(m || {}) + if (editing) { + if (!cancelled) { + setLatest(editing) + setLoaded(true) + } + } else { + const m = await getLatestMeasurement() + if (!cancelled) { + setLatest(m || {}) + setLoaded(true) + } } } load() return () => { cancelled = true } - }, []) + }, [editing]) ) + useEffect(() => { + if (editing) { + navigation.setOptions({ title: 'Meting wijzigen' }) + } + }, [editing, navigation]) + const handleSubmit = async (m: Measurement) => { await initDatabase() + if (editing) { + m.id = editing.id + m.createdAt = editing.createdAt + await upsertMeasurement(m) + doSync() + return + } const existing = await getMeasurementByDate(m.measuredAt) if (existing) { Alert.alert( @@ -36,11 +66,7 @@ export default function NewMeasurementScreen({ navigation }: Props) { `Er bestaat al een meting van ${new Date(m.measuredAt).toLocaleDateString('nl-NL')}. Overschrijven?`, [ { text: 'Annuleren', style: 'cancel' }, - { - text: 'Overschrijven', - style: 'destructive', - onPress: () => doSave(m, existing.id), - }, + { text: 'Overschrijven', style: 'destructive', onPress: () => doSave(m, existing.id) }, ] ) return @@ -55,6 +81,10 @@ export default function NewMeasurementScreen({ navigation }: Props) { } else { await insertMeasurement(m) } + doSync() + } + + const doSync = async () => { try { const { syncAll } = await import('../sync/syncService') await syncAll() @@ -68,7 +98,7 @@ export default function NewMeasurementScreen({ navigation }: Props) { } } - if (latest === undefined) { + if (!loaded) { return ( Laden...