From bca1aee9f32ca3968e7fb0af0406e574da4111ef Mon Sep 17 00:00:00 2001
From: hollum <hollum@hotmail.com>
Date: Mon, 7 Mar 2022 14:58:11 +0100
Subject: [PATCH] added possibility to add goals to backend

---
 backend/secfit/workouts/models.py      | 22 +++++++++++
 backend/secfit/workouts/serializers.py | 17 ++++++++-
 backend/secfit/workouts/urls.py        |  1 +
 backend/secfit/workouts/views.py       | 52 +++++++++++++++++++++++++-
 frontend/www/goal.html                 |  2 +-
 frontend/www/scripts/goal.js           | 27 ++++++-------
 frontend/www/scripts/goals.js          | 15 ++++++++
 7 files changed, 119 insertions(+), 17 deletions(-)

diff --git a/backend/secfit/workouts/models.py b/backend/secfit/workouts/models.py
index 0f6214f..f8c0c3d 100644
--- a/backend/secfit/workouts/models.py
+++ b/backend/secfit/workouts/models.py
@@ -92,6 +92,28 @@ class Exercise(models.Model):
     def __str__(self):
         return self.name
 
+class Goal(models.Model):
+    """Django model for an exercise type that users can create.
+
+    Each exercise instance must have an exercise type, e.g., Pushups, Crunches, or Lunges.
+
+    Attributes:
+        name:        Name of the exercise type
+        description: Description of the exercise type
+        duration:    Duration of one unit of the exercise
+        calories:    Calories spent per minute
+        muscleGroup: What major muscle group is used in the exercise
+        unit:        Name of the unit for the exercise type (e.g., reps, seconds)
+    """
+
+    name = models.CharField(max_length=100)
+    description = models.TextField()
+    date = models.DateTimeField()
+    exercise = models.TextField()
+
+    def __str__(self):
+        return self.name
+
 
 class ExerciseInstance(models.Model):
     """Django model for an instance of an exercise.
diff --git a/backend/secfit/workouts/serializers.py b/backend/secfit/workouts/serializers.py
index 6abbe31..b21342d 100644
--- a/backend/secfit/workouts/serializers.py
+++ b/backend/secfit/workouts/serializers.py
@@ -2,7 +2,7 @@
 """
 from rest_framework import serializers
 from rest_framework.serializers import HyperlinkedRelatedField
-from workouts.models import Workout, Exercise, ExerciseInstance, WorkoutFile, RememberMe
+from workouts.models import Workout, Exercise, ExerciseInstance, Goal, WorkoutFile, RememberMe
 
 
 class ExerciseInstanceSerializer(serializers.HyperlinkedModelSerializer):
@@ -215,6 +215,21 @@ class ExerciseSerializer(serializers.HyperlinkedModelSerializer):
         model = Exercise
         fields = ["url", "id", "name", "description", "duration", "calories", "muscleGroup", "unit", "instances"]
 
+class GoalSerializer(serializers.HyperlinkedModelSerializer):
+    """Serializer for an Exercise. Hyperlinks are used for relationships by default.
+
+    Serialized fields: url, id, name, description, duration, calories, muscle group, unit, instances
+
+    Attributes:
+        instances:  Associated exercise instances with this Exercise type. Hyperlinks.
+    """
+
+
+
+    class Meta:
+        model = Goal
+        fields = ["id", "name", "description", "date", "exercise"]
+
 
 class RememberMeSerializer(serializers.HyperlinkedModelSerializer):
     """Serializer for an RememberMe. Hyperlinks are used for relationships by default.
diff --git a/backend/secfit/workouts/urls.py b/backend/secfit/workouts/urls.py
index 7c46a3f..a58f818 100644
--- a/backend/secfit/workouts/urls.py
+++ b/backend/secfit/workouts/urls.py
@@ -16,6 +16,7 @@ urlpatterns = format_suffix_patterns(
             views.WorkoutDetail.as_view(),
             name="workout-detail",
         ),
+        path("api/goal/", views.GoalList.as_view(), name="goal-list"),
         path("api/exercises/", views.ExerciseList.as_view(), name="exercise-list"),
         path(
             "api/exercises/<int:pk>/",
diff --git a/backend/secfit/workouts/views.py b/backend/secfit/workouts/views.py
index efddf40..db217e0 100644
--- a/backend/secfit/workouts/views.py
+++ b/backend/secfit/workouts/views.py
@@ -22,8 +22,8 @@ from workouts.permissions import (
     IsWorkoutPublic,
 )
 from workouts.mixins import CreateListModelMixin
-from workouts.models import Workout, Exercise, ExerciseInstance, WorkoutFile
-from workouts.serializers import WorkoutSerializer, ExerciseSerializer
+from workouts.models import Workout, Exercise, ExerciseInstance, Goal, WorkoutFile
+from workouts.serializers import WorkoutSerializer, ExerciseSerializer, GoalSerializer
 from workouts.serializers import RememberMeSerializer
 from workouts.serializers import ExerciseInstanceSerializer, WorkoutFileSerializer
 from django.core.exceptions import PermissionDenied
@@ -41,6 +41,7 @@ def api_root(request, format=None):
         {
             "users": reverse("user-list", request=request, format=format),
             "workouts": reverse("workout-list", request=request, format=format),
+            "goals": reverse("goal-list", request=request, format=format),
             "exercises": reverse("exercise-list", request=request, format=format),
             "exercise-instances": reverse(
                 "exercise-instance-list", request=request, format=format
@@ -221,6 +222,53 @@ class ExerciseDetail(
     def delete(self, request, *args, **kwargs):
         return self.destroy(request, *args, **kwargs)
 
+class GoalList(
+    mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView
+):
+    """Class defining the web response for the creation of an Exercise, or
+    a list of Exercises.
+
+    HTTP methods: GET, POST
+    """
+
+    queryset = Goal.objects.all()
+    serializer_class = GoalSerializer
+    permission_classes = [permissions.IsAuthenticated]
+
+    def get(self, request, *args, **kwargs):
+        return self.list(request, *args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        return self.create(request, *args, **kwargs)
+
+
+class GoalDetail(
+    mixins.RetrieveModelMixin,
+    mixins.UpdateModelMixin,
+    mixins.DestroyModelMixin,
+    generics.GenericAPIView,
+):
+    """Class defining the web response for the details of an individual Exercise.
+
+    HTTP methods: GET, PUT, PATCH, DELETE
+    """
+
+    queryset = Goal.objects.all()
+    serializer_class = GoalSerializer
+    permission_classes = [permissions.IsAuthenticated]
+
+    def get(self, request, *args, **kwargs):
+        return self.retrieve(request, *args, **kwargs)
+
+    def put(self, request, *args, **kwargs):
+        return self.update(request, *args, **kwargs)
+
+    def patch(self, request, *args, **kwargs):
+        return self.partial_update(request, *args, **kwargs)
+
+    def delete(self, request, *args, **kwargs):
+        return self.destroy(request, *args, **kwargs)
+
 
 class ExerciseInstanceList(
     mixins.ListModelMixin,
diff --git a/frontend/www/goal.html b/frontend/www/goal.html
index eb439d4..db8c653 100644
--- a/frontend/www/goal.html
+++ b/frontend/www/goal.html
@@ -37,7 +37,7 @@
     <div class="col-lg-6"></div>
     <div class="col-lg-6">
       <label for="inputMuscles" class="form-label">Connect to exercise</label>
-      <select class="form-select" id="exercise-content" name="muscleGroup" disabled="true">
+      <select class="form-select" id="exercise-content" name="exercise" disabled="true">
       </select>
     </div>
     <div class="col-lg-6"></div>
diff --git a/frontend/www/scripts/goal.js b/frontend/www/scripts/goal.js
index 3cfd9de..7b86918 100644
--- a/frontend/www/scripts/goal.js
+++ b/frontend/www/scripts/goal.js
@@ -63,25 +63,26 @@ function handleCancelButtonDuringCreate() {
 }
 
 async function createExercise() {
-    document.querySelector("select").removeAttribute("disabled")
+
     let form = document.querySelector("#form-exercise");
     let formData = new FormData(form);
     let body = {"name": formData.get("name"),
                 "description": formData.get("description"),
-                "duration": formData.get("duration"),
-                "calories": formData.get("calories"),
-                "muscleGroup": formData.get("muscleGroup"),
-                "unit": formData.get("unit")};
+                "date": formData.get("date"),
+                "exercise": formData.get("exercise")};
 
-    let response = await sendRequest("POST", `${HOST}/api/exercises/`, body);
+    console.log("HEELO", body)
+
+      let response = await sendRequest("POST", `${HOST}/api/goal/`, body);
+
+      if (response.ok) {
+          window.location.replace("goals.html");
+      } else {
+          let data = await response.json();
+          let alert = createAlert("Could not create new goal!", data);
+          document.body.prepend(alert);
+      }
 
-    if (response.ok) {
-        window.location.replace("exercises.html");
-    } else {
-        let data = await response.json();
-        let alert = createAlert("Could not create new exercise!", data);
-        document.body.prepend(alert);
-    }
 }
 
 function handleEditExerciseButtonClick() {
diff --git a/frontend/www/scripts/goals.js b/frontend/www/scripts/goals.js
index 9a3ab38..b7304e6 100644
--- a/frontend/www/scripts/goals.js
+++ b/frontend/www/scripts/goals.js
@@ -31,11 +31,26 @@ function createExercise() {
     window.location.replace("goal.html");
 }
 
+async function init() {
+    let response = await sendRequest("GET", `${HOST}/api/goal/`);
+
+    if (response.ok) {
+        let data = await response.json();
+        data.results.map((goal) => {console.log(goal)});
+    }else{
+        console.log("ERROR")
+    }
+
+    return response;
+}
+
+
 window.addEventListener("DOMContentLoaded", async () => {
     let createButton = document.querySelector("#btn-create-goal");
     createButton.addEventListener("click", createExercise);
 
     let response = await fetchExerciseTypes();
+    await init();
 
     if (!response.ok) {
         let data = await response.json();
-- 
GitLab