From 40ac174f88372f222b6b05a9c738ea9af391fda7 Mon Sep 17 00:00:00 2001 From: Seth W Date: Mon, 26 Jul 2021 03:44:16 -0400 Subject: [PATCH] Receipts + Order History --- routes/authenticate.js | 16 ++++ routes/cart.js | 155 ++++++++++++++++++++++++++++++++++++++ www/404.html | 1 + www/_includes/navbar.html | 7 +- www/_layouts/default.html | 11 +++ www/cart.html | 30 ++++++-- www/cdn/css/global.css | 8 ++ www/cdn/img/invoice.svg | 1 + www/cdn/img/receipt.svg | 1 + www/history.html | 101 +++++++++++++++++++++++++ www/index.html | 2 + www/receipt.html | 101 +++++++++++++++++++++++++ 12 files changed, 425 insertions(+), 9 deletions(-) create mode 100644 www/cdn/img/invoice.svg create mode 100644 www/cdn/img/receipt.svg create mode 100644 www/history.html create mode 100644 www/receipt.html diff --git a/routes/authenticate.js b/routes/authenticate.js index bbcd876..312ac21 100644 --- a/routes/authenticate.js +++ b/routes/authenticate.js @@ -2,6 +2,22 @@ const bcrypt = require('bcryptjs') const express = require('express') const router = express.Router(); +router.post('/verifyIntegrity', async (req, res) => { + const { + body: { token }, + method, + } = req + + let user = await sql.query(` + SELECT id + FROM users + WHERE token = ? + LIMIT 1`, [token]); + + if (!user) return res.json({ error: 'Invalid token. Try logging back in.' }) + res.status(200).end(); +}) + router.post('/login', async (req, res) => { const { body: { email, password }, diff --git a/routes/cart.js b/routes/cart.js index f830959..d7a26ed 100644 --- a/routes/cart.js +++ b/routes/cart.js @@ -58,6 +58,129 @@ router.post('/fetch', async (req, res) => { res.json({ data: Object.values(result) }); }); +router.post('/fetchall', async (req, res) => { + const { + body: { token }, + method, + } = req + + let user = await sql.query(` + SELECT id + FROM users + WHERE token = ? + LIMIT 1`, [token]); + if (!user) return res.json({ error: 'Invalid token. Try logging back in.' }) + user = user.id + + let orders = await sql.query(` + SELECT id, time FROM orders + WHERE user_id = ? AND status = 1 + ORDER BY time DESC`, + [user]) + if (!orders || !orders.length) return res.json({ data: [] }) + + let result = {}; + for (let order of orders) { + let { time } = order; + order = order.id; + result[order] = { id: order, time, items: []}; + + let items = await sql.query(` + SELECT items.id, items.product_id, items.quantity, products.name, products.cost as price FROM orders + INNER JOIN order_items as items + ON orders.id = items.order_id + JOIN products + ON items.product_id = products.id + WHERE orders.id = ? + ORDER BY time DESC`, + [order]) + if (!items) return res.json({ data: [] }) + + let temp = {}; + items.map(item => { + let { id, name, price, quantity } = item; + return temp[id] = { id, name, price, quantity }; + }); + + let toppings = await sql.query(` + SELECT orders.order_item, toppings.name, toppings.price FROM order_modifications as orders + JOIN toppings + ON orders.topping_id = toppings.id + WHERE order_id = ?`, [order]); + + if (toppings) { + for (let topping of toppings) { + if (!temp[topping.order_item].toppings) + temp[topping.order_item].toppings = []; + let { name, price } = topping; + temp[topping.order_item].toppings.push({ name, price }); + } + } + + result[order].items = Object.values(temp); + } + + res.json({ data: Object.values(result) }); +}); + +router.post('/receipt', async (req, res) => { + const { + body: { token }, + method, + } = req + + let user = await sql.query(` + SELECT id + FROM users + WHERE token = ? + LIMIT 1`, [token]); + if (!user) return res.json({ error: 'Invalid token. Try logging back in.' }) + user = user.id + + let order = await sql.query(` + SELECT id, time FROM orders + WHERE user_id = ? AND status = 1 + ORDER BY time DESC LIMIT 1`, + [user]) + if (!order) return res.json({ data: [] }) + let { time } = order; + order = order.id + + let items = await sql.query(` + SELECT items.id, items.product_id, items.quantity, products.name, products.cost as price FROM orders + INNER JOIN order_items as items + ON orders.id = items.order_id + JOIN products + ON items.product_id = products.id + WHERE orders.id = ? + ORDER BY time DESC`, + [order]) + if (!items) return res.json({ data: [] }) + + let result = {}; + items.map(item => { + let { id, name, price, quantity } = item; + return result[id] = { id, name, price, quantity }; + }); + + let toppings = await sql.query(` + SELECT orders.order_item, toppings.name, toppings.price FROM order_modifications as orders + JOIN toppings + ON orders.topping_id = toppings.id + WHERE order_id = ?`, [order]); + + if (toppings) { + for (let topping of toppings) { + if (!result[topping.order_item].toppings) + result[topping.order_item].toppings = []; + let { name, price } = topping; + result[topping.order_item].toppings.push({ name, price }); + } + } + + res.json({ data: { id: order, time, items: Object.values(result) }}); +}); + router.post('/add', async (req, res) => { const { body: { token, product, quantity, toppings }, @@ -154,4 +277,36 @@ router.post('/remove', async (req, res) => { res.status(200).end(); }) +router.post('/checkout', async (req, res) => { + const { + body: { token, type }, + method, + } = req + + let user = await sql.query(` + SELECT id + FROM users + WHERE token = ? + LIMIT 1`, [token]); + if (!user) return res.json({ error: 'Invalid token. Try logging back in.' }) + user = user.id + + let order = await sql.query(` + SELECT id FROM orders + WHERE user_id = ? AND status = 0 + ORDER BY time DESC LIMIT 1`, + [user]) + if (!order) return res.json({ data: [] }) + order = order.id + + let r = await sql.query(` + UPDATE orders + SET status = 1, + type = ?, + time = ? + WHERE id = ?`, [type, ~~(Date.now() / 1000), order]); + + res.status(200).end(); +}); + module.exports = router diff --git a/www/404.html b/www/404.html index af43df5..be1bc32 100644 --- a/www/404.html +++ b/www/404.html @@ -1,5 +1,6 @@ --- permalink: /404 +title: 404 layout: default --- diff --git a/www/_includes/navbar.html b/www/_includes/navbar.html index 85462b3..3d57eea 100644 --- a/www/_includes/navbar.html +++ b/www/_includes/navbar.html @@ -20,6 +20,9 @@ + @@ -36,6 +39,6 @@ \ No newline at end of file diff --git a/www/_layouts/default.html b/www/_layouts/default.html index 14c5f60..f97c4e2 100644 --- a/www/_layouts/default.html +++ b/www/_layouts/default.html @@ -27,6 +27,17 @@ type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" > + {% include navbar.html %}
{{ content }} diff --git a/www/cart.html b/www/cart.html index 35e9894..0b98d99 100644 --- a/www/cart.html +++ b/www/cart.html @@ -1,6 +1,6 @@ --- layout: default -title: Login +title: Cart container_class: col-xl-5 col-lg-6 col-sm-8 d-flex flex-column justify-content-center flex-grow-1 mt-2 --- @@ -14,7 +14,7 @@ @@ -63,7 +69,7 @@ // something in cart let items = res.data; let subtotal = 0; - items.map(item => { + items.map((item, i) => { let price = item.price * item.quantity; if (item.toppings) { for (let topping of item.toppings) @@ -74,7 +80,7 @@ subtotal += price; $('#table').append(` - 1 + ${item.quantity} ${item.name} ${item.price} @@ -87,8 +93,18 @@ } })(); - document.querySelector('#check_out').addEventListener('click', e => { + document.querySelector('#check_out').addEventListener('click', async e => { e.preventDefault(); - window.location.href = '/'; + let token = localStorage.getItem('loginToken'); + let res = await $.post('{{ site.api }}/cart/checkout', { + token, + type: document.querySelector('#type').value + }); + + if (typeof res === 'string') { + window.location.href = '/receipt'; + } else if (!res || res.error) { + console.error(res.error); + } }); diff --git a/www/cdn/css/global.css b/www/cdn/css/global.css index f2b1be2..0fceb0f 100644 --- a/www/cdn/css/global.css +++ b/www/cdn/css/global.css @@ -83,6 +83,14 @@ html, body { border: 0.125rem solid var(--danger-hover-color) !important; } +.custom-select { + padding: .375rem 1.75rem .375rem .75rem; + color: #495057; + vertical-align: middle; + border: 1px solid #ced4da; + border-radius: .25rem; +} + /* Menu Items */ .menuItem > .row { margin: 1rem 0.25rem 0.5rem 0; diff --git a/www/cdn/img/invoice.svg b/www/cdn/img/invoice.svg new file mode 100644 index 0000000..bb9e997 --- /dev/null +++ b/www/cdn/img/invoice.svg @@ -0,0 +1 @@ +printing invoices \ No newline at end of file diff --git a/www/cdn/img/receipt.svg b/www/cdn/img/receipt.svg new file mode 100644 index 0000000..aedcc79 --- /dev/null +++ b/www/cdn/img/receipt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/www/history.html b/www/history.html new file mode 100644 index 0000000..680ce7e --- /dev/null +++ b/www/history.html @@ -0,0 +1,101 @@ +--- +layout: default +title: Order History +container_class: col-xl-5 col-lg-6 col-sm-8 d-flex flex-column justify-content-center flex-grow-1 mt-2 +--- + + + +
+ + diff --git a/www/index.html b/www/index.html index 6217637..2f0da2f 100644 --- a/www/index.html +++ b/www/index.html @@ -17,6 +17,8 @@