diff --git a/EditSet.tsx b/EditSet.tsx index 5a3712a..8fe39e2 100644 --- a/EditSet.tsx +++ b/EditSet.tsx @@ -1,5 +1,6 @@ import { DateTimePickerAndroid } from "@react-native-community/datetimepicker"; import { + NavigationProp, RouteProp, useFocusEffect, useNavigation, @@ -24,7 +25,7 @@ import { fixNumeric } from "./fix-numeric"; export default function EditSet() { const { params } = useRoute>(); const { set } = params; - const navigation = useNavigation(); + const { navigate } = useNavigation>(); const [settings, setSettings] = useState({} as Settings); const [name, setName] = useState(set.name); const [reps, setReps] = useState(set.reps?.toString()); @@ -63,20 +64,18 @@ export default function EditSet() { [settings] ); - const added = useCallback( - async (value: GymSet) => { - startTimer(value.name); - console.log(`${EditSet.name}.add`, { set: value }); - if (!settings.notify) return; - if ( - value.weight > set.weight || - (value.reps > set.reps && value.weight === set.weight) - ) { - toast("Great work King! That's a new record."); - } - }, - [startTimer, set, settings] - ); + const added = async (value: GymSet) => { + startTimer(value.name); + console.log(`${EditSet.name}.add`, { set: value }); + if (!settings.notify) return; + if ( + value.weight > set.weight || + (value.reps > set.reps && value.weight === set.weight) + ) { + toast("Great work King! That's a new record."); + } + navigate("Sets", { added: value.id }); + }; const handleSubmit = async () => { if (!name) return; @@ -104,8 +103,9 @@ export default function EditSet() { if (typeof set.id !== "number") newSet.created = await getNow(); const saved = await setRepo.save(newSet); - if (typeof set.id !== "number") added(saved); - navigation.goBack(); + if (typeof set.id !== "number") return added(saved); + if (createdDirty) navigate("Sets", { reset: saved.id }); + else navigate("Sets", { refresh: saved.id }); }; const changeImage = useCallback(async () => { diff --git a/SetList.tsx b/SetList.tsx index 178801f..d2c488c 100644 --- a/SetList.tsx +++ b/SetList.tsx @@ -1,9 +1,10 @@ import { NavigationProp, - useFocusEffect, + RouteProp, useNavigation, + useRoute, } from "@react-navigation/native"; -import { useCallback, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { FlatList } from "react-native"; import { List } from "react-native-paper"; import { Like } from "typeorm"; @@ -18,33 +19,77 @@ import SetItem from "./SetItem"; import Settings from "./settings"; export default function SetList() { + const [refreshing, setRefreshing] = useState(false); const [sets, setSets] = useState([]); const [offset, setOffset] = useState(0); - const [term, setTerm] = useState(""); const [end, setEnd] = useState(false); const [settings, setSettings] = useState(); const [ids, setIds] = useState([]); const navigation = useNavigation>(); + const { params } = useRoute>(); + const [term, setTerm] = useState(params?.search || ""); - const refresh = useCallback(async (value: string) => { - const newSets = await setRepo.find({ - where: { name: Like(`%${value.trim()}%`), hidden: 0 as any }, - take: LIMIT, - skip: 0, - order: { created: "DESC" }, - }); - console.log(`${SetList.name}.refresh:`, { value }); + const refresh = async ({ + value, + take, + skip, + }: { + value: string; + take: number; + skip: number; + }) => { + setRefreshing(true); + const newSets = await setRepo + .find({ + where: { name: Like(`%${value.trim()}%`), hidden: 0 as any }, + take, + skip, + order: { created: "DESC" }, + }) + .finally(() => setRefreshing(false)); + console.log(`${SetList.name}.refresh:`, { value, take, offset }); setSets(newSets); - setOffset(0); setEnd(false); + }; + + useEffect(() => { + settingsRepo.findOne({ where: {} }).then(setSettings); + refresh({ + take: LIMIT, + value: "", + skip: 0, + }); + /* eslint-disable react-hooks/exhaustive-deps */ }, []); - useFocusEffect( - useCallback(() => { - refresh(term); - settingsRepo.findOne({ where: {} }).then(setSettings); - }, [refresh, term]) - ); + const search = (value: string) => { + setTerm(value); + setOffset(0); + refresh({ + skip: 0, + take: LIMIT, + value, + }); + }; + + useEffect(() => { + if (!params) return; + console.log({ params }); + if (params.search) search(params.search); + else if (params.refresh) + refresh({ + skip: 0, + take: offset, + value: term, + }); + else if (params.reset) + refresh({ + skip: 0, + take: LIMIT, + value: term, + }); + /* eslint-disable react-hooks/exhaustive-deps */ + }, [params]); const renderItem = useCallback( ({ item }: { item: GymSet }) => ( @@ -59,22 +104,29 @@ export default function SetList() { [settings, ids] ); - const next = useCallback(async () => { - if (end) return; + const next = async () => { + if (end || refreshing) return; const newOffset = offset + LIMIT; console.log(`${SetList.name}.next:`, { offset, newOffset, term }); - const newSets = await setRepo.find({ - where: { name: Like(`%${term}%`), hidden: 0 as any }, - take: LIMIT, - skip: newOffset, - order: { created: "DESC" }, - }); + setRefreshing(true); + const newSets = await setRepo + .find({ + where: { name: Like(`%${term}%`), hidden: 0 as any }, + take: LIMIT, + skip: newOffset, + order: { created: "DESC" }, + }) + .finally(() => setRefreshing(false)); if (newSets.length === 0) return setEnd(true); if (!sets) return; - setSets([...sets, ...newSets]); + const map = new Map(); + for (const set of sets) map.set(set.id, set); + for (const set of newSets) map.set(set.id, set); + const unique = Array.from(map.values()); + setSets(unique); if (newSets.length < LIMIT) return setEnd(true); setOffset(newOffset); - }, [term, end, offset, sets]); + }; const onAdd = useCallback(async () => { const now = await getNow(); @@ -85,14 +137,6 @@ export default function SetList() { navigation.navigate("EditSet", { set }); }, [navigation, sets]); - const search = useCallback( - (value: string) => { - setTerm(value); - refresh(value); - }, - [refresh] - ); - const edit = useCallback(() => { navigation.navigate("EditSets", { ids }); setIds([]); @@ -112,16 +156,47 @@ export default function SetList() { setIds([]); }, []); - const remove = useCallback(async () => { + const remove = async () => { setIds([]); await setRepo.delete(ids.length > 0 ? ids : {}); - await refresh(term); - }, [ids, refresh, term]); + return refresh({ + skip: 0, + take: LIMIT, + value: term, + }); + }; const select = useCallback(() => { setIds(sets.map((set) => set.id)); }, [sets]); + const content = useMemo(() => { + if (!settings) return null; + if (sets?.length === 0) + return ( + + ); + return ( + + refresh({ + skip: 0, + take: LIMIT, + value: term, + }) + } + /> + ); + }, [sets, settings, term]); + return ( <> 0 ? `${ids.length} selected` : "Home"}> @@ -136,21 +211,7 @@ export default function SetList() { - {sets?.length === 0 ? ( - - ) : ( - settings && ( - - ) - )} + {content} ); diff --git a/StartPlanItem.tsx b/StartPlanItem.tsx index edcc129..6d2a1a5 100644 --- a/StartPlanItem.tsx +++ b/StartPlanItem.tsx @@ -5,6 +5,7 @@ import { List, Menu, RadioButton, useTheme } from "react-native-paper"; import { Like } from "typeorm"; import CountMany from "./count-many"; import { getNow, setRepo } from "./db"; +import { HomePageParams } from "./home-page-params"; import { PlanPageParams } from "./plan-page-params"; import { toast } from "./toast"; @@ -20,6 +21,8 @@ export default function StartPlanItem(props: Props) { const [anchor, setAnchor] = useState({ x: 0, y: 0 }); const [showMenu, setShowMenu] = useState(false); const { navigate } = useNavigation>(); + const { navigate: navigateHome } = + useNavigation>(); const undo = useCallback(async () => { const now = await getNow(); @@ -62,6 +65,11 @@ export default function StartPlanItem(props: Props) { navigate("EditSet", { set: first }); }, [item.name, navigate]); + const view = () => { + setShowMenu(false); + navigateHome("Sets", { search: item.name }); + }; + const left = useCallback( () => ( @@ -89,6 +97,7 @@ export default function StartPlanItem(props: Props) { visible={showMenu} onDismiss={() => setShowMenu(false)} > + diff --git a/home-page-params.ts b/home-page-params.ts index 7d2fd62..ca197ff 100644 --- a/home-page-params.ts +++ b/home-page-params.ts @@ -1,7 +1,19 @@ import GymSet from "./gym-set"; export type HomePageParams = { - Sets: {}; + Sets: { + search?: string; + + /** + * Reload the current list with limit = offset + */ + refresh?: number; + + /** + * Reload the list with limit = 0 + */ + reset?: number; + }; EditSet: { set: GymSet; };