Prevent double searching everywhere

Also change variable names. Search should represent the
act of searching, rather than the value being typed by the user.
This commit is contained in:
Brandon Presley 2022-10-28 18:59:54 +13:00
parent 3d591f4618
commit 463852e6a6
8 changed files with 88 additions and 75 deletions

View File

@ -3,7 +3,7 @@ import {
useFocusEffect, useFocusEffect,
useNavigation, useNavigation,
} from '@react-navigation/native'; } from '@react-navigation/native';
import {useCallback, useEffect, 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 {getBestReps, getBestWeights} from './best.service'; import {getBestReps, getBestWeights} from './best.service';
@ -15,12 +15,12 @@ import {useSettings} from './use-settings';
export default function BestList() { export default function BestList() {
const [bests, setBests] = useState<Set[]>(); const [bests, setBests] = useState<Set[]>();
const [search, setSearch] = useState(''); const [term, setTerm] = useState('');
const navigation = useNavigation<NavigationProp<BestPageParams>>(); const navigation = useNavigation<NavigationProp<BestPageParams>>();
const {settings} = useSettings(); const {settings} = useSettings();
const refresh = useCallback(async () => { const refresh = useCallback(async (value: string) => {
const weights = await getBestWeights(search); const weights = await getBestWeights(value);
console.log(`${BestList.name}.refresh:`, {length: weights.length}); console.log(`${BestList.name}.refresh:`, {length: weights.length});
let newBest: Set[] = []; let newBest: Set[] = [];
for (const set of weights) { for (const set of weights) {
@ -28,17 +28,21 @@ export default function BestList() {
newBest.push(...reps); newBest.push(...reps);
} }
setBests(newBest); setBests(newBest);
}, [search]); }, []);
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
refresh(); refresh(term);
}, [refresh]), }, [refresh, term]),
); );
useEffect(() => { const search = useCallback(
refresh(); (value: string) => {
}, [search, refresh]); setTerm(value);
refresh(value);
},
[refresh],
);
const renderItem = ({item}: {item: Set}) => ( const renderItem = ({item}: {item: Set}) => (
<List.Item <List.Item
@ -58,7 +62,7 @@ export default function BestList() {
return ( return (
<> <>
<DrawerHeader name="Best" /> <DrawerHeader name="Best" />
<Page search={search} setSearch={setSearch}> <Page term={term} search={search}>
{bests?.length === 0 ? ( {bests?.length === 0 ? (
<List.Item <List.Item
title="No exercises yet" title="No exercises yet"

View File

@ -6,20 +6,20 @@ import MassiveFab from './MassiveFab';
export default function Page({ export default function Page({
onAdd, onAdd,
children, children,
term,
search, search,
setSearch,
}: { }: {
children: JSX.Element | JSX.Element[]; children: JSX.Element | JSX.Element[];
onAdd?: () => void; onAdd?: () => void;
search: string; term: string;
setSearch: (value: string) => void; search: (value: string) => void;
}) { }) {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Searchbar <Searchbar
placeholder="Search" placeholder="Search"
value={search} value={term}
onChangeText={setSearch} onChangeText={search}
icon="search" icon="search"
clearIcon="clear" clearIcon="clear"
/> />

View File

@ -3,7 +3,7 @@ import {
useFocusEffect, useFocusEffect,
useNavigation, useNavigation,
} from '@react-navigation/native'; } from '@react-navigation/native';
import {useCallback, useEffect, useState} from 'react'; import {useCallback, useState} from 'react';
import {FlatList} from 'react-native'; import {FlatList} from 'react-native';
import {List} from 'react-native-paper'; import {List} from 'react-native-paper';
import DrawerHeader from './DrawerHeader'; import DrawerHeader from './DrawerHeader';
@ -14,29 +14,33 @@ import {getPlans} from './plan.service';
import PlanItem from './PlanItem'; import PlanItem from './PlanItem';
export default function PlanList() { export default function PlanList() {
const [search, setSearch] = useState(''); const [term, setTerm] = useState('');
const [plans, setPlans] = useState<Plan[]>(); const [plans, setPlans] = useState<Plan[]>();
const navigation = useNavigation<NavigationProp<PlanPageParams>>(); const navigation = useNavigation<NavigationProp<PlanPageParams>>();
const refresh = useCallback(async () => { const refresh = useCallback(async (value: string) => {
getPlans(search).then(setPlans); getPlans(value).then(setPlans);
}, [search]); }, []);
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
refresh(); refresh(term);
}, [refresh]), }, [refresh, term]),
); );
useEffect(() => { const search = useCallback(
refresh(); (value: string) => {
}, [search, refresh]); setTerm(value);
refresh(value);
},
[refresh],
);
const renderItem = useCallback( const renderItem = useCallback(
({item}: {item: Plan}) => ( ({item}: {item: Plan}) => (
<PlanItem item={item} key={item.id} onRemove={refresh} /> <PlanItem item={item} key={item.id} onRemove={() => refresh(term)} />
), ),
[refresh], [refresh, term],
); );
const onAdd = () => const onAdd = () =>
@ -45,7 +49,7 @@ export default function PlanList() {
return ( return (
<> <>
<DrawerHeader name="Plans" /> <DrawerHeader name="Plans" />
<Page onAdd={onAdd} search={search} setSearch={setSearch}> <Page onAdd={onAdd} term={term} search={search}>
{plans?.length === 0 ? ( {plans?.length === 0 ? (
<List.Item <List.Item
title="No plans yet" title="No plans yet"

View File

@ -39,7 +39,7 @@ export default function SetForm({
if (!name) return; if (!name) return;
let image = newImage; let image = newImage;
if (!newImage && !removeImage) if (!newImage && !removeImage)
image = await getSets({search: name, limit: 1, offset: 0}).then( image = await getSets({term: name, limit: 1, offset: 0}).then(
([gotSet]) => gotSet?.image, ([gotSet]) => gotSet?.image,
); );
console.log(`${SetForm.name}.handleSubmit:`, {image}); console.log(`${SetForm.name}.handleSubmit:`, {image});

View File

@ -20,17 +20,17 @@ export default function SetList() {
const [sets, setSets] = useState<Set[]>(); const [sets, setSets] = useState<Set[]>();
const [set, setSet] = useState<Set>(); const [set, setSet] = useState<Set>();
const [offset, setOffset] = useState(0); const [offset, setOffset] = useState(0);
const [search, setSearch] = useState(''); const [term, setTerm] = useState('');
const [end, setEnd] = useState(false); const [end, setEnd] = useState(false);
const {settings} = useSettings(); const {settings} = useSettings();
const navigation = useNavigation<NavigationProp<HomePageParams>>(); const navigation = useNavigation<NavigationProp<HomePageParams>>();
const refresh = useCallback( const refresh = useCallback(
async (term: string) => { async (value: string) => {
const todaysSet = await getToday(); const todaysSet = await getToday();
if (todaysSet) setSet({...todaysSet}); if (todaysSet) setSet({...todaysSet});
const newSets = await getSets({ const newSets = await getSets({
search: `%${term}%`, term: `%${value}%`,
limit, limit,
offset: 0, offset: 0,
format: settings.date || '%Y-%m-%d %H:%M', format: settings.date || '%Y-%m-%d %H:%M',
@ -46,33 +46,32 @@ export default function SetList() {
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
refresh(search); refresh(term);
}, [refresh, search]), }, [refresh, term]),
); );
const renderItem = useCallback( const renderItem = useCallback(
({item}: {item: Set}) => ( ({item}: {item: Set}) => (
<SetItem item={item} key={item.id} onRemove={() => refresh(search)} /> <SetItem item={item} key={item.id} onRemove={() => refresh(term)} />
), ),
[refresh, search], [refresh, term],
); );
const next = useCallback(async () => { const next = useCallback(async () => {
if (end) return; if (end) return;
const newOffset = offset + limit; const newOffset = offset + limit;
console.log(`${SetList.name}.next:`, {offset, newOffset, search}); console.log(`${SetList.name}.next:`, {offset, newOffset, term});
const newSets = await getSets({ const newSets = await getSets({
search: `%${search}%`, term: `%${term}%`,
limit, limit,
offset: newOffset, offset: newOffset,
format: settings.date || '%Y-%m-%d %H:%M',
}); });
if (newSets.length === 0) return setEnd(true); if (newSets.length === 0) return setEnd(true);
if (!sets) return; if (!sets) return;
setSets([...sets, ...newSets]); setSets([...sets, ...newSets]);
if (newSets.length < limit) return setEnd(true); if (newSets.length < limit) return setEnd(true);
setOffset(newOffset); setOffset(newOffset);
}, [search, end, offset, sets, settings.date]); }, [term, end, offset, sets]);
const onAdd = useCallback(async () => { const onAdd = useCallback(async () => {
console.log(`${SetList.name}.onAdd`, {set}); console.log(`${SetList.name}.onAdd`, {set});
@ -81,9 +80,9 @@ export default function SetList() {
}); });
}, [navigation, set]); }, [navigation, set]);
const handleSearch = useCallback( const search = useCallback(
(value: string) => { (value: string) => {
setSearch(value); setTerm(value);
refresh(value); refresh(value);
}, },
[refresh], [refresh],
@ -92,7 +91,7 @@ export default function SetList() {
return ( return (
<> <>
<DrawerHeader name="Home" /> <DrawerHeader name="Home" />
<Page onAdd={onAdd} search={search} setSearch={handleSearch}> <Page onAdd={onAdd} term={term} search={search}>
{sets?.length === 0 ? ( {sets?.length === 0 ? (
<List.Item <List.Item
title="No sets yet" title="No sets yet"

View File

@ -20,7 +20,7 @@ import {useSettings} from './use-settings';
export default function SettingsPage() { export default function SettingsPage() {
const [battery, setBattery] = useState(false); const [battery, setBattery] = useState(false);
const [ignoring, setIgnoring] = useState(false); const [ignoring, setIgnoring] = useState(false);
const [search, setSearch] = useState(''); const [term, setTerm] = useState('');
const {settings, setSettings} = useSettings(); const {settings, setSettings} = useSettings();
const { const {
vibrate, vibrate,
@ -180,11 +180,11 @@ export default function SettingsPage() {
return ( return (
<> <>
<DrawerHeader name="Settings" /> <DrawerHeader name="Settings" />
<Page search={search} setSearch={setSearch}> <Page term={term} search={setTerm}>
<ScrollView style={{marginTop: MARGIN}}> <ScrollView style={{marginTop: MARGIN}}>
{switches {switches
.filter(input => .filter(input =>
input.name.toLowerCase().includes(search.toLowerCase()), input.name.toLowerCase().includes(term.toLowerCase()),
) )
.map(input => ( .map(input => (
<Switch <Switch
@ -195,7 +195,7 @@ export default function SettingsPage() {
{input.name} {input.name}
</Switch> </Switch>
))} ))}
{'theme'.includes(search.toLowerCase()) && ( {'theme'.includes(term.toLowerCase()) && (
<Picker <Picker
style={{color}} style={{color}}
dropdownIconColor={color} dropdownIconColor={color}
@ -206,7 +206,7 @@ export default function SettingsPage() {
<Picker.Item value="light" label="Light theme" /> <Picker.Item value="light" label="Light theme" />
</Picker> </Picker>
)} )}
{'color'.includes(search.toLowerCase()) && ( {'color'.includes(term.toLowerCase()) && (
<Picker <Picker
style={{color, marginTop: -10}} style={{color, marginTop: -10}}
dropdownIconColor={color} dropdownIconColor={color}
@ -222,7 +222,7 @@ export default function SettingsPage() {
))} ))}
</Picker> </Picker>
)} )}
{'date format'.includes(search.toLowerCase()) && ( {'date format'.includes(term.toLowerCase()) && (
<Picker <Picker
style={{color, marginTop: -10}} style={{color, marginTop: -10}}
dropdownIconColor={color} dropdownIconColor={color}
@ -242,7 +242,7 @@ export default function SettingsPage() {
<Picker.Item value="%d/%m %h:%M %p" label="24/12 3:05 PM" /> <Picker.Item value="%d/%m %h:%M %p" label="24/12 3:05 PM" />
</Picker> </Picker>
)} )}
{'alarm sound'.includes(search.toLowerCase()) && ( {'alarm sound'.includes(term.toLowerCase()) && (
<Button style={{alignSelf: 'flex-start'}} onPress={changeSound}> <Button style={{alignSelf: 'flex-start'}} onPress={changeSound}>
Alarm sound Alarm sound
{sound {sound

View File

@ -3,7 +3,7 @@ import {
useFocusEffect, useFocusEffect,
useNavigation, useNavigation,
} from '@react-navigation/native'; } from '@react-navigation/native';
import {useCallback, useEffect, useState} from 'react'; import {useCallback, useState} from 'react';
import {FlatList} from 'react-native'; import {FlatList} from 'react-native';
import {List} from 'react-native-paper'; import {List} from 'react-native-paper';
import DrawerHeader from './DrawerHeader'; import DrawerHeader from './DrawerHeader';
@ -19,13 +19,13 @@ const limit = 15;
export default function WorkoutList() { export default function WorkoutList() {
const [workouts, setWorkouts] = useState<Set[]>(); const [workouts, setWorkouts] = useState<Set[]>();
const [offset, setOffset] = useState(0); const [offset, setOffset] = useState(0);
const [search, setSearch] = useState(''); const [term, setTerm] = useState('');
const [end, setEnd] = useState(false); const [end, setEnd] = useState(false);
const navigation = useNavigation<NavigationProp<WorkoutsPageParams>>(); const navigation = useNavigation<NavigationProp<WorkoutsPageParams>>();
const refresh = useCallback(async () => { const refresh = useCallback(async (value: string) => {
const newWorkouts = await getDistinctSets({ const newWorkouts = await getDistinctSets({
search: `%${search}%`, term: `%${value}%`,
limit, limit,
offset: 0, offset: 0,
}); });
@ -33,23 +33,23 @@ export default function WorkoutList() {
setWorkouts(newWorkouts); setWorkouts(newWorkouts);
setOffset(0); setOffset(0);
setEnd(false); setEnd(false);
}, [search]); }, []);
useEffect(() => {
refresh();
}, [search, refresh]);
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
refresh(); refresh(term);
}, [refresh]), }, [refresh, term]),
); );
const renderItem = useCallback( const renderItem = useCallback(
({item}: {item: Set}) => ( ({item}: {item: Set}) => (
<WorkoutItem item={item} key={item.name} onRemoved={refresh} /> <WorkoutItem
item={item}
key={item.name}
onRemoved={() => refresh(term)}
/>
), ),
[refresh], [refresh, term],
); );
const next = useCallback(async () => { const next = useCallback(async () => {
@ -59,10 +59,10 @@ export default function WorkoutList() {
offset, offset,
limit, limit,
newOffset, newOffset,
search, term,
}); });
const newWorkouts = await getDistinctSets({ const newWorkouts = await getDistinctSets({
search: `%${search}%`, term: `%${term}%`,
limit, limit,
offset: newOffset, offset: newOffset,
}); });
@ -71,7 +71,7 @@ export default function WorkoutList() {
setWorkouts([...workouts, ...newWorkouts]); setWorkouts([...workouts, ...newWorkouts]);
if (newWorkouts.length < limit) return setEnd(true); if (newWorkouts.length < limit) return setEnd(true);
setOffset(newOffset); setOffset(newOffset);
}, [search, end, offset, workouts]); }, [term, end, offset, workouts]);
const onAdd = useCallback(async () => { const onAdd = useCallback(async () => {
navigation.navigate('EditWorkout', { navigation.navigate('EditWorkout', {
@ -79,10 +79,18 @@ export default function WorkoutList() {
}); });
}, [navigation]); }, [navigation]);
const search = useCallback(
(value: string) => {
setTerm(value);
refresh(value);
},
[refresh],
);
return ( return (
<> <>
<DrawerHeader name="Workouts" /> <DrawerHeader name="Workouts" />
<Page onAdd={onAdd} search={search} setSearch={setSearch}> <Page onAdd={onAdd} term={term} search={search}>
{workouts?.length === 0 ? ( {workouts?.length === 0 ? (
<List.Item <List.Item
title="No workouts yet." title="No workouts yet."

View File

@ -57,10 +57,9 @@ export const getAllSets = async (): Promise<Set[]> => {
}; };
interface PageParams { interface PageParams {
search: string; term: string;
limit: number; limit: number;
offset: number; offset: number;
format?: string;
} }
export const getSet = async (name: string): Promise<Set> => { export const getSet = async (name: string): Promise<Set> => {
@ -75,10 +74,9 @@ export const getSet = async (name: string): Promise<Set> => {
}; };
export const getSets = async ({ export const getSets = async ({
search, term,
limit, limit,
offset, offset,
format,
}: PageParams): Promise<Set[]> => { }: PageParams): Promise<Set[]> => {
const select = ` const select = `
SELECT id, name, reps, weight, sets, minutes, seconds, SELECT id, name, reps, weight, sets, minutes, seconds,
@ -88,7 +86,7 @@ export const getSets = async ({
ORDER BY STRFTIME('%Y-%m-%d %H:%M', created) DESC ORDER BY STRFTIME('%Y-%m-%d %H:%M', created) DESC
LIMIT ? OFFSET ? LIMIT ? OFFSET ?
`; `;
const [result] = await db.executeSql(select, [`%${search}%`, limit, offset]); const [result] = await db.executeSql(select, [`%${term}%`, limit, offset]);
return result.rows.raw(); return result.rows.raw();
}; };
@ -180,7 +178,7 @@ export const countMany = async (names: string[]): Promise<CountMany[]> => {
}; };
export const getDistinctSets = async ({ export const getDistinctSets = async ({
search, term,
limit, limit,
offset, offset,
}: PageParams): Promise<Set[]> => { }: PageParams): Promise<Set[]> => {
@ -192,6 +190,6 @@ export const getDistinctSets = async ({
ORDER BY sets.name ORDER BY sets.name
LIMIT ? OFFSET ? LIMIT ? OFFSET ?
`; `;
const [result] = await db.executeSql(select, [search, limit, offset]); const [result] = await db.executeSql(select, [term, limit, offset]);
return result.rows.raw(); return result.rows.raw();
}; };