From 8c91b3030ab7483c79e71892050bc1b8f5f1af75 Mon Sep 17 00:00:00 2001 From: Chaiyawut Thengket Date: Fri, 17 Nov 2023 10:44:54 +0700 Subject: [PATCH 1/2] create apiview --- backend/core/settings.py | 1 + backend/core/urls.py | 1 + backend/dashboard/__init__.py | 0 backend/dashboard/admin.py | 3 ++ backend/dashboard/apps.py | 6 +++ backend/dashboard/migrations/__init__.py | 0 backend/dashboard/models.py | 3 ++ backend/dashboard/serializers.py | 7 +++ backend/dashboard/tests.py | 3 ++ backend/dashboard/urls.py | 6 +++ backend/dashboard/views.py | 58 ++++++++++++++++++++++++ 11 files changed, 88 insertions(+) create mode 100644 backend/dashboard/__init__.py create mode 100644 backend/dashboard/admin.py create mode 100644 backend/dashboard/apps.py create mode 100644 backend/dashboard/migrations/__init__.py create mode 100644 backend/dashboard/models.py create mode 100644 backend/dashboard/serializers.py create mode 100644 backend/dashboard/tests.py create mode 100644 backend/dashboard/urls.py create mode 100644 backend/dashboard/views.py diff --git a/backend/core/settings.py b/backend/core/settings.py index 5c01d05..4936805 100644 --- a/backend/core/settings.py +++ b/backend/core/settings.py @@ -52,6 +52,7 @@ INSTALLED_APPS = [ 'tasks', 'users', 'authentications', + 'dashboard', 'corsheaders', 'drf_spectacular', diff --git a/backend/core/urls.py b/backend/core/urls.py index a02869c..434a21f 100644 --- a/backend/core/urls.py +++ b/backend/core/urls.py @@ -27,4 +27,5 @@ urlpatterns = [ path('api/schema/', SpectacularAPIView.as_view(), name='schema'), path('api/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'), + path('dashboard/', include('dashboard.urls')), ] \ No newline at end of file diff --git a/backend/dashboard/__init__.py b/backend/dashboard/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/dashboard/admin.py b/backend/dashboard/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/backend/dashboard/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/backend/dashboard/apps.py b/backend/dashboard/apps.py new file mode 100644 index 0000000..7b1cc05 --- /dev/null +++ b/backend/dashboard/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class DashboardConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'dashboard' diff --git a/backend/dashboard/migrations/__init__.py b/backend/dashboard/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/dashboard/models.py b/backend/dashboard/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/backend/dashboard/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/backend/dashboard/serializers.py b/backend/dashboard/serializers.py new file mode 100644 index 0000000..ddc207b --- /dev/null +++ b/backend/dashboard/serializers.py @@ -0,0 +1,7 @@ +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 diff --git a/backend/dashboard/tests.py b/backend/dashboard/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/backend/dashboard/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/backend/dashboard/urls.py b/backend/dashboard/urls.py new file mode 100644 index 0000000..beb8f1b --- /dev/null +++ b/backend/dashboard/urls.py @@ -0,0 +1,6 @@ +from django.urls import path +from .views import DashboardStatsAPIView + +urlpatterns = [ + path('dashboard/stats/', DashboardStatsAPIView.as_view(), name='dashboard-stats'), +] diff --git a/backend/dashboard/views.py b/backend/dashboard/views.py new file mode 100644 index 0000000..4475d77 --- /dev/null +++ b/backend/dashboard/views.py @@ -0,0 +1,58 @@ +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import status +from rest_framework.permissions import IsAuthenticated +from django.db.models import Count +from django.utils import timezone + +from tasks.models import Todo, RecurrenceTask + +class DashboardStatsAPIView(APIView): + permission_classes = [IsAuthenticated] + + def get(self, request): + user = request.user + + # Calculate task usage statistics + todo_count = Todo.objects.filter(user=user).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 + + 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, + } + + return Response(data, status=status.HTTP_200_OK) + + def post(self, request): + # Handle incoming data from the POST request + # Update the necessary information based on the data + + task_id = request.data.get('task_id') + is_completed = request.data.get('is_completed') + + try: + task = Todo.objects.get(id=task_id, user=request.user) + task.completed = is_completed + task.save() + return Response({'message': 'Task completion status updated successfully'}, status=status.HTTP_200_OK) + except Todo.DoesNotExist: + return Response({'error': 'Task not found'}, status=status.HTTP_404_NOT_FOUND) \ No newline at end of file From e372c1b3ba4c5bf17e046e8a47c324cd4c6b95b4 Mon Sep 17 00:00:00 2001 From: sosokker Date: Mon, 20 Nov 2023 01:38:34 +0700 Subject: [PATCH 2/2] Update API url --- backend/core/urls.py | 2 +- backend/dashboard/models.py | 3 --- ...recurrencetask_completed_todo_completed.py | 23 +++++++++++++++++++ backend/tasks/models.py | 3 ++- 4 files changed, 26 insertions(+), 5 deletions(-) delete mode 100644 backend/dashboard/models.py create mode 100644 backend/tasks/migrations/0014_recurrencetask_completed_todo_completed.py diff --git a/backend/core/urls.py b/backend/core/urls.py index 434a21f..06a4fd2 100644 --- a/backend/core/urls.py +++ b/backend/core/urls.py @@ -27,5 +27,5 @@ urlpatterns = [ path('api/schema/', SpectacularAPIView.as_view(), name='schema'), path('api/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'), - path('dashboard/', include('dashboard.urls')), + path('api/', include('dashboard.urls')), ] \ No newline at end of file diff --git a/backend/dashboard/models.py b/backend/dashboard/models.py deleted file mode 100644 index 71a8362..0000000 --- a/backend/dashboard/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/backend/tasks/migrations/0014_recurrencetask_completed_todo_completed.py b/backend/tasks/migrations/0014_recurrencetask_completed_todo_completed.py new file mode 100644 index 0000000..d89360d --- /dev/null +++ b/backend/tasks/migrations/0014_recurrencetask_completed_todo_completed.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.6 on 2023-11-17 16:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tasks', '0013_alter_recurrencetask_recurrence_rule'), + ] + + operations = [ + migrations.AddField( + model_name='recurrencetask', + name='completed', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='todo', + name='completed', + field=models.BooleanField(default=False), + ), + ] diff --git a/backend/tasks/models.py b/backend/tasks/models.py index a8fc4e5..9a914c0 100644 --- a/backend/tasks/models.py +++ b/backend/tasks/models.py @@ -18,7 +18,6 @@ class Task(models.Model): :param title: Title of the task. :param notes: Optional additional notes for the task. :param tags: Associated tags for the task. - :param completed: A boolean field indicating whether the task is completed. :param importance: The importance of the task (range: 1 to 5) :param difficulty: The difficulty of the task (range: 1 to 5). :param challenge: Associated challenge (optional). @@ -62,12 +61,14 @@ class Todo(Task): NOT_IMPORTANT_URGENT = 3, 'Not Important & Urgent' NOT_IMPORTANT_NOT_URGENT = 4, 'Not Important & Not Urgent' + completed = models.BooleanField(default=False) priority = models.PositiveSmallIntegerField(choices=EisenhowerMatrix.choices, default=EisenhowerMatrix.NOT_IMPORTANT_NOT_URGENT) def __str__(self): return self.title class RecurrenceTask(Task): + completed = models.BooleanField(default=False) recurrence_rule = models.CharField() def __str__(self) -> str: