Add most active hours of the day to insights - 1.166 🚀
This commit is contained in:
parent
32da68e905
commit
7ea91eeca9
156
InsightsPage.tsx
156
InsightsPage.tsx
|
@ -1,6 +1,6 @@
|
||||||
import { useFocusEffect } from "@react-navigation/native";
|
import { useFocusEffect } from "@react-navigation/native";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { View } from "react-native";
|
import { ScrollView, View } from "react-native";
|
||||||
import { IconButton, Text } from "react-native-paper";
|
import { IconButton, Text } from "react-native-paper";
|
||||||
import AppBarChart from "./AppBarChart";
|
import AppBarChart from "./AppBarChart";
|
||||||
import { MARGIN, PADDING } from "./constants";
|
import { MARGIN, PADDING } from "./constants";
|
||||||
|
@ -10,16 +10,24 @@ import { DAYS } from "./time";
|
||||||
import Select from "./Select";
|
import Select from "./Select";
|
||||||
import { Periods } from "./periods";
|
import { Periods } from "./periods";
|
||||||
import ConfirmDialog from "./ConfirmDialog";
|
import ConfirmDialog from "./ConfirmDialog";
|
||||||
|
import Chart from "./Chart";
|
||||||
|
|
||||||
export interface WeekCounts {
|
interface WeekCount {
|
||||||
week: number;
|
week: string;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HourCount {
|
||||||
|
hour: string;
|
||||||
count: number;
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function InsightsPage() {
|
export default function InsightsPage() {
|
||||||
const [weekCounts, setWeekCounts] = useState<WeekCounts[]>([]);
|
const [weekCounts, setWeekCounts] = useState<WeekCount[]>([]);
|
||||||
|
const [hourCounts, setHourCounts] = useState<HourCount[]>([]);
|
||||||
const [period, setPeriod] = useState(Periods.Monthly);
|
const [period, setPeriod] = useState(Periods.Monthly);
|
||||||
const [showActive, setShowActive] = useState(false);
|
const [showWeek, setShowWeek] = useState(false);
|
||||||
|
const [showHour, setShowHour] = useState(false);
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
|
@ -27,27 +35,57 @@ export default function InsightsPage() {
|
||||||
if (period === Periods.TwoMonths) difference = "-2 months";
|
if (period === Periods.TwoMonths) difference = "-2 months";
|
||||||
if (period === Periods.ThreeMonths) difference = "-3 months";
|
if (period === Periods.ThreeMonths) difference = "-3 months";
|
||||||
if (period === Periods.SixMonths) difference = "-6 months";
|
if (period === Periods.SixMonths) difference = "-6 months";
|
||||||
const select = `
|
const selectWeeks = `
|
||||||
SELECT strftime('%w', created) as week, COUNT(*) as count
|
SELECT strftime('%w', created) as week, COUNT(*) as count
|
||||||
FROM sets
|
FROM sets
|
||||||
WHERE DATE(created) >= DATE('now', 'weekday 0', '${difference}')
|
WHERE DATE(created) >= DATE('now', 'weekday 0', '${difference}')
|
||||||
GROUP BY week
|
GROUP BY week
|
||||||
HAVING week IS NOT NULL
|
HAVING week IS NOT NULL
|
||||||
ORDER BY count DESC;
|
ORDER BY count DESC;
|
||||||
`;
|
`;
|
||||||
AppDataSource.manager.query(select).then(setWeekCounts);
|
const selectHours = `
|
||||||
|
SELECT strftime('%H', created) AS hour, COUNT(*) AS count
|
||||||
|
FROM sets
|
||||||
|
WHERE DATE(created) >= DATE('now', 'weekday 0', '${difference}')
|
||||||
|
GROUP BY hour
|
||||||
|
having hour is not null
|
||||||
|
ORDER BY hour
|
||||||
|
`;
|
||||||
|
AppDataSource.manager.query(selectWeeks).then(setWeekCounts);
|
||||||
|
AppDataSource.manager.query(selectHours).then(setHourCounts);
|
||||||
}, [period])
|
}, [period])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const hourLabel = (hour: string) => {
|
||||||
|
let twelveHour = Number(hour);
|
||||||
|
if (twelveHour === 0) return "12AM";
|
||||||
|
let amPm = "AM";
|
||||||
|
if (twelveHour >= 12) amPm = "PM";
|
||||||
|
if (twelveHour > 12) twelveHour -= 12;
|
||||||
|
return `${twelveHour} ${amPm}`;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DrawerHeader name="Insights" />
|
<DrawerHeader name="Insights" />
|
||||||
<View
|
<ScrollView
|
||||||
style={{
|
style={{
|
||||||
padding: PADDING,
|
padding: PADDING,
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Select
|
||||||
|
label="Period"
|
||||||
|
items={[
|
||||||
|
{ value: Periods.Monthly, label: Periods.Monthly },
|
||||||
|
{ value: Periods.TwoMonths, label: Periods.TwoMonths },
|
||||||
|
{ value: Periods.ThreeMonths, label: Periods.ThreeMonths },
|
||||||
|
{ value: Periods.SixMonths, label: Periods.SixMonths },
|
||||||
|
]}
|
||||||
|
value={period}
|
||||||
|
onChange={(value) => setPeriod(value as Periods)}
|
||||||
|
/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
|
@ -67,37 +105,79 @@ export default function InsightsPage() {
|
||||||
icon="help-circle-outline"
|
icon="help-circle-outline"
|
||||||
size={25}
|
size={25}
|
||||||
style={{ padding: 0, margin: 0, paddingBottom: 10 }}
|
style={{ padding: 0, margin: 0, paddingBottom: 10 }}
|
||||||
onPress={() => setShowActive(true)}
|
onPress={() => setShowWeek(true)}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Select
|
{weekCounts.length > 0 ? (
|
||||||
label="Period"
|
<AppBarChart
|
||||||
items={[
|
options={weekCounts.map((weekCount) => ({
|
||||||
{ value: Periods.Monthly, label: Periods.Monthly },
|
label: DAYS[weekCount.week],
|
||||||
{ value: Periods.TwoMonths, label: Periods.TwoMonths },
|
value: weekCount.count,
|
||||||
{ value: Periods.ThreeMonths, label: Periods.ThreeMonths },
|
}))}
|
||||||
{ value: Periods.SixMonths, label: Periods.SixMonths },
|
/>
|
||||||
]}
|
) : (
|
||||||
value={period}
|
<Text style={{ marginBottom: MARGIN }}>
|
||||||
onChange={(value) => setPeriod(value as Periods)}
|
No entries yet! Start recording sets to see your most active days of
|
||||||
/>
|
the week.
|
||||||
<AppBarChart
|
</Text>
|
||||||
options={weekCounts.map((weekCount) => ({
|
)}
|
||||||
label: DAYS[weekCount.week],
|
|
||||||
value: weekCount.count,
|
<View
|
||||||
}))}
|
style={{
|
||||||
/>
|
flexDirection: "row",
|
||||||
</View>
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
variant="titleLarge"
|
||||||
|
style={{
|
||||||
|
marginBottom: MARGIN,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Most active hours of the day
|
||||||
|
</Text>
|
||||||
|
<IconButton
|
||||||
|
icon="help-circle-outline"
|
||||||
|
size={25}
|
||||||
|
style={{ padding: 0, margin: 0, paddingBottom: 10 }}
|
||||||
|
onPress={() => setShowHour(true)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{hourCounts.length > 0 ? (
|
||||||
|
<Chart
|
||||||
|
data={hourCounts.map((hc) => hc.count)}
|
||||||
|
labels={hourCounts.map((hc) => hourLabel(hc.hour))}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Text>
|
||||||
|
No entries yet! Start recording sets to see your most active hours
|
||||||
|
of the day.
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
title="Most active days of the week"
|
title="Most active days of the week"
|
||||||
show={showActive}
|
show={showWeek}
|
||||||
setShow={setShowActive}
|
setShow={setShowWeek}
|
||||||
onOk={() => setShowActive(false)}
|
onOk={() => setShowWeek(false)}
|
||||||
>
|
>
|
||||||
If your plan expects an equal # of sets each day of the week, then this
|
If your plan expects an equal # of sets each day of the week, then this
|
||||||
pie graph should be evenly sliced.
|
pie graph should be evenly sliced.
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
title="Most active hours of the day"
|
||||||
|
show={showHour}
|
||||||
|
setShow={setShowHour}
|
||||||
|
onOk={() => setShowHour(false)}
|
||||||
|
>
|
||||||
|
If you find yourself giving up on the gym after 5pm, consider starting
|
||||||
|
earlier! Or vice-versa.
|
||||||
|
</ConfirmDialog>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,8 +85,8 @@ android {
|
||||||
applicationId "com.massive"
|
applicationId "com.massive"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 36191
|
versionCode 36192
|
||||||
versionName "1.165"
|
versionName "1.166"
|
||||||
}
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
release {
|
release {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "massive",
|
"name": "massive",
|
||||||
"version": "1.165",
|
"version": "1.166",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user