Skip to content

Commit

Permalink
feat: add stats to Month header
Browse files Browse the repository at this point in the history
  • Loading branch information
HereEast committed Sep 10, 2024
1 parent d392221 commit 4ae5940
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 15 deletions.
28 changes: 26 additions & 2 deletions client/src/api/getEntries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,39 @@ import axios from "axios";
import { BASE_URL } from "~/utils";
import { IEntry } from "~/~/models/Entry";

export async function getEntries(
export async function getMonthEntriesByTaskId(
userId: string,
taskId: mongoose.Types.ObjectId | undefined,
year: number,
month: number,
): Promise<IEntry[] | undefined> {
try {
const response = await axios.get(
`${BASE_URL}/entries/${userId}/${taskId}/${year}/${month}`,
`${BASE_URL}/entries/month/task/${userId}/${taskId}/${year}/${month}`,
);

if (response.status !== 200) {
throw new Error(`${response.status} ${response.statusText}`);
}

const data = response.data;

return data;
} catch (err) {
console.log(err); // Handle
}
}

// All daily entries
export async function getAllDailyEntries(
userId: string,
year: number,
month: number,
day: number,
): Promise<IEntry[] | undefined> {
try {
const response = await axios.get(
`${BASE_URL}/entries/day/${userId}/${year}/${month}/${day}`,
);

if (response.status !== 200) {
Expand Down
24 changes: 19 additions & 5 deletions client/src/components/MonthCardHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useAppContext } from "~/hooks";
import { useDayEntries } from "~/hooks/useDayEntries";
import { cn, getDateDetails } from "~/utils";
import { useAppContext, useAllDailyEntries } from "~/hooks";
import { calculateStatusPercentage, cn, getDateDetails } from "~/utils";

interface MonthCardHeaderProps {
title: string;
Expand All @@ -13,11 +12,26 @@ export function MonthCardHeader({ title, classes }: MonthCardHeaderProps) {
const today = new Date();
const { year, month, day } = getDateDetails(today);

// const { data, isLoading, error } = useDayEntries(userId, year, month, day);
const { data, isLoading, error } = useAllDailyEntries(
userId,
year,
month,
day,
);

const statuses = data?.map((entry) => entry.status);

const percentage = calculateStatusPercentage(statuses);

return (
<div className={cn(classes)}>
<div className={cn("flex w-full justify-between items-center", classes)}>
<h2 className="text-xl font-semibold capitalize">{title}</h2>

<div className="space-x-1 text-sm">
<span>{`${data?.length} tasks`}</span>
<span></span>
<span>{`${percentage}% today 🔥`}</span>
</div>
</div>
);
}
1 change: 1 addition & 0 deletions client/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./useTasks";
export * from "./useUser";
export * from "./useEntries";
export * from "./useContext";
export * from "./useAllDailyEntries";
38 changes: 38 additions & 0 deletions client/src/hooks/useAllDailyEntries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useEffect, useState } from "react";

import { getAllDailyEntries } from "~/api";
import { IEntry } from "~/~/models/Entry";

export function useAllDailyEntries(
userId: string,
year: number,
month: number,
day: number,
) {
const [data, setData] = useState<IEntry[] | undefined>([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(false);

useEffect(() => {
async function fetchAllDailyEntries() {
setIsLoading(true);
setError(false);

try {
const entries = await getAllDailyEntries(userId, year, month, day);

setData(entries);
setIsLoading(false);
} catch (err) {
setError(true);
console.log("Error", err);
} finally {
setIsLoading(false);
}
}

fetchAllDailyEntries();
}, [userId, year, month, day]);

return { data, isLoading, error };
}
9 changes: 7 additions & 2 deletions client/src/hooks/useEntries.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useState } from "react";
import mongoose from "mongoose";

import { getEntries } from "~/api";
import { getMonthEntriesByTaskId } from "~/api";
import { IEntry } from "~/~/models/Entry";

export function useEntries(
Expand All @@ -20,7 +20,12 @@ export function useEntries(
setError(false);

try {
const entries = await getEntries(userId, taskId, year, month);
const entries = await getMonthEntriesByTaskId(
userId,
taskId,
year,
month,
);

setData(entries);
setIsLoading(false);
Expand Down
19 changes: 17 additions & 2 deletions client/src/utils/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

import { MonthType } from "~/~/utils/types";
import { MonthType, StatusType } from "~/~/utils/types";

// Calculate % of accomplishment
export function calculateStatusPercentage(statuses: StatusType[] | undefined) {
if (!statuses || statuses.length === 0) {
return 0;
}

const maxStatusValue: StatusType = 5;
const totalPossibleScore = statuses.length * maxStatusValue;

const totalScore = statuses.reduce<number>((sum, status) => sum + status, 0);
const percentage = (totalScore / totalPossibleScore) * 100;

return percentage;
}

// Get date details
export function getDateDetails(date: Date) {
return {
year: date.getFullYear(),
month: date.getMonth(),
month: date.getMonth() + 1,
day: date.getDate(),
};
}
Expand Down
5 changes: 3 additions & 2 deletions server/src/api/entries.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import express from "express";

import { getTaskEntriesByMonth } from "../controllers/getEntries.js";
import { getAllDailyEntries, getMonthEntriesByTaskId } from "../controllers/getEntries.js";

const router = express.Router();

router.route("/:userId/:taskId/:year/:month").get(getTaskEntriesByMonth);
router.route("/month/task/:userId/:taskId/:year/:month").get(getMonthEntriesByTaskId);
router.route("/day/:userId/:year/:month/:day").get(getAllDailyEntries);

export { router as entriesRouter };
35 changes: 33 additions & 2 deletions server/src/controllers/getEntries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Request, Response } from "express";

import { Entry } from "../models/Entry.js";

// Get Entries by year, month, taskId
export async function getTaskEntriesByMonth(req: Request, res: Response) {
// Month entries by taskId
export async function getMonthEntriesByTaskId(req: Request, res: Response) {
const { userId, taskId, year, month } = req.params;

if (!taskId || !userId || !year || !month) {
Expand All @@ -21,3 +21,34 @@ export async function getTaskEntriesByMonth(req: Request, res: Response) {

return res.json(entries);
}

// Get all daily entries
export async function getAllDailyEntries(req: Request, res: Response) {
const { userId, year, month, day } = req.params;

if (!userId || !year || !month || !day) {
throw new Error("Some parameters are missing: userId, year, month, day.");
}

const parsedYear = Number(year);
const parsedMonth = Number(month) - 1;
const parsedDay = Number(day);

const startOfDay = new Date(parsedYear, parsedMonth, parsedDay);
const endOfDay = new Date(parsedYear, parsedMonth, parsedDay + 1);

try {
const entries = await Entry.find({
userId,
entryDate: { $gte: startOfDay, $lt: endOfDay },
}).exec();

return res.json(entries);
} catch (err) {
console.error("Error fetching daily entries:", err);

return res.status(500).json({
message: "Internal server error in getAllDailyEntries().",
});
}
}

0 comments on commit 4ae5940

Please sign in to comment.