Begin Store Front project using web components
This commit is contained in:
parent
4e61a13d5e
commit
1aeaed646e
6 changed files with 184 additions and 0 deletions
20
web-apps/main.go
Normal file
20
web-apps/main.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.Handle("GET /store-front/", http.StripPrefix("/store-front", http.FileServer(http.Dir("store-front"))))
|
||||
|
||||
log.Println("Start the web server...")
|
||||
err := http.ListenAndServe(":8080", mux)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
24
web-apps/store-front/css/grid.css
Normal file
24
web-apps/store-front/css/grid.css
Normal file
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Grid Layout
|
||||
*/
|
||||
|
||||
@media (min-width: 20em) {
|
||||
grid-of-photos div {
|
||||
display: grid;
|
||||
grid-template-columns: 50% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 32em) {
|
||||
grid-of-photos div {
|
||||
display: grid;
|
||||
grid-template-columns: 33% 33% 33%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 42em) {
|
||||
grid-of-photos div {
|
||||
display: grid;
|
||||
grid-template-columns: 20% 20% 20% 20% 20%;
|
||||
}
|
||||
}
|
4
web-apps/store-front/css/pico.min.css
vendored
Normal file
4
web-apps/store-front/css/pico.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
34
web-apps/store-front/index.html
Normal file
34
web-apps/store-front/index.html
Normal file
|
@ -0,0 +1,34 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<link rel="stylesheet" href="css/pico.min.css">
|
||||
<link rel="stylesheet" href="css/grid.css">
|
||||
<title>Project - Store Front</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<nav>
|
||||
<ul>
|
||||
<li><strong>Sparrow Photography</strong></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="#">About</a></li>
|
||||
<li><a href="#">Services</a></li>
|
||||
<li><a href="#">Products</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="container">
|
||||
<grid-of-photos>
|
||||
<p aria-busy="true">Loading...</p>
|
||||
</grid-of-photos>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p><em>Photos by Jack Sparrow. All rights reserved.</em></p>
|
||||
</div>
|
||||
<script src="js/grid-of-photos.js"></script>
|
||||
</body>
|
||||
</html>
|
1
web-apps/store-front/js/.#grid-of-photos.js
Symbolic link
1
web-apps/store-front/js/.#grid-of-photos.js
Symbolic link
|
@ -0,0 +1 @@
|
|||
andrea@lv5.321700:1727085997
|
101
web-apps/store-front/js/grid-of-photos.js
Normal file
101
web-apps/store-front/js/grid-of-photos.js
Normal file
|
@ -0,0 +1,101 @@
|
|||
const endpoint = 'https://leanwebclub.com/course-apis/photos.json';
|
||||
|
||||
class GridOfPhotos extends HTMLElement {
|
||||
|
||||
/**
|
||||
* Instantiate the component
|
||||
*/
|
||||
constructor () {
|
||||
// Inherit parent class properties
|
||||
super();
|
||||
|
||||
// LIsten for events
|
||||
this.addEventListener('click', this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs each time the element is appended to or moved in the DOM
|
||||
*/
|
||||
async connectedCallback () {
|
||||
|
||||
// Fetch the photos from the API
|
||||
this.photos = await this.fetchPhotos();
|
||||
|
||||
// If there are no photos
|
||||
if (!this.photos || !this.photos.length) {
|
||||
this.innerHTML = '<p>There are no available photos at this time. Please try again later. Sorry!</p>';
|
||||
}
|
||||
|
||||
// Render the element
|
||||
this.innerHTML = `
|
||||
<div>
|
||||
${this.photos.map( (image) => { return `<img src="${image.url}" alt="${image.description}"></img>` } ).join('')}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch photos from the API
|
||||
* @return {Promise} response - The response from the API
|
||||
*/
|
||||
async fetchPhotos () {
|
||||
try {
|
||||
let response = await fetch(endpoint);
|
||||
if (!response.ok) throw response.status;
|
||||
|
||||
let data = await response.json();
|
||||
if (!data) throw 'No data!';
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.warn("ERR:", error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle events
|
||||
* @param {Event} event - The event object
|
||||
*/
|
||||
handleEvent (event) {
|
||||
this[`on${event.type}`](event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the click event
|
||||
* @param {Event} event - The event object
|
||||
*/
|
||||
onclick (event) {
|
||||
if (!event.target.closest('img')) return;
|
||||
|
||||
let dialog = document.createElement('dialog');
|
||||
dialog.setAttribute('open', '');
|
||||
|
||||
dialog.innerHTML = `
|
||||
<article>
|
||||
<h2>Confirm Your Membership</h2>
|
||||
<p>
|
||||
Thank you for signing up for a membership!
|
||||
Please review the membership details below:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Membership: Individual</li>
|
||||
<li>Price: $10</li>
|
||||
</ul>
|
||||
<footer>
|
||||
<button class="secondary">
|
||||
Close
|
||||
</button>
|
||||
</footer>
|
||||
</article>
|
||||
`
|
||||
this.append(dialog);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Define the new web component
|
||||
if ('customElements' in window) {
|
||||
customElements.define('grid-of-photos', GridOfPhotos);
|
||||
}
|
Loading…
Reference in a new issue