Run prettier
Something happened with the deno formatter, I can't remember what! Hahahahahaahahaha
This commit is contained in:
parent
44283fc990
commit
f778426aba
104
App.tsx
104
App.tsx
|
@ -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;
|
||||
|
|
22
AppFab.tsx
22
AppFab.tsx
|
@ -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}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
22
AppInput.tsx
22
AppInput.tsx
|
@ -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);
|
||||
|
|
38
Chart.tsx
38
Chart.tsx
|
@ -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>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
142
EditPlan.tsx
142
EditPlan.tsx
|
@ -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: {},
|
||||
})
|
||||
});
|
||||
|
|
124
EditSets.tsx
124
EditSets.tsx
|
@ -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>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
142
EditWorkout.tsx
142
EditWorkout.tsx
|
@ -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>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
20
HomePage.tsx
20
HomePage.tsx
|
@ -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>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
89
ListMenu.tsx
89
ListMenu.tsx
|
@ -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>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
28
Page.tsx
28
Page.tsx
|
@ -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,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
|
112
PlanItem.tsx
112
PlanItem.tsx
|
@ -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
|