HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
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}