Add progress to plans
This commit is contained in:
parent
67b22f9f51
commit
ecb436f8a6
|
@ -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}
|
||||
|
|
|
@ -72,6 +72,7 @@ export default function EditSet({
|
|||
value={name}
|
||||
onChangeText={setName}
|
||||
onSubmitEditing={() => repsRef.current?.focus()}
|
||||
autoCorrect={false}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.text}
|
||||
|
|
|
@ -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]);
|
||||
|
|
29
Home.tsx
29
Home.tsx
|
@ -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,
|
||||
},
|
||||
|
|
53
Plans.tsx
53
Plans.tsx
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
|
36
Settings.tsx
36
Settings.tsx
|
@ -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
8
db.ts
|
@ -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
4
progress.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
export default interface Progress {
|
||||
name: string;
|
||||
sets: number;
|
||||
}
|
Loading…
Reference in New Issue
Block a user