From d9c9a08710c6bd49e81cf1763cafb1ffc99c5b55 Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Sat, 15 Jul 2023 12:14:41 +1200 Subject: [PATCH] Copy scaffolding from Sets to Food Still need to add migrations for the food table. --- EditFoods.tsx | 158 +++++++++++++++++++++++++++++++++++++++++++ FoodItem.tsx | 74 ++++++++++++++++++++ FoodList.tsx | 57 ++++++++-------- FoodPage.tsx | 7 +- Routes.tsx | 3 +- SetItem.tsx | 4 +- SetList.tsx | 22 +++--- constants.ts | 2 + drawer-param-list.ts | 1 + food.ts | 3 + 10 files changed, 286 insertions(+), 45 deletions(-) create mode 100644 EditFoods.tsx create mode 100644 FoodItem.tsx diff --git a/EditFoods.tsx b/EditFoods.tsx new file mode 100644 index 0000000..2034265 --- /dev/null +++ b/EditFoods.tsx @@ -0,0 +1,158 @@ +import { + RouteProp, + useFocusEffect, + useNavigation, + useRoute, +} from '@react-navigation/native' +import { useCallback, useState } from 'react' +import { View } from 'react-native' +import DocumentPicker from 'react-native-document-picker' +import { Button, Card, TouchableRipple } from 'react-native-paper' +import { In } from 'typeorm' +import AppInput from './AppInput' +import ConfirmDialog from './ConfirmDialog' +import { FoodPageParams } from './FoodPage' +import StackHeader from './StackHeader' +import { MARGIN, PADDING } from './constants' +import { setRepo, settingsRepo } from './db' +import GymSet from './gym-set' +import Settings from './settings' + +export default function EditFoods() { + const { params } = useRoute>() + const { ids } = params + const navigation = useNavigation() + const [settings, setSettings] = useState({} as Settings) + const [name, setName] = useState('') + const [reps, setReps] = useState('') + const [weight, setWeight] = useState('') + const [newImage, setNewImage] = useState('') + const [unit, setUnit] = useState('') + const [showRemove, setShowRemove] = useState(false) + const [names, setNames] = useState('') + const [oldReps, setOldReps] = useState('') + const [weights, setWeights] = useState('') + const [units, setUnits] = useState('') + + const [selection, setSelection] = useState({ + start: 0, + end: 1, + }) + + useFocusEffect( + useCallback(() => { + settingsRepo.findOne({ where: {} }).then(setSettings) + setRepo.find({ where: { id: In(ids) } }).then((sets) => { + setNames(sets.map((set) => set.name).join(', ')) + setOldReps(sets.map((set) => set.reps).join(', ')) + setWeights(sets.map((set) => set.weight).join(', ')) + setUnits(sets.map((set) => set.unit).join(', ')) + }) + }, [ids]), + ) + + const handleSubmit = async () => { + console.log(`${EditFoods.name}.handleSubmit:`, { uri: newImage, name }) + const update: Partial = {} + if (name) update.name = name + if (reps) update.reps = Number(reps) + if (weight) update.weight = Number(weight) + if (unit) update.unit = unit + if (newImage) update.image = newImage + if (Object.keys(update).length > 0) await setRepo.update(ids, update) + navigation.goBack() + } + + const changeImage = useCallback(async () => { + const { fileCopyUri } = await DocumentPicker.pickSingle({ + type: DocumentPicker.types.images, + copyTo: 'documentDirectory', + }) + if (fileCopyUri) setNewImage(fileCopyUri) + }, []) + + const handleRemove = useCallback(async () => { + setNewImage('') + setShowRemove(false) + }, []) + + return ( + <> + + + + + + setSelection(e.nativeEvent.selection)} + autoFocus={!!name} + /> + + + + {settings.showUnit && ( + + )} + + {settings.images && newImage && ( + setShowRemove(true)} + > + + + )} + + Are you sure you want to remove the image? + + + {settings.images && !newImage && ( + + )} + + + + + ) +} diff --git a/FoodItem.tsx b/FoodItem.tsx new file mode 100644 index 0000000..c077eb4 --- /dev/null +++ b/FoodItem.tsx @@ -0,0 +1,74 @@ +import { NavigationProp, useNavigation } from '@react-navigation/native' +import { format } from 'date-fns' +import { useCallback, useMemo } from 'react' +import { Image } from 'react-native' +import { List, Text } from 'react-native-paper' +import { FoodPageParams } from './FoodPage' +import { DARK_RIPPLE, DARK_TEXT, LIGHT_RIPPLE, LIGHT_TEXT } from './constants' +import Food from './food' +import Settings from './settings' +import useDark from './use-dark' + +export default function FoodItem({ + food, + settings, + ids, + setIds, +}: { + food: Food + onRemove: () => void + settings: Settings + ids: number[] + setIds: (value: number[]) => void +}) { + const dark = useDark() + const navigation = useNavigation>() + + const longPress = useCallback(() => { + if (ids.length > 0) return + setIds([food.id]) + }, [ids.length, food.id, setIds]) + + const press = useCallback(() => { + if (ids.length === 0) return navigation.navigate('EditFood', { food }) + const removing = ids.find((id) => id === food.id) + if (removing) setIds(ids.filter((id) => id !== food.id)) + else setIds([...ids, food.id]) + }, [ids, food, navigation, setIds]) + + const backgroundColor = useMemo(() => { + if (!ids.includes(food.id)) return + if (dark) return DARK_RIPPLE + return LIGHT_RIPPLE + }, [dark, ids, food.id]) + + return ( + + settings.images && + food.image && ( + + )} + right={() => ( + settings.showDate && ( + + {format(new Date(food.created), settings.date || 'P')} + + ) + )} + /> + ) +} diff --git a/FoodList.tsx b/FoodList.tsx index 99e1964..73b1243 100644 --- a/FoodList.tsx +++ b/FoodList.tsx @@ -1,20 +1,19 @@ import { - NavigationProp, - useFocusEffect, - useNavigation, + NavigationProp, + useFocusEffect, + useNavigation, } from '@react-navigation/native' import { useCallback, useState } from 'react' import { FlatList } from 'react-native' -import { List } from 'react-native-paper' +import { ActivityIndicator, List } from 'react-native-paper' import { Like } from 'typeorm' import DrawerHeader from './DrawerHeader' +import FoodItem from './FoodItem' import { FoodPageParams } from './FoodPage' import ListMenu from './ListMenu' import Page from './Page' -import SetItem from './SetItem' import { foodRepo, getNow, settingsRepo } from './db' import Food, { defaultFood } from './food' -import GymSet from './gym-set' import Settings from './settings' const limit = 15 @@ -29,14 +28,14 @@ export default function FoodList() { const navigation = useNavigation>() const refresh = useCallback(async (value: string) => { - const newSets = await foodRepo.find({ + const newFoods = await foodRepo.find({ where: { name: Like(`%${value.trim()}%`) }, take: limit, skip: 0, order: { created: 'DESC' }, }) console.log(`${FoodList.name}.refresh:`, { value, limit }) - setFoods(newSets) + setFoods(newFoods) setOffset(0) setEnd(false) }, []) @@ -49,10 +48,10 @@ export default function FoodList() { ) const renderItem = useCallback( - ({ item }: { item: GymSet }) => ( - ( + refresh(term)} ids={ids} @@ -66,16 +65,16 @@ export default function FoodList() { if (end) return const newOffset = offset + limit console.log(`${FoodList.name}.next:`, { offset, newOffset, term }) - const newSets = await foodRepo.find({ + const newFoods = await foodRepo.find({ where: { name: Like(`%${term}%`) }, take: limit, skip: newOffset, order: { created: 'DESC' }, }) - if (newSets.length === 0) return setEnd(true) + if (newFoods.length === 0) return setEnd(true) if (!foods) return - setFoods([...foods, ...newSets]) - if (newSets.length < limit) return setEnd(true) + setFoods([...foods, ...newFoods]) + if (newFoods.length < limit) return setEnd(true) setOffset(newOffset) }, [term, end, offset, foods]) @@ -96,8 +95,8 @@ export default function FoodList() { [refresh], ) - const edit = useCallback(() => { - navigation.navigate('EditFood', { ids }) + const editFoods = useCallback(() => { + navigation.navigate('EditFoods', { ids }) setIds([]) }, [ids, navigation]) @@ -125,14 +124,16 @@ export default function FoodList() { setIds(foods.map((set) => set.id)) }, [foods]) + if (!settings) return + return ( <> - 0 ? `${ids.length} selected` : 'Home'}> + 0 ? `${ids.length} selected` : 'Food'}> @@ -142,19 +143,17 @@ export default function FoodList() { {foods?.length === 0 ? ( ) : ( - settings && ( - - ) + )} diff --git a/FoodPage.tsx b/FoodPage.tsx index 6fb32a5..b1b2a38 100644 --- a/FoodPage.tsx +++ b/FoodPage.tsx @@ -4,10 +4,13 @@ import EditFood from './EditFood' import Food from './food' export type FoodPageParams = { - Food: {} + FoodList: {} EditFood: { food: Food } + EditFoods: { + ids: number[] + } } const Stack = createStackNavigator() @@ -17,7 +20,7 @@ export default function FoodPage() { - + ) diff --git a/Routes.tsx b/Routes.tsx index e1d049d..35d209d 100644 --- a/Routes.tsx +++ b/Routes.tsx @@ -8,6 +8,7 @@ import SettingsPage from './SettingsPage' import TimerPage from './TimerPage' import useDark from './use-dark' import WorkoutsPage from './WorkoutsPage' +import FoodPage from './FoodPage' const Drawer = createDrawerNavigator() @@ -49,7 +50,7 @@ export default function Routes() { /> }} /> {format(new Date(item.created), settings.date || 'P')} diff --git a/SetList.tsx b/SetList.tsx index e646cc9..05f6221 100644 --- a/SetList.tsx +++ b/SetList.tsx @@ -5,7 +5,7 @@ import { } from '@react-navigation/native' import { useCallback, useState } from 'react' import { FlatList } from 'react-native' -import { List } from 'react-native-paper' +import { ActivityIndicator, List } from 'react-native-paper' import { Like } from 'typeorm' import { getNow, setRepo, settingsRepo } from './db' import DrawerHeader from './DrawerHeader' @@ -95,7 +95,7 @@ export default function SetList() { [refresh], ) - const edit = useCallback(() => { + const editSets = useCallback(() => { navigation.navigate('EditSets', { ids }) setIds([]) }, [ids, navigation]) @@ -124,6 +124,8 @@ export default function SetList() { setIds(sets.map((set) => set.id)) }, [sets]) + if (!settings) return + return ( <> 0 ? `${ids.length} selected` : 'Home'}> @@ -131,7 +133,7 @@ export default function SetList() { onClear={clear} onCopy={copy} onDelete={remove} - onEdit={edit} + onEdit={editSets} ids={ids} onSelect={select} /> @@ -146,14 +148,12 @@ export default function SetList() { /> ) : ( - settings && ( - - ) + )} diff --git a/constants.ts b/constants.ts index 7471ca1..47dc77e 100644 --- a/constants.ts +++ b/constants.ts @@ -3,3 +3,5 @@ export const PADDING = 10 export const ITEM_PADDING = 8 export const DARK_RIPPLE = '#444444' export const LIGHT_RIPPLE = '#c2c2c2' +export const DARK_TEXT = '#909090ff' +export const LIGHT_TEXT = '#717171ff' diff --git a/drawer-param-list.ts b/drawer-param-list.ts index 4247f54..a09be43 100644 --- a/drawer-param-list.ts +++ b/drawer-param-list.ts @@ -5,4 +5,5 @@ export type DrawerParamList = { Plans: {} Workouts: {} Timer: {} + Food: {} } diff --git a/food.ts b/food.ts index 36b4068..5565fa9 100644 --- a/food.ts +++ b/food.ts @@ -22,6 +22,9 @@ export default class Food { @Column('number') calories: number + + @Column('text') + image?: string } export const defaultFood: Food = {