From f4b7a5fb38a7a455d3ed4f503833e405af5d151a Mon Sep 17 00:00:00 2001 From: Ben <36240171+benkyd@users.noreply.github.com> Date: Wed, 27 Apr 2022 00:35:37 +0100 Subject: [PATCH] better basket and users table Former-commit-id: cb7a9735df12510bc9d45b2bef984082799b0ab2 --- README.md | Bin 7900 -> 8360 bytes client/public/auth.mjs | 18 +- client/public/components/basket-popout.mjs | 48 +- client/public/components/basket.mjs | 124 +- client/public/components/navbar.mjs | 6 +- db/dump.sql | 4 + db/schema.sql | 12 +- package-lock.json | 9920 +++++++++++++++++++- src/controllers/brick-controller.js | 8 +- src/controllers/set-controller.js | 8 +- src/controllers/user-controller.js | 89 + src/logger.js | 25 +- src/routes/auth0-router.js | 34 +- src/routes/helpers.js | 6 +- src/routes/sets-router.js | 2 +- 15 files changed, 9775 insertions(+), 529 deletions(-) create mode 100644 src/controllers/user-controller.js diff --git a/README.md b/README.md index ab18b5a0e5994c523a857dcd583f9de4d46148c4..691a5f705eb2b3137d1a5f8cd1034e5a6323a3d3 100644 GIT binary patch delta 457 zcmZ`#u}Z^G6g^2TB#Kk%D7?W%kOo^QQV`4_E?o*;g{Vzip-IFf7^m#6adFboQGB~U z;4k%s|FZZ2u?>YCr&!d;{_1X1v#0-O?Ic@K>_py!5=E>c2O!MJBo`k}X z&v_c0V}=A*NcjnJL!>~)zi^j~3?*5qjZytp<;}O-tykn0+B*^tL>i)9v0jjpnlZIf zY9-7@RLOCtPBD=`_hYQcFQ~Xy?WuF3D%Y&b8MivuOjV|ccU30*cYy=+F|d=C-LRhb z=Gb@t-m&AY2hTU`>C6f+S2g1Nj~#&fPa&-A|37g=Mn pfzc^TZXx`IA`t@K0$K*V2ke)8z!*|{h(q)|CMnmC>{++=e*h%yTvz}A delta 61 zcmZ4Cc*l0b0;b7lm^7Gq8Mr2YWtzEp9?Jq25NES3=VnGQ<2_e5gi*;em1DDvXdB~Z IBk?j$0Aq3z0ssI2 diff --git a/client/public/auth.mjs b/client/public/auth.mjs index 470c584..dfff757 100644 --- a/client/public/auth.mjs +++ b/client/public/auth.mjs @@ -11,6 +11,7 @@ let auth0 = null; async function CheckRedirect() { const isAuthenticated = await auth0.isAuthenticated(); if (isAuthenticated) { + localStorage.loggedIn = true; return; } @@ -21,6 +22,7 @@ async function CheckRedirect() { await auth0.handleRedirectCallback(); } catch (e) { window.alert(e.message || 'authentication error, sorry'); + localStorage.loggedIn = false; Signout(); } @@ -30,6 +32,9 @@ async function CheckRedirect() { } export async function InitAuth0() { + localStorage.loggedIn = false; + localStorage.user = 'Guest'; + auth0 = await window.createAuth0Client({ domain: AUTH0CONFIG.domain, client_id: AUTH0CONFIG.clientId, @@ -41,7 +46,9 @@ export async function InitAuth0() { const isAuthenticated = await auth0.isAuthenticated(); if (isAuthenticated) { const user = await auth0.getUser(); + localStorage.user = user.given_name || user.nickname; NotifyNavbar('login', user); + localStorage.loggedIn = true; // tell the server about the logon, so that it can make the proper // entry in the database, if there is for example an address @@ -52,10 +59,11 @@ export async function InitAuth0() { method: 'GET', headers: { Authorization: `Bearer ${token}` }, }; - const res = await fetch('/api/auth/login', fetchOptions); - if (!res.ok) { - throw new Error('failed to login with the server'); - } + + const res = await fetch('/api/auth/login', fetchOptions).then(res => res.json()); + console.log(res); + + // do stuff } } @@ -80,6 +88,8 @@ export async function LoginSignup() { } export async function Signout() { + localStorage.loggedIn = false; + localStorage.user = 'Guest'; await auth0.logout({ returnTo: window.location.origin, }); diff --git a/client/public/components/basket-popout.mjs b/client/public/components/basket-popout.mjs index 3c77269..870140d 100644 --- a/client/public/components/basket-popout.mjs +++ b/client/public/components/basket-popout.mjs @@ -19,6 +19,13 @@ let basketCallback = null; // TODO: Does the localstorage have a problem with mutual exclusion? // TODO: Should the basket be persisted to the server? +export function GetBasketItems() { + if (localStorage.getItem('basket') === null || !localStorage.getItem('basket')) { + return; + } + return JSON.parse(localStorage.getItem('basket')).items; +} + export function AddProductToBasket(product, type, amount, brickModifier = 'none') { if (localStorage.getItem('basket') === null || !localStorage.getItem('basket')) { localStorage.setItem('basket', JSON.stringify({ @@ -61,46 +68,15 @@ export function RemoveProductFromBasket(product, type, amount, brickModifier = ' product += '~' + brickModifier; } - if (basket.items[product].quantity > amount) { - basket.items[product].quantity -= amount; - } else { - delete basket.items[product]; - } - - basket.total -= amount; - - localStorage.setItem('basket', JSON.stringify(basket)); - - if (basketCallback) { - basketCallback(); - } -} - -export function SetProductInBasket(product, type, amount, brickModifier = 'none') { - if (localStorage.getItem('basket') === null || !localStorage.getItem('basket')) { - return; - } - const basket = JSON.parse(localStorage.getItem('basket')); - - if (type === 'brick') { - product += '~' + brickModifier; - } - - if (amount === 0) { - delete basket.items[product]; - } else { - if (basket.items[product]) { - basket.total -= basket.items[product].quantity; - basket.items[product].quantity = amount; + if (basket.items[product]) { + if (basket.items[product].quantity > amount) { + basket.items[product].quantity -= amount; } else { - basket.items[product] = { - quantity: amount, - type, - }; + delete basket.items[product]; } } - basket.total += amount; + basket.total -= amount; localStorage.setItem('basket', JSON.stringify(basket)); diff --git a/client/public/components/basket.mjs b/client/public/components/basket.mjs index 4005561..2cf674a 100644 --- a/client/public/components/basket.mjs +++ b/client/public/components/basket.mjs @@ -1,4 +1,4 @@ -import { AddProductToBasket, SetProductInBasket, RemoveProductFromBasket, GetBasketTotal, GetBasketTotalPrice } from './basket-popout.mjs'; +import { GetBasketItems, AddProductToBasket, RemoveProductFromBasket, GetBasketTotal, GetBasketTotalPrice } from './basket-popout.mjs'; import { RegisterComponent, Component } from './components.mjs'; class Basket extends Component { @@ -39,7 +39,6 @@ class Basket extends Component {
${Object.keys(this.state.items).map((key) => { const item = this.state.items[key]; - console.log(key, item); const modifier = key.includes('~'); return /* html */`
@@ -49,13 +48,15 @@ class Basket extends Component { bigimage="true" ${modifier ? `modifier="${key.split('~')[1]}"` : ''}> -
- - - -  0 in stock -
- +
+
+ + + +  0 in stock +
+ +
`; }).join('')} @@ -65,9 +66,11 @@ class Basket extends Component { - - -
+ + + `, style: ` .basket { @@ -88,15 +91,38 @@ class Basket extends Component { flex-direction: row; align-items: center; } - + .basket-item-listing { + font-size: 1.3em; + flex-basis: 65%; + flex-grow: 4; + } + + @media (pointer:none), (pointer:coarse), screen and (max-width: 900px) { + .basket-item { + flex-direction: column; + } + + .basket-item-listing { + font-size: 1.3em; + width: 100%; + flex-basis: 100%; + flex-grow: 4; + } + } + + .basket-item-content { + flex-basis: 35%; + flex-grow: 1; width: 100%; margin: 0 auto; - font-size: 1.3em; + display: flex; + flex-direction: row; + justify-content: space-around; + align-items: center; } - + .product-quantity-selector { - flex-basis: 40%; display: flex; flex-direction: row; justify-content: center; @@ -140,6 +166,44 @@ class Basket extends Component { text-align: center; font-size: 1.2em; } + + .basket-footer { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 10px; + border-top: 1px solid #ccc; + } + + .basket-footer-subtotal { + font-size: 1.5em; + } + + .basket-footer-checkout { + flex-basis: 70%; + display: flex; + flex-direction: row; + justify-content: flex-end; + align-items: center; + } + + .basket-footer-button { + cursor: pointer; + background-color: #222; + border: none; + color: #F5F6F6; + padding: 0.5em; + margin-left: 1em; + font-size: 1.4em; + transition: all 0.2s ease-in; + } + + .basket-footer-button:hover { + background-color: #F5F6F6; + outline: 2px solid #222; + color: #222; + } `, }; } @@ -203,7 +267,6 @@ class Basket extends Component { const modifier = listing.getAttribute('modifier'); const compositeId = id + (modifier ? `~${modifier}` : ''); const item = this.state.items[compositeId]; - console.log(id, modifier, item); // update the quantity if (event.target.classList.contains('reduce-quantity')) { @@ -214,13 +277,12 @@ class Basket extends Component { if (item.quantity === 0) { RemoveProductFromBasket(id, item.type, item.quantity, modifier); this.UpdateSubtotal(); - delete this.state.items[compositeId]; return this.setState({ ...this.state, total: GetBasketTotal(), items: { - ...this.state.items, + ...GetBasketItems(), }, }); } @@ -232,13 +294,12 @@ class Basket extends Component { } else if (event.target.classList.contains('remove-quantity')) { RemoveProductFromBasket(id, item.type, item.quantity, modifier); this.UpdateSubtotal(); - delete this.state.items[compositeId]; return this.setState({ ...this.state, total: GetBasketTotal(), items: { - ...this.state.items, + ...GetBasketItems(), }, }); } @@ -286,23 +347,30 @@ class Basket extends Component { if (event.target.value > item.stock) { event.target.value = item.stock; } - item.quantity = parseInt(event.target.value); - SetProductInBasket(id, item.type, item.quantity, modifier); - this.UpdateSubtotal(); - - if (item.quantity === 0) { - delete this.state.items[compositeId]; + if (parseInt(event.target.value) === 0) { + RemoveProductFromBasket(id, item.type, item.quantity, modifier); return this.setState({ ...this.state, total: GetBasketTotal(), items: { - ...this.state.items, + ...GetBasketItems(), }, }); } + // if has gone up in quantity then add it + if (item.quantity < event.target.value) { + AddProductToBasket(id, item.type, event.target.value - item.quantity, modifier); + item.quantity = parseInt(event.target.value); + } else if (item.quantity > event.target.value) { + RemoveProductFromBasket(id, item.type, item.quantity - event.target.value, modifier); + item.quantity = parseInt(event.target.value); + } + + this.UpdateSubtotal(); + // update the total this.setState({ ...this.state, diff --git a/client/public/components/navbar.mjs b/client/public/components/navbar.mjs index 195a07c..1db13e4 100644 --- a/client/public/components/navbar.mjs +++ b/client/public/components/navbar.mjs @@ -7,7 +7,7 @@ import { LoginSignup, Signout } from '../auth.mjs'; let navbarCallback = null; export function NotifyNavbar(type, user) { if (navbarCallback && type === 'login') { - navbarCallback.OnLogin(user); + navbarCallback.OnLogin(); } if (navbarCallback && type === 'logout') { navbarCallback.OnLogout(); @@ -39,12 +39,12 @@ class NavBar extends Component { }); } - OnLogin(user) { + OnLogin() { const account = this.root.querySelector('.account-item'); // doing this with proper dom manipulation wasn't working account.innerHTML = ` - ${user.name}▾ + ${localStorage.user}▾