product listing

Former-commit-id: 1ee2385fa95125e08311a8e15b7ac4b38c111e26
This commit is contained in:
Benjamin Kyd
2022-03-29 00:23:42 +01:00
parent 01c624e1b5
commit b652d8cd6b
12 changed files with 186 additions and 35 deletions

View File

@@ -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);
}
}

View File

@@ -44,11 +44,11 @@
}
.notification-bar-close:active {
color: #fff;
color: #F5F6F6;
}
.notification-bar-close:hover {
color: #fff;
color: #F5F6F6;
}
.notification-bar-close:focus {

View File

@@ -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'),

View File

@@ -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,

View 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);

View File

@@ -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>

View File

@@ -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%;
}
}

View File

@@ -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>

View File

@@ -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

View File

@@ -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.

View File

@@ -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/');

View File

@@ -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,
};