diff --git a/App.tsx b/App.tsx index f7ba8ec..2601aab 100644 --- a/App.tsx +++ b/App.tsx @@ -26,7 +26,7 @@ export type DrawerParamList = { Home: {}; Settings: {}; Best: {}; - Plan: {}; + Plans: {}; }; export const DatabaseContext = React.createContext({} as any); @@ -83,7 +83,7 @@ const App = () => { /> ), }} - name="Plan" + name="Plans" component={PlanPage} /> void; - plan?: Plan; - setPlan: (plan?: Plan) => void; -}) { - const [days, setDays] = useState([]); - const [workouts, setWorkouts] = useState([]); +export default function EditPlan() { + const {params} = useRoute>(); + const [days, setDays] = useState(params.plan.days.split(',')); + const [workouts, setWorkouts] = useState( + params.plan.workouts.split(','), + ); const [names, setNames] = useState([]); const db = useContext(DatabaseContext); + const navigation = useNavigation(); + + useFocusEffect( + useCallback(() => { + navigation.getParent()?.setOptions({ + headerLeft: () => ( + navigation.goBack()} /> + ), + title: 'Plan', + }); + }, []), + ); useEffect(() => { const refresh = async () => { @@ -26,19 +39,16 @@ export default function EditPlan({ ); if (!namesResult.rows.length) return setNames([]); setNames(namesResult.rows.raw().map(({name}) => name)); - if (!plan) return; - if (plan.days) setDays(plan.days.split(',')); - if (plan.workouts) setWorkouts(plan.workouts.split(',')); }; refresh(); - }, [plan, db]); + }, [db]); const save = useCallback(async () => { - console.log(`${EditPlan.name}.save`, {days, workouts, plan}); + console.log(`${EditPlan.name}.save`, {days, workouts, params}); if (!days || !workouts) return; const newWorkouts = workouts.filter(workout => workout).join(','); const newDays = days.filter(day => day).join(','); - if (!plan?.id) + if (!params.plan.id) await db.executeSql(`INSERT INTO plans(days, workouts) VALUES (?, ?)`, [ newDays, newWorkouts, @@ -46,11 +56,10 @@ export default function EditPlan({ else await db.executeSql( `UPDATE plans SET days = ?, workouts = ? WHERE id = ?`, - [newDays, newWorkouts, plan.id], + [newDays, newWorkouts, params.plan.id], ); - setPlan(undefined); - onSave(); - }, [days, workouts, db, onSave, plan, setPlan]); + navigation.goBack(); + }, [days, workouts, db, params.plan]); const toggleWorkout = useCallback( (on: boolean, name: string) => { @@ -75,60 +84,49 @@ export default function EditPlan({ ); return ( - - setPlan(undefined)}> - - {plan?.days ? `Edit "${days.slice(0, 2).join(', ')}"` : 'Add a plan'} - - - - Days - {DAYS.map(day => ( - - toggleDay(value, day)} - /> - toggleDay(!days.includes(day), day)}> - {day} - - - ))} - Workouts - {names.length === 0 && ( - - No sets found. Try going to the home page and adding some - workouts first. - - )} - {names.map(name => ( - - toggleWorkout(value, name)} - /> - toggleWorkout(!workouts.includes(name), name)}> - {name} - - - ))} - - - - - - - - + + + Days + {DAYS.map(day => ( + + toggleDay(value, day)} + /> + toggleDay(!days.includes(day), day)}> + {day} + + + ))} + Workouts + {names.length === 0 && ( + + No sets found. Try going to the home page and adding some workouts + first. + + )} + {names.map(name => ( + + toggleWorkout(value, name)} + /> + toggleWorkout(!workouts.includes(name), name)}> + {name} + + + ))} + + + ); } diff --git a/EditSet.tsx b/EditSet.tsx index c3f8fd9..0ce54a3 100644 --- a/EditSet.tsx +++ b/EditSet.tsx @@ -1,17 +1,22 @@ import AsyncStorage from '@react-native-async-storage/async-storage'; -import {RouteProp, useNavigation, useRoute} from '@react-navigation/native'; +import { + RouteProp, + useFocusEffect, + useNavigation, + useRoute, +} from '@react-navigation/native'; import React, {useCallback, useContext, useEffect, useState} from 'react'; -import {NativeModules, ScrollView, StyleSheet} from 'react-native'; +import {NativeModules, ScrollView, StyleSheet, View} from 'react-native'; import DateTimePickerModal from 'react-native-modal-datetime-picker'; -import {Button, TextInput} from 'react-native-paper'; +import {Button, IconButton, TextInput} from 'react-native-paper'; import {DatabaseContext} from './App'; -import {StackParams} from './HomePage'; +import {HomePageParams} from './HomePage'; import {Plan} from './plan'; import Set from './set'; import {DAYS, format} from './time'; export default function EditSet() { - const {params} = useRoute>(); + const {params} = useRoute>(); const [name, setName] = useState(params.set.name); const [reps, setReps] = useState(params.set.reps.toString()); const [weight, setWeight] = useState(params.set.weight.toString()); @@ -21,6 +26,17 @@ export default function EditSet() { const db = useContext(DatabaseContext); const navigation = useNavigation(); + useFocusEffect( + useCallback(() => { + navigation.getParent()?.setOptions({ + headerLeft: () => ( + navigation.goBack()} /> + ), + title: 'Set', + }); + }, []), + ); + const getTodaysPlan = useCallback(async (): Promise => { const today = DAYS[new Date().getDay()]; const [result] = await db.executeSql( @@ -113,55 +129,57 @@ export default function EditSet() { }, [update, add, params.set.id]); return ( - - - - - + + + + + + - - setShowDate(false)} - date={created} - /> + + setShowDate(false)} + date={created} + /> + - + ); } diff --git a/HomePage.tsx b/HomePage.tsx index 4abadbb..d1ed911 100644 --- a/HomePage.tsx +++ b/HomePage.tsx @@ -8,8 +8,8 @@ import EditSet from './EditSet'; import Set from './set'; import SetList from './SetList'; -const Stack = createStackNavigator(); -export type StackParams = { +const Stack = createStackNavigator(); +export type HomePageParams = { Sets: {}; EditSet: { set: Set; @@ -27,14 +27,6 @@ export default function HomePage() { name="EditSet" component={EditSet} listeners={{ - focus: () => { - navigation.setOptions({ - headerLeft: () => ( - - ), - title: 'Set', - }); - }, beforeRemove: () => { navigation.setOptions({ headerLeft: () => ( diff --git a/PlanItem.tsx b/PlanItem.tsx index 5c3e634..2b7d22b 100644 --- a/PlanItem.tsx +++ b/PlanItem.tsx @@ -1,21 +1,22 @@ +import {NavigationProp, useNavigation} from '@react-navigation/native'; import React, {useCallback, useContext, useState} from 'react'; import {GestureResponderEvent} from 'react-native'; import {List, Menu} from 'react-native-paper'; import {DatabaseContext} from './App'; import {Plan} from './plan'; +import {PlanPageParams} from './PlanPage'; export default function PlanItem({ item, - setPlan, onRemove, }: { item: Plan; - setPlan: (plan: Plan) => void; onRemove: () => void; }) { const [show, setShow] = useState(false); const [anchor, setAnchor] = useState({x: 0, y: 0}); const db = useContext(DatabaseContext); + const navigation = useNavigation>(); const remove = useCallback(async () => { await db.executeSql(`DELETE FROM plans WHERE id = ?`, [item.id]); @@ -34,7 +35,7 @@ export default function PlanItem({ return ( <> setPlan(item)} + onPress={() => navigation.navigate('EditPlan', {plan: item})} title={item.days.replace(/,/g, ', ')} description={item.workouts.replace(/,/g, ', ')} onLongPress={longPress} diff --git a/PlanList.tsx b/PlanList.tsx new file mode 100644 index 0000000..8d6d5b3 --- /dev/null +++ b/PlanList.tsx @@ -0,0 +1,92 @@ +import { + NavigationProp, + useFocusEffect, + useNavigation, +} from '@react-navigation/native'; +import React, {useCallback, useContext, useEffect, useState} from 'react'; +import {FlatList, StyleSheet, View} from 'react-native'; +import {List, Searchbar} from 'react-native-paper'; +import {DatabaseContext} from './App'; +import MassiveFab from './MassiveFab'; +import {Plan} from './plan'; +import PlanItem from './PlanItem'; +import {PlanPageParams} from './PlanPage'; + +export default function PlanList() { + const [search, setSearch] = useState(''); + const [plans, setPlans] = useState([]); + const [refreshing, setRefresing] = useState(false); + const db = useContext(DatabaseContext); + const navigation = useNavigation>(); + + const refresh = useCallback(async () => { + const selectPlans = ` + SELECT * from plans + WHERE days LIKE ? OR workouts LIKE ? + `; + const getPlans = ({s}: {s: string}) => + db.executeSql(selectPlans, [`%${s}%`, `%${s}%`]); + const [plansResult] = await getPlans({s: search}); + setPlans(plansResult.rows.raw()); + }, [search, db]); + + useFocusEffect( + useCallback(() => { + refresh(); + }, [refresh]), + ); + + useEffect(() => { + if (!search) return; + refresh(); + }, [search, refresh]); + + const renderItem = useCallback( + ({item}: {item: Plan}) => ( + + ), + [refresh], + ); + + return ( + + + set.id.toString()} + refreshing={refreshing} + onRefresh={() => { + setRefresing(true); + refresh().finally(() => setRefresing(false)); + }} + ListEmptyComponent={ + + } + /> + + + navigation.navigate('EditPlan', { + plan: {days: '', workouts: '', id: 0}, + }) + } + /> + + ); +} + +const styles = StyleSheet.create({ + container: { + flexGrow: 1, + padding: 10, + paddingBottom: '10%', + }, + progress: { + marginTop: 10, + }, +}); diff --git a/PlanPage.tsx b/PlanPage.tsx index b85e9dd..7960dcb 100644 --- a/PlanPage.tsx +++ b/PlanPage.tsx @@ -1,85 +1,42 @@ -import React, {useCallback, useContext, useEffect, useState} from 'react'; -import {FlatList, StyleSheet, View} from 'react-native'; -import {List, Searchbar} from 'react-native-paper'; -import {DatabaseContext} from './App'; +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 {DrawerParamList} from './App'; import EditPlan from './EditPlan'; -import MassiveFab from './MassiveFab'; import {Plan} from './plan'; -import PlanItem from './PlanItem'; +import PlanList from './PlanList'; + +const Stack = createStackNavigator(); +export type PlanPageParams = { + PlanList: {}; + EditPlan: { + plan: Plan; + }; +}; export default function PlanPage() { - const [search, setSearch] = useState(''); - const [plans, setPlans] = useState([]); - const [refreshing, setRefresing] = useState(false); - const [plan, setPlan] = useState(); - const db = useContext(DatabaseContext); - - const refresh = useCallback(async () => { - const selectPlans = ` - SELECT * from plans - WHERE days LIKE ? OR workouts LIKE ? - `; - const getPlans = ({s}: {s: string}) => - db.executeSql(selectPlans, [`%${s}%`, `%${s}%`]); - const [plansResult] = await getPlans({s: search}); - setPlans(plansResult.rows.raw()); - }, [search, db]); - - useEffect(() => { - refresh(); - }, [search, refresh]); - - const renderItem = useCallback( - ({item}: {item: Plan}) => ( - - ), - [setPlan, refresh], - ); + const navigation = useNavigation>(); return ( - - - set.id.toString()} - refreshing={refreshing} - onRefresh={() => { - setRefresing(true); - refresh().finally(() => setRefresing(false)); - }} - ListEmptyComponent={ - - } - /> - - - - { - setPlan({} as Plan); + + + { + navigation.setOptions({ + headerLeft: () => ( + + ), + title: 'Plans', + }); + }, }} /> - + ); } - -const styles = StyleSheet.create({ - container: { - flexGrow: 1, - padding: 10, - paddingBottom: '10%', - }, - progress: { - marginTop: 10, - }, -}); diff --git a/SetItem.tsx b/SetItem.tsx index 8d1a805..51fb0fe 100644 --- a/SetItem.tsx +++ b/SetItem.tsx @@ -3,7 +3,7 @@ import React, {useCallback, useContext, useState} from 'react'; import {GestureResponderEvent} from 'react-native'; import {List, Menu} from 'react-native-paper'; import {DatabaseContext} from './App'; -import {StackParams} from './HomePage'; +import {HomePageParams} from './HomePage'; import Set from './set'; export default function SetItem({ @@ -16,7 +16,7 @@ export default function SetItem({ const [showMenu, setShowMenu] = useState(false); const [anchor, setAnchor] = useState({x: 0, y: 0}); const db = useContext(DatabaseContext); - const navigation = useNavigation>(); + const navigation = useNavigation>(); const remove = useCallback(async () => { await db.executeSql(`DELETE FROM sets WHERE id = ?`, [item.id]); diff --git a/SetList.tsx b/SetList.tsx index 123de04..6b67cf3 100644 --- a/SetList.tsx +++ b/SetList.tsx @@ -7,7 +7,7 @@ import React, {useCallback, useContext, useEffect, useState} from 'react'; import {FlatList, StyleSheet, View} from 'react-native'; import {List, Searchbar} from 'react-native-paper'; import {DatabaseContext} from './App'; -import {StackParams} from './HomePage'; +import {HomePageParams} from './HomePage'; import MassiveFab from './MassiveFab'; import Set from './set'; import SetItem from './SetItem'; @@ -21,7 +21,7 @@ export default function SetList() { const [refreshing, setRefreshing] = useState(false); const [end, setEnd] = useState(false); const db = useContext(DatabaseContext); - const navigation = useNavigation>(); + const navigation = useNavigation>(); const selectSets = ` SELECT * from sets