diff --git a/.prettierrc.js b/.prettierrc.js index 11ff33d..a6271df 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -4,4 +4,5 @@ module.exports = { bracketSpacing: false, singleQuote: true, trailingComma: 'all', -} + semi: false, +}; diff --git a/App.tsx b/App.tsx index 086090e..42aa61f 100644 --- a/App.tsx +++ b/App.tsx @@ -2,22 +2,22 @@ import { DarkTheme as NavigationDarkTheme, DefaultTheme as NavigationDefaultTheme, NavigationContainer, -} from '@react-navigation/native'; -import {useEffect, useMemo, useState} from 'react'; -import {useColorScheme} from 'react-native'; +} from '@react-navigation/native' +import {useEffect, useMemo, useState} from 'react' +import {useColorScheme} from 'react-native' import { DarkTheme as PaperDarkTheme, DefaultTheme as PaperDefaultTheme, Provider as PaperProvider, -} from 'react-native-paper'; -import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; -import {Color} from './color'; -import {lightColors} from './colors'; -import {runMigrations, settingsRepo} from './db'; -import MassiveSnack from './MassiveSnack'; -import Routes from './Routes'; -import Settings from './settings'; -import {SettingsContext} from './use-settings'; +} from 'react-native-paper' +import MaterialIcon from 'react-native-vector-icons/MaterialIcons' +import {Color} from './color' +import {lightColors} from './colors' +import {runMigrations, settingsRepo} from './db' +import MassiveSnack from './MassiveSnack' +import Routes from './Routes' +import Settings from './settings' +import {SettingsContext} from './use-settings' export const CombinedDefaultTheme = { ...NavigationDefaultTheme, @@ -26,7 +26,7 @@ export const CombinedDefaultTheme = { ...NavigationDefaultTheme.colors, ...PaperDefaultTheme.colors, }, -}; +} export const CombinedDarkTheme = { ...NavigationDarkTheme, @@ -37,40 +37,40 @@ export const CombinedDarkTheme = { primary: lightColors[0].hex, background: '#0E0E0E', }, -}; +} const App = () => { - const isDark = useColorScheme() === 'dark'; - const [settings, setSettings] = useState(); + const isDark = useColorScheme() === 'dark' + const [settings, setSettings] = useState() const [color, setColor] = useState( isDark ? CombinedDarkTheme.colors.primary.toUpperCase() : CombinedDefaultTheme.colors.primary.toUpperCase(), - ); + ) useEffect(() => { runMigrations().then(async () => { - const gotSettings = await settingsRepo.findOne({where: {}}); - console.log(`${App.name}.runMigrations:`, {gotSettings}); - setSettings(gotSettings); - if (gotSettings.color) setColor(gotSettings.color); - }); - }, [setColor]); + const gotSettings = await settingsRepo.findOne({where: {}}) + console.log(`${App.name}.runMigrations:`, {gotSettings}) + setSettings(gotSettings) + if (gotSettings.color) setColor(gotSettings.color) + }) + }, [setColor]) const theme = useMemo(() => { const darkTheme = { ...CombinedDarkTheme, colors: {...CombinedDarkTheme.colors, primary: color}, - }; + } const lightTheme = { ...CombinedDefaultTheme, colors: {...CombinedDefaultTheme.colors, primary: color}, - }; - let value = isDark ? darkTheme : lightTheme; - if (settings?.theme === 'dark') value = darkTheme; - else if (settings?.theme === 'light') value = lightTheme; - return value; - }, [color, isDark, settings]); + } + let value = isDark ? darkTheme : lightTheme + if (settings?.theme === 'dark') value = darkTheme + else if (settings?.theme === 'light') value = lightTheme + return value + }, [color, isDark, settings]) return ( @@ -88,7 +88,7 @@ const App = () => { - ); -}; + ) +} -export default App; +export default App diff --git a/BestList.tsx b/BestList.tsx index 90f1212..3846d4d 100644 --- a/BestList.tsx +++ b/BestList.tsx @@ -2,22 +2,22 @@ import { NavigationProp, useFocusEffect, useNavigation, -} from '@react-navigation/native'; -import {useCallback, useState} from 'react'; -import {FlatList, Image} from 'react-native'; -import {List} from 'react-native-paper'; -import {BestPageParams} from './BestPage'; -import {setRepo} from './db'; -import DrawerHeader from './DrawerHeader'; -import GymSet from './gym-set'; -import Page from './Page'; -import {useSettings} from './use-settings'; +} from '@react-navigation/native' +import {useCallback, useState} from 'react' +import {FlatList, Image} from 'react-native' +import {List} from 'react-native-paper' +import {BestPageParams} from './BestPage' +import {setRepo} from './db' +import DrawerHeader from './DrawerHeader' +import GymSet from './gym-set' +import Page from './Page' +import {useSettings} from './use-settings' export default function BestList() { - const [bests, setBests] = useState(); - const [term, setTerm] = useState(''); - const navigation = useNavigation>(); - const {settings} = useSettings(); + const [bests, setBests] = useState() + const [term, setTerm] = useState('') + const navigation = useNavigation>() + const {settings} = useSettings() const refresh = useCallback(async (value: string) => { const weights = await setRepo @@ -27,9 +27,9 @@ export default function BestList() { .where('name LIKE :name', {name: `%${value}%`}) .andWhere('NOT hidden') .groupBy('name') - .getMany(); - console.log(`${BestList.name}.refresh:`, {length: weights.length}); - let newBest: GymSet[] = []; + .getMany() + console.log(`${BestList.name}.refresh:`, {length: weights.length}) + let newBest: GymSet[] = [] for (const set of weights) { const reps = await setRepo .createQueryBuilder() @@ -39,25 +39,25 @@ export default function BestList() { .andWhere('weight = :weight', {weight: set.weight}) .andWhere('NOT hidden') .groupBy('name') - .getMany(); - newBest.push(...reps); + .getMany() + newBest.push(...reps) } - setBests(newBest); - }, []); + setBests(newBest) + }, []) useFocusEffect( useCallback(() => { - refresh(term); + refresh(term) }, [refresh, term]), - ); + ) const search = useCallback( (value: string) => { - setTerm(value); - refresh(value); + setTerm(value) + refresh(value) }, [refresh], - ); + ) const renderItem = ({item}: {item: GymSet}) => ( - ); + ) return ( <> @@ -88,5 +88,5 @@ export default function BestList() { )} - ); + ) } diff --git a/BestPage.tsx b/BestPage.tsx index 3ae6d58..697b20f 100644 --- a/BestPage.tsx +++ b/BestPage.tsx @@ -1,15 +1,15 @@ -import {createStackNavigator} from '@react-navigation/stack'; -import BestList from './BestList'; -import GymSet from './gym-set'; -import ViewBest from './ViewBest'; +import {createStackNavigator} from '@react-navigation/stack' +import BestList from './BestList' +import GymSet from './gym-set' +import ViewBest from './ViewBest' -const Stack = createStackNavigator(); +const Stack = createStackNavigator() export type BestPageParams = { - BestList: {}; + BestList: {} ViewBest: { - best: GymSet; - }; -}; + best: GymSet + } +} export default function BestPage() { return ( @@ -18,5 +18,5 @@ export default function BestPage() { - ); + ) } diff --git a/Chart.tsx b/Chart.tsx index 0c1ba81..ae27db0 100644 --- a/Chart.tsx +++ b/Chart.tsx @@ -1,11 +1,11 @@ -import * as shape from 'd3-shape'; -import {View} from 'react-native'; -import {Grid, LineChart, XAxis, YAxis} from 'react-native-svg-charts'; -import {CombinedDarkTheme, CombinedDefaultTheme} from './App'; -import {useColor} from './color'; -import {MARGIN, PADDING} from './constants'; -import GymSet from './gym-set'; -import useDark from './use-dark'; +import * as shape from 'd3-shape' +import {View} from 'react-native' +import {Grid, LineChart, XAxis, YAxis} from 'react-native-svg-charts' +import {CombinedDarkTheme, CombinedDefaultTheme} from './App' +import {useColor} from './color' +import {MARGIN, PADDING} from './constants' +import GymSet from './gym-set' +import useDark from './use-dark' export default function Chart({ yData, @@ -13,21 +13,21 @@ export default function Chart({ xData, yFormat, }: { - yData: number[]; - xData: GymSet[]; - xFormat: (value: any, index: number) => string; - yFormat: (value: any) => string; + yData: number[] + xData: GymSet[] + xFormat: (value: any, index: number) => string + yFormat: (value: any) => string }) { - const {color} = useColor(); - const dark = useDark(); + const {color} = useColor() + const dark = useDark() const axesSvg = { fontSize: 10, fill: dark ? CombinedDarkTheme.colors.text : CombinedDefaultTheme.colors.text, - }; - const verticalContentInset = {top: 10, bottom: 10}; - const xAxisHeight = 30; + } + const verticalContentInset = {top: 10, bottom: 10} + const xAxisHeight = 30 return ( <> @@ -60,5 +60,5 @@ export default function Chart({ - ); + ) } diff --git a/ConfirmDialog.tsx b/ConfirmDialog.tsx index e316950..7b68b97 100644 --- a/ConfirmDialog.tsx +++ b/ConfirmDialog.tsx @@ -1,4 +1,4 @@ -import {Button, Dialog, Portal, Text} from 'react-native-paper'; +import {Button, Dialog, Portal, Text} from 'react-native-paper' export default function ConfirmDialog({ title, @@ -7,11 +7,11 @@ export default function ConfirmDialog({ show, setShow, }: { - title: string; - children: JSX.Element | JSX.Element[] | string; - onOk: () => void; - show: boolean; - setShow: (show: boolean) => void; + title: string + children: JSX.Element | JSX.Element[] | string + onOk: () => void + show: boolean + setShow: (show: boolean) => void }) { return ( @@ -26,5 +26,5 @@ export default function ConfirmDialog({ - ); + ) } diff --git a/DrawerHeader.tsx b/DrawerHeader.tsx index c9eea2f..3f41d3a 100644 --- a/DrawerHeader.tsx +++ b/DrawerHeader.tsx @@ -1,13 +1,13 @@ -import {DrawerNavigationProp} from '@react-navigation/drawer'; -import {useNavigation} from '@react-navigation/native'; -import {Appbar, IconButton} from 'react-native-paper'; -import {DrawerParamList} from './drawer-param-list'; -import DrawerMenu from './DrawerMenu'; -import useDark from './use-dark'; +import {DrawerNavigationProp} from '@react-navigation/drawer' +import {useNavigation} from '@react-navigation/native' +import {Appbar, IconButton} from 'react-native-paper' +import {DrawerParamList} from './drawer-param-list' +import DrawerMenu from './DrawerMenu' +import useDark from './use-dark' export default function DrawerHeader({name}: {name: keyof DrawerParamList}) { - const navigation = useNavigation>(); - const dark = useDark(); + const navigation = useNavigation>() + const dark = useDark() return ( @@ -19,5 +19,5 @@ export default function DrawerHeader({name}: {name: keyof DrawerParamList}) { - ); + ) } diff --git a/DrawerMenu.tsx b/DrawerMenu.tsx index c02d2fb..8a7ca82 100644 --- a/DrawerMenu.tsx +++ b/DrawerMenu.tsx @@ -1,72 +1,71 @@ -import {NavigationProp, useNavigation} from '@react-navigation/native'; -import {useCallback, useState} from 'react'; -import DocumentPicker from 'react-native-document-picker'; -import {FileSystem} from 'react-native-file-access'; -import {Divider, IconButton, Menu} from 'react-native-paper'; -import ConfirmDialog from './ConfirmDialog'; -import {AppDataSource} from './data-source'; -import {planRepo} from './db'; -import {DrawerParamList} from './drawer-param-list'; -import GymSet from './gym-set'; -import {useSnackbar} from './MassiveSnack'; -import {Plan} from './plan'; -import useDark from './use-dark'; -import {write} from './write'; +import {NavigationProp, useNavigation} from '@react-navigation/native' +import {useCallback, useState} from 'react' +import DocumentPicker from 'react-native-document-picker' +import {FileSystem} from 'react-native-file-access' +import {Divider, IconButton, Menu} from 'react-native-paper' +import ConfirmDialog from './ConfirmDialog' +import {AppDataSource} from './data-source' +import {planRepo} from './db' +import {DrawerParamList} from './drawer-param-list' +import GymSet from './gym-set' +import {useSnackbar} from './MassiveSnack' +import {Plan} from './plan' +import useDark from './use-dark' +import {write} from './write' -const setFields = - 'id,name,reps,weight,created,unit,hidden,sets,minutes,seconds'; -const planFields = 'id,days,workouts'; -const setRepo = AppDataSource.manager.getRepository(GymSet); +const setFields = 'id,name,reps,weight,created,unit,hidden,sets,minutes,seconds' +const planFields = 'id,days,workouts' +const setRepo = AppDataSource.manager.getRepository(GymSet) export default function DrawerMenu({name}: {name: keyof DrawerParamList}) { - const [showMenu, setShowMenu] = useState(false); - const [showRemove, setShowRemove] = useState(false); - const {toast} = useSnackbar(); - const {reset} = useNavigation>(); - const dark = useDark(); + const [showMenu, setShowMenu] = useState(false) + const [showRemove, setShowRemove] = useState(false) + const {toast} = useSnackbar() + const {reset} = useNavigation>() + const dark = useDark() const exportSets = useCallback(async () => { - const sets = await setRepo.find({}); + const sets = await setRepo.find({}) const data = [setFields] .concat( sets.map(set => setFields .split(',') .map(fieldString => { - const field = fieldString as keyof GymSet; - if (field === 'unit') return set[field] || 'kg'; - return set[field]; + const field = fieldString as keyof GymSet + if (field === 'unit') return set[field] || 'kg' + return set[field] }) .join(','), ), ) - .join('\n'); - console.log(`${DrawerMenu.name}.exportSets`, {length: sets.length}); - await write('sets.csv', data); - }, []); + .join('\n') + console.log(`${DrawerMenu.name}.exportSets`, {length: sets.length}) + await write('sets.csv', data) + }, []) const exportPlans = useCallback(async () => { - const plans = await planRepo.find({}); + const plans = await planRepo.find({}) const data = [planFields] .concat(plans.map(set => `"${set.id}","${set.days}","${set.workouts}"`)) - .join('\n'); - console.log(`${DrawerMenu.name}.exportPlans`, {length: plans.length}); - await write('plans.csv', data); - }, []); + .join('\n') + console.log(`${DrawerMenu.name}.exportPlans`, {length: plans.length}) + await write('plans.csv', data) + }, []) const download = useCallback(async () => { - setShowMenu(false); - if (name === 'Home') exportSets(); - else if (name === 'Plans') exportPlans(); - }, [name, exportSets, exportPlans]); + setShowMenu(false) + if (name === 'Home') exportSets() + else if (name === 'Plans') exportPlans() + }, [name, exportSets, exportPlans]) const uploadSets = useCallback(async () => { - const result = await DocumentPicker.pickSingle(); - const file = await FileSystem.readFile(result.uri); - console.log(`${DrawerMenu.name}.uploadSets:`, file.length); - const lines = file.split('\n'); - console.log(lines[0]); - if (!setFields.includes(lines[0])) return toast('Invalid csv.', 3000); + const result = await DocumentPicker.pickSingle() + const file = await FileSystem.readFile(result.uri) + console.log(`${DrawerMenu.name}.uploadSets:`, file.length) + const lines = file.split('\n') + console.log(lines[0]) + if (!setFields.includes(lines[0])) return toast('Invalid csv.', 3000) const values = lines .slice(1) .filter(line => line) @@ -82,7 +81,7 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) { sets, minutes, seconds, - ] = line.split(','); + ] = line.split(',') const set: GymSet = { name: setName, reps: +reps, @@ -93,21 +92,21 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) { sets: +sets, minutes: +minutes, seconds: +seconds, - }; - return set; - }); - console.log(`${DrawerMenu.name}.uploadSets:`, {values}); - await setRepo.insert(values); - toast('Data imported.', 3000); - reset({index: 0, routes: [{name}]}); - }, [reset, name, toast]); + } + return set + }) + console.log(`${DrawerMenu.name}.uploadSets:`, {values}) + await setRepo.insert(values) + toast('Data imported.', 3000) + reset({index: 0, routes: [{name}]}) + }, [reset, name, toast]) const uploadPlans = useCallback(async () => { - const result = await DocumentPicker.pickSingle(); - const file = await FileSystem.readFile(result.uri); - console.log(`${DrawerMenu.name}.uploadPlans:`, file.length); - const lines = file.split('\n'); - if (lines[0] != planFields) return toast('Invalid csv.', 3000); + const result = await DocumentPicker.pickSingle() + const file = await FileSystem.readFile(result.uri) + console.log(`${DrawerMenu.name}.uploadPlans:`, file.length) + const lines = file.split('\n') + if (lines[0] != planFields) return toast('Invalid csv.', 3000) const values = file .split('\n') .slice(1) @@ -115,32 +114,32 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) { .map(set => { const [, days, workouts] = set .split('","') - .map(cell => cell.replace(/"/g, '')); + .map(cell => cell.replace(/"/g, '')) const plan: Plan = { days, workouts, - }; - return plan; - }); - await planRepo.insert(values); - toast('Data imported.', 3000); - }, [toast]); + } + return plan + }) + await planRepo.insert(values) + toast('Data imported.', 3000) + }, [toast]) const upload = useCallback(async () => { - setShowMenu(false); - if (name === 'Home') await uploadSets(); - else if (name === 'Plans') await uploadPlans(); - reset({index: 0, routes: [{name}]}); - }, [name, uploadPlans, uploadSets, reset]); + setShowMenu(false) + if (name === 'Home') await uploadSets() + else if (name === 'Plans') await uploadPlans() + reset({index: 0, routes: [{name}]}) + }, [name, uploadPlans, uploadSets, reset]) const remove = useCallback(async () => { - setShowMenu(false); - setShowRemove(false); - if (name === 'Home') await setRepo.delete({}); - else if (name === 'Plans') await planRepo.delete({}); - toast('All data has been deleted.', 4000); - reset({index: 0, routes: [{name}]}); - }, [reset, name, toast]); + setShowMenu(false) + setShowRemove(false) + if (name === 'Home') await setRepo.delete({}) + else if (name === 'Plans') await planRepo.delete({}) + toast('All data has been deleted.', 4000) + reset({index: 0, routes: [{name}]}) + }, [reset, name, toast]) if (name === 'Home' || name === 'Plans') return ( @@ -170,7 +169,7 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) { This irreversibly deletes all data from the app. Are you sure? - ); + ) - return null; + return null } diff --git a/EditPlan.tsx b/EditPlan.tsx index a12f22e..c86a374 100644 --- a/EditPlan.tsx +++ b/EditPlan.tsx @@ -3,29 +3,29 @@ import { RouteProp, useNavigation, useRoute, -} from '@react-navigation/native'; -import {useCallback, useEffect, useState} from 'react'; -import {ScrollView, StyleSheet, View} from 'react-native'; -import {Button, Text} from 'react-native-paper'; -import {MARGIN, PADDING} from './constants'; -import {planRepo, setRepo} from './db'; -import {DrawerParamList} from './drawer-param-list'; -import {PlanPageParams} from './plan-page-params'; -import StackHeader from './StackHeader'; -import Switch from './Switch'; -import {DAYS} from './time'; +} from '@react-navigation/native' +import {useCallback, useEffect, useState} from 'react' +import {ScrollView, StyleSheet, View} from 'react-native' +import {Button, Text} from 'react-native-paper' +import {MARGIN, PADDING} from './constants' +import {planRepo, setRepo} from './db' +import {DrawerParamList} from './drawer-param-list' +import {PlanPageParams} from './plan-page-params' +import StackHeader from './StackHeader' +import Switch from './Switch' +import {DAYS} from './time' export default function EditPlan() { - const {params} = useRoute>(); - const {plan} = params; + const {params} = useRoute>() + const {plan} = params const [days, setDays] = useState( plan.days ? plan.days.split(',') : [], - ); + ) const [workouts, setWorkouts] = useState( plan.workouts ? plan.workouts.split(',') : [], - ); - const [names, setNames] = useState([]); - const navigation = useNavigation>(); + ) + const [names, setNames] = useState([]) + const navigation = useNavigation>() useEffect(() => { setRepo @@ -34,41 +34,41 @@ export default function EditPlan() { .distinct(true) .getRawMany() .then(values => { - console.log(EditPlan.name, {values}); - setNames(values.map(value => value.name)); - }); - }, []); + console.log(EditPlan.name, {values}) + setNames(values.map(value => value.name)) + }) + }, []) const save = useCallback(async () => { - console.log(`${EditPlan.name}.save`, {days, workouts, plan}); - if (!days || !workouts) return; - const newWorkouts = workouts.filter(workout => workout).join(','); - const newDays = days.filter(day => day).join(','); - await planRepo.save({days: newDays, workouts: newWorkouts, id: plan.id}); - navigation.goBack(); - }, [days, workouts, plan, navigation]); + console.log(`${EditPlan.name}.save`, {days, workouts, plan}) + if (!days || !workouts) return + const newWorkouts = workouts.filter(workout => workout).join(',') + const newDays = days.filter(day => day).join(',') + await planRepo.save({days: newDays, workouts: newWorkouts, id: plan.id}) + navigation.goBack() + }, [days, workouts, plan, navigation]) const toggleWorkout = useCallback( (on: boolean, name: string) => { if (on) { - setWorkouts([...workouts, name]); + setWorkouts([...workouts, name]) } else { - setWorkouts(workouts.filter(workout => workout !== name)); + setWorkouts(workouts.filter(workout => workout !== name)) } }, [setWorkouts, workouts], - ); + ) const toggleDay = useCallback( (on: boolean, day: string) => { if (on) { - setDays([...days, day]); + setDays([...days, day]) } else { - setDays(days.filter(d => d !== day)); + setDays(days.filter(d => d !== day)) } }, [setDays, days], - ); + ) return ( <> @@ -107,11 +107,11 @@ export default function EditPlan() { disabled={workouts.length === 0 && days.length === 0} mode="contained" onPress={() => { - navigation.goBack(); + navigation.goBack() navigation.navigate('Workouts', { screen: 'EditWorkout', params: {value: {name: ''}}, - }); + }) }}> Add workout @@ -127,7 +127,7 @@ export default function EditPlan() { )} - ); + ) } const styles = StyleSheet.create({ @@ -135,4 +135,4 @@ const styles = StyleSheet.create({ fontSize: 20, marginBottom: MARGIN, }, -}); +}) diff --git a/EditSet.tsx b/EditSet.tsx index ecca964..13e7000 100644 --- a/EditSet.tsx +++ b/EditSet.tsx @@ -1,64 +1,64 @@ -import {RouteProp, useNavigation, useRoute} from '@react-navigation/native'; -import {useCallback} from 'react'; -import {NativeModules, View} from 'react-native'; -import {PADDING} from './constants'; -import {getNow, setRepo} from './db'; -import GymSet from './gym-set'; -import {HomePageParams} from './home-page-params'; -import {useSnackbar} from './MassiveSnack'; -import SetForm from './SetForm'; -import StackHeader from './StackHeader'; -import {useSettings} from './use-settings'; +import {RouteProp, useNavigation, useRoute} from '@react-navigation/native' +import {useCallback} from 'react' +import {NativeModules, View} from 'react-native' +import {PADDING} from './constants' +import {getNow, setRepo} from './db' +import GymSet from './gym-set' +import {HomePageParams} from './home-page-params' +import {useSnackbar} from './MassiveSnack' +import SetForm from './SetForm' +import StackHeader from './StackHeader' +import {useSettings} from './use-settings' export default function EditSet() { - const {params} = useRoute>(); - const {set} = params; - const navigation = useNavigation(); - const {toast} = useSnackbar(); - const {settings} = useSettings(); + const {params} = useRoute>() + const {set} = params + const navigation = useNavigation() + const {toast} = useSnackbar() + const {settings} = useSettings() const startTimer = useCallback( async (name: string) => { - if (!settings.alarm) return; - const {minutes, seconds} = await setRepo.findOne({where: {name}}); - const milliseconds = (minutes ?? 3) * 60 * 1000 + (seconds ?? 0) * 1000; + if (!settings.alarm) return + const {minutes, seconds} = await setRepo.findOne({where: {name}}) + const milliseconds = (minutes ?? 3) * 60 * 1000 + (seconds ?? 0) * 1000 NativeModules.AlarmModule.timer( milliseconds, !!settings.vibrate, settings.sound, !!settings.noSound, - ); + ) }, [settings], - ); + ) const add = useCallback( async (value: GymSet) => { - startTimer(value.name); - const [{now}] = await getNow(); - value.created = now; - value.hidden = false; - console.log(`${EditSet.name}.add`, {set: value}); - const result = await setRepo.save(value); - console.log({result}); - if (!settings.notify) return; + startTimer(value.name) + const [{now}] = await getNow() + value.created = now + value.hidden = false + console.log(`${EditSet.name}.add`, {set: value}) + const result = await setRepo.save(value) + console.log({result}) + if (!settings.notify) return if ( value.weight > set.weight || (value.reps > set.reps && value.weight === set.weight) ) - toast("Great work King! That's a new record.", 3000); + toast("Great work King! That's a new record.", 3000) }, [startTimer, set, toast, settings], - ); + ) const save = useCallback( async (value: GymSet) => { - if (typeof set.id === 'number') await setRepo.save(value); - else await add(value); - navigation.goBack(); + if (typeof set.id === 'number') await setRepo.save(value) + else await add(value) + navigation.goBack() }, [add, set.id, navigation], - ); + ) return ( <> @@ -67,5 +67,5 @@ export default function EditSet() { - ); + ) } diff --git a/EditWorkout.tsx b/EditWorkout.tsx index 206f8d0..46870b0 100644 --- a/EditWorkout.tsx +++ b/EditWorkout.tsx @@ -1,39 +1,39 @@ -import {RouteProp, useNavigation, useRoute} from '@react-navigation/native'; -import {useCallback, useRef, useState} from 'react'; -import {ScrollView, TextInput, View} from 'react-native'; -import DocumentPicker from 'react-native-document-picker'; -import {Button, Card, TouchableRipple} from 'react-native-paper'; -import {Like} from 'typeorm'; -import ConfirmDialog from './ConfirmDialog'; -import {MARGIN, PADDING} from './constants'; -import {getNow, planRepo, setRepo} from './db'; -import MassiveInput from './MassiveInput'; -import {useSnackbar} from './MassiveSnack'; -import StackHeader from './StackHeader'; -import {useSettings} from './use-settings'; -import {WorkoutsPageParams} from './WorkoutsPage'; +import {RouteProp, useNavigation, useRoute} from '@react-navigation/native' +import {useCallback, useRef, useState} from 'react' +import {ScrollView, TextInput, View} from 'react-native' +import DocumentPicker from 'react-native-document-picker' +import {Button, Card, TouchableRipple} from 'react-native-paper' +import {Like} from 'typeorm' +import ConfirmDialog from './ConfirmDialog' +import {MARGIN, PADDING} from './constants' +import {getNow, planRepo, setRepo} from './db' +import MassiveInput from './MassiveInput' +import {useSnackbar} from './MassiveSnack' +import StackHeader from './StackHeader' +import {useSettings} from './use-settings' +import {WorkoutsPageParams} from './WorkoutsPage' export default function EditWorkout() { - const {params} = useRoute>(); - const [removeImage, setRemoveImage] = useState(false); - const [showRemove, setShowRemove] = useState(false); - const [name, setName] = useState(params.value.name); - const [steps, setSteps] = useState(params.value.steps); - const [uri, setUri] = useState(params.value.image); + const {params} = useRoute>() + const [removeImage, setRemoveImage] = useState(false) + const [showRemove, setShowRemove] = useState(false) + const [name, setName] = useState(params.value.name) + const [steps, setSteps] = useState(params.value.steps) + const [uri, setUri] = useState(params.value.image) const [minutes, setMinutes] = useState( params.value.minutes?.toString() ?? '3', - ); + ) const [seconds, setSeconds] = useState( params.value.seconds?.toString() ?? '30', - ); - const [sets, setSets] = useState(params.value.sets?.toString() ?? '3'); - const {toast} = useSnackbar(); - const navigation = useNavigation(); - const setsRef = useRef(null); - const stepsRef = useRef(null); - const minutesRef = useRef(null); - const secondsRef = useRef(null); - const {settings} = useSettings(); + ) + const [sets, setSets] = useState(params.value.sets?.toString() ?? '3') + const {toast} = useSnackbar() + const navigation = useNavigation() + const setsRef = useRef(null) + const stepsRef = useRef(null) + const minutesRef = useRef(null) + const secondsRef = useRef(null) + const {settings} = useSettings() const update = async () => { await setRepo.update( @@ -46,18 +46,18 @@ export default function EditWorkout() { steps, image: removeImage ? '' : uri, }, - ); + ) await planRepo.query( `UPDATE plans SET workouts = REPLACE(workouts, $1, $2) WHERE workouts LIKE $3`, [params.value.name, name, `%${params.value.name}%`], - ); - navigation.goBack(); - }; + ) + navigation.goBack() + } const add = async () => { - const [{now}] = await getNow(); + const [{now}] = await getNow() await setRepo.save({ name, reps: 0, @@ -69,45 +69,45 @@ export default function EditWorkout() { sets: sets ? +sets : 3, steps, created: now, - }); - navigation.goBack(); - }; + }) + navigation.goBack() + } const save = async () => { - if (params.value.name) return update(); - return add(); - }; + if (params.value.name) return update() + return add() + } const changeImage = useCallback(async () => { const {fileCopyUri} = await DocumentPicker.pickSingle({ type: 'image/*', copyTo: 'documentDirectory', - }); - if (fileCopyUri) setUri(fileCopyUri); - }, []); + }) + if (fileCopyUri) setUri(fileCopyUri) + }, []) const handleRemove = useCallback(async () => { - setUri(''); - setRemoveImage(true); - setShowRemove(false); - }, []); + setUri('') + setRemoveImage(true) + setShowRemove(false) + }, []) const handleName = (value: string) => { - setName(value.replace(/,|'/g, '')); + setName(value.replace(/,|'/g, '')) if (value.match(/,|'/)) - toast('Commas and single quotes would break CSV exports', 6000); - }; + toast('Commas and single quotes would break CSV exports', 6000) + } const handleSteps = (value: string) => { - setSteps(value.replace(/,|'/g, '')); + setSteps(value.replace(/,|'/g, '')) if (value.match(/,|'/)) - toast('Commas and single quotes would break CSV exports', 6000); - }; + toast('Commas and single quotes would break CSV exports', 6000) + } const submitName = () => { - if (settings.steps) stepsRef.current?.focus(); - else setsRef.current?.focus(); - }; + if (settings.steps) stepsRef.current?.focus() + else setsRef.current?.focus() + } return ( <> @@ -191,5 +191,5 @@ export default function EditWorkout() { - ); + ) } diff --git a/HomePage.tsx b/HomePage.tsx index 03d9d66..891eaac 100644 --- a/HomePage.tsx +++ b/HomePage.tsx @@ -1,9 +1,9 @@ -import {createStackNavigator} from '@react-navigation/stack'; -import EditSet from './EditSet'; -import {HomePageParams} from './home-page-params'; -import SetList from './SetList'; +import {createStackNavigator} from '@react-navigation/stack' +import EditSet from './EditSet' +import {HomePageParams} from './home-page-params' +import SetList from './SetList' -const Stack = createStackNavigator(); +const Stack = createStackNavigator() export default function HomePage() { return ( @@ -12,5 +12,5 @@ export default function HomePage() { - ); + ) } diff --git a/MassiveFab.tsx b/MassiveFab.tsx index bf60392..0991091 100644 --- a/MassiveFab.tsx +++ b/MassiveFab.tsx @@ -1,13 +1,13 @@ -import {ComponentProps} from 'react'; -import {FAB} from 'react-native-paper'; -import {useColor} from './color'; -import {lightColors} from './colors'; +import {ComponentProps} from 'react' +import {FAB} from 'react-native-paper' +import {useColor} from './color' +import {lightColors} from './colors' export default function MassiveFab(props: Partial>) { - const {color} = useColor(); + const {color} = useColor() const fabColor = lightColors.map(lightColor => lightColor.hex).includes(color) ? 'black' - : undefined; + : undefined return ( >) { }} {...props} /> - ); + ) } diff --git a/MassiveInput.tsx b/MassiveInput.tsx index 2c81648..8b51717 100644 --- a/MassiveInput.tsx +++ b/MassiveInput.tsx @@ -1,15 +1,15 @@ -import {ComponentProps, Ref} from 'react'; -import {TextInput} from 'react-native-paper'; -import {CombinedDefaultTheme} from './App'; -import {MARGIN} from './constants'; -import useDark from './use-dark'; +import {ComponentProps, Ref} from 'react' +import {TextInput} from 'react-native-paper' +import {CombinedDefaultTheme} from './App' +import {MARGIN} from './constants' +import useDark from './use-dark' export default function MassiveInput( props: Partial> & { - innerRef?: Ref; + innerRef?: Ref }, ) { - const dark = useDark(); + const dark = useDark() return ( - ); + ) } diff --git a/MassiveSnack.tsx b/MassiveSnack.tsx index 2f2313d..3613189 100644 --- a/MassiveSnack.tsx +++ b/MassiveSnack.tsx @@ -1,31 +1,31 @@ -import {createContext, useContext, useState} from 'react'; -import {Snackbar} from 'react-native-paper'; -import {CombinedDarkTheme, CombinedDefaultTheme} from './App'; -import useDark from './use-dark'; +import {createContext, useContext, useState} from 'react' +import {Snackbar} from 'react-native-paper' +import {CombinedDarkTheme, CombinedDefaultTheme} from './App' +import useDark from './use-dark' export const SnackbarContext = createContext<{ - toast: (value: string, timeout: number) => void; -}>({toast: () => null}); + toast: (value: string, timeout: number) => void +}>({toast: () => null}) export const useSnackbar = () => { - return useContext(SnackbarContext); -}; + return useContext(SnackbarContext) +} export default function MassiveSnack({ children, }: { - children?: JSX.Element[] | JSX.Element; + children?: JSX.Element[] | JSX.Element }) { - const [snackbar, setSnackbar] = useState(''); - const [timeoutId, setTimeoutId] = useState(0); - const dark = useDark(); + const [snackbar, setSnackbar] = useState('') + const [timeoutId, setTimeoutId] = useState(0) + const dark = useDark() const toast = (value: string, timeout: number) => { - setSnackbar(value); - clearTimeout(timeoutId); - const id = setTimeout(() => setSnackbar(''), timeout); - setTimeoutId(id); - }; + setSnackbar(value) + clearTimeout(timeoutId) + const id = setTimeout(() => setSnackbar(''), timeout) + setTimeoutId(id) + } return ( <> @@ -45,5 +45,5 @@ export default function MassiveSnack({ {snackbar} - ); + ) } diff --git a/Page.tsx b/Page.tsx index aae1404..eb65413 100644 --- a/Page.tsx +++ b/Page.tsx @@ -1,7 +1,7 @@ -import {StyleSheet, View} from 'react-native'; -import {Searchbar} from 'react-native-paper'; -import {PADDING} from './constants'; -import MassiveFab from './MassiveFab'; +import {StyleSheet, View} from 'react-native' +import {Searchbar} from 'react-native-paper' +import {PADDING} from './constants' +import MassiveFab from './MassiveFab' export default function Page({ onAdd, @@ -9,10 +9,10 @@ export default function Page({ term, search, }: { - children: JSX.Element | JSX.Element[]; - onAdd?: () => void; - term: string; - search: (value: string) => void; + children: JSX.Element | JSX.Element[] + onAdd?: () => void + term: string + search: (value: string) => void }) { return ( @@ -26,7 +26,7 @@ export default function Page({ {children} {onAdd && } - ); + ) } const styles = StyleSheet.create({ @@ -34,4 +34,4 @@ const styles = StyleSheet.create({ flexGrow: 1, padding: PADDING, }, -}); +}) diff --git a/PlanItem.tsx b/PlanItem.tsx index 6496e52..a95b68d 100644 --- a/PlanItem.tsx +++ b/PlanItem.tsx @@ -2,60 +2,60 @@ import { NavigationProp, useFocusEffect, useNavigation, -} from '@react-navigation/native'; -import {useCallback, useMemo, useState} from 'react'; -import {GestureResponderEvent, Text} from 'react-native'; -import {Divider, List, Menu} from 'react-native-paper'; -import {getBestSet} from './best.service'; -import {planRepo} from './db'; -import {Plan} from './plan'; -import {PlanPageParams} from './plan-page-params'; -import {DAYS} from './time'; +} from '@react-navigation/native' +import {useCallback, useMemo, useState} from 'react' +import {GestureResponderEvent, Text} from 'react-native' +import {Divider, List, Menu} from 'react-native-paper' +import {getBestSet} from './best.service' +import {planRepo} from './db' +import {Plan} from './plan' +import {PlanPageParams} from './plan-page-params' +import {DAYS} from './time' export default function PlanItem({ item, onRemove, }: { - item: Plan; - onRemove: () => void; + item: Plan + onRemove: () => void }) { - const [show, setShow] = useState(false); - const [anchor, setAnchor] = useState({x: 0, y: 0}); - const [today, setToday] = useState(); - const days = useMemo(() => item.days.split(','), [item.days]); - const navigation = useNavigation>(); + const [show, setShow] = useState(false) + const [anchor, setAnchor] = useState({x: 0, y: 0}) + const [today, setToday] = useState() + const days = useMemo(() => item.days.split(','), [item.days]) + const navigation = useNavigation>() useFocusEffect( useCallback(() => { - const newToday = DAYS[new Date().getDay()]; - setToday(newToday); + const newToday = DAYS[new Date().getDay()] + setToday(newToday) }, []), - ); + ) const remove = useCallback(async () => { - if (typeof item.id === 'number') await planRepo.delete(item.id); - setShow(false); - onRemove(); - }, [setShow, item.id, onRemove]); + if (typeof item.id === 'number') await planRepo.delete(item.id) + setShow(false) + onRemove() + }, [setShow, item.id, onRemove]) const start = useCallback(async () => { - console.log(`${PlanItem.name}.start:`, {item}); - setShow(false); - navigation.navigate('StartPlan', {plan: item}); - }, [item, navigation]); + console.log(`${PlanItem.name}.start:`, {item}) + setShow(false) + navigation.navigate('StartPlan', {plan: item}) + }, [item, navigation]) const longPress = useCallback( (e: GestureResponderEvent) => { - setAnchor({x: e.nativeEvent.pageX, y: e.nativeEvent.pageY}); - setShow(true); + setAnchor({x: e.nativeEvent.pageX, y: e.nativeEvent.pageY}) + setShow(true) }, [setAnchor, setShow], - ); + ) const edit = useCallback(() => { - setShow(false); - navigation.navigate('EditPlan', {plan: item}); - }, [navigation, item]); + setShow(false) + navigation.navigate('EditPlan', {plan: item}) + }, [navigation, item]) const title = useMemo( () => @@ -72,12 +72,12 @@ export default function PlanItem({ )), [days, today], - ); + ) const description = useMemo( () => item.workouts.replace(/,/g, ', '), [item.workouts], - ); + ) return ( <> @@ -95,5 +95,5 @@ export default function PlanItem({ )} /> - ); + ) } diff --git a/PlanList.tsx b/PlanList.tsx index 0153169..b20fd38 100644 --- a/PlanList.tsx +++ b/PlanList.tsx @@ -2,54 +2,54 @@ import { NavigationProp, useFocusEffect, useNavigation, -} from '@react-navigation/native'; -import {useCallback, useState} from 'react'; -import {FlatList} from 'react-native'; -import {List} from 'react-native-paper'; -import {Like} from 'typeorm'; -import {planRepo} from './db'; -import DrawerHeader from './DrawerHeader'; -import Page from './Page'; -import {Plan} from './plan'; -import {PlanPageParams} from './plan-page-params'; -import PlanItem from './PlanItem'; +} from '@react-navigation/native' +import {useCallback, useState} from 'react' +import {FlatList} from 'react-native' +import {List} from 'react-native-paper' +import {Like} from 'typeorm' +import {planRepo} from './db' +import DrawerHeader from './DrawerHeader' +import Page from './Page' +import {Plan} from './plan' +import {PlanPageParams} from './plan-page-params' +import PlanItem from './PlanItem' export default function PlanList() { - const [term, setTerm] = useState(''); - const [plans, setPlans] = useState(); - const navigation = useNavigation>(); + const [term, setTerm] = useState('') + const [plans, setPlans] = useState() + const navigation = useNavigation>() const refresh = useCallback(async (value: string) => { planRepo .find({ where: [{days: Like(`%${value}%`)}, {workouts: Like(`%${value}%`)}], }) - .then(setPlans); - }, []); + .then(setPlans) + }, []) useFocusEffect( useCallback(() => { - refresh(term); + refresh(term) }, [refresh, term]), - ); + ) const search = useCallback( (value: string) => { - setTerm(value); - refresh(value); + setTerm(value) + refresh(value) }, [refresh], - ); + ) const renderItem = useCallback( ({item}: {item: Plan}) => ( refresh(term)} /> ), [refresh, term], - ); + ) const onAdd = () => - navigation.navigate('EditPlan', {plan: {days: '', workouts: ''}}); + navigation.navigate('EditPlan', {plan: {days: '', workouts: ''}}) return ( <> @@ -70,5 +70,5 @@ export default function PlanList() { )} - ); + ) } diff --git a/PlanPage.tsx b/PlanPage.tsx index 980ca2a..0507684 100644 --- a/PlanPage.tsx +++ b/PlanPage.tsx @@ -1,10 +1,10 @@ -import {createStackNavigator} from '@react-navigation/stack'; -import EditPlan from './EditPlan'; -import {PlanPageParams} from './plan-page-params'; -import PlanList from './PlanList'; -import StartPlan from './StartPlan'; +import {createStackNavigator} from '@react-navigation/stack' +import EditPlan from './EditPlan' +import {PlanPageParams} from './plan-page-params' +import PlanList from './PlanList' +import StartPlan from './StartPlan' -const Stack = createStackNavigator(); +const Stack = createStackNavigator() export default function PlanPage() { return ( @@ -14,5 +14,5 @@ export default function PlanPage() { - ); + ) } diff --git a/Routes.tsx b/Routes.tsx index 028cd97..de8bb32 100644 --- a/Routes.tsx +++ b/Routes.tsx @@ -1,18 +1,18 @@ -import {createDrawerNavigator} from '@react-navigation/drawer'; -import {IconButton} from 'react-native-paper'; -import BestPage from './BestPage'; -import {DrawerParamList} from './drawer-param-list'; -import HomePage from './HomePage'; -import PlanPage from './PlanPage'; -import Route from './route'; -import SettingsPage from './SettingsPage'; -import useDark from './use-dark'; -import WorkoutsPage from './WorkoutsPage'; +import {createDrawerNavigator} from '@react-navigation/drawer' +import {IconButton} from 'react-native-paper' +import BestPage from './BestPage' +import {DrawerParamList} from './drawer-param-list' +import HomePage from './HomePage' +import PlanPage from './PlanPage' +import Route from './route' +import SettingsPage from './SettingsPage' +import useDark from './use-dark' +import WorkoutsPage from './WorkoutsPage' -const Drawer = createDrawerNavigator(); +const Drawer = createDrawerNavigator() export default function Routes() { - const dark = useDark(); + const dark = useDark() const routes: Route[] = [ {name: 'Home', component: HomePage, icon: 'home'}, @@ -20,7 +20,7 @@ export default function Routes() { {name: 'Best', component: BestPage, icon: 'insights'}, {name: 'Workouts', component: WorkoutsPage, icon: 'fitness-center'}, {name: 'Settings', component: SettingsPage, icon: 'settings'}, - ]; + ] return ( ))} - ); + ) } diff --git a/SetForm.tsx b/SetForm.tsx index 1fa7f10..f07a4a6 100644 --- a/SetForm.tsx +++ b/SetForm.tsx @@ -1,47 +1,47 @@ -import {useCallback, useRef, useState} from 'react'; -import {TextInput, View} from 'react-native'; -import DocumentPicker from 'react-native-document-picker'; -import {Button, Card, TouchableRipple} from 'react-native-paper'; -import ConfirmDialog from './ConfirmDialog'; -import {MARGIN} from './constants'; -import {setRepo} from './db'; -import GymSet from './gym-set'; -import MassiveInput from './MassiveInput'; -import {useSnackbar} from './MassiveSnack'; -import {useSettings} from './use-settings'; +import {useCallback, useRef, useState} from 'react' +import {TextInput, View} from 'react-native' +import DocumentPicker from 'react-native-document-picker' +import {Button, Card, TouchableRipple} from 'react-native-paper' +import ConfirmDialog from './ConfirmDialog' +import {MARGIN} from './constants' +import {setRepo} from './db' +import GymSet from './gym-set' +import MassiveInput from './MassiveInput' +import {useSnackbar} from './MassiveSnack' +import {useSettings} from './use-settings' export default function SetForm({ save, set, }: { - set: GymSet; - save: (set: GymSet) => void; + set: GymSet + save: (set: GymSet) => void }) { - const [name, setName] = useState(set.name); - const [reps, setReps] = useState(set.reps.toString()); - const [weight, setWeight] = useState(set.weight.toString()); - const [newImage, setNewImage] = useState(set.image); - const [unit, setUnit] = useState(set.unit); - const [showRemove, setShowRemove] = useState(false); + const [name, setName] = useState(set.name) + const [reps, setReps] = useState(set.reps.toString()) + const [weight, setWeight] = useState(set.weight.toString()) + const [newImage, setNewImage] = useState(set.image) + const [unit, setUnit] = useState(set.unit) + const [showRemove, setShowRemove] = useState(false) const [selection, setSelection] = useState({ start: 0, end: set.reps.toString().length, - }); - const [removeImage, setRemoveImage] = useState(false); - const {toast} = useSnackbar(); - const {settings} = useSettings(); - const weightRef = useRef(null); - const repsRef = useRef(null); - const unitRef = useRef(null); + }) + const [removeImage, setRemoveImage] = useState(false) + const {toast} = useSnackbar() + const {settings} = useSettings() + const weightRef = useRef(null) + const repsRef = useRef(null) + const unitRef = useRef(null) const handleSubmit = async () => { - console.log(`${SetForm.name}.handleSubmit:`, {set, uri: newImage, name}); - if (!name) return; - let image = newImage; + console.log(`${SetForm.name}.handleSubmit:`, {set, uri: newImage, name}) + if (!name) return + let image = newImage if (!newImage && !removeImage) - image = await setRepo.findOne({where: {name}}).then(s => s?.image); + image = await setRepo.findOne({where: {name}}).then(s => s?.image) - console.log(`${SetForm.name}.handleSubmit:`, {image}); + console.log(`${SetForm.name}.handleSubmit:`, {image}) save({ name, reps: Number(reps), @@ -53,34 +53,34 @@ export default function SetForm({ seconds: Number(set.seconds ?? 30), sets: set.sets ?? 3, hidden: false, - }); - }; + }) + } const handleName = (value: string) => { - setName(value.replace(/,|'/g, '')); + setName(value.replace(/,|'/g, '')) if (value.match(/,|'/)) - toast('Commas and single quotes would break CSV exports', 6000); - }; + toast('Commas and single quotes would break CSV exports', 6000) + } const handleUnit = (value: string) => { - setUnit(value.replace(/,|'/g, '')); + setUnit(value.replace(/,|'/g, '')) if (value.match(/,|'/)) - toast('Commas and single quotes would break CSV exports', 6000); - }; + toast('Commas and single quotes would break CSV exports', 6000) + } const changeImage = useCallback(async () => { const {fileCopyUri} = await DocumentPicker.pickSingle({ type: 'image/*', copyTo: 'documentDirectory', - }); - if (fileCopyUri) setNewImage(fileCopyUri); - }, []); + }) + if (fileCopyUri) setNewImage(fileCopyUri) + }, []) const handleRemove = useCallback(async () => { - setNewImage(''); - setRemoveImage(true); - setShowRemove(false); - }, []); + setNewImage('') + setRemoveImage(true) + setShowRemove(false) + }, []) return ( <> @@ -156,5 +156,5 @@ export default function SetForm({ Are you sure you want to remove the image? - ); + ) } diff --git a/SetItem.tsx b/SetItem.tsx index da84ed3..91319cc 100644 --- a/SetItem.tsx +++ b/SetItem.tsx @@ -1,47 +1,47 @@ -import {NavigationProp, useNavigation} from '@react-navigation/native'; -import {useCallback, useState} from 'react'; -import {GestureResponderEvent, Image} from 'react-native'; -import {Divider, List, Menu, Text} from 'react-native-paper'; -import {setRepo} from './db'; -import GymSet from './gym-set'; -import {HomePageParams} from './home-page-params'; -import {format} from './time'; -import useDark from './use-dark'; -import {useSettings} from './use-settings'; +import {NavigationProp, useNavigation} from '@react-navigation/native' +import {useCallback, useState} from 'react' +import {GestureResponderEvent, Image} from 'react-native' +import {Divider, List, Menu, Text} from 'react-native-paper' +import {setRepo} from './db' +import GymSet from './gym-set' +import {HomePageParams} from './home-page-params' +import {format} from './time' +import useDark from './use-dark' +import {useSettings} from './use-settings' export default function SetItem({ item, onRemove, }: { - item: GymSet; - onRemove: () => void; + item: GymSet + onRemove: () => void }) { - const [showMenu, setShowMenu] = useState(false); - const [anchor, setAnchor] = useState({x: 0, y: 0}); - const {settings} = useSettings(); - const dark = useDark(); - const navigation = useNavigation>(); + const [showMenu, setShowMenu] = useState(false) + const [anchor, setAnchor] = useState({x: 0, y: 0}) + const {settings} = useSettings() + const dark = useDark() + const navigation = useNavigation>() const remove = useCallback(async () => { - if (typeof item.id === 'number') await setRepo.delete(item.id); - setShowMenu(false); - onRemove(); - }, [setShowMenu, onRemove, item.id]); + if (typeof item.id === 'number') await setRepo.delete(item.id) + setShowMenu(false) + onRemove() + }, [setShowMenu, onRemove, item.id]) const copy = useCallback(() => { - const set: GymSet = {...item}; - delete set.id; - setShowMenu(false); - navigation.navigate('EditSet', {set}); - }, [navigation, item]); + const set: GymSet = {...item} + delete set.id + setShowMenu(false) + navigation.navigate('EditSet', {set}) + }, [navigation, item]) const longPress = useCallback( (e: GestureResponderEvent) => { - setAnchor({x: e.nativeEvent.pageX, y: e.nativeEvent.pageY}); - setShowMenu(true); + setAnchor({x: e.nativeEvent.pageX, y: e.nativeEvent.pageY}) + setShowMenu(true) }, [setShowMenu, setAnchor], - ); + ) return ( <> @@ -79,5 +79,5 @@ export default function SetItem({ )} /> - ); + ) } diff --git a/SetList.tsx b/SetList.tsx index 4460a4e..e612fa4 100644 --- a/SetList.tsx +++ b/SetList.tsx @@ -2,29 +2,29 @@ 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 {Like} from 'typeorm'; -import {getNow, setRepo} from './db'; -import DrawerHeader from './DrawerHeader'; -import GymSet from './gym-set'; -import {HomePageParams} from './home-page-params'; -import Page from './Page'; -import SetItem from './SetItem'; +} from '@react-navigation/native' +import React, {useCallback, useEffect, useState} from 'react' +import {FlatList} from 'react-native' +import {List} from 'react-native-paper' +import {Like} from 'typeorm' +import {getNow, setRepo} from './db' +import DrawerHeader from './DrawerHeader' +import GymSet from './gym-set' +import {HomePageParams} from './home-page-params' +import Page from './Page' +import SetItem from './SetItem' -const limit = 15; +const limit = 15 export default function SetList() { - const [sets, setSets] = useState([]); - const [set, setSet] = useState(); - const [offset, setOffset] = useState(0); - const [term, setTerm] = useState(''); - const [end, setEnd] = useState(false); - const navigation = useNavigation>(); + const [sets, setSets] = useState([]) + const [set, setSet] = useState() + const [offset, setOffset] = useState(0) + const [term, setTerm] = useState('') + const [end, setEnd] = useState(false) + const navigation = useNavigation>() - useEffect(() => console.log({sets}), [sets]); + useEffect(() => console.log({sets}), [sets]) const refresh = useCallback(async (value: string) => { const newSets = await setRepo.find({ @@ -32,47 +32,47 @@ export default function SetList() { take: limit, skip: 0, order: {created: 'DESC'}, - }); - setSet(newSets[0]); - if (newSets.length === 0) return setSets([]); - setSets(newSets); - setOffset(0); - setEnd(false); - }, []); + }) + setSet(newSets[0]) + if (newSets.length === 0) return setSets([]) + setSets(newSets) + setOffset(0) + setEnd(false) + }, []) useFocusEffect( useCallback(() => { - refresh(term); + refresh(term) }, [refresh, term]), - ); + ) const renderItem = useCallback( ({item}: {item: GymSet}) => ( refresh(term)} /> ), [refresh, term], - ); + ) const next = useCallback(async () => { - if (end) return; - const newOffset = offset + limit; - console.log(`${SetList.name}.next:`, {offset, newOffset, term}); + if (end) return + const newOffset = offset + limit + console.log(`${SetList.name}.next:`, {offset, newOffset, term}) const newSets = await setRepo.find({ where: {name: Like(`%${term}%`), hidden: 0 as any}, take: limit, skip: newOffset, order: {created: 'DESC'}, - }); - if (newSets.length === 0) return setEnd(true); - if (!sets) return; - setSets([...sets, ...newSets]); - if (newSets.length < limit) return setEnd(true); - setOffset(newOffset); - }, [term, end, offset, sets]); + }) + if (newSets.length === 0) return setEnd(true) + if (!sets) return + setSets([...sets, ...newSets]) + if (newSets.length < limit) return setEnd(true) + setOffset(newOffset) + }, [term, end, offset, sets]) const onAdd = useCallback(async () => { - console.log(`${SetList.name}.onAdd`, {set}); - const [{now}] = await getNow(); + console.log(`${SetList.name}.onAdd`, {set}) + const [{now}] = await getNow() navigation.navigate('EditSet', { set: set || { hidden: false, @@ -84,16 +84,16 @@ export default function SetList() { weight: 0, created: now, }, - }); - }, [navigation, set]); + }) + }, [navigation, set]) const search = useCallback( (value: string) => { - setTerm(value); - refresh(value); + setTerm(value) + refresh(value) }, [refresh], - ); + ) return ( <> @@ -114,5 +114,5 @@ export default function SetList() { )} - ); + ) } diff --git a/SettingsPage.tsx b/SettingsPage.tsx index def0f63..0c25c2b 100644 --- a/SettingsPage.tsx +++ b/SettingsPage.tsx @@ -1,27 +1,27 @@ -import {Picker} from '@react-native-picker/picker'; -import {useFocusEffect} from '@react-navigation/native'; -import {useCallback, useEffect, useState} from 'react'; -import {NativeModules, ScrollView} from 'react-native'; -import DocumentPicker from 'react-native-document-picker'; -import {Button} from 'react-native-paper'; -import {useColor} from './color'; -import {darkColors, lightColors} from './colors'; -import ConfirmDialog from './ConfirmDialog'; -import {MARGIN} from './constants'; -import {settingsRepo} from './db'; -import DrawerHeader from './DrawerHeader'; -import Input from './input'; -import {useSnackbar} from './MassiveSnack'; -import Page from './Page'; -import Settings from './settings'; -import Switch from './Switch'; -import {useSettings} from './use-settings'; +import {Picker} from '@react-native-picker/picker' +import {useFocusEffect} from '@react-navigation/native' +import {useCallback, useEffect, useState} from 'react' +import {NativeModules, ScrollView} from 'react-native' +import DocumentPicker from 'react-native-document-picker' +import {Button} from 'react-native-paper' +import {useColor} from './color' +import {darkColors, lightColors} from './colors' +import ConfirmDialog from './ConfirmDialog' +import {MARGIN} from './constants' +import {settingsRepo} from './db' +import DrawerHeader from './DrawerHeader' +import Input from './input' +import {useSnackbar} from './MassiveSnack' +import Page from './Page' +import Settings from './settings' +import Switch from './Switch' +import {useSettings} from './use-settings' export default function SettingsPage() { - const [battery, setBattery] = useState(false); - const [ignoring, setIgnoring] = useState(false); - const [term, setTerm] = useState(''); - const {settings, setSettings} = useSettings(); + const [battery, setBattery] = useState(false) + const [ignoring, setIgnoring] = useState(false) + const [term, setTerm] = useState('') + const {settings, setSettings} = useSettings() const { vibrate, sound, @@ -34,120 +34,120 @@ export default function SettingsPage() { theme, alarm, noSound, - } = settings; - const {color, setColor} = useColor(); - const {toast} = useSnackbar(); + } = settings + const {color, setColor} = useColor() + const {toast} = useSnackbar() useEffect(() => { - console.log(`${SettingsPage.name}.useEffect:`, {settings}); - }, [settings]); + console.log(`${SettingsPage.name}.useEffect:`, {settings}) + }, [settings]) useFocusEffect( useCallback(() => { - NativeModules.AlarmModule.ignoringBattery(setIgnoring); + NativeModules.AlarmModule.ignoringBattery(setIgnoring) }, []), - ); + ) const update = useCallback( (value: boolean, field: keyof Settings) => { - settingsRepo.update({}, {[field]: value}); - setSettings({...settings, [field]: value}); + settingsRepo.update({}, {[field]: value}) + setSettings({...settings, [field]: value}) }, [settings, setSettings], - ); + ) const changeAlarmEnabled = useCallback( (enabled: boolean) => { - if (enabled) toast('Timers will now run after each set.', 4000); - else toast('Stopped timers running after each set.', 4000); - if (enabled && !ignoring) setBattery(true); - update(enabled, 'alarm'); + if (enabled) toast('Timers will now run after each set.', 4000) + else toast('Stopped timers running after each set.', 4000) + if (enabled && !ignoring) setBattery(true) + update(enabled, 'alarm') }, [setBattery, ignoring, toast, update], - ); + ) const changeVibrate = useCallback( (enabled: boolean) => { - if (enabled) toast('When a timer completes, vibrate your phone.', 4000); - else toast('Stop vibrating at the end of timers.', 4000); - update(enabled, 'vibrate'); + if (enabled) toast('When a timer completes, vibrate your phone.', 4000) + else toast('Stop vibrating at the end of timers.', 4000) + update(enabled, 'vibrate') }, [toast, update], - ); + ) const changeSound = useCallback(async () => { const {fileCopyUri} = await DocumentPicker.pickSingle({ type: 'audio/*', copyTo: 'documentDirectory', - }); - if (!fileCopyUri) return; - settingsRepo.update({}, {sound: fileCopyUri}); - setSettings({...settings, sound: fileCopyUri}); - toast('This song will now play after rest timers complete.', 4000); - }, [toast, setSettings, settings]); + }) + if (!fileCopyUri) return + settingsRepo.update({}, {sound: fileCopyUri}) + setSettings({...settings, sound: fileCopyUri}) + toast('This song will now play after rest timers complete.', 4000) + }, [toast, setSettings, settings]) const changeNotify = useCallback( (enabled: boolean) => { - update(enabled, 'notify'); - if (enabled) toast('Show when a set is a new record.', 4000); - else toast('Stopped showing notifications for new records.', 4000); + update(enabled, 'notify') + if (enabled) toast('Show when a set is a new record.', 4000) + else toast('Stopped showing notifications for new records.', 4000) }, [toast, update], - ); + ) const changeImages = useCallback( (enabled: boolean) => { - update(enabled, 'images'); - if (enabled) toast('Show images for sets.', 4000); - else toast('Stopped showing images for sets.', 4000); + update(enabled, 'images') + if (enabled) toast('Show images for sets.', 4000) + else toast('Stopped showing images for sets.', 4000) }, [toast, update], - ); + ) const changeUnit = useCallback( (enabled: boolean) => { - update(enabled, 'showUnit'); - if (enabled) toast('Show option to select unit for sets.', 4000); - else toast('Hid unit option for sets.', 4000); + update(enabled, 'showUnit') + if (enabled) toast('Show option to select unit for sets.', 4000) + else toast('Hid unit option for sets.', 4000) }, [toast, update], - ); + ) const changeSteps = useCallback( (enabled: boolean) => { - update(enabled, 'steps'); - if (enabled) toast('Show steps for a workout.', 4000); - else toast('Stopped showing steps for workouts.', 4000); + update(enabled, 'steps') + if (enabled) toast('Show steps for a workout.', 4000) + else toast('Stopped showing steps for workouts.', 4000) }, [toast, update], - ); + ) const changeShowDate = useCallback( (enabled: boolean) => { - update(enabled, 'showDate'); - if (enabled) toast('Show date for sets by default.', 4000); - else toast('Stopped showing date for sets by default.', 4000); + update(enabled, 'showDate') + if (enabled) toast('Show date for sets by default.', 4000) + else toast('Stopped showing date for sets by default.', 4000) }, [toast, update], - ); + ) const changeShowSets = useCallback( (enabled: boolean) => { - update(enabled, 'showSets'); - if (enabled) toast('Show maximum sets for workouts.', 4000); - else toast('Stopped showing maximum sets for workouts.', 4000); + update(enabled, 'showSets') + if (enabled) toast('Show maximum sets for workouts.', 4000) + else toast('Stopped showing maximum sets for workouts.', 4000) }, [toast, update], - ); + ) const changeNoSound = useCallback( (enabled: boolean) => { - update(enabled, 'noSound'); - if (enabled) toast('Disable sound on rest timer alarms.', 4000); - else toast('Enabled sound for rest timer alarms.', 4000); + update(enabled, 'noSound') + if (enabled) toast('Disable sound on rest timer alarms.', 4000) + else toast('Enabled sound for rest timer alarms.', 4000) }, [toast, update], - ); + ) const switches: Input[] = [ {name: 'Rest timers', value: alarm, onChange: changeAlarmEnabled}, @@ -159,23 +159,23 @@ export default function SettingsPage() { {name: 'Show steps', value: steps, onChange: changeSteps}, {name: 'Show date', value: showDate, onChange: changeShowDate}, {name: 'Show sets', value: showSets, onChange: changeShowSets}, - ]; + ] const changeTheme = useCallback( (value: string) => { - settingsRepo.update({}, {theme: value}); - setSettings({...settings, theme: value}); + settingsRepo.update({}, {theme: value}) + setSettings({...settings, theme: value}) }, [settings, setSettings], - ); + ) const changeDate = useCallback( (value: string) => { - settingsRepo.update({}, {date: value}); - setSettings({...settings, date: value as any}); + settingsRepo.update({}, {date: value}) + setSettings({...settings, date: value as any}) }, [settings, setSettings], - ); + ) return ( <> @@ -256,12 +256,12 @@ export default function SettingsPage() { show={battery} setShow={setBattery} onOk={() => { - NativeModules.AlarmModule.ignoreBattery(); - setBattery(false); + NativeModules.AlarmModule.ignoreBattery() + setBattery(false) }}> Disable battery optimizations for Massive to use rest timers. - ); + ) } diff --git a/StackHeader.tsx b/StackHeader.tsx index 581a682..3b0562a 100644 --- a/StackHeader.tsx +++ b/StackHeader.tsx @@ -1,13 +1,13 @@ -import {useNavigation} from '@react-navigation/native'; -import Share from 'react-native-share'; -import {FileSystem} from 'react-native-file-access'; -import {Appbar, IconButton} from 'react-native-paper'; -import {captureScreen} from 'react-native-view-shot'; -import useDark from './use-dark'; +import {useNavigation} from '@react-navigation/native' +import Share from 'react-native-share' +import {FileSystem} from 'react-native-file-access' +import {Appbar, IconButton} from 'react-native-paper' +import {captureScreen} from 'react-native-view-shot' +import useDark from './use-dark' export default function StackHeader({title}: {title: string}) { - const navigation = useNavigation(); - const dark = useDark(); + const navigation = useNavigation() + const dark = useDark() return ( @@ -21,16 +21,16 @@ export default function StackHeader({title}: {title: string}) { color={dark ? 'white' : 'white'} onPress={() => captureScreen().then(async uri => { - const base64 = await FileSystem.readFile(uri, 'base64'); - const url = `data:image/jpeg;base64,${base64}`; + const base64 = await FileSystem.readFile(uri, 'base64') + const url = `data:image/jpeg;base64,${base64}` Share.open({ type: 'image/jpeg', url, - }); + }) }) } icon="share" /> - ); + ) } diff --git a/StartPlan.tsx b/StartPlan.tsx index 22091a2..53fac07 100644 --- a/StartPlan.tsx +++ b/StartPlan.tsx @@ -1,50 +1,50 @@ -import {RouteProp, useFocusEffect, useRoute} from '@react-navigation/native'; -import {useCallback, useMemo, useRef, useState} from 'react'; -import {NativeModules, TextInput, View} from 'react-native'; -import {FlatList} from 'react-native-gesture-handler'; -import {Button} from 'react-native-paper'; -import {getBestSet} from './best.service'; -import {PADDING} from './constants'; -import CountMany from './count-many'; -import {AppDataSource} from './data-source'; -import {getNow, setRepo} from './db'; -import GymSet from './gym-set'; -import MassiveInput from './MassiveInput'; -import {useSnackbar} from './MassiveSnack'; -import {PlanPageParams} from './plan-page-params'; -import SetForm from './SetForm'; -import StackHeader from './StackHeader'; -import StartPlanItem from './StartPlanItem'; -import {useSettings} from './use-settings'; +import {RouteProp, useFocusEffect, useRoute} from '@react-navigation/native' +import {useCallback, useMemo, useRef, useState} from 'react' +import {NativeModules, TextInput, View} from 'react-native' +import {FlatList} from 'react-native-gesture-handler' +import {Button} from 'react-native-paper' +import {getBestSet} from './best.service' +import {PADDING} from './constants' +import CountMany from './count-many' +import {AppDataSource} from './data-source' +import {getNow, setRepo} from './db' +import GymSet from './gym-set' +import MassiveInput from './MassiveInput' +import {useSnackbar} from './MassiveSnack' +import {PlanPageParams} from './plan-page-params' +import SetForm from './SetForm' +import StackHeader from './StackHeader' +import StartPlanItem from './StartPlanItem' +import {useSettings} from './use-settings' export default function StartPlan() { - const {params} = useRoute>(); - const [name, setName] = useState(''); - const [reps, setReps] = useState(''); - const [weight, setWeight] = useState(''); - const [unit, setUnit] = useState('kg'); - const {toast} = useSnackbar(); - const [minutes, setMinutes] = useState(3); - const [seconds, setSeconds] = useState(30); - const [best, setBest] = useState(); - const [selected, setSelected] = useState(0); - const {settings} = useSettings(); - const [counts, setCounts] = useState(); - const weightRef = useRef(null); - const repsRef = useRef(null); - const unitRef = useRef(null); - const workouts = useMemo(() => params.plan.workouts.split(','), [params]); + const {params} = useRoute>() + const [name, setName] = useState('') + const [reps, setReps] = useState('') + const [weight, setWeight] = useState('') + const [unit, setUnit] = useState('kg') + const {toast} = useSnackbar() + const [minutes, setMinutes] = useState(3) + const [seconds, setSeconds] = useState(30) + const [best, setBest] = useState() + const [selected, setSelected] = useState(0) + const {settings} = useSettings() + const [counts, setCounts] = useState() + const weightRef = useRef(null) + const repsRef = useRef(null) + const unitRef = useRef(null) + const workouts = useMemo(() => params.plan.workouts.split(','), [params]) const [selection, setSelection] = useState({ start: 0, end: 0, - }); + }) const refresh = useCallback(() => { const questions = workouts .map((workout, index) => `('${workout}',${index})`) - .join(','); - console.log({questions, workouts}); + .join(',') + console.log({questions, workouts}) const select = ` SELECT workouts.name, COUNT(sets.id) as total FROM (select 0 as name, 0 as sequence union values ${questions}) as workouts @@ -55,43 +55,43 @@ export default function StartPlan() { ORDER BY workouts.sequence LIMIT -1 OFFSET 1 - `; + ` return AppDataSource.manager.query(select).then(newCounts => { - setCounts(newCounts); - console.log(`${StartPlan.name}.focus:`, {newCounts}); - return newCounts; - }); - }, [workouts]); + setCounts(newCounts) + console.log(`${StartPlan.name}.focus:`, {newCounts}) + return newCounts + }) + }, [workouts]) const select = useCallback( async (index: number, newCounts?: CountMany[]) => { - setSelected(index); - console.log(`${StartPlan.name}.next:`, {name, index}); - if (!counts && !newCounts) return; - const workout = counts ? counts[index] : newCounts[index]; - console.log(`${StartPlan.name}.next:`, {workout}); - const newBest = await getBestSet(workout.name); - console.log(`${StartPlan.name}.next:`, {newBest}); - setMinutes(newBest.minutes); - setSeconds(newBest.seconds); - setName(newBest.name); - setReps(newBest.reps.toString()); - setWeight(newBest.weight.toString()); - setUnit(newBest.unit); - setBest(newBest); + setSelected(index) + console.log(`${StartPlan.name}.next:`, {name, index}) + if (!counts && !newCounts) return + const workout = counts ? counts[index] : newCounts[index] + console.log(`${StartPlan.name}.next:`, {workout}) + const newBest = await getBestSet(workout.name) + console.log(`${StartPlan.name}.next:`, {newBest}) + setMinutes(newBest.minutes) + setSeconds(newBest.seconds) + setName(newBest.name) + setReps(newBest.reps.toString()) + setWeight(newBest.weight.toString()) + setUnit(newBest.unit) + setBest(newBest) }, [name, counts], - ); + ) useFocusEffect( useCallback(() => { - refresh().then(newCounts => select(0, newCounts)); + refresh().then(newCounts => select(0, newCounts)) }, [refresh]), - ); + ) const handleSubmit = async () => { - console.log(`${SetForm.name}.handleSubmit:`, {reps, weight, unit, best}); - const [{now}] = await getNow(); + console.log(`${SetForm.name}.handleSubmit:`, {reps, weight, unit, best}) + const [{now}] = await getNow() await setRepo.save({ name, weight: +weight, @@ -102,30 +102,30 @@ export default function StartPlan() { seconds, sets: best.sets, hidden: false, - }); - await refresh(); + }) + await refresh() if ( settings.notify && (+weight > best.weight || (+reps > best.reps && +weight === best.weight)) ) - toast("Great work King! That's a new record.", 5000); - else if (settings.alarm) toast('Resting...', 3000); - else toast('Added set', 3000); - if (!settings.alarm) return; - const milliseconds = Number(minutes) * 60 * 1000 + Number(seconds) * 1000; - const {vibrate, sound, noSound} = settings; - const args = [milliseconds, !!vibrate, sound, !!noSound]; - NativeModules.AlarmModule.timer(...args); - }; + toast("Great work King! That's a new record.", 5000) + else if (settings.alarm) toast('Resting...', 3000) + else toast('Added set', 3000) + if (!settings.alarm) return + const milliseconds = Number(minutes) * 60 * 1000 + Number(seconds) * 1000 + const {vibrate, sound, noSound} = settings + const args = [milliseconds, !!vibrate, sound, !!noSound] + NativeModules.AlarmModule.timer(...args) + } const handleUnit = useCallback( (value: string) => { - setUnit(value.replace(/,|'/g, '')); + setUnit(value.replace(/,|'/g, '')) if (value.match(/,|'/)) - toast('Commas and single quotes would break CSV exports', 6000); + toast('Commas and single quotes would break CSV exports', 6000) }, [toast], - ); + ) return ( <> @@ -179,5 +179,5 @@ export default function StartPlan() { - ); + ) } diff --git a/StartPlanItem.tsx b/StartPlanItem.tsx index d618b84..cce51ce 100644 --- a/StartPlanItem.tsx +++ b/StartPlanItem.tsx @@ -1,40 +1,40 @@ -import React, {useCallback, useState} from 'react'; -import {GestureResponderEvent, ListRenderItemInfo, View} from 'react-native'; -import {List, Menu, RadioButton} from 'react-native-paper'; -import {useColor} from './color'; -import CountMany from './count-many'; -import {setRepo} from './db'; +import React, {useCallback, useState} from 'react' +import {GestureResponderEvent, ListRenderItemInfo, View} from 'react-native' +import {List, Menu, RadioButton} from 'react-native-paper' +import {useColor} from './color' +import CountMany from './count-many' +import {setRepo} from './db' interface Props extends ListRenderItemInfo { - onSelect: (index: number) => void; - selected: number; - onUndo: () => void; + onSelect: (index: number) => void + selected: number + onUndo: () => void } export default function StartPlanItem(props: Props) { - const {index, item, onSelect, selected, onUndo} = props; - const {color} = useColor(); - const [anchor, setAnchor] = useState({x: 0, y: 0}); - const [showMenu, setShowMenu] = useState(false); + const {index, item, onSelect, selected, onUndo} = props + const {color} = useColor() + const [anchor, setAnchor] = useState({x: 0, y: 0}) + const [showMenu, setShowMenu] = useState(false) const undo = useCallback(async () => { const first = await setRepo.findOne({ where: {name: item.name, hidden: 0 as any}, order: {created: 'desc'}, - }); - console.log({first}); - await setRepo.delete(first.id); - setShowMenu(false); - onUndo(); - }, [setShowMenu, onUndo, item.name]); + }) + console.log({first}) + await setRepo.delete(first.id) + setShowMenu(false) + onUndo() + }, [setShowMenu, onUndo, item.name]) const longPress = useCallback( (e: GestureResponderEvent) => { - setAnchor({x: e.nativeEvent.pageX, y: e.nativeEvent.pageY}); - setShowMenu(true); + setAnchor({x: e.nativeEvent.pageX, y: e.nativeEvent.pageY}) + setShowMenu(true) }, [setShowMenu, setAnchor], - ); + ) return ( )} /> - ); + ) } diff --git a/Switch.tsx b/Switch.tsx index 4d5454d..11f6f5d 100644 --- a/Switch.tsx +++ b/Switch.tsx @@ -1,11 +1,11 @@ -import {useMemo} from 'react'; -import {Pressable} from 'react-native'; -import {Switch as PaperSwitch, Text} from 'react-native-paper'; -import {CombinedDarkTheme, CombinedDefaultTheme} from './App'; -import {useColor} from './color'; -import {colorShade} from './colors'; -import {MARGIN} from './constants'; -import useDark from './use-dark'; +import {useMemo} from 'react' +import {Pressable} from 'react-native' +import {Switch as PaperSwitch, Text} from 'react-native-paper' +import {CombinedDarkTheme, CombinedDefaultTheme} from './App' +import {useColor} from './color' +import {colorShade} from './colors' +import {MARGIN} from './constants' +import useDark from './use-dark' export default function Switch({ value, @@ -13,25 +13,25 @@ export default function Switch({ onPress, children, }: { - value?: boolean; - onValueChange: (value: boolean) => void; - onPress: () => void; - children: string; + value?: boolean + onValueChange: (value: boolean) => void + onPress: () => void + children: string }) { - const {color} = useColor(); - const dark = useDark(); + const {color} = useColor() + const dark = useDark() const track = useMemo(() => { if (dark) return { false: CombinedDarkTheme.colors.placeholder, true: colorShade(color, -40), - }; + } return { false: CombinedDefaultTheme.colors.placeholder, true: colorShade(color, -40), - }; - }, [dark, color]); + } + }, [dark, color]) return ( {children} - ); + ) } diff --git a/ViewBest.tsx b/ViewBest.tsx index 040fcf4..6dbdb4b 100644 --- a/ViewBest.tsx +++ b/ViewBest.tsx @@ -1,35 +1,35 @@ -import {Picker} from '@react-native-picker/picker'; -import {RouteProp, useRoute} from '@react-navigation/native'; -import {useEffect, useState} from 'react'; -import {View} from 'react-native'; -import {BestPageParams} from './BestPage'; -import Chart from './Chart'; -import {PADDING} from './constants'; -import {setRepo} from './db'; -import GymSet from './gym-set'; -import {Metrics} from './metrics'; -import {Periods} from './periods'; -import StackHeader from './StackHeader'; -import {formatMonth} from './time'; -import useDark from './use-dark'; -import Volume from './volume'; +import {Picker} from '@react-native-picker/picker' +import {RouteProp, useRoute} from '@react-navigation/native' +import {useEffect, useState} from 'react' +import {View} from 'react-native' +import {BestPageParams} from './BestPage' +import Chart from './Chart' +import {PADDING} from './constants' +import {setRepo} from './db' +import GymSet from './gym-set' +import {Metrics} from './metrics' +import {Periods} from './periods' +import StackHeader from './StackHeader' +import {formatMonth} from './time' +import useDark from './use-dark' +import Volume from './volume' export default function ViewBest() { - const {params} = useRoute>(); - const dark = useDark(); - const [weights, setWeights] = useState([]); - const [volumes, setVolumes] = useState([]); - const [metric, setMetric] = useState(Metrics.Weight); - const [period, setPeriod] = useState(Periods.Monthly); + const {params} = useRoute>() + const dark = useDark() + const [weights, setWeights] = useState([]) + const [volumes, setVolumes] = useState([]) + const [metric, setMetric] = useState(Metrics.Weight) + const [period, setPeriod] = useState(Periods.Monthly) useEffect(() => { - console.log(`${ViewBest.name}.useEffect`, {metric}); - console.log(`${ViewBest.name}.useEffect`, {period}); - let difference = '-7 days'; - if (period === Periods.Monthly) difference = '-1 months'; - else if (period === Periods.Yearly) difference = '-1 years'; - let group = '%Y-%m-%d'; - if (period === Periods.Yearly) group = '%Y-%m'; + console.log(`${ViewBest.name}.useEffect`, {metric}) + console.log(`${ViewBest.name}.useEffect`, {period}) + let difference = '-7 days' + if (period === Periods.Monthly) difference = '-1 months' + else if (period === Periods.Yearly) difference = '-1 years' + let group = '%Y-%m-%d' + if (period === Periods.Yearly) group = '%Y-%m' const builder = setRepo .createQueryBuilder() .select("STRFTIME('%Y-%m-%d', created)", 'created') @@ -40,31 +40,28 @@ export default function ViewBest() { difference, }) .groupBy('name') - .addGroupBy(`STRFTIME('${group}', created)`); + .addGroupBy(`STRFTIME('${group}', created)`) switch (metric) { case Metrics.Weight: - builder - .addSelect('MAX(weight)', 'weight') - .getRawMany() - .then(setWeights); - break; + builder.addSelect('MAX(weight)', 'weight').getRawMany().then(setWeights) + break case Metrics.Volume: builder .addSelect('SUM(weight * reps)', 'value') .getRawMany() - .then(setVolumes); - break; + .then(setVolumes) + break default: // Brzycki formula https://en.wikipedia.org/wiki/One-repetition_maximum#Brzycki builder .addSelect('MAX(weight / (1.0278 - 0.0278 * reps))', 'weight') .getRawMany() .then(weights => { - console.log({weights}); - setWeights(weights); - }); + console.log({weights}) + setWeights(weights) + }) } - }, [params.best.name, metric, period]); + }, [params.best.name, metric, period]) return ( <> @@ -109,5 +106,5 @@ export default function ViewBest() { )} - ); + ) } diff --git a/WorkoutItem.tsx b/WorkoutItem.tsx index 6132b0e..4cd5b0d 100644 --- a/WorkoutItem.tsx +++ b/WorkoutItem.tsx @@ -1,48 +1,48 @@ -import {NavigationProp, useNavigation} from '@react-navigation/native'; -import {useCallback, useMemo, useState} from 'react'; -import {GestureResponderEvent, Image} from 'react-native'; -import {List, Menu, Text} from 'react-native-paper'; -import ConfirmDialog from './ConfirmDialog'; -import {setRepo} from './db'; -import GymSet from './gym-set'; -import {useSettings} from './use-settings'; -import {WorkoutsPageParams} from './WorkoutsPage'; +import {NavigationProp, useNavigation} from '@react-navigation/native' +import {useCallback, useMemo, useState} from 'react' +import {GestureResponderEvent, Image} from 'react-native' +import {List, Menu, Text} from 'react-native-paper' +import ConfirmDialog from './ConfirmDialog' +import {setRepo} from './db' +import GymSet from './gym-set' +import {useSettings} from './use-settings' +import {WorkoutsPageParams} from './WorkoutsPage' export default function WorkoutItem({ item, onRemove, }: { - item: GymSet; - onRemove: () => void; + item: GymSet + onRemove: () => void }) { - const [showMenu, setShowMenu] = useState(false); - const [anchor, setAnchor] = useState({x: 0, y: 0}); - const [showRemove, setShowRemove] = useState(''); - const {settings} = useSettings(); - const navigation = useNavigation>(); + const [showMenu, setShowMenu] = useState(false) + const [anchor, setAnchor] = useState({x: 0, y: 0}) + const [showRemove, setShowRemove] = useState('') + const {settings} = useSettings() + const navigation = useNavigation>() const remove = useCallback(async () => { - await setRepo.delete({name: item.name}); - setShowMenu(false); - onRemove(); - }, [setShowMenu, onRemove, item.name]); + await setRepo.delete({name: item.name}) + setShowMenu(false) + onRemove() + }, [setShowMenu, onRemove, item.name]) const longPress = useCallback( (e: GestureResponderEvent) => { - setAnchor({x: e.nativeEvent.pageX, y: e.nativeEvent.pageY}); - setShowMenu(true); + setAnchor({x: e.nativeEvent.pageX, y: e.nativeEvent.pageY}) + setShowMenu(true) }, [setShowMenu, setAnchor], - ); + ) const description = useMemo(() => { - const seconds = item.seconds?.toString().padStart(2, '0'); + const seconds = item.seconds?.toString().padStart(2, '0') if (settings.alarm && settings.showSets) - return `${item.sets} x ${item.minutes || 0}:${seconds}`; + return `${item.sets} x ${item.minutes || 0}:${seconds}` else if (settings.alarm && !settings.showSets) - return `${item.minutes || 0}:${seconds}`; - return `${item.sets}`; - }, [item, settings]); + return `${item.minutes || 0}:${seconds}` + return `${item.sets}` + }, [item, settings]) return ( <> @@ -69,8 +69,8 @@ export default function WorkoutItem({ { - setShowRemove(item.name); - setShowMenu(false); + setShowRemove(item.name) + setShowMenu(false) }} title="Delete" /> @@ -87,5 +87,5 @@ export default function WorkoutItem({ sure? - ); + ) } diff --git a/WorkoutList.tsx b/WorkoutList.tsx index ca5e7f5..94050c6 100644 --- a/WorkoutList.tsx +++ b/WorkoutList.tsx @@ -2,26 +2,26 @@ import { NavigationProp, useFocusEffect, useNavigation, -} from '@react-navigation/native'; -import {useCallback, useState} from 'react'; -import {FlatList} from 'react-native'; -import {List} from 'react-native-paper'; -import DrawerHeader from './DrawerHeader'; -import Page from './Page'; -import GymSet from './gym-set'; -import SetList from './SetList'; -import WorkoutItem from './WorkoutItem'; -import {WorkoutsPageParams} from './WorkoutsPage'; -import {setRepo} from './db'; +} from '@react-navigation/native' +import {useCallback, useState} from 'react' +import {FlatList} from 'react-native' +import {List} from 'react-native-paper' +import DrawerHeader from './DrawerHeader' +import Page from './Page' +import GymSet from './gym-set' +import SetList from './SetList' +import WorkoutItem from './WorkoutItem' +import {WorkoutsPageParams} from './WorkoutsPage' +import {setRepo} from './db' -const limit = 15; +const limit = 15 export default function WorkoutList() { - const [workouts, setWorkouts] = useState(); - const [offset, setOffset] = useState(0); - const [term, setTerm] = useState(''); - const [end, setEnd] = useState(false); - const navigation = useNavigation>(); + const [workouts, setWorkouts] = useState() + const [offset, setOffset] = useState(0) + const [term, setTerm] = useState('') + const [end, setEnd] = useState(false) + const navigation = useNavigation>() const refresh = useCallback(async (value: string) => { const newWorkouts = await setRepo @@ -31,35 +31,35 @@ export default function WorkoutList() { .groupBy('name') .orderBy('name') .limit(limit) - .getMany(); - console.log(`${WorkoutList.name}`, {newWorkout: newWorkouts[0]}); - setWorkouts(newWorkouts); - setOffset(0); - setEnd(false); - }, []); + .getMany() + console.log(`${WorkoutList.name}`, {newWorkout: newWorkouts[0]}) + setWorkouts(newWorkouts) + setOffset(0) + setEnd(false) + }, []) useFocusEffect( useCallback(() => { - refresh(term); + refresh(term) }, [refresh, term]), - ); + ) const renderItem = useCallback( ({item}: {item: GymSet}) => ( refresh(term)} /> ), [refresh, term], - ); + ) const next = useCallback(async () => { - if (end) return; - const newOffset = offset + limit; + if (end) return + const newOffset = offset + limit console.log(`${SetList.name}.next:`, { offset, limit, newOffset, term, - }); + }) const newWorkouts = await setRepo .createQueryBuilder() .select() @@ -68,27 +68,27 @@ export default function WorkoutList() { .orderBy('name') .limit(limit) .offset(newOffset) - .getMany(); - if (newWorkouts.length === 0) return setEnd(true); - if (!workouts) return; - setWorkouts([...workouts, ...newWorkouts]); - if (newWorkouts.length < limit) return setEnd(true); - setOffset(newOffset); - }, [term, end, offset, workouts]); + .getMany() + if (newWorkouts.length === 0) return setEnd(true) + if (!workouts) return + setWorkouts([...workouts, ...newWorkouts]) + if (newWorkouts.length < limit) return setEnd(true) + setOffset(newOffset) + }, [term, end, offset, workouts]) const onAdd = useCallback(async () => { navigation.navigate('EditWorkout', { value: new GymSet(), - }); - }, [navigation]); + }) + }, [navigation]) const search = useCallback( (value: string) => { - setTerm(value); - refresh(value); + setTerm(value) + refresh(value) }, [refresh], - ); + ) return ( <> @@ -110,5 +110,5 @@ export default function WorkoutList() { )} - ); + ) } diff --git a/WorkoutsPage.tsx b/WorkoutsPage.tsx index 35cb780..8419b1d 100644 --- a/WorkoutsPage.tsx +++ b/WorkoutsPage.tsx @@ -1,16 +1,16 @@ -import {createStackNavigator} from '@react-navigation/stack'; -import EditWorkout from './EditWorkout'; -import GymSet from './gym-set'; -import WorkoutList from './WorkoutList'; +import {createStackNavigator} from '@react-navigation/stack' +import EditWorkout from './EditWorkout' +import GymSet from './gym-set' +import WorkoutList from './WorkoutList' export type WorkoutsPageParams = { - WorkoutList: {}; + WorkoutList: {} EditWorkout: { - value: GymSet; - }; -}; + value: GymSet + } +} -const Stack = createStackNavigator(); +const Stack = createStackNavigator() export default function WorkoutsPage() { return ( @@ -19,5 +19,5 @@ export default function WorkoutsPage() { - ); + ) } diff --git a/best.service.ts b/best.service.ts index 9dc22a0..92450fb 100644 --- a/best.service.ts +++ b/best.service.ts @@ -1,5 +1,5 @@ -import {setRepo} from './db'; -import GymSet from './gym-set'; +import {setRepo} from './db' +import GymSet from './gym-set' export const getBestSet = async (name: string): Promise => { return setRepo @@ -11,5 +11,5 @@ export const getBestSet = async (name: string): Promise => { .addGroupBy('reps') .orderBy('weight', 'DESC') .addOrderBy('reps', 'DESC') - .getOne(); -}; + .getOne() +} diff --git a/color.ts b/color.ts index 2f5f353..51acc05 100644 --- a/color.ts +++ b/color.ts @@ -1,11 +1,11 @@ -import React, {useContext} from 'react'; +import React, {useContext} from 'react' export const Color = React.createContext({ color: '', setColor: (_value: string) => {}, -}); +}) export const useColor = () => { - const context = useContext(Color); - return context; -}; + const context = useContext(Color) + return context +} diff --git a/colors.ts b/colors.ts index 3491c72..1e6339c 100644 --- a/colors.ts +++ b/colors.ts @@ -3,34 +3,34 @@ export const lightColors = [ {hex: '#B3E5FC', name: 'Cyan'}, {hex: '#FFC0CB', name: 'Pink'}, {hex: '#E9DCC9', name: 'Linen'}, -]; +] export const darkColors = [ {hex: '#8156A7', name: 'Purple'}, {hex: '#007AFF', name: 'Blue'}, {hex: '#000000', name: 'Black'}, {hex: '#CD5C5C', name: 'Red'}, -]; +] export const colorShade = (color: any, amount: number) => { - color = color.replace(/^#/, ''); + color = color.replace(/^#/, '') if (color.length === 3) - color = color[0] + color[0] + color[1] + color[1] + color[2] + color[2]; + color = color[0] + color[0] + color[1] + color[1] + color[2] + color[2] - let [r, g, b] = color.match(/.{2}/g); - [r, g, b] = [ + let [r, g, b] = color.match(/.{2}/g) + ;[r, g, b] = [ parseInt(r, 16) + amount, parseInt(g, 16) + amount, parseInt(b, 16) + amount, - ]; + ] - r = Math.max(Math.min(255, r), 0).toString(16); - g = Math.max(Math.min(255, g), 0).toString(16); - b = Math.max(Math.min(255, b), 0).toString(16); + r = Math.max(Math.min(255, r), 0).toString(16) + g = Math.max(Math.min(255, g), 0).toString(16) + b = Math.max(Math.min(255, b), 0).toString(16) - const rr = (r.length < 2 ? '0' : '') + r; - const gg = (g.length < 2 ? '0' : '') + g; - const bb = (b.length < 2 ? '0' : '') + b; + const rr = (r.length < 2 ? '0' : '') + r + const gg = (g.length < 2 ? '0' : '') + g + const bb = (b.length < 2 ? '0' : '') + b - return `#${rr}${gg}${bb}`; -}; + return `#${rr}${gg}${bb}` +} diff --git a/constants.ts b/constants.ts index ae645e4..f8c3a3a 100644 --- a/constants.ts +++ b/constants.ts @@ -1,2 +1,2 @@ -export const MARGIN = 10; -export const PADDING = 10; +export const MARGIN = 10 +export const PADDING = 10 diff --git a/count-many.ts b/count-many.ts index 0fbcafd..cf82397 100644 --- a/count-many.ts +++ b/count-many.ts @@ -1,5 +1,5 @@ export default interface CountMany { - name: string; - total: number; - sets?: number; + name: string + total: number + sets?: number } diff --git a/data-source.ts b/data-source.ts index 9faa6a7..6f7e296 100644 --- a/data-source.ts +++ b/data-source.ts @@ -1,29 +1,29 @@ -import {DataSource} from 'typeorm'; -import GymSet from './gym-set'; -import {Sets1667185586014} from './migrations/1667185586014-sets'; -import {plans1667186124792} from './migrations/1667186124792-plans'; -import {settings1667186130041} from './migrations/1667186130041-settings'; -import {addSound1667186139844} from './migrations/1667186139844-add-sound'; -import {addHidden1667186159379} from './migrations/1667186159379-add-hidden'; -import {addNotify1667186166140} from './migrations/1667186166140-add-notify'; -import {addImage1667186171548} from './migrations/1667186171548-add-image'; -import {addImages1667186179488} from './migrations/1667186179488-add-images'; -import {insertSettings1667186203827} from './migrations/1667186203827-insert-settings'; -import {addSteps1667186211251} from './migrations/1667186211251-add-steps'; -import {addSets1667186250618} from './migrations/1667186250618-add-sets'; -import {addMinutes1667186255650} from './migrations/1667186255650-add-minutes'; -import {addSeconds1667186259174} from './migrations/1667186259174-add-seconds'; -import {addShowUnit1667186265588} from './migrations/1667186265588-add-show-unit'; -import {addColor1667186320954} from './migrations/1667186320954-add-color'; -import {addSteps1667186348425} from './migrations/1667186348425-add-steps'; -import {addDate1667186431804} from './migrations/1667186431804-add-date'; -import {addShowDate1667186435051} from './migrations/1667186435051-add-show-date'; -import {addTheme1667186439366} from './migrations/1667186439366-add-theme'; -import {addShowSets1667186443614} from './migrations/1667186443614-add-show-sets'; -import {addSetsCreated1667186451005} from './migrations/1667186451005-add-sets-created'; -import {addNoSound1667186456118} from './migrations/1667186456118-add-no-sound'; -import {Plan} from './plan'; -import Settings from './settings'; +import {DataSource} from 'typeorm' +import GymSet from './gym-set' +import {Sets1667185586014} from './migrations/1667185586014-sets' +import {plans1667186124792} from './migrations/1667186124792-plans' +import {settings1667186130041} from './migrations/1667186130041-settings' +import {addSound1667186139844} from './migrations/1667186139844-add-sound' +import {addHidden1667186159379} from './migrations/1667186159379-add-hidden' +import {addNotify1667186166140} from './migrations/1667186166140-add-notify' +import {addImage1667186171548} from './migrations/1667186171548-add-image' +import {addImages1667186179488} from './migrations/1667186179488-add-images' +import {insertSettings1667186203827} from './migrations/1667186203827-insert-settings' +import {addSteps1667186211251} from './migrations/1667186211251-add-steps' +import {addSets1667186250618} from './migrations/1667186250618-add-sets' +import {addMinutes1667186255650} from './migrations/1667186255650-add-minutes' +import {addSeconds1667186259174} from './migrations/1667186259174-add-seconds' +import {addShowUnit1667186265588} from './migrations/1667186265588-add-show-unit' +import {addColor1667186320954} from './migrations/1667186320954-add-color' +import {addSteps1667186348425} from './migrations/1667186348425-add-steps' +import {addDate1667186431804} from './migrations/1667186431804-add-date' +import {addShowDate1667186435051} from './migrations/1667186435051-add-show-date' +import {addTheme1667186439366} from './migrations/1667186439366-add-theme' +import {addShowSets1667186443614} from './migrations/1667186443614-add-show-sets' +import {addSetsCreated1667186451005} from './migrations/1667186451005-add-sets-created' +import {addNoSound1667186456118} from './migrations/1667186456118-add-no-sound' +import {Plan} from './plan' +import Settings from './settings' export const AppDataSource = new DataSource({ type: 'react-native', @@ -55,4 +55,4 @@ export const AppDataSource = new DataSource({ addSetsCreated1667186451005, addNoSound1667186456118, ], -}); +}) diff --git a/db.ts b/db.ts index bde42d1..3888f8a 100644 --- a/db.ts +++ b/db.ts @@ -1,26 +1,26 @@ -import {enablePromise, SQLiteDatabase} from 'react-native-sqlite-storage'; -import {AppDataSource} from './data-source'; -import GymSet from './gym-set'; -import {Plan} from './plan'; -import Settings from './settings'; +import {enablePromise, SQLiteDatabase} from 'react-native-sqlite-storage' +import {AppDataSource} from './data-source' +import GymSet from './gym-set' +import {Plan} from './plan' +import Settings from './settings' -enablePromise(true); +enablePromise(true) -export let db: SQLiteDatabase; +export let db: SQLiteDatabase -export const setRepo = AppDataSource.manager.getRepository(GymSet); -export const planRepo = AppDataSource.manager.getRepository(Plan); -export const settingsRepo = AppDataSource.manager.getRepository(Settings); +export const setRepo = AppDataSource.manager.getRepository(GymSet) +export const planRepo = AppDataSource.manager.getRepository(Plan) +export const settingsRepo = AppDataSource.manager.getRepository(Settings) export const getNow = (): Promise<{now: string}[]> => { return AppDataSource.manager.query( "SELECT STRFTIME('%Y-%m-%dT%H:%M:%S','now','localtime') AS now", - ); -}; + ) +} export const runMigrations = async () => { - console.log(`${runMigrations.name}:`, 'Initializing...'); - await AppDataSource.initialize(); - console.log(`${runMigrations.name}:`, 'Running migrations...'); - await AppDataSource.runMigrations(); -}; + console.log(`${runMigrations.name}:`, 'Initializing...') + await AppDataSource.initialize() + console.log(`${runMigrations.name}:`, 'Running migrations...') + await AppDataSource.runMigrations() +} diff --git a/drawer-param-list.ts b/drawer-param-list.ts index e590f4c..a7e8ac5 100644 --- a/drawer-param-list.ts +++ b/drawer-param-list.ts @@ -1,7 +1,7 @@ export type DrawerParamList = { - Home: {}; - Settings: {}; - Best: {}; - Plans: {}; - Workouts: {}; -}; + Home: {} + Settings: {} + Best: {} + Plans: {} + Workouts: {} +} diff --git a/gym-set.ts b/gym-set.ts index f0c8a59..4bab6f6 100644 --- a/gym-set.ts +++ b/gym-set.ts @@ -1,40 +1,40 @@ -import {Column, Entity, PrimaryGeneratedColumn} from 'typeorm'; +import {Column, Entity, PrimaryGeneratedColumn} from 'typeorm' @Entity('sets') export default class GymSet { @PrimaryGeneratedColumn() - id?: number; + id?: number @Column('text') - name: string; + name: string @Column('int') - reps: number; + reps: number @Column('int') - weight: number; + weight: number @Column('int') - sets = 3; + sets = 3 @Column('int') - minutes = 3; + minutes = 3 @Column('int') - seconds = 30; + seconds = 30 @Column('boolean') - hidden = false; + hidden = false @Column('text') - created: string; + created: string @Column('text') - unit: string; + unit: string @Column('text') - image: string; + image: string @Column('text') - steps?: string; + steps?: string } diff --git a/home-page-params.ts b/home-page-params.ts index a19a8d7..7d7c907 100644 --- a/home-page-params.ts +++ b/home-page-params.ts @@ -1,8 +1,8 @@ -import GymSet from './gym-set'; +import GymSet from './gym-set' export type HomePageParams = { - Sets: {}; + Sets: {} EditSet: { - set: GymSet; - }; -}; + set: GymSet + } +} diff --git a/input.ts b/input.ts index 15a2cff..22e7fde 100644 --- a/input.ts +++ b/input.ts @@ -1,5 +1,5 @@ export default interface Input { - name: string; - value?: T; - onChange: (value: T) => void; + name: string + value?: T + onChange: (value: T) => void } diff --git a/jestSetup.ts b/jestSetup.ts index 15a7964..64d7f6f 100644 --- a/jestSetup.ts +++ b/jestSetup.ts @@ -1,5 +1,5 @@ -import 'react-native-gesture-handler/jestSetup'; -import {NativeModules as RNNativeModules} from 'react-native'; +import 'react-native-gesture-handler/jestSetup' +import {NativeModules as RNNativeModules} from 'react-native' //RNNativeModules.UIManager = RNNativeModules.UIManager || {}; //RNNativeModules.UIManager.RCTView = RNNativeModules.UIManager.RCTView || {}; @@ -16,14 +16,14 @@ import {NativeModules as RNNativeModules} from 'react-native'; //}; RNNativeModules.RNViewShot = RNNativeModules.RNViewShot || { captureScreen: jest.fn(), -}; +} -jest.mock('react-native-file-access', () => jest.fn()); -jest.mock('react-native-share', () => jest.fn()); -jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper'); -jest.useFakeTimers(); +jest.mock('react-native-file-access', () => jest.fn()) +jest.mock('react-native-share', () => jest.fn()) +jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper') +jest.useFakeTimers() jest.mock('react-native-reanimated', () => { - const Reanimated = require('react-native-reanimated/mock'); - Reanimated.default.call = () => {}; - return Reanimated; -}); + const Reanimated = require('react-native-reanimated/mock') + Reanimated.default.call = () => {} + return Reanimated +}) diff --git a/mock-providers.tsx b/mock-providers.tsx index ed1b337..60af785 100644 --- a/mock-providers.tsx +++ b/mock-providers.tsx @@ -1,21 +1,21 @@ -import {NavigationContainer} from '@react-navigation/native'; -import React from 'react'; -import {Provider as PaperProvider} from 'react-native-paper'; -import {Color} from './color'; -import {lightColors} from './colors'; -import MassiveSnack from './MassiveSnack'; -import {defaultSettings, SettingsContext} from './use-settings'; -import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; +import {NavigationContainer} from '@react-navigation/native' +import React from 'react' +import {Provider as PaperProvider} from 'react-native-paper' +import {Color} from './color' +import {lightColors} from './colors' +import MassiveSnack from './MassiveSnack' +import {defaultSettings, SettingsContext} from './use-settings' +import MaterialIcon from 'react-native-vector-icons/MaterialIcons' -const color = lightColors[0].hex; -export const setColor = jest.fn(); -const settings = defaultSettings; -export const setSettings = jest.fn(); +const color = lightColors[0].hex +export const setColor = jest.fn() +const settings = defaultSettings +export const setSettings = jest.fn() export const MockProviders = ({ children, }: { - children: JSX.Element | JSX.Element[]; + children: JSX.Element | JSX.Element[] }) => ( }}> @@ -26,4 +26,4 @@ export const MockProviders = ({ -); +) diff --git a/plan-page-params.ts b/plan-page-params.ts index 425a4a4..f336b1d 100644 --- a/plan-page-params.ts +++ b/plan-page-params.ts @@ -1,11 +1,11 @@ -import {Plan} from './plan'; +import {Plan} from './plan' export type PlanPageParams = { - PlanList: {}; + PlanList: {} EditPlan: { - plan: Plan; - }; + plan: Plan + } StartPlan: { - plan: Plan; - }; -}; + plan: Plan + } +} diff --git a/plan.ts b/plan.ts index 2012639..ce258e6 100644 --- a/plan.ts +++ b/plan.ts @@ -1,13 +1,13 @@ -import {Column, Entity, PrimaryGeneratedColumn} from 'typeorm'; +import {Column, Entity, PrimaryGeneratedColumn} from 'typeorm' @Entity('plans') export class Plan { @PrimaryGeneratedColumn() - id?: number; + id?: number @Column('text') - days: string; + days: string @Column('text') - workouts: string; + workouts: string } diff --git a/route.ts b/route.ts index b8d37c1..8d09a3e 100644 --- a/route.ts +++ b/route.ts @@ -1,7 +1,7 @@ -import {DrawerParamList} from './drawer-param-list'; +import {DrawerParamList} from './drawer-param-list' export default interface Route { - name: keyof DrawerParamList; - component: React.ComponentType; - icon: string; + name: keyof DrawerParamList + component: React.ComponentType + icon: string } diff --git a/settings.ts b/settings.ts index 283353b..f925efc 100644 --- a/settings.ts +++ b/settings.ts @@ -1,43 +1,43 @@ -import {Column, Entity, PrimaryColumn} from 'typeorm'; +import {Column, Entity, PrimaryColumn} from 'typeorm' @Entity() export default class Settings { @PrimaryColumn('boolean') - alarm: boolean; + alarm: boolean @Column('boolean') - vibrate: boolean; + vibrate: boolean @Column('text') - sound: string; + sound: string @Column('boolean') - notify: boolean; + notify: boolean @Column('boolean') - images: boolean; + images: boolean @Column('boolean') - showUnit: boolean; + showUnit: boolean @Column('text') - color: string; + color: string @Column('boolean') - steps: boolean; + steps: boolean @Column('text') - date: string; + date: string @Column('boolean') - showDate: boolean; + showDate: boolean @Column('text') - theme: string; + theme: string @Column('boolean') - showSets: boolean; + showSets: boolean @Column('boolean') - noSound: boolean; + noSound: boolean } diff --git a/time.ts b/time.ts index 8bbec8b..465658b 100644 --- a/time.ts +++ b/time.ts @@ -6,26 +6,26 @@ export const DAYS = [ 'Thursday', 'Friday', 'Saturday', -]; +] export function formatMonth(iso: string) { - const date = new Date(iso); - const dd = date.getDate().toString(); - const mm = (date.getMonth() + 1).toString(); - return `${dd}/${mm}`; + const date = new Date(iso) + const dd = date.getDate().toString() + const mm = (date.getMonth() + 1).toString() + return `${dd}/${mm}` } function twelveHour(twentyFourHour: string) { - const [hourString, minute] = twentyFourHour.split(':'); - const hour = +hourString % 24; - return (hour % 12 || 12) + ':' + minute + (hour < 12 ? ' AM' : ' PM'); + const [hourString, minute] = twentyFourHour.split(':') + const hour = +hourString % 24 + return (hour % 12 || 12) + ':' + minute + (hour < 12 ? ' AM' : ' PM') } function dayOfWeek(iso: string) { - const date = new Date(iso); - const day = date.getDay(); - const target = DAYS[day]; - return target.slice(0, 3); + const date = new Date(iso) + const day = date.getDay() + const target = DAYS[day] + return target.slice(0, 3) } /** @@ -33,29 +33,29 @@ function dayOfWeek(iso: string) { * @param kind Intended format for the date, e.g. '%Y-%m-%d %H:%M' */ export function format(iso: string, kind: string) { - const split = iso.split('T'); - const [year, month, day] = split[0].split('-'); - const time = twelveHour(split[1]); + const split = iso.split('T') + const [year, month, day] = split[0].split('-') + const time = twelveHour(split[1]) switch (kind) { case '%Y-%m-%d %H:%M': - return iso.replace('T', ' ').replace(/:\d{2}/, ''); + return iso.replace('T', ' ').replace(/:\d{2}/, '') case '%Y-%m-%d': - return split[0]; + return split[0] case '%H:%M': - return split[1].replace(/:\d{2}/, ''); + return split[1].replace(/:\d{2}/, '') case '%d/%m/%y %h:%M %p': - return `${day}/${month}/${year} ${time}`; + return `${day}/${month}/${year} ${time}` case '%d/%m %h:%M %p': - return `${day}/${month} ${time}`; + return `${day}/${month} ${time}` case '%d/%m/%y': - return `${day}/${month}/${year}`; + return `${day}/${month}/${year}` case '%d/%m': - return `${day}/${month}`; + return `${day}/${month}` case '%h:%M %p': - return time; + return time case '%A %h:%M %p': - return dayOfWeek(iso) + ' ' + time; + return dayOfWeek(iso) + ' ' + time default: - return iso; + return iso } } diff --git a/use-dark.ts b/use-dark.ts index 5629c3f..345746c 100644 --- a/use-dark.ts +++ b/use-dark.ts @@ -1,11 +1,11 @@ -import {useColorScheme} from 'react-native'; -import {useSettings} from './use-settings'; +import {useColorScheme} from 'react-native' +import {useSettings} from './use-settings' export default function useDark() { - const dark = useColorScheme() === 'dark'; - const {settings} = useSettings(); + const dark = useColorScheme() === 'dark' + const {settings} = useSettings() - if (settings.theme === 'dark') return true; - if (settings.theme === 'light') return false; - return dark; + if (settings.theme === 'dark') return true + if (settings.theme === 'light') return false + return dark } diff --git a/use-settings.ts b/use-settings.ts index 8c40c20..2f72009 100644 --- a/use-settings.ts +++ b/use-settings.ts @@ -1,5 +1,5 @@ -import React, {useContext} from 'react'; -import Settings from './settings'; +import React, {useContext} from 'react' +import Settings from './settings' export const defaultSettings: Settings = { alarm: 0, @@ -15,16 +15,16 @@ export const defaultSettings: Settings = { theme: 'system', vibrate: 1, noSound: 0, -}; +} export const SettingsContext = React.createContext<{ - settings: Settings; - setSettings: (value: Settings) => void; + settings: Settings + setSettings: (value: Settings) => void }>({ settings: defaultSettings, setSettings: () => null, -}); +}) export function useSettings() { - return useContext(SettingsContext); + return useContext(SettingsContext) } diff --git a/volume.ts b/volume.ts index 786b73e..d019f36 100644 --- a/volume.ts +++ b/volume.ts @@ -1,6 +1,6 @@ export default interface Volume { - name: string; - created: string; - value: number; - unit: string; + name: string + created: string + value: number + unit: string } diff --git a/write.ts b/write.ts index 679acf7..16d9387 100644 --- a/write.ts +++ b/write.ts @@ -1,18 +1,18 @@ -import {NativeModules, PermissionsAndroid} from 'react-native'; -import {Dirs, FileSystem} from 'react-native-file-access'; +import {NativeModules, PermissionsAndroid} from 'react-native' +import {Dirs, FileSystem} from 'react-native-file-access' export const write = async (name: string, data: string) => { - const filePath = `${Dirs.DocumentDir}/${name}`; + const filePath = `${Dirs.DocumentDir}/${name}` const permission = async () => { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, - ); - return granted === PermissionsAndroid.RESULTS.GRANTED; - }; - const granted = await permission(); - if (!granted) return; - await FileSystem.writeFile(filePath, data); - if (!FileSystem.exists(filePath)) return; - await FileSystem.cpExternal(filePath, name, 'downloads'); - NativeModules.DownloadModule.show(name); -}; + ) + return granted === PermissionsAndroid.RESULTS.GRANTED + } + const granted = await permission() + if (!granted) return + await FileSystem.writeFile(filePath, data) + if (!FileSystem.exists(filePath)) return + await FileSystem.cpExternal(filePath, name, 'downloads') + NativeModules.DownloadModule.show(name) +}