Add progress to plans

This commit is contained in:
Brandon Presley 2022-07-07 12:45:45 +12:00
parent 67b22f9f51
commit ecb436f8a6
8 changed files with 96 additions and 47 deletions

View File

@ -86,7 +86,7 @@ export default function EditPlan({
<Portal>
<Dialog visible={show} onDismiss={() => setShow(false)}>
<Dialog.Title>{id ? `Edit "${days}"` : 'Add a plan'}</Dialog.Title>
<Dialog.Content style={{alignItems: 'flex-end'}}>
<Dialog.Content>
{days.split(',').map((day, index) => (
<DayMenu
index={index}

View File

@ -72,6 +72,7 @@ export default function EditSet({
value={name}
onChangeText={setName}
onSubmitEditing={() => repsRef.current?.focus()}
autoCorrect={false}
/>
<TextInput
style={styles.text}

View File

@ -1,3 +1,4 @@
import {useFocusEffect} from '@react-navigation/native';
import {NativeStackScreenProps} from '@react-navigation/native-stack';
import React, {useEffect, useState} from 'react';
import {FlatList, StyleSheet, View} from 'react-native';
@ -6,9 +7,7 @@ import {RootStackParamList} from './App';
import {getDb} from './db';
import Exercise from './exercise';
export default function Exercises({
navigation,
}: NativeStackScreenProps<RootStackParamList, 'Exercises'>) {
export default function Exercises() {
const [exercises, setExercises] = useState<Exercise[]>([]);
const [search, setSearch] = useState('');
const [refreshing, setRefresing] = useState(false);
@ -26,7 +25,10 @@ export default function Exercises({
setExercises(result.rows.raw());
};
useEffect(() => navigation.addListener('focus', refresh), [navigation]);
useFocusEffect(() => {
refresh();
});
useEffect(() => {
refresh();
}, [search]);

View File

@ -1,13 +1,7 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import {useNavigation} from '@react-navigation/native';
import {useFocusEffect} from '@react-navigation/native';
import React, {useEffect, useState} from 'react';
import {
FlatList,
NativeModules,
SafeAreaView,
StyleSheet,
View,
} from 'react-native';
import {FlatList, NativeModules, SafeAreaView, StyleSheet} from 'react-native';
import {AnimatedFAB, Searchbar} from 'react-native-paper';
import {getSets} from './db';
import EditSet from './EditSet';
@ -24,23 +18,26 @@ export default function Home() {
const [showEdit, setShowEdit] = useState(false);
const [search, setSearch] = useState('');
const [refreshing, setRefresing] = useState(false);
const navigation = useNavigation();
const refresh = async () => {
setRefresing(true);
const [result] = await getSets({search, limit, offset: 0}).finally(() =>
setRefresing(false),
);
const [result] = await getSets({search, limit, offset: 0});
if (!result) return setSets([]);
setSets(result.rows.raw());
setOffset(0);
};
const refreshLoader = async () => {
setRefresing(true);
refresh().finally(() => setRefresing(false));
};
useEffect(() => {
refresh();
}, [search]);
useEffect(() => navigation.addListener('focus', refresh), [navigation]);
useFocusEffect(() => {
refresh();
});
const renderItem = ({item}: {item: Set}) => (
<SetItem
@ -78,13 +75,12 @@ export default function Home() {
<SafeAreaView style={styles.container}>
<Searchbar placeholder="Search" value={search} onChangeText={setSearch} />
<FlatList
style={{height: '90%'}}
data={sets}
renderItem={renderItem}
keyExtractor={set => set.id.toString()}
onEndReached={next}
refreshing={refreshing}
onRefresh={refresh}
onRefresh={refreshLoader}
/>
<EditSet
clearId={() => setId(undefined)}
@ -113,6 +109,7 @@ const styles = StyleSheet.create({
fontSize: 18,
},
container: {
flexGrow: 1,
flex: 1,
padding: 10,
},

View File

@ -1,10 +1,13 @@
import {useFocusEffect} from '@react-navigation/native';
import {format} from 'date-fns';
import React, {useEffect, useState} from 'react';
import {FlatList, View} from 'react-native';
import {AnimatedFAB, Searchbar} from 'react-native-paper';
import {getPlans} from './db';
import {FlatList, StyleSheet, Text, View} from 'react-native';
import {AnimatedFAB, ProgressBar, Searchbar} from 'react-native-paper';
import {getPlans, getProgress} from './db';
import EditPlan from './EditPlan';
import {Plan} from './plan';
import PlanItem from './PlanItem';
import Progress from './progress';
export default function Plans() {
const [search, setSearch] = useState('');
@ -12,12 +15,31 @@ export default function Plans() {
const [refreshing, setRefresing] = useState(false);
const [id, setId] = useState<number>();
const [showEdit, setShowEdit] = useState(false);
const [progresses, setProgresses] = useState<Progress[]>([]);
const today = `%${format(new Date(new Date().toUTCString()), 'EEEE')}%`;
const now = `${format(new Date(new Date().toUTCString()), 'yyyy-MM-dd')}%`;
const refresh = async () => {
const [plansResult] = await getPlans({search});
setPlans(plansResult.rows.raw());
const [todaysResult] = await getPlans({search: today});
if (todaysResult.rows.length === 0) return;
const workouts: string[] = todaysResult.rows.item(0).workouts.split(',');
const newProgress: Progress[] = [];
for (const workout of workouts) {
const [workoutResult] = await getProgress({
created: now,
name: workout,
});
newProgress.push({name: workout, sets: workoutResult.rows.item(0).count});
}
setProgresses(newProgress);
};
useFocusEffect(() => {
refresh();
});
useEffect(() => {
refresh();
}, [search]);
@ -33,15 +55,24 @@ export default function Plans() {
);
return (
<View style={{padding: 10}}>
<View style={styles.container}>
<Searchbar value={search} onChangeText={setSearch} placeholder="Search" />
{progresses.map(progress => (
<React.Fragment key={progress.name}>
<Text style={styles.progress}>{progress.name}</Text>
<ProgressBar progress={progress.sets / 3} />
</React.Fragment>
))}
<FlatList
style={{height: '90%'}}
data={plans}
renderItem={renderItem}
keyExtractor={set => set.id.toString()}
refreshing={refreshing}
onRefresh={refresh}
onRefresh={() => {
setRefresing(true);
refresh().finally(() => setRefresing(false));
}}
/>
<EditPlan
@ -65,3 +96,13 @@ export default function Plans() {
</View>
);
}
const styles = StyleSheet.create({
container: {
flexGrow: 1,
padding: 10,
},
progress: {
marginTop: 10,
},
});

View File

@ -1,28 +1,29 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import {NativeStackScreenProps} from '@react-navigation/native-stack';
import {useFocusEffect, useNavigation} from '@react-navigation/native';
import React, {useEffect, useState} from 'react';
import {NativeModules, StyleSheet, Text, View} from 'react-native';
import {Button, Snackbar, Switch, TextInput} from 'react-native-paper';
import {RootStackParamList} from './App';
import {getDb} from './db';
import BatteryDialog from './BatteryDialog';
import {getDb} from './db';
export default function Settings({
navigation,
}: NativeStackScreenProps<RootStackParamList, 'Settings'>) {
export default function Settings() {
const [minutes, setMinutes] = useState<string>('');
const [seconds, setSeconds] = useState<string>('');
const [alarmEnabled, setAlarmEnabled] = useState<boolean>(true);
const [snackbar, setSnackbar] = useState('');
const [showBattery, setShowBattery] = useState(false);
const [ignoring, setIgnoring] = useState(false);
useEffect(() => {
(async () => {
setMinutes((await AsyncStorage.getItem('minutes')) || '3');
setSeconds((await AsyncStorage.getItem('seconds')) || '');
setAlarmEnabled((await AsyncStorage.getItem('alarmEnabled')) === 'true');
})();
}, [navigation]);
const refresh = async () => {
setMinutes((await AsyncStorage.getItem('minutes')) || '3');
setSeconds((await AsyncStorage.getItem('seconds')) || '');
setAlarmEnabled((await AsyncStorage.getItem('alarmEnabled')) === 'true');
NativeModules.AlarmModule.ignoringBatteryOptimizations(setIgnoring);
};
useFocusEffect(() => {
refresh();
});
useEffect(() => {
if (minutes) AsyncStorage.setItem('minutes', minutes);
@ -46,13 +47,8 @@ export default function Settings({
};
const changeAlarmEnabled = (enabled: boolean) => {
if (!enabled) return setAlarmEnabled(enabled);
NativeModules.AlarmModule.ignoringBatteryOptimizations(
(ignoring: boolean) => {
if (ignoring) return setAlarmEnabled(true);
setShowBattery(true);
},
);
setAlarmEnabled(enabled);
if (enabled && !ignoring) setShowBattery(true);
};
return (

8
db.ts
View File

@ -37,6 +37,14 @@ export const getPlans = ({search}: {search: string}) =>
db.executeSql(selectPlans, [`%${search}%`, `%${search}%`]),
);
const selectProgress = `
SELECT count(*) as count from sets
WHERE created LIKE ?
AND name = ?
`;
export const getProgress = ({created, name}: {created: string; name: string}) =>
getDb().then(db => db.executeSql(selectProgress, [`%${created}%`, name]));
const selectSets = `
SELECT * from sets
WHERE name LIKE ?

4
progress.ts Normal file
View File

@ -0,0 +1,4 @@
export default interface Progress {
name: string;
sets: number;
}