Massive/ViewBest.tsx
Brandon Presley 3012b69e00 Add one rep max calculator for best graphs
I tried out a bunch of formulas as well as
having them as options, and I ended up liking
the Brzycki formula the most.
https://en.wikipedia.org/wiki/One-repetition_maximum#Brzycki
All of them produced similar trends (for me) and the one using
exponents wouldn't work with the SQLite version on android
(can't use POWER function). Also having all the options looked
kind of cluttered. If people ask for it I'll add the other ones
later.
2022-10-16 13:39:59 +13:00

118 lines
4.0 KiB
TypeScript

import {Picker} from '@react-native-picker/picker';
import {
RouteProp,
useFocusEffect,
useNavigation,
useRoute,
} from '@react-navigation/native';
import React, {useCallback, useEffect, useState} from 'react';
import {View} from 'react-native';
import {FileSystem} from 'react-native-file-access';
import {IconButton} from 'react-native-paper';
import Share from 'react-native-share';
import {captureScreen} from 'react-native-view-shot';
import {getOneRepMax, getVolumes, getWeightsBy} from './best.service';
import {BestPageParams} from './BestPage';
import Chart from './Chart';
import {PADDING} from './constants';
import {Metrics} from './metrics';
import {Periods} from './periods';
import Set from './set';
import {formatMonth} from './time';
import useDark from './use-dark';
import Volume from './volume';
export default function ViewBest() {
const {params} = useRoute<RouteProp<BestPageParams, 'ViewBest'>>();
const dark = useDark();
const [weights, setWeights] = useState<Set[]>([]);
const [volumes, setVolumes] = useState<Volume[]>([]);
const [metric, setMetric] = useState(Metrics.Weight);
const [period, setPeriod] = useState(Periods.Monthly);
const navigation = useNavigation();
useFocusEffect(
useCallback(() => {
console.log(`${ViewBest.name}.useFocusEffect`);
navigation.getParent()?.setOptions({
headerLeft: () => (
<IconButton icon="arrow-back" onPress={() => navigation.goBack()} />
),
headerRight: () => (
<IconButton
onPress={() =>
captureScreen().then(async uri => {
const base64 = await FileSystem.readFile(uri, 'base64');
const url = `data:image/jpeg;base64,${base64}`;
Share.open({
type: 'image/jpeg',
url,
});
})
}
icon="share"
/>
),
title: params.best.name,
});
}, [navigation, params.best]),
);
useEffect(() => {
console.log(`${ViewBest.name}.useEffect`, {metric});
console.log(`${ViewBest.name}.useEffect`, {period});
switch (metric) {
case Metrics.Weight:
getWeightsBy(params.best.name, period).then(setWeights);
break;
case Metrics.Volume:
getVolumes(params.best.name, period).then(setVolumes);
break;
default:
getOneRepMax({name: params.best.name, period}).then(setWeights);
}
}, [params.best.name, metric, period]);
return (
<View style={{padding: PADDING}}>
<Picker
style={{color: dark ? 'white' : 'black'}}
dropdownIconColor={dark ? 'white' : 'black'}
selectedValue={metric}
onValueChange={value => setMetric(value)}>
<Picker.Item value={Metrics.Volume} label={Metrics.Volume} />
<Picker.Item value={Metrics.Weight} label={Metrics.Weight} />
<Picker.Item value={Metrics.OneRepMax} label={Metrics.OneRepMax} />
</Picker>
<Picker
style={{color: dark ? 'white' : 'black'}}
dropdownIconColor={dark ? 'white' : 'black'}
selectedValue={period}
onValueChange={value => setPeriod(value)}>
<Picker.Item value={Periods.Weekly} label={Periods.Weekly} />
<Picker.Item value={Periods.Monthly} label={Periods.Monthly} />
<Picker.Item value={Periods.Yearly} label={Periods.Yearly} />
</Picker>
{metric === Metrics.Volume ? (
<Chart
yData={volumes.map(v => v.value)}
yFormat={(value: number) =>
`${value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')}${
volumes[0].unit
}`
}
xData={weights}
xFormat={(_value, index) => formatMonth(weights[index].created!)}
/>
) : (
<Chart
yData={weights.map(set => set.weight)}
yFormat={value => `${value}${weights[0].unit}`}
xData={weights}
xFormat={(_value, index) => formatMonth(weights[index].created!)}
/>
)}
</View>
);
}