Massive/EditPlan.tsx

236 lines
6.4 KiB
TypeScript
Raw Permalink Normal View History

2022-07-11 00:28:30 +00:00
import {
NavigationProp,
2022-07-11 00:28:30 +00:00
RouteProp,
useNavigation,
useRoute,
} from "@react-navigation/native";
import React, { useCallback, useEffect, useState } from "react";
import {
FlatList,
Pressable,
ScrollView,
StyleSheet,
View,
} from "react-native";
import {
Button,
IconButton,
Switch as PaperSwitch,
Text,
} from "react-native-paper";
import AppInput from "./AppInput";
import { StackParams } from "./AppStack";
import PrimaryButton from "./PrimaryButton";
import StackHeader from "./StackHeader";
import Switch from "./Switch";
import { MARGIN, PADDING } from "./constants";
2023-11-06 01:27:27 +00:00
import { DAYS } from "./days";
import { planRepo, setRepo } from "./db";
import { DrawerParams } from "./drawer-params";
2023-11-13 05:13:23 +00:00
import GymSet, { defaultSet } from "./gym-set";
import { toast } from "./toast";
2022-07-06 05:40:53 +00:00
2022-07-11 00:28:30 +00:00
export default function EditPlan() {
const { params } = useRoute<RouteProp<StackParams, "EditPlan">>();
const { plan } = params;
2023-08-21 12:25:29 +00:00
const [title, setTitle] = useState<string>(plan?.title);
const [names, setNames] = useState<string[]>();
2023-11-14 00:56:50 +00:00
2022-09-18 06:45:05 +00:00
const [days, setDays] = useState<string[]>(
plan.days ? plan.days.split(",") : []
);
2023-11-14 00:56:50 +00:00
const [exercises, setExercises] = useState<string[]>(
plan.exercises ? plan.exercises.split(",") : []
);
2023-11-14 00:56:50 +00:00
const { navigate: drawerNavigate } =
useNavigation<NavigationProp<DrawerParams>>();
const { navigate: stackNavigate } =
useNavigation<NavigationProp<StackParams>>();
2022-07-11 00:28:30 +00:00
2022-07-06 05:40:53 +00:00
useEffect(() => {
setRepo
.createQueryBuilder()
.select("name")
.distinct(true)
.orderBy("name")
.getRawMany()
2023-06-27 03:16:59 +00:00
.then((values) => {
const newNames = values.map((value) => value.name);
console.log(EditPlan.name, { newNames });
setNames(newNames);
});
}, []);
2022-07-06 05:40:53 +00:00
2022-07-09 23:51:52 +00:00
const save = useCallback(async () => {
console.log(`${EditPlan.name}.save`, { days, exercises, plan });
if (!days || !exercises) return;
const newExercises = exercises.filter((exercise) => exercise).join(",");
const newDays = days.filter((day) => day).join(",");
const saved = await planRepo.save({
2023-08-21 12:25:29 +00:00
title: title,
days: newDays,
exercises: newExercises,
2023-08-21 12:25:29 +00:00
id: plan.id,
});
if (saved.id === 1) toast("Tap your plan again to begin using it");
}, [title, days, exercises, plan]);
2022-07-06 05:40:53 +00:00
const toggleExercise = useCallback(
2022-07-09 23:51:52 +00:00
(on: boolean, name: string) => {
if (on) {
setExercises([...exercises, name]);
2022-07-09 23:51:52 +00:00
} else {
setExercises(exercises.filter((exercise) => exercise !== name));
2022-07-09 23:51:52 +00:00
}
},
[setExercises, exercises]
);
2022-07-06 06:26:43 +00:00
2022-07-09 23:51:52 +00:00
const toggleDay = useCallback(
(on: boolean, day: string) => {
if (on) {
setDays([...days, day]);
2022-07-09 23:51:52 +00:00
} else {
setDays(days.filter((d) => d !== day));
2022-07-09 23:51:52 +00:00
}
},
[setDays, days]
);
2022-07-06 05:40:53 +00:00
const renderDay = (day: string) => (
<Switch
key={day}
onChange={(value) => toggleDay(value, day)}
value={days.includes(day)}
title={day}
/>
);
const renderExercise = (name: string, index: number, movable: boolean) => (
<Pressable
onPress={() => toggleExercise(!exercises.includes(name), name)}
style={{ flexDirection: "row", alignItems: "center" }}
key={name}
>
<PaperSwitch
value={exercises.includes(name)}
style={{ marginRight: MARGIN }}
onValueChange={(value) => toggleExercise(value, name)}
/>
<Text>{name}</Text>
{movable && (
<>
<IconButton
icon="arrow-up"
style={{ marginLeft: "auto" }}
onPressIn={() => moveUp(index)}
/>
<IconButton icon="arrow-down" onPressIn={() => moveDown(index)} />
</>
)}
</Pressable>
);
const moveDown = (from: number) => {
if (from === exercises.length - 1) return;
const to = from + 1;
const newExercises = [...exercises];
const copy = newExercises[from];
newExercises[from] = newExercises[to];
newExercises[to] = copy;
setExercises(newExercises);
};
const moveUp = (from: number) => {
if (from === 0) return;
const to = from - 1;
const newExercises = [...exercises];
const copy = newExercises[from];
newExercises[from] = newExercises[to];
newExercises[to] = copy;
setExercises(newExercises);
};
2022-07-06 05:40:53 +00:00
return (
<>
2023-01-08 05:05:59 +00:00
<StackHeader
title={typeof plan.id === "number" ? "Edit plan" : "Add plan"}
2023-06-27 03:16:59 +00:00
>
{typeof plan.id === "number" && (
<IconButton
onPress={async () => {
await save();
const newPlan = await planRepo.findOne({
where: { id: plan.id },
});
2023-11-13 05:13:23 +00:00
let first: Partial<GymSet> = await setRepo.findOne({
where: { name: exercises[0] },
order: { created: "desc" },
});
if (!first) first = { ...defaultSet, name: exercises[0] };
delete first.id;
stackNavigate("StartPlan", { plan: newPlan, first });
}}
2023-10-19 05:28:56 +00:00
icon="play"
/>
)}
</StackHeader>
<ScrollView style={{ padding: PADDING, flex: 1 }}>
<AppInput
label="Title"
value={title}
2023-11-21 06:24:40 +00:00
placeholder={days.join(", ")}
onChangeText={(value) => setTitle(value)}
/>
<Text style={styles.title}>Days</Text>
{DAYS.map((day) => renderDay(day))}
<Text style={[styles.title, { marginTop: MARGIN }]}>Exercises</Text>
{exercises.map((exercise, index) =>
renderExercise(exercise, index, true)
)}
{names?.length === 0 && (
<>
<Text>No exercises yet.</Text>
<Button
onPress={() =>
stackNavigate("EditExercise", { gymSet: defaultSet })
}
style={{ alignSelf: "flex-start" }}
>
Add some?
</Button>
</>
)}
{names !== undefined &&
names
.filter((name) => !exercises.includes(name))
.map((name, index) => renderExercise(name, index, false))}
<View style={{ marginBottom: MARGIN }}></View>
</ScrollView>
<PrimaryButton
disabled={exercises.length === 0 && days.length === 0}
icon="content-save"
onPress={async () => {
await save();
drawerNavigate("Plans");
}}
style={{ margin: MARGIN }}
>
Save
</PrimaryButton>
</>
);
2022-07-06 05:40:53 +00:00
}
2022-07-07 04:17:55 +00:00
const styles = StyleSheet.create({
title: {
fontSize: 20,
marginBottom: MARGIN,
2022-07-07 04:17:55 +00:00
},
});