Run prettier

Something happened with the deno formatter,
I can't remember what! Hahahahahaahahaha
This commit is contained in:
Brandon Presley 2023-08-12 15:22:50 +12:00
parent 44283fc990
commit f778426aba
57 changed files with 1609 additions and 1628 deletions

104
App.tsx
View File

@ -2,21 +2,21 @@ import {
DarkTheme as NavigationDarkTheme,
DefaultTheme as NavigationDefaultTheme,
NavigationContainer,
} from '@react-navigation/native'
import React, { useEffect, useMemo, useState } from 'react'
import { DeviceEventEmitter, useColorScheme } from 'react-native'
} from "@react-navigation/native";
import React, { useEffect, useMemo, useState } from "react";
import { DeviceEventEmitter, useColorScheme } from "react-native";
import {
MD3DarkTheme as PaperDarkTheme,
MD3LightTheme as PaperDefaultTheme,
Provider as PaperProvider,
Snackbar,
} from 'react-native-paper'
import MaterialIcon from 'react-native-vector-icons/MaterialIcons'
import { AppDataSource } from './data-source'
import { settingsRepo } from './db'
import Routes from './Routes'
import { TOAST } from './toast'
import { ThemeContext } from './use-theme'
} from "react-native-paper";
import MaterialIcon from "react-native-vector-icons/MaterialIcons";
import { AppDataSource } from "./data-source";
import { settingsRepo } from "./db";
import Routes from "./Routes";
import { TOAST } from "./toast";
import { ThemeContext } from "./use-theme";
export const CombinedDefaultTheme = {
...NavigationDefaultTheme,
@ -25,7 +25,7 @@ export const CombinedDefaultTheme = {
...NavigationDefaultTheme.colors,
...PaperDefaultTheme.colors,
},
}
};
export const CombinedDarkTheme = {
...NavigationDarkTheme,
@ -34,58 +34,58 @@ export const CombinedDarkTheme = {
...NavigationDarkTheme.colors,
...PaperDarkTheme.colors,
},
}
};
const App = () => {
const phoneTheme = useColorScheme()
const [initialized, setInitialized] = useState(false)
const [snackbar, setSnackbar] = useState('')
const [appTheme, setAppTheme] = useState('system')
const phoneTheme = useColorScheme();
const [initialized, setInitialized] = useState(false);
const [snackbar, setSnackbar] = useState("");
const [appTheme, setAppTheme] = useState("system");
const [lightColor, setLightColor] = useState<string>(
CombinedDefaultTheme.colors.primary,
)
CombinedDefaultTheme.colors.primary
);
const [darkColor, setDarkColor] = useState<string>(
CombinedDarkTheme.colors.primary,
)
CombinedDarkTheme.colors.primary
);
useEffect(() => {
;(async () => {
if (!AppDataSource.isInitialized) await AppDataSource.initialize()
const settings = await settingsRepo.findOne({ where: {} })
setAppTheme(settings.theme)
if (settings.lightColor) setLightColor(settings.lightColor)
if (settings.darkColor) setDarkColor(settings.darkColor)
setInitialized(true)
})()
(async () => {
if (!AppDataSource.isInitialized) await AppDataSource.initialize();
const settings = await settingsRepo.findOne({ where: {} });
setAppTheme(settings.theme);
if (settings.lightColor) setLightColor(settings.lightColor);
if (settings.darkColor) setDarkColor(settings.darkColor);
setInitialized(true);
})();
const description = DeviceEventEmitter.addListener(
TOAST,
({ value }: { value: string }) => {
setSnackbar(value)
},
)
return description.remove
}, [])
setSnackbar(value);
}
);
return description.remove;
}, []);
const paperTheme = useMemo(() => {
const darkTheme = lightColor
? {
...CombinedDarkTheme,
colors: { ...CombinedDarkTheme.colors, primary: darkColor },
}
: CombinedDarkTheme
...CombinedDarkTheme,
colors: { ...CombinedDarkTheme.colors, primary: darkColor },
}
: CombinedDarkTheme;
const lightTheme = lightColor
? {
...CombinedDefaultTheme,
colors: { ...CombinedDefaultTheme.colors, primary: lightColor },
}
: CombinedDefaultTheme
let value = phoneTheme === 'dark' ? darkTheme : lightTheme
if (appTheme === 'dark') value = darkTheme
else if (appTheme === 'light') value = lightTheme
return value
}, [phoneTheme, appTheme, lightColor, darkColor])
...CombinedDefaultTheme,
colors: { ...CombinedDefaultTheme.colors, primary: lightColor },
}
: CombinedDefaultTheme;
let value = phoneTheme === "dark" ? darkTheme : lightTheme;
if (appTheme === "dark") value = darkTheme;
else if (appTheme === "light") value = lightTheme;
return value;
}, [phoneTheme, appTheme, lightColor, darkColor]);
return (
<PaperProvider
@ -111,18 +111,18 @@ const App = () => {
<Snackbar
duration={3000}
onDismiss={() => setSnackbar('')}
onDismiss={() => setSnackbar("")}
visible={!!snackbar}
action={{
label: 'Close',
onPress: () => setSnackbar(''),
label: "Close",
onPress: () => setSnackbar(""),
textColor: paperTheme.colors.background,
}}
>
{snackbar}
</Snackbar>
</PaperProvider>
)
}
);
};
export default App
export default App;

View File

@ -1,31 +1,31 @@
import { ComponentProps, useMemo } from 'react'
import { FAB, useTheme } from 'react-native-paper'
import { CombinedDarkTheme, CombinedDefaultTheme } from './App'
import { lightColors } from './colors'
import { ComponentProps, useMemo } from "react";
import { FAB, useTheme } from "react-native-paper";
import { CombinedDarkTheme, CombinedDefaultTheme } from "./App";
import { lightColors } from "./colors";
export default function AppFab(props: Partial<ComponentProps<typeof FAB>>) {
const { colors } = useTheme()
const { colors } = useTheme();
const fabColor = useMemo(
() =>
lightColors.map((color) => color.hex).includes(colors.primary)
? CombinedDarkTheme.colors.background
: CombinedDefaultTheme.colors.background,
[colors.primary],
)
[colors.primary]
);
return (
<FAB
icon='add'
testID='add'
icon="add"
testID="add"
color={fabColor}
style={{
position: 'absolute',
position: "absolute",
right: 20,
bottom: 20,
backgroundColor: colors.primary,
}}
{...props}
/>
)
);
}

View File

@ -1,26 +1,26 @@
import React, { ComponentProps, Ref } from 'react'
import { TextInput } from 'react-native-paper'
import { CombinedDefaultTheme } from './App'
import { MARGIN } from './constants'
import useDark from './use-dark'
import React, { ComponentProps, Ref } from "react";
import { TextInput } from "react-native-paper";
import { CombinedDefaultTheme } from "./App";
import { MARGIN } from "./constants";
import useDark from "./use-dark";
function AppInput(
props: Partial<ComponentProps<typeof TextInput>> & {
innerRef?: Ref<any>
},
innerRef?: Ref<any>;
}
) {
const dark = useDark()
const dark = useDark();
return (
<TextInput
selectionColor={dark ? '#2A2A2A' : CombinedDefaultTheme.colors.border}
selectionColor={dark ? "#2A2A2A" : CombinedDefaultTheme.colors.border}
style={{ marginBottom: MARGIN, minWidth: 100 }}
selectTextOnFocus
ref={props.innerRef}
blurOnSubmit={false}
{...props}
/>
)
);
}
export default React.memo(AppInput)
export default React.memo(AppInput);

View File

@ -1,11 +1,11 @@
import { useTheme } from '@react-navigation/native'
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 { MARGIN, PADDING } from './constants'
import GymSet from './gym-set'
import useDark from './use-dark'
import { useTheme } from "@react-navigation/native";
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 { 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 { colors } = useTheme()
const dark = useDark()
const { colors } = useTheme();
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 (
<>
@ -35,7 +35,7 @@ export default function Chart({
style={{
height: 300,
padding: PADDING,
flexDirection: 'row',
flexDirection: "row",
}}
>
<YAxis
@ -66,5 +66,5 @@ export default function Chart({
</View>
</View>
</>
)
);
}

View File

@ -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,
@ -8,17 +8,17 @@ export default function ConfirmDialog({
setShow,
onCancel,
}: {
title: string
children: JSX.Element | JSX.Element[] | string
onOk: () => void
show: boolean
setShow: (show: boolean) => void
onCancel?: () => void
title: string;
children: JSX.Element | JSX.Element[] | string;
onOk: () => void;
show: boolean;
setShow: (show: boolean) => void;
onCancel?: () => void;
}) {
const cancel = () => {
setShow(false)
onCancel && onCancel()
}
setShow(false);
onCancel && onCancel();
};
return (
<Portal>
@ -33,5 +33,5 @@ export default function ConfirmDialog({
</Dialog.Actions>
</Dialog>
</Portal>
)
);
}

View File

@ -1,25 +1,22 @@
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 { DrawerNavigationProp } from "@react-navigation/drawer";
import { useNavigation } from "@react-navigation/native";
import { Appbar, IconButton } from "react-native-paper";
import { DrawerParamList } from "./drawer-param-list";
export default function DrawerHeader({
name,
children,
}: {
name: string
children?: JSX.Element | JSX.Element[]
name: string;
children?: JSX.Element | JSX.Element[];
}) {
const navigation = useNavigation<DrawerNavigationProp<DrawerParamList>>()
const navigation = useNavigation<DrawerNavigationProp<DrawerParamList>>();
return (
<Appbar.Header>
<IconButton
icon='menu'
onPress={navigation.openDrawer}
/>
<IconButton icon="menu" onPress={navigation.openDrawer} />
<Appbar.Content title={name} />
{children}
</Appbar.Header>
)
);
}

View File

@ -3,92 +3,94 @@ import {
RouteProp,
useNavigation,
useRoute,
} from '@react-navigation/native'
import { useCallback, useEffect, useState } from 'react'
import { ScrollView, StyleSheet, View } from 'react-native'
import { Button, IconButton, Text } from 'react-native-paper'
import { MARGIN, PADDING } from './constants'
import { planRepo, setRepo } from './db'
import { defaultSet } from './gym-set'
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, IconButton, Text } from "react-native-paper";
import { MARGIN, PADDING } from "./constants";
import { planRepo, setRepo } from "./db";
import { defaultSet } from "./gym-set";
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<RouteProp<PlanPageParams, 'EditPlan'>>()
const { plan } = params
const { params } = useRoute<RouteProp<PlanPageParams, "EditPlan">>();
const { plan } = params;
const [days, setDays] = useState<string[]>(
plan.days ? plan.days.split(',') : [],
)
plan.days ? plan.days.split(",") : []
);
const [workouts, setWorkouts] = useState<string[]>(
plan.workouts ? plan.workouts.split(',') : [],
)
const [names, setNames] = useState<string[]>([])
const navigation = useNavigation<NavigationProp<PlanPageParams>>()
plan.workouts ? plan.workouts.split(",") : []
);
const [names, setNames] = useState<string[]>([]);
const navigation = useNavigation<NavigationProp<PlanPageParams>>();
useEffect(() => {
setRepo
.createQueryBuilder()
.select('name')
.select("name")
.distinct(true)
.orderBy('name')
.orderBy("name")
.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 })
}, [days, workouts, plan])
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 });
}, [days, workouts, plan]);
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],
)
[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],
)
[setDays, days]
);
return (
<>
<StackHeader
title={typeof plan.id === 'number' ? 'Edit plan' : 'Add plan'}
title={typeof plan.id === "number" ? "Edit plan" : "Add plan"}
>
{typeof plan.id === 'number' && (
{typeof plan.id === "number" && (
<IconButton
onPress={async () => {
await save()
const newPlan = await planRepo.findOne({ where: { id: plan.id } })
await save();
const newPlan = await planRepo.findOne({
where: { id: plan.id },
});
let first = await setRepo.findOne({
where: { name: workouts[0] },
order: { created: 'desc' },
})
if (!first) first = { ...defaultSet, name: workouts[0] }
delete first.id
navigation.navigate('StartPlan', { plan: newPlan, first })
order: { created: "desc" },
});
if (!first) first = { ...defaultSet, name: workouts[0] };
delete first.id;
navigation.navigate("StartPlan", { plan: newPlan, first });
}}
icon='play-arrow'
icon="play-arrow"
/>
)}
</StackHeader>
@ -104,39 +106,37 @@ export default function EditPlan() {
/>
))}
<Text style={[styles.title, { marginTop: MARGIN }]}>Workouts</Text>
{names.length === 0
? (
<View>
<Text>No workouts found.</Text>
</View>
)
: (
names.map((name) => (
<Switch
key={name}
onChange={(value) => toggleWorkout(value, name)}
value={workouts.includes(name)}
title={name}
/>
))
)}
{names.length === 0 ? (
<View>
<Text>No workouts found.</Text>
</View>
) : (
names.map((name) => (
<Switch
key={name}
onChange={(value) => toggleWorkout(value, name)}
value={workouts.includes(name)}
title={name}
/>
))
)}
</ScrollView>
<Button
disabled={workouts.length === 0 && days.length === 0}
style={styles.button}
mode='outlined'
icon='save'
mode="outlined"
icon="save"
onPress={async () => {
await save()
navigation.navigate('PlanList')
await save();
navigation.navigate("PlanList");
}}
>
Save
</Button>
</View>
</>
)
);
}
const styles = StyleSheet.create({
@ -145,4 +145,4 @@ const styles = StyleSheet.create({
marginBottom: MARGIN,
},
button: {},
})
});

View File

@ -3,78 +3,78 @@ import {
useFocusEffect,
useNavigation,
useRoute,
} from '@react-navigation/native'
import { useCallback, useState } from 'react'
import { View } from 'react-native'
import DocumentPicker from 'react-native-document-picker'
import { Button, Card, TouchableRipple } from 'react-native-paper'
import { In } from 'typeorm'
import AppInput from './AppInput'
import ConfirmDialog from './ConfirmDialog'
import { MARGIN, PADDING } from './constants'
import { setRepo, settingsRepo } from './db'
import GymSet from './gym-set'
import { HomePageParams } from './home-page-params'
import Settings from './settings'
import StackHeader from './StackHeader'
} from "@react-navigation/native";
import { useCallback, useState } from "react";
import { View } from "react-native";
import DocumentPicker from "react-native-document-picker";
import { Button, Card, TouchableRipple } from "react-native-paper";
import { In } from "typeorm";
import AppInput from "./AppInput";
import ConfirmDialog from "./ConfirmDialog";
import { MARGIN, PADDING } from "./constants";
import { setRepo, settingsRepo } from "./db";
import GymSet from "./gym-set";
import { HomePageParams } from "./home-page-params";
import Settings from "./settings";
import StackHeader from "./StackHeader";
export default function EditSets() {
const { params } = useRoute<RouteProp<HomePageParams, 'EditSets'>>()
const { ids } = params
const navigation = useNavigation()
const [settings, setSettings] = useState<Settings>({} as Settings)
const [name, setName] = useState('')
const [reps, setReps] = useState('')
const [weight, setWeight] = useState('')
const [newImage, setNewImage] = useState('')
const [unit, setUnit] = useState('')
const [showRemove, setShowRemove] = useState(false)
const [names, setNames] = useState('')
const [oldReps, setOldReps] = useState('')
const [weights, setWeights] = useState('')
const [units, setUnits] = useState('')
const { params } = useRoute<RouteProp<HomePageParams, "EditSets">>();
const { ids } = params;
const navigation = useNavigation();
const [settings, setSettings] = useState<Settings>({} as Settings);
const [name, setName] = useState("");
const [reps, setReps] = useState("");
const [weight, setWeight] = useState("");
const [newImage, setNewImage] = useState("");
const [unit, setUnit] = useState("");
const [showRemove, setShowRemove] = useState(false);
const [names, setNames] = useState("");
const [oldReps, setOldReps] = useState("");
const [weights, setWeights] = useState("");
const [units, setUnits] = useState("");
const [selection, setSelection] = useState({
start: 0,
end: 1,
})
});
useFocusEffect(
useCallback(() => {
settingsRepo.findOne({ where: {} }).then(setSettings)
settingsRepo.findOne({ where: {} }).then(setSettings);
setRepo.find({ where: { id: In(ids) } }).then((sets) => {
setNames(sets.map((set) => set.name).join(', '))
setOldReps(sets.map((set) => set.reps).join(', '))
setWeights(sets.map((set) => set.weight).join(', '))
setUnits(sets.map((set) => set.unit).join(', '))
})
}, [ids]),
)
setNames(sets.map((set) => set.name).join(", "));
setOldReps(sets.map((set) => set.reps).join(", "));
setWeights(sets.map((set) => set.weight).join(", "));
setUnits(sets.map((set) => set.unit).join(", "));
});
}, [ids])
);
const handleSubmit = async () => {
console.log(`${EditSets.name}.handleSubmit:`, { uri: newImage, name })
const update: Partial<GymSet> = {}
if (name) update.name = name
if (reps) update.reps = Number(reps)
if (weight) update.weight = Number(weight)
if (unit) update.unit = unit
if (newImage) update.image = newImage
if (Object.keys(update).length > 0) await setRepo.update(ids, update)
navigation.goBack()
}
console.log(`${EditSets.name}.handleSubmit:`, { uri: newImage, name });
const update: Partial<GymSet> = {};
if (name) update.name = name;
if (reps) update.reps = Number(reps);
if (weight) update.weight = Number(weight);
if (unit) update.unit = unit;
if (newImage) update.image = newImage;
if (Object.keys(update).length > 0) await setRepo.update(ids, update);
navigation.goBack();
};
const changeImage = useCallback(async () => {
const { fileCopyUri } = await DocumentPicker.pickSingle({
type: DocumentPicker.types.images,
copyTo: 'documentDirectory',
})
if (fileCopyUri) setNewImage(fileCopyUri)
}, [])
copyTo: "documentDirectory",
});
if (fileCopyUri) setNewImage(fileCopyUri);
}, []);
const handleRemove = useCallback(async () => {
setNewImage('')
setShowRemove(false)
}, [])
setNewImage("");
setShowRemove(false);
}, []);
return (
<>
@ -91,7 +91,7 @@ export default function EditSets() {
<AppInput
label={`Reps: ${oldReps}`}
keyboardType='numeric'
keyboardType="numeric"
value={reps}
onChangeText={setReps}
selection={selection}
@ -101,7 +101,7 @@ export default function EditSets() {
<AppInput
label={`Weights: ${weights}`}
keyboardType='numeric'
keyboardType="numeric"
value={weight}
onChangeText={setWeight}
onSubmitEditing={handleSubmit}
@ -109,7 +109,7 @@ export default function EditSets() {
{settings.showUnit && (
<AppInput
autoCapitalize='none'
autoCapitalize="none"
label={`Units: ${units}`}
value={unit}
onChangeText={setUnit}
@ -126,7 +126,7 @@ export default function EditSets() {
</TouchableRipple>
)}
<ConfirmDialog
title='Remove image'
title="Remove image"
onOk={handleRemove}
show={showRemove}
setShow={setShowRemove}
@ -138,7 +138,7 @@ export default function EditSets() {
<Button
style={{ marginBottom: MARGIN }}
onPress={changeImage}
icon='add-photo-alternate'
icon="add-photo-alternate"
>
Image
</Button>
@ -146,13 +146,13 @@ export default function EditSets() {
</View>
<Button
mode='outlined'
icon='save'
mode="outlined"
icon="save"
style={{ margin: MARGIN }}
onPress={handleSubmit}
>
Save
</Button>
</>
)
);
}

View File

@ -3,46 +3,46 @@ import {
useFocusEffect,
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 AppInput from './AppInput'
import ConfirmDialog from './ConfirmDialog'
import { MARGIN, PADDING } from './constants'
import { getNow, planRepo, setRepo, settingsRepo } from './db'
import { defaultSet } from './gym-set'
import Settings from './settings'
import StackHeader from './StackHeader'
import { WorkoutsPageParams } from './WorkoutsPage'
} 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 AppInput from "./AppInput";
import ConfirmDialog from "./ConfirmDialog";
import { MARGIN, PADDING } from "./constants";
import { getNow, planRepo, setRepo, settingsRepo } from "./db";
import { defaultSet } from "./gym-set";
import Settings from "./settings";
import StackHeader from "./StackHeader";
import { WorkoutsPageParams } from "./WorkoutsPage";
export default function EditWorkout() {
const { params } = useRoute<RouteProp<WorkoutsPageParams, 'EditWorkout'>>()
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<RouteProp<WorkoutsPageParams, "EditWorkout">>();
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',
)
params.value.minutes?.toString() ?? "3"
);
const [seconds, setSeconds] = useState(
params.value.seconds?.toString() ?? '30',
)
const [sets, setSets] = useState(params.value.sets?.toString() ?? '3')
const navigation = useNavigation()
const setsRef = useRef<TextInput>(null)
const stepsRef = useRef<TextInput>(null)
const minutesRef = useRef<TextInput>(null)
const secondsRef = useRef<TextInput>(null)
const [settings, setSettings] = useState<Settings>()
params.value.seconds?.toString() ?? "30"
);
const [sets, setSets] = useState(params.value.sets?.toString() ?? "3");
const navigation = useNavigation();
const setsRef = useRef<TextInput>(null);
const stepsRef = useRef<TextInput>(null);
const minutesRef = useRef<TextInput>(null);
const secondsRef = useRef<TextInput>(null);
const [settings, setSettings] = useState<Settings>();
useFocusEffect(
useCallback(() => {
settingsRepo.findOne({ where: {} }).then(setSettings)
}, []),
)
settingsRepo.findOne({ where: {} }).then(setSettings);
}, [])
);
const update = async () => {
await setRepo.update(
@ -53,20 +53,20 @@ export default function EditWorkout() {
minutes: +minutes,
seconds: +seconds,
steps,
image: removeImage ? '' : uri,
},
)
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()
}
[params.value.name, name, `%${params.value.name}%`]
);
navigation.goBack();
};
const add = async () => {
const now = await getNow()
const now = await getNow();
await setRepo.save({
...defaultSet,
name,
@ -77,42 +77,42 @@ 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: DocumentPicker.types.images,
copyTo: 'documentDirectory',
})
if (fileCopyUri) setUri(fileCopyUri)
}, [])
copyTo: "documentDirectory",
});
if (fileCopyUri) setUri(fileCopyUri);
}, []);
const handleRemove = useCallback(async () => {
setUri('')
setRemoveImage(true)
setShowRemove(false)
}, [])
setUri("");
setRemoveImage(true);
setShowRemove(false);
}, []);
const submitName = () => {
if (settings.steps) stepsRef.current?.focus()
else setsRef.current?.focus()
}
if (settings.steps) stepsRef.current?.focus();
else setsRef.current?.focus();
};
return (
<>
<StackHeader title={params.value.name ? 'Edit workout' : 'Add workout'} />
<StackHeader title={params.value.name ? "Edit workout" : "Add workout"} />
<View style={{ padding: PADDING, flex: 1 }}>
<ScrollView style={{ flex: 1 }}>
<AppInput
autoFocus
label='Name'
label="Name"
value={name}
onChangeText={setName}
onSubmitEditing={submitName}
@ -123,7 +123,7 @@ export default function EditWorkout() {
selectTextOnFocus={false}
value={steps}
onChangeText={setSteps}
label='Steps'
label="Steps"
multiline
onSubmitEditing={() => setsRef.current?.focus()}
/>
@ -132,8 +132,8 @@ export default function EditWorkout() {
innerRef={setsRef}
value={sets}
onChangeText={setSets}
label='Sets per workout'
keyboardType='numeric'
label="Sets per workout"
keyboardType="numeric"
onSubmitEditing={() => minutesRef.current?.focus()}
/>
{settings?.alarm && (
@ -143,15 +143,15 @@ export default function EditWorkout() {
onSubmitEditing={() => secondsRef.current?.focus()}
value={minutes}
onChangeText={setMinutes}
label='Rest minutes'
keyboardType='numeric'
label="Rest minutes"
keyboardType="numeric"
/>
<AppInput
innerRef={secondsRef}
value={seconds}
onChangeText={setSeconds}
label='Rest seconds'
keyboardType='numeric'
label="Rest seconds"
keyboardType="numeric"
blurOnSubmit
/>
</>
@ -169,17 +169,17 @@ export default function EditWorkout() {
<Button
style={{ marginBottom: MARGIN }}
onPress={changeImage}
icon='add-photo-alternate'
icon="add-photo-alternate"
>
Image
</Button>
)}
</ScrollView>
<Button disabled={!name} mode='outlined' icon='save' onPress={save}>
<Button disabled={!name} mode="outlined" icon="save" onPress={save}>
Save
</Button>
<ConfirmDialog
title='Remove image'
title="Remove image"
onOk={handleRemove}
show={showRemove}
setShow={setShowRemove}
@ -188,5 +188,5 @@ export default function EditWorkout() {
</ConfirmDialog>
</View>
</>
)
);
}

View File

@ -1,23 +1,23 @@
import { createStackNavigator } from '@react-navigation/stack'
import GraphsList from './GraphsList'
import GymSet from './gym-set'
import ViewGraph from './ViewGraph'
import { createStackNavigator } from "@react-navigation/stack";
import GraphsList from "./GraphsList";
import GymSet from "./gym-set";
import ViewGraph from "./ViewGraph";
const Stack = createStackNavigator<GraphsPageParams>()
const Stack = createStackNavigator<GraphsPageParams>();
export type GraphsPageParams = {
GraphsList: {}
GraphsList: {};
ViewGraph: {
best: GymSet
}
}
best: GymSet;
};
};
export default function GraphsPage() {
return (
<Stack.Navigator
screenOptions={{ headerShown: false, animationEnabled: false }}
>
<Stack.Screen name='GraphsList' component={GraphsList} />
<Stack.Screen name='ViewGraph' component={ViewGraph} />
<Stack.Screen name="GraphsList" component={GraphsList} />
<Stack.Screen name="ViewGraph" component={ViewGraph} />
</Stack.Navigator>
)
);
}

View File

@ -1,19 +1,19 @@
import { createStackNavigator } from '@react-navigation/stack'
import EditSet from './EditSet'
import EditSets from './EditSets'
import { HomePageParams } from './home-page-params'
import SetList from './SetList'
import { createStackNavigator } from "@react-navigation/stack";
import EditSet from "./EditSet";
import EditSets from "./EditSets";
import { HomePageParams } from "./home-page-params";
import SetList from "./SetList";
const Stack = createStackNavigator<HomePageParams>()
const Stack = createStackNavigator<HomePageParams>();
export default function HomePage() {
return (
<Stack.Navigator
screenOptions={{ headerShown: false, animationEnabled: false }}
>
<Stack.Screen name='Sets' component={SetList} />
<Stack.Screen name='EditSet' component={EditSet} />
<Stack.Screen name='EditSets' component={EditSets} />
<Stack.Screen name="Sets" component={SetList} />
<Stack.Screen name="EditSet" component={EditSet} />
<Stack.Screen name="EditSets" component={EditSets} />
</Stack.Navigator>
)
);
}

View File

@ -1,6 +1,6 @@
import { useState } from 'react'
import { Divider, IconButton, Menu } from 'react-native-paper'
import ConfirmDialog from './ConfirmDialog'
import { useState } from "react";
import { Divider, IconButton, Menu } from "react-native-paper";
import ConfirmDialog from "./ConfirmDialog";
export default function ListMenu({
onEdit,
@ -10,88 +10,85 @@ export default function ListMenu({
onSelect,
ids,
}: {
onEdit: () => void
onCopy: () => void
onClear: () => void
onDelete: () => void
onSelect: () => void
ids?: number[]
onEdit: () => void;
onCopy: () => void;
onClear: () => void;
onDelete: () => void;
onSelect: () => void;
ids?: number[];
}) {
const [showMenu, setShowMenu] = useState(false)
const [showRemove, setShowRemove] = useState(false)
const [showMenu, setShowMenu] = useState(false);
const [showRemove, setShowRemove] = useState(false);
const edit = () => {
setShowMenu(false)
onEdit()
}
setShowMenu(false);
onEdit();
};
const copy = () => {
setShowMenu(false)
onCopy()
}
setShowMenu(false);
onCopy();
};
const clear = () => {
setShowMenu(false)
onClear()
}
setShowMenu(false);
onClear();
};
const remove = () => {
setShowMenu(false)
setShowRemove(false)
onDelete()
}
setShowMenu(false);
setShowRemove(false);
onDelete();
};
const select = () => {
onSelect()
}
onSelect();
};
return (
<Menu
visible={showMenu}
onDismiss={() => setShowMenu(false)}
anchor={
<IconButton
onPress={() => setShowMenu(true)}
icon='more-vert'
/>
}
anchor={<IconButton onPress={() => setShowMenu(true)} icon="more-vert" />}
>
<Menu.Item leadingIcon='done-all' title='Select all' onPress={select} />
<Menu.Item leadingIcon="done-all" title="Select all" onPress={select} />
<Menu.Item
leadingIcon='clear'
title='Clear'
leadingIcon="clear"
title="Clear"
onPress={clear}
disabled={ids?.length === 0}
/>
<Menu.Item
leadingIcon='edit'
title='Edit'
leadingIcon="edit"
title="Edit"
onPress={edit}
disabled={ids?.length === 0}
/>
<Menu.Item
leadingIcon='content-copy'
title='Copy'
leadingIcon="content-copy"
title="Copy"
onPress={copy}
disabled={ids?.length === 0}
/>
<Divider />
<Menu.Item
leadingIcon='delete'
leadingIcon="delete"
onPress={() => setShowRemove(true)}
title='Delete'
title="Delete"
/>
<ConfirmDialog
title={ids?.length === 0 ? 'Delete all' : 'Delete selected'}
title={ids?.length === 0 ? "Delete all" : "Delete selected"}
show={showRemove}
setShow={setShowRemove}
onOk={remove}
onCancel={() => setShowMenu(false)}
>
{ids?.length === 0
? <>This irreversibly deletes records from the app. Are you sure?</>
: <>This will delete {ids?.length} record(s). Are you sure?</>}
{ids?.length === 0 ? (
<>This irreversibly deletes records from the app. Are you sure?</>
) : (
<>This will delete {ids?.length} record(s). Are you sure?</>
)}
</ConfirmDialog>
</Menu>
)
);
}

View File

@ -1,7 +1,7 @@
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'
import { Searchbar } from 'react-native-paper'
import AppFab from './AppFab'
import { PADDING } from './constants'
import { StyleProp, StyleSheet, View, ViewStyle } from "react-native";
import { Searchbar } from "react-native-paper";
import AppFab from "./AppFab";
import { PADDING } from "./constants";
export default function Page({
onAdd,
@ -10,25 +10,25 @@ export default function Page({
search,
style,
}: {
children: JSX.Element | JSX.Element[]
onAdd?: () => void
term: string
search: (value: string) => void
style?: StyleProp<ViewStyle>
children: JSX.Element | JSX.Element[];
onAdd?: () => void;
term: string;
search: (value: string) => void;
style?: StyleProp<ViewStyle>;
}) {
return (
<View style={[styles.view, style]}>
<Searchbar
placeholder='Search'
placeholder="Search"
value={term}
onChangeText={search}
icon='search'
clearIcon='clear'
icon="search"
clearIcon="clear"
/>
{children}
{onAdd && <AppFab onPress={onAdd} />}
</View>
)
);
}
const styles = StyleSheet.create({
@ -36,4 +36,4 @@ const styles = StyleSheet.create({
padding: PADDING,
flexGrow: 1,
},
})
});

View File

<
@ -2,91 +2,89 @@ import {
NavigationProp,
useFocusEffect,
useNavigation,
} from '@react-navigation/native'
import { useCallback, useMemo, useState } from 'react'
import { Text } from 'react-native'
import { List } from 'react-native-paper'
import { DARK_RIPPLE, LIGHT_RIPPLE } from './constants'
import { setRepo } from './db'
import { defaultSet } from './gym-set'
import { Plan } from './plan'
import { PlanPageParams } from './plan-page-params'
import { DAYS } from './time'
import useDark from './use-dark'
} from "@react-navigation/native";
import { useCallback, useMemo, useState } from "react";
import { Text } from "react-native";
import { List } from "react-native-paper";
import { DARK_RIPPLE, LIGHT_RIPPLE } from "./constants";
import { setRepo } from "./db";
import { defaultSet } from "./gym-set";
import { Plan } from "./plan";
import { PlanPageParams } from "./plan-page-params";
import { DAYS } from "./time";
import useDark from "./use-dark";
export default function PlanItem({
item,
setIds,
ids,
}: {
item: Plan
ids: number[]
setIds: (value: number[]) => void