AnalyticsView
This commit is contained in:
parent
4222c910eb
commit
10b1ed944d
@ -8,9 +8,10 @@ import { useSearchParams } from "next/navigation";
|
||||
import { parseISO, format as fmt } from "date-fns";
|
||||
import { DatePickerInput } from '@mantine/dates';
|
||||
import { Calendar1, MenuIcon } from "lucide-react";
|
||||
import { Anchor, Button, Menu } from "@mantine/core";
|
||||
import { Anchor, Button, ButtonGroup, Menu } from "@mantine/core";
|
||||
import { useTooltip, useTooltipInPortal, defaultStyles } from '@visx/tooltip';
|
||||
import PieChart from "./PieChart";
|
||||
// import PieChart from "./PieChart";
|
||||
import { Cell, LabelList, Pie, PieChart, Tooltip } from "recharts";
|
||||
|
||||
import { useTimezone } from "@/lib/userLocalSettings/client";
|
||||
import TimeseriesChart from "./Timeseries";
|
||||
@ -56,6 +57,7 @@ export default function AnalyticsView() {
|
||||
|
||||
const [dateRange, setDateRange] = useState(initialDateRange);
|
||||
const [datePickerRange, setDatePickerRange] = useState(initialDateRange);
|
||||
const [hideSleep, setHideSleep] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (datePickerRef.current?.getAttribute("aria-expanded") === "false") {
|
||||
@ -71,19 +73,34 @@ export default function AnalyticsView() {
|
||||
scroll: true,
|
||||
});
|
||||
|
||||
const categoryFrequencies = api.hours.categoryFrequencies.useQuery({
|
||||
const rawCategoryFrequencies = api.hours.categoryFrequencies.useQuery({
|
||||
dateRange,
|
||||
timezone: useTimezone(),
|
||||
}).data ?? [];
|
||||
}).data?.filter(
|
||||
(category) => category.categoryCode != undefined
|
||||
) ?? [];
|
||||
|
||||
const categoryFrequencies = hideSleep ? rawCategoryFrequencies.filter((category) => category.categoryCode > 1) : rawCategoryFrequencies;
|
||||
|
||||
const maybeExtendWindow = (dateRange: Date[]) => {
|
||||
// If distance between dates is less than 2 days, extend the first date back by 14 days
|
||||
if (spacetime(dateRange[0]).diff(dateRange[1], "day") < 2) {
|
||||
return [
|
||||
spacetime(dateRange[0]).subtract(14, "day").toNativeDate(),
|
||||
dateRange[1]
|
||||
];
|
||||
}
|
||||
return [dateRange[0], dateRange[1]];
|
||||
}
|
||||
|
||||
const weightData = api.measurements.getTimeseries.useQuery({
|
||||
dateRange,
|
||||
dateRange: maybeExtendWindow(dateRange) as [Date, Date],
|
||||
timezone: useTimezone(),
|
||||
metricName: "weight"
|
||||
}).data ?? [];
|
||||
|
||||
return (
|
||||
<div className="px-4 flex flex-col gap-y-4">
|
||||
<div className="px-4 flex flex-col">
|
||||
<div className="flex justify-between">
|
||||
<h1>Analytics for
|
||||
{dateRange[0].getUTCDate() == dateRange[1].getUTCDate()
|
||||
@ -147,12 +164,29 @@ export default function AnalyticsView() {
|
||||
</Menu></div>
|
||||
</div>
|
||||
|
||||
<div className="flex hidden">
|
||||
<PieChart width={500} height={500}
|
||||
data={categoryFrequencies}
|
||||
<div className="mt-8 pt-4 flex gap-4">
|
||||
<h2>Time</h2>
|
||||
{categoryFrequencies.length === 0 ? <LoadingSpinner /> :
|
||||
<div className="w-full flex flex-col lg:flex-row gap-4">
|
||||
|
||||
<PieChart width={500} height={500} startAngle={180} endAngle={0} >
|
||||
<Pie data={categoryFrequencies} dataKey="percentage" nameKey="categoryName" label={false}
|
||||
paddingAngle={0} stroke={(c) => console.log(c)}>
|
||||
{categoryFrequencies.sort(
|
||||
(a, b) => b.count - a.count
|
||||
).map((c, _i) => (
|
||||
<Cell key={`pie-category-${c.id}`} fill={c.background}
|
||||
style={{ outline: 'none !important' }}
|
||||
/>
|
||||
))}
|
||||
</Pie>
|
||||
<Tooltip />
|
||||
</PieChart>
|
||||
|
||||
<div className="grow">
|
||||
<div className="grid font-bold border-b border-gray-200"
|
||||
<div className="flex flex-col justify-evenly h-full">
|
||||
<div>
|
||||
<div className="grid font-bold border-b border-gray-200 pl-4"
|
||||
style={{
|
||||
gridTemplateColumns: "1fr 1fr"
|
||||
}}
|
||||
@ -168,9 +202,11 @@ export default function AnalyticsView() {
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.map((category, i) => (
|
||||
|
||||
<div key={i} className="grid"
|
||||
<div key={i} className="grid p-1 pl-4"
|
||||
style={{
|
||||
gridTemplateColumns: "1fr 1fr"
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
color: category.inverse,
|
||||
backgroundColor: category.color
|
||||
}}
|
||||
>
|
||||
<div className="whitespace-nowrap">
|
||||
@ -180,19 +216,30 @@ export default function AnalyticsView() {
|
||||
{category.count} hours
|
||||
</div></div>
|
||||
))
|
||||
}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 bg-accent w-fit p-2 border border-primary rounded-md cursor-pointer flex flex-col items-center">
|
||||
Sleep
|
||||
<ButtonGroup className="mt-2">
|
||||
<Button
|
||||
onClick={() => setHideSleep(true)}
|
||||
color={hideSleep ? "gray" : "primary"}
|
||||
>
|
||||
Hide
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => setHideSleep(false)}
|
||||
color={hideSleep ? "primary" : "gray"}
|
||||
>
|
||||
Show
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<h2>Weight</h2>
|
||||
<div>
|
||||
{
|
||||
!weightData ? <LoadingSpinner /> :
|
||||
<TimeseriesChart data={weightData} />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<div className="mt-8 pt-4 flex gap-4">
|
||||
<h2 className="">Drugs</h2>
|
||||
<div>
|
||||
{
|
||||
@ -206,7 +253,19 @@ export default function AnalyticsView() {
|
||||
</ul>
|
||||
}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="mt-8 pt-4 flex gap-4">
|
||||
<h2>Weight</h2>
|
||||
{
|
||||
weightData.length === 0 ? <LoadingSpinner /> :
|
||||
<div>
|
||||
<TimeseriesChart data={weightData} />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
</div >
|
||||
|
||||
);
|
||||
}
|
||||
@ -29,7 +29,6 @@ export default function TimeseriesChart({ data }) {
|
||||
smoothed: polyResult.predict(i)[1],
|
||||
};
|
||||
}));
|
||||
console.log(polyResult);
|
||||
|
||||
return (
|
||||
<div className='flex flex-col items-center'>
|
||||
|
||||
@ -229,6 +229,8 @@ export const hoursAppRouter = router({
|
||||
{
|
||||
count: z.number(),
|
||||
percentage: z.number(),
|
||||
color: z.string(),
|
||||
inverse: z.string(),
|
||||
...zHourSchema.shape
|
||||
}
|
||||
)))
|
||||
@ -257,6 +259,8 @@ export const hoursAppRouter = router({
|
||||
if (!categoriesList[h.categoryCode]) {
|
||||
categoriesList[h.categoryCode] = {
|
||||
count: 0,
|
||||
color: h.background,
|
||||
inverse: h.foreground,
|
||||
...h
|
||||
};
|
||||
}
|
||||
@ -269,7 +273,7 @@ export const hoursAppRouter = router({
|
||||
const percentage = (count / totalHours);
|
||||
return {
|
||||
...categoriesList[categoryCode],
|
||||
percentage: percentage
|
||||
percentage: percentage,
|
||||
};
|
||||
});
|
||||
return categoryPercentages;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user