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