diff --git a/backend/dashboard/serializers.py b/backend/dashboard/serializers.py index ddc207b..8563ec4 100644 --- a/backend/dashboard/serializers.py +++ b/backend/dashboard/serializers.py @@ -1,7 +1,7 @@ -from rest_framework import serializers -from .models import UserStats +# from rest_framework import serializers +# from .models import UserStats -class UserStatsSerializer(serializers.ModelSerializer): - class Meta: - model = UserStats - fields = ['health', 'gold', 'experience', 'strength', 'intelligence', 'endurance', 'perception', 'luck', 'level'] \ No newline at end of file +# class UserStatsSerializer(serializers.ModelSerializer): +# class Meta: +# model = UserStats +# fields = ['health', 'gold', 'experience', 'strength', 'intelligence', 'endurance', 'perception', 'luck', 'level'] \ No newline at end of file diff --git a/backend/dashboard/urls.py b/backend/dashboard/urls.py index 56624ca..af8d154 100644 --- a/backend/dashboard/urls.py +++ b/backend/dashboard/urls.py @@ -1,11 +1,12 @@ from django.urls import path, include from rest_framework.routers import DefaultRouter -from .views import DashboardStatsViewSet, DashboardWeeklyViewSet +from .views import DashboardStatsTodoViewSet, DashboardWeeklyViewSet router = DefaultRouter() -router.register(r'dashboard/stats', DashboardStatsViewSet, basename='stats') +router.register(r'dashboard/todostats', DashboardStatsTodoViewSet, basename='statstodo') router.register(r'dashboard/weekly', DashboardWeeklyViewSet, basename='weekly') +router.register(r'dashboard/recstats', DashboardStatsTodoViewSet, basename='statsrec') urlpatterns = [ path('', include(router.urls)), ] diff --git a/backend/dashboard/views.py b/backend/dashboard/views.py index abe0576..b6fd552 100644 --- a/backend/dashboard/views.py +++ b/backend/dashboard/views.py @@ -5,10 +5,13 @@ from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from rest_framework import viewsets, mixins -from tasks.models import Todo +from tasks.models import Todo, RecurrenceTask -class DashboardStatsViewSet(viewsets.GenericViewSet, mixins.ListModelMixin): +class DashboardStatsTodoViewSet(viewsets.GenericViewSet, mixins.ListModelMixin): + """ + A viewset for retrieving statistics related to user tasks for the last 7 days. + """ permission_classes = (IsAuthenticated,) def get_queryset(self): @@ -66,6 +69,27 @@ class DashboardStatsViewSet(viewsets.GenericViewSet, mixins.ListModelMixin): # Overall completion rate total_tasks = Todo.objects.filter(user=user).count() overall_completion_rate = (completed_last_7_days / total_tasks) * 100 if total_tasks > 0 else 0 + + total_completed_tasks = Todo.objects.filter(user=user, completed=True).count() + + total_tasks = Todo.objects.filter(user=user).count() + + today_start = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0) + today_end = timezone.now().replace(hour=23, minute=59, second=59, microsecond=999999) + + tasks_completed_today = Todo.objects.filter( + user=user, + completed=True, + completion_date__gte=today_start, + completion_date__lte=today_end + ).count() + + total_tasks_today = Todo.objects.filter( + user=user, + completion_date__gte=today_start, + completion_date__lte=today_end + ).count() + data = { "completed_last_7_days": completed_last_7_days, @@ -75,6 +99,10 @@ class DashboardStatsViewSet(viewsets.GenericViewSet, mixins.ListModelMixin): "completed_this_week": completed_this_week, "overdue_tasks": overdue_tasks, "overall_completion_rate": overall_completion_rate, + "total_completed_tasks": total_completed_tasks, + "total_tasks" : total_tasks, + "total_tasks_today": total_tasks_today, + "tasks_completed_today": tasks_completed_today, } return Response(data, status=status.HTTP_200_OK) @@ -145,7 +173,142 @@ class DashboardWeeklyViewSet(viewsets.GenericViewSet, mixins.ListModelMixin): return Response(weekly_stats, status=status.HTTP_200_OK) +class DashboardStatsReccurenceViewSet(viewsets.GenericViewSet, mixins.ListModelMixin): + """ + A viewset for retrieving statistics related to user tasks for the last 7 days. + """ + permission_classes = (IsAuthenticated,) + def get_queryset(self): + return RecurrenceTask.objects.all() + + def list(self, request, *args, **kwargs): + user = self.request.user + + # Calculate the start and end date for the last 7 days + end_date = timezone.now() + start_date = end_date - timedelta(days=7) + + # How many tasks were completed in the last 7 days + completed_last_7_days = RecurrenceTask.objects.filter( + user=user, + completed=True, + completion_date__gte=start_date, + completion_date__lte=end_date + ).count() + + # Task assign last week compared with this week + tasks_assigned_last_week = RecurrenceTask.objects.filter( + user=user, + completion_date__gte=start_date - timedelta(days=7), + completion_date__lte=start_date + ).count() + + tasks_assigned_this_week = RecurrenceTask.objects.filter( + user=user, + completion_date__gte=start_date, + completion_date__lte=end_date + ).count() + + # Completed tasks from last week compared with this week + completed_last_week = RecurrenceTask.objects.filter( + user=user, + completed=True, + completion_date__gte=start_date - timedelta(days=7), + completion_date__lte=start_date + ).count() + + completed_this_week = RecurrenceTask.objects.filter( + user=user, + completed=True, + completion_date__gte=start_date, + completion_date__lte=end_date + ).count() + + overdue_tasks = RecurrenceTask.objects.filter( + user=user, + completed=False, + end_event__lt=timezone.now() + ).count() + + # Overall completion rate + total_tasks = RecurrenceTask.objects.filter(user=user).count() + overall_completion_rate = (completed_last_7_days / total_tasks) * 100 if total_tasks > 0 else 0 + + total_completed_tasks = RecurrenceTask.objects.filter( + user=user, + completed=True + ).count() + + total_tasks = RecurrenceTask.objects.filter(user=user).count() + + tasks_completed_today = RecurrenceTask.objects.filter( + user=user, + completed=True, + completion_date__gte=timezone.now().replace(hour=0, minute=0, second=0, microsecond=0) + ).count() + + data = { + "completed_last_7_days": completed_last_7_days, + "tasks_assigned_last_week": tasks_assigned_last_week, + "tasks_assigned_this_week": tasks_assigned_this_week, + "completed_last_week": completed_last_week, + "completed_this_week": completed_this_week, + "overdue_tasks": overdue_tasks, + "overall_completion_rate": overall_completion_rate, + "total_completed_tasks": total_completed_tasks, + "total_tasks" : total_tasks, + "tasks_completed_today": tasks_completed_today, + } + + return Response(data, status=status.HTTP_200_OK) + +# class DashboardStatsAllViewSet(viewsets.GenericViewSet, mixins.ListModelMixin): +# permission_classes = [IsAuthenticated] + +# def get_queryset(self): +# return Todo.objects.filter(user=self.request.user) + +# def list(self, request, *args, **kwargs): +# user = request.user + +# # Calculate task usage statistics +# todo_count = self.get_queryset().count() +# recurrence_task_count = RecurrenceTask.objects.filter(user=user).count() + +# # Calculate how many tasks were completed in the last 7 days +# completed_todo_count_last_week = Todo.objects.filter(user=user, completed=True, last_update__gte=timezone.now() - timezone.timedelta(days=7)).count() +# completed_recurrence_task_count_last_week = RecurrenceTask.objects.filter(user=user, completed=True, last_update__gte=timezone.now() - timezone.timedelta(days=7)).count() + +# # Calculate subtask completion rate +# total_subtasks = Todo.objects.filter(user=user).aggregate(total=Count('subtask__id'))['total'] +# completed_subtasks = Todo.objects.filter(user=user, subtask__completed=True).aggregate(total=Count('subtask__id'))['total'] + +# # Calculate overall completion rate +# total_tasks = todo_count + recurrence_task_count +# completed_tasks = completed_todo_count_last_week + completed_recurrence_task_count_last_week +# overall_completion_rate = (completed_tasks / total_tasks) * 100 if total_tasks > 0 else 0 + +# # pie chart show +# complete_todo_percent_last_week = (completed_todo_count_last_week / todo_count) * 100 if todo_count > 0 else 0 +# complete_recurrence_percent_last_week = (completed_recurrence_task_count_last_week / recurrence_task_count) * 100 if recurrence_task_count > 0 else 0 +# incomplete_task_percent_last_week = 100 - complete_recurrence_percent_last_week - complete_todo_percent_last_week + +# data = { +# 'todo_count': todo_count, +# 'recurrence_task_count': recurrence_task_count, +# 'completed_todo_count_last_week': completed_todo_count_last_week, +# 'completed_recurrence_task_count_last_week': completed_recurrence_task_count_last_week, +# 'total_subtasks': total_subtasks, +# 'completed_subtasks': completed_subtasks, +# 'overall_completion_rate': overall_completion_rate, +# 'complete_todo_percent_last_week': complete_todo_percent_last_week, +# 'complete_recurrence_percent_last_week' : complete_recurrence_percent_last_week, +# 'incomplete_task_percent_last_week': incomplete_task_percent_last_week, +# } + +# return Response(data, status=status.HTTP_200_OK) + # class DashboardStatsAPIView(APIView): # permission_classes = [IsAuthenticated] diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index a917ca5..625b9b8 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -11,7 +11,7 @@ import { SideNav } from "./components/navigations/IconSideNav"; import { Eisenhower } from "./components/EisenhowerMatrix/Eisenhower"; import { PrivateRoute } from "./PrivateRoute"; import { ProfileUpdatePage } from "./components/profile/profilePage"; -import { Dashboard } from "./components/dashboard/dashboard"; +import { Dashboard } from "./components/dashboard/Dashboard"; import { LandingPage } from "./components/landingPage/LandingPage"; import { PublicRoute } from "./PublicRoute"; import { useAuth } from "./hooks/AuthHooks"; diff --git a/frontend/src/components/dashboard/KpiCard.jsx b/frontend/src/components/dashboard/KpiCard.jsx index c5c3165..85c74c9 100644 --- a/frontend/src/components/dashboard/KpiCard.jsx +++ b/frontend/src/components/dashboard/KpiCard.jsx @@ -13,7 +13,7 @@ export function KpiCard() { useEffect(() => { const fetchKpiCardData = async () => { try { - const response = await axiosInstance.get("/dashboard/stats/"); + const response = await axiosInstance.get("/dashboard/todostats/"); const completedThisWeek = response.data.completed_this_week || 0; const completedLastWeek = response.data.completed_last_week || 0; const percentage = (completedThisWeek / completedLastWeek) * 100; diff --git a/frontend/src/components/dashboard/DonutChart.jsx b/frontend/src/components/dashboard/PieChart.jsx similarity index 64% rename from frontend/src/components/dashboard/DonutChart.jsx rename to frontend/src/components/dashboard/PieChart.jsx index 63fc591..645137b 100644 --- a/frontend/src/components/dashboard/DonutChart.jsx +++ b/frontend/src/components/dashboard/PieChart.jsx @@ -8,13 +8,13 @@ export function DonutChartGraph() { useEffect(() => { const fetchDonutData = async () => { try { - const response = await axiosInstance.get("/dashboard/stats/"); - const todoCount = response.data.todo_count || 0; - const recurrenceCount = response.data.recurrence_count || 0; + const response = await axiosInstance.get("/dashboard/todostats/"); + const totalTask = response.data.total_tasks || 0; + const completedTask = response.data.total_completed_tasks || 0; const donutData = [ - { name: "Todo", count: todoCount }, - { name: "Recurrence", count: recurrenceCount }, + { name: "Completed task", count: totalTask }, + { name: "Total task", count: completedTask }, ]; setDonutData(donutData); @@ -31,9 +31,10 @@ export function DonutChartGraph() { data={donutData} category="count" index="name" - colors={["rose", "yellow", "orange"]} + colors={["rose", "yellow"]} showAnimation radius={25} + variant="pie" /> ); } diff --git a/frontend/src/components/dashboard/ProgressCircle.jsx b/frontend/src/components/dashboard/ProgressCircle.jsx index 683781e..4a290d9 100644 --- a/frontend/src/components/dashboard/ProgressCircle.jsx +++ b/frontend/src/components/dashboard/ProgressCircle.jsx @@ -8,7 +8,7 @@ export function ProgressCircleChart() { useEffect(() => { const fetchProgressData = async () => { try { - const response = await axiosInstance.get("/dashboard/stats/"); + const response = await axiosInstance.get("/dashboard/todostats/"); let completedLastWeek = response.data.completed_last_week || 0; let assignLastWeek = response.data.tasks_assigned_last_week || 0; diff --git a/frontend/src/components/dashboard/dashboard.jsx b/frontend/src/components/dashboard/dashboard.jsx index 31cc71f..1901ebb 100644 --- a/frontend/src/components/dashboard/dashboard.jsx +++ b/frontend/src/components/dashboard/dashboard.jsx @@ -1,22 +1,66 @@ -import { Card, Grid, Tab, TabGroup, TabList, TabPanel, TabPanels, Text, Title, Legend } from "@tremor/react"; +import { + Card, + Grid, + Tab, + TabGroup, + TabList, + TabPanel, + TabPanels, + Text, + Title, + Legend, + Metric, + ProgressCircle, + Flex, +} from "@tremor/react"; import { KpiCard } from "./KpiCard"; import { BarChartGraph } from "./Barchart"; -import { DonutChartGraph } from "./DonutChart"; import { AreaChartGraph } from "./Areachart"; +import { DonutChartGraph } from "./PieChart"; import { ProgressCircleChart } from "./ProgressCircle"; -import { useState } from "react"; +import { axiosInstance } from "src/api/AxiosConfig"; +import { useEffect, useState } from "react"; + +const valueFormatter = (number) => + `$ ${new Intl.NumberFormat("us").format(number).toString()}`; export function Dashboard() { - const [value, setValue] = useState({ - from: new Date(2021, 0, 1), - to: new Date(2023, 0, 7), - }); + const [totalTask, setTotalTask] = useState(0); + const [totalCompletedTasks, settotalCompletedTasks] = useState(0); + const [totalCompletedTasksToday, setTotalCompletedTasksToday] = useState(0); + const [progressData, setProgressData] = useState(0); + const [overdueTask, setOverdueTask] = useState(0); + + useEffect(() => { + const fetchData = async () => { + const response = await axiosInstance.get("/dashboard/todostats/"); + const totalTaskValue = response.data.total_tasks || 0; + const totalCompletedTasksValue = response.data.total_completed_tasks || 0; + const totalCompletedTasksTodayValue = + response.data.total_completed_tasks_today || 0; + const totalTaskToday = response.data.total_task_today || 0; + const totalCompletedTasksToday = response.data.tasks_completed_today || 0; + const overdueTasks = response.data.overdue_tasks || 0; + + const progress = + (totalCompletedTasksToday / totalCompletedTasksToday) * 100; + + setTotalTask(totalTaskValue); + settotalCompletedTasks(totalCompletedTasksValue); + setTotalCompletedTasksToday(totalCompletedTasksTodayValue); + setTotalTaskToday(totalTaskToday); + setProgressData(progress); + setOverdueTask(overdueTasks); + }; + + fetchData(); + }, []); + return (
Dashboard All of your progress will be shown right here. -
@@ -39,8 +83,9 @@ export function Dashboard() { + categories={["Completed Tasks"]} + colors={["indigo"]} + > @@ -50,19 +95,77 @@ export function Dashboard() { + {/*Overview Tab*/} -
+ + + Overview + + Total tasks + {totalTask} + +

+ + Total completed tasks + {totalCompletedTasks} + +

+ + Overdue tasks + {overdueTask} + +

+
+ {/*Pie chart graph*/} - Tasks + Overall completion rate
-
+ {/*Progress circle graph*/} + + + Today's progress +
+ + + + {progressData.toFixed(0)} % + + +

+ +
+
+