From b652d8cd6b7738b0cd397cde8cbb913200fa422e Mon Sep 17 00:00:00 2001 From: Benjamin Kyd Date: Tue, 29 Mar 2022 00:23:42 +0100 Subject: [PATCH] product listing Former-commit-id: 1ee2385fa95125e08311a8e15b7ac4b38c111e26 --- client/public/components/components.mjs | 11 ++- .../public/components/css/notificationbar.css | 4 +- client/public/components/notificationbar.mjs | 37 ++++++++++ client/public/components/product-list.mjs | 74 +++++++++++++------ client/public/components/product-listing.mjs | 22 ++++++ .../components/templates/notificationbar.html | 2 +- client/public/global.css | 16 ++-- client/public/index.html | 3 +- docs/API.md | 29 ++++++++ docs/CLIENT-FRAMEWORK.md | 5 ++ src/routes/api.js | 3 + src/routes/helpers.js | 15 ++++ 12 files changed, 186 insertions(+), 35 deletions(-) create mode 100644 client/public/components/product-listing.mjs diff --git a/client/public/components/components.mjs b/client/public/components/components.mjs index d14d12b..394bdc2 100644 --- a/client/public/components/components.mjs +++ b/client/public/components/components.mjs @@ -28,6 +28,7 @@ export class Component extends HTMLElement { } // Override these + PostLoad() { } Update() { } Render() { Component.__WARN('Render'); } OnceRendered() { Component.__WARN('Render'); } @@ -46,10 +47,12 @@ export class Component extends HTMLElement { } this.setState(stateUpdateQueue); - this.Update(); + this.PostLoad(Object.bind(this)); + + this.Update(Object.bind(this)); if (this.attributes.length === 0) { - this.__INVOKE_RENDER(); + this.__INVOKE_RENDER(Object.bind(this)); } } @@ -122,12 +125,12 @@ export class Component extends HTMLElement { if (m[1].startsWith('this.state')) { const stateKey = m[1].substring(11); const stateValue = this.state[stateKey]; - console.log('attempting to replace', m[0], 'with', stateValue); + // console.log('attempting to replace', m[0], 'with', stateValue); if (stateValue === undefined) { continue; } - console.log('replacing', m[0], 'with', stateValue); + // console.log('replacing', m[0], 'with', stateValue); resolved = resolved.replace(m[0], stateValue); } } diff --git a/client/public/components/css/notificationbar.css b/client/public/components/css/notificationbar.css index 3c68835..e1f61f1 100644 --- a/client/public/components/css/notificationbar.css +++ b/client/public/components/css/notificationbar.css @@ -44,11 +44,11 @@ } .notification-bar-close:active { - color: #fff; + color: #F5F6F6; } .notification-bar-close:hover { - color: #fff; + color: #F5F6F6; } .notification-bar-close:focus { diff --git a/client/public/components/notificationbar.mjs b/client/public/components/notificationbar.mjs index 261c20a..69d8dca 100644 --- a/client/public/components/notificationbar.mjs +++ b/client/public/components/notificationbar.mjs @@ -7,6 +7,43 @@ class NotificationBar extends Component { super(NotificationBar); } + daysHoursMinutesSecondsUntil(time) { + const now = new Date(); + const end = new Date(time); + const diff = end.getTime() - now.getTime(); + const days = Math.floor(diff / (1000 * 60 * 60 * 24)); + const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((diff % (1000 * 60)) / 1000); + return { + days, + hours, + minutes, + seconds, + }; + } + + async PostLoad() { + const data = await fetch('/api/special').then(response => response.json()); + const { days, hours, minutes, seconds } = this.daysHoursMinutesSecondsUntil(data.data.end); + + this.setState({ + title: data.data.title, + endTime: data.data.end, + timePretty: `${days}d ${hours}h ${minutes}m ${seconds}s`, + }); + } + + Update() { + setInterval(() => { + const { days, hours, minutes, seconds } = this.daysHoursMinutesSecondsUntil(this.state.endTime); + this.setState({ + ...this.getState, + timePretty: `${days}d ${hours}h ${minutes}m ${seconds}s`, + }); + }, 1000); + } + Render() { return { template: SideLoad('./components/templates/notificationbar.html'), diff --git a/client/public/components/product-list.mjs b/client/public/components/product-list.mjs index af064be..243ff7f 100644 --- a/client/public/components/product-list.mjs +++ b/client/public/components/product-list.mjs @@ -27,7 +27,8 @@ class ProductList extends Component {
-
+ +
`, style: ` @@ -57,41 +58,72 @@ class ProductList extends Component { border: none; } - .lds-ring { + .product-list-loader { + display: flex; + justify-content: center; + } + + .lds-ellipsis { display: inline-block; position: relative; width: 80px; height: 80px; } - .lds-ring div { - box-sizing: border-box; - display: block; + .lds-ellipsis div { position: absolute; - width: 64px; - height: 64px; - margin: 8px; - border: 8px solid #fff; + top: 33px; + width: 13px; + height: 13px; border-radius: 50%; - animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; - border-color: #fff transparent transparent transparent; + background: #7F5CFF; + animation-timing-function: cubic-bezier(0, 1, 1, 0); } - .lds-ring div:nth-child(1) { - animation-delay: -0.45s; + .lds-ellipsis div:nth-child(1) { + left: 8px; + animation: lds-ellipsis1 0.6s infinite; } - .lds-ring div:nth-child(2) { - animation-delay: -0.3s; + .lds-ellipsis div:nth-child(2) { + left: 8px; + animation: lds-ellipsis2 0.6s infinite; } - .lds-ring div:nth-child(3) { - animation-delay: -0.15s; + .lds-ellipsis div:nth-child(3) { + left: 32px; + animation: lds-ellipsis2 0.6s infinite; } - @keyframes lds-ring { + .lds-ellipsis div:nth-child(4) { + left: 56px; + animation: lds-ellipsis3 0.6s infinite; + } + @keyframes lds-ellipsis1 { 0% { - transform: rotate(0deg); + transform: scale(0); } 100% { - transform: rotate(360deg); + transform: scale(1); } - } + } + @keyframes lds-ellipsis3 { + 0% { + transform: scale(1); + } + 100% { + transform: scale(0); + } + } + @keyframes lds-ellipsis2 { + 0% { + transform: translate(0, 0); + } + 100% { + transform: translate(24px, 0); + } + } + + @media (pointer:none), (pointer:coarse), screen and (max-width: 900px) { + .product-list { + /*justify-content: space-between;*/ + } + } `, state: { ...this.getState, diff --git a/client/public/components/product-listing.mjs b/client/public/components/product-listing.mjs new file mode 100644 index 0000000..114c884 --- /dev/null +++ b/client/public/components/product-listing.mjs @@ -0,0 +1,22 @@ +import { RegisterComponent, Component } from './components.mjs'; + +class ProductListing extends Component { + static __IDENTIFY() { return 'product-listing'; } + + constructor() { + super(ProductListing); + } + + async Render() { + const route = this.state.getroute; + const productDetails = await fetch(route).then(response => response.json()); + } + + + OnceRendered() { + + + } +} + +RegisterComponent(ProductListing); diff --git a/client/public/components/templates/notificationbar.html b/client/public/components/templates/notificationbar.html index f7ed97f..5635b17 100644 --- a/client/public/components/templates/notificationbar.html +++ b/client/public/components/templates/notificationbar.html @@ -1,6 +1,6 @@
- {this.state.notification} + {this.state.timePretty} - {this.state.title}