Massive/ViewBest.tsx

158 lines
5.0 KiB
TypeScript
Raw Normal View History

2022-10-31 04:22:08 +00:00
import {RouteProp, useRoute} from '@react-navigation/native'
import {format} from 'date-fns'
2022-11-23 08:50:11 +00:00
import {useEffect, useMemo, useState} from 'react'
2022-10-31 04:22:08 +00:00
import {View} from 'react-native'
2023-03-27 23:04:54 +00:00
import {FileSystem} from 'react-native-file-access'
import {IconButton, List} from 'react-native-paper'
import Share from 'react-native-share'
import {captureScreen} from 'react-native-view-shot'
2022-10-31 04:22:08 +00:00
import {BestPageParams} from './BestPage'
import Chart from './Chart'
import {PADDING} from './constants'
import {setRepo} from './db'
import GymSet from './gym-set'
import {Metrics} from './metrics'
import {Periods} from './periods'
import Select from './Select'
2022-10-31 04:22:08 +00:00
import StackHeader from './StackHeader'
2023-03-27 23:04:54 +00:00
import useDark from './use-dark'
2022-10-31 04:22:08 +00:00
import Volume from './volume'
2022-09-02 00:24:28 +00:00
2022-07-11 01:00:17 +00:00
export default function ViewBest() {
2022-10-31 04:22:08 +00:00
const {params} = useRoute<RouteProp<BestPageParams, 'ViewBest'>>()
const [weights, setWeights] = useState<GymSet[]>()
const [volumes, setVolumes] = useState<Volume[]>()
2022-10-31 04:22:08 +00:00
const [metric, setMetric] = useState(Metrics.Weight)
const [period, setPeriod] = useState(Periods.Monthly)
2023-03-27 23:04:54 +00:00
const dark = useDark()
2022-07-08 12:11:10 +00:00
2022-09-02 00:24:28 +00:00
useEffect(() => {
2022-10-31 04:22:08 +00:00
console.log(`${ViewBest.name}.useEffect`, {metric})
console.log(`${ViewBest.name}.useEffect`, {period})
let difference = '-7 days'
if (period === Periods.Monthly) difference = '-1 months'
else if (period === Periods.Yearly) difference = '-1 years'
let group = '%Y-%m-%d'
if (period === Periods.Yearly) group = '%Y-%m'
const builder = setRepo
.createQueryBuilder()
.select("STRFTIME('%Y-%m-%d', created)", 'created')
.addSelect('unit')
.where('name = :name', {name: params.best.name})
.andWhere('NOT hidden')
.andWhere("DATE(created) >= DATE('now', 'weekday 0', :difference)", {
difference,
})
.groupBy('name')
2022-10-31 04:22:08 +00:00
.addGroupBy(`STRFTIME('${group}', created)`)
switch (metric) {
case Metrics.Weight:
builder
.addSelect('ROUND(MAX(weight), 2)', 'weight')
.getRawMany()
.then(setWeights)
2022-10-31 04:22:08 +00:00
break
case Metrics.Volume:
builder
.addSelect('ROUND(SUM(weight * reps), 2)', 'value')
.getRawMany()
2022-10-31 04:22:08 +00:00
.then(setVolumes)
break
default:
2022-10-31 04:05:31 +00:00
// Brzycki formula https://en.wikipedia.org/wiki/One-repetition_maximum#Brzycki
builder
.addSelect(
'ROUND(MAX(weight / (1.0278 - 0.0278 * reps)), 2)',
'weight',
)
2022-10-31 04:05:31 +00:00
.getRawMany()
2022-10-31 08:00:10 +00:00
.then(newWeights => {
console.log({weights: newWeights})
setWeights(newWeights)
2022-10-31 04:22:08 +00:00
})
}
2022-10-31 04:22:08 +00:00
}, [params.best.name, metric, period])
2022-07-12 03:54:04 +00:00
2022-11-23 08:50:11 +00:00
const charts = useMemo(() => {
if (
(metric === Metrics.Volume && volumes?.length === 0) ||
(metric === Metrics.Weight && weights?.length === 0) ||
(metric === Metrics.OneRepMax && weights?.length === 0)
2022-11-23 08:50:11 +00:00
)
return <List.Item title="No data yet." />
if (metric === Metrics.Volume && volumes?.length && weights?.length)
2022-11-23 08:50:11 +00:00
return (
<Chart
yData={volumes.map(v => v.value)}
yFormat={(value: number) =>
`${value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')}${
volumes[0].unit || 'kg'
}`
}
xData={weights}
xFormat={(_value, index) =>
format(new Date(weights[index].created), 'd/M')
}
/>
)
return (
<Chart
yData={weights?.map(set => set.weight) || []}
yFormat={value => `${value}${weights?.[0].unit}`}
xData={weights || []}
2022-11-23 08:50:11 +00:00
xFormat={(_value, index) =>
format(new Date(weights?.[index].created), 'd/M')
2022-11-23 08:50:11 +00:00
}
/>
)
}, [volumes, weights, metric])
2022-07-08 12:11:10 +00:00
return (
<>
2023-03-27 23:04:54 +00:00
<StackHeader title={params.best.name}>
<IconButton
color={dark ? 'white' : 'white'}
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"
/>
</StackHeader>
<View style={{padding: PADDING}}>
<Select
2022-11-30 02:15:19 +00:00
label="Metric"
items={[
{value: Metrics.Volume, label: Metrics.Volume},
{value: Metrics.OneRepMax, label: Metrics.OneRepMax},
{
label: Metrics.Weight,
value: Metrics.Weight,
},
]}
onChange={value => setMetric(value as Metrics)}
value={metric}
/>
<Select
2022-11-30 02:15:19 +00:00
label="Period"
items={[
{value: Periods.Weekly, label: Periods.Weekly},
{value: Periods.Monthly, label: Periods.Monthly},
{value: Periods.Yearly, label: Periods.Yearly},
]}
onChange={value => setPeriod(value as Periods)}
value={period}
/>
2022-11-23 08:50:11 +00:00
{charts}
</View>
</>
2022-10-31 04:22:08 +00:00
)
2022-07-08 12:11:10 +00:00
}