var miniCart = {
jsonCart: null,
idCart: null,
component: document.querySelector(".store-minicart-component"),
currency : '€',
errorCodes: {
'noError' : 'NO_ERROR',
'noStockUnits': 'NO_STOCK_UNITS',
'fewStockUnits': 'FEW_STOCK_UNITS',
'cartOutdated' : 'CART_OUTDATED',
'cartInactive' : 'CART_INACTIVE',
'customerTokenOutdated' : 'CUSTOMER_TOKEN_OUTDATED',
'updatedProductStockError' : 'UPDATED_PRODUCT_STOCK_ERROR',
'shippingAddressNotSelected' : 'SHIPPING_ADDRESS_NOT_SELECTED',
'placeOrderError' : 'PLACE_ORDER_ERROR',
'unhandledError' : 'UNHANDLED_ERROR',
},
scrollToTop: false,
init: function () {
miniCart.setPosition();
miniCart.checkLocalStorageCart();
miniCart.events();
miniCart.resetStoreCookie();
},
setPosition: () =>{
let component = miniCart.component;
let headerMiniCart = component.closest(".header-es").querySeleor(".header-store .minicart");
if(headerMiniCart && component){
headerMiniCart.after(component);
}
},
events: function () {
let component = miniCart.component;
document.querySelector(".header .header-store .minicart").addEventListener("click", (e) =>{
let target = e.target;
if (window.matchMedia("(min-width: 1024px)").matches) {
miniCart.redirectToCart()
}else{
if(component.classList.contains("minicart-products")){
miniCart.redirectToCart()
}else{
if(component.classList.contains("show")){
miniCart.hideCart();
}else{
miniCart.showCart();
}
}
}
})
document.addEventListener("click", (e) =>{
let target = e.target;
if(!target.closest(".header-store")){
if(component.classList.contains("show")){
miniCart.hideCart();
}
}
})
let openCart = false;
document.querySelector(".header .header-store .minicart").addEventListener("mouseover", (e) =>{
if (window.matchMedia("(min-width: 1024px)").matches) {
let target = e.target;
if(!openCart){
miniCart.showCart();
openCart = true;
}
}
})
document.querySelector(".header .header-store").addEventListener("mouseleave", (e) =>{
let target = e.target;
if(!target.closest(".store-minicart-component")){
miniCart.hideCart();
openCart = false;
}
})
component.querySelector(".minicart-header .rp-close").addEventListener("click", (e) =>{
e.stopImmediatePropagation();
let target = e.target;
miniCart.hideCart();
Repsol.Analytics.Store.clickCartClose($(target))
})
component.querySelector(".js-show-login").addEventListener("click", (e) =>{
e.preventDefault();
miniCart.hideCart();
RepsolRegisterLoginModal.showModal();
RepsolLoginStore.open();
})
},
showCart: async function () {
let component = miniCart.component;
component.classList.add("show");
document.querySelector("body").classList.add("minicart-open");
if(component.classList.contains("minicart-products")){
miniCart.checkScrollProductsList()
}
RepsolHeaderMenu.hideUserDropdowns();
},
hideCart: function () {
let component = miniCart.component;
component.classList.remove("show");
document.querySelector("body").classList.remove("minicart-open");
},
checkLocalStorageCart: async function() {
const activeCart = localStorage.getItem("activeCart");
if(activeCart === 'true'){
let component = miniCart.component;
const storageCartId = window.localStorage?.cartId;
const cartId = storageCartId ? JSON.parse(storageCartId)?.id : undefined;
if(cartId) {
Repsol.utils.setLoader(true, $(component))
let cartResponse, cart
cartResponse = await RepsolStore.getCartOverlay();
const errors = cartResponse?.errors;
if(errors) {
await miniCart.handleMiniCartErrors(errors);
cartResponse = await RepsolStore.getCartOverlay();
}
cart = cartResponse?.data?.cart;
RepsolStore.saveCartToLocalStorage(cart);
miniCart.loadProductsToMiniCart();
Repsol.utils.setLoader(false, $(component))
} else {
miniCart.createEmptyCart();
}
}else{
miniCart.emptyCart();
}
},
showWayletMessage: () => {
let component = miniCart.component;
let total = component.querySelector('.grand_total')?.getAttribute('data-price')
let currency = miniCart.currency;
let percentageNotLogged = component.getAttribute('data-percentage-not-logged');
let percentageLoggedNotWaylet = component.getAttribute('data-percentage-logged-not-waylet');
let percentageLoggedNotWaylet2 = component.getAttribute('data-percentage-2-logged-not-waylet');
let data = {
'total' : total,
'currency': currency,
'percentageNotLogged': percentageNotLogged,
'percentageLoggedNotWaylet' : percentageLoggedNotWaylet,
'percentageLoggedNotWaylet2' : percentageLoggedNotWaylet2
}
RepsolConecta.showWayletMessage($(component), data);
},
handleMiniCartErrors: async function(errors) {
const error = RepsolStoreErrors.checkHandledErrorType(errors)
const errorCodes = miniCart.errorCodes
if(error === errorCodes.cartOutdated) {
await RepsolStore.handleOutdatedCart();
}
if(error === errorCodes.cartInactive) {
miniCart.createEmptyCart();
}
if(error === errorCodes.customerTokenOutdated) {
await RepsolStore.loginUserOnMagento();
await RepsolStore.restoreUserCart();
}
if (error === errorCodes.updatedProductStockError) {
miniCart.showProductFewStockError(errors);
}
if(error === errorCodes.shippingAddressNotSelected) {
const errorMesage = 'Selecciona una direccion de envio antes de tramitar el pedido';
}
if(error === errorCodes.placeOrderError) {
miniCart.showUnhandledErrorMessage();
}
if(error === errorCodes.unhandledError) {
miniCart.showUnhandledErrorMessage();
}
},
showUnhandledErrorMessage: function() {
let component = miniCart.component;
const errorMessage = component.getAttribute('data-unhandled-error-msg')
RpAlert.msgError(errorMessage)
Repsol.Analytics.Store.errorRpAlert(errorMessage);
var myObj = $('.store-minicart-component');
var params = {
error_type: errorMessage,
error_description: errorMessage,
};
Repsol.AnalyticsRomProd.errorRomProd(myObj, params);
},
loginUserOnMagento: async function() {
const magentoLoginResponse = await RepsolLoginStore.magentoLogin();
const errorCode = magentoLoginResponse?.errorCode;
if (errorCode === 0) {
const customerToken = magentoLoginResponse?.customerToken;
localStorage.setItem("ct", JSON.stringify(customerToken));
}
},
createEmptyCart: async function() {
try {
await RepsolStore.createNewCart();
miniCart.updateCart();
} catch(error) {
RepsolStore.showUnhandledErrorMessage();
}
},
createCart: function () {
var settings = {
"url": "/api/graphql" + RepsolGraphql.generateQueryParamRequest(),
"method": "POST",
"timeout": 5000,
"headers": { "content-type": "application/json" },
"data": JSON.stringify({
query: `mutation {
createEmptyCart
}`
}),
"success": function (data, textStatus, request) {
},
"error": function (request, textStatus, errorThrown) {
}
}
$.ajax(settings).done(function (response) {
if (response.errors && response.errors.length > 0) {
console.log("error al crear carrito")
} else {
let date = new Date();
date.setDate(date.getDate() + 1);
localStorage.setItem("cartId", `{"id": "${response.data.createEmptyCart}", "expDate":${date.getTime()}}`)
miniCart.idCart = response.data.createEmptyCart;
miniCart.updateCart();
}
}).fail(function (jqXHR, textStatus, errorThrown) {
console.log('Error:', errorThrown);
});
},
newUserCart: function () {
let url = "/bin/repsol-ecommerce/store/cart";
let token = miniCart.getLocalData("ct");
let data = {
"operation": "getCustomerCart",
"token": token
}
localStorage.setItem("cart", "");
localStorage.setItem("cartId", "");
RepsolLoginStore.isLoggedMagento()
.then(resp => {
let xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
if (this.status == 200) {
let response = JSON.parse(this.responseText);
if (response.errorCode == 0) {
let date = new Date();
date.setDate(date.getDate() + 1);
localStorage.setItem("cartId", `{"id": "${response.magentoResponse.magentoCartId}", "expDate":${date.getTime()}}`)
miniCart.idCart = response.magentoResponse.magentoCartId;
miniCart.loadProducts();
} else {
}
} else {
console.log("servlet error: " + this.responseText)
}
}
miniCart.updateCart();
});
xhr.open("POST", url);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(data));
}).catch(err => {
console.log(err)
})
},
updateCart: function (event) {
let url = "/bin/repsol-ecommerce/store/cart";
let data = {
"operation": "update",
"cartId": miniCart.idCart,
"token": miniCart.getLocalData("ct") || null
};
var cart = miniCart.getLocalData("cart");
var jsonCart = "";
var products = ""
var status = true;
if (!event && cart && cart != "" && (cart != "undefined" || cart != undefined)) {
if (cart.cart && cart.cart != "") {
jsonCart = cart.cart;
} else {
jsonCart = cart
}
products = jsonCart.items ? jsonCart.items : "";
miniCart.updateCartFn(jsonCart, products);
} else {
RepsolLoginStore.isLoggedMagento().then(resp => {
let xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
if (this.status == 200) {
let response = JSON.parse(this.responseText);
if (response.errorCode == 0) {
jsonCart = response.magentoResponse;
products = response.magentoResponse.cart.items;
miniCart.updateCartFn(jsonCart, products);
miniCart.setStorageProducts(products)
if(sessionStorage.getItem('products') == 0) {
miniCart.redirectCheckoutWithoutProducts()
}
} else {
status = false;
console.log("servlet error: " + response.errorCode)
}
} else {
status = false;
console.log("servlet error: " + this.responseText)
}
}
});
xhr.open("POST", url);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(data));
}).catch(error => {
var settings = {
"url": "/api/graphql" + RepsolGraphql.generateQueryParamRequest(),
"method": "POST",
"timeout": 5000,
"headers": { "content-type": "application/json" },
"data": JSON.stringify({
query: `{
cart(cart_id: "${miniCart.idCart}") {
items {
id
uid
product {
stock_status
name
sku
salable_quantity
thumbnail{
url
}
price_range {
minimum_price {
final_price {
value
currency
}
}
}
... on SimpleProduct{
capacidad_label
talla_label
}
}
quantity
errors {
code
message
}
}
prices {
grand_total {
value
currency
}
}
}
}`
}),
"success": function (data, textStatus, request) {
},
"error": function (request, textStatus, errorThrown) {
}
}
$.ajax(settings).done(function (response) {
jsonCart = response.data;
if (response.errors) {
miniCart.createCart();
localStorage.removeItem("cart");
} else {
if (response.data && response.data.cart && response.data.cart.items) {
products = response.data.cart.items;
}
miniCart.updateCartFn(jsonCart, products);
}
}).fail(function (jqXHR, textStatus, errorThrown) {
console.log('Error:', errorThrown);
});
});
}
},
updateCartFn: function (jsonCart, products) {
if (jsonCart.errors && response.errors.length > 0) {
for (i = 0; i < products.length; i++) {
if (products[i] == null) {
products.splice(i, 1);
}
}
if (products.length) {
localStorage.setItem("cart", JSON.stringify(cart));
miniCart.loadProducts();
}
} else if ((!!jsonCart && jsonCart.cart) || (!!jsonCart && jsonCart.items)) {
localStorage.setItem("cart", JSON.stringify(jsonCart));
if (products.length > 0) {
miniCart.loadProducts();
} else {
miniCart.emptyCart();
miniCart.checkSummaryCount()
}
} else {
miniCart.emptyCart();
}
},
checkSummaryCount: function () {
let component = miniCart.component;
const $emptyMiniCart = component.querySelector(".minicart-empty");
const items = component.querySelectorAll('.minicart-product')
let productCount = []
if($emptyMiniCart.classList.contains('d-none') && items.length > 0){
items.forEach((item) => {
const productQty = parseInt(item.getAttribute("data-quantity"))
productCount.push(productQty)
})
const productTotal = productCount.reduce((a, b) => a + b, 0)
if (productTotal > 0) {
document.querySelector(".header .js-summary").innerText = productTotal;
document.querySelector(".header .js-summary").classList.remove("d-none")
}else{
document.querySelector(".header .js-summary").classList.add("d-none")
}
} else {
document.querySelector(".header .js-summary").classList.add("d-none")
miniCart.emptyCart();
}
},
loadProducts: function () {
let jsonCart = miniCart.getLocalData("cart");
let items = [];
if (jsonCart && jsonCart != "") {
if (jsonCart.items && jsonCart.items != "") {
items = jsonCart.items;
} else if (jsonCart.cart && jsonCart.cart != "") {
items = jsonCart.cart.items ? jsonCart.cart.items : [];
}
if (items.length > 0) {
miniCart.printProducts(items);
miniCart.printTotalPrices(jsonCart);
miniCart.showWayletMessage();
miniCart.checkSummaryCount();
miniCart.showStockErrorMessage()
miniCart.updateButtonsStatus();
}
}
},
printProducts: (items) => {
let component = miniCart.component;
let miniCartProducts = component.querySelector(".minicart-products");
let miniCartProductsList = miniCartProducts.querySelector(".minicart-products-list");
miniCartProductsList.innerHTML = "";
let sizeText = component.getAttribute("data-size-text")
let capacityText = component.getAttribute("data-capacity-text")
let quantityText = component.getAttribute("data-quantity-text")
const currency = miniCart.currency;
let fragment = document.createDocumentFragment()
const template = component.querySelector('#template-minicart-product').content
for (let i = 0; i < items.length; i++) {
let cloneTemplate = template.cloneNode(true)
let item = items[i];
const productId = item.id;
const productUid = item.uid;
const productSku = item.product.sku;
const productParentSku = item.product.parent_sku ? item.product.parent_sku[0] : '';
const productH1 = item.product.h1_label;
const productNameCart = item.name;
const productName = item.product.name;
const itemName = productNameCart ? productNameCart : (productH1 ? productH1 : productName);
const productImageAlt = productName;
const damImageURL = RepsolStore.generateDAMImageURL(items[i]);
const productImage = imgSrc = damImageURL ?? item.product?.thumbnail?.url;
const productPrice = item?.product?.price_range?.minimum_price?.final_price?.value ?? 0;
let productPriceRegular = item?.product?.price_range?.minimum_price?.regular_price?.value != productPrice ? item?.product?.price_range?.minimum_price?.regular_price?.value : '';
const reservationPriceItem = item.product?.reservation_price ? item.product.reservation_price : 0;
const analyticsPriceToShow = reservationPriceItem ? reservationPriceItem : (productPriceRegular ? productPriceRegular : productPrice);
const productQty = item.quantity ?? 0;
const productVariant = RepsolStore.getVariant(item);
const productCapacity = item.product?.capacidad_label;
const productSize = item.product?.talla_label;
const productTotal = item.prices?.row_total_including_tax?.value.toFixed(2).replace('.', ',') ?? 0
const productStock = item.product?.stock_status;
const productSalableQuantity = (item.product?.salable_quantity && item.product?.salable_quantity >= 0) ? item.product.salable_quantity : 0;
const productDescription = item.product?.short_description ? RepsolEcommerce.utils.removeHTMLTags(item?.product?.short_description.html) : "";
const productDiscount = item?.product?.price_range?.minimum_price?.discount?.amount_off.toFixed(2) ?? 0;
const productCategories = item?.product?.category_ids ?? [];
const categoriesList = Repsol.Analytics.Store.getProductCategories(productCategories);
const productBrand = item.product?.manufacturer_label ? item.product?.manufacturer_label : "";
const productIndex = Repsol.Analytics.Store.getProductDataStorage('index', productSku);
const productListName = Repsol.Analytics.Store.getProductDataStorage('item_list_name', productSku);
//Bundle options
const bundleOptions = item.bundle_options ? item.bundle_options : [];
const bundleItems = item.product?.items ? item.product?.items : [];
const error = item.errors ? true : false;
let errorType = '';
const errorCodes = miniCart.errorCodes;
let bundleOptionStockError = false;
cloneTemplate.querySelector('.minicart-product').dataset.magentoId = productId
cloneTemplate.querySelector('.minicart-product').dataset.id = productUid
cloneTemplate.querySelector('.minicart-product').dataset.sku = productSku
cloneTemplate.querySelector('.minicart-product').dataset.stock = productStock
cloneTemplate.querySelector('.minicart-product').dataset.salableQuantity = productSalableQuantity
cloneTemplate.querySelector('.minicart-product').dataset.listIndex = productIndex ? productIndex - 1 : ""
cloneTemplate.querySelector('.minicart-product').dataset.quantity = productQty
cloneTemplate.querySelector('.minicart-product').dataset.error = error
cloneTemplate.querySelector('.product-image img').src = productImage
cloneTemplate.querySelector('.product-image img').alt = productImageAlt
cloneTemplate.querySelector('.product-description-name').textContent = itemName
// Display product capacity label
if (productCapacity && productCapacity.length > 0) {
cloneTemplate.querySelector('.product-description-size').textContent = `${capacityText} ${productCapacity}`
cloneTemplate.querySelector('.product-description-size').classList.remove('d-none');
} else if (productSize && productSize.length > 0) {
cloneTemplate.querySelector('.product-description-size').textContent = `${sizeText} ${productSize}`
cloneTemplate.querySelector('.product-description-size').classList.remove('d-none');
} else {
cloneTemplate.querySelector('.product-description-size').textContent = ''
cloneTemplate.querySelector('.product-description-size').classList.add('d-none');
}
cloneTemplate.querySelector('.product-description-quantity').textContent = `${quantityText} ${productQty}`
cloneTemplate.querySelector('.product-description-price').textContent = `${productTotal} ${currency}`
if(productPriceRegular){
let finalProductPriceRegular = productPriceRegular;
if (productQty > 1) {
finalProductPriceRegular = (productPriceRegular * productQty);
}
finalProductPriceRegular = finalProductPriceRegular.toFixed(2).replace('.', ',')
cloneTemplate.querySelector('.product-description-secondary-price').textContent = `${finalProductPriceRegular} ${currency}`
cloneTemplate.querySelector('.product-description-secondary-price').classList.remove("d-none")
}else{
cloneTemplate.querySelector('.product-description-secondary-price').textContent = ""
cloneTemplate.querySelector('.product-description-secondary-price').classList.add("d-none")
}
//Analytics
cloneTemplate.querySelector('.js-analytics-store-product').dataset.id = productParentSku ? productParentSku : productSku
cloneTemplate.querySelector('.js-analytics-store-product').dataset.name = itemName
cloneTemplate.querySelector('.js-analytics-store-product').dataset.price = analyticsPriceToShow
cloneTemplate.querySelector('.js-analytics-store-product').dataset.quantity = productQty
cloneTemplate.querySelector('.js-analytics-store-product').dataset.category = categoriesList
cloneTemplate.querySelector('.js-analytics-store-product').dataset.brand = productBrand
cloneTemplate.querySelector('.js-analytics-store-product').dataset.variant = productVariant
cloneTemplate.querySelector('.js-analytics-store-product').dataset.image = productImage
cloneTemplate.querySelector('.js-analytics-store-product').dataset.discount = productDiscount
cloneTemplate.querySelector('.js-analytics-store-product').dataset.description = productDescription
cloneTemplate.querySelector('.js-analytics-store-product').dataset.salableQuantity = productSalableQuantity
cloneTemplate.querySelector('.js-analytics-store-product').dataset.sku = productSku
cloneTemplate.querySelector('.js-analytics-store-product').dataset.listName = productListName
//Bundle options
if(bundleOptions.length > 0){
let bundleLabelOptions = [];
bundleOptions.forEach((option) =>{
let valueOption = option.values && option.values.length > 0 ? option.values[0] : {};
let uidOption = valueOption.uid ? valueOption.uid : "";
let labelOption = valueOption.label ? valueOption.label : "";
if (uidOption) {
let found = false;
bundleLabelOptions.push(labelOption);
bundleItems.forEach((item) =>{
let optionsItem = item.options ? item.options : [];
optionsItem.forEach((option) => {
if(uidOption == option.uid){
found = true;
}
});
})
//Bundle option out of stock
if(error && !found){
bundleOptionStockError = true;
}
}
})
if(bundleLabelOptions.length > 0){
let itemHtml = "";
bundleLabelOptions.forEach((label) =>{
itemHtml += `
${label}`;
})
cloneTemplate.querySelector('.product-description-bundle-options').innerHTML = itemHtml;
cloneTemplate.querySelector('.product-description-bundle-options').classList.remove("d-none")
}
}
if(error && (productStock === 'OUT_OF_STOCK' || bundleOptionStockError)) {
errorType = errorCodes.noStockUnits
} else if(error && productStock === 'IN_STOCK') {
errorType = errorCodes.fewStockUnits
} else {
errorType = errorCodes.noError
}
cloneTemplate.querySelector('.minicart-product').dataset.errorCode = errorType
fragment.appendChild(cloneTemplate)
miniCartProductsList.appendChild(fragment);
}
miniCartProducts.classList.remove("d-none")
miniCart.removeEmptyCartBlock();
component.classList.add("minicart-products")
},
printTotalPrices: (cart) => {
let component = miniCart.component;
let currency = miniCart.currency;
cart = cart.cart ? cart.cart : cart;
const items = cart.items;
const prices = cart.prices ? cart.prices : '';
const totalPrice = prices.grand_total.value ? prices.grand_total.value.toFixed(2) : 0;
const coupon = cart?.applied_coupons ? cart?.applied_coupons[0]?.code : undefined
const appliedCouponText = component.getAttribute('data-coupon-label-text') ? component.getAttribute('data-coupon-label-text').trim() : '';
const giftCard = cart.applied_gift_cards ? cart.applied_gift_cards[0] : undefined;
const appliedGiftCardText = component.getAttribute('data-gift-card-label-text');
let appliedDiscountText = '';
let grandTotalElem = component.querySelector(".grand_total");
let grandTotalSecondaryElem = component.querySelector(".grand_total_secondary");
let discountCouponElem = component.querySelector(".minicart-footer-discount-coupon");
grandTotalElem.innerText = `${totalPrice} ${currency}`
grandTotalElem.setAttribute("data-price", totalPrice)
let totalPriceSecondary = 0;
for (const item of items) {
let productQty = item.quantity ? item.quantity : 1;
let productPrice = item?.product?.price_range?.minimum_price?.final_price?.value.toFixed(2) ?? 0
let productPriceRegular = item?.product?.price_range?.minimum_price?.regular_price?.value.toFixed(2) != productPrice ? item?.product?.price_range?.minimum_price?.regular_price?.value.toFixed(2) : 0;
const reservationPrice = item?.product?.reservation_price ? item.product.reservation_price : 0;
if(reservationPrice > 0){
totalPriceSecondary+= parseFloat(reservationPrice) * productQty
}else if(productPriceRegular){
totalPriceSecondary+= parseFloat(productPriceRegular) * productQty
}else{
totalPriceSecondary+= parseFloat(productPrice) * productQty
}
}
totalPriceSecondary = totalPriceSecondary.toFixed(2)
if(totalPriceSecondary != totalPrice){
grandTotalSecondaryElem.innerText = `${totalPriceSecondary} ${currency}`
grandTotalSecondaryElem.classList.remove("d-none")
}else{
grandTotalSecondaryElem.innerText = ''
grandTotalSecondaryElem.classList.add("d-none")
}
// const totalNum = prices.grand_total.value;
// Display cost-shipping-progress
const totalNum = prices.subtotal_including_tax?.value;
const dataList = miniCart.component.dataset.constants ? JSON.parse(miniCart.component.dataset.constants) : '';
const manualCostMinFreeShipping = miniCart.component.dataset.freeshipping ? JSON.parse(miniCart.component.dataset.freeshipping) : '';
let costMinFreeShipping = dataList && dataList.coste_min_envio ? dataList.coste_min_envio : '';
if (manualCostMinFreeShipping && manualCostMinFreeShipping != ''){
costMinFreeShipping = manualCostMinFreeShipping;
}
// console.log('Envio gratis a partir de' + costMinFreeShipping);
if(totalNum){
const progress = Math.min(1, totalNum / costMinFreeShipping);
const remaining = totalNum < costMinFreeShipping ? costMinFreeShipping - totalNum : 0;
const barProgress = miniCart.component.querySelector('.bar-progress');
const shippingText = miniCart.component.querySelector('.cost-shipping-title');
if (totalNum >= costMinFreeShipping) {
barProgress.style.width = `100%`;
shippingText.innerHTML = `¡Envío gratis!`;
} else {
barProgress.style.width = `${progress * 100}%`;
const remainingText = `Faltan ${remaining.toFixed(2).replace('.', ',')} € para el `;
shippingText.innerHTML = `${remainingText}envío gratis!`;
}
}else{
component.querySelector('.cart-cost-shipping').classList.add('d-none');
}
const discounts = prices?.discounts ?? [];
let discountsArray = []
let discountLabel
let discountLabelLower
let discountValue
let discountPercent
let numberFind
if (discounts && discounts.length > 0) {
discountPercent = discounts[0]?.label;
var match = discountPercent.match(/\d+/);
if (match) {
numberFind = parseInt(match[0], 10);
}
discounts.map(discount => discountsArray.push(discount?.label))
discountLabelLower = discountsArray.join(' - ')
discountLabel = discountLabelLower.toUpperCase()
discountValue = discounts.reduce((sum, discount) => sum + discount?.amount?.value, 0).toFixed(2)
appliedDiscountText = appliedCouponText.replace("{0}", discountLabelLower);;
}
if(giftCard){
const gifCardValue = giftCard.applied_balance?.value;
const gifCardCode = giftCard.code;
const giftCardType = currency;
appliedDiscountText = appliedGiftCardText.replace("{0}", `${gifCardValue}${giftCardType}`);
}
if((discounts && discounts.length > 0) || giftCard){
discountCouponElem.querySelector('.amount-title').textContent = appliedDiscountText;
discountCouponElem.classList.remove('d-none')
}
else{
discountCouponElem.classList.add('d-none');
discountCouponElem.querySelector('.amount-title').textContent = "";
}
miniCart.replacePriceDotForComma(component)
},
updateButtonsStatus: () =>{
let component = miniCart.component;
let storeBtn = component.querySelector(".cart-btn-store");
let isStorePage = miniCart.isStorePage()
if(isStorePage){
storeBtn.classList.add("d-none")
}else{
storeBtn.classList.remove("d-none")
}
},
emptyCart: function () {
let component = miniCart.component;
let isStorePage = miniCart.isStorePage()
let isLogged = Repsol.utils.getCookie("isLogged");
component.querySelector(".minicart-description").classList.add("d-none");
if (isLogged === "true") {
component.querySelector(".minicart-empty .js-show-login").classList.add("d-none");
if(isStorePage){
component.querySelector(".minicart-empty .js-show-news").classList.remove("d-none");
component.querySelector(".minicart-description-logged-store-pages").classList.remove("d-none");
}else{
component.querySelector(".minicart-empty .js-show-go-to-store").classList.remove("d-none");
component.querySelector(".minicart-description-logged").classList.remove("d-none");
}
}else{
component.querySelector(".minicart-empty .js-show-login").classList.remove("d-none");
if (isStorePage) {
component.querySelector(".minicart-empty .js-show-news").classList.remove("d-none");
component.querySelector(".minicart-description-unlogged-store-pages")?.classList.remove("d-none");
} else {
component.querySelector(".minicart-empty .js-show-go-to-store").classList.remove("d-none");
component.querySelector(".minicart-description-unlogged")?.classList.remove("d-none");
}
}
component.querySelector(".minicart-empty").classList.remove("d-none");
component.querySelector(".minicart-products").classList.add("d-none");
component.classList.remove("minicart-products")
},
removeEmptyCartBlock: function () {
let component = miniCart.component;
component.querySelector('.minicart-empty').classList.add('d-none');
},
replacePriceDotForComma: (obj) => {
obj.querySelectorAll('.js-format-price').forEach( (item) => {
let itemPrice = item.innerText.replace('.', ',')
item.innerText = itemPrice
})
},
getLocalData: function (nameSesion) {
data = window.localStorage.getItem(nameSesion);
try {
return JSON.parse(data);
} catch (e) {
return data;
}
},
setStorageProducts: function(data) {
let locationPath = window.location.href
let checkout = locationPath.includes('tienda/checkout') ? true : false
let productsLength = data.length
if(checkout && productsLength == 0) {
sessionStorage.setItem('products', 0)
}
},
redirectCheckoutWithoutProducts: function() {
let locationPath = window.location.href
let checkout = locationPath.includes('tienda/checkout') ? true : false
let productsLength = sessionStorage.getItem('products')
let pathOrigin = window.location.origin
if(checkout && productsLength == 0) {
sessionStorage.removeItem('products')
window.location.href = `${pathOrigin}/tienda/carrito`
}
},
addProductAnalytics: function() {
let component = miniCart.component;
let sku = document.querySelector(".product-detail-component .product-detail-card")?.getAttribute("data-product-sku");
let analyticProduct = component.querySelector(`.js-analytics-store-product[data-sku='${sku}']`);
if (analyticProduct) {
const cartProduct = analyticProduct.closest(".minicart-product");
cartProduct.setAttribute("data-event", Repsol.Analytics.Store.event.addToCart);
//Analytics
Repsol.Analytics.Store.getProductsDataLayer(Repsol.Analytics.Store.event.addToCart, $(cartProduct));
cartProduct.removeAttribute("data-event");
}
},
isSelectedOption: (productId) =>{
let isSelectedOption = false;
let bundleSelectors = document.querySelectorAll(".product-detail-component .product-detail__dropdown.is-checked");
bundleSelectors.forEach((selector) => {
let uid = selector.getAttribute("data-uid");
if(productId == uid){
isSelectedOption = true;
}
})
return isSelectedOption;
},
addProduct: async function() {
let component = miniCart.component;
let productDetailComponent = document.querySelector(".product-detail-component");
let addCartBtn = productDetailComponent?.querySelector(".product-detail__cart-actions .button-repsol");
try {
Repsol.utils.setLoader(true, $(productDetailComponent))
let item = productDetailComponent.querySelector(".product-detail-card").getAttribute("data-product-sku")
let qty = 1
let productJson = document.querySelector('.product-json') && document.querySelector('.product-json').getAttribute('data-product') ? JSON.parse(document.querySelector('.product-json').getAttribute('data-product')) : ''
let productType = productJson.__typename ? productJson.__typename : ''
let bundleOptions = [];
let selectOption = $(".product-detail__dropdown.is-checked").attr("data-uid");
if(productType == 'BundleProduct'){
let itemsBundle = productJson.items && productJson.items.length > 0 ? productJson.items : [];
itemsBundle.forEach((item) => {
let optionsItem = item.options ? item.options : []
optionsItem.forEach((option) => {
if (optionsItem.length > 1) {
if(miniCart.isSelectedOption(option.uid)){
bundleOptions.push(option.uid)
}
} else if (optionsItem.length == 1) {
bundleOptions.push(option.uid);
}
});
})
}
const cartId = localStorage?.cartId ? JSON.parse(localStorage.getItem('cartId'))?.id : undefined;
if(!cartId){
await miniCart.createEmptyCart();
}
let addProductToCartResponse, cart
addProductToCartResponse = await RepsolStore.addProductsToCart(qty, item, bundleOptions)
const errors = addProductToCartResponse?.errors
if(errors) {
await miniCart.handleMiniCartErrors(errors)
addProductToCartResponse = await RepsolStore.addProductsToCart(qty, item)
}
cart = addProductToCartResponse?.data?.addProductsToCart?.cart
RepsolStore.saveCartToLocalStorage(cart)
miniCart.displayProductOnCart(addProductToCartResponse)
localStorage.setItem("activeCart", true);
} catch(error) {
miniCart.showUnhandledErrorMessage();
} finally {
Repsol.utils.setLoader(false, $(productDetailComponent));
}
},
displayProductOnCart: function(response) {
const cart = response?.data?.addProductsToCart?.cart
const items = response?.data?.addProductsToCart?.cart?.items.length > 0 ? response?.data?.addProductsToCart?.cart?.items : []
const userErrors = response?.data?.addProductsToCart?.user_errors.length > 0 ? response?.data?.addProductsToCart?.user_errors : null
if(items.length > 0) {
miniCart.removeEmptyCartBlock();
miniCart.loadProducts();
miniCart.addProductAnalytics();
if (userErrors) {
const cartItemWithStockError = checkCartItemWithStockError(items)
const userErrorsArray = RepsolStoreErrors.checkUserErrorTypes(userErrors)
const stockErrorCount = countDuplicateStrings(userErrorsArray, 'PRODUCT_WITH_STOCK_ERROR')
const productNotAvailable = userErrorsArray.some(error => error === 'PRODUCT_NOT_AVAILABLE')
function checkCartItemWithStockError(items) {
function hasStockErrors(item) {
return (
item?.product?.stock_status === 'IN_STOCK' &&
item?.errors !== null &&
item.quantity > item?.product?.salable_quantity
);
}
return items?.some(hasStockErrors) ?? false;
}
function countDuplicateStrings(array, string) {
let count = 0;
array.forEach(item => {
if (item === string) {
count++;
}
});
return count;
}
function countItemsWithErrors(items) {
let itemsErrorCount = 0;
items.forEach((item) => {
if (item.product.stock_status === "IN_STOCK" &&
item.errors !== null &&
item.quantity > item.product.salable_quantity
) {
itemsErrorCount++;
}
});
return itemsErrorCount;
}
if(stockErrorCount === 2 || productNotAvailable) {
miniCart.showProductError()
} else if(stockErrorCount === 1) {
if(cartItemWithStockError) {
miniCart.showAddProductSuccessMsg()
} else {
miniCart.showProductError()
}
} else {
miniCart.showAddProductSuccessMsg()
}
} else {
miniCart.showAddProductSuccessMsg()
}
} else {
miniCart.emptyCart();
document.querySelector(".header .js-summary").classList.add("d-none")
}
},
showAddProductSuccessMsg: () =>{
let component = miniCart.component
let info = {
"type": 'rp-warning-success',
"text": component.getAttribute("data-add-to-cart-success-msg-text"),
"icon": component.getAttribute("data-add-to-cart-success-msg-icon")
}
RpAlert.msgContainer(info, undefined, false, true)
const time = 3000;
var obj = $(document).find(".warning-block-alert").eq(0);
setTimeout(function(){ RpAlert.removeAlert(obj); }, time);
document.querySelector(".warning-block-alert .warning-component").classList.add("rp-warning-add-product")
miniCart.setPositionAddProductSuccessMsg();
window.scroll({
top: 0,
behavior: "smooth",
});
const pageScroll = document.documentElement.scrollTop;
if(pageScroll == 0){
miniCart.scrollToTop = false;
}else{
miniCart.scrollToTop = true;
}
},
setPositionAddProductSuccessMsg: () =>{
let isMegaMenuHeader = document.querySelector("header.header-megamenu") ? true: false
let isMenuHeader2024 = document.querySelector("header.header-2024") ? true: false
if(isMegaMenuHeader){
var heightHeader = document.querySelector("header").offsetHeight;
}else if(isMenuHeader2024 && window.matchMedia("(min-width: 1024px)").matches){
var heightHeaderTop = document.querySelector("header").offsetHeight;
if(document.querySelector("header-bottom")){
var heightHeaderBottom = document.querySelector("header-bottom").offsetHeight;
}else{
var heightHeaderBottom = 57;
}
var heightHeader = heightHeaderTop + heightHeaderBottom;
}else{
var heightHeader = document.getElementById("headTop").offsetHeight;
}
let linksBarElement = document.querySelector(".linksbar-ecommerce-component");
if(linksBarElement && linksBarElement.style.display !== "none"){
linksBarHeight = 64;
heightHeader += linksBarHeight;
}
let storeMessage = document.querySelector(".store-message-component") ? document.querySelector(".store-message-component").offsetHeight : 0;
let topPosition = heightHeader + storeMessage;
let warningMsg = document.querySelector(".warning-block-alert .warning-component");
if(warningMsg){
warningMsg.style.cssText = `top: ${topPosition}px !important;`
}
},
showProductError: function() {
const $product = $('.product-detail-component').find('.product-detail-card')
const $productWithVariantError = $('.store-minicart-component').attr('msg-stock-var')
const $productError = $('.store-minicart-component').attr('msg-stock')
const $productWithVariants = $product.find(".product-detail__options").length > 0 ? true : false
let errorMessage
if ($productWithVariants) {
errorMessage = $productWithVariantError
textActive = $product.find(".product-detail__options").find(".active").find('span').html()
let textReplace = errorMessage.replace("{0}", textActive)
errorMessage = textReplace
} else {
errorMessage = $productError
}
$product.find('.product-detail__cart-actions .error-msg').removeClass('d-none')
$product.find('.product-detail__cart-actions .error-msg').text(errorMessage)
$product.find('.product-detail__cart-actions .js-add-cart .rp-btn').addClass('disabled')
$product.find('.product-detail__stock-actions').addClass('d-none');
//Analytics
Repsol.Analytics.Store.errorStock(errorMessage);
let params = {
error_type: 'out of stock',
error_description: errorMessage,
}
Repsol.AnalyticsRomProd.errorRomProd($(minicart.component), params);
},
showStockErrorMessage: function() {
const component = miniCart.component;
const products = component.querySelectorAll('.minicart-product')
const noStockErrorMsg = component.getAttribute("data-no-stock-error-msg")
const fewStockErrorMsg = component.getAttribute("data-few-stock-error-msg")
const repeatedProductFewStockErrorMsg = component.getAttribute('data-repeated-product-few-stock-error-msg')
const errorCodes = miniCart.errorCodes;
let productErrors = []
const template = component.querySelector('#template-minicart-product-error').content
let fragment = document.createDocumentFragment()
products.forEach((item) => {
let errorMessage = "";
const errorCode = item.getAttribute('data-error-code')
const error = item.getAttribute('data-error')
const salableQuantity = item.getAttribute('data-salable-quantity')
const productSku = item.getAttribute('data-sku');
const repeatedProducts = component.querySelectorAll(`.minicart-product[data-sku="${productSku}"]`);
if(errorCode === errorCodes.noStockUnits) {
errorMessage = noStockErrorMsg
}
if(errorCode === errorCodes.fewStockUnits) {
errorMessage = fewStockErrorMsg.replace('{0}', salableQuantity)
if(repeatedProducts.length > 1){
errorMessage = repeatedProductFewStockErrorMsg
}
}
item.querySelector(".warning-block-alert")?.remove();
if(errorCode != errorCodes.noError){
productErrors.push(error)
template.querySelector(".warning-text").textContent = errorMessage
const cloneTemplate = template.cloneNode(true)
fragment.appendChild(cloneTemplate)
let div = document.createElement('div')
div.appendChild(fragment)
html = div.innerHTML
item.querySelector(".minicart-product-content-botton").innerHTML += html
Repsol.Analytics.Store.errorStock(errorMessage);
let params = {
error_type: 'out of stock',
error_description: errorMessage,
}
Repsol.AnalyticsRomProd.errorRomProd($(item), params);
}
})
},
getProductsFromLocalStorageCart: function() {
const localStorageCart = JSON.parse(localStorage.getItem('cart'));
return localStorageCart?.cart?.items || localStorageCart?.items;
},
loadProductsToMiniCart: function() {
let component = miniCart.component;
const products = miniCart.getProductsFromLocalStorageCart();
if (products && products.length > 0) {
miniCart.loadProducts();
} else {
miniCart.emptyCart();
miniCart.checkSummaryCount();
}
},
showProductFewStockError: function(errors) {
let component = miniCart.component;
let message = errors[0]?.message.toString()
let products = document.querySelectorAll('.minicart-product')
let pattern = /SKU (\d+)/
let match = message.match(pattern)
let sku = match ? match[1] : ''
let productErrorMsg = component.getAttribute('msg-stock')
const errorCodes = miniCart.errorCodes;
let productErrors = []
const template = component.querySelector('#template-minicart-product-error').content
let fragment = document.createDocumentFragment()
products.forEach(product => {
let productSku = product.getAttribute('data-sku')
item.querySelector(".warning-block-alert")?.remove();
if(sku === productSku) {
template.querySelector(".warning-text").textContent = productErrorMsg
const cloneTemplate = template.cloneNode(true)
fragment.appendChild(cloneTemplate)
let div = document.createElement('div')
div.appendChild(fragment)
html = div.innerHTML
product.querySelector(".minicart-product-content").innerHTML += html
product.setAttribute('data-error', true)
product.setAttribute('data-error-code', errorCodes.fewStockUnits)
const error = product.getAttribute('data-error')
productErrors.push(error)
Repsol.Analytics.Store.errorStock(productErrorMsg);
let params = {
error_type: 'out of stock',
error_description: productErrorMsg,
}
Repsol.AnalyticsRomProd.errorRomProd($(product), params);
}
})
},
redirectToCart: () =>{
let component = miniCart.component;
let cartPage = component.getAttribute("data-cart-page");
if(cartPage){
window.location.href = cartPage
}
},
checkScrollProductsList: () =>{
let component = miniCart.component;
let minicartBody = component.querySelector(".minicart-products .minicart-body")
minicartBodyHeight = minicartBody.offsetHeight;
let productsList = component.querySelector(".minicart-products-list")
productsListHeight = productsList.offsetHeight;
if(productsListHeight > minicartBodyHeight){
minicartBody.classList.add("minicart-body--scroll")
}else{
minicartBody.classList.remove("minicart-body--scroll")
}
},
isStorePage: () =>{
let locationPath = window.location.href
let isStorePage = locationPath.includes('tienda') ? true : false
return isStorePage;
},
resetStoreCookie: () => {
RepsolLoginStore.close();
}
}
if(window.performance) {
let data = window.performance.getEntriesByType("navigation")[0].type
if(data == 'reload') {
miniCart.redirectCheckoutWithoutProducts()
}
}
$(document).ready(function () {
miniCart.init();
});
window.addEventListener("scroll", (event) => {
const pageScroll = document.documentElement.scrollTop;
if(pageScroll == 0){
miniCart.scrollToTop = false;
}
if(!miniCart.scrollToTop){
let addProductSuccessMsg = document.querySelector(".rp-warning-add-product")
let isMegaMenuHeader = document.querySelector("header.header-megamenu") ? true: false
let isHeader2024 = document.querySelector("header.header-2024") ? true: false
if (addProductSuccessMsg){
if(pageScroll > 0 && (isMegaMenuHeader || isHeader2024)){
document.querySelector(".warning-block-alert .warning-component").style.cssText = `top: 0px !important; z-index: 1500;`
}else{
miniCart.setPositionAddProductSuccessMsg();
}
}
}
})