From 339ba2a802aca8ec6d44b01d2a8eb44fe45a5f4c Mon Sep 17 00:00:00 2001
From: ibooking-sigurd <sigurd.augdal@ibooking.no>
Date: Fri, 26 Feb 2021 12:01:29 +0100
Subject: [PATCH] First commit. ref. #2 #4 #7. Add first version of the Diet
 page in frontend.

---
 frontend/www/diet.html          |  54 +++++++++++
 frontend/www/diets.html         |  47 ++++++++++
 frontend/www/scripts/diet.js    | 154 ++++++++++++++++++++++++++++++++
 frontend/www/scripts/diets.js   |  42 +++++++++
 frontend/www/scripts/navbar.js  |   1 +
 frontend/www/scripts/scripts.js |   3 +
 6 files changed, 301 insertions(+)
 create mode 100644 frontend/www/diet.html
 create mode 100644 frontend/www/diets.html
 create mode 100644 frontend/www/scripts/diet.js
 create mode 100644 frontend/www/scripts/diets.js

diff --git a/frontend/www/diet.html b/frontend/www/diet.html
new file mode 100644
index 0000000..2643bbe
--- /dev/null
+++ b/frontend/www/diet.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Diet</title>
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
+
+    <script src="https://kit.fontawesome.com/0ce6c392ca.js" crossorigin="anonymous"></script>
+    <link rel="stylesheet" href="styles/style.css">
+    <script src="scripts/navbar.js" type="text/javascript" defer></script>
+</head>
+    <body>
+        <navbar-el></navbar-el>
+
+        <div class="container">
+            <div class="row">
+                <div class="col-lg">
+                    <h3 class="mt-3">View/Edit Diet</h3>
+                </div>
+            </div>
+        <form class="row g-3" id="form-diet">
+            <div class="col-lg-6 ">
+                <label for="inputName" class="form-label">Name</label>
+                <input type="text" class="form-control" id="inputName" name="name" readonly>
+            </div>
+            <div class="col-lg-6"></div>
+            <div class="col-lg-6">
+                <label for="inputDescription" class="form-label">Description</label>
+                <textarea class="form-control" id="inputDescription" name="description" readonly></textarea>
+            </div>
+            <div class="col-lg-6"></div>
+            <div class="col-lg-6">
+                <label for="inputUnit" class="form-label">Unit</label>
+                <input type="text" class="form-control" id="inputUnit" name="unit" readonly>
+            </div>
+            <div class="col-lg-6"></div>
+            <div class="col-lg-6">
+                <input type="button" class="btn btn-primary hide" id="btn-ok-diet" value="  OK  ">
+                <input type="button" class="btn btn-primary" id="btn-edit-diet" value=" Edit ">
+                <input type="button" class="btn btn-secondary hide" id="btn-cancel-diet" value="Cancel">
+                <input type="button" class="btn btn-danger float-end hide" id="btn-delete-diet" value="Delete">
+            </div>
+            <div class="col-lg-6">
+
+            </div>
+        </form>
+        </div>
+        <script src="scripts/defaults.js"></script>
+        <script src="scripts/scripts.js"></script>
+        <script src="scripts/diet.js"></script>
+        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
+    </body>
+</html>
\ No newline at end of file
diff --git a/frontend/www/diets.html b/frontend/www/diets.html
new file mode 100644
index 0000000..25787b6
--- /dev/null
+++ b/frontend/www/diets.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Exercises</title>
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
+
+    <script src="https://kit.fontawesome.com/0ce6c392ca.js" crossorigin="anonymous"></script>
+    <link rel="stylesheet" href="styles/style.css">
+    <script src="scripts/navbar.js" type="text/javascript" defer></script>
+</head>
+<body>
+    <navbar-el></navbar-el>
+
+    <div class="container">
+        <div class="row">
+            <div class="col-lg text-center">
+                <h3 class="mt-5">View Diets</h3>
+                <p>Here you can view, create, and edit diets defined by you and other coaches.</p>
+                <input type="button" class="btn btn-primary" id="btn-create-diet" value="Create new diet">
+        </div>
+        <div class="row">
+            <div class="col-lg text-center">
+                <div class="list-group mt-1" id="div-content"></div>
+            </div>
+        </div>
+    </div>
+
+    <template id="template-diet">
+        <a class="list-group-item list-group-item-action flex-column align-items-start my-1 diet" href="">
+            <div class="d-flex w-100 justify-content-between align-items-center">
+                <h5 class="mb-1"></h5>
+            </div>
+            <div class="d-flex">
+                <p class="mb-1">
+                </p>
+            </div>
+        </a>
+    </template>
+
+    <script src="scripts/defaults.js"></script>
+    <script src="scripts/scripts.js"></script>
+    <script src="scripts/diets.js"></script>
+    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/frontend/www/scripts/diet.js b/frontend/www/scripts/diet.js
new file mode 100644
index 0000000..3ba2734
--- /dev/null
+++ b/frontend/www/scripts/diet.js
@@ -0,0 +1,154 @@
+let cancelButton;
+let okButton;
+let deleteButton;
+let editButton;
+let oldFormData;
+
+
+function handleCancelButtonDuringEdit() {
+    setReadOnly(true, "#form-diet");
+    okButton.className += " hide";
+    deleteButton.className += " hide";
+    cancelButton.className += " hide";
+    editButton.className = editButton.className.replace(" hide", "");
+
+    cancelButton.removeEventListener("click", handleCancelButtonDuringEdit);
+
+    let form = document.querySelector("#form-diet");
+    if (oldFormData.has("name")) form.name.value = oldFormData.get("name");
+    if (oldFormData.has("description")) form.description.value = oldFormData.get("description");
+    if (oldFormData.has("unit")) form.unit.value = oldFormData.get("unit");
+    
+    oldFormData.delete("name");
+    oldFormData.delete("description");
+    oldFormData.delete("unit");
+
+}
+
+function handleCancelButtonDuringCreate() {
+    window.location.replace("diets.html");
+}
+
+async function createDiet() {
+    let form = document.querySelector("#form-diet");
+    let formData = new FormData(form);
+    let body = {"name": formData.get("name"), 
+                "description": formData.get("description"), 
+                "unit": formData.get("unit")};
+
+    let response = await sendRequest("POST", `${HOST}/api/diets/`, body);
+
+    if (response.ok) {
+        window.location.replace("diets.html");
+    } else {
+        let data = await response.json();
+        let alert = createAlert("Could not create new diet!", data);
+        document.body.prepend(alert);
+    }
+}
+
+function handleEditDietButtonClick() {
+    setReadOnly(false, "#form-diet");
+
+    editButton.className += " hide";
+    okButton.className = okButton.className.replace(" hide", "");
+    cancelButton.className = cancelButton.className.replace(" hide", "");
+    deleteButton.className = deleteButton.className.replace(" hide", "");
+
+    cancelButton.addEventListener("click", handleCancelButtonDuringEdit);
+
+    let form = document.querySelector("#form-diet");
+    oldFormData = new FormData(form);
+}
+
+async function deleteDiet(id) {
+    let response = await sendRequest("DELETE", `${HOST}/api/diets/${id}/`);
+    if (!response.ok) {
+        let data = await response.json();
+        let alert = createAlert(`Could not delete diet ${id}`, data);
+        document.body.prepend(alert);
+    } else {
+        window.location.replace("diets.html");
+    }
+}
+
+async function retrieveDiet(id) {
+    let response = await sendRequest("GET", `${HOST}/api/diets/${id}/`);
+    console.log(response.ok);
+    if (!response.ok) {
+        let data = await response.json();
+        let alert = createAlert("Could not retrieve diet data!", data);
+        document.body.prepend(alert);
+    } else {
+        let dietData = await response.json();
+        let form = document.querySelector("#form-diet");
+        let formData = new FormData(form);
+
+        for (let key of formData.keys()) {
+            let selector = `input[name="${key}"], textarea[name="${key}"]`;
+            let input = form.querySelector(selector);
+            let newVal = dietData[key];
+            input.value = newVal;
+        }
+    }
+}
+
+async function updateDiet(id) {
+    let form = document.querySelector("#form-diet");
+    let formData = new FormData(form);
+    let body = {"name": formData.get("name"), 
+                "description": formData.get("description"), 
+                "unit": formData.get("unit")};
+    let response = await sendRequest("PUT", `${HOST}/api/diets/${id}/`, body);
+
+    if (!response.ok) {
+        let data = await response.json();
+        let alert = createAlert(`Could not update diet ${id}`, data);
+        document.body.prepend(alert);
+    } else {
+        // duplicate code from handleCancelButtonDuringEdit
+        // you should refactor this
+        setReadOnly(true, "#form-diet");
+        okButton.className += " hide";
+        deleteButton.className += " hide";
+        cancelButton.className += " hide";
+        editButton.className = editButton.className.replace(" hide", "");
+    
+        cancelButton.removeEventListener("click", handleCancelButtonDuringEdit);
+        
+        oldFormData.delete("name");
+        oldFormData.delete("description");
+        oldFormData.delete("unit");
+    }
+}
+
+window.addEventListener("DOMContentLoaded", async () => {
+    cancelButton = document.querySelector("#btn-cancel-diet");
+    okButton = document.querySelector("#btn-ok-diet");
+    deleteButton = document.querySelector("#btn-delete-diet");
+    editButton = document.querySelector("#btn-edit-diet");
+    oldFormData = null;
+
+    const urlParams = new URLSearchParams(window.location.search);
+
+    // view/edit
+    if (urlParams.has('id')) {
+        const dietId = urlParams.get('id');
+        await retrieveDiet(dietId);
+
+        editButton.addEventListener("click", handleEditDietButtonClick);
+        deleteButton.addEventListener("click", (async (id) => await deleteDiet(id)).bind(undefined, dietId));
+        okButton.addEventListener("click", (async (id) => await updateDiet(id)).bind(undefined, dietId));
+    } 
+    //create
+    else {
+        setReadOnly(false, "#form-diet");
+
+        editButton.className += " hide";
+        okButton.className = okButton.className.replace(" hide", "");
+        cancelButton.className = cancelButton.className.replace(" hide", "");
+
+        okButton.addEventListener("click", async () => await createDiet());
+        cancelButton.addEventListener("click", handleCancelButtonDuringCreate);
+    }
+});
\ No newline at end of file
diff --git a/frontend/www/scripts/diets.js b/frontend/www/scripts/diets.js
new file mode 100644
index 0000000..cf1a78f
--- /dev/null
+++ b/frontend/www/scripts/diets.js
@@ -0,0 +1,42 @@
+async function fetchDiets(request) {
+    let response = await sendRequest("GET", `${HOST}/api/diets/`);
+
+    if (response.ok) {
+        let data = await response.json();
+
+        let diets = data.results;
+        let container = document.getElementById('div-content');
+        let dietTemplate = document.querySelector("#template-diet");
+        diets.forEach(diet => {
+            const dietAnchor = dietTemplate.content.firstElementChild.cloneNode(true);
+            dietAnchor.href = `diet.html?id=${diet.id}`;
+
+            const h5 = dietAnchor.querySelector("h5");
+            h5.textContent = diet.name;
+
+            const p = dietAnchor.querySelector("p");
+            p.textContent = diet.description;   
+
+            container.appendChild(dietAnchor);
+        });
+    }
+
+    return response;
+}
+
+function createExercise() {
+    window.location.replace("diet.html");
+}
+
+window.addEventListener("DOMContentLoaded", async () => {
+    let createButton = document.querySelector("#btn-create-diet");
+    createButton.addEventListener("click", createDiet);
+
+    let response = await fetchDiets();
+    
+    if (!response.ok) {
+        let data = await response.json();
+        let alert = createAlert("Could not retrieve diets!", data);
+        document.body.prepend(alert);
+    }
+});
\ No newline at end of file
diff --git a/frontend/www/scripts/navbar.js b/frontend/www/scripts/navbar.js
index d906f61..70c1cb1 100644
--- a/frontend/www/scripts/navbar.js
+++ b/frontend/www/scripts/navbar.js
@@ -18,6 +18,7 @@ class NavBar extends HTMLElement {
                 <a class="nav-link hide" id="nav-exercises" href="exercises.html">Exercises</a>
                 <a class="nav-link hide" id="nav-mycoach" href="mycoach.html">Coach</a>
                 <a class="nav-link hide" id="nav-myathletes" href="myathletes.html">Athletes</a>
+                <a class="nav-link hide" id="nav-diets" href="diets.html">Diets</a>
                 <hr>
             </div>
             <div class="my-2 my-lg-0 me-5">
diff --git a/frontend/www/scripts/scripts.js b/frontend/www/scripts/scripts.js
index 8c55000..ae40f74 100644
--- a/frontend/www/scripts/scripts.js
+++ b/frontend/www/scripts/scripts.js
@@ -22,6 +22,8 @@ function updateNavBar() {
     makeNavLinkActive("nav-mycoach")
   } else if (window.location.pathname == "/myathletes.html") {
     makeNavLinkActive("nav-myathletes");
+  } else if (window.location.pathname == "/diets.html") {
+    makeNavLinkActive("nav-diets");
   }
 
   if (isUserAuthenticated()) {
@@ -32,6 +34,7 @@ function updateNavBar() {
     document.querySelector('a[href="mycoach.html"').classList.remove("hide");
     document.querySelector('a[href="exercises.html"').classList.remove("hide");
     document.querySelector('a[href="myathletes.html"').classList.remove("hide");
+    document.querySelector('a[href="diets.html"').classList.remove("hide");
   } else {
     document.getElementById("btn-login-nav").classList.remove("hide");
     document.getElementById("btn-register").classList.remove("hide");
-- 
GitLab