Optimize GraphsList

Instead of getting a list of max weights,
then looping in JS to run SQL queries for max
reps, use a subquery.
This commit is contained in:
Brandon Presley 2023-08-12 15:03:31 +12:00
parent 95681c0b3d
commit c97ba1151e

View File

@ -2,75 +2,68 @@ import {
NavigationProp, NavigationProp,
useFocusEffect, useFocusEffect,
useNavigation, useNavigation,
} from '@react-navigation/native' } from "@react-navigation/native";
import { useCallback, useState } from 'react' import { useCallback, useState } from "react";
import { FlatList, Image } from 'react-native' import { FlatList, Image } from "react-native";
import { List } from 'react-native-paper' import { List } from "react-native-paper";
import { GraphsPageParams } from './GraphsPage' import { GraphsPageParams } from "./GraphsPage";
import { setRepo, settingsRepo } from './db' import { setRepo, settingsRepo } from "./db";
import DrawerHeader from './DrawerHeader' import DrawerHeader from "./DrawerHeader";
import GymSet from './gym-set' import GymSet from "./gym-set";
import Page from './Page' import Page from "./Page";
import Settings from './settings' import Settings from "./settings";
export default function GraphsList() { export default function GraphsList() {
const [bests, setBests] = useState<GymSet[]>() const [bests, setBests] = useState<GymSet[]>();
const [term, setTerm] = useState('') const [term, setTerm] = useState("");
const navigation = useNavigation<NavigationProp<GraphsPageParams>>() const navigation = useNavigation<NavigationProp<GraphsPageParams>>();
const [settings, setSettings] = useState<Settings>() const [settings, setSettings] = useState<Settings>();
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
settingsRepo.findOne({ where: {} }).then(setSettings) settingsRepo.findOne({ where: {} }).then(setSettings);
}, []), }, [])
) );
const refresh = useCallback(async (value: string) => { const refresh = useCallback(async (value: string) => {
const weights = await setRepo const result = await setRepo
.createQueryBuilder() .createQueryBuilder("gym_set")
.select() .select(["gym_set.name", "gym_set.reps", "gym_set.weight"])
.addSelect('MAX(weight)', 'weight') .groupBy("gym_set.name")
.where('name LIKE :name', { name: `%${value.trim()}%` }) .innerJoin(
.andWhere('NOT hidden') (qb) =>
.groupBy('name') qb
.getMany() .select(["gym_set2.name", "MAX(gym_set2.weight) AS max_weight"])
console.log(`${GraphsList.name}.refresh:`, { length: weights.length }) .from(GymSet, "gym_set2")
let newBest: GymSet[] = [] .where("gym_set2.name LIKE (:name)", { name: `%${value.trim()}%` })
for (const set of weights) { .groupBy("gym_set2.name"),
const reps = await setRepo "subquery",
.createQueryBuilder() "gym_set.name = subquery.gym_set2_name AND gym_set.weight = subquery.max_weight"
.select() )
.addSelect('MAX(reps)', 'reps') .getMany();
.where('name = :name', { name: set.name }) setBests(result);
.andWhere('weight = :weight', { weight: set.weight }) }, []);
.andWhere('NOT hidden')
.groupBy('name')
.getMany()
newBest.push(...reps)
}
setBests(newBest)
}, [])
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
refresh(term) refresh(term);
}, [refresh, term]), }, [refresh, term])
) );
const search = useCallback( const search = useCallback(
(value: string) => { (value: string) => {
setTerm(value) setTerm(value);
refresh(value) refresh(value);
}, },
[refresh], [refresh]
) );
const renderItem = ({ item }: { item: GymSet }) => ( const renderItem = ({ item }: { item: GymSet }) => (
<List.Item <List.Item
key={item.name} key={item.name}
title={item.name} title={item.name}
description={`${item.reps} x ${item.weight}${item.unit || 'kg'}`} description={`${item.reps} x ${item.weight}${item.unit || "kg"}`}
onPress={() => navigation.navigate('ViewGraph', { best: item })} onPress={() => navigation.navigate("ViewGraph", { best: item })}
left={() => left={() =>
(settings.images && item.image && ( (settings.images && item.image && (
<Image <Image
@ -78,29 +71,24 @@ export default function GraphsList() {
style={{ height: 75, width: 75 }} style={{ height: 75, width: 75 }}
/> />
)) || )) ||
null} null
}
/> />
) );
return ( return (
<> <>
<DrawerHeader name='Graphs' /> <DrawerHeader name="Graphs" />
<Page term={term} search={search}> <Page term={term} search={search}>
{bests?.length === 0 {bests?.length === 0 ? (
? ( <List.Item
<List.Item title="No exercises yet"
title='No exercises yet' description="Once sets have been added, this will highlight your personal bests."
description='Once sets have been added, this will highlight your personal bests.' />
/> ) : (
) <FlatList style={{ flex: 1 }} renderItem={renderItem} data={bests} />
: ( )}
<FlatList
style={{ flex: 1 }}
renderItem={renderItem}
data={bests}
/>
)}
</Page> </Page>
</> </>
) );
} }