2022-07-11 01:00:17 +00:00
|
|
|
import {
|
|
|
|
RouteProp,
|
|
|
|
useFocusEffect,
|
|
|
|
useNavigation,
|
|
|
|
useRoute,
|
|
|
|
} from '@react-navigation/native';
|
2022-08-24 01:23:21 +00:00
|
|
|
import React, {
|
|
|
|
useCallback,
|
|
|
|
useContext,
|
|
|
|
useEffect,
|
|
|
|
useRef,
|
|
|
|
useState,
|
|
|
|
} from 'react';
|
2022-08-26 01:54:51 +00:00
|
|
|
import {FileSystem} from 'react-native-file-access';
|
2022-09-02 00:24:28 +00:00
|
|
|
import {IconButton} from 'react-native-paper';
|
|
|
|
import RNPickerSelect from 'react-native-picker-select';
|
2022-08-24 01:23:21 +00:00
|
|
|
import Share from 'react-native-share';
|
|
|
|
import ViewShot from 'react-native-view-shot';
|
2022-07-11 01:00:17 +00:00
|
|
|
import {BestPageParams} from './BestPage';
|
2022-09-02 00:24:28 +00:00
|
|
|
import Chart from './Chart';
|
2022-08-30 11:21:25 +00:00
|
|
|
import {DatabaseContext} from './Routes';
|
2022-07-11 01:00:17 +00:00
|
|
|
import Set from './set';
|
|
|
|
import {formatMonth} from './time';
|
2022-07-08 12:11:10 +00:00
|
|
|
|
2022-08-24 00:32:57 +00:00
|
|
|
interface Volume {
|
|
|
|
name: string;
|
|
|
|
created: string;
|
|
|
|
value: number;
|
|
|
|
unit: string;
|
|
|
|
}
|
|
|
|
|
2022-09-02 00:24:28 +00:00
|
|
|
enum Metrics {
|
|
|
|
Weight = 'Best weight per day',
|
2022-09-02 01:55:18 +00:00
|
|
|
Volume = 'Volume per day',
|
2022-09-02 00:24:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
enum Periods {
|
|
|
|
Weekly = 'This week',
|
|
|
|
Monthly = 'This month',
|
|
|
|
Yearly = 'This year',
|
|
|
|
}
|
|
|
|
|
2022-07-11 01:00:17 +00:00
|
|
|
export default function ViewBest() {
|
|
|
|
const {params} = useRoute<RouteProp<BestPageParams, 'ViewBest'>>();
|
2022-08-24 00:32:57 +00:00
|
|
|
const [weights, setWeights] = useState<Set[]>([]);
|
|
|
|
const [volumes, setVolumes] = useState<Volume[]>([]);
|
2022-09-02 00:24:28 +00:00
|
|
|
const [metric, setMetric] = useState(Metrics.Weight);
|
|
|
|
const [period, setPeriod] = useState(Periods.Monthly);
|
2022-07-08 12:11:10 +00:00
|
|
|
const db = useContext(DatabaseContext);
|
2022-07-11 01:00:17 +00:00
|
|
|
const navigation = useNavigation();
|
2022-08-24 01:23:21 +00:00
|
|
|
const viewShot = useRef<ViewShot>(null);
|
2022-07-11 01:00:17 +00:00
|
|
|
|
|
|
|
useFocusEffect(
|
|
|
|
useCallback(() => {
|
2022-07-12 03:54:04 +00:00
|
|
|
console.log(`${ViewBest.name}.useFocusEffect`);
|
2022-07-11 01:00:17 +00:00
|
|
|
navigation.getParent()?.setOptions({
|
|
|
|
headerLeft: () => (
|
|
|
|
<IconButton icon="arrow-back" onPress={() => navigation.goBack()} />
|
|
|
|
),
|
2022-08-24 01:23:21 +00:00
|
|
|
headerRight: () => (
|
|
|
|
<IconButton
|
|
|
|
onPress={() =>
|
|
|
|
viewShot.current?.capture?.().then(async uri => {
|
|
|
|
const base64 = await FileSystem.readFile(uri, 'base64');
|
|
|
|
const url = `data:image/jpeg;base64,${base64}`;
|
|
|
|
Share.open({
|
2022-08-27 04:43:25 +00:00
|
|
|
message: params.best.name,
|
2022-08-24 01:23:21 +00:00
|
|
|
type: 'image/jpeg',
|
|
|
|
url,
|
|
|
|
failOnCancel: false,
|
|
|
|
});
|
|
|
|
})
|
|
|
|
}
|
|
|
|
icon="share-social-outline"
|
|
|
|
/>
|
|
|
|
),
|
2022-07-11 01:00:17 +00:00
|
|
|
title: params.best.name,
|
|
|
|
});
|
2022-08-24 01:23:21 +00:00
|
|
|
}, [navigation, params.best]),
|
2022-07-11 01:00:17 +00:00
|
|
|
);
|
2022-07-08 12:11:10 +00:00
|
|
|
|
2022-09-02 00:24:28 +00:00
|
|
|
const refreshWeight = useCallback(async () => {
|
|
|
|
const select = `
|
2022-08-24 00:32:57 +00:00
|
|
|
SELECT max(weight) AS weight,
|
|
|
|
STRFTIME('%Y-%m-%d', created) as created, unit
|
|
|
|
FROM sets
|
2022-08-26 03:10:28 +00:00
|
|
|
WHERE name = ? AND NOT hidden
|
2022-09-02 00:24:28 +00:00
|
|
|
AND DATE(created) >= DATE('now', 'weekday 0', ?)
|
2022-08-24 00:32:57 +00:00
|
|
|
GROUP BY name, STRFTIME('%Y-%m-%d', created)
|
|
|
|
`;
|
2022-09-02 00:24:28 +00:00
|
|
|
let difference = '-7 days';
|
|
|
|
if (period === Periods.Monthly) difference = '-1 months';
|
|
|
|
else if (period === Periods.Yearly) difference = '-1 years';
|
|
|
|
const [result] = await db.executeSql(select, [
|
|
|
|
params.best.name,
|
|
|
|
difference,
|
|
|
|
]);
|
|
|
|
if (result.rows.length === 0) return;
|
|
|
|
setWeights(result.rows.raw());
|
|
|
|
}, [params.best.name, db, period]);
|
|
|
|
|
|
|
|
const refreshVolume = useCallback(async () => {
|
|
|
|
const select = `
|
2022-08-24 00:32:57 +00:00
|
|
|
SELECT sum(weight * reps) AS value,
|
|
|
|
STRFTIME('%Y-%m-%d', created) as created, unit
|
2022-07-09 00:51:13 +00:00
|
|
|
FROM sets
|
2022-08-26 03:10:28 +00:00
|
|
|
WHERE name = ? AND NOT hidden
|
2022-09-02 00:24:28 +00:00
|
|
|
AND DATE(created) >= DATE('now', 'weekday 0', ?)
|
2022-07-09 00:51:13 +00:00
|
|
|
GROUP BY name, STRFTIME('%Y-%m-%d', created)
|
|
|
|
`;
|
2022-09-02 00:24:28 +00:00
|
|
|
let difference = '-7 days';
|
|
|
|
if (period === Periods.Monthly) difference = '-1 months';
|
|
|
|
else if (period === Periods.Yearly) difference = '-1 years';
|
|
|
|
const [result] = await db.executeSql(select, [
|
|
|
|
params.best.name,
|
|
|
|
difference,
|
|
|
|
]);
|
|
|
|
if (result.rows.length === 0) return;
|
|
|
|
setVolumes(result.rows.raw());
|
|
|
|
}, [db, params.best.name, period]);
|
2022-07-09 00:51:13 +00:00
|
|
|
|
2022-09-02 00:24:28 +00:00
|
|
|
useEffect(() => {
|
|
|
|
if (metric === Metrics.Weight) refreshWeight();
|
|
|
|
else if (metric === Metrics.Volume) refreshVolume();
|
|
|
|
console.log(`${ViewBest.name}.useEffect`, {metric, period});
|
|
|
|
}, [params.best.name, db, metric, period, refreshVolume, refreshWeight]);
|
2022-07-12 03:54:04 +00:00
|
|
|
|
2022-07-08 12:11:10 +00:00
|
|
|
return (
|
2022-08-24 01:23:21 +00:00
|
|
|
<ViewShot style={{padding: 10}} ref={viewShot}>
|
2022-09-02 00:24:28 +00:00
|
|
|
<RNPickerSelect
|
|
|
|
onValueChange={setMetric}
|
|
|
|
items={[
|
|
|
|
{label: Metrics.Weight, value: Metrics.Weight},
|
|
|
|
{label: Metrics.Volume, value: Metrics.Volume},
|
|
|
|
]}
|
|
|
|
value={metric}
|
|
|
|
/>
|
|
|
|
<RNPickerSelect
|
|
|
|
onValueChange={setPeriod}
|
|
|
|
items={[
|
|
|
|
{label: Periods.Weekly, value: Periods.Weekly},
|
|
|
|
{label: Periods.Monthly, value: Periods.Monthly},
|
|
|
|
{label: Periods.Yearly, value: Periods.Yearly},
|
|
|
|
]}
|
|
|
|
value={period}
|
|
|
|
/>
|
|
|
|
{metric === Metrics.Volume && (
|
|
|
|
<Chart
|
|
|
|
yData={volumes.map(v => v.value)}
|
|
|
|
yFormat={(value: number) =>
|
2022-08-24 00:32:57 +00:00
|
|
|
`${value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')}${
|
|
|
|
volumes[0].unit
|
|
|
|
}`
|
|
|
|
}
|
2022-09-02 00:24:28 +00:00
|
|
|
xData={weights}
|
|
|
|
xFormat={(_value, index) => formatMonth(weights[index].created!)}
|
2022-07-11 01:00:17 +00:00
|
|
|
/>
|
2022-09-02 00:24:28 +00:00
|
|
|
)}
|
|
|
|
{metric === Metrics.Weight && (
|
|
|
|
<Chart
|
|
|
|
yData={weights.map(set => set.weight)}
|
|
|
|
yFormat={value => `${value}${weights[0].unit}`}
|
|
|
|
xData={weights}
|
|
|
|
xFormat={(_value, index) => formatMonth(weights[index].created!)}
|
|
|
|
/>
|
|
|
|
)}
|
2022-08-24 01:23:21 +00:00
|
|
|
</ViewShot>
|
2022-07-08 12:11:10 +00:00
|
|
|
);
|
|
|
|
}
|