display cart

master
Gustavo Luigi 2023-10-21 01:05:42 -03:00
parent d87fb39a71
commit 18536ec606
8 changed files with 509 additions and 91 deletions

View File

@ -62,7 +62,6 @@

<div class="collapse navbar-collapse justify-content-end" id="navbarSupportedContent">
<ul class="navbar-nav fs-5">

<a class="nav-item nav-link {{request()->is('produkt*')?'active':''}}" href="{{url('/produkte')}}">Produkte</a>
<a class="nav-item nav-link {{request()->is('leistung*')?'active':''}}" href="{{url('/leistungen')}}">Leistungen</a>
<a class="nav-item nav-link {{request()->is('aktuelles*') || request()->is('news*')?'active':''}}" href="{{url('/aktuelles')}}">Aktuelles</a>
@ -75,9 +74,9 @@

@if($_warenkorb_aktiv)
<li class="nav-item ms-md-5">
<a href="" data-bs-toggle="modal" data-bs-target="#shopping-cart" class="position-relative">
<a href="" data-bs-toggle="modal" data-bs-target="#shopping-cart" class="position-relative d-block">
<svg style="fill: {{$_primary_ci_color}}; width: 30px; margin-top: 6px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M352 128C352 57.42 294.579 0 224 0 153.42 0 96 57.42 96 128H0v304c0 44.183 35.817 80 80 80h288c44.183 0 80-35.817 80-80V128h-96zM224 48c44.112 0 80 35.888 80 80H144c0-44.112 35.888-80 80-80zm176 384c0 17.645-14.355 32-32 32H80c-17.645 0-32-14.355-32-32V176h48v40c0 13.255 10.745 24 24 24s24-10.745 24-24v-40h160v40c0 13.255 10.745 24 24 24s24-10.745 24-24v-40h48v256z"></path></svg>
<span class="position-absolute top-10 start-90 badge rounded-pill bg-danger js-product-counter" style="display: none; right: -10px;">0</span>
<span class="position-absolute badge rounded-pill bg-danger js-product-counter" style="display: none; bottom: -10px; right: -10px;">0</span>
</a>
</li>
@endif
@ -124,7 +123,7 @@
<a class="btn btn-primary mb-3" href="{{url('/produkte')}}">Jetzt Produkte entdecken</a>
<br>
</div>
<div class="col-12">
<div class="col-12" id="selected-products">
<table class="table table-striped">
<tbody id="list-products-in-bag"></tbody>
<tfoot>

View File

@ -163,7 +163,7 @@
<tr>
<th scope="col">Gesammt:</th>
<th colspan="2" class="text-end">
<span id="total-checkout-price">0 €</span>
<span class="js-total-price">0 €</span>
<br>
<small class="text-end fw-light">Preise inkl. 0% Umsatzsteuer</small>
</th>
@ -190,7 +190,7 @@
</div>

<div class="text-center mt-4">
<a href="" class="text-muted text-decoration-none text-center" data-bs-toggle="modal" data-bs-target="#shareCart">
<a href="" class="text-muted text-decoration-none text-center" data-bs-toggle="modal" data-bs-target="#share-cart">
Warenkorb teilen
<svg style="fill: currentColor; width: 19px; margin-left: 4px; margin-bottom: 4px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M564.907 196.35L388.91 12.366C364.216-13.45 320 3.746 320 40.016v88.154C154.548 130.155 0 160.103 0 331.19c0 94.98 55.84 150.231 89.13 174.571 24.233 17.722 58.021-4.992 49.68-34.51C100.937 336.887 165.575 321.972 320 320.16V408c0 36.239 44.19 53.494 68.91 27.65l175.998-184c14.79-15.47 14.79-39.83-.001-55.3zm-23.127 33.18l-176 184c-4.933 5.16-13.78 1.73-13.78-5.53V288c-171.396 0-295.313 9.707-243.98 191.7C72 453.36 32 405.59 32 331.19 32 171.18 194.886 160 352 160V40c0-7.262 8.851-10.69 13.78-5.53l176 184a7.978 7.978 0 0 1 0 11.06z"/></svg>
</a>
@ -204,5 +204,5 @@
@section('scripts')
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAKGJCCKvmWZl-L5bBF0uS5BWf0gN4ZkpI&v=3.exp&sensor=false&libraries=places"></script>
<script src="{{storage('libs/intl-tel-input/js/intlTelInput.min.js')}}"></script>
<script src="{{storage('js/checkout.js')}}"></script>
<script type="module" src="{{storage('js/checkout.js')}}"></script>
@stop

View File

@ -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 () {
}
});
});
});
});
*/

29
js/elements/product.js Normal file
View File

@ -0,0 +1,29 @@
import { numberToEuroFormat } from "../utils.js";

export function Product(data) {
return `
<tr>
<td class="text-start">
<img class="rounded img-fluid" style="height: 100px;" src="${data.image ?? data.default_image}">
</td>
<td class="text-start">
<span class="fs-5">
<a class="text-decoration-none" href="${data.path}">${data.title}</a>
</span>
<br>
<small class="text-success">sofort verfügbar</small>
<br>
<input type="number" min="1" max="100" class="form-control select-quantity" data-id="${data.id}" style="width:125px;" value="${data.quantity}">
<button data-id="${data.id}" class="btn-remove-product text-muted small text-decoration-none" style="padding: 0; border: none; background: transparen;">Löschen</button>
</td>
<td class="align-middle text-end product-price">
<span>${numberToEuroFormat(data.calc_preis)}</span>
<br>
<button class="${data.calc_preis == data.preis ? 'd-none' : ''}" style="font-size: 14px; padding: 0;" class="btn btn-link text-muted text-decoration-none" type="button" data-bs-toggle="collapse" data-bs-target="#collapseWidthExample" aria-expanded="false" aria-controls="collapseWidthExample">
<svg style="fill: currentColor; width: 15px; margin-right: 2px; margin-bottom: 2px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M349.66 173.65l-11.31-11.31c-3.12-3.12-8.19-3.12-11.31 0l-164.7 164.69c-3.12 3.12-3.12 8.19 0 11.31l11.31 11.31c3.12 3.12 8.19 3.12 11.31 0l164.69-164.69c3.13-3.12 3.13-8.18.01-11.31zM240 192c0-26.47-21.53-48-48-48s-48 21.53-48 48 21.53 48 48 48 48-21.53 48-48zm-64 0c0-8.83 7.19-16 16-16s16 7.17 16 16-7.19 16-16 16-16-7.17-16-16zm144 80c-26.47 0-48 21.53-48 48s21.53 48 48 48 48-21.53 48-48-21.53-48-48-48zm0 64c-8.81 0-16-7.17-16-16s7.19-16 16-16 16 7.17 16 16-7.19 16-16 16zm192-80c0-35.5-19.4-68.2-49.6-85.5 9.1-33.6-.3-70.4-25.4-95.5s-61.9-34.5-95.5-25.4C324.2 19.4 291.5 0 256 0s-68.2 19.4-85.5 49.6c-33.6-9.1-70.4.3-95.5 25.4s-34.5 61.9-25.4 95.5C19.4 187.8 0 220.5 0 256s19.4 68.2 49.6 85.5c-9.1 33.6.3 70.4 25.4 95.5 26.5 26.5 63.4 34.1 95.5 25.4 17.4 30.2 50 49.6 85.5 49.6s68.1-19.4 85.5-49.6c32.7 8.9 69.4.7 95.5-25.4 25.1-25.1 34.5-61.9 25.4-95.5 30.2-17.3 49.6-50 49.6-85.5zm-91.1 68.3c5.3 11.8 29.5 54.1-6.5 90.1-28.9 28.9-57.5 21.3-90.1 6.5C319.7 433 307 480 256 480c-52.1 0-64.7-49.5-68.3-59.1-32.6 14.8-61.3 22.2-90.1-6.5-36.8-36.7-10.9-80.5-6.5-90.1C79 319.7 32 307 32 256c0-52.1 49.5-64.7 59.1-68.3-5.3-11.8-29.5-54.1 6.5-90.1 36.8-36.9 80.8-10.7 90.1-6.5C192.3 79 205 32 256 32c52.1 0 64.7 49.5 68.3 59.1 11.8-5.3 54.1-29.5 90.1 6.5 36.8 36.7 10.9 80.5 6.5 90.1C433 192.3 480 205 480 256c0 52.1-49.5 64.7-59.1 68.3z"/></svg>
Mengenrabat
</button>
<span class="badge text-bg-dark">${(((data.calc_preis - data.preis) * 100) / data.preis).toFixed(2) + ' %'}</span>
</td>
</tr>`;
}

199
js/main.js Normal file
View File

@ -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 = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16">
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/>
<path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>
</svg>`;

let copiedIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M10.854 7.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 9.793l2.646-2.647a.5.5 0 0 1 .708 0z"/>
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/>
<path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>
</svg>`;

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 + `<svg style="fill: white; width: 12px; margin-left: 3px; margin-bottom: 2px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M352 128C352 57.42 294.579 0 224 0 153.42 0 96 57.42 96 128H0v304c0 44.183 35.817 80 80 80h288c44.183 0 80-35.817 80-80V128h-96zM224 48c44.112 0 80 35.888 80 80H144c0-44.112 35.888-80 80-80zm176 384c0 17.645-14.355 32-32 32H80c-17.645 0-32-14.355-32-32V176h48v40c0 13.255 10.745 24 24 24s24-10.745 24-24v-40h160v40c0 13.255 10.745 24 24 24s24-10.745 24-24v-40h48v256z"/></svg>`);
}
} */
}
});

/* 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 = `
<span>${numberToEuroFormat(product.calc_preis)}</span>`;
if (product.calc_preis != product.preis) elementPrice += `
<br>
<button style="font-size: 14px; padding: 0;" class="btn btn-link text-muted text-decoration-none" type="button" data-bs-toggle="collapse" data-bs-target="#collapseWidthExample" aria-expanded="false" aria-controls="collapseWidthExample">
<svg style="fill: currentColor; width: 15px; margin-right: 2px; margin-bottom: 2px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M349.66 173.65l-11.31-11.31c-3.12-3.12-8.19-3.12-11.31 0l-164.7 164.69c-3.12 3.12-3.12 8.19 0 11.31l11.31 11.31c3.12 3.12 8.19 3.12 11.31 0l164.69-164.69c3.13-3.12 3.13-8.18.01-11.31zM240 192c0-26.47-21.53-48-48-48s-48 21.53-48 48 21.53 48 48 48 48-21.53 48-48zm-64 0c0-8.83 7.19-16 16-16s16 7.17 16 16-7.19 16-16 16-16-7.17-16-16zm144 80c-26.47 0-48 21.53-48 48s21.53 48 48 48 48-21.53 48-48-21.53-48-48-48zm0 64c-8.81 0-16-7.17-16-16s7.19-16 16-16 16 7.17 16 16-7.19 16-16 16zm192-80c0-35.5-19.4-68.2-49.6-85.5 9.1-33.6-.3-70.4-25.4-95.5s-61.9-34.5-95.5-25.4C324.2 19.4 291.5 0 256 0s-68.2 19.4-85.5 49.6c-33.6-9.1-70.4.3-95.5 25.4s-34.5 61.9-25.4 95.5C19.4 187.8 0 220.5 0 256s19.4 68.2 49.6 85.5c-9.1 33.6.3 70.4 25.4 95.5 26.5 26.5 63.4 34.1 95.5 25.4 17.4 30.2 50 49.6 85.5 49.6s68.1-19.4 85.5-49.6c32.7 8.9 69.4.7 95.5-25.4 25.1-25.1 34.5-61.9 25.4-95.5 30.2-17.3 49.6-50 49.6-85.5zm-91.1 68.3c5.3 11.8 29.5 54.1-6.5 90.1-28.9 28.9-57.5 21.3-90.1 6.5C319.7 433 307 480 256 480c-52.1 0-64.7-49.5-68.3-59.1-32.6 14.8-61.3 22.2-90.1-6.5-36.8-36.7-10.9-80.5-6.5-90.1C79 319.7 32 307 32 256c0-52.1 49.5-64.7 59.1-68.3-5.3-11.8-29.5-54.1 6.5-90.1 36.8-36.9 80.8-10.7 90.1-6.5C192.3 79 205 32 256 32c52.1 0 64.7 49.5 68.3 59.1 11.8-5.3 54.1-29.5 90.1 6.5 36.8 36.7 10.9 80.5 6.5 90.1C433 192.3 480 205 480 256c0 52.1-49.5 64.7-59.1 68.3z"/></svg>
Mengenrabat
</button>
<span class="badge text-bg-dark">${(((product.calc_preis - product.preis) * 100) / product.preis).toFixed(2)} %</span>
`;
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 + `<svg style="fill: white; width: 12px; margin-left: 3px; margin-bottom: 2px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M352 128C352 57.42 294.579 0 224 0 153.42 0 96 57.42 96 128H0v304c0 44.183 35.817 80 80 80h288c44.183 0 80-35.817 80-80V128h-96zM224 48c44.112 0 80 35.888 80 80H144c0-44.112 35.888-80 80-80zm176 384c0 17.645-14.355 32-32 32H80c-17.645 0-32-14.355-32-32V176h48v40c0 13.255 10.745 24 24 24s24-10.745 24-24v-40h160v40c0 13.255 10.745 24 24 24s24-10.745 24-24v-40h48v256z"/></svg>`);
}
}
} ); * /

/* 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); }); */
});

97
js/modules/cart.js Normal file
View File

@ -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)));
}

View File

@ -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 + `<svg style="fill: white; width: 12px; margin-left: 3px; margin-bottom: 2px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M352 128C352 57.42 294.579 0 224 0 153.42 0 96 57.42 96 128H0v304c0 44.183 35.817 80 80 80h288c44.183 0 80-35.817 80-80V128h-96zM224 48c44.112 0 80 35.888 80 80H144c0-44.112 35.888-80 80-80zm176 384c0 17.645-14.355 32-32 32H80c-17.645 0-32-14.355-32-32V176h48v40c0 13.255 10.745 24 24 24s24-10.745 24-24v-40h160v40c0 13.255 10.745 24 24 24s24-10.745 24-24v-40h48v256z"/></svg>`);
}
}

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);
});
});

54
js/utils.js Normal file
View File

@ -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;
}