product listing
Former-commit-id: 1ee2385fa95125e08311a8e15b7ac4b38c111e26
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,11 +44,11 @@
|
||||
}
|
||||
|
||||
.notification-bar-close:active {
|
||||
color: #fff;
|
||||
color: #F5F6F6;
|
||||
}
|
||||
|
||||
.notification-bar-close:hover {
|
||||
color: #fff;
|
||||
color: #F5F6F6;
|
||||
}
|
||||
|
||||
.notification-bar-close:focus {
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -27,7 +27,8 @@ class ProductList extends Component {
|
||||
</div>
|
||||
<!--Infinite Loading-->
|
||||
<div class="product-list-loader">
|
||||
<div class="lds-ring"><div></div><div></div><div></div><div></div></div>
|
||||
<!-- https://loading.io/css/ -->
|
||||
<div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
|
||||
</div>
|
||||
`,
|
||||
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,
|
||||
|
||||
22
client/public/components/product-listing.mjs
Normal file
22
client/public/components/product-listing.mjs
Normal file
@@ -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);
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="notification-bar">
|
||||
<div class="notification-bar-text">
|
||||
{this.state.notification}
|
||||
{this.state.timePretty} - {this.state.title}
|
||||
</div>
|
||||
<button class="notification-toggler">
|
||||
<span class="cross-line cross-line-top"></span>
|
||||
|
||||
@@ -22,17 +22,21 @@ limited-margin {
|
||||
max-width: 1400px;
|
||||
}
|
||||
|
||||
/* responsive sidebar stop scrolling */
|
||||
/* also making sure this is applied any time it's on a mobile device */
|
||||
@media (pointer:none), (pointer:coarse), screen and (max-width: 900px) {
|
||||
/* small screen */
|
||||
@media screen and (max-width: 900px) {
|
||||
limited-margin {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
/* mobile */
|
||||
@media (pointer:none), (pointer:coarse) {
|
||||
body {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
limited-margin {
|
||||
width: 90%;
|
||||
/* padding-left: 1em;
|
||||
padding-right: 1em; */
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
<script type="module" src="components/storefront.mjs"></script>
|
||||
<script type="module" src="components/product-list.mjs"></script>
|
||||
<script type="module" src="components/compact-listing.mjs"></script>
|
||||
<script type="module" src="components/product-listing.mjs"></script>
|
||||
|
||||
<script type="module" src="index.mjs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<notificationbar-component notification="15:03:04 - New Limited Time Offer, Get Any Lego Set for £10 Using Code LEGO10"></notificationbar-component>
|
||||
<notificationbar-component></notificationbar-component>
|
||||
|
||||
<limited-margin>
|
||||
<navbar-component></navbar-component>
|
||||
|
||||
29
docs/API.md
29
docs/API.md
@@ -10,6 +10,8 @@ automatically every request
|
||||
|
||||
| Type | Route | Queries | Auth? | Notes |
|
||||
| --- | --- | --- | -- | --- |
|
||||
| GET | /api/special/ | | no | |
|
||||
| GET | /api/type/:id | | no | |
|
||||
| GET | /api/search/ | query, page | no | Query endpoint |
|
||||
| GET | /api/bricks/ | query, page | no | Query endpoint |
|
||||
| GET | /api/sets/ | query, page | no | Query endpoint |
|
||||
@@ -47,6 +49,33 @@ brick: brick to search for (absolute)
|
||||
|
||||
set: brick to search for (absolute)
|
||||
|
||||
### /api/special/
|
||||
|
||||
GET /api/special/
|
||||
|
||||
Response Object
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"title": "Special 1",
|
||||
"end": "2020-01-31T00:00:00.000Z",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### /api/type/:id
|
||||
|
||||
GET /api/type/:id
|
||||
|
||||
Response Object
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"type": "brick", // or set
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### /api/search/
|
||||
|
||||
GET /api/search?params
|
||||
|
||||
@@ -90,6 +90,11 @@ State is updated with `setState()`.
|
||||
Within the HTML, any instance of `{this.state.}` will be replaced with
|
||||
the internal state of the component.
|
||||
|
||||
The `PostLoad` method is called once the component has been loaded and
|
||||
attatched to the DOM. This is where you can do any post-load setup.
|
||||
It is only called once and it's return value becomes the state of the
|
||||
component.
|
||||
|
||||
The `Update` method is called when the global state or the attribute
|
||||
state changes, and is expected to modify the internal state before
|
||||
rendering.
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
const Logger = require('../logger.js');
|
||||
const Server = require('./server.js');
|
||||
|
||||
const Helpers = require('./helpers.js');
|
||||
const Bricks = require('./bricks-router.js');
|
||||
const Sets = require('./sets-router.js');
|
||||
const Query = require('./query-router.js');
|
||||
const Auth0 = require('./auth0-router.js');
|
||||
|
||||
function Init() {
|
||||
Server.App.get('/api/special/', Helpers.Special);
|
||||
|
||||
Server.App.get('/api/search/', []);
|
||||
Server.App.get('/api/bricks/', Bricks.Query);
|
||||
Server.App.get('/api/sets/');
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// 15 days from now
|
||||
const EndDate = new Date(Date.parse(new Date()) + 15 * 24 * 60 * 60 * 1000);
|
||||
|
||||
function Special(req, res, next) {
|
||||
res.send({
|
||||
data: {
|
||||
title: '£10 off any LEGO set! Limited Time Only!',
|
||||
end: EndDate,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Special,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user