Brandon Presley
185ebd1824
Every time we create/update/delete fire a DeviceEventEmitter event for gym sets. Then we subscribe to the changes in relevant components. Also fixed flickering of "No data yet" on graphs page.
122 lines
3.5 KiB
TypeScript
122 lines
3.5 KiB
TypeScript
import { NavigationProp, useNavigation } from "@react-navigation/native";
|
|
import { useCallback, useEffect, useState } from "react";
|
|
import {
|
|
DeviceEventEmitter,
|
|
EmitterSubscription,
|
|
FlatList,
|
|
Image,
|
|
} from "react-native";
|
|
import { List } from "react-native-paper";
|
|
import { getBestSets } from "./best.service";
|
|
import {
|
|
GYM_SET_CREATED,
|
|
GYM_SET_DELETED,
|
|
GYM_SET_UPDATED,
|
|
LIMIT,
|
|
} from "./constants";
|
|
import { settingsRepo } from "./db";
|
|
import DrawerHeader from "./DrawerHeader";
|
|
import { GraphsPageParams } from "./GraphsPage";
|
|
import GymSet from "./gym-set";
|
|
import Page from "./Page";
|
|
import Settings, { SETTINGS } from "./settings";
|
|
|
|
export default function GraphsList() {
|
|
const [bests, setBests] = useState<GymSet[]>();
|
|
const [refreshing, setRefreshing] = useState(false);
|
|
const [offset, setOffset] = useState(0);
|
|
const [end, setEnd] = useState(false);
|
|
const [term, setTerm] = useState("");
|
|
const navigation = useNavigation<NavigationProp<GraphsPageParams>>();
|
|
const [settings, setSettings] = useState<Settings>();
|
|
|
|
const refresh = useCallback(async (value: string) => {
|
|
setRefreshing(true);
|
|
const result = await getBestSets({ term: value, offset: 0 }).finally(() =>
|
|
setRefreshing(false)
|
|
);
|
|
setBests(result);
|
|
setOffset(0);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
refresh("");
|
|
settingsRepo.findOne({ where: {} }).then(setSettings);
|
|
const subs: EmitterSubscription[] = [];
|
|
|
|
subs.push(
|
|
DeviceEventEmitter.addListener(GYM_SET_CREATED, () => refresh("")),
|
|
DeviceEventEmitter.addListener(GYM_SET_UPDATED, () => refresh("")),
|
|
DeviceEventEmitter.addListener(GYM_SET_DELETED, () => refresh("")),
|
|
DeviceEventEmitter.addListener(SETTINGS, () =>
|
|
settingsRepo.findOne({ where: {} }).then(setSettings)
|
|
)
|
|
);
|
|
|
|
return () => subs.forEach((sub) => sub.remove());
|
|
/* eslint-disable react-hooks/exhaustive-deps */
|
|
}, []);
|
|
|
|
const next = useCallback(async () => {
|
|
console.log("next:", { end, offset });
|
|
if (end) return;
|
|
const newOffset = offset + LIMIT;
|
|
console.log(`${GraphsList.name}.next:`, { offset, newOffset, term });
|
|
const newBests = await getBestSets({ term, offset });
|
|
if (newBests.length === 0) return setEnd(true);
|
|
if (!bests) return;
|
|
setBests([...bests, ...newBests]);
|
|
if (newBests.length < LIMIT) return setEnd(true);
|
|
setOffset(newOffset);
|
|
}, [term, end, offset, bests]);
|
|
|
|
const search = useCallback(
|
|
(value: string) => {
|
|
setTerm(value);
|
|
refresh(value);
|
|
},
|
|
[refresh]
|
|
);
|
|
|
|
const renderItem = ({ item }: { item: GymSet }) => (
|
|
<List.Item
|
|
key={item.name}
|
|
title={item.name}
|
|
description={`${item.reps} x ${item.weight}${item.unit || "kg"}`}
|
|
onPress={() => navigation.navigate("ViewGraph", { best: item })}
|
|
left={() =>
|
|
(settings?.images && item.image && (
|
|
<Image
|
|
source={{ uri: item.image }}
|
|
style={{ height: 75, width: 75 }}
|
|
/>
|
|
)) ||
|
|
null
|
|
}
|
|
/>
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<DrawerHeader name="Graphs" />
|
|
<Page term={term} search={search}>
|
|
{bests?.length === 0 ? (
|
|
<List.Item
|
|
title="No exercises yet"
|
|
description="Once sets have been added, this will highlight your personal bests."
|
|
/>
|
|
) : (
|
|
<FlatList
|
|
style={{ flex: 1 }}
|
|
renderItem={renderItem}
|
|
data={bests}
|
|
onEndReached={next}
|
|
refreshing={refreshing}
|
|
onRefresh={() => refresh("")}
|
|
/>
|
|
)}
|
|
</Page>
|
|
</>
|
|
);
|
|
}
|