{"version":3,"file":"index.es.min.js","sources":["../../../packages/components/src/sku-coffee/services/index.js","../../../packages/helpers/src/props.helpers.js","../../../packages/page-builder-sections/src/bundle-details/bundle-details.js","../../../packages/helpers/src/catalog.js"],"sourcesContent":["import { INTENSITY_MAX_OL, INTENSITY_MAX_VL } from '@kissui/components'\n\nexport const getMaxIntensity = ({ technologies }) =>\n technologies.indexOf('original') !== -1 ? INTENSITY_MAX_OL : INTENSITY_MAX_VL\n","const getData = attributes => attributes.find(attribute => attribute.nodeName === 'data')\n\nconst createProps = attributes => {\n const data = getData([...attributes])\n const props = [...attributes]\n .filter(attribute => attribute.nodeName !== 'data')\n .reduce((all, attr) => {\n return { ...all, [attr.nodeName]: attr.nodeValue }\n }, {})\n\n if (isNil(data)) {\n return props\n }\n\n try {\n return { ...props, ...JSON.parse(data.nodeValue) }\n } catch (error) {\n console.log('ERROR: No data', error, data?.nodeValue)\n }\n}\n\nconst isNil = obj => obj === undefined || obj === null\n\nexport const parseBool = value => (!value || value === 'false' ? false : true)\n\nexport default createProps\n","import { getMaxIntensity } from '@kissui/components/src/sku-coffee/services'\nimport createProps from '@kissui/helpers/src/props.helpers'\nimport { getProduct } from '@kissui/helpers/src/catalog'\n\nclass BundleDetails extends HTMLElement {\n constructor() {\n super()\n this.props = {}\n this.detailLinks = []\n this.popinCenter = ''\n this.popinRight = ''\n this.boundShowHide = this.showHideDetailBlock.bind(this)\n }\n\n connectedCallback() {\n this.renderLoader()\n this.props = createProps(this.attributes)\n this.loadProducts()\n }\n\n renderLoader() {\n this.innerHTML = '<div class=\"loading\"><nb-loader></nb-loader></div>'\n }\n\n loadProducts() {\n const { main_sku, other_skus } = this.props\n const otherSkus = other_skus.split(',').map(item => item.trim())\n\n this.mainProduct = null\n this.otherProducts = []\n\n const skus = [main_sku, ...otherSkus]\n let currentSku = null\n\n Promise.all(\n skus.map(sku => {\n currentSku = sku\n return getProduct(sku)\n })\n )\n .then(result => {\n this.mainProduct = result[0]\n this.otherProducts = result.slice(1)\n })\n .catch(() => {\n throw new Error(`getProduct fail on sku ${currentSku}`)\n })\n .finally(() => {\n this.renderContainer()\n })\n }\n\n render() {\n if (!this.mainProduct || this.mainProduct.errorDate) {\n console.warn('Invalid SKU')\n return ''\n }\n\n const { main_sku, headline_desc, position, range } = this.props\n const { name, headline, images, id } = this.mainProduct\n const finalHeadline = headline_desc || headline || ''\n\n return `\n <div class=\"left\">\n ${this.renderImage(images, name)}\n <nb-add-to-cart\n sku=\"${main_sku}\"\n longSku=\"${id}\"\n position=\"${position}\"\n range=\"${range}\"\n buttonSize=\"large\"\n showPrice\n ></nb-add-to-cart>\n\n </div>\n\n <div class=\"center\">\n <h2 class=\"h-lg-700\">${name}</h2>\n ${this.renderHeadline(finalHeadline)}\n <ul role=\"tablist\">\n ${this.otherProducts.map((item, i) => this.renderLi(item, i)).join('')}\n </ul>\n </div>\n\n <div class=\"right\">\n ${this.otherProducts.map((item, i) => this.renderSubItemDetail(item, i)).join('')}\n </div>\n `\n }\n\n renderHeadline(headline) {\n return headline ? `<p class=\"t-sm-400\">${headline}</p>` : ''\n }\n\n renderImage(image, name) {\n if (!image.icon) {\n return ''\n }\n return `<img loading=\"lazy\" src=\"${image.icon}\" alt=\"${name}\" />`\n }\n\n renderLi(subItem, index) {\n const { other_skus_quantity } = this.props\n const quantities = other_skus_quantity.split(',')\n const { name, images } = subItem\n\n return `<li\n data-testid=\"bundle-details-li-${index}\"\n data-index=\"${index}\"\n data-name=\"${name.toLowerCase()}\"\n id=\"liElement${index}\"\n tabindex=\"${index ? '-1' : '0'}\"\n role=\"tab\"\n aria-selected=\"${index ? 'false' : 'true'}\"\n >\n ${this.renderImage(images, '')}\n <span>\n <h3 class=\"t-3xs-700-caps-sl\">${name.toLowerCase()}</h3>\n <p class=\"t-2xs-500-sl\">x${quantities[index]}</p>\n </span>\n </li>`\n }\n\n renderSubItemDetail(product, index) {\n const { name, images } = product\n\n return `\n <div\n class=\"tabPannel\"\n data-show-index=\"${index}\"\n role=\"tabpanel\"\n aria-labelledby=\"liElement${index}\"\n id=\"panel${index}\"\n data-testid=\"bundle-details-tabPannel-${index}\"\n tabindex=\"0\"\n aria-hidden=\"${index ? 'true' : 'false'}\">\n ${this.renderImage(images, name)}\n <h3 class=\"t-md-700-sl\">${name}</h3>\n ${this.renderTypes(product)}\n </div>\n `\n }\n\n renderTypes(product) {\n const { type, headline = '', category, capsuleProperties } = product\n\n return type\n ? `\n <div class=\"${type}\">\n ${type === 'capsule' && category ? `<h4>${category}</h4>` : ''}\n <p class=\"t-xs-500\">${headline}</p>\n ${\n type === 'capsule'\n ? this.renderCapsuleIntensity(capsuleProperties.intensity, product)\n : ''\n }\n </div>\n `\n : ''\n }\n\n renderCapsuleIntensity(intensity, product) {\n if (!intensity) {\n return ''\n }\n\n const { intensity_label = 'Intensity' } = this.props\n const intensityMax = getMaxIntensity(product)\n\n return `<nb-intensity intensity=\"${intensity}\" max_intensity=\"${intensityMax}\" intensity_label=\"${intensity_label}\"></nb-intensity>`\n }\n\n renderContainer() {\n this.innerHTML = this.render()\n this.popinCenter = this.querySelector('.center')\n this.popinRight = this.querySelector('.right')\n this.detailLinks = this.querySelectorAll('li')\n this.detailBlocks = this.querySelectorAll('.tabPannel')\n this.bindEvents()\n }\n\n showHideDetailBlock(e) {\n e.stopPropagation()\n\n const currentIdx = parseInt(e.currentTarget.getAttribute('data-index'))\n const totalTabs = this.detailLinks.length\n\n const activateTab = index => {\n this.detailLinks?.forEach((link, idx) => {\n const aside = this.querySelector(`.tabPannel[data-show-index=\"${idx}\"]`)\n const isSelected = idx === index\n\n link.setAttribute('aria-selected', String(isSelected))\n link.setAttribute('tabindex', isSelected ? '0' : '-1')\n aside.setAttribute('aria-hidden', String(!isSelected))\n })\n }\n\n if (e.type === 'click' || (e.type === 'keydown' && (e.key === 'Enter' || e.key === ' '))) {\n activateTab(currentIdx)\n } else if (e.type === 'keydown') {\n switch (e.key) {\n case 'ArrowRight':\n activateTab((currentIdx + 1) % totalTabs)\n this.detailLinks[(currentIdx + 1) % totalTabs].focus()\n break\n case 'ArrowLeft':\n activateTab((currentIdx - 1 + totalTabs) % totalTabs)\n this.detailLinks[(currentIdx - 1 + totalTabs) % totalTabs].focus()\n break\n case 'Home':\n activateTab(0)\n this.detailLinks[0].focus()\n break\n case 'End':\n activateTab(totalTabs - 1)\n this.detailLinks[totalTabs - 1].focus()\n break\n }\n }\n }\n\n bindEvents() {\n this.detailLinks.forEach(link => {\n link.addEventListener('click', this.boundShowHide.bind(this))\n link.addEventListener('keydown', this.boundShowHide.bind(this))\n })\n }\n\n unbindEvents() {\n this.detailLinks.forEach(link => {\n link.removeEventListener('click', this.boundShowHide.bind(this))\n link.removeEventListener('keydown', this.boundShowHide.bind(this))\n })\n }\n\n disconnectedCallback() {\n this.unbindEvents()\n }\n}\n\ncustomElements.get('nb-bundle-details') || customElements.define('nb-bundle-details', BundleDetails)\n\nexport default BundleDetails\n","import { COFFEE_VERTUO } from '@kissui/components/src/constants.mjs'\nimport { getCurrency } from './getCurrency'\nexport { getCurrency } from './getCurrency'\n\nexport const ECAPI_TYPE_CAPSULE = 'capsule'\nexport const ECAPI_TYPE_MACHINE = 'machine'\nexport const ECAPI_TYPE_ACCESSORY = 'accessory'\nexport const ECAPI_TYPE_GIFT_CARD = 'giftcard'\n\nconst TECHNOLOGY_CATEGORY_IDENTIFIER = '/machineTechno/'\nconst SLEEVE_OF_10 = 10\nconst SLEEVE_OF_7 = 7\n\nconst trimSku = sku => sku.replace(/[^a-z0-9- +./]/gi, '')\n\nexport const getLegacySKU = productId => productId.split('prod/').pop()\n\nexport const getPriceFormatter = async () => await window.napi.priceFormat()\n\nexport const getProduct = sku => window.napi.catalog().getProduct(trimSku(sku))\n\nexport function getTechnologyName(productData) {\n const techno = productData.technologies[0]\n return techno.substring(\n techno.indexOf(TECHNOLOGY_CATEGORY_IDENTIFIER) + TECHNOLOGY_CATEGORY_IDENTIFIER.length\n )\n}\n\nfunction isMultipleOf(quantity, multiple) {\n return quantity % multiple === 0\n}\n\nexport function getSleeveNumber(product, getTechnologyNameFn = getTechnologyName) {\n if (product.sales_multiple !== 1 && isMultipleOf(product.sales_multiple, SLEEVE_OF_10)) {\n // Sleeve of original or vertuo\n return product.sales_multiple / SLEEVE_OF_10\n }\n\n if (\n product.sales_multiple !== 1 &&\n getTechnologyNameFn(product) === COFFEE_VERTUO &&\n isMultipleOf(product.sales_multiple, SLEEVE_OF_7)\n ) {\n // Sleeve of vertuo\n return product.sales_multiple / SLEEVE_OF_7\n }\n\n if (product.sales_multiple === 1 && isMultipleOf(product.unitQuantity, SLEEVE_OF_10)) {\n // Bundle of original or vertuo\n return product.unitQuantity / SLEEVE_OF_10\n }\n\n if (\n product.sales_multiple === 1 &&\n getTechnologyNameFn(product) === COFFEE_VERTUO &&\n isMultipleOf(product.unitQuantity, SLEEVE_OF_7)\n ) {\n // Bundle of vertuo\n return product.unitQuantity / SLEEVE_OF_7\n }\n\n return NaN\n}\n\n/**\n * Guess if the product is part of a bundle.\n * This is determined by checking the 'sales_multiple' and 'unitQuantity' properties.\n */\nexport function isBundled(productData) {\n // TODO: this function should not change the productData, but some components still need it\n productData.sales_multiple = productData.sales_multiple || productData.salesMultiple\n\n const isSalesMultipleGreaterThanOne = productData.sales_multiple > 1\n const isUnitQuantityEqualToOne = productData.unitQuantity === 1\n const isSalesMultipleEqualToOne = productData.sales_multiple === 1\n const isUnitQuantityGreaterThanOne = productData.unitQuantity > 1\n\n // The product is not bundled if sales_multiple > 1 and unitQuantity = 1\n if (isSalesMultipleGreaterThanOne && isUnitQuantityEqualToOne) {\n return false\n }\n\n // The product is bundled if sales_multiple = 1 and unitQuantity > 1\n return isSalesMultipleEqualToOne && isUnitQuantityGreaterThanOne\n}\n\n/**\n * Replace an array of SKU with product data\n * Remove the element inside the list if sku fail. It prevents to get an empty item.\n * @param {Array.<String>} skus\n * @param getProductFn\n * @returns {Promise<Awaited<unknown>[]>}\n */\nexport function getProductAndClean(skus, getProductFn = getProduct, napi = window.napi) {\n const promises = []\n\n if (!napi) {\n return Promise.reject()\n }\n\n if (!Array.isArray(skus)) {\n skus = [skus]\n }\n\n // Load manually the product to delete SKU fail\n for (const sku of skus) {\n promises.push(\n getProductFn(sku)\n .then(data => skus.splice(skus.indexOf(sku), 1, data))\n .catch(() => {\n skus.splice(skus.indexOf(sku), 1)\n console.error(`getProduct fail on sku ${sku}`)\n })\n )\n }\n\n return Promise.all(promises)\n}\n\nexport const getFormattedPrice = async price => {\n const priceFormatter = await getPriceFormatter()\n const currency = getCurrency()\n\n return priceFormatter.html\n ? priceFormatter.html(currency, price)\n : priceFormatter.short(currency, price) || ''\n}\n\nexport const getProductCategories = async sku => {\n const productDetails = await getProduct(sku)\n const productCategories = productDetails ? productDetails.supercategories : []\n const productCategoriesNew = await Promise.all(\n productCategories.map(async categoryEncoded => {\n const productCategoryData = await window.napi.catalog().getCategory(categoryEncoded)\n return productCategoryData\n })\n )\n return productCategoriesNew\n}\n"],"names":["isNil","obj","BundleDetails","HTMLElement","constructor","this","props","detailLinks","popinCenter","popinRight","boundShowHide","showHideDetailBlock","bind","connectedCallback","renderLoader","attributes","data","find","attribute","nodeName","getData","filter","reduce","all","attr","nodeValue","JSON","parse","error","console","log","createProps","loadProducts","innerHTML","main_sku","other_skus","otherSkus","split","map","item","trim","mainProduct","otherProducts","skus","currentSku","Promise","sku","window","napi","catalog","getProduct","replace","trimSku","then","result","slice","catch","Error","finally","renderContainer","render","errorDate","warn","headline_desc","position","range","name","headline","images","id","finalHeadline","renderImage","renderHeadline","i","renderLi","join","renderSubItemDetail","image","icon","subItem","index","other_skus_quantity","quantities","toLowerCase","product","renderTypes","type","category","capsuleProperties","renderCapsuleIntensity","intensity","intensity_label","getMaxIntensity","technologies","indexOf","INTENSITY_MAX_OL","INTENSITY_MAX_VL","querySelector","querySelectorAll","detailBlocks","bindEvents","e","stopPropagation","currentIdx","parseInt","currentTarget","getAttribute","totalTabs","length","activateTab","forEach","link","idx","aside","isSelected","setAttribute","String","key","focus","addEventListener","unbindEvents","removeEventListener","disconnectedCallback","customElements","get","define"],"mappings":"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"}