diff --git a/Chart.tsx b/Chart.tsx
new file mode 100644
index 0000000..12fdcbd
--- /dev/null
+++ b/Chart.tsx
@@ -0,0 +1,58 @@
+import * as shape from 'd3-shape';
+import React from 'react';
+import {useColorScheme, View} from 'react-native';
+import {Grid, LineChart, XAxis, YAxis} from 'react-native-svg-charts';
+import {CombinedDarkTheme, CombinedDefaultTheme} from './App';
+import Set from './set';
+
+export default function Chart({
+ yData,
+ xFormat,
+ xData,
+ yFormat,
+}: {
+ yData: number[];
+ xData: Set[];
+ xFormat: (value: any, index: number) => string;
+ yFormat: (value: any) => string;
+}) {
+ const dark = useColorScheme() === 'dark';
+ const axesSvg = {fontSize: 10, fill: 'grey'};
+ const verticalContentInset = {top: 10, bottom: 10};
+ const xAxisHeight = 30;
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/ViewBest.tsx b/ViewBest.tsx
index a58160d..5504f17 100644
--- a/ViewBest.tsx
+++ b/ViewBest.tsx
@@ -4,7 +4,6 @@ import {
useNavigation,
useRoute,
} from '@react-navigation/native';
-import * as shape from 'd3-shape';
import React, {
useCallback,
useContext,
@@ -12,14 +11,13 @@ import React, {
useRef,
useState,
} from 'react';
-import {useColorScheme, View} from 'react-native';
import {FileSystem} from 'react-native-file-access';
-import {Text, IconButton} from 'react-native-paper';
+import {IconButton} from 'react-native-paper';
+import RNPickerSelect from 'react-native-picker-select';
import Share from 'react-native-share';
-import {Grid, LineChart, XAxis, YAxis} from 'react-native-svg-charts';
import ViewShot from 'react-native-view-shot';
-import {CombinedDarkTheme, CombinedDefaultTheme} from './App';
import {BestPageParams} from './BestPage';
+import Chart from './Chart';
import {DatabaseContext} from './Routes';
import Set from './set';
import {formatMonth} from './time';
@@ -31,13 +29,25 @@ interface Volume {
unit: string;
}
+enum Metrics {
+ Weight = 'Best weight per day',
+ Volume = 'Best volume per day',
+}
+
+enum Periods {
+ Weekly = 'This week',
+ Monthly = 'This month',
+ Yearly = 'This year',
+}
+
export default function ViewBest() {
const {params} = useRoute>();
const [weights, setWeights] = useState([]);
const [volumes, setVolumes] = useState([]);
+ const [metric, setMetric] = useState(Metrics.Weight);
+ const [period, setPeriod] = useState(Periods.Monthly);
const db = useContext(DatabaseContext);
const navigation = useNavigation();
- const dark = useColorScheme() === 'dark';
const viewShot = useRef(null);
useFocusEffect(
@@ -69,114 +79,91 @@ export default function ViewBest() {
}, [navigation, params.best]),
);
- useEffect(() => {
- console.log(`${ViewBest.name}.useEffect`);
- const selectWeights = `
+ const refreshWeight = useCallback(async () => {
+ const select = `
SELECT max(weight) AS weight,
STRFTIME('%Y-%m-%d', created) as created, unit
FROM sets
WHERE name = ? AND NOT hidden
+ AND DATE(created) >= DATE('now', 'weekday 0', ?)
GROUP BY name, STRFTIME('%Y-%m-%d', created)
`;
- const selectVolumes = `
+ 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 = `
SELECT sum(weight * reps) AS value,
STRFTIME('%Y-%m-%d', created) as created, unit
FROM sets
WHERE name = ? AND NOT hidden
+ AND DATE(created) >= DATE('now', 'weekday 0', ?)
GROUP BY name, STRFTIME('%Y-%m-%d', created)
`;
- const refresh = async () => {
- const [weightsResult] = await db.executeSql(selectWeights, [
- params.best.name,
- ]);
- if (weightsResult.rows.length === 0) return;
- setWeights(weightsResult.rows.raw());
- const [volumesResult] = await db.executeSql(selectVolumes, [
- params.best.name,
- ]);
- console.log(volumesResult.rows.raw());
- if (volumesResult.rows.length === 0) return;
- setVolumes(volumesResult.rows.raw());
- };
- refresh();
- }, [params.best.name, db]);
+ 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]);
- const axesSvg = {fontSize: 10, fill: 'grey'};
- const verticalContentInset = {top: 10, bottom: 10};
- const xAxisHeight = 30;
+ 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]);
return (
- Best weight per day
-
- set.weight)}
- style={{marginBottom: xAxisHeight}}
- contentInset={verticalContentInset}
- svg={axesSvg}
- formatLabel={value => `${value}${weights[0].unit}`}
- />
-
- set.weight)}
- contentInset={verticalContentInset}
- curve={shape.curveBasis}
- svg={{
- stroke: dark
- ? CombinedDarkTheme.colors.primary
- : CombinedDefaultTheme.colors.primary,
- }}>
-
-
-
- formatMonth(weights[index].created!)
- }
- contentInset={{left: 10, right: 10}}
- svg={axesSvg}
- />
-
-
- Volume per day
-
- volume.value)}
- style={{marginBottom: xAxisHeight}}
- contentInset={verticalContentInset}
- svg={axesSvg}
- formatLabel={(value: number) =>
+
+
+ {metric === Metrics.Volume && (
+ 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!)}
/>
-
- volume.value)}
- contentInset={verticalContentInset}
- curve={shape.curveBasis}
- svg={{
- stroke: dark
- ? CombinedDarkTheme.colors.primary
- : CombinedDefaultTheme.colors.primary,
- }}>
-
-
-
- formatMonth(volumes[index]?.created)
- }
- contentInset={{left: 10, right: 10}}
- svg={axesSvg}
- />
-
-
+ )}
+ {metric === Metrics.Weight && (
+ set.weight)}
+ yFormat={value => `${value}${weights[0].unit}`}
+ xData={weights}
+ xFormat={(_value, index) => formatMonth(weights[index].created!)}
+ />
+ )}
);
}
diff --git a/package.json b/package.json
index 48c02b6..c59c309 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"dependencies": {
"@babel/preset-env": "^7.1.6",
"@react-native-masked-view/masked-view": "^0.2.6",
+ "@react-native-picker/picker": "^2.4.4",
"@react-navigation/drawer": "^6.4.3",
"@react-navigation/native": "^6.0.10",
"@react-navigation/stack": "^6.2.2",
@@ -29,6 +30,7 @@
"react-native-linear-gradient": "^2.6.2",
"react-native-pager-view": "^5.4.24",
"react-native-paper": "^4.12.2",
+ "react-native-picker-select": "^8.0.4",
"react-native-reanimated": "^2.9.0",
"react-native-safe-area-context": "^4.3.1",
"react-native-screens": "^3.14.0",
diff --git a/yarn.lock b/yarn.lock
index 5264eea..a86c43d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1913,6 +1913,26 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-picker/picker@npm:^1.8.3":
+ version: 1.16.8
+ resolution: "@react-native-picker/picker@npm:1.16.8"
+ peerDependencies:
+ react: 16 || 17
+ react-native: ">=0.57"
+ checksum: c0176e41ba7486bf0a27ab5471315848cb166330313bd12e29ee65b7d2e1dfde22383de6a89be15770d132b33bca1764e64feee3acf22c67c3733fd877d3e91f
+ languageName: node
+ linkType: hard
+
+"@react-native-picker/picker@npm:^2.4.4":
+ version: 2.4.4
+ resolution: "@react-native-picker/picker@npm:2.4.4"
+ peerDependencies:
+ react: ">=16"
+ react-native: ">=0.57"
+ checksum: 8a122707e39f3f6a97536bd7800bdb2a326bdcff85d7e03472250454974a14789c8963c0d99397410955a9bbe31a67cef38bccfd0834b161e8a169e25ecc2304
+ languageName: node
+ linkType: hard
+
"@react-native/assets@npm:1.0.0":
version: 1.0.0
resolution: "@react-native/assets@npm:1.0.0"
@@ -6001,6 +6021,7 @@ __metadata:
"@babel/runtime": ^7.12.5
"@react-native-community/eslint-config": ^2.0.0
"@react-native-masked-view/masked-view": ^0.2.6
+ "@react-native-picker/picker": ^2.4.4
"@react-navigation/drawer": ^6.4.3
"@react-navigation/native": ^6.0.10
"@react-navigation/stack": ^6.2.2
@@ -6023,6 +6044,7 @@ __metadata:
react-native-linear-gradient: ^2.6.2
react-native-pager-view: ^5.4.24
react-native-paper: ^4.12.2
+ react-native-picker-select: ^8.0.4
react-native-reanimated: ^2.9.0
react-native-safe-area-context: ^4.3.1
react-native-screens: ^3.14.0
@@ -7434,6 +7456,16 @@ __metadata:
languageName: node
linkType: hard
+"react-native-picker-select@npm:^8.0.4":
+ version: 8.0.4
+ resolution: "react-native-picker-select@npm:8.0.4"
+ dependencies:
+ "@react-native-picker/picker": ^1.8.3
+ lodash.isequal: ^4.5.0
+ checksum: 9656a2f7b330a9e5a8b6b90393140fc5370762d2a14de4c5d31ce43de8abc677870c7f2ee8a493f48535157ddcbc3311cf3f41dac262bd84e50e913f0d4a24ff
+ languageName: node
+ linkType: hard
+
"react-native-reanimated@npm:^2.9.0":
version: 2.9.0
resolution: "react-native-reanimated@npm:2.9.0"