浏览代码

Add recipes page into inventory page

Lee Morgan 6 年之前
父节点
当前提交
d6ec2480e7
共有 4 个文件被更改,包括 454 次插入11 次删除
  1. 85 9
      views/inventoryPage/inventory.css
  2. 36 2
      views/inventoryPage/inventory.ejs
  3. 71 0
      views/inventoryPage/recipes.js
  4. 262 0
      views/inventoryPage/singleRecipe.js

+ 85 - 9
views/inventoryPage/inventory.css

@@ -1,3 +1,8 @@
+#title{
+    text-align: center;
+    margin-top: 25px;
+}
+
 /* Inventory Strand */
 #inventoryStrand{
     flex-direction: column;
@@ -8,15 +13,6 @@
         margin: 10px;
     }
 
-    #inventoryStrand h1{
-        font-size: 40px;
-        margin: 40px;
-    }
-
-    #inventoryStrand span{
-        color: rgb(255, 99, 107);
-    }
-
     #inventoryStrand th{
         cursor: pointer;
     }
@@ -35,6 +31,50 @@
             max-height: 32px;
         }
 
+/* Recipes Strand */
+#recipesStrand{
+    flex-direction: column;
+    align-items: center;
+}
+
+    #recipesStrand > *{
+        margin: 15px;
+    }
+
+    #recipeUpdate{
+        margin-bottom: 10px;
+    }
+
+    #recipesContainer{
+        display: flex;
+        justify-content: space-around;
+        flex-wrap: wrap;
+        padding: 25px;
+    }
+
+        .recipe-card{
+            border: 2px solid rgb(255, 99, 107);
+            box-shadow: 2px 2px 2px rgb(0, 27, 45);
+            background: rgb(0, 27, 45);
+            color: rgb(255, 99, 107);
+            width: 20%;
+            min-width: 200px;
+            padding: 35px;
+            margin: 25px;
+            border-radius: 10px;
+            cursor: pointer;
+        }
+
+            .recipe-card:hover{
+                transform: translateY(-3px);
+            }
+
+            .empty-recipe{
+                background: rgb(255, 99, 107);
+                border: 2px solid rgb(0, 27, 45);
+                color: rgb(0, 27, 45);
+            }
+
 /* Account Strand */
 #accountStrand{
     flex-direction: column;
@@ -75,6 +115,42 @@
         margin: 10px;
     }
 
+/* Single Recipe Action */
+#singleRecipeAction{
+    display: none;
+    flex-direction: column;
+    margin: auto;
+    align-items: center;
+}
+
+    #singleRecipeAction > *{
+        margin: 15px;
+    }
+
+    #delRecipe{
+        display: "none"
+    }
+
+    #recipeName{
+        margin-top: 0;
+    }
+
+@media screen and (max-width: 1000px){
+    /* General use */
+    body{
+        text-align: center;
+    }
+
+    /* Single Recipe Action */
+    #singleRecipeAction .buttonsDiv{
+        font-size: 15px;
+    }
+
+    #singleRecipeAction input{
+        max-width: 100px;
+    }
+}
+
 @media screen and (max-width: 600px){
     /* Inventory Strand */
     #inventoryStrand h1{

+ 36 - 2
views/inventoryPage/inventory.ejs

@@ -12,11 +12,11 @@
 
         <% include ../shared/banner %>
 
+        <h1 id="title"><%=merchant.name%></h1>
+
         <strand-selector></strand-selector>
 
         <div id="inventoryStrand" class="strand">
-            <h1><span><%= merchant.name %></span> inventory</h1>
-
             <div class="options">
                 <a class="button" href="/recipes">View Recipes</a>
 
@@ -45,6 +45,16 @@
             </table>
         </div>
 
+        <div id="recipesStrand" class="strand">
+            <div>
+                <% if(merchant.pos !== "none"){ %>
+                    <button class="button" id="recipeUpdate" onclick="recipesObj.updateRecipes()">Update Recipes</button>
+                <% } %>
+            </div>
+
+            <div id="recipesContainer"></div>
+        </div>
+
         <div id="accountStrand" class="strand">
             <h1>Account Strand</h1>
             <form onsubmit="accountObj.submitForm()"></form>
@@ -128,6 +138,28 @@
             <button class="button" onclick="enterPurchaseObj.submit()">Submit</button>
         </div>
 
+        <div id="singleRecipeAction" class="action">
+            <h1><span><%=merchant.name%></span>'s</h1>
+            <h1 id="recipeName"></h1>
+
+            <div class="buttonsDiv">
+                <button class="button" id="addButton">Add Ingredient</button>
+
+                <button class="button" onclick="recipesObj.display()">Back to Recipes</button>
+            </div>
+
+            <table>
+                <thead>
+                    <tr>
+                        <th>Name</th>
+                        <th>Quantity</th>
+                        <th>Actions</th>
+                    </tr>
+                </thead>
+                <tbody></tbody>
+            </table>
+        </div>
+
         <script>
                 <% if(locals.error){ %>
                     let error = <%- JSON.stringify(error) %>;
@@ -141,10 +173,12 @@
         <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
         <script src="../shared/validation.js"></script>
         <script src="/inventoryPage/inventory.js"></script>
+        <script src="/inventoryPage/recipes.js"></script>
         <script src="/inventoryPage/account.js"></script>
         <script src="/inventoryPage/addIngredient.js"></script>
         <script src="/inventoryPage/enterTransactions.js"></script>
         <script src="/inventoryPage/enterPurchase.js"></script>
+        <script src="/inventoryPage/singleRecipe.js"></script>
         <script src="/shared/controller.js"></script>
     </body>
 </html>

+ 71 - 0
views/inventoryPage/recipes.js

@@ -0,0 +1,71 @@
+window.recipesObj = {
+    isPopulated: false,
+
+    display: function(){
+        clearScreen();
+        document.querySelector("#recipesStrand").style.display = "flex";
+
+        if(!this.isPopulated){
+            this.populateRecipes();
+            this.isPopulated = true;
+        }
+    },
+
+    populateRecipes: function(){
+        let body = document.querySelector("#recipesContainer");
+        let blankRecipes = 0;
+
+        while(body.children.length > 0){
+            body.removeChild(body.firstChild);
+        }
+
+        merchant.recipes.sort((a, b) => (a.name > b.name)? 1 : -1);
+        
+        for(let recipe of merchant.recipes){
+            let recipeDiv = document.createElement("div");
+            recipeDiv.classList = "recipe-card";
+            recipeDiv.onclick = ()=>{singleRecipeObj.display(recipe)};
+            body.appendChild(recipeDiv);
+
+            if(recipe.ingredients.length === 0){
+                recipeDiv.classList = "recipe-card empty-recipe";
+                blankRecipes++;
+            }else{
+                recipeDiv.classList = "recipe-card";
+            }
+
+            let title = document.createElement("h2");
+            title.innerText = recipe.name;
+            recipeDiv.appendChild(title);
+
+            let ingredientList = document.createElement("ul");
+            recipeDiv.appendChild(ingredientList);
+
+            for(let ingredient of recipe.ingredients){
+                let ul = document.createElement("li");
+                ul.innerText = ingredient.ingredient.name;
+                ingredientList.appendChild(ul);
+            }
+        }
+
+        if(blankRecipes > 0){
+            banner.createError(`You have ${blankRecipes} recipes without ingredients, please add ingredients to all recipes`);
+        }
+    },
+
+    updateRecipes: function(){
+        axios.get("/merchant/recipes/update")
+            .then((result)=>{
+                if(typeof(result.data) === "string"){
+                    banner.createError(result.data);
+                }else{
+                    merchant = result.data;
+                    this.populateRecipes();
+                    banner.createNotification("Your recipes have been updated successfully");
+                }
+            })
+            .catch((err)=>{
+                banner.createError("There was an error and your recipes could not be updated");
+            });
+    }
+}

+ 262 - 0
views/inventoryPage/singleRecipe.js

@@ -0,0 +1,262 @@
+window.singleRecipeObj = {
+    display: function(recipe){
+        clearScreen();
+        document.querySelector("#singleRecipeAction").style.display = "flex";
+
+        let tbody = document.querySelector("tbody");
+
+        while(tbody.children.length > 0){
+            tbody.removeChild(tbody.firstChild);
+        }
+
+        document.querySelector("#recipeName").innerText = recipe.name;
+        document.querySelector("#addButton").onclick = ()=>{this.displayAdd(recipe)};
+
+        for(let ingredient of recipe.ingredients){
+            let row = document.createElement("tr");
+            tbody.appendChild(row);
+
+            let name = document.createElement("td");
+            name.innerText = ingredient.ingredient.name;
+            name.classList = "truncateLong";
+            row.appendChild(name);
+
+            let quantity = document.createElement("td");
+            quantity.innerText = `${ingredient.quantity} ${ingredient.ingredient.unit}`;
+            row.appendChild(quantity);
+
+            let actions = document.createElement("td");
+            row.appendChild(actions);
+
+            let editButton = document.createElement("button");
+            editButton.innerText = "Edit";
+            editButton.classList = "button-small";
+            editButton.onclick = ()=>{this.editIngredient(row, ingredient, recipe);};
+            actions.appendChild(editButton);
+
+            let removeButton = document.createElement("button");
+            removeButton.innerText = "Remove";
+            removeButton.classList = "button-small";
+            removeButton.onclick = ()=>{this.deleteIngredient(recipe._id, ingredient.ingredient._id, ingredient.quantity, row);};
+            actions.appendChild(removeButton);
+        }
+    },
+
+    displayAdd: function(recipe){
+        let tbody = document.querySelector("tbody");
+
+        let row = document.createElement("tr");
+        tbody.appendChild(row);
+
+        let nameTd = document.createElement("td");
+        row.appendChild(nameTd);
+
+        let name = document.createElement("select");
+        name.classList = "truncateLong";
+        nameTd.appendChild(name);
+
+        for(let item of merchant.inventory){
+            let exists = false;
+            for(let recipeIngredient of recipe.ingredients){
+                if(item.ingredient._id === recipeIngredient.ingredient._id){
+                    exists = true;
+                    break;
+                }
+            }
+
+            if(!exists){
+                let nameOption = document.createElement("option");
+                nameOption.innerText = `${item.ingredient.name} (${item.ingredient.unit})`;
+                nameOption.value = item.ingredient._id;
+                name.appendChild(nameOption);
+            }
+        }
+
+        let quantityTd = document.createElement("td");
+        row.appendChild(quantityTd);
+
+        let quantity = document.createElement("input");
+        quantity.type = "text";
+        quantity.step = "0.01";
+        quantity.onkeypress = (event)=>{if(event.keyCode===13) this.addIngredient(recipe, name.value, quantity.value, row)};
+        quantityTd.appendChild(quantity);
+
+        let actionTd = document.createElement("td");
+        row.appendChild(actionTd);
+
+        let saveButton = document.createElement("button");
+        saveButton.innerText = "Save";
+        saveButton.classList = "button-small";
+        saveButton.onclick = ()=>{this.addIngredient(recipe, name.value, quantity.value, row);};
+        actionTd.appendChild(saveButton);
+
+        let cancelButton = document.createElement("button");
+        cancelButton.innerText = "Cancel";
+        cancelButton.classList = "button-small";
+        cancelButton.onclick = ()=>{tbody.removeChild(row)};
+        actionTd.appendChild(cancelButton);
+    },
+
+    addIngredient: function(recipe, ingredientId, quantity, row){
+        let item = {
+            ingredient: ingredientId,
+            quantity: quantity
+        }
+        
+        if(validator.ingredient.quantity(item.quantity)){
+            axios.post("/merchant/recipes/ingredients/create", {recipeId: recipe._id, item: item})
+                .then((response)=>{
+                    if(typeof(response.data) === "string"){
+                        banner.createError(response.data);
+                    }else{
+                        for(let i = 0; i < merchant.recipes.length; i++){
+                            if(merchant.recipes[i]._id === recipe._id){
+                                merchant.recipes.splice(i, 1);
+                                break;
+                            }
+                        }
+                        merchant.recipes.push(response.data);
+                        recipesObj.isPopulated = false;
+
+                        while(row.children.length > 0){
+                            row.removeChild(row.firstChild);
+                        }
+
+                        let addIngredient = response.data.ingredients.find(i => i.ingredient._id === ingredientId);
+
+                        let name = document.createElement("td");
+                        name.innerText = addIngredient.ingredient.name;
+                        row.appendChild(name);
+
+                        let quantity = document.createElement("td");
+                        quantity.innerText = `${item.quantity} ${addIngredient.ingredient.unit}`;
+                        row.appendChild(quantity);
+
+                        let actions = document.createElement("td");
+                        row.appendChild(actions);
+
+                        let editButton = document.createElement("button");
+                        editButton.innerText = "Edit";
+                        editButton.classList = "button-small";
+                        editButton.onclick = ()=>{this.editIngredient(row, addIngredient, recipe);};
+                        actions.appendChild(editButton);
+
+                        let removeButton = document.createElement("button");
+                        removeButton.innerText = "Remove";
+                        removeButton.classList = "button-small";
+                        removeButton.onclick = ()=>{this.deleteIngredient(recipe._id, ingredientId, quantity, row);};
+                        actions.appendChild(removeButton);
+                    }
+                })
+                .catch((err)=>{
+                    row.parentNode.removeChild(row);
+                    banner.createError("There was an error and the recipe could not be updated");
+                });
+        }
+    },
+
+    //Delete ingredient from table
+    //Delete ingredient from database
+    deleteIngredient: function(recipeId, ingredientId, quantity, row){
+        axios.post("/merchant/recipes/ingredients/remove", {ingredientId: ingredientId, recipeId: recipeId, quantity: quantity})
+            .then((result)=>{
+                if(typeof(result.data) === "string"){
+                    banner.createError(result.data);
+                }else{
+                    row.parentNode.removeChild(row);
+
+                    let updateRecipe = merchant.recipes.find(r => r._id === recipeId);
+                    for(let i = 0; i < updateRecipe.ingredients.length; i++){
+                        if(updateRecipe.ingredients[i].ingredient._id === ingredientId){
+                            updateRecipe.ingredients.splice(i, 1);
+                            break;
+                        }
+                    }
+
+                    recipesObj.isPopulated = false;
+                }
+            })
+            .catch((err)=>{
+                banner.createError("There was an error and the ingredient could not be removed from the recipe");
+            });
+    },
+
+    //Change quantity field to input
+    //Change edit button
+    editIngredient: function(row, ingredient, recipe){
+        let td = row.children[1];
+        td.innerText = "";
+
+        let input = document.createElement("input");
+        input.type = "number";
+        input.step = "0.01";
+        input.value = ingredient.quantity;
+        input.onkeypress = (event)=>{if(event.keyCode===13) this.updateIngredient(row, ingredient, recipe)};
+        td.appendChild(input);
+
+        let para = document.createElement("p");
+        para.innerText = ingredient.ingredient.unit;
+        td.appendChild(para);
+
+        let editButton = row.children[2].children[0];
+        editButton.innerText = "Save";
+        editButton.onclick = ()=>{this.updateIngredient(row, ingredient, recipe);};
+
+        let removeButton = row.children[2].children[1];
+        removeButton.innerText = "Cancel";
+        removeButton.onclick = ()=>{this.cancelEdit(row, ingredient, recipe)};
+
+        input.focus();
+    },
+
+    cancelEdit: function(row, ingredient, recipe){
+        let quantity = row.children[1];
+        quantity.removeChild(quantity.firstChild);
+        quantity.innerText = `${ingredient.quantity} ${ingredient.ingredient.unit}`;
+
+        let saveButton = row.children[2].children[0];
+        saveButton.innerText = "Edit";
+        saveButton.onclick = ()=>{this.editIngredient(row, ingredient, recipe)};
+
+        let cancelButton = row.children[2].children[1];
+        cancelButton.innerText = "Remove";
+        cancelButton.onclick = ()=>{this.deleteIngredient(recipe._id, ingredient.ingredient._id, row)};
+    },
+
+    updateIngredient: function(row, ingredient, recipe){
+        let originalQuantity = ingredient.quantity;
+        ingredient.quantity = row.children[1].children[0].value;
+
+        let td = row.children[1];
+        while(td.children.length > 0){
+            td.removeChild(td.firstChild);
+        }
+
+        let saveButton = row.children[2].children[0];
+        saveButton.innerText = "Edit";
+        saveButton.onclick = ()=>{this.editIngredient(row, ingredient, recipe);};
+
+        let cancelButton = row.children[2].children[1];
+        cancelButton.innerText = "Remove";
+        cancelButton.onclick = ()=>{this.deleteIngredient(recipe._id, ingredient.ingredient._id, row)};
+
+        if(validator.ingredient.quantity(ingredient.quantity)){
+            axios.post("/merchant/recipes/ingredients/update", {recipeId: recipe._id, ingredient: ingredient})
+                .then((result)=>{
+                    if(typeof(result.data) === "string"){
+                        td.innerText = `${originalQuantity} ${ingredient.ingredient.unit}`;
+                        banner.createError(result.data);
+                    }else{
+                        td.innerText = `${ingredient.quantity} ${ingredient.ingredient.unit}`;
+                        banner.createNotification("Ingredient successfully updated");
+                    }
+                })
+                .catch((err)=>{
+                    td.innerText = `${originalQuantity} ${ingredient.ingredient.unit}`;
+                    banner.createError("There was an error and the ingredient could not be updated");
+                });
+        }else{
+            td.innerText = `${originalQuantity} ${ingredient.ingredient.unit}`;
+        }
+    },
+}