mirror of
https://github.com/cloudmaker97/DurstRechner.git
synced 2025-12-05 23:48:39 +00:00
283 lines
No EOL
9.2 KiB
JavaScript
283 lines
No EOL
9.2 KiB
JavaScript
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 getSettingsProductTemplate() {
|
|
const element = document.querySelector('[data-template=settings-product]').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;
|
|
}
|
|
getSettingsProductElement() {
|
|
const productElement = TemplateElement.getSettingsProductTemplate();
|
|
productElement.setAttribute('data-id', this.id);
|
|
productElement.textContent = this.name;
|
|
productElement.addEventListener('click', () => {
|
|
productList.removeProduct(this);
|
|
productList.setExportField();
|
|
productElement.remove();
|
|
})
|
|
return productElement;
|
|
}
|
|
}
|
|
|
|
class CartLine {
|
|
constructor(product, quantity) {
|
|
this.product = product;
|
|
this.quantity = quantity;
|
|
}
|
|
}
|
|
|
|
class ProductList {
|
|
constructor() {
|
|
this.loadFromJson(localStorage.getItem('products') ?? [])
|
|
this.setExportField();
|
|
this.getImportExportTextarea().addEventListener('input', (e) => {
|
|
try {
|
|
const json = e.target.value;
|
|
localStorage.setItem('products', json);
|
|
window.location = window.location;
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
setExportField() {
|
|
this.getImportExportTextarea().textContent = JSON.stringify(this.products);
|
|
}
|
|
|
|
loadFromJson(json) {
|
|
let parse = [];
|
|
try {
|
|
parse = JSON.parse(json);
|
|
} catch (e) {}
|
|
this.products = parse.map(e => new Product(e.name, e.price, e.image));
|
|
this.renderProductList();
|
|
}
|
|
|
|
getImportExportTextarea() {
|
|
return document.querySelector('#input-export-import');
|
|
}
|
|
|
|
getProductListElement() {
|
|
return document.querySelector('.product-list');
|
|
}
|
|
|
|
getSettingListElement() {
|
|
return document.querySelector('.settings-product-list');
|
|
}
|
|
|
|
renderProductList() {
|
|
// Clear the product list element before rendering except the template
|
|
this.getProductListElement().querySelectorAll('[data-id]').forEach(e => {
|
|
if (e.getAttribute('data-template') === null) {
|
|
e.remove();
|
|
}
|
|
});
|
|
this.products.forEach(e => {
|
|
this.getProductListElement().appendChild(e.getProductElement());
|
|
this.getSettingListElement().appendChild(e.getSettingsProductElement());
|
|
})
|
|
}
|
|
|
|
addProduct(product) {
|
|
this.products.push(product);
|
|
localStorage.setItem('products', JSON.stringify(this.products));
|
|
this.getProductListElement().appendChild(product.getProductElement());
|
|
this.getSettingListElement().appendChild(product.getSettingsProductElement());
|
|
this.setExportField();
|
|
}
|
|
|
|
removeProduct(product) {
|
|
this.products = this.products.filter(e => e.id !== product.id);
|
|
const productElement = this.getProductListElement().querySelector(`[data-id="${product.id}"]`);
|
|
if (productElement) {
|
|
productElement.remove();
|
|
}
|
|
localStorage.setItem('products', JSON.stringify(this.products));
|
|
this.setExportField();
|
|
}
|
|
}
|
|
|
|
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');
|
|
}
|
|
}
|
|
|
|
class Tab {
|
|
static toggleTab() {
|
|
if(!isSettingsTab) {
|
|
this.switchTab('settings');
|
|
} else {
|
|
this.switchTab('products');
|
|
}
|
|
isSettingsTab = !isSettingsTab;
|
|
}
|
|
static switchTab(tab) {
|
|
const tabs = document.querySelectorAll('[data-tab]');
|
|
tabs.forEach(e => {
|
|
e.classList.add('d-none');
|
|
});
|
|
const activeTab = document.querySelector(`[data-tab=${tab}]`);
|
|
activeTab.classList.remove('d-none');
|
|
}
|
|
}
|
|
|
|
let isSettingsTab = false;
|
|
const cart = new Cart();
|
|
const productList = new ProductList();
|
|
|
|
document.querySelector('[data-toggle-tab]').addEventListener('click', (e) => {
|
|
Tab.toggleTab();
|
|
});
|
|
|
|
document.querySelector('#create-product').addEventListener('click', (e) => {
|
|
e.preventDefault(); // Prevent form submission (if any)
|
|
|
|
const name = document.querySelector('#product-name').value;
|
|
let fieldPrice = document.querySelector('#product-price').value;
|
|
const image = document.querySelector('#product-image').files[0];
|
|
|
|
if(name.length === 0) {
|
|
alert('Name muss ausgefüllt sein');
|
|
return;
|
|
}
|
|
|
|
if (image) {
|
|
const reader = new FileReader();
|
|
reader.onloadend = function () {
|
|
const imageBase64 = reader.result;
|
|
const imageSrcWithBase64 = `data:${image.type};base64,${imageBase64.split(',')[1]}`;
|
|
productList.addProduct(new Product(name, fieldPrice, imageSrcWithBase64));
|
|
document.querySelector('#product-name').value = '';
|
|
document.querySelector('#product-price').value = '0,00';
|
|
document.querySelector('#product-image').value = '';
|
|
};
|
|
reader.readAsDataURL(image);
|
|
} else {
|
|
productList.addProduct(new Product(name, fieldPrice, `https://placehold.co/250x250?text={${name}}`));
|
|
document.querySelector('#product-name').value = '';
|
|
document.querySelector('#product-price').value = '';
|
|
document.querySelector('#product-image').value = '';
|
|
}
|
|
}); |