File: D:/HostingSpaces/blijegasten/blijegasten.be/resources/js/shop/components/shoppingcartController.js
import {ErrorResponse} from "../../global/models/errorResponse";
import {CheckoutInformationResponse} from "../../global/models/checkoutInformationResponse";
/**
* Shopping cart form controller.
*/
class ShoppingcartController {
/**
* @param {ShoppingcartService} shoppingcartService
*/
constructor(shoppingcartService) {
this.shoppingCartElement = document.querySelector('.js-cart');
if (!isset(this.shoppingCartElement)) {
return;
}
// ONLY FOR THE DEV BUTTONS
this._addToShoppingcartButtons = document.querySelectorAll('.js-add-product-to-shoppingcart');
this._removeFromShoppingcartButtons = this.shoppingCartElement.querySelectorAll('.js-remove-item-from-shoppingcart');
this.changeQuantityShoppingcartInputs = this.shoppingCartElement.querySelectorAll('.js-change-quantity-item');
this.addProduct = this.shoppingCartElement.querySelector('.js-add-product');
this.invoicePostalElement = this.shoppingCartElement.querySelector('.js-invoice-postal-code');
this.invoiceCountryElement = this.shoppingCartElement.querySelector('.js-invoice-city');
this._shoppingcartService = shoppingcartService;
if (!shoppingcartService) {
console.error('ShoppingCartController: The shoppingCartController was expected to get an instance of ShoppingcartService, but did not get one.');
return;
}
// if(isset(this.addProduct)) {
// this.addProductListener();
// }
this.addProductButtonClicked = this.addProductButtonClicked.bind(this);
this.removeProductButtonClicked = this.removeProductButtonClicked.bind(this);
this.quantityInputChanged = this.quantityInputChanged.bind(this);
this.getShippingCosts = this.getShippingCosts.bind(this);
this.handleKeyPressed = this.handleKeyPressed.bind(this);
this.toggleShippingBox();
this.controlListeners(true);
}
/**
* Enable or disable event listeners
*
* @param enable
*/
controlListeners(enable = true) {
const self = this;
window.addEventListener('keydown', this.handleKeyPressed);
const addToShoppingcartButtonsLength = this._addToShoppingcartButtons.length;
const removeFromShoppingcartButtonsLength = this._removeFromShoppingcartButtons.length;
const changeQuantityShoppingcartInputsLength = this.changeQuantityShoppingcartInputs.length;
for (let index = 0; index < addToShoppingcartButtonsLength; index++) this._addToShoppingcartButtons[index].removeEventListener('click', this.addProductButtonClicked);
for (let index = 0; index < removeFromShoppingcartButtonsLength; index++) this._removeFromShoppingcartButtons[index].removeEventListener('click', this.removeProductButtonClicked);
for (let index = 0; index < changeQuantityShoppingcartInputsLength; index++) this.changeQuantityShoppingcartInputs[index].removeEventListener('change', this.quantityInputChanged);
if (isset(this.invoicePostalElement)) this.invoicePostalElement.removeEventListener('keyup', this.getShippingCosts);
if (isset(this.invoiceCountryElement)) this.invoiceCountryElement.removeEventListener('change', this.getShippingCosts);
if (enable) {
for (let index = 0; index < addToShoppingcartButtonsLength; index++) this._addToShoppingcartButtons[index].addEventListener('click', this.addProductButtonClicked);
for (let index = 0; index < removeFromShoppingcartButtonsLength; index++) this._removeFromShoppingcartButtons[index].addEventListener('click', this.removeProductButtonClicked);
for (let index = 0; index < changeQuantityShoppingcartInputsLength; index++) this.changeQuantityShoppingcartInputs[index].addEventListener('change', this.quantityInputChanged);
if (isset(this.invoicePostalElement)) this.invoicePostalElement.addEventListener('keyup', this.getShippingCosts);
if (isset(this.invoiceCountryElement)) this.invoiceCountryElement.addEventListener('change', this.getShippingCosts);
}
}
/**
* Add Product listener for show page
* There the input value will determine the quantity.
*/
addProductListener() {
const self = this;
const product = this.addProduct;
const addProductButton = this.addProduct.querySelector('.js-add-product-button');
const productQuantityInput = this.addProduct.querySelector('.js-add-product-quantity');
addProductButton.addEventListener('click', function () {
const productId = product.dataset.productId;
const productType = product.dataset.productType;
self._shoppingcartService.validateProductQuantityInput(productQuantityInput);
self._shoppingcartService._addProductToShoppingcart(productId, productType, parseInt(productQuantityInput.value));
});
productQuantityInput.addEventListener('change', function () {
self._shoppingcartService.validateProductQuantityInput(productQuantityInput);
});
}
addProductButtonClicked(event) {
const button = event.currentTarget;
const productId = button.dataset.productId;
const productType = button.dataset.productType;
const productQuantity = button.dataset.productQuantity;
if(!isset(productId) || !isset(productType) || !isset(productQuantity) ) {
console.warn('AddProductButtonClicked: One of the required value is undefined');
return;
}
this._shoppingcartService._addProductToShoppingcart(productId, productType, productQuantity);
}
/**
* @param {MouseEvent} event
*/
async removeProductButtonClicked(event) {
const removeButton = event.currentTarget;
const shoppingcartItemId = removeButton.dataset.shoppingcartItemId;
if(!isset(shoppingcartItemId) ) {
console.warn('removeProductButtonClicked: Shopping cart id is undefined.');
return;
}
// if (!("productId" in removeButton.dataset)) {
// console.error('ShoppingCartController: Expected an add button to have the data-product-id attribute set. But did not have that. Not processing click', removeButton.dataset);
// return;
// }
// if (!("productType" in removeButton.dataset)) {
// console.error('ShoppingCartController: Expected an add button to have the data-type attribute set. But did not have that. Not processing click', removeButton.dataset);
// return;
// }
const shoppingCartItem = removeButton.parentElement.parentElement;
if(shoppingCartItem.classList.contains('js-shopping-cart-item')) {
await this._shoppingcartService._removeItemFromShoppingcart(shoppingcartItemId);
// await this._shoppingcartService._removeItemFromShoppingcart(removeButton.dataset.productId, removeButton.dataset.productType);
shoppingCartItem.remove();
// Update the rest of the shopping cart
this.updateShoppingCartAmounts();
}
else {
console.error("ShoppingCartController: Not the shopping cart item element is selected or it's missing the 'js-shopping-cart-item' hook.");
}
}
async quantityInputChanged(event) {
const input = event.currentTarget;
// const originalQuantity = parseInt(input.dataset.productQuantity);
const shoppingcartItemId = input.dataset.shoppingcartItemId;
if(!isset(shoppingcartItemId) ) {
console.warn('quantityInputChanged: Shopping cart id is undefined.');
return;
}
this._shoppingcartService.validateProductQuantityInput(input);
// Make sure that the change really is a different input
// if(originalQuantity === parseInt(input.value)) {
// console.warn('quantityInputChanged: Original quantity and the new one is the same. Therefor skip this method');
// return;
// }
const itemQuantity = parseInt(input.value);
if(itemQuantity === 0) {
// Grab the shopping cart by calling the parentElement
const shoppingCartItem = input.parentElement.parentElement;
await this._shoppingcartService._removeItemFromShoppingcart(shoppingcartItemId);
shoppingCartItem.remove();
}
else {
await this._shoppingcartService._setItemQuantityInShoppingcart(shoppingcartItemId, parseInt(input.value));
}
// Update the rest of the shopping cart
this.updateShoppingCartAmounts();
}
async getShippingCosts(event) {
const country = this.shoppingCartElement.querySelector('#invoice_country');
// if(isset(event) && event.currentTarget === country) {
// debugger;
// }
// else if (isset(event) && event.currentTarget === zipcode){
// debugger;
// }
if (isset(event) && event.currentTarget === this.invoicePostalElement){
// Convert zip value without space and uppercase
let zipValue = this.invoicePostalElement.value;
zipValue = zipValue.replace(/\s+/g, '');
zipValue = zipValue.toUpperCase();
this.invoicePostalElement.value = zipValue;
}
// if(zipcode.value.length <= 3) return;
// Get the postal response from shopping cart
const postalResponse = await this._shoppingcartService.getShippingCost(this.invoicePostalElement.value, this.invoiceCountryElement.value);
// Update the rest of the shopping cart
this.updateShoppingCartAmounts();
// Global shopping cart elements
const receiptTotalElement = this.shoppingCartElement.querySelector('.js-receipt-total');
const shoppingCartSubmit = this.shoppingCartElement.querySelector('.js-shopping-cart-submit');
// Zipcode search components
const foundLocationElement = this.shoppingCartElement.querySelector('.js-found-location');
const foundLocationSuccessLabel = this.shoppingCartElement.querySelector('.js-found-location-success-label');
const foundLocationErrorLabel = this.shoppingCartElement.querySelector('.js-found-location-error-label');
const foundLocationCity = this.shoppingCartElement.querySelector('#invoice_city');
const messageElement = this.shoppingCartElement.querySelector('.js-zipcode-message');
// Set to default value
foundLocationElement.hidden = false;
receiptTotalElement.hidden = false;
shoppingCartSubmit.hidden = false;
messageElement.classList.remove('c-delivery__address--success');
let shippingCost = null;
if(!isset(postalResponse.price)) {
// receiptTotalElement.hidden = true;
// shoppingCartSubmit.hidden = true;
}
if(postalResponse.status === 206 || postalResponse.status === 422) {
foundLocationSuccessLabel.hidden = true;
foundLocationErrorLabel.hidden = false;
messageElement.innerHTML = postalResponse.message;
foundLocationCity.value = '';
}
if(postalResponse.status === 200) {
foundLocationSuccessLabel.hidden = false;
foundLocationErrorLabel.hidden = true;
messageElement.classList.add('c-delivery__address--success');
messageElement.innerHTML = postalResponse.region_name + '<br/>' + postalResponse.zipcode + '<br/><strong>€' + number_format((postalResponse.price/100), 2, ',', '.') + '</strong>';
// zipcode.value = postalResponse.zipcode;
foundLocationCity.value = postalResponse.region_name;
// zipcode.blur();
}
}
async setToFreeShippingCosts() {
// Disable the hidden attributes
const receiptTotalElement = this.shoppingCartElement.querySelector('.js-receipt-total');
const shoppingCartSubmit = this.shoppingCartElement.querySelector('.js-shopping-cart-submit');
receiptTotalElement.hidden = false;
shoppingCartSubmit.hidden = false;
await this._shoppingcartService.setShippingCostToFree();
// Update the rest of the shopping cart
this.updateShoppingCartAmounts();
}
toggleShippingBox() {
const deliveryLocationToggles = this.shoppingCartElement.querySelectorAll('.js-delivery-location-toggle');
const self = this;
let currentDeliveryType;
for (let i = 0; i < deliveryLocationToggles.length; i++) {
const deliveryLocationToggle = deliveryLocationToggles[i];
if(deliveryLocationToggle.checked) currentDeliveryType = deliveryLocationToggle.value;
deliveryLocationToggle.addEventListener('change', function () {
self.setDeliveryLocation(this.value);
});
}
if(isset(currentDeliveryType)) {
this.setDeliveryLocation(currentDeliveryType);
}
}
setDeliveryLocation(deliveryType)
{
const deliveryLocation = this.shoppingCartElement.querySelector('.js-delivery-location');
if(deliveryType === 'ship') {
deliveryLocation.classList.remove('is-hidden');
this.getShippingCosts();
}
else {
deliveryLocation.classList.add('is-hidden');
this.setToFreeShippingCosts();
}
}
handleKeyPressed(event) {
switch (event.key) {
case 'Enter':
const targetedElement = event.target;
if(targetedElement.classList.contains('js-change-quantity-item')) {
event.preventDefault();
targetedElement.blur();
}
return;
// case 'Shift':
// this.updateShoppingCartAmounts();
// return;
default:
return;
}
}
async updateShoppingCartAmounts() {
const self = this;
const shoppingCartInfo = await this._shoppingcartService.getCurrentShoppingCart();
const shoppingCartProductTotal = this.shoppingCartElement.querySelector('.js-cart-product-total');
const shoppingCartReceiptSubtotal = this.shoppingCartElement.querySelector('.js-shoppingcart-subtotal');
const shoppingCartShippingCostCurrency = this.shoppingCartElement.querySelector('.js-shipping-cost-currency');
const shoppingCartShippingCost = this.shoppingCartElement.querySelector('.js-shipping-costs');
const shoppingCartTotal = this.shoppingCartElement.querySelector('.js-shoppingcart-total');
const shoppingCartVat = this.shoppingCartElement.querySelector('.js-vat');
const shoppingCartDeposit = this.shoppingCartElement.querySelector('.js-deposit');
const shoppingCartToPay = this.shoppingCartElement.querySelector('.js-shoppingcart-to-pay');
// Reload window when item count is zero
if(shoppingCartInfo.itemCount === 0) {
shoppingCartProductTotal.innerHTML = 0;
shoppingCartReceiptSubtotal.innerHTML = 0;
shoppingCartTotal.innerHTML = 0;
shoppingCartVat.innerHTML = 0;
shoppingCartDeposit.innerHTML = 0;
shoppingCartToPay.innerHTML = 0;
// Reload after a magic number
setTimeout(function () {
window.location.reload();
}, 2000);
return;
}
shoppingCartProductTotal.innerHTML = shoppingCartInfo.formated.productTotal;
shoppingCartReceiptSubtotal.innerHTML = shoppingCartInfo.formated.productTotal;
shoppingCartTotal.innerHTML = shoppingCartInfo.formated.cartTotal;
shoppingCartVat.innerHTML = shoppingCartInfo.formated.vat;
shoppingCartDeposit.innerHTML = shoppingCartInfo.formated.deposit;
shoppingCartToPay.innerHTML = shoppingCartInfo.formated.totalIncludingDeposit;
// Shipping cost can be free therefor 0 and null for when undefined
// When null there is a shipping_undefined
if(isset(shoppingCartInfo.shipping_undefined)) {
shoppingCartShippingCost.innerHTML = shoppingCartInfo.shipping_undefined;
shoppingCartShippingCostCurrency.hidden = true;
}
else {
shoppingCartShippingCost.innerHTML = shoppingCartInfo.formated.shippingCost;
shoppingCartShippingCostCurrency.hidden = !shoppingCartInfo.useShipping;
}
// Loop through the items
shoppingCartInfo.items.forEach(function(item){
const shoppingCartItem = self.shoppingCartElement.querySelector('.js-shopping-cart-item[data-id="' + item.id + '"]');
// Warn if the item isn't found, shouldn't happend...
if(!isset(shoppingCartItem)) console.warn('updateCartInformation: Shopping Cart Item not found within the cart for id: "' + item.id + '".');
// Update the total of the item
const shoppingCartItemTotal = shoppingCartItem.querySelector('.js-shopping-cart-item-amount');
shoppingCartItemTotal.innerHTML = item.formatted;
});
// Update the shopping cart amount buttons
this._shoppingcartService.updateShoppingCartCounters(shoppingCartInfo.itemCount);
}
}
export {ShoppingcartController}