-
+
Warenkorb teilen
@@ -204,5 +204,5 @@
@section('scripts')
-
+
@stop
diff --git a/js/checkout.js b/js/checkout.js
index a35c99b..663d44a 100644
--- a/js/checkout.js
+++ b/js/checkout.js
@@ -1,17 +1,22 @@
+import * as Cart from './modules/cart.js';
+import { numberToEuroFormat } from './utils.js';
+import { Product } from './elements/product.js';
+
function clearAddressFields() {
- $('#address-components').hide();
- $('#street-number').val('');
- $('#street-number').prop('disabled', true);
- $('#route').val('');
- $('#locality').val('');
- $('#postal-code').val('');
+ document.querySelector('#address-components').style.display = "none";
+ document.querySelector('#street-number').value = '';
+ document.querySelector('#street-number').setAttribute('disabled', true);
+ document.querySelector('#route').value = '';
+ document.querySelector('#locality').value = '';
+ document.querySelector('#postal-code').value = '';
}
+
function getAddressFiedlValue(addressComponents, $field) {
let field = addressComponents.find(obj => obj.types.indexOf($field) > -1);
return field != undefined ? field.long_name : '';
}
-urlBase = $('meta[name="url-base"]').attr("content");
+const urlBase = document.querySelector('meta[name="url-base"]').getAttribute("content");
let input = document.querySelector("#ctelefon");
let iti = null;
@@ -28,50 +33,55 @@ if (input != undefined) {
utilsScript: urlBase + "/template/libs/intl-tel-input/js/utils.min.js",
});
}
-function updateProducts() {
- $('#list-products').html('');
- if (objProducts.length > 0) {
- getInfoFromSelectedProduct().done(function (response, status) {
- response.contents.forEach(function (product) {
- let objProduct = getProductInfo(product);
- let elementProduct = createProductElement(objProduct);
- $('#list-products').append(elementProduct);
- });
- if (totalPrice > 0) {
- $('#total-checkout-price').text(numberToEuroFormat(totalPrice));
- } else {
- $('#form-section').hide();
- $('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').hide();
- $('#total-checkout-price').parent().parent().parent().hide();
- $('#no-products-in-checkout').hide();
- $('#cart-error-in-checkout').show();
- }
- }).fail(function (response) {
- $('#form-section').hide();
- $('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').hide();
- $('#total-checkout-price').parent().parent().parent().hide();
- $('#no-products-in-checkout').hide();
- $('#cart-error-in-checkout').show();
+
+async function updateProducts() {
+ document.querySelector('#list-products').innerHTML = '';
+
+ let products = await Cart.getItems();
+
+ if (products.length > 0) {
+
+ products.forEach(function (product) {
+
+
+ let elementProduct = Product(product);
+
+ let productRow = document.createElement('tr');
+ productRow.innerHTML = elementProduct;
+
+ document.querySelector('#list-products').append(productRow);
+
});
- $('#form-section').show();
- $('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').show();
- $('#total-checkout-price').parent().parent().parent().show();
- $('#no-products-in-checkout').hide();
- $('#cart-error-in-checkout').hide();
+
+ if (Cart.getTotalPrice() > 0) {
+ document.querySelector('#total-checkout-price').text(numberToEuroFormat(Cart.getTotal()));
+ } else {
+ document.querySelector('#form-section').style.display = "none";
+ //$('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').hide();
+ //document.querySelector('#total-checkout-price').parentElement.parentElement.parentElement.style.display = "none";
+ document.querySelector('#no-products-in-checkout').style.display = "none";
+ document.querySelector('#cart-error-in-checkout').style.display = "block";
+ }
+
+ document.querySelector('#form-section').style.display = "block";
+ //document.querySelector('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').show();
+ //document.querySelector('#total-checkout-price').parentElement.parentElement.parentElement.style.display = "block";
+ document.querySelector('#no-products-in-checkout').style.display = "none";
+ document.querySelector('#cart-error-in-checkout').style.display = "none";
}
else {
- $('#form-section').hide();
- $('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').hide();
- $('#total-checkout-price').parent().parent().parent().hide();
- $('#no-products-in-checkout').show();
- $('#cart-error-in-checkout').hide();
+ document.querySelector('#form-section').style.display = "none";
+ //$('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').hide();
+ document.querySelector('#total-checkout-price').parentElement.parentElement.parentElement.style.display = "none";
+ document.querySelector('#no-products-in-checkout').style.display = "block";
+ document.querySelector('#cart-error-in-checkout').style.display = "none";
}
}
-$(window).on('load', function () {
+document.addEventListener('DOMContentLoaded', () => {
updateProducts();
- $("#successful-submitting-form").delay(4000).slideUp(200, function () { $(this).alert('close'); });
- $('#anfrage').submit(function (event) {
+ //document.querySelector("#successful-submitting-form").delay(4000).slideUp(200, function () { $(this).alert('close'); });
+ document.querySelector('#checkout').addEventListener("submit", function (event) {
event.preventDefault();
let form = $(this);
getInfoFromSelectedProduct().done(function (response, status) {
@@ -88,32 +98,32 @@ $(window).on('load', function () {
form.unbind('submit').submit();
});
});
- $(document).on('click', '.btn-remove-product', function () {
- if (objProducts.length > 0) {
- $('#form-section').show();
- $('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').show();
- $('#total-checkout-price').parent().parent().parent().show();
- $('#no-products-in-checkout').hide();
- } else {
- $('#form-section').hide();
- $('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').hide();
- $('#total-checkout-price').parent().parent().parent().hide();
- $('#no-products-in-checkout').show();
+
+ document.body.addEventListener('click', async function (event) {
+ if (event.target.matches('.btn-remove-product')) {
+ if (objProducts.length > 0) {
+ $('#form-section').show();
+ $('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').show();
+ $('#total-checkout-price').parent().parent().parent().show();
+ $('#no-products-in-checkout').hide();
+ } else {
+ $('#form-section').hide();
+ $('#list-products').parent().parent().parent().parent().parent().find('.modal-footer').hide();
+ $('#total-checkout-price').parent().parent().parent().hide();
+ $('#no-products-in-checkout').show();
+ }
}
});
- $(document).on('input', '.select-quantity', function () {
- getInfoFromSelectedProduct().done(function (response, status) {
- totalPrice = 0;
- response.contents.forEach(function (product) {
- let objProduct = getProductInfo(product);
- objProduct = calculatePrice(objProduct);
- totalPrice += objProduct.calc_preis * objProduct.quantity;
- });
- $('#total-checkout-price').text(numberToEuroFormat(totalPrice));
- });
+
+ document.body.addEventListener('input', async function (event) {
+ if (event.target.matches('.select-quantity')) {
+ let products = await Cart.getTotalPrice();
+ document.querySelector('.js-total-price').innerText = numberToEuroFormat(products);
+ }
});
});
+/*
$(window).on('load', google.maps.event, function () {
let input = document.getElementById('field_location');
let options = {
@@ -122,7 +132,9 @@ $(window).on('load', google.maps.event, function () {
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
autocomplete.addListener("place_changed", () => {
+
clearAddressFields();
+
const place = autocomplete.getPlace();
if (!place.geometry) return;
var componentMap = {
@@ -160,4 +172,5 @@ $(window).on('load', google.maps.event, function () {
}
});
});
-});
\ No newline at end of file
+});
+*/
\ No newline at end of file
diff --git a/js/elements/product.js b/js/elements/product.js
new file mode 100644
index 0000000..113ce3c
--- /dev/null
+++ b/js/elements/product.js
@@ -0,0 +1,29 @@
+import { numberToEuroFormat } from "../utils.js";
+
+export function Product(data) {
+ return `
+
+
+
+ |
+
+
+ ${data.title}
+
+
+ sofort verfügbar
+
+
+
+ |
+
+ ${numberToEuroFormat(data.calc_preis)}
+
+
+ ${(((data.calc_preis - data.preis) * 100) / data.preis).toFixed(2) + ' %'}
+ |
+
`;
+}
\ No newline at end of file
diff --git a/js/main.js b/js/main.js
new file mode 100644
index 0000000..093f7a3
--- /dev/null
+++ b/js/main.js
@@ -0,0 +1,199 @@
+import * as Cart from './modules/cart.js';
+import { numberToEuroFormat } from './utils.js';
+import { Product } from './elements/product.js';
+
+async function displayProducts() {
+ document.querySelector('#list-products-in-bag').innerHTML = '';
+ let products = await Cart.getItems();
+ if (products.length > 0) {
+ products.forEach(function (product) {
+ let elementProduct = Product(product);
+
+ let productRow = document.createElement("tr");
+ productRow.innerHTML = elementProduct;
+
+ document.querySelector('#list-products-in-bag').append(productRow);
+ });
+
+ let quantity = await Cart.getQuantity();
+ document.querySelectorAll('.js-product-counter').forEach(element => {
+ element.innerText = quantity;
+
+ if (quantity > 0) element.style.display = "block";
+ else element.style.display = "none";
+ });
+
+ let totalPrice = await Cart.getTotalPrice();
+ document.querySelectorAll(".js-total-price").forEach(element => {
+ element.innerText = numberToEuroFormat(totalPrice);
+ });
+
+ let link = await Cart.getLink();
+ document.querySelectorAll('.js-cart-link').forEach(element => element.value = link);
+
+ if (navigator.share) document.querySelectorAll(".btn-share").forEach(button => {
+ button.addEventListener("click", async function () {
+ try {
+ const shareData = {
+ title: "Share cart list",
+ text: 'share cart list',
+ url: link,
+ };
+ await navigator.share(shareData);
+ }
+ catch (error) {
+ console.error(error);
+ }
+ });
+ });
+ else {
+ document.querySelectorAll(".btn-share").forEach(button => { button.style.display = "none"; });
+
+ console.warn('Native Web Sharing not supported');
+ }
+
+ let copyCartLink = document.querySelector('#btn-copy-cart-link');
+
+ let copyIcon = `
`;
+
+ let copiedIcon = `
`;
+
+ if (copyCartLink != undefined) copyCartLink.addEventListener("click", () => {
+ let cartLink = document.querySelector('.cart-link');
+ if (cartLink && cartLink.select) {
+ navigator.clipboard.writeText(cartLink.value).then(() => {
+ copyCartLink.innerHTML = copiedIcon;
+ setTimeout(() => { copyCartLink.innerHTML = copyIcon; }, 3000);
+ }).catch(function (error) {
+ console.error(error);
+ });
+ }
+ });
+
+ //document.querySelectorAll('.cart-link').forEach(cartLink => cartLink.style.display = "block");
+ //document.querySelectorAll(".btn-share").forEach(btnShare => btnShare.style.display = "block");
+
+ //document.querySelector('#shopping-cart').querySelector('.modal-footer').style.display = "block";
+ //document.querySelector('#total-price').parentElement.parentElement.parentElement.style.display = "block";
+ document.querySelector('#no-products').style.display = "none";
+ document.querySelector('#cart-error').style.display = "none";
+ document.querySelector('#modal-buttons').style.display = "flex";
+ } else {
+ document.querySelectorAll('.cart-link').forEach(cartLink => cartLink.style.display = "none");
+ document.querySelectorAll(".btn-share").forEach(btnShare => btnShare.style.display = "none");
+
+ //document.querySelector('#list-products-in-bag').parentElement.parentElement.parentElement.parentElement.parentElement.querySelector('.modal-footer').style.display = "none";
+ //document.querySelector('#total-price').parentElement.parentElement.parentElement.style.display = "none";
+ document.querySelector('#no-products').style.display = "block";
+ document.querySelector('#cart-error').style.display = "none";
+ document.querySelector('#modal-buttons').style.display = "none";
+
+ document.querySelector('#selected-products').style.display = "none";
+ }
+}
+
+document.addEventListener('DOMContentLoaded', async () => {
+
+ displayProducts();
+
+ document.body.addEventListener('click', async function (event) {
+ if (event.target.matches('.btn-remove-product')) {
+ let button = event.target;
+
+ let productId = button.getAttribute('data-id');
+
+ await Cart.removeItem(productId);
+
+ button.parentElement.parentElement.remove();
+
+ displayProducts();
+
+ /* productId = document.querySelector('meta[name="product-id"]').getAttribute('content');
+ if (productId != undefined) {
+ let objProduct = objProducts.find(obj => obj.id == productId);
+ if (objProduct == undefined) {
+ $('#btn-add-to-bag').show();
+ $('#btn-show-bag').hide();
+ if (objProducts.length > 0) $('#btn-check-out').parent().hide();
+ else $('#btn-check-out').parent().show();
+ }
+ else {
+ $('#btn-add-to-bag').hide();
+ $('#btn-show-bag').show();
+ $('#btn-check-out').parent().hide();
+ $('#count-items-in-bag').html(objProduct.quantity + `
`);
+ }
+ } */
+ }
+ });
+
+ /* document.querySelectorAll('.select-quantity').forEach(async input => {
+
+ let quantity = input.value;
+ let productId = input.getAttribute('data-id');
+
+ Cart.updateItem(productId, { quantity: quantity });
+
+ let product = Cart.getItem(productId);
+
+ let elementPrice = `
+
${numberToEuroFormat(product.calc_preis)}`;
+ if (product.calc_preis != product.preis) elementPrice += `
+
+
+
${(((product.calc_preis - product.preis) * 100) / product.preis).toFixed(2)} %
+ `;
+ input.parentElement.parentElement.querySelector('.product-price').innerHTML = elementPrice;
+
+ quantity = await Cart.getQuantity();
+ document.querySelectorAll('.js-product-counter').forEach(counter => {
+ counter.innerText = quantity;
+ if (quantity > 0) counter.style.display = "block";
+ else counter.style.display = "none";
+ });
+
+ document.querySelector('#total-price').innerText = numberToEuroFormat(Cart.getTotalPrice());
+
+ productId = document.querySelector('meta[name="product-id"]').getAttribute('content');
+ if (productId != undefined) {
+ let objProduct = objProducts.find(obj => obj.id == productId);
+ if (objProduct == undefined) {
+ $('#btn-add-to-bag').show();
+ $('#btn-show-bag').hide();
+ if (objProducts.length > 0) $('#btn-check-out').parent().hide();
+ else $('#btn-check-out').parent().show();
+ }
+ else {
+ $('#btn-add-to-bag').hide();
+ $('#btn-show-bag').show();
+ $('#btn-check-out').parent().hide();
+ $('#count-items-in-bag').html(objProduct.quantity + `
`);
+ }
+ }
+} ); * /
+
+ /* let sharedCode = getSharedCode();
+ if (sharedCode) {
+ if (Cart.getItems().length > 0) $('#modal-confirm-product-replacement').modal('show');
+ else $('#modal-confirm-addition-of-products').modal('show');
+
+ $('.btn-confirm-product-link').click(function () {
+ objProducts = JSON.parse(sharedCode);
+ window.location.replace($('meta[name="checkout"]').attr('content'));
+ });
+ } */
+
+ /* if (localStorage.getItem("dismiss-message") == 1) $('.alert-dismissible').remove();
+ else $('.alert-dismissible').show();
+ $('#btn-close-message').click(function () { localStorage.setItem("dismiss-message", 1); }); */
+});
diff --git a/js/modules/cart.js b/js/modules/cart.js
new file mode 100644
index 0000000..e649bea
--- /dev/null
+++ b/js/modules/cart.js
@@ -0,0 +1,97 @@
+import { url } from '../utils.js';
+
+let isSync = false;
+let items = null;
+
+export async function sync() {
+ if (!isSync) {
+ if (items !== null) {
+ let miniItems = items.map(obj => { return { id: obj.id, quantity: obj.quantity } });
+ localStorage.setItem("cart", JSON.stringify(miniItems));
+ }
+
+ if (localStorage.getItem("cart") != null) {
+ let cartItems = localStorage.getItem("cart");
+ items = JSON.parse(cartItems);
+ }
+
+ let ids = items.map(obj => obj.id);
+
+ if (ids.length > 0) {
+ let products = await fetch(document.querySelector('meta[name="get-contents"]').getAttribute('content') + "/" + ids.join(","));
+ products = await products.json();
+
+ products.contents.forEach(product => {
+ product.quantity = items.find(obj => obj.id == product.id).quantity;
+
+ product.calc_preis = product.preis;
+ if (product.quantity >= 5 && product.preis_5) product.calc_preis = product.preis_5;
+ if (product.quantity >= 10 && product.preis_10) product.calc_preis = product.preis_10;
+ });
+
+ items = products.contents;
+ }
+
+ isSync = true;
+ }
+}
+
+export function addItem(id) {
+ let objProductInfo = items.find(obj => obj.id == id);
+ let index = items.indexOf(objProductInfo);
+ if (index == -1) items.push({ id: id, quantity: 1 });
+ isSync = false;
+ sync();
+}
+
+export async function updateItem(id, data) {
+ let product = await getItem(id);
+ if (data.quantity) product.quantity = data.quantity;
+ isSync = false;
+ await sync();
+}
+
+export async function removeItem(id) {
+ items = items.filter(item => item.id !== Number(id));
+ console.log(items);
+ isSync = false;
+ await sync();
+}
+
+export async function getItem(id) {
+ await sync();
+ return items.find(obj => obj.id == id);
+}
+
+export async function getItems() {
+ await sync();
+ return items;
+}
+
+export async function getQuantity() {
+ await sync();
+ let quantitys = items.map(obj => obj.quantity);
+ let quantityOfProducts = 0;
+ for (let i = 0; i < quantitys.length; i++) { if (Number.isInteger(Number(quantitys[i]))) quantityOfProducts += Number(quantitys[i]); }
+ return quantityOfProducts;
+}
+
+export async function getTotalPrice() {
+ await sync();
+
+ let totalPrice = 0;
+
+ items.forEach(product => {
+ product.calc_preis = product.preis;
+ if (product.quantity >= 5 && product.preis_5) product.calc_preis = product.preis_5;
+ if (product.quantity >= 10 && product.preis_10) product.calc_preis = product.preis_10;
+ totalPrice += product.calc_preis * product.quantity;
+ });
+
+ return totalPrice;
+}
+
+export async function getLink() {
+ await sync();
+ return url(btoa(JSON.stringify(items)));
+}
\ No newline at end of file
diff --git a/js/product.js b/js/product.js
index 3a9a4d0..da6a74f 100644
--- a/js/product.js
+++ b/js/product.js
@@ -1,20 +1,47 @@
-$(window).on('load', function(){
- $('#btn-check-out').click(function(){
- let productId = $(this).attr("data-id");
- addToBag(productId);
- window.location.replace($('meta[name="checkout"]').attr('content'));
- });
- $('#btn-add-to-bag').click(function(){
- let productId = $(this).attr("data-id");
- let parentElement = $('#count-products-in-bag').parent();
- let copyElemetn = $('#count-products-in-bag').clone();
- copyElemetn.attr('id', '');
- copyElemetn.appendTo(parentElement);
- $('#count-products-in-bag').addClass('animate__animated animate__backInUp');
- $('#count-products-in-bag').on('animationend', function(){
- $('#count-products-in-bag').removeClass('animate__animated animate__backInUp');
- copyElemetn.remove();
- });
- addToBag(productId);
+import * as Cart from './modules/cart.js';
+
+document.addEventListener("DOMContentLoaded", async () => {
+ let productId = document.querySelector('meta[name="product-id"]').getAttribute('content');
+ if (productId != undefined) {
+
+ let products = await Cart.getItems();
+
+ let objProduct = products.find(obj => obj.id == productId);
+ if (objProduct == undefined) {
+ document.querySelector('#btn-add-to-bag').style.display = "block";
+ document.querySelector('#btn-show-bag').style.display = "none";
+ if (Cart.getItems().length > 0) document.querySelector('#btn-check-out').parentElement.style.display = "none";
+ else document.querySelector('#btn-check-out').parentElement.display = "block";
+ }
+ else {
+ $('#btn-add-to-bag').hide();
+ $('#btn-show-bag').show();
+ $('#btn-check-out').parent().hide();
+ $('#count-items-in-bag').html(objProduct.quantity + `
`);
+ }
+ }
+
+ let btnCheckOut = document.querySelector('#btn-check-out');
+
+ btnCheckOut.addEventListener("click", () => {
+ let productId = btnCheckOut.getAttribute("data-id");
+ Cart.addItem(productId);
+ window.location.replace(document.querySelector('meta[name="checkout"]').getAttribute('content'));
+ });
+
+ let btnAddToBag = document.querySelector('#btn-add-to-bag');
+
+ btnAddToBag.addEventListener("click", () => {
+ let productId = btnAddToBag.getAttribute("data-id");
+ let parentElement = document.querySelector('#count-products-in-bag').parentElement;
+ let copyElemetn = document.querySelector('#count-products-in-bag').clone();
+ copyElemetn.attr('id', '');
+ copyElemetn.appendTo(parentElement);
+ $('#count-products-in-bag').addClass('animate__animated animate__backInUp');
+ $('#count-products-in-bag').on('animationend', function () {
+ $('#count-products-in-bag').removeClass('animate__animated animate__backInUp');
+ copyElemetn.remove();
});
+ Cart.addProduct(productId);
+ });
});
\ No newline at end of file
diff --git a/js/utils.js b/js/utils.js
new file mode 100644
index 0000000..151cdc3
--- /dev/null
+++ b/js/utils.js
@@ -0,0 +1,54 @@
+export function numberToEuroFormat(number) {
+ let formatter = new Intl.NumberFormat('de', { style: 'currency', currency: 'EUR' });
+ return formatter.format(number);
+}
+
+export function isJson(string) {
+ try { JSON.parse(string); }
+ catch (error) { return false; }
+ return true;
+}
+
+export function isEncoded(string) {
+ try { atob(string); }
+ catch (error) { return false; }
+ return true;
+}
+
+export function fetchData(method = null, url, data = null) {
+
+ const csrf = $('meta[name="csrf-token"]').attr('content');
+ const urlBase = document.querySelector('meta[name="url-base"]').getAttribute("content");
+
+ const urlPattern = /^(https?:\/\/|ftp:\/\/)[^\s/$.?#].[^\s]*$/i;
+ const pathPattern = /^(\/|[^\/\s]+\/)[^\s]*$/;
+
+ if (pathPattern.test(url)) url = urlBase + (url.startsWith('/') ? "" : "/") + url;
+ else if (!urlPattern.test(url)) throw new Error("Invalid URL.");
+
+ return fetch(url, {
+ method: method ?? 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-CSRF-TOKEN': csrf
+ },
+ body: JSON.stringify(data ?? {})
+ })
+ .then(response => response.json())
+ .catch(error => console.error("Error fetching data:", error));
+}
+
+export function url(path = "") {
+ let protocol = window.location.protocol;
+ let host = window.location.hostname;
+ let port = window.location.port;
+ let pathk = window.location.pathname;
+
+ let baseUrl = protocol + "//" + host + (port ? ':' + port : '');
+
+ let pathArray = pathk.split('/');
+ pathArray.pop();
+ let directoryOnly = pathArray.join('/');
+
+ return baseUrl + directoryOnly + '/' + path;
+}
\ No newline at end of file