Rename workout -> exercise
A workout would typically refer to a list of exercises.
This commit is contained in:
parent
6754e2a8ae
commit
8988e584ae
|
@ -7,7 +7,7 @@ import SetList from "./SetList";
|
||||||
import SettingsPage from "./SettingsPage";
|
import SettingsPage from "./SettingsPage";
|
||||||
import TimerPage from "./TimerPage";
|
import TimerPage from "./TimerPage";
|
||||||
import WeightList from "./WeightList";
|
import WeightList from "./WeightList";
|
||||||
import WorkoutList from "./WorkoutList";
|
import ExerciseList from "./ExerciseList";
|
||||||
import { DrawerParams } from "./drawer-param-list";
|
import { DrawerParams } from "./drawer-param-list";
|
||||||
import useDark from "./use-dark";
|
import useDark from "./use-dark";
|
||||||
|
|
||||||
|
@ -29,6 +29,11 @@ export default function AppDrawer() {
|
||||||
component={SetList}
|
component={SetList}
|
||||||
options={{ drawerIcon: () => <IconButton icon="home-outline" /> }}
|
options={{ drawerIcon: () => <IconButton icon="home-outline" /> }}
|
||||||
/>
|
/>
|
||||||
|
<Drawer.Screen
|
||||||
|
name="Exercises"
|
||||||
|
component={ExerciseList}
|
||||||
|
options={{ drawerIcon: () => <IconButton icon="dumbbell" /> }}
|
||||||
|
/>
|
||||||
<Drawer.Screen
|
<Drawer.Screen
|
||||||
name="Plans"
|
name="Plans"
|
||||||
component={PlanList}
|
component={PlanList}
|
||||||
|
@ -41,11 +46,6 @@ export default function AppDrawer() {
|
||||||
drawerIcon: () => <IconButton icon="chart-bell-curve-cumulative" />,
|
drawerIcon: () => <IconButton icon="chart-bell-curve-cumulative" />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Drawer.Screen
|
|
||||||
name="Workouts"
|
|
||||||
component={WorkoutList}
|
|
||||||
options={{ drawerIcon: () => <IconButton icon="dumbbell" /> }}
|
|
||||||
/>
|
|
||||||
<Drawer.Screen
|
<Drawer.Screen
|
||||||
name="Timer"
|
name="Timer"
|
||||||
component={TimerPage}
|
component={TimerPage}
|
||||||
|
|
12
AppStack.tsx
12
AppStack.tsx
|
@ -4,8 +4,8 @@ import EditPlan from "./EditPlan";
|
||||||
import EditSet from "./EditSet";
|
import EditSet from "./EditSet";
|
||||||
import EditSets from "./EditSets";
|
import EditSets from "./EditSets";
|
||||||
import EditWeight from "./EditWeight";
|
import EditWeight from "./EditWeight";
|
||||||
import EditWorkout from "./EditWorkout";
|
import EditExercise from "./EditExercise";
|
||||||
import EditWorkouts from "./EditWorkouts";
|
import EditExercises from "./EditExercises";
|
||||||
import StartPlan from "./StartPlan";
|
import StartPlan from "./StartPlan";
|
||||||
import ViewGraph from "./ViewGraph";
|
import ViewGraph from "./ViewGraph";
|
||||||
import ViewWeightGraph from "./ViewWeightGraph";
|
import ViewWeightGraph from "./ViewWeightGraph";
|
||||||
|
@ -36,10 +36,10 @@ export type StackParams = {
|
||||||
weight: Weight;
|
weight: Weight;
|
||||||
};
|
};
|
||||||
ViewWeightGraph: {};
|
ViewWeightGraph: {};
|
||||||
EditWorkout: {
|
EditExercise: {
|
||||||
gymSet: GymSet;
|
gymSet: GymSet;
|
||||||
};
|
};
|
||||||
EditWorkouts: {
|
EditExercises: {
|
||||||
names: string[];
|
names: string[];
|
||||||
};
|
};
|
||||||
ViewSetList: {
|
ViewSetList: {
|
||||||
|
@ -62,8 +62,8 @@ export default function AppStack() {
|
||||||
<Stack.Screen name="ViewGraph" component={ViewGraph} />
|
<Stack.Screen name="ViewGraph" component={ViewGraph} />
|
||||||
<Stack.Screen name="EditWeight" component={EditWeight} />
|
<Stack.Screen name="EditWeight" component={EditWeight} />
|
||||||
<Stack.Screen name="ViewWeightGraph" component={ViewWeightGraph} />
|
<Stack.Screen name="ViewWeightGraph" component={ViewWeightGraph} />
|
||||||
<Stack.Screen name="EditWorkout" component={EditWorkout} />
|
<Stack.Screen name="EditExercise" component={EditExercise} />
|
||||||
<Stack.Screen name="EditWorkouts" component={EditWorkouts} />
|
<Stack.Screen name="EditExercises" component={EditExercises} />
|
||||||
<Stack.Screen name="ViewSetList" component={ViewSetList} />
|
<Stack.Screen name="ViewSetList" component={ViewSetList} />
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,8 +22,8 @@ import { toast } from "./toast";
|
||||||
import { DrawerParams } from "./drawer-param-list";
|
import { DrawerParams } from "./drawer-param-list";
|
||||||
import { StackParams } from "./AppStack";
|
import { StackParams } from "./AppStack";
|
||||||
|
|
||||||
export default function EditWorkout() {
|
export default function EditExercise() {
|
||||||
const { params } = useRoute<RouteProp<StackParams, "EditWorkout">>();
|
const { params } = useRoute<RouteProp<StackParams, "EditExercise">>();
|
||||||
const [removeImage, setRemoveImage] = useState(false);
|
const [removeImage, setRemoveImage] = useState(false);
|
||||||
const [showRemove, setShowRemove] = useState(false);
|
const [showRemove, setShowRemove] = useState(false);
|
||||||
const [name, setName] = useState(params.gymSet.name);
|
const [name, setName] = useState(params.gymSet.name);
|
||||||
|
@ -50,7 +50,7 @@ export default function EditWorkout() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const update = async () => {
|
const update = async () => {
|
||||||
const newWorkout = {
|
const newExercise = {
|
||||||
name: name || params.gymSet.name,
|
name: name || params.gymSet.name,
|
||||||
sets: Number(sets),
|
sets: Number(sets),
|
||||||
minutes: +minutes,
|
minutes: +minutes,
|
||||||
|
@ -58,14 +58,14 @@ export default function EditWorkout() {
|
||||||
steps,
|
steps,
|
||||||
image: removeImage ? "" : uri,
|
image: removeImage ? "" : uri,
|
||||||
} as GymSet;
|
} as GymSet;
|
||||||
await setRepo.update({ name: params.gymSet.name }, newWorkout);
|
await setRepo.update({ name: params.gymSet.name }, newExercise);
|
||||||
await planRepo.query(
|
await planRepo.query(
|
||||||
`UPDATE plans
|
`UPDATE plans
|
||||||
SET workouts = REPLACE(workouts, $1, $2)
|
SET exercises = REPLACE(exercises, $1, $2)
|
||||||
WHERE workouts LIKE $3`,
|
WHERE exercises LIKE $3`,
|
||||||
[params.gymSet.name, name, `%${params.gymSet.name}%`]
|
[params.gymSet.name, name, `%${params.gymSet.name}%`]
|
||||||
);
|
);
|
||||||
navigate("Workouts", { update: newWorkout });
|
navigate("Exercises", { update: newExercise });
|
||||||
};
|
};
|
||||||
|
|
||||||
const add = async () => {
|
const add = async () => {
|
||||||
|
@ -82,7 +82,7 @@ export default function EditWorkout() {
|
||||||
created: now,
|
created: now,
|
||||||
});
|
});
|
||||||
emitter.emit(GYM_SET_CREATED);
|
emitter.emit(GYM_SET_CREATED);
|
||||||
navigate("Workouts", { reset: new Date().getTime() });
|
navigate("Exercises", { reset: new Date().getTime() });
|
||||||
};
|
};
|
||||||
|
|
||||||
const save = async () => {
|
const save = async () => {
|
||||||
|
@ -112,7 +112,7 @@ export default function EditWorkout() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StackHeader
|
<StackHeader
|
||||||
title={params.gymSet.name ? "Edit workout" : "Add workout"}
|
title={params.gymSet.name ? "Edit exercise" : "Add exercise"}
|
||||||
/>
|
/>
|
||||||
<View style={{ padding: PADDING, flex: 1 }}>
|
<View style={{ padding: PADDING, flex: 1 }}>
|
||||||
<ScrollView style={{ flex: 1 }}>
|
<ScrollView style={{ flex: 1 }}>
|
||||||
|
@ -143,7 +143,7 @@ export default function EditWorkout() {
|
||||||
if (fixed.length !== newSets.length)
|
if (fixed.length !== newSets.length)
|
||||||
toast("Sets must be a number");
|
toast("Sets must be a number");
|
||||||
}}
|
}}
|
||||||
label="Sets per workout"
|
label="Sets per exercise"
|
||||||
keyboardType="numeric"
|
keyboardType="numeric"
|
||||||
onSubmitEditing={() => minutesRef.current?.focus()}
|
onSubmitEditing={() => minutesRef.current?.focus()}
|
||||||
/>
|
/>
|
|
@ -20,10 +20,11 @@ import { GYM_SET_CREATED } from "./gym-set";
|
||||||
import Settings from "./settings";
|
import Settings from "./settings";
|
||||||
import StackHeader from "./StackHeader";
|
import StackHeader from "./StackHeader";
|
||||||
import { toast } from "./toast";
|
import { toast } from "./toast";
|
||||||
import { WorkoutsPageParams } from "./WorkoutsPage";
|
import { ExercisesPageParams } from "./ExercisesPage";
|
||||||
|
|
||||||
export default function EditWorkouts() {
|
export default function EditExercises() {
|
||||||
const { params } = useRoute<RouteProp<WorkoutsPageParams, "EditWorkouts">>();
|
const { params } =
|
||||||
|
useRoute<RouteProp<ExercisesPageParams, "EditExercises">>();
|
||||||
const [removeImage, setRemoveImage] = useState(false);
|
const [removeImage, setRemoveImage] = useState(false);
|
||||||
const [showRemove, setShowRemove] = useState(false);
|
const [showRemove, setShowRemove] = useState(false);
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
|
@ -37,7 +38,7 @@ export default function EditWorkouts() {
|
||||||
const [oldSeconds, setOldSeconds] = useState("");
|
const [oldSeconds, setOldSeconds] = useState("");
|
||||||
const [sets, setSets] = useState("");
|
const [sets, setSets] = useState("");
|
||||||
const [oldSets, setOldSets] = useState("");
|
const [oldSets, setOldSets] = useState("");
|
||||||
const navigation = useNavigation<NavigationProp<WorkoutsPageParams>>();
|
const navigation = useNavigation<NavigationProp<ExercisesPageParams>>();
|
||||||
const setsRef = useRef<TextInput>(null);
|
const setsRef = useRef<TextInput>(null);
|
||||||
const stepsRef = useRef<TextInput>(null);
|
const stepsRef = useRef<TextInput>(null);
|
||||||
const minutesRef = useRef<TextInput>(null);
|
const minutesRef = useRef<TextInput>(null);
|
||||||
|
@ -82,12 +83,12 @@ export default function EditWorkouts() {
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.update()
|
.update()
|
||||||
.set({
|
.set({
|
||||||
workouts: () => `REPLACE(workouts, '${oldName}', '${name}')`,
|
exercises: () => `REPLACE(exercises, '${oldName}', '${name}')`,
|
||||||
})
|
})
|
||||||
.where("workouts LIKE :name", { name: `%${oldName}%` })
|
.where("exercises LIKE :name", { name: `%${oldName}%` })
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
navigation.navigate("WorkoutList", { clearNames: true });
|
navigation.navigate("ExerciseList", { clearNames: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeImage = useCallback(async () => {
|
const changeImage = useCallback(async () => {
|
||||||
|
@ -111,7 +112,7 @@ export default function EditWorkouts() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StackHeader title={`Edit ${params.names.length} workouts`} />
|
<StackHeader title={`Edit ${params.names.length} exercises`} />
|
||||||
<View style={{ padding: PADDING, flex: 1 }}>
|
<View style={{ padding: PADDING, flex: 1 }}>
|
||||||
<ScrollView style={{ flex: 1 }}>
|
<ScrollView style={{ flex: 1 }}>
|
||||||
<AppInput
|
<AppInput
|
52
EditPlan.tsx
52
EditPlan.tsx
|
@ -32,8 +32,8 @@ export default function EditPlan() {
|
||||||
const [days, setDays] = useState<string[]>(
|
const [days, setDays] = useState<string[]>(
|
||||||
plan.days ? plan.days.split(",") : []
|
plan.days ? plan.days.split(",") : []
|
||||||
);
|
);
|
||||||
const [workouts, setWorkouts] = useState<string[]>(
|
const [exercises, setExercises] = useState<string[]>(
|
||||||
plan.workouts ? plan.workouts.split(",") : []
|
plan.exercises ? plan.exercises.split(",") : []
|
||||||
);
|
);
|
||||||
const [names, setNames] = useState<string[]>([]);
|
const [names, setNames] = useState<string[]>([]);
|
||||||
const { navigate: drawerNavigate } =
|
const { navigate: drawerNavigate } =
|
||||||
|
@ -56,27 +56,27 @@ export default function EditPlan() {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const save = useCallback(async () => {
|
const save = useCallback(async () => {
|
||||||
console.log(`${EditPlan.name}.save`, { days, workouts, plan });
|
console.log(`${EditPlan.name}.save`, { days, exercises, plan });
|
||||||
if (!days || !workouts) return;
|
if (!days || !exercises) return;
|
||||||
const newWorkouts = workouts.filter((workout) => workout).join(",");
|
const newExercises = exercises.filter((exercise) => exercise).join(",");
|
||||||
const newDays = days.filter((day) => day).join(",");
|
const newDays = days.filter((day) => day).join(",");
|
||||||
await planRepo.save({
|
await planRepo.save({
|
||||||
title: title,
|
title: title,
|
||||||
days: newDays,
|
days: newDays,
|
||||||
workouts: newWorkouts,
|
exercises: newExercises,
|
||||||
id: plan.id,
|
id: plan.id,
|
||||||
});
|
});
|
||||||
}, [title, days, workouts, plan]);
|
}, [title, days, exercises, plan]);
|
||||||
|
|
||||||
const toggleWorkout = useCallback(
|
const toggleExercise = useCallback(
|
||||||
(on: boolean, name: string) => {
|
(on: boolean, name: string) => {
|
||||||
if (on) {
|
if (on) {
|
||||||
setWorkouts([...workouts, name]);
|
setExercises([...exercises, name]);
|
||||||
} else {
|
} else {
|
||||||
setWorkouts(workouts.filter((workout) => workout !== name));
|
setExercises(exercises.filter((exercise) => exercise !== name));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[setWorkouts, workouts]
|
[setExercises, exercises]
|
||||||
);
|
);
|
||||||
|
|
||||||
const toggleDay = useCallback(
|
const toggleDay = useCallback(
|
||||||
|
@ -99,32 +99,32 @@ export default function EditPlan() {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderWorkout = ({
|
const renderExercise = ({
|
||||||
item,
|
item,
|
||||||
drag,
|
drag,
|
||||||
}: ReorderableListRenderItemInfo<string>) => (
|
}: ReorderableListRenderItemInfo<string>) => (
|
||||||
<Pressable
|
<Pressable
|
||||||
onLongPress={drag}
|
onLongPress={drag}
|
||||||
onPress={() => toggleWorkout(!workouts.includes(item), item)}
|
onPress={() => toggleExercise(!exercises.includes(item), item)}
|
||||||
style={{ flexDirection: "row", alignItems: "center" }}
|
style={{ flexDirection: "row", alignItems: "center" }}
|
||||||
>
|
>
|
||||||
<PaperSwitch
|
<PaperSwitch
|
||||||
value={workouts.includes(item)}
|
value={exercises.includes(item)}
|
||||||
style={{ marginRight: MARGIN }}
|
style={{ marginRight: MARGIN }}
|
||||||
onValueChange={(value) => toggleWorkout(value, item)}
|
onValueChange={(value) => toggleExercise(value, item)}
|
||||||
/>
|
/>
|
||||||
<Text>{item}</Text>
|
<Text>{item}</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
);
|
);
|
||||||
|
|
||||||
const reorderWorkout = (from: number, to: number) => {
|
const reorderExercise = (from: number, to: number) => {
|
||||||
const newNames = [...names];
|
const newNames = [...names];
|
||||||
const copy = newNames[from];
|
const copy = newNames[from];
|
||||||
newNames[from] = newNames[to];
|
newNames[from] = newNames[to];
|
||||||
newNames[to] = copy;
|
newNames[to] = copy;
|
||||||
const newWorkouts = newNames.filter((name) => workouts.includes(name));
|
const newExercises = newNames.filter((name) => exercises.includes(name));
|
||||||
console.log({ newWorkouts });
|
console.log({ newExercises });
|
||||||
setWorkouts(newWorkouts);
|
setExercises(newExercises);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -140,10 +140,10 @@ export default function EditPlan() {
|
||||||
where: { id: plan.id },
|
where: { id: plan.id },
|
||||||
});
|
});
|
||||||
let first = await setRepo.findOne({
|
let first = await setRepo.findOne({
|
||||||
where: { name: workouts[0] },
|
where: { name: exercises[0] },
|
||||||
order: { created: "desc" },
|
order: { created: "desc" },
|
||||||
});
|
});
|
||||||
if (!first) first = { ...defaultSet, name: workouts[0] };
|
if (!first) first = { ...defaultSet, name: exercises[0] };
|
||||||
delete first.id;
|
delete first.id;
|
||||||
stackNavigate("StartPlan", { plan: newPlan, first });
|
stackNavigate("StartPlan", { plan: newPlan, first });
|
||||||
}}
|
}}
|
||||||
|
@ -161,18 +161,18 @@ export default function EditPlan() {
|
||||||
<Text style={styles.title}>Days</Text>
|
<Text style={styles.title}>Days</Text>
|
||||||
{DAYS.map((day) => renderDay(day))}
|
{DAYS.map((day) => renderDay(day))}
|
||||||
|
|
||||||
<Text style={[styles.title, { marginTop: MARGIN }]}>Workouts</Text>
|
<Text style={[styles.title, { marginTop: MARGIN }]}>Exercises</Text>
|
||||||
{names.length === 0 ? (
|
{names.length === 0 ? (
|
||||||
<View>
|
<View>
|
||||||
<Text>No workouts found.</Text>
|
<Text>No exercises found.</Text>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
<ReorderableList
|
<ReorderableList
|
||||||
data={names}
|
data={names}
|
||||||
onReorder={({ fromIndex, toIndex }) =>
|
onReorder={({ fromIndex, toIndex }) =>
|
||||||
reorderWorkout(fromIndex, toIndex)
|
reorderExercise(fromIndex, toIndex)
|
||||||
}
|
}
|
||||||
renderItem={renderWorkout}
|
renderItem={renderExercise}
|
||||||
keyExtractor={(item) => item}
|
keyExtractor={(item) => item}
|
||||||
dragScale={1.025}
|
dragScale={1.025}
|
||||||
style={{
|
style={{
|
||||||
|
@ -183,7 +183,7 @@ export default function EditPlan() {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
disabled={workouts.length === 0 && days.length === 0}
|
disabled={exercises.length === 0 && days.length === 0}
|
||||||
style={styles.button}
|
style={styles.button}
|
||||||
mode="outlined"
|
mode="outlined"
|
||||||
icon="content-save"
|
icon="content-save"
|
||||||
|
|
|
@ -6,9 +6,9 @@ import { DARK_RIPPLE } from "./constants";
|
||||||
import { LIGHT_RIPPLE } from "./constants";
|
import { LIGHT_RIPPLE } from "./constants";
|
||||||
import GymSet from "./gym-set";
|
import GymSet from "./gym-set";
|
||||||
import useDark from "./use-dark";
|
import useDark from "./use-dark";
|
||||||
import { WorkoutsPageParams } from "./WorkoutsPage";
|
import { ExercisesPageParams } from "./ExercisesPage";
|
||||||
|
|
||||||
export default function WorkoutItem({
|
export default function ExerciseItem({
|
||||||
item,
|
item,
|
||||||
setNames,
|
setNames,
|
||||||
names,
|
names,
|
||||||
|
@ -21,7 +21,7 @@ export default function WorkoutItem({
|
||||||
names: string[];
|
names: string[];
|
||||||
alarm: boolean;
|
alarm: boolean;
|
||||||
}) {
|
}) {
|
||||||
const navigation = useNavigation<NavigationProp<WorkoutsPageParams>>();
|
const navigation = useNavigation<NavigationProp<ExercisesPageParams>>();
|
||||||
const dark = useDark();
|
const dark = useDark();
|
||||||
|
|
||||||
const description = useMemo(() => {
|
const description = useMemo(() => {
|
||||||
|
@ -52,7 +52,7 @@ export default function WorkoutItem({
|
||||||
const press = () => {
|
const press = () => {
|
||||||
console.log({ names });
|
console.log({ names });
|
||||||
if (names.length === 0)
|
if (names.length === 0)
|
||||||
return navigation.navigate("EditWorkout", { gymSet: item });
|
return navigation.navigate("EditExercise", { gymSet: item });
|
||||||
const removing = names.find((name) => name === item.name);
|
const removing = names.find((name) => name === item.name);
|
||||||
if (removing) setNames(names.filter((name) => name !== item.name));
|
if (removing) setNames(names.filter((name) => name !== item.name));
|
||||||
else setNames([...names, item.name]);
|
else setNames([...names, item.name]);
|
|
@ -17,12 +17,12 @@ import ListMenu from "./ListMenu";
|
||||||
import Page from "./Page";
|
import Page from "./Page";
|
||||||
import SetList from "./SetList";
|
import SetList from "./SetList";
|
||||||
import Settings, { SETTINGS } from "./settings";
|
import Settings, { SETTINGS } from "./settings";
|
||||||
import WorkoutItem from "./WorkoutItem";
|
import ExerciseItem from "./ExerciseItem";
|
||||||
import { DrawerParams } from "./drawer-param-list";
|
import { DrawerParams } from "./drawer-param-list";
|
||||||
import { StackParams } from "./AppStack";
|
import { StackParams } from "./AppStack";
|
||||||
|
|
||||||
export default function WorkoutList() {
|
export default function ExerciseList() {
|
||||||
const [workouts, setWorkouts] = useState<GymSet[]>();
|
const [exercises, setExercises] = useState<GymSet[]>();
|
||||||
const [offset, setOffset] = useState(0);
|
const [offset, setOffset] = useState(0);
|
||||||
const [term, setTerm] = useState("");
|
const [term, setTerm] = useState("");
|
||||||
const [end, setEnd] = useState(false);
|
const [end, setEnd] = useState(false);
|
||||||
|
@ -30,20 +30,20 @@ export default function WorkoutList() {
|
||||||
const [names, setNames] = useState<string[]>([]);
|
const [names, setNames] = useState<string[]>([]);
|
||||||
const [refreshing, setRefreshing] = useState(false);
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
const navigation = useNavigation<NavigationProp<StackParams>>();
|
const navigation = useNavigation<NavigationProp<StackParams>>();
|
||||||
const { params } = useRoute<RouteProp<DrawerParams, "Workouts">>();
|
const { params } = useRoute<RouteProp<DrawerParams, "Exercises">>();
|
||||||
|
|
||||||
const update = (newWorkout: GymSet) => {
|
const update = (newExercise: GymSet) => {
|
||||||
console.log(`${WorkoutList.name}.update:`, newWorkout);
|
console.log(`${ExerciseList.name}.update:`, newExercise);
|
||||||
if (!workouts) return;
|
if (!exercises) return;
|
||||||
const newWorkouts = workouts.map((workout) =>
|
const newExercises = exercises.map((exercise) =>
|
||||||
workout.name === newWorkout.name ? newWorkout : workout
|
exercise.name === newExercise.name ? newExercise : exercise
|
||||||
);
|
);
|
||||||
setWorkouts(newWorkouts);
|
setExercises(newExercises);
|
||||||
};
|
};
|
||||||
|
|
||||||
const reset = async (value: string) => {
|
const reset = async (value: string) => {
|
||||||
console.log(`${WorkoutList.name}.reset`, value);
|
console.log(`${ExerciseList.name}.reset`, value);
|
||||||
const newWorkouts = await setRepo
|
const newExercises = await setRepo
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.select()
|
.select()
|
||||||
.where("name LIKE :name", { name: `%${value.trim()}%` })
|
.where("name LIKE :name", { name: `%${value.trim()}%` })
|
||||||
|
@ -52,9 +52,9 @@ export default function WorkoutList() {
|
||||||
.limit(LIMIT)
|
.limit(LIMIT)
|
||||||
.getMany();
|
.getMany();
|
||||||
setOffset(0);
|
setOffset(0);
|
||||||
console.log(`${WorkoutList.name}.reset`, { length: newWorkouts.length });
|
console.log(`${ExerciseList.name}.reset`, { length: newExercises.length });
|
||||||
setEnd(newWorkouts.length < LIMIT);
|
setEnd(newExercises.length < LIMIT);
|
||||||
setWorkouts(newWorkouts);
|
setExercises(newExercises);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -66,7 +66,7 @@ export default function WorkoutList() {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(`${WorkoutList.name}.useEffect`, params);
|
console.log(`${ExerciseList.name}.useEffect`, params);
|
||||||
if (!params) reset("");
|
if (!params) reset("");
|
||||||
if (params?.search) search(params.search);
|
if (params?.search) search(params.search);
|
||||||
else if (params?.update) update(params.update);
|
else if (params?.update) update(params.update);
|
||||||
|
@ -77,7 +77,7 @@ export default function WorkoutList() {
|
||||||
|
|
||||||
const renderItem = useCallback(
|
const renderItem = useCallback(
|
||||||
({ item }: { item: GymSet }) => (
|
({ item }: { item: GymSet }) => (
|
||||||
<WorkoutItem
|
<ExerciseItem
|
||||||
images={settings?.images}
|
images={settings?.images}
|
||||||
alarm={settings?.alarm}
|
alarm={settings?.alarm}
|
||||||
item={item}
|
item={item}
|
||||||
|
@ -98,7 +98,7 @@ export default function WorkoutList() {
|
||||||
});
|
});
|
||||||
if (end) return;
|
if (end) return;
|
||||||
const newOffset = offset + LIMIT;
|
const newOffset = offset + LIMIT;
|
||||||
const newWorkouts = await setRepo
|
const newExercises = await setRepo
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.select()
|
.select()
|
||||||
.where("name LIKE :name", { name: `%${term.trim()}%` })
|
.where("name LIKE :name", { name: `%${term.trim()}%` })
|
||||||
|
@ -107,15 +107,15 @@ export default function WorkoutList() {
|
||||||
.limit(LIMIT)
|
.limit(LIMIT)
|
||||||
.offset(newOffset)
|
.offset(newOffset)
|
||||||
.getMany();
|
.getMany();
|
||||||
if (newWorkouts.length === 0) return setEnd(true);
|
if (newExercises.length === 0) return setEnd(true);
|
||||||
if (!workouts) return;
|
if (!exercises) return;
|
||||||
setWorkouts([...workouts, ...newWorkouts]);
|
setExercises([...exercises, ...newExercises]);
|
||||||
if (newWorkouts.length < LIMIT) return setEnd(true);
|
if (newExercises.length < LIMIT) return setEnd(true);
|
||||||
setOffset(newOffset);
|
setOffset(newOffset);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAdd = useCallback(async () => {
|
const onAdd = useCallback(async () => {
|
||||||
navigation.navigate("EditWorkout", {
|
navigation.navigate("EditExercise", {
|
||||||
gymSet: new GymSet(),
|
gymSet: new GymSet(),
|
||||||
});
|
});
|
||||||
}, [navigation]);
|
}, [navigation]);
|
||||||
|
@ -137,19 +137,19 @@ export default function WorkoutList() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const select = () => {
|
const select = () => {
|
||||||
if (!workouts) return;
|
if (!exercises) return;
|
||||||
if (names.length === workouts.length) return setNames([]);
|
if (names.length === exercises.length) return setNames([]);
|
||||||
setNames(workouts.map((workout) => workout.name));
|
setNames(exercises.map((exercise) => exercise.name));
|
||||||
};
|
};
|
||||||
|
|
||||||
const edit = () => {
|
const edit = () => {
|
||||||
navigation.navigate("EditWorkouts", { names });
|
navigation.navigate("EditExercises", { names });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DrawerHeader
|
<DrawerHeader
|
||||||
name={names.length > 0 ? `${names.length} selected` : "Workouts"}
|
name={names.length > 0 ? `${names.length} selected` : "Exercises"}
|
||||||
>
|
>
|
||||||
<ListMenu
|
<ListMenu
|
||||||
onClear={clear}
|
onClear={clear}
|
||||||
|
@ -160,14 +160,14 @@ export default function WorkoutList() {
|
||||||
/>
|
/>
|
||||||
</DrawerHeader>
|
</DrawerHeader>
|
||||||
<Page onAdd={onAdd} term={term} search={search}>
|
<Page onAdd={onAdd} term={term} search={search}>
|
||||||
{workouts?.length === 0 ? (
|
{exercises?.length === 0 ? (
|
||||||
<List.Item
|
<List.Item
|
||||||
title="No workouts yet."
|
title="No exercises yet."
|
||||||
description="A workout is something you do at the gym. E.g. Deadlifts"
|
description="An exercise is something you do at the gym. E.g. Deadlifts"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<FlatList
|
<FlatList
|
||||||
data={workouts}
|
data={exercises}
|
||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
keyExtractor={(w) => w.name}
|
keyExtractor={(w) => w.name}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { createStackNavigator } from "@react-navigation/stack";
|
||||||
|
import EditExercise from "./EditExercise";
|
||||||
|
import EditExercises from "./EditExercises";
|
||||||
|
import GymSet from "./gym-set";
|
||||||
|
import ExerciseList from "./ExerciseList";
|
||||||
|
|
||||||
|
export type ExercisesPageParams = {
|
||||||
|
ExerciseList: {
|
||||||
|
clearNames?: boolean;
|
||||||
|
search?: string;
|
||||||
|
update?: GymSet;
|
||||||
|
reset?: number;
|
||||||
|
};
|
||||||
|
EditExercise: {
|
||||||
|
gymSet: GymSet;
|
||||||
|
};
|
||||||
|
EditExercises: {
|
||||||
|
names: string[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const Stack = createStackNavigator<ExercisesPageParams>();
|
||||||
|
|
||||||
|
export default function ExercisesPage() {
|
||||||
|
return (
|
||||||
|
<Stack.Navigator
|
||||||
|
screenOptions={{ headerShown: false, animationEnabled: false }}
|
||||||
|
>
|
||||||
|
<Stack.Screen name="ExerciseList" component={ExerciseList} />
|
||||||
|
<Stack.Screen name="EditExercise" component={EditExercise} />
|
||||||
|
<Stack.Screen name="EditExercises" component={EditExercises} />
|
||||||
|
</Stack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
10
PlanItem.tsx
10
PlanItem.tsx
|
@ -36,12 +36,12 @@ export default function PlanItem({
|
||||||
);
|
);
|
||||||
|
|
||||||
const start = useCallback(async () => {
|
const start = useCallback(async () => {
|
||||||
const workout = item.workouts.split(",")[0];
|
const exercise = item.exercises.split(",")[0];
|
||||||
let first = await setRepo.findOne({
|
let first = await setRepo.findOne({
|
||||||
where: { name: workout },
|
where: { name: exercise },
|
||||||
order: { created: "desc" },
|
order: { created: "desc" },
|
||||||
});
|
});
|
||||||
if (!first) first = { ...defaultSet, name: workout };
|
if (!first) first = { ...defaultSet, name: exercise };
|
||||||
delete first.id;
|
delete first.id;
|
||||||
if (ids.length === 0) {
|
if (ids.length === 0) {
|
||||||
return navigation.navigate("StartPlan", { plan: item, first });
|
return navigation.navigate("StartPlan", { plan: item, first });
|
||||||
|
@ -85,8 +85,8 @@ export default function PlanItem({
|
||||||
);
|
);
|
||||||
|
|
||||||
const description = useMemo(
|
const description = useMemo(
|
||||||
() => (item.title ? currentDays : item.workouts.replace(/,/g, ", ")),
|
() => (item.title ? currentDays : item.exercises.replace(/,/g, ", ")),
|
||||||
[item.title, currentDays, item.workouts]
|
[item.title, currentDays, item.exercises]
|
||||||
);
|
);
|
||||||
|
|
||||||
const backgroundColor = useMemo(() => {
|
const backgroundColor = useMemo(() => {
|
||||||
|
|
|
@ -28,7 +28,7 @@ export default function PlanList() {
|
||||||
where: [
|
where: [
|
||||||
{ title: Like(`%${value.trim()}%`) },
|
{ title: Like(`%${value.trim()}%`) },
|
||||||
{ days: Like(`%${value.trim()}%`) },
|
{ days: Like(`%${value.trim()}%`) },
|
||||||
{ workouts: Like(`%${value.trim()}%`) },
|
{ exercises: Like(`%${value.trim()}%`) },
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.then(setPlans);
|
.then(setPlans);
|
||||||
|
@ -57,7 +57,7 @@ export default function PlanList() {
|
||||||
|
|
||||||
const onAdd = () =>
|
const onAdd = () =>
|
||||||
navigation.navigate("EditPlan", {
|
navigation.navigate("EditPlan", {
|
||||||
plan: { title: "", days: "", workouts: "" },
|
plan: { title: "", days: "", exercises: "" },
|
||||||
});
|
});
|
||||||
|
|
||||||
const edit = useCallback(async () => {
|
const edit = useCallback(async () => {
|
||||||
|
@ -107,7 +107,7 @@ export default function PlanList() {
|
||||||
{plans?.length === 0 ? (
|
{plans?.length === 0 ? (
|
||||||
<List.Item
|
<List.Item
|
||||||
title="No plans yet"
|
title="No plans yet"
|
||||||
description="A plan is a list of workouts for certain days."
|
description="A plan is a list of exercises for certain days."
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<FlatList
|
<FlatList
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { NavigationProp, useNavigation } from "@react-navigation/native";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { NativeModules, ScrollView, View } from "react-native";
|
import { NativeModules, ScrollView } from "react-native";
|
||||||
import DocumentPicker from "react-native-document-picker";
|
import DocumentPicker from "react-native-document-picker";
|
||||||
import { Dirs, FileSystem } from "react-native-file-access";
|
import { Dirs, FileSystem } from "react-native-file-access";
|
||||||
import { Button } from "react-native-paper";
|
import { Button } from "react-native-paper";
|
||||||
|
@ -145,8 +145,8 @@ export default function SettingsPage() {
|
||||||
else toast("Hid unit option for sets.");
|
else toast("Hid unit option for sets.");
|
||||||
return;
|
return;
|
||||||
case "steps":
|
case "steps":
|
||||||
if (value) toast("Show steps for a workout.");
|
if (value) toast("Show steps for exercises.");
|
||||||
else toast("Hid steps for workouts.");
|
else toast("Hid steps for exercises.");
|
||||||
return;
|
return;
|
||||||
case "showDate":
|
case "showDate":
|
||||||
if (value) toast("Show date for sets.");
|
if (value) toast("Show date for sets.");
|
||||||
|
|
|
@ -34,7 +34,7 @@ export default function StartPlan() {
|
||||||
const weightRef = useRef<TextInput>(null);
|
const weightRef = useRef<TextInput>(null);
|
||||||
const repsRef = useRef<TextInput>(null);
|
const repsRef = useRef<TextInput>(null);
|
||||||
const unitRef = useRef<TextInput>(null);
|
const unitRef = useRef<TextInput>(null);
|
||||||
const workouts = useMemo(() => params.plan.workouts.split(","), [params]);
|
const exercises = useMemo(() => params.plan.exercises.split(","), [params]);
|
||||||
const navigation = useNavigation<NavigationProp<StackParams>>();
|
const navigation = useNavigation<NavigationProp<StackParams>>();
|
||||||
|
|
||||||
const [selection, setSelection] = useState({
|
const [selection, setSelection] = useState({
|
||||||
|
@ -43,33 +43,33 @@ export default function StartPlan() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const refresh = useCallback(async () => {
|
const refresh = useCallback(async () => {
|
||||||
const questions = workouts
|
const questions = exercises
|
||||||
.map((workout, index) => `('${workout}',${index})`)
|
.map((exercise, index) => `('${exercise}',${index})`)
|
||||||
.join(",");
|
.join(",");
|
||||||
const select = `
|
const select = `
|
||||||
SELECT workouts.name, COUNT(sets.id) as total, sets.sets
|
SELECT exercises.name, COUNT(sets.id) as total, sets.sets
|
||||||
FROM (select 0 as name, 0 as sequence union values ${questions}) as workouts
|
FROM (select 0 as name, 0 as sequence union values ${questions}) as exercises
|
||||||
LEFT JOIN sets ON sets.name = workouts.name
|
LEFT JOIN sets ON sets.name = exercises.name
|
||||||
AND sets.created LIKE STRFTIME('%Y-%m-%d%%', 'now', 'localtime')
|
AND sets.created LIKE STRFTIME('%Y-%m-%d%%', 'now', 'localtime')
|
||||||
AND NOT sets.hidden
|
AND NOT sets.hidden
|
||||||
GROUP BY workouts.name
|
GROUP BY exercises.name
|
||||||
ORDER BY workouts.sequence
|
ORDER BY exercises.sequence
|
||||||
LIMIT -1
|
LIMIT -1
|
||||||
OFFSET 1
|
OFFSET 1
|
||||||
`;
|
`;
|
||||||
const newCounts = await AppDataSource.manager.query(select);
|
const newCounts = await AppDataSource.manager.query(select);
|
||||||
console.log(`${StartPlan.name}.focus:`, { newCounts });
|
console.log(`${StartPlan.name}.focus:`, { newCounts });
|
||||||
setCounts(newCounts);
|
setCounts(newCounts);
|
||||||
}, [workouts]);
|
}, [exercises]);
|
||||||
|
|
||||||
const select = useCallback(
|
const select = useCallback(
|
||||||
async (index: number, newCounts?: CountMany[]) => {
|
async (index: number, newCounts?: CountMany[]) => {
|
||||||
setSelected(index);
|
setSelected(index);
|
||||||
if (!counts && !newCounts) return;
|
if (!counts && !newCounts) return;
|
||||||
const workout = counts ? counts[index] : newCounts[index];
|
const exercise = counts ? counts[index] : newCounts[index];
|
||||||
console.log(`${StartPlan.name}.next:`, { workout });
|
console.log(`${StartPlan.name}.next:`, { exercise });
|
||||||
const last = await setRepo.findOne({
|
const last = await setRepo.findOne({
|
||||||
where: { name: workout.name },
|
where: { name: exercise.name },
|
||||||
order: { created: "desc" },
|
order: { created: "desc" },
|
||||||
});
|
});
|
||||||
console.log({ last });
|
console.log({ last });
|
||||||
|
@ -92,8 +92,8 @@ export default function StartPlan() {
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
const now = await getNow();
|
const now = await getNow();
|
||||||
const workout = counts[selected];
|
const exercise = counts[selected];
|
||||||
const best = await getBestSet(workout.name);
|
const best = await getBestSet(exercise.name);
|
||||||
delete best.id;
|
delete best.id;
|
||||||
const newSet: GymSet = {
|
const newSet: GymSet = {
|
||||||
...best,
|
...best,
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import { createStackNavigator } from "@react-navigation/stack";
|
|
||||||
import EditWorkout from "./EditWorkout";
|
|
||||||
import EditWorkouts from "./EditWorkouts";
|
|
||||||
import GymSet from "./gym-set";
|
|
||||||
import WorkoutList from "./WorkoutList";
|
|
||||||
|
|
||||||
export type WorkoutsPageParams = {
|
|
||||||
WorkoutList: {
|
|
||||||
clearNames?: boolean;
|
|
||||||
search?: string;
|
|
||||||
update?: GymSet;
|
|
||||||
reset?: number;
|
|
||||||
};
|
|
||||||
EditWorkout: {
|
|
||||||
gymSet: GymSet;
|
|
||||||
};
|
|
||||||
EditWorkouts: {
|
|
||||||
names: string[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const Stack = createStackNavigator<WorkoutsPageParams>();
|
|
||||||
|
|
||||||
export default function WorkoutsPage() {
|
|
||||||
return (
|
|
||||||
<Stack.Navigator
|
|
||||||
screenOptions={{ headerShown: false, animationEnabled: false }}
|
|
||||||
>
|
|
||||||
<Stack.Screen name="WorkoutList" component={WorkoutList} />
|
|
||||||
<Stack.Screen name="EditWorkout" component={EditWorkout} />
|
|
||||||
<Stack.Screen name="EditWorkouts" component={EditWorkouts} />
|
|
||||||
</Stack.Navigator>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -30,6 +30,7 @@ import { weight1697766633971 } from "./migrations/1697766633971-weight";
|
||||||
import { Plan } from "./plan";
|
import { Plan } from "./plan";
|
||||||
import Settings from "./settings";
|
import Settings from "./settings";
|
||||||
import Weight from "./weight";
|
import Weight from "./weight";
|
||||||
|
import { exercises1699508495726 } from "./migrations/1699508495726-exercises";
|
||||||
|
|
||||||
export const AppDataSource = new DataSource({
|
export const AppDataSource = new DataSource({
|
||||||
type: "react-native",
|
type: "react-native",
|
||||||
|
@ -66,5 +67,6 @@ export const AppDataSource = new DataSource({
|
||||||
addBackup1678334268359,
|
addBackup1678334268359,
|
||||||
planTitle1692654882408,
|
planTitle1692654882408,
|
||||||
weight1697766633971,
|
weight1697766633971,
|
||||||
|
exercises1699508495726,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ export type DrawerParams = {
|
||||||
Settings: {};
|
Settings: {};
|
||||||
Graphs: {};
|
Graphs: {};
|
||||||
Plans: {};
|
Plans: {};
|
||||||
Workouts: {
|
Exercises: {
|
||||||
clearNames?: boolean;
|
clearNames?: boolean;
|
||||||
search?: string;
|
search?: string;
|
||||||
update?: GymSet;
|
update?: GymSet;
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class exercises1699508495726 implements MigrationInterface {
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE plans ADD COLUMN exercises TEXT`);
|
||||||
|
await queryRunner.query(`UPDATE plans SET exercises = workouts`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {}
|
||||||
|
}
|
Loading…
Reference in New Issue