diff --git a/app.js b/app.js index d5d7409..ad358a4 100644 --- a/app.js +++ b/app.js @@ -7,12 +7,13 @@ const logger = require("morgan"); const config = require("./config/config.json"); const indexRouter = require("./routes/index"); -const loginRouter = require("./routes/login") -const logoutRouter = require("./routes/logout") -const commandsRouter = require("./routes/commands") -const kitchenRouter = require("./routes/kitchen") -const serviceRouter = require("./routes/service") -const stocksRouter = require("./routes/stocks") +const loginRouter = require("./routes/login"); +const logoutRouter = require("./routes/logout"); +const commandsRouter = require("./routes/commands"); +const kitchenRouter = require("./routes/kitchen"); +const menuRouter = require("./routes/menu"); +const serviceRouter = require("./routes/service"); +const stocksRouter = require("./routes/stocks"); const app = express(); const sess = { @@ -49,6 +50,7 @@ app.use("/login", loginRouter); app.use("/logout", logoutRouter); app.use("/commands", commandsRouter); app.use("/kitchen", kitchenRouter); +app.use("/menu", menuRouter); app.use("/stocks", stocksRouter); app.use("/service", serviceRouter); diff --git a/models/dessert.js b/models/dessert.js index 112e68f..433be92 100644 --- a/models/dessert.js +++ b/models/dessert.js @@ -10,6 +10,11 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.FLOAT, defaultValue: 0, allowNull: false + }, + available: { + type: DataTypes.BOOLEAN, + defaultValue: true, + allowNull: false } }, { tableName: "Desserts" diff --git a/models/dish.js b/models/dish.js index 96fc15f..afe0426 100644 --- a/models/dish.js +++ b/models/dish.js @@ -11,6 +11,11 @@ module.exports = (sequelize, DataTypes) => { defaultValue: 0, allowNull: false }, + available: { + type: DataTypes.BOOLEAN, + defaultValue: true, + allowNull: false + }, maxIngredients: { type: DataTypes.INTEGER, allowNull: false diff --git a/models/drink.js b/models/drink.js index c934a62..c78b8b6 100644 --- a/models/drink.js +++ b/models/drink.js @@ -10,6 +10,11 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.FLOAT, defaultValue: 0, allowNull: false + }, + available: { + type: DataTypes.BOOLEAN, + defaultValue: true, + allowNull: false } }, { tableName: "Drinks" diff --git a/models/ingredient.js b/models/ingredient.js index 80caa15..c81dd77 100644 --- a/models/ingredient.js +++ b/models/ingredient.js @@ -10,6 +10,11 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.FLOAT, defaultValue: 0, allowNull: false + }, + available: { + type: DataTypes.BOOLEAN, + defaultValue: true, + allowNull: false } }, { tableName: "Ingredients" diff --git a/models/sauce.js b/models/sauce.js index c9e312b..5b79ffe 100644 --- a/models/sauce.js +++ b/models/sauce.js @@ -10,6 +10,11 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.FLOAT, defaultValue: 0, allowNull: false + }, + available: { + type: DataTypes.BOOLEAN, + defaultValue: true, + allowNull: false } }, { tableName: "Sauces" diff --git a/public/javascripts/menu.js b/public/javascripts/menu.js new file mode 100644 index 0000000..1f23df8 --- /dev/null +++ b/public/javascripts/menu.js @@ -0,0 +1,171 @@ +const socket = io(); +const dish = document.querySelector("#dish ul"); +const ingredient = document.querySelector("#ingredient ul"); +const sauce = document.querySelector("#sauce ul"); +const drink = document.querySelector("#drink ul"); +const dessert = document.querySelector("#dessert ul"); + + +if (window.location.href.endsWith("#popup")) + window.location.href = window.location.href.replace("#popup", "#"); + + +function popup(ob, el) { + document.querySelector("body").insertAdjacentHTML("afterbegin", ``); + let e = document.getElementById("popup"); + if (ob.available) + e.querySelector("#available").click() + if (ob.maxIngredients !== undefined) + e.querySelector("#edit div:last-of-type").insertAdjacentHTML("afterend", `
`); + if (ob.maxSauces !== undefined) + e.querySelector("#edit div:last-of-type").insertAdjacentHTML("afterend", `
`); + + e.querySelector("#cancel").addEventListener("click", () => { + e.remove(); + }); + e.querySelector("#apply").addEventListener("click", () => { + socket.emit("set " + el.id.replace(ob.id, ""), { + id: ob.id, + available: e.querySelector("#available").checked, + price: parseFloat(e.querySelector("#price").value), + maxIngredients: ob.maxIngredients === undefined ? undefined : parseInt(e.querySelector("#maxIngredients").value), + maxSauces: ob.maxSauces === undefined ? undefined : parseInt(e.querySelector("#maxSauces").value), + }); + e.remove(); + }); + + if (window.location.href.endsWith("#")) + window.location.href = window.location.href + "popup"; + else if (!window.location.href.endsWith("#popup")) + window.location.href = window.location.href + "#popup"; + else + window.location.href = window.location.href.replace("#popup", "#"); +} + +function addDish(d) { + dish.insertAdjacentHTML("beforeend", `
  • ${d.name}
  • `); + let e = document.getElementById(`dish${d.id}`); + e.addEventListener("click", () => { + popup(d, e); + }); +} + +function addIngredient(i) { + ingredient.insertAdjacentHTML("beforeend", `
  • ${i.name}
  • `); + let e = document.getElementById(`ingredient${i.id}`); + e.addEventListener("click", () => { + popup(i, e); + }); +} + +function addSauce(s) { + sauce.insertAdjacentHTML("beforeend", `
  • ${s.name}
  • `); + let e = document.getElementById(`sauce${s.id}`); + e.addEventListener("click", () => { + popup(s, e); + }); +} + +function addDrink(d) { + drink.insertAdjacentHTML("beforeend", `
  • ${d.name}
  • `); + let e = document.getElementById(`drink${d.id}`); + e.addEventListener("click", () => { + popup(d, e); + }); +} + +function addDessert(d) { + dessert.insertAdjacentHTML("beforeend", `
  • ${d.name}
  • `); + let e = document.getElementById(`dessert${d.id}`); + e.addEventListener("click", () => { + popup(d, e); + }); +} + +socket.on("connected", () => { + socket.emit("list dish"); + socket.emit("list ingredient"); + socket.emit("list sauce"); + socket.emit("list drink"); + socket.emit("list dessert"); +}); + +socket.on("list dish", data => { + let child = dish.lastElementChild; + while (child) { + dish.removeChild(child); + child = dish.lastElementChild; + } + for (let d of data) + addDish(d); +}); + +socket.on("list ingredient", data => { + let child = ingredient.lastElementChild; + while (child) { + ingredient.removeChild(child); + child = ingredient.lastElementChild; + } + for (let i of data) + addIngredient(i); +}); + +socket.on("list sauce", data => { + let child = sauce.lastElementChild; + while (child) { + sauce.removeChild(child); + child = sauce.lastElementChild; + } + for (let s of data) + addSauce(s); +}); + +socket.on("list drink", data => { + let child = drink.lastElementChild; + while (child) { + drink.removeChild(child); + child = drink.lastElementChild; + } + for (let d of data) + addDrink(d); +}); + +socket.on("list dessert", data => { + let child = dessert.lastElementChild; + while (child) { + dessert.removeChild(child); + child = dessert.lastElementChild; + } + for (let d of data) + addDessert(d); +}); + +socket.on("internal error", () => { + alert("An error occurred !"); +}) diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 24fbc1b..4dc38f1 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -661,6 +661,10 @@ audio{ opacity: 0.2; } +#popup h1 { + text-align: center; +} + #WIP{ display: flex; flex-wrap : wrap; @@ -830,4 +834,21 @@ div#teams{ #okteam button{ font-size: 30px; -} \ No newline at end of file +} + +#edit { + display: flex; + flex-direction: column; + align-content: space-between; + justify-content: space-between; +} + +#edit div { + margin-bottom: 0.5em; + text-align: center; +} + +#validation { + display: flex; + flex-direction: row; +} diff --git a/routes/menu.js b/routes/menu.js new file mode 100644 index 0000000..4bf914e --- /dev/null +++ b/routes/menu.js @@ -0,0 +1,10 @@ +const express = require("express"); +const router = express.Router(); +const middleware = require("./middleware"); + +/* GET home page. */ +router.get("/", middleware.sessionCheck, (req, res) => { + res.render("menu", { title: "Kfet - Menu" }); +}); + +module.exports = router; diff --git a/sockets/index.js b/sockets/index.js index a81cfe8..acb15fa 100644 --- a/sockets/index.js +++ b/sockets/index.js @@ -8,6 +8,11 @@ const listUser = require("./listUser"); const listService = require("./listService"); const addCommand = require("./addCommand"); const addUSer = require("./addUser"); +const setDish = require("./setDish"); +const setIngredient = require("./setIngredient"); +const setSauce = require("./setSauce"); +const setDrink = require("./setDrink"); +const setDessert = require("./setDessert"); const setService = require("./setService"); const giveCommand = require("./giveCommand"); const WIPCommand = require("./WIPCommand"); @@ -23,11 +28,15 @@ module.exports = socket => { socket.on("list sauce", listSauce(socket)); socket.on("list drink", listDrink(socket)); socket.on("list dessert", listDessert(socket)); - socket.on("list dessert", listDessert(socket)); socket.on("list user", listUser(socket)); socket.on("list service", listService(socket)); socket.on("add command", addCommand(socket)); socket.on("add user", addUSer(socket)); + socket.on("set dish", setDish(socket)); + socket.on("set ingredient", setIngredient(socket)); + socket.on("set sauce", setSauce(socket)); + socket.on("set drink", setDrink(socket)); + socket.on("set dessert", setDessert(socket)); socket.on("set service", setService(socket)); socket.on("give command", giveCommand(socket)); socket.on("WIP command", WIPCommand(socket)); diff --git a/sockets/listDessert.js b/sockets/listDessert.js index fb23272..e8479fb 100644 --- a/sockets/listDessert.js +++ b/sockets/listDessert.js @@ -1,16 +1,13 @@ const models = require("../models"); +const utils = require("./utils"); module.exports = socket => { return async () => { let desserts = [] - for (let i of await models.Dessert.findAll({ + for (let d of await models.Dessert.findAll({ order: ["name"] })) { - desserts.push({ - id: i.id, - name: i.name, - price: i.price - }); + desserts.push(utils.dessertExport(d)); } socket.emit("list dessert", desserts); } diff --git a/sockets/listDish.js b/sockets/listDish.js index 079a4d9..caf26e1 100644 --- a/sockets/listDish.js +++ b/sockets/listDish.js @@ -1,4 +1,5 @@ const models = require("../models"); +const utils = require("./utils"); module.exports = socket => { return async () => { @@ -6,13 +7,7 @@ module.exports = socket => { for (let d of await models.Dish.findAll({ order: ["name"] })) { - dishes.push({ - id: d.id, - name: d.name, - price: d.price, - maxIngredients: d.maxIngredients, - maxSauces: d.maxSauces - }); + dishes.push(utils.dishExport(d)); } socket.emit("list dish", dishes); } diff --git a/sockets/listDrink.js b/sockets/listDrink.js index 8581241..ce1113e 100644 --- a/sockets/listDrink.js +++ b/sockets/listDrink.js @@ -1,16 +1,13 @@ const models = require("../models"); +const utils = require("./utils"); module.exports = socket => { return async () => { let drinks = [] - for (let i of await models.Drink.findAll({ + for (let d of await models.Drink.findAll({ order: ["name"] })) { - drinks.push({ - id: i.id, - name: i.name, - price: i.price - }); + drinks.push(utils.drinkExport(d)); } socket.emit("list drink", drinks); } diff --git a/sockets/listIngredient.js b/sockets/listIngredient.js index e1be04a..5c69774 100644 --- a/sockets/listIngredient.js +++ b/sockets/listIngredient.js @@ -1,4 +1,5 @@ const models = require("../models"); +const utils = require("./utils"); module.exports = socket => { return async () => { @@ -6,11 +7,7 @@ module.exports = socket => { for (let i of await models.Ingredient.findAll({ order: ["name"] })) { - ingredients.push({ - id: i.id, - name: i.name, - price: i.price - }); + ingredients.push(utils.ingredientExport(i)); } socket.emit("list ingredient", ingredients); } diff --git a/sockets/listSauce.js b/sockets/listSauce.js index a4b6582..e894b56 100644 --- a/sockets/listSauce.js +++ b/sockets/listSauce.js @@ -1,16 +1,13 @@ const models = require("../models"); +const utils = require("./utils"); module.exports = socket => { return async () => { let sauces = [] - for (let d of await models.Sauce.findAll({ + for (let s of await models.Sauce.findAll({ order: ["name"] })) { - sauces.push({ - id: d.id, - name: d.name, - price: d.price - }); + sauces.push(utils.sauceExport(s)); } socket.emit("list sauce", sauces); } diff --git a/sockets/setDessert.js b/sockets/setDessert.js new file mode 100644 index 0000000..ac8172e --- /dev/null +++ b/sockets/setDessert.js @@ -0,0 +1,21 @@ +const models = require("../models"); +const utils = require("./utils"); + +module.exports = socket => { + return async (data) => { + try { + let d = await models.Dessert.findByPk(data.id); + if (!d) + throw new Error("Dessert not found !"); + + if (await utils.update(d, data)) { + let send = utils.dessertExport(d); + socket.emit("set dessert", send); + socket.broadcast.emit("set dessert", send); + } + } catch (e) { + socket.emit("internal error"); + console.error(e); + } + } +} diff --git a/sockets/setDish.js b/sockets/setDish.js new file mode 100644 index 0000000..3f08dad --- /dev/null +++ b/sockets/setDish.js @@ -0,0 +1,21 @@ +const models = require("../models"); +const utils = require("./utils"); + +module.exports = socket => { + return async (data) => { + try { + let d = await models.Dish.findByPk(data.id); + if (!d) + throw new Error("Dish not found !"); + + if (await utils.update(d, data)) { + let send = utils.dishExport(d); + socket.emit("set dish", send); + socket.broadcast.emit("set dish", send); + } + } catch (e) { + socket.emit("internal error"); + console.error(e); + } + } +} diff --git a/sockets/setDrink.js b/sockets/setDrink.js new file mode 100644 index 0000000..9ef1638 --- /dev/null +++ b/sockets/setDrink.js @@ -0,0 +1,21 @@ +const models = require("../models"); +const utils = require("./utils"); + +module.exports = socket => { + return async (data) => { + try { + let d = await models.Drink.findByPk(data.id); + if (!d) + throw new Error("Drink not found !"); + + if (await utils.update(d, data)) { + let send = utils.drinkExport(d); + socket.emit("set drink", send); + socket.broadcast.emit("set drink", send); + } + } catch (e) { + socket.emit("internal error"); + console.error(e); + } + } +} diff --git a/sockets/setIngredient.js b/sockets/setIngredient.js new file mode 100644 index 0000000..8e47e61 --- /dev/null +++ b/sockets/setIngredient.js @@ -0,0 +1,21 @@ +const models = require("../models"); +const utils = require("./utils"); + +module.exports = socket => { + return async (data) => { + try { + let i = await models.Ingredient.findByPk(data.id); + if (!i) + throw new Error("Ingredient not found !"); + + if (await utils.update(i, data)) { + let send = utils.ingredientExport(i); + socket.emit("set ingredient", send); + socket.broadcast.emit("set ingredient", send); + } + } catch (e) { + socket.emit("internal error"); + console.error(e); + } + } +} diff --git a/sockets/setSauce.js b/sockets/setSauce.js new file mode 100644 index 0000000..3edcddd --- /dev/null +++ b/sockets/setSauce.js @@ -0,0 +1,21 @@ +const models = require("../models"); +const utils = require("./utils"); + +module.exports = socket => { + return async (data) => { + try { + let s = await models.Sauce.findByPk(data.id); + if (!s) + throw new Error("Sauce not found !"); + + if (await utils.update(s, data)) { + let send = utils.sauceExport(s); + socket.emit("set sauce", send); + socket.broadcast.emit("set sauce", send); + } + } catch (e) { + socket.emit("internal error"); + console.error(e); + } + } +} diff --git a/sockets/utils.js b/sockets/utils.js index 59fd784..38c1320 100644 --- a/sockets/utils.js +++ b/sockets/utils.js @@ -17,6 +17,65 @@ function commandExport (c) { } } +function dishExport(d) { + return { + id: d.id, + name: d.name, + available: d.available, + price: d.price, + maxIngredients: d.maxIngredients, + maxSauces: d.maxSauces + } +} + +function ingredientExport(i) { + return { + id: i.id, + name: i.name, + available: i.available, + price: i.price + } +} + +function sauceExport(s) { + return { + id: s.id, + name: s.name, + available: s.available, + price: s.price + } +} + +function drinkExport(d) { + return { + id: d.id, + name: d.name, + available: d.available, + price: d.price + } +} + +function dessertExport(d) { + return { + id: d.id, + name: d.name, + available: d.available, + price: d.price + } +} + +async function update(s, v) { + let edit = false; + for (let a in v) + if (s[a] !== v[a]) { + s[a] = v[a]; + edit = true; + } + if (edit) + await s.save(); + return edit; +} + async function resetService(c) { let service = await models.Service.findOne({where:{date:{[models.Sequelize.Op.eq]: new Date()}}, include: ["sandwich1", "sandwich2", "sandwich3"]}); if (c.WIP && service) { @@ -51,5 +110,11 @@ async function price(data) { } module.exports.commandExport = commandExport; +module.exports.dishExport = dishExport; +module.exports.ingredientExport = ingredientExport; +module.exports.sauceExport = sauceExport; +module.exports.drinkExport = drinkExport; +module.exports.dessertExport = dessertExport; module.exports.resetService = resetService; +module.exports.update = update; module.exports.price = price; diff --git a/views/menu.pug b/views/menu.pug index e69de29..f467665 100644 --- a/views/menu.pug +++ b/views/menu.pug @@ -0,0 +1,23 @@ +extends layout + +block content + div#main-container.bg-contact2(style="background-image: url(/images/bg-01.jpg);") + form#stocks.container(action="") + div#dish + h1 Dishes + ul + div#ingredient + h1 Ingredients + ul + div#sauce + h1 Sauces + ul + div#drink + h1 Drinks + ul + div#dessert + h1 Desserts + ul + + script(src="/socket.io/socket.io.js") + script(src="/javascripts/menu.js")