diff --git a/app/routes/statistics.tsx b/app/routes/statistics.tsx index f4f2203..07631b4 100644 --- a/app/routes/statistics.tsx +++ b/app/routes/statistics.tsx @@ -1,21 +1,99 @@ -import type { User, Team } from "@prisma/client"; +import type { User, Team, Expense } from "@prisma/client"; import type { LoaderFunction } from "remix"; -import { redirect, Link, useLoaderData, useCatch } from "remix"; -import { getUser } from "~/utils/session.server"; +import { redirect, useLoaderData, useCatch, Link } from "remix"; +import { db } from "~/utils/db.server"; +import { getUser, requireUserId } from "~/utils/session.server"; import Header from "../components/Header"; type LoaderData = { user: (User & { team: Team & { members: User[] } }) | null; + thisMonth: { + count: number; + amount: number; + }; + count: number; + avg: number; + statsByMonth: { + [month: string]: { + count: number; + amount: number; + }; + }; }; export const loader: LoaderFunction = async ({ request }) => { + const userId = requireUserId(request); const user = await getUser(request); - if (!user?.id) { + if (!user?.id || !userId) { return redirect("/login"); } + const expenses = await db.expense.aggregate({ + _avg: { + amount: true, + }, + _count: { + _all: true, + }, + where: { userId: user.id }, + orderBy: { + createdAt: "asc", + }, + }); + + let thisMonth = new Date(); + thisMonth.setDate(0); + const thisMonthExp = await db.expense.aggregate({ + _avg: { + amount: true, + }, + _count: { + _all: true, + }, + where: { userId: user.id, createdAt: { gt: thisMonth } }, + orderBy: { + createdAt: "asc", + }, + }); + + const allExpenses = await db.expense.findMany({ + where: { userId: user.id }, + }); + + const statsByMonth = allExpenses.reduce( + ( + acc: { [key: string]: { count: number; amount: number } }, + exp: Expense + ) => { + const month = new Intl.DateTimeFormat("it", { + month: "2-digit", + year: "numeric", + }).format(new Date(exp.createdAt)); + if (!acc[month]) { + acc[month] = { + count: 0, + amount: 0, + }; + } + + acc[month].count += 1; + acc[month].amount += exp.amount; + return acc; + }, + {} + ); + + console.log(statsByMonth); + const data: LoaderData = { user, + thisMonth: { + count: thisMonthExp?._count?._all ?? 0, + amount: thisMonthExp?._avg?.amount ?? 0, + }, + count: expenses._count._all ?? 0, + avg: expenses._avg?.amount ?? 0, + statsByMonth, }; return data; }; @@ -26,33 +104,52 @@ export default function ListExpensesRoute() { return ( <>
-
-
-
-

Work in progress

-

- - This page is under construction. -

- - - - - Back - +
+

Statistics

+ +
+
+
Expenses count
+
{data.count}
+
+
+ +
+
Average per month
+
{data.avg} €
+
+ +
+
This month
+
{data.thisMonth.amount} €
+
{data.thisMonth.count} expenses
-
+ +

Expenses by month

+
+
+ + + + + + + + + + {Object.keys(data.statsByMonth)?.map((month) => ( + + + + + + ))} + +
MonthTotalCount
{month}{data.statsByMonth[month].amount} €{data.statsByMonth[month].count}
+
+
+ ); }