diff --git a/BestList.tsx b/BestList.tsx deleted file mode 100644 index 069cceb..0000000 --- a/BestList.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { - NavigationProp, - useFocusEffect, - useNavigation, -} from '@react-navigation/native'; -import React, {useCallback, useEffect, useState} from 'react'; -import {FlatList, Image} from 'react-native'; -import {List} from 'react-native-paper'; -import {getBestReps, getBestWeights} from './best.service'; -import {BestPageParams} from './BestPage'; -import Page from './Page'; -import Set from './set'; -import {settings} from './settings.service'; - -export default function BestList() { - const [bests, setBests] = useState([]); - const [search, setSearch] = useState(''); - const navigation = useNavigation>(); - - const refresh = useCallback(async () => { - const weights = await getBestWeights(search); - console.log(`${BestList.name}.refresh:`, {length: weights.length}); - let newBest: Set[] = []; - for (const set of weights) { - const reps = await getBestReps(set.name, set.weight); - newBest.push(...reps); - } - setBests(newBest); - }, [search]); - - useFocusEffect( - useCallback(() => { - refresh(); - navigation.getParent()?.setOptions({ - headerRight: () => null, - }); - }, [refresh, navigation]), - ); - - useEffect(() => { - refresh(); - }, [search, refresh]); - - const renderItem = ({item}: {item: Set}) => ( - navigation.navigate('ViewBest', {best: item})} - left={() => - (settings.images && item.image && ( - - )) || - null - } - /> - ); - - return ( - - - } - renderItem={renderItem} - data={bests} - /> - - ); -} diff --git a/BestPage.tsx b/BestPage.tsx index 5f8496c..4098acd 100644 --- a/BestPage.tsx +++ b/BestPage.tsx @@ -1,42 +1,74 @@ -import {DrawerNavigationProp} from '@react-navigation/drawer'; -import {useNavigation} from '@react-navigation/native'; -import {createStackNavigator} from '@react-navigation/stack'; -import React from 'react'; -import {IconButton} from 'react-native-paper'; -import BestList from './BestList'; +import { + NavigationProp, + useFocusEffect, + useNavigation, +} from '@react-navigation/native'; +import {default as React, useCallback, useEffect, useState} from 'react'; +import {FlatList, Image} from 'react-native'; +import {List} from 'react-native-paper'; +import {getBestReps, getBestWeights} from './best.service'; import {DrawerParamList} from './drawer-param-list'; +import Page from './Page'; import Set from './set'; -import ViewBest from './ViewBest'; - -const Stack = createStackNavigator(); -export type BestPageParams = { - BestList: {}; - ViewBest: { - best: Set; - }; -}; +import {settings} from './settings.service'; export default function BestPage() { - const navigation = useNavigation>(); + const [bests, setBests] = useState([]); + const [search, setSearch] = useState(''); + const navigation = useNavigation>(); + + const refresh = useCallback(async () => { + const weights = await getBestWeights(search); + console.log(`${BestPage.name}.refresh:`, {length: weights.length}); + let newBest: Set[] = []; + for (const set of weights) { + const reps = await getBestReps(set.name, set.weight); + newBest.push(...reps); + } + setBests(newBest); + }, [search]); + + useFocusEffect( + useCallback(() => { + refresh(); + navigation.getParent()?.setOptions({ + headerRight: () => null, + }); + }, [refresh, navigation]), + ); + + useEffect(() => { + refresh(); + }, [search, refresh]); + + const renderItem = ({item}: {item: Set}) => ( + navigation.navigate('View best', {best: item})} + left={() => + (settings.images && item.image && ( + + )) || + null + } + /> + ); return ( - - - { - navigation.setOptions({ - headerLeft: () => ( - - ), - title: 'Best', - }); - }, - }} + + + } + renderItem={renderItem} + data={bests} /> - + ); } diff --git a/EditPlan.tsx b/EditPlan.tsx index b8c4169..4766da4 100644 --- a/EditPlan.tsx +++ b/EditPlan.tsx @@ -10,14 +10,13 @@ import {ScrollView, StyleSheet, View} from 'react-native'; import {Button, IconButton, Text} from 'react-native-paper'; import {MARGIN, PADDING} from './constants'; import {DrawerParamList} from './drawer-param-list'; -import {PlanPageParams} from './plan-page-params'; import {addPlan, updatePlan} from './plan.service'; import {getNames} from './set.service'; import Switch from './Switch'; import {DAYS} from './time'; export default function EditPlan() { - const {params} = useRoute>(); + const {params} = useRoute>(); const {plan} = params; const [days, setDays] = useState( plan.days ? plan.days.split(',') : [], diff --git a/EditSet.tsx b/EditSet.tsx index 83ca82e..8f1b7ba 100644 --- a/EditSet.tsx +++ b/EditSet.tsx @@ -6,9 +6,8 @@ import { } from '@react-navigation/native'; import React, {useCallback, useContext} from 'react'; import {NativeModules, View} from 'react-native'; -import {IconButton} from 'react-native-paper'; import {PADDING} from './constants'; -import {HomePageParams} from './home-page-params'; +import {DrawerParamList} from './drawer-param-list'; import {SnackbarContext} from './MassiveSnack'; import Set from './set'; import {addSet, updateSet} from './set.service'; @@ -16,7 +15,7 @@ import SetForm from './SetForm'; import {getSettings, settings, updateSettings} from './settings.service'; export default function EditSet() { - const {params} = useRoute>(); + const {params} = useRoute>(); const {set, count, workouts} = params; const navigation = useNavigation(); const {toast} = useContext(SnackbarContext); @@ -28,11 +27,7 @@ export default function EditSet() { if (typeof set.id === 'number') title = 'Edit set'; else if (Number(set.sets) > 0) title = `${set.name} (${count + 1} / ${set.sets})`; - navigation.getParent()?.setOptions({ - headerLeft: () => ( - navigation.goBack()} /> - ), - headerRight: null, + navigation.setOptions({ title, }); }, [navigation, set, count]), diff --git a/EditWorkout.tsx b/EditWorkout.tsx index abb7a96..01981ea 100644 --- a/EditWorkout.tsx +++ b/EditWorkout.tsx @@ -10,15 +10,15 @@ import DocumentPicker from 'react-native-document-picker'; import {Button, Card, IconButton, TouchableRipple} from 'react-native-paper'; import ConfirmDialog from './ConfirmDialog'; import {MARGIN, PADDING} from './constants'; +import {DrawerParamList} from './drawer-param-list'; import MassiveInput from './MassiveInput'; import {SnackbarContext} from './MassiveSnack'; import {updatePlanWorkouts} from './plan.service'; import {addSet, updateManySet, updateSetImage} from './set.service'; import {settings} from './settings.service'; -import {WorkoutsPageParams} from './WorkoutsPage'; export default function EditWorkout() { - const {params} = useRoute>(); + const {params} = useRoute>(); const [removeImage, setRemoveImage] = useState(false); const [showRemove, setShowRemove] = useState(false); const [name, setName] = useState(params.value.name); diff --git a/HomePage.tsx b/HomePage.tsx index fc0350e..780e73b 100644 --- a/HomePage.tsx +++ b/HomePage.tsx @@ -1,36 +1,135 @@ -import {DrawerNavigationProp} from '@react-navigation/drawer'; -import {useNavigation} from '@react-navigation/native'; -import {createStackNavigator} from '@react-navigation/stack'; -import React from 'react'; -import {IconButton} from 'react-native-paper'; +import { + NavigationProp, + useFocusEffect, + useNavigation, +} from '@react-navigation/native'; +import {default as React, useCallback, useEffect, useState} from 'react'; +import {FlatList} from 'react-native'; +import {List} from 'react-native-paper'; +import {getBestSet} from './best.service'; import {DrawerParamList} from './drawer-param-list'; -import EditSet from './EditSet'; -import {HomePageParams} from './home-page-params'; -import SetList from './SetList'; +import Page from './Page'; +import {getTodaysPlan} from './plan.service'; +import Set from './set'; +import {countToday, defaultSet, getSets, getToday} from './set.service'; +import SetItem from './SetItem'; +import {settings} from './settings.service'; -const Stack = createStackNavigator(); +const limit = 15; export default function HomePage() { - const navigation = useNavigation>(); + const [sets, setSets] = useState(); + const [set, setSet] = useState(); + const [count, setCount] = useState(0); + const [workouts, setWorkouts] = useState([]); + const [offset, setOffset] = useState(0); + const [search, setSearch] = useState(''); + const [end, setEnd] = useState(false); + const [dates, setDates] = useState(false); + const [images, setImages] = useState(true); + const navigation = useNavigation>(); + + const predict = useCallback(async () => { + setCount(0); + setSet({...defaultSet}); + if (!settings.predict) return; + const todaysPlan = await getTodaysPlan(); + console.log(`${HomePage.name}.predict:`, {todaysPlan}); + if (todaysPlan.length === 0) return; + const todaysWorkouts = todaysPlan[0].workouts.split(','); + setWorkouts(todaysWorkouts); + let best = await getBestSet(todaysWorkouts[0]); + const todaysSet = await getToday(); + if (!todaysSet || !todaysWorkouts.includes(todaysSet.name)) + return setSet({...best}); + let _count = await countToday(todaysSet.name); + best = await getBestSet(todaysSet.name); + const index = todaysWorkouts.indexOf(todaysSet.name) + 1; + if (_count >= Number(best.sets)) { + best = await getBestSet(todaysWorkouts[index]); + _count = 0; + } + if (best.name === '') setCount(0); + else setCount(_count); + setSet({...best}); + }, []); + + const refresh = useCallback(async () => { + predict(); + const newSets = await getSets({search: `%${search}%`, limit, offset: 0}); + console.log(`${HomePage.name}.refresh:`, {first: newSets[0]}); + if (newSets.length === 0) return setSets([]); + setSets(newSets); + setOffset(0); + setEnd(false); + }, [search, predict]); + + useFocusEffect( + useCallback(() => { + refresh(); + setImages(!!settings.images); + }, [refresh]), + ); + + useEffect(() => { + refresh(); + }, [search, refresh]); + + const renderItem = useCallback( + ({item}: {item: Set}) => ( + + ), + [refresh, dates, setDates, images, setImages], + ); + + const next = useCallback(async () => { + if (end) return; + const newOffset = offset + limit; + console.log(`${HomePage.name}.next:`, {offset, newOffset, search}); + const newSets = await getSets({ + search: `%${search}%`, + limit, + offset: newOffset, + }); + if (newSets.length === 0) return setEnd(true); + if (!sets) return; + setSets([...sets, ...newSets]); + if (newSets.length < limit) return setEnd(true); + setOffset(newOffset); + }, [search, end, offset, sets]); + + const onAdd = useCallback(async () => { + console.log(`${HomePage.name}.onAdd`, {set, workouts}); + navigation.navigate('Edit set', { + set: set || {...defaultSet}, + workouts, + count, + }); + }, [navigation, set, workouts, count]); return ( - - - { - navigation.setOptions({ - headerLeft: () => ( - - ), - title: 'Home', - }); - }, - }} + + + } + renderItem={renderItem} + keyExtractor={s => s.id!.toString()} + onEndReached={next} /> - + ); } diff --git a/PlanItem.tsx b/PlanItem.tsx index 2dcd173..ce1cb02 100644 --- a/PlanItem.tsx +++ b/PlanItem.tsx @@ -2,8 +2,8 @@ import {NavigationProp, useNavigation} from '@react-navigation/native'; import React, {useCallback, useState} from 'react'; import {GestureResponderEvent} from 'react-native'; import {List, Menu} from 'react-native-paper'; +import {DrawerParamList} from './drawer-param-list'; import {Plan} from './plan'; -import {PlanPageParams} from './plan-page-params'; import {deletePlan} from './plan.service'; export default function PlanItem({ @@ -15,7 +15,7 @@ export default function PlanItem({ }) { const [show, setShow] = useState(false); const [anchor, setAnchor] = useState({x: 0, y: 0}); - const navigation = useNavigation>(); + const navigation = useNavigation>(); const remove = useCallback(async () => { if (typeof item.id === 'number') await deletePlan(item.id); @@ -34,7 +34,7 @@ export default function PlanItem({ return ( <> navigation.navigate('EditPlan', {plan: item})} + onPress={() => navigation.navigate('Edit plan', {plan: item})} title={ item.days ? item.days.replace(/,/g, ', ') diff --git a/PlanList.tsx b/PlanList.tsx deleted file mode 100644 index ccf3c1b..0000000 --- a/PlanList.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { - NavigationProp, - useFocusEffect, - useNavigation, -} from '@react-navigation/native'; -import React, {useCallback, useEffect, useState} from 'react'; -import {FlatList} from 'react-native'; -import {List} from 'react-native-paper'; -import DrawerMenu from './DrawerMenu'; -import Page from './Page'; -import {Plan} from './plan'; -import {PlanPageParams} from './plan-page-params'; -import {getPlans} from './plan.service'; -import PlanItem from './PlanItem'; - -export default function PlanList() { - const [search, setSearch] = useState(''); - const [plans, setPlans] = useState([]); - const navigation = useNavigation>(); - - const refresh = useCallback(async () => { - getPlans(search).then(setPlans); - }, [search]); - - useFocusEffect( - useCallback(() => { - refresh(); - navigation.getParent()?.setOptions({ - headerRight: () => , - }); - }, [refresh, navigation]), - ); - - useEffect(() => { - refresh(); - }, [search, refresh]); - - const renderItem = useCallback( - ({item}: {item: Plan}) => ( - - ), - [refresh], - ); - - const onAdd = () => - navigation.navigate('EditPlan', {plan: {days: '', workouts: ''}}); - - return ( - - set.id?.toString() || ''} - ListEmptyComponent={ - - } - /> - - ); -} diff --git a/PlanPage.tsx b/PlanPage.tsx index 8a08823..b3087d3 100644 --- a/PlanPage.tsx +++ b/PlanPage.tsx @@ -1,36 +1,64 @@ -import {DrawerNavigationProp} from '@react-navigation/drawer'; -import {useNavigation} from '@react-navigation/native'; -import {createStackNavigator} from '@react-navigation/stack'; -import React from 'react'; -import {IconButton} from 'react-native-paper'; +import { + NavigationProp, + useFocusEffect, + useNavigation, +} from '@react-navigation/native'; +import {default as React, useCallback, useEffect, useState} from 'react'; +import {FlatList} from 'react-native'; +import {List} from 'react-native-paper'; import {DrawerParamList} from './drawer-param-list'; -import EditPlan from './EditPlan'; -import {PlanPageParams} from './plan-page-params'; -import PlanList from './PlanList'; - -const Stack = createStackNavigator(); +import DrawerMenu from './DrawerMenu'; +import Page from './Page'; +import {Plan} from './plan'; +import {getPlans} from './plan.service'; +import PlanItem from './PlanItem'; export default function PlanPage() { - const navigation = useNavigation>(); + const [search, setSearch] = useState(''); + const [plans, setPlans] = useState([]); + const navigation = useNavigation>(); + + const refresh = useCallback(async () => { + getPlans(search).then(setPlans); + }, [search]); + + useFocusEffect( + useCallback(() => { + refresh(); + navigation.getParent()?.setOptions({ + headerRight: () => , + }); + }, [refresh, navigation]), + ); + + useEffect(() => { + refresh(); + }, [search, refresh]); + + const renderItem = useCallback( + ({item}: {item: Plan}) => ( + + ), + [refresh], + ); + + const onAdd = () => + navigation.navigate('Edit plan', {plan: {days: '', workouts: ''}}); return ( - - - { - navigation.setOptions({ - headerLeft: () => ( - - ), - title: 'Plans', - }); - }, - }} + + set.id?.toString() || ''} + ListEmptyComponent={ + + } /> - + ); } diff --git a/Routes.tsx b/Routes.tsx index af0a6a9..571eec0 100644 --- a/Routes.tsx +++ b/Routes.tsx @@ -1,4 +1,5 @@ import {createDrawerNavigator} from '@react-navigation/drawer'; +import {useNavigation} from '@react-navigation/native'; import React, {useContext, useEffect, useState} from 'react'; import {useColorScheme} from 'react-native'; import {IconButton} from 'react-native-paper'; @@ -6,11 +7,16 @@ import {CustomTheme} from './App'; import BestPage from './BestPage'; import {runMigrations} from './db'; import {DrawerParamList} from './drawer-param-list'; +import DrawerMenu from './DrawerMenu'; +import EditPlan from './EditPlan'; +import EditSet from './EditSet'; +import EditWorkout from './EditWorkout'; import HomePage from './HomePage'; import PlanPage from './PlanPage'; import Route from './route'; import {getSettings, settings} from './settings.service'; import SettingsPage from './SettingsPage'; +import ViewBest from './ViewBest'; import WorkoutsPage from './WorkoutsPage'; const Drawer = createDrawerNavigator(); @@ -19,6 +25,7 @@ export default function Routes() { const [migrated, setMigrated] = useState(false); const dark = useColorScheme() === 'dark'; const {setColor} = useContext(CustomTheme); + const navigation = useNavigation(); useEffect(() => { runMigrations() @@ -39,6 +46,13 @@ export default function Routes() { {name: 'Settings', component: SettingsPage, icon: 'settings'}, ]; + const hiddenRoutes: Route[] = [ + {name: 'Edit set', component: EditSet}, + {name: 'Edit plan', component: EditPlan}, + {name: 'Edit workout', component: EditWorkout}, + {name: 'View best', component: ViewBest}, + ]; + return ( , + drawerIcon: () => , + headerRight: () => , + }} + /> + ))} + {hiddenRoutes.map(route => ( + ( + navigation.goBack()} + /> + ), }} /> ))} diff --git a/SetForm.tsx b/SetForm.tsx index b828449..3109285 100644 --- a/SetForm.tsx +++ b/SetForm.tsx @@ -31,12 +31,16 @@ export default function SetForm({ const unitRef = useRef(null); useEffect(() => { - console.log('SetForm.useEffect:', {uri, name: set.name}); + console.log('SetForm.useEffect:', {uri, set, name, reps, unit}); + setName(set.name); + setReps(set.reps.toString()); + setWeight(set.weight.toString()); + setUnit(set.unit); if (!uri) getSets({search: set.name, limit: 1, offset: 0}).then(([s]) => setUri(s?.image), ); - }, [uri, set.name]); + }, [uri, set, name, reps, unit]); const handleSubmit = () => { if (!name) return; @@ -109,7 +113,7 @@ export default function SetForm({ {workouts.length > 0 && !!settings.workouts && ( {workouts.map((workout, index) => ( - + >(); + const navigation = useNavigation>(); const remove = useCallback(async () => { if (typeof item.id === 'number') await deleteSet(item.id); @@ -35,7 +35,7 @@ export default function SetItem({ const set: Set = {...item}; delete set.id; setShowMenu(false); - navigation.navigate('EditSet', {set, workouts: [], count: 0}); + navigation.navigate('Edit set', {set, workouts: [], count: 0}); }, [navigation, item]); const longPress = useCallback( @@ -60,7 +60,7 @@ export default function SetItem({ <> - navigation.navigate('EditSet', {set: item, workouts: [], count: 0}) + navigation.navigate('Edit set', {set: item, workouts: [], count: 0}) } title={item.name} description={`${item.reps} x ${item.weight}${item.unit || 'kg'}`} diff --git a/SetList.tsx b/SetList.tsx deleted file mode 100644 index 25737a1..0000000 --- a/SetList.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import { - NavigationProp, - useFocusEffect, - useNavigation, -} from '@react-navigation/native'; -import React, {useCallback, useEffect, useState} from 'react'; -import {FlatList} from 'react-native'; -import {List} from 'react-native-paper'; -import {getBestSet} from './best.service'; -import DrawerMenu from './DrawerMenu'; -import {HomePageParams} from './home-page-params'; -import Page from './Page'; -import {getTodaysPlan} from './plan.service'; -import Set from './set'; -import {countToday, defaultSet, getSets, getToday} from './set.service'; -import SetItem from './SetItem'; -import {settings} from './settings.service'; - -const limit = 15; - -export default function SetList() { - const [sets, setSets] = useState(); - const [set, setSet] = useState(); - const [count, setCount] = useState(0); - const [workouts, setWorkouts] = useState([]); - const [offset, setOffset] = useState(0); - const [search, setSearch] = useState(''); - const [end, setEnd] = useState(false); - const [dates, setDates] = useState(false); - const [images, setImages] = useState(true); - const navigation = useNavigation>(); - - const predict = useCallback(async () => { - setCount(0); - setSet({...defaultSet}); - if (!settings.predict) return; - const todaysPlan = await getTodaysPlan(); - if (todaysPlan.length === 0) return; - const todaysWorkouts = todaysPlan[0].workouts.split(','); - setWorkouts(todaysWorkouts); - let workout = todaysWorkouts[0]; - let best = await getBestSet(workout); - const todaysSet = await getToday(); - if (!todaysSet || !todaysWorkouts.includes(todaysSet.name)) - return setSet(best); - let _count = await countToday(todaysSet.name); - workout = todaysSet.name; - best = await getBestSet(workout); - const index = todaysWorkouts.indexOf(todaysSet.name) + 1; - if (_count >= Number(best.sets)) { - best = await getBestSet(todaysWorkouts[index]); - _count = 0; - } - if (best.name === '') setCount(0); - else setCount(_count); - setSet(best); - }, []); - - const refresh = useCallback(async () => { - predict(); - const newSets = await getSets({search: `%${search}%`, limit, offset: 0}); - console.log(`${SetList.name}.refresh:`, {first: newSets[0]}); - if (newSets.length === 0) return setSets([]); - setSets(newSets); - setOffset(0); - setEnd(false); - }, [search, predict]); - - useFocusEffect( - useCallback(() => { - refresh(); - navigation.getParent()?.setOptions({ - headerRight: () => , - }); - setImages(!!settings.images); - }, [refresh, navigation]), - ); - - useEffect(() => { - refresh(); - }, [search, refresh]); - - const renderItem = useCallback( - ({item}: {item: Set}) => ( - - ), - [refresh, dates, setDates, images, setImages], - ); - - const next = useCallback(async () => { - if (end) return; - const newOffset = offset + limit; - console.log(`${SetList.name}.next:`, {offset, newOffset, search}); - const newSets = await getSets({ - search: `%${search}%`, - limit, - offset: newOffset, - }); - if (newSets.length === 0) return setEnd(true); - if (!sets) return; - setSets([...sets, ...newSets]); - if (newSets.length < limit) return setEnd(true); - setOffset(newOffset); - }, [search, end, offset, sets]); - - const onAdd = useCallback(async () => { - console.log(`${SetList.name}.onAdd`, {set, defaultSet, workouts}); - navigation.navigate('EditSet', { - set: set || {...defaultSet}, - workouts, - count, - }); - }, [navigation, set, workouts, count]); - - return ( - - - } - renderItem={renderItem} - keyExtractor={s => s.id!.toString()} - onEndReached={next} - /> - - ); -} diff --git a/ViewBest.tsx b/ViewBest.tsx index 1532d12..f18f86e 100644 --- a/ViewBest.tsx +++ b/ViewBest.tsx @@ -12,9 +12,9 @@ import {IconButton} from 'react-native-paper'; import Share from 'react-native-share'; import {captureScreen} from 'react-native-view-shot'; import {getVolumes, getWeightsBy} from './best.service'; -import {BestPageParams} from './BestPage'; import Chart from './Chart'; import {PADDING} from './constants'; +import {DrawerParamList} from './drawer-param-list'; import {Metrics} from './metrics'; import {Periods} from './periods'; import Set from './set'; @@ -22,7 +22,7 @@ import {formatMonth} from './time'; import Volume from './volume'; export default function ViewBest() { - const {params} = useRoute>(); + const {params} = useRoute>(); const dark = useColorScheme() === 'dark'; const [weights, setWeights] = useState([]); const [volumes, setVolumes] = useState([]); diff --git a/WorkoutItem.tsx b/WorkoutItem.tsx index 736d995..8672fef 100644 --- a/WorkoutItem.tsx +++ b/WorkoutItem.tsx @@ -3,9 +3,9 @@ import React, {useCallback, useState} from 'react'; import {GestureResponderEvent, Image} from 'react-native'; import {List, Menu, Text} from 'react-native-paper'; import ConfirmDialog from './ConfirmDialog'; +import {DrawerParamList} from './drawer-param-list'; import Set from './set'; import {deleteSetsBy} from './set.service'; -import {WorkoutsPageParams} from './WorkoutsPage'; export default function WorkoutItem({ item, @@ -17,7 +17,7 @@ export default function WorkoutItem({ const [showMenu, setShowMenu] = useState(false); const [anchor, setAnchor] = useState({x: 0, y: 0}); const [showRemove, setShowRemove] = useState(''); - const navigation = useNavigation>(); + const navigation = useNavigation>(); const remove = useCallback(async () => { await deleteSetsBy(item.name); @@ -39,7 +39,7 @@ export default function WorkoutItem({ return ( <> navigation.navigate('EditWorkout', {value: item})} + onPress={() => navigation.navigate('Edit workout', {value: item})} title={item.name} description={`${item.sets} sets ${minutes}:${seconds} rest`} onLongPress={longPress} diff --git a/WorkoutList.tsx b/WorkoutList.tsx deleted file mode 100644 index 85bfadb..0000000 --- a/WorkoutList.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { - NavigationProp, - useFocusEffect, - useNavigation, -} from '@react-navigation/native'; -import React, {useCallback, useEffect, useState} from 'react'; -import {FlatList} from 'react-native'; -import {List} from 'react-native-paper'; -import Page from './Page'; -import Set from './set'; -import {getDistinctSets} from './set.service'; -import SetList from './SetList'; -import WorkoutItem from './WorkoutItem'; -import {WorkoutsPageParams} from './WorkoutsPage'; - -const limit = 15; - -export default function WorkoutList() { - const [workouts, setWorkouts] = useState(); - const [offset, setOffset] = useState(0); - const [search, setSearch] = useState(''); - const [end, setEnd] = useState(false); - const navigation = useNavigation>(); - - const refresh = useCallback(async () => { - const newWorkouts = await getDistinctSets({ - search: `%${search}%`, - limit, - offset: 0, - }); - console.log(`${WorkoutList.name}`, {newWorkout: newWorkouts[0]}); - setWorkouts(newWorkouts); - setOffset(0); - setEnd(false); - }, [search]); - - useEffect(() => { - refresh(); - }, [search, refresh]); - - useFocusEffect( - useCallback(() => { - refresh(); - }, [refresh]), - ); - - const renderItem = useCallback( - ({item}: {item: Set}) => ( - - ), - [refresh], - ); - - const next = useCallback(async () => { - if (end) return; - const newOffset = offset + limit; - console.log(`${SetList.name}.next:`, { - offset, - limit, - newOffset, - search, - }); - const newWorkouts = await getDistinctSets({ - search: `%${search}%`, - limit, - offset: newOffset, - }); - if (newWorkouts.length === 0) return setEnd(true); - if (!workouts) return; - setWorkouts([...workouts, ...newWorkouts]); - if (newWorkouts.length < limit) return setEnd(true); - setOffset(newOffset); - }, [search, end, offset, workouts]); - - const onAdd = useCallback(async () => { - navigation.navigate('EditWorkout', { - value: {name: '', sets: 3, image: '', steps: '', reps: 0, weight: 0}, - }); - }, [navigation]); - - return ( - - - } - renderItem={renderItem} - keyExtractor={w => w.name} - onEndReached={next} - /> - - ); -} diff --git a/WorkoutsPage.tsx b/WorkoutsPage.tsx index 17912df..8859978 100644 --- a/WorkoutsPage.tsx +++ b/WorkoutsPage.tsx @@ -1,43 +1,97 @@ -import {DrawerNavigationProp} from '@react-navigation/drawer'; -import {useNavigation} from '@react-navigation/native'; -import {createStackNavigator} from '@react-navigation/stack'; -import React from 'react'; -import {IconButton} from 'react-native-paper'; +import { + NavigationProp, + useFocusEffect, + useNavigation, +} from '@react-navigation/native'; +import React, {useCallback, useEffect, useState} from 'react'; +import {FlatList} from 'react-native'; +import {List} from 'react-native-paper'; import {DrawerParamList} from './drawer-param-list'; -import EditWorkout from './EditWorkout'; +import Page from './Page'; import Set from './set'; -import WorkoutList from './WorkoutList'; +import {getDistinctSets} from './set.service'; +import WorkoutItem from './WorkoutItem'; -export type WorkoutsPageParams = { - WorkoutList: {}; - EditWorkout: { - value: Set; - }; -}; - -const Stack = createStackNavigator(); +const limit = 15; export default function WorkoutsPage() { - const navigation = useNavigation>(); + const [workouts, setWorkouts] = useState(); + const [offset, setOffset] = useState(0); + const [search, setSearch] = useState(''); + const [end, setEnd] = useState(false); + const navigation = useNavigation>(); + + const refresh = useCallback(async () => { + const newWorkouts = await getDistinctSets({ + search: `%${search}%`, + limit, + offset: 0, + }); + console.log(`${WorkoutsPage.name}`, {newWorkout: newWorkouts[0]}); + setWorkouts(newWorkouts); + setOffset(0); + setEnd(false); + }, [search]); + + useEffect(() => { + refresh(); + }, [search, refresh]); + + useFocusEffect( + useCallback(() => { + refresh(); + }, [refresh]), + ); + + const renderItem = useCallback( + ({item}: {item: Set}) => ( + + ), + [refresh], + ); + + const next = useCallback(async () => { + if (end) return; + const newOffset = offset + limit; + console.log(`${WorkoutsPage.name}.next:`, { + offset, + limit, + newOffset, + search, + }); + const newWorkouts = await getDistinctSets({ + search: `%${search}%`, + limit, + offset: newOffset, + }); + if (newWorkouts.length === 0) return setEnd(true); + if (!workouts) return; + setWorkouts([...workouts, ...newWorkouts]); + if (newWorkouts.length < limit) return setEnd(true); + setOffset(newOffset); + }, [search, end, offset, workouts]); + + const onAdd = useCallback(async () => { + navigation.navigate('Edit workout', { + value: {name: '', sets: 3, image: '', steps: '', reps: 0, weight: 0}, + }); + }, [navigation]); return ( - - - { - navigation.setOptions({ - headerLeft: () => ( - - ), - title: 'Workouts', - }); - }, - }} + + + } + renderItem={renderItem} + keyExtractor={w => w.name} + onEndReached={next} /> - + ); } diff --git a/drawer-param-list.ts b/drawer-param-list.ts index e590f4c..251a2e7 100644 --- a/drawer-param-list.ts +++ b/drawer-param-list.ts @@ -1,7 +1,24 @@ +import {Plan} from './plan'; +import Set from './set'; + export type DrawerParamList = { Home: {}; Settings: {}; Best: {}; Plans: {}; Workouts: {}; + 'Edit set': { + set: Set; + workouts: string[]; + count: number; + }; + 'Edit plan': { + plan: Plan; + }; + 'Edit workout': { + value: Set; + }; + 'View best': { + best: Set; + }; }; diff --git a/home-page-params.ts b/home-page-params.ts deleted file mode 100644 index d0eb7f8..0000000 --- a/home-page-params.ts +++ /dev/null @@ -1,10 +0,0 @@ -import Set from './set'; - -export type HomePageParams = { - Sets: {}; - EditSet: { - set: Set; - workouts: string[]; - count: number; - }; -}; diff --git a/package.json b/package.json index 844aa59..a62d3dc 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,6 @@ "@react-native-picker/picker": "^2.4.4", "@react-navigation/drawer": "^6.5.0", "@react-navigation/native": "^6.0.13", - "@react-navigation/stack": "^6.3.0", "@types/d3-shape": "^3.1.0", "@types/react-native-sqlite-storage": "^5.0.2", "@types/react-native-svg-charts": "^5.0.12", diff --git a/plan-page-params.ts b/plan-page-params.ts deleted file mode 100644 index 89e15d1..0000000 --- a/plan-page-params.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {Plan} from './plan'; - -export type PlanPageParams = { - PlanList: {}; - EditPlan: { - plan: Plan; - }; -}; diff --git a/route.ts b/route.ts index b8d37c1..7e8dc75 100644 --- a/route.ts +++ b/route.ts @@ -3,5 +3,5 @@ import {DrawerParamList} from './drawer-param-list'; export default interface Route { name: keyof DrawerParamList; component: React.ComponentType; - icon: string; + icon?: string; } diff --git a/yarn.lock b/yarn.lock index 7f31363..32a6bcd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2393,24 +2393,6 @@ __metadata: languageName: node linkType: hard -"@react-navigation/stack@npm:^6.3.0": - version: 6.3.0 - resolution: "@react-navigation/stack@npm:6.3.0" - dependencies: - "@react-navigation/elements": ^1.3.6 - color: ^4.2.3 - warn-once: ^0.1.0 - peerDependencies: - "@react-navigation/native": ^6.0.0 - react: "*" - react-native: "*" - react-native-gesture-handler: ">= 1.0.0" - react-native-safe-area-context: ">= 3.0.0" - react-native-screens: ">= 3.0.0" - checksum: fac540297b827249317e1383b6b4d47b3f356e6d20f8e9acadfb5ce5973faf63e56b74b18846837031c15264fc37518701aae16efcf9b8131d22b66f47c19d14 - languageName: node - linkType: hard - "@sideway/address@npm:^4.1.3": version: 4.1.4 resolution: "@sideway/address@npm:4.1.4" @@ -6434,7 +6416,6 @@ __metadata: "@react-native-picker/picker": ^2.4.4 "@react-navigation/drawer": ^6.5.0 "@react-navigation/native": ^6.0.13 - "@react-navigation/stack": ^6.3.0 "@types/d3-shape": ^3.1.0 "@types/react-native": ^0.69.0 "@types/react-native-sqlite-storage": ^5.0.2