diff --git a/.gitignore b/.gitignore index b512c09..34977ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +node_modules +.idea \ No newline at end of file diff --git a/index.html b/index.html index 94c5443..554bd3a 100644 --- a/index.html +++ b/index.html @@ -5,51 +5,57 @@ - + Der Durstrechner -
+
-
-
    -
  • Test
  • -
-
Keine Produkte ausgewählt
+
+
  • + + 5 + 2,50 + Wasser mit Kohlensäure + + +
  • +
      +
      Keine Produkte ausgewählt

      -
      -
      -
      -
      +
      +
      +
      - Produktbild + Produktbild
      - Wasser mit Kohlensäure + Wasser mit Kohlensäure
      -
      +
      diff --git a/script/all.js b/script/all.js index 4da7e10..39f51ca 100644 --- a/script/all.js +++ b/script/all.js @@ -1 +1,2 @@ -import './theme.js' \ No newline at end of file +import './theme.js' +import './calculator.js' \ No newline at end of file diff --git a/script/calculator.js b/script/calculator.js index e69de29..35f763e 100644 --- a/script/calculator.js +++ b/script/calculator.js @@ -0,0 +1,165 @@ +class TemplateElement { + static getProductTemplate() { + const element = document.querySelector('[data-template=product]').cloneNode(true); + return this.removeTemplate(element); + } + static getCartLineTemplate() { + const element = document.querySelector('[data-template=product-line-item]').cloneNode(true); + return this.removeTemplate(element); + } + + static removeTemplate(element) { + element.removeAttribute('data-template'); + return element; + } +} + +class Product { + constructor(name, price, image) { + this.id = Product.generateId(); + this.name = name; + this.price = price; + this.image = image; + } + + static generateId() { + return Math.floor(Math.random() * 1000000000) * Math.floor(Math.random() * 1000000000); + } + + getProductElement() { + const productElement = TemplateElement.getProductTemplate(); + productElement.setAttribute('data-id', this.id); + productElement.querySelector('[data-attr=name]').textContent = this.name; + productElement.querySelector('[data-attr=image]').src = this.image; + productElement.addEventListener('click', () => { + cart.addProduct(this); + }) + return productElement; + } +} + +class CartLine { + constructor(product, quantity) { + this.product = product; + this.quantity = quantity; + } +} + +class ProductList { + constructor() { + this.products = []; + this.products.push(new Product('Product 1', 10, 'https://placehold.co/250x250/000000/FFF?text=Product 1')); + this.products.push(new Product('Product 2', 5, 'https://placehold.co/250x250/000000/FFF?text=Product 2')); + this.products.push(new Product('Product 3', 2.5, 'https://placehold.co/250x250/000000/FFF?text=Product 3')); + this.products.push(new Product('Product 4', 1, 'https://placehold.co/250x250/000000/FFF?text=Product 4')); + this.renderProductList(); + } + + getProductJson() { + return JSON.stringify(this.products); + } + + getProductListElement() { + return document.querySelector('.product-list'); + } + + renderProductList() { + this.products.forEach(e => { + this.getProductListElement().appendChild(e.getProductElement()); + }) + } +} + +class Cart { + constructor() { + this.cartLines = []; + this.getCartButton().addEventListener('click', () => { + this.cartLines = []; + this.renderCart(); + }); + } + + addProduct(product) { + const cartLine = this.cartLines.find(e => e.product.id === product.id); + if (cartLine) { + cartLine.quantity++; + } else { + this.cartLines.push(new CartLine(product, 1)); + } + this.renderCart(); + } + + removeProduct(product) { + const cartLine = this.cartLines.find(e => e.product.id === product.id); + if (cartLine) { + cartLine.quantity--; + if (cartLine.quantity <= 0) { + this.cartLines = this.cartLines.filter(e => e.product.id !== product.id); + } + } + this.renderCart(); + } + + renderCart() { + // Clear the cart element before rendering except the template + this.getCartElement().querySelectorAll('[data-id]').forEach(e => { + if (e.getAttribute('data-template') === null) { + e.remove(); + } + }); + + if(this.cartLines.length === 0) { + this.getAlertElement().classList.remove('d-none'); + } else { + this.getAlertElement().classList.add('d-none'); + } + this.calculateCartValue(); + + // Render each cart line + this.cartLines.forEach(cartLine => { + const cartLineElement = this.getCartLineElement(cartLine); + this.getCartElement().appendChild(cartLineElement); + }); + } + + getCartLineElement(cartLine) { + const cartLineElement = TemplateElement.getCartLineTemplate(); + cartLineElement.setAttribute('data-id', cartLine.product.id); + cartLineElement.querySelector('[data-attr=name]').textContent = cartLine.product.name; + cartLineElement.querySelector('[data-attr=value]').textContent = Cart.getNumberFormatter().format(cartLine.product.price); + cartLineElement.querySelector('[data-attr=quantity]').textContent = cartLine.quantity; + cartLineElement.addEventListener('click', () => { + this.removeProduct(cartLine.product); + }) + return cartLineElement; + } + + getAlertElement() { + return document.querySelector('.alert.cart-empty'); + } + + getCartElement() { + return document.querySelector('.cart-items'); + } + + calculateCartValue() { + let cartValue = this.cartLines.reduce((acc, cartLine) => { + return acc + (cartLine.product.price * cartLine.quantity); + }, 0); + this.getCartButton().querySelector('[data-total-value]').textContent = Cart.getNumberFormatter().format(cartValue); + } + + static getNumberFormatter() { + return new Intl.NumberFormat('de-DE', { + currency: 'EUR', + minimumFractionDigits: 2 + }); + } + + getCartButton() { + return document.querySelector('button.cart-value'); + } +} + +const cart = new Cart(); +const productList = new ProductList(); \ No newline at end of file diff --git a/stylesheet.css b/stylesheet.css index 6080ed7..126af62 100644 --- a/stylesheet.css +++ b/stylesheet.css @@ -1,3 +1,36 @@ +.line-item-details { + .amount { + display: inline-block; + min-width: 1.5em; + } + .price { + display: inline-block; + min-width: 3em; + } +} .currency-value::after { content: ' €'; +} +.quantity-value::after { + content: 'x '; +} +.name-value { + margin-left: 1em; + font-weight: bold; +} +[data-template] { + display: none !important; +} +.cart-items, .product-list, .alert, .navbar-brand { + user-select: none; + -webkit-user-select: none; + -webkit-user-drag: none; +} +img { + user-select: none; + -webkit-user-select: none; + -webkit-user-drag: none; +} +.product-box, .cart-items { + cursor: pointer; } \ No newline at end of file