diff options
| author | Leo Goetz <dev@leogtz.de> | 2026-01-29 14:55:56 +0100 |
|---|---|---|
| committer | Leo Goetz <dev@leogtz.de> | 2026-01-29 14:55:56 +0100 |
| commit | d5a420a8135537c9fc36f9dd81ec7c9fc0500e66 (patch) | |
| tree | 7b3db6a743d8f463432b719748e2a3f99960dade | |
| parent | 64cc496a6cb6e1b73ed731f814018bab62d01d84 (diff) | |
feat: added router, api and data
| -rw-r--r-- | app.js | 13 | ||||
| -rw-r--r-- | index.html | 154 | ||||
| -rw-r--r-- | services/API.js | 10 | ||||
| -rw-r--r-- | services/Menu.js | 5 | ||||
| -rw-r--r-- | services/Router.js | 61 | ||||
| -rw-r--r-- | services/Store.js | 8 |
6 files changed, 180 insertions, 71 deletions
@@ -0,0 +1,13 @@ +import Store from "./services/Store.js"; +import { loadData } from "./services/Menu.js"; +import Router from "./services/Router.js"; + +window.app = { + store: Store, + router: Router, +}; + +window.addEventListener("DOMContentLoaded", () => { + loadData(); + app.router.init(); +}); @@ -1,94 +1,106 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width" /> <title>Coffee Masters</title> - <link rel="preconnect" href="https://fonts.googleapis.com"> - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> - <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;700&display=swap" rel="stylesheet"> - <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0" /> + <link rel="preconnect" href="https://fonts.googleapis.com" /> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> + <link + href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;700&display=swap" + rel="stylesheet" + /> + <link + rel="stylesheet" + href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0" + /> - <link rel="stylesheet" href="styles.css"> - <link rel="manifest" href="app.webmanifest"> - <link rel="apple-touch-icon" href="images/icons/icon.png"> - <link rel="icon" href="images/icons/icon.png"> -</head> + <script src="app.js" type="module" defer></script> -<body> + <link rel="stylesheet" href="styles.css" /> + <link rel="manifest" href="app.webmanifest" /> + <link rel="apple-touch-icon" href="images/icons/icon.png" /> + <link rel="icon" href="images/icons/icon.png" /> + </head> + + <body> <header> - <h1><img src="images/logo.svg" width="140" alt="Coffee Masters"></h1> - <nav> - <a class="navlink material-symbols-outlined" id="linkHome" href="/"> - local_cafe - </a> - <a class="navlink material-symbols-outlined" id="linkOrder" href="/order"> - shopping_cart - </a> - <span id="badge" hidden></span> - </nav> + <h1><img src="images/logo.svg" width="140" alt="Coffee Masters" /></h1> + <nav> + <a class="navlink material-symbols-outlined" id="linkHome" href="/"> + local_cafe + </a> + <a + class="navlink material-symbols-outlined" + id="linkOrder" + href="/order" + > + shopping_cart + </a> + <span id="badge" hidden></span> + </nav> </header> - <main> - </main> + <main></main> <template id="menu-page-template"> - <section> - <ul id="menu"></ul> - </section> + <section> + <ul id="menu"></ul> + </section> </template> <template id="product-item-template"> - <article> - <a href="#"> - <img> - <section> - <div> - <h4></h4> - <p class="price"><p> - </div> - <button>Add</button> - </section> - </a> - </article> + <article> + <a href="#"> + <img /> + <section> + <div> + <h4></h4> + <p class="price"></p> + <p></p> + </div> + <button>Add</button> + </section> + </a> + </article> </template> <template id="order-form-template"> - <form> - <label for="name">Your Name</label> - <input name="name" required> - <label for="phone">Your Phone Number</label> - <input name="phone" type="tel"> - <label for="email">Your Email</label> - <input name="email" type="email"> - <button type="submit">Place Order</button> - </form> + <form> + <label for="name">Your Name</label> + <input name="name" required /> + <label for="phone">Your Phone Number</label> + <input name="phone" type="tel" /> + <label for="email">Your Email</label> + <input name="email" type="email" /> + <button type="submit">Place Order</button> + </form> </template> <template id="details-page-template"> - <header> - <a href="#" onclick="app.router.go('/'); event.preventDefault()">< Back</a> - <h2></h2> - <a></a> - </header> - <img src=""> - <p class="description"></p> - <p class="price"></p> - <button>Add to cart</button> + <header> + <a href="#" onclick="app.router.go('/'); event.preventDefault()" + >< Back</a + > + <h2></h2> + <a></a> + </header> + <img src="" /> + <p class="description"></p> + <p class="price"></p> + <button>Add to cart</button> </template> <template id="cart-item-template"> - <li> - <p class='qty'></p> - <p class='name'></p> - <p class='price'></p> - <p class='toolbar'> - <a href="#" class="delete-button"> - 🗑️ - </a> - </p> - </li> + <li> + <p class="qty"></p> + <p class="name"></p> + <p class="price"></p> + <p class="toolbar"> + <a href="#" class="delete-button"> 🗑️ </a> + </p> + </li> </template> -</body> -</html>
\ No newline at end of file + </body> +</html> diff --git a/services/API.js b/services/API.js new file mode 100644 index 0000000..b28feba --- /dev/null +++ b/services/API.js @@ -0,0 +1,10 @@ +const API = { + // url: "https://firtman.github.io/coffeemasters/api/menu.json", + url: "/data/menu.json", + fetchMenu: async () => { + const result = await fetch(API.url); + return await result.json(); + }, +}; + +export default API; diff --git a/services/Menu.js b/services/Menu.js new file mode 100644 index 0000000..88e3f35 --- /dev/null +++ b/services/Menu.js @@ -0,0 +1,5 @@ +import API from "./API.js"; + +export async function loadData() { + app.store.menu = await API.fetchMenu(); +} diff --git a/services/Router.js b/services/Router.js new file mode 100644 index 0000000..13ef58e --- /dev/null +++ b/services/Router.js @@ -0,0 +1,61 @@ +const Router = { + init: () => { + document.querySelectorAll("a.navlink").forEach((a) => { + a.addEventListener("click", (event) => { + event.preventDefault(); + const url = event.target.getAttribute("href"); + Router.go(url); + }); + }); + // Event Handler for URL changes + window.addEventListener("popstate", (event) => { + Router.go(event.state.route, false); + }); + + // Check inital URL + Router.go(location.pathname); + }, + + go: (route, addToHistory = true) => { + console.log("Going to route" + route); + + if (addToHistory) { + history.pushState({ route }, "", route); + } + + let pageElement = null; + + switch (route) { + case "/": + pageElement = document.createElement("h1"); + pageElement.textContent = "Menu"; + break; + case "/order": + pageElement = document.createElement("h1"); + pageElement.textContent = "Your Order"; + break; + default: + if (route.startsWith("/product-")) { + pageElement = document.createElement("h1"); + pageElement.textContent = "Your Order"; + const paramId = route.substring(route.lastIndexOf("-") + 1); + // Dataset is great for storing costum data because it doesnt get + // parsed by the browser + pageElement.dataset.id = paramId; + } + } + + if (pageElement) { + // document.querySelector("main").children[0].remove(); + + // For little Performance Improvement + const cache = document.querySelector("main"); + cache.innerHTML = ""; + cache.appendChild(pageElement); + window.screenX = 0; + window.screenY = 0; + } + }, +}; + +export default Router; diff --git a/services/Store.js b/services/Store.js new file mode 100644 index 0000000..979a5a6 --- /dev/null +++ b/services/Store.js @@ -0,0 +1,8 @@ +import API from "./API.js"; + +const Store = { + menu: null, + cart: [], +}; + +export default Store; |
