let DEFAULT_addToCartBtnSelectorsApp7Ext = 'input[name="add"], button[name="add"], form[action*="/cart/add"] .gfg__add-to-cart,form[action*="/cart/add"] button[type="submit"], form[action*="/cart/add"] input[type="submit"], .product-form__buttons, .productView-group, .prd-Benefits, .product__submit__buttons, .t4s-product-form__buttons, .product-form__buy-buttons, .product__description, .v-stack.gap-4, .groups-btn'; let DEFAULT_checkoutBtnSelectorsApp7Ext = 'button[name="checkout"], input[name="checkout"], form[action*="/cart"] a[href="/checkout"], a[href="/checkout"], form[action="/cart"] input[type="submit"][name="checkout"], form[action="/cart"] button[type="submit"][name="checkout"], .previewCartInfo, .cart__ctas, .cart__items, .buy-buttons--compact, .drawer__footer, .ajax-cart__buttons, .taxes-discounts, .button-container, cart-drawer .line-item__content-wrapper, .mini-cart__actions, .cart__checkout-wrapper, .cart__footer-message, .js-contents, .cart--footer'; let DEFAULT_quantityBtnSelectorsApp7Ext = '.ajaxcart__qty,quantity-input .quantity,.quantity-input,.quantity__input,.quantity_input,.quantity,.quantity__container,.quantity_container, .quantity-selector, input[name="quantity"], .cart-item__quantity, .quantity-selector__input, .product-form__qty-input, .product__quantity, .product-quantity, .js-qty__num, .product-details input, .product-form__info-item--quantity, .product__quantity--button .js-qty__num, .product-form__quantity, .quantity__container, .QuantitySelector.QuantitySelector--large, .prd-quantity, .t4s-quantity-wrapper.t4s-product-form__qty, .qty-actual__input, .js-qty__wrapper, .t4s-quantity-wrapper, .t4s-product-form__buttons .t4s-quantity-input, .ProductForm__QuantitySelector, #quantity'; let DEFAULT_sideCartSelectorsApp7Ext = '.cart-notification,cart-notification,.cart-notification-wrapper,#cart-notification, #CartDrawer, .drawer, .drawer-cover, .Drawer'; let DEFAULT_buyNowBtnApp7Ext = '.shopify-payment-button__button, .shopify-payment-button__button--unbranded'; let DEFAULT_cartFormApp7Ext = 'form[action="/cart"], form[action="/cart/"], form[action="cart"]'; //for cart integration let DEFAULT_cartItemSelectorApp7Ext = ".cart-item"; let DEFAULT_cartItemRemoveParentSelectorApp7Ext = "cart-remove-button"; let DEFAULT_cartItemRemoveSelectorApp7Ext = ""; let DEFAULT_cartItemQuantityBtnSelectorsApp7Ext = ""; let CONSTANT_ARROW_SVG_APP7EXT = '' + '' + ''; let CONSTANT_LOADING_SPINNER_SVG = `
`; const UNIFIED_WIDGET_FREE_GIFT_ICON = ` ` const UNIFIED_WIDGET_DISCOUNT_ICON = ` ` const UNIFIED_WIDGET_SHIPPING_DISCOUNT_ICON = ` ` const CURRENCY_SYMBOLS = { AED: 'د.إ', AFN: '؋', ALL: 'L', AMD: '֏', ANG: 'ƒ', AOA: 'Kz', ARS: '$', AUD: '$', AWG: 'ƒ', AZN: '₼', BAM: 'KM', BBD: '$', BDT: '৳', BGN: 'лв', BHD: '.د.ب', BIF: 'FBu', BMD: '$', BND: '$', BOB: '$b', BOV: 'BOV', BRL: 'R$', BSD: '$', BTC: '₿', BTN: 'Nu.', BWP: 'P', BYN: 'Br', BYR: 'Br', BZD: 'BZ$', CAD: '$', CDF: 'FC', CHE: 'CHE', CHF: 'CHF', CHW: 'CHW', CLF: 'CLF', CLP: '$', CNH: '¥', CNY: '¥', COP: '$', COU: 'COU', CRC: '₡', CUC: '$', CUP: '₱', CVE: '$', CZK: 'Kč', DJF: 'Fdj', DKK: 'kr', DOP: 'RD$', DZD: 'دج', EEK: 'kr', EGP: '£', ERN: 'Nfk', ETB: 'Br', ETH: 'Ξ', EUR: '€', FJD: '$', FKP: '£', GBP: '£', GEL: '₾', GGP: '£', GHC: '₵', GHS: 'GH₵', GIP: '£', GMD: 'D', GNF: 'FG', GTQ: 'Q', GYD: '$', HKD: '$', HNL: 'L', HRK: 'kn', HTG: 'G', HUF: 'Ft', IDR: 'Rp', ILS: '₪', IMP: '£', INR: '₹', IQD: 'ع.د', IRR: '﷼', ISK: 'kr', JEP: '£', JMD: 'J$', JOD: 'JD', JPY: '¥', KES: 'KSh', KGS: 'лв', KHR: '៛', KMF: 'CF', KPW: '₩', KRW: '₩', KWD: 'KD', KYD: '$', KZT: '₸', LAK: '₭', LBP: '£', LKR: '₨', LRD: '$', LSL: 'M', LTC: 'Ł', LTL: 'Lt', LVL: 'Ls', LYD: 'LD', MAD: 'MAD', MDL: 'lei', MGA: 'Ar', MKD: 'ден', MMK: 'K', MNT: '₮', MOP: 'MOP$', MRO: 'UM', MRU: 'UM', MUR: '₨', MVR: 'Rf', MWK: 'MK', MXN: '$', MXV: 'MXV', MYR: 'RM', MZN: 'MT', NAD: '$', NGN: '₦', NIO: 'C$', NOK: 'kr', NPR: '₨', NZD: '$', OMR: '﷼', PAB: 'B/.', PEN: 'S/.', PGK: 'K', PHP: '₱', PKR: '₨', PLN: 'zł', PYG: 'Gs', QAR: '﷼', RMB: '¥', RON: 'lei', RSD: 'Дин.', RUB: '₽', RWF: 'R₣', SAR: '﷼', SBD: '$', SCR: '₨', SDG: 'ج.س.', SEK: 'kr', SGD: 'S$', SHP: '£', SLL: 'Le', SOS: 'S', SRD: '$', SSP: '£', STD: 'Db', STN: 'Db', SVC: '$', SYP: '£', SZL: 'E', THB: '฿', TJS: 'SM', TMT: 'T', TND: 'د.ت', TOP: 'T$', TRL: '₤', TRY: '₺', TTD: 'TT$', TVD: '$', TWD: 'NT$', TZS: 'TSh', UAH: '₴', UGX: 'USh', USD: '$', UYI: 'UYI', UYU: '$U', UYW: 'UYW', UZS: 'лв', VEF: 'Bs', VES: 'Bs.S', VND: '₫', VUV: 'VT', WST: 'WS$', XAF: 'FCFA', XBT: 'Ƀ', XCD: '$', XOF: 'CFA', XPF: '₣', XSU: 'Sucre', XUA: 'XUA', YER: '﷼', ZAR: 'R', ZMW: 'ZK', ZWD: 'Z$', ZWL: '$' } // Archived app block selectors const PRODUCT_PAGE_APP_BLOCK_SELECTOR= '.gfgProductPageAppBlock'; const CART_PAGE_APP_BLOCK_SELECTOR = '.gfgCartPageAppBlock'; // new feature specific app block selectors for product & cart page const FREE_GIFT_APP_BLOCK_SELECTOR = '.gfgFreeGiftWrapperV3'; const VOLUME_DISCOUNT_APP_BLOCK_SELECTOR = '.gfgVolDiscountWrapperV3'; const BOGO_APP_BLOCK_SELECTOR = '.gfgBogoDiscountWrapperV3'; const UNIFIED_APP_BLOCK_SELECTOR = '.gfgUnifiedDiscountWrapperV3'; const CUSTOM_DISCOUNT_APP_BLOCK_SELECTOR = '.gfgCustomDiscountWrapperV2'; const SHIPPING_DISCOUNT_APP_BLOCK_SELECTOR = '.gfgShippingDiscountWrapperV2'; // feature specific side cart wrappers // const FREEGIFT_SIDE_CART_WRAPPER = '
' // const VOLUME_DISCOUNT_SIDE_CART_WRAPPER = '
' // const UNIFIED_SIDE_CART_WRAPPER = '
' // const CUSTOM_DISCOUNT_SIDE_CART_WRAPPER = '
' // const SHIPPING_DISCOUNT_SIDE_CART_WRAPPER = '
' const FREEGIFT_SIDE_CART_WRAPPER = document.createElement('div'); FREEGIFT_SIDE_CART_WRAPPER.className = 'gfgFreeGiftSideCartWrapperV4'; const VOLUME_DISCOUNT_SIDE_CART_WRAPPER = document.createElement('div'); VOLUME_DISCOUNT_SIDE_CART_WRAPPER.className = 'gfgVolumeDiscountSideCartWrapperV4'; const UNIFIED_SIDE_CART_WRAPPER = document.createElement('div'); UNIFIED_SIDE_CART_WRAPPER.className = 'gfgUnifiedSideCartWrapperV4'; const CUSTOM_DISCOUNT_SIDE_CART_WRAPPER = document.createElement('div'); CUSTOM_DISCOUNT_SIDE_CART_WRAPPER.className = 'gfgCustomDiscountSideCartWrapperV4'; const SHIPPING_DISCOUNT_SIDE_CART_WRAPPER = document.createElement('div'); SHIPPING_DISCOUNT_SIDE_CART_WRAPPER.className = 'gfgShippingDiscountSideCartWrapperV4'; // feature specific side cart wrappers selector const FREEGIFT_SIDE_CART_WRAPPER_SELECTOR = '.gfgFreeGiftSideCartWrapperV4'; const VOLUME_DISCOUNT_SIDE_CART_WRAPPER_SELECTOR = '.gfgVolumeDiscountSideCartWrapperV4'; const UNIFIED_SIDE_CART_WRAPPER_SELECTOR = '.gfgUnifiedSideCartWrapperV4'; const CUSTOM_DISCOUNT_SIDE_CART_WRAPPER_SELECTOR = '.gfgCustomDiscountSideCartWrapperV4'; const SHIPPING_DISCOUNT_SIDE_CART_WRAPPER_SELECTOR = '.gfgShippingDiscountSideCartWrapperV4'; const FREE_GIFT_PAGINATION_ITEMS_PER_PAGE = 2; var gfgUtils = { f: {} } window.gfgUtils = gfgUtils; // gfgUtils.f.loadScript = function (a, b) { // var c = document.createElement("script"); // c.type = "text/javascript"; // c.src = a; // document.getElementsByTagName("head")[0].appendChild(c) // c.onload = function () { b() }; // }; /* * we changed loadScript function - if else block for onload is removed as it was not making sense *fn(param1) => *param1 - represents function that should be executed once jquery is loaded *https://www.w3schools.com/jquery/jquery_noconflict.asp */ // gfgUtils.f.loadJquery = function (b) { // let flag = false; // if("undefined" === typeof jQuery || 3.0 > parseFloat(jQuery.fn.jquery)){ // flag = true; // } // if("undefined" != typeof jQuery && jQuery.post == undefined){ // flag = true; // } // if(flag){ // gfgUtils.f.loadScript("https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js", function () { // gfgJquery = jQuery.noConflict(!0); // b(gfgJquery) // }) // }else{ // b(jQuery); // } // }; var gfg = { debug: [], version: 1.35, state: { submitted: "", product_added: "", page_type: "", lastClickTimestamps: new Map(), insertWrapperOnPage: [], cartData: undefined, isOverWriteBuyNowBtnTriggered: false, timer: undefined, freeGiftcardPopupModalTriggered: false, atleastOneProduct:{}, checkForFreeGift: false, isCheckForFreeGiftTriggered: false, gfgFreeGiftMsgRowButton: false, CONSTANT_DEBUG_FLAG: undefined, freeGiftsCartDataMap_productId: {}, freeGiftsCartDataMap_variantId: {}, freeGiftsCartData: {}, gfgFreeGiftCartData: {}, activeCampaignName: "EMPTY", activeCustomerData: "EMPTY", formatPriceViaCustomScript: false, shouldInitShippingDiscountAgain: false, shouldInitUnifiedDiscountAgain: false, featuresWrapperMap:{} }, constants: { themesIds: { DAWN_THEME: 887, VENTURE_THEME: 775, EXPRESS_THEME: 885, CRAVE_THEME: 1363, SENSE_THEME: 1356, CRAFT_THEME: 1368, } }, settings: {}, //object from function selectors: {}, cartInterval: "", productinterval: "", f: { bootstrap: function (settings) { gfg.utility.debugConsole("bootstap?"); gfg.f.initThemeCSS(); gfg.f.globalListener(settings); gfg.f.executeCustomScriptOnLoadFn() }, initThemeCSS: function (){ }, getSettings: async function () { //promise gfg.utility.debugConsole("GET setting of giftboxbuilder ext fired") return new Promise(function (resolve, reject) { gfg.utility.debugConsole("fetching from s3") gfg.f.getSettingsFromS3().then( success => { resolve(success); } ).catch(error => { gfg.utility.debugError("error in s3 fetch. ", error); }); }); }, getSettingsFromS3: async function () { //promise let shopName = window.Shopify.shop gfg.utility.debugConsole("GET setting of giftlab pro fired") return new Promise(function (resolve, reject) { fetch(`https://free-gift-app7.s3.us-east-2.amazonaws.com/tempCartSettings/${shopName}.json?nocache=${(new Date()).getTime()}`,{ method: 'GET', }).then( response => response.json() // if the response is a JSON object ).then( success => { if(success.responseCode == 200){ gfg.utility.debugConsole("success-data", success); } resolve(success); } ).catch(error => { gfg.utility.debugConsole(error) // Handle the error response object reject(error) }) }) }, setSettings: function(tmpCartSettings){ var cart_settings = { SERVER_URL: tmpCartSettings.SERVER_URL, app: { disableApp: tmpCartSettings.userData.customSettings.disableApp || false, disableSideCart: tmpCartSettings.userData.customSettings.disableSideCart || false, refreshProductPageOnGiftWrap: tmpCartSettings.userData.customSettings.refreshProductPageOnGiftWrap || false, addToCartBtnSelectors: tmpCartSettings.userData.customSettings.addToCartBtnSelectors || DEFAULT_addToCartBtnSelectorsApp7Ext, checkoutBtnSelectors: tmpCartSettings.userData.customSettings.checkoutBtnSelectors || DEFAULT_checkoutBtnSelectorsApp7Ext, sideCartCheckoutBtnSelectors: tmpCartSettings.userData.customSettings.sideCartCheckoutBtnSelectors || DEFAULT_checkoutBtnSelectorsApp7Ext, overWriteCheckoutBtn: tmpCartSettings.userData.customSettings.overWriteCheckoutBtn || false, quantityBtnSelectors: tmpCartSettings.userData.customSettings.quantityBtnSelectors || DEFAULT_quantityBtnSelectorsApp7Ext, sideCartSelectors: tmpCartSettings.userData.customSettings.sideCartSelectors || DEFAULT_sideCartSelectorsApp7Ext, isCartIntegrationEnabled: tmpCartSettings.userData.customSettings.isCartIntegrationEnabled || false, cartItemSelectors: tmpCartSettings.userData.customSettings.cartItemSelectors || DEFAULT_cartItemSelectorApp7Ext, cartItemRemoveParentSelectors: tmpCartSettings.userData.customSettings.cartItemRemoveParentSelectors || DEFAULT_cartItemRemoveParentSelectorApp7Ext, cartItemRemoveSelectors: tmpCartSettings.userData.customSettings.cartItemRemoveSelectors || DEFAULT_cartItemRemoveSelectorApp7Ext, cartItemQuantityBtnSelectors: tmpCartSettings.userData.customSettings.cartItemQuantityBtnSelectors || DEFAULT_cartItemQuantityBtnSelectorsApp7Ext, customCartIntegrationScript: tmpCartSettings.userData.customSettings.customCartIntegrationScript || null, activeVariantCodes: tmpCartSettings.userData.customSettings.activeVariantCodes || "123456789", showBranding : tmpCartSettings.userData.customSettings.showBranding, buyNowBtn: tmpCartSettings.userData.customSettings.buyNowBtn || DEFAULT_buyNowBtnApp7Ext, customStyle: tmpCartSettings.userData.customSettings.customStyle || null, enablingApiFromSetInterval: tmpCartSettings.userData.customSettings.enablingApiFromSetInterval || false, isMultipleFreeGiftAllowed: tmpCartSettings.userData.customSettings.isMultipleFreeGiftAllowed || false, addAfterAddTocartBtn: tmpCartSettings.userData.customSettings.addAfterAddTocartBtn || false, addAftercheckoutBtn: tmpCartSettings.userData.customSettings.addAftercheckoutBtn || false, // sideCartSectionId = "cart-drawer" sideCartSectionId: tmpCartSettings.userData.customSettings.sideCartSectionId || "cart-drawer", sideCartSectionSelector: tmpCartSettings.userData.customSettings.sideCartSectionSelector || null, // cartPageItemsId = "cart-items" cartPageItemsSectionId : tmpCartSettings.userData.customSettings.cartPageItemsSectionId || tmpCartSettings.userData.customSettings.cartPageItemsId || "cart-items", cartPageItemsSelector: tmpCartSettings.userData.customSettings.cartPageItemsSelector || ".cart__row", disableApiCallListen: tmpCartSettings.userData.customSettings.disableApiCallListen || false, executeScriptAfterAddToCart: tmpCartSettings.userData.customSettings.executeScriptAfterAddToCart || "", executeCustomScriptAfterFreeGiftAddition: tmpCartSettings.userData.customSettings.executeCustomScriptAfterFreeGiftAddition || "", executeCustomScriptAfterBogoAddition : tmpCartSettings.userData.customSettings.executeCustomScriptAfterBogoAddition || "", redirectToCartAfterBogoAddition : tmpCartSettings.userData.customSettings?.redirectToCartAfterBogoAddition || null, redirectToCheckoutAfterBogoAddition: tmpCartSettings.userData.customSettings?.redirectToCheckoutAfterBogoAddition || null, executeCustomScriptOnLoad : tmpCartSettings.userData.customSettings.executeCustomScriptOnLoad || null, productHandlesAreTranslated: tmpCartSettings.userData?.customSettings?.productHandlesAreTranslated ? tmpCartSettings.userData.customSettings.productHandlesAreTranslated : false, isWidgetAccordionExpandedByDefault_FREE_GIFT: tmpCartSettings.userData?.customSettings?.isWidgetAccordionExpandedByDefault_FREE_GIFT ? tmpCartSettings.userData.customSettings.isWidgetAccordionExpandedByDefault_FREE_GIFT : false, skipDefaultSideCartCheck: tmpCartSettings.userData?.customSettings?.skipDefaultSideCartCheck ? tmpCartSettings.userData.customSettings.skipDefaultSideCartCheck : false, isRegionalLocaleUrlRequiredForHref: tmpCartSettings.userData?.customSettings?.isRegionalLocaleUrlRequiredForHref ? tmpCartSettings.userData.customSettings.isRegionalLocaleUrlRequiredForHref : false, hideAccordionOnClaim_FREE_GIFT: tmpCartSettings.userData?.customSettings?.hideAccordionOnClaim_FREE_GIFT ? tmpCartSettings.userData.customSettings.hideAccordionOnClaim_FREE_GIFT : false, global_afterAddToCartScript: tmpCartSettings.userData?.customSettings?.global_afterAddToCartScript ? tmpCartSettings.userData.customSettings.global_afterAddToCartScript : "", AddMultipleFreeGiftsInOneAPICall: tmpCartSettings.userData?.customSettings?.AddMultipleFreeGiftsInOneAPICall ? tmpCartSettings.userData.customSettings.AddMultipleFreeGiftsInOneAPICall : false, freeGiftSideCartSelector: tmpCartSettings.userData?.customSettings?.freeGiftSideCartSelector || null, freeGiftSideCartWrapperAboveSelector: tmpCartSettings.userData?.customSettings?.freeGiftSideCartWrapperAboveSelector === false ? false : true, volumeDiscountSideCartSelector: tmpCartSettings.userData?.customSettings?.volumeDiscountSideCartSelector || null, volumeDiscountSideCartWrapperAboveSelector: tmpCartSettings.userData?.customSettings?.volumeDiscountSideCartWrapperAboveSelector === false ? false : true, unifiedSideCartSelector: tmpCartSettings.userData?.customSettings?.unifiedSideCartSelector || null, unifiedSideCartWrapperAboveSelector: tmpCartSettings.userData?.customSettings?.unifiedSideCartWrapperAboveSelector === false ? false : true, customDiscountSideCartSelector: tmpCartSettings.userData?.customSettings?.customDiscountSideCartSelector || null, customDiscountSideCartWrapperAboveSelector: tmpCartSettings.userData?.customSettings?.customDiscountSideCartWrapperAboveSelector === false ? false : true, shippingDiscountSideCartSelector: tmpCartSettings.userData?.customSettings?.shippingDiscountSideCartSelector || null, shippingDiscountSideCartWrapperAboveSelector: tmpCartSettings.userData?.customSettings?.shippingDiscountSideCartWrapperAboveSelector === false ? false : true, fireNewSideCartRefreshCodeFirst: tmpCartSettings.userData?.customSettings?.fireNewSideCartRefreshCodeFirst ? tmpCartSettings.userData.customSettings.fireNewSideCartRefreshCodeFirst : false, considerRequestListenerData: tmpCartSettings.userData?.customSettings?.considerRequestListenerData ? tmpCartSettings.userData.customSettings.considerRequestListenerData : false, showConsoleAdvertisement: tmpCartSettings.userData?.customSettings?.showConsoleAdvertisement !== false ? true : false, fetchDataForFirstRenderInFreeGiftOnCartPage: tmpCartSettings.userData?.customSettings?.fetchDataForFirstRenderInFreeGiftOnCartPage ? tmpCartSettings.userData.customSettings.fetchDataForFirstRenderInFreeGiftOnCartPage : false, isKiteUniqueIdRequired: tmpCartSettings.userData?.customSettings?.isKiteUniqueIdRequired ? tmpCartSettings.userData.customSettings.isKiteUniqueIdRequired : false, enableFreeGiftWidgetPagination: tmpCartSettings.userData?.customSettings?.enableFreeGiftWidgetPagination ? tmpCartSettings.userData.customSettings.enableFreeGiftWidgetPagination : false, metafieldNameSpaceAndKeys: tmpCartSettings.userData?.customSettings?.metafieldNameSpaceAndKeys ? tmpCartSettings.userData.customSettings.metafieldNameSpaceAndKeys : [] }, merchantInfo: tmpCartSettings.userData, languageData: tmpCartSettings.languageData || {}, freeGifts: gfg.f.freeGiftDataTransformation(tmpCartSettings.promotionCampaigns), discounts: tmpCartSettings.discounts, urlSearchString: window.location.search ? window.location.search : "", boGoFeature: tmpCartSettings.boGo, shippingDiscount: tmpCartSettings.shippingDiscount, customDiscount: tmpCartSettings.customDiscount, unifiedWidgets: tmpCartSettings.unifiedWidget } // cart_settings.freeGifts[0].configuration.addtionalFields = { // claimText: "Claim", // claimedText: "Claimed", // addingText:"Adding", // alreadyClaimedText:"Note: Only one gift can be claimed at a time!", // claimedCartTitle:"Congratulations! Free Gift Won!", // claimedCartSubtitle:"Gift Added to Bag" // } // let drivedSettings = gfg.f.drivedSettings(tmpCartSettings) gfg.settings = cart_settings; gfg.utility.debugConsole("settings assigned") }, updateSettingsBasedOnLanguage: function(){ try { const currentLocale = gfg.utility.getLocale(); // handle MultiLanguage for Free Gift if(gfg.settings.freeGifts && gfg.settings.freeGifts.length > 0){ const allFreeGiftCampaigns = gfg.settings.freeGifts || []; for(let i=0; i 0){ const discounts = gfg.settings.discounts; for(let i=0; i 0){ for(let j=0; j{ try { for(let i=0; i 0){ bundleLinkProductIdMap.set(parseInt(bundleLink.productsForBundleLink[0].productId),{productData:bundleLink.productsForBundleLink[0], bundleId: bundleLink.bundleId}) bundleLinkProductHandleMap.set(bundleLink.productsForBundleLink[0].handle,{productData:bundleLink.productsForBundleLink[0], bundleId: bundleLink.bundleId}) } } return { bundleLinkProductIdMap: bundleLinkProductIdMap, bundleLinkProductHandleMap: bundleLinkProductHandleMap, } }, setSelectors: function(){ let settings = gfg.settings gfg.selectors = { addToCart: settings.app.addToCartBtnSelectors, checkoutBtn : settings.app.checkoutBtnSelectors, sideCartCheckoutBtn: settings.app.sideCartCheckoutBtnSelectors, sideCartSelectors: settings.app.sideCartSelectors, buyNowBtn: settings.app.buyNowBtn, cartForm: settings.app.cartForm, productPageWrapperV2: '.gfgProductPageWrapperV2', cartPageWrapperV2: '.gfgCartPageWrapperV2', quantityBtnSelectors : settings.app.quantityBtnSelectors, cartItemSelectors : settings.app.cartItemSelectors, cartItemRemoveSelectors : settings.app.cartItemRemoveSelectors, cartItemRemoveParentSelectors : settings.app.cartItemRemoveParentSelectors, customCartIntegrationScript : settings.app.customCartIntegrationScript, cartItemQuantityBtnSelectors : settings.app.cartItemQuantityBtnSelectors, } }, setCustomStyling: function (){ let customStyle = gfg.settings.app.customStyle if(customStyle){ var styleSheet = document.createElement("style") styleSheet.innerText = customStyle styleSheet.id="custom-css" styleSheet.setAttribute("data-source-name","gfgFreeGift") document.body.appendChild(styleSheet) } }, getPageType: function () { var pageType = ""; if (window.location.pathname.includes("/cart") && !window.location.pathname.includes("/products")) { pageType = "cart"; } else if (window.location.pathname.includes("/products")) { pageType = "product"; } else if (window.location.pathname.includes("/collections")) { pageType = "COLLECTION"; } else if (window.location.pathname.includes("/")) { pageType = "HOME"; } else if ("undefined" != typeof Shopify && "undefined" != typeof Shopify.Checkout) { pageType = "CHECKOUT"; } else { pageType = "PAGE_NOT_FOUND"; } return pageType; }, addPoweredByBlock: function () { try { const gfgPoweredByLabelBlock = document.createElement("div"); gfgPoweredByLabelBlock.classList.add("gfgPoweredByLabelBlock"); const htmlForPoweredByBlock = gfg.utility.renderPoweredByLabel(); if (!htmlForPoweredByBlock) return; gfgPoweredByLabelBlock.appendChild(htmlForPoweredByBlock); const gfgPageWrappers = document.querySelectorAll(".gfgPageWrapper"); gfgPageWrappers.forEach((element) => { const isVolDiscountWrapperPresentIsEmpty = element.querySelector(".gfgVolDiscountWrapper")?.children.length < 1; const isGftFreeGiftWrapperPresentIsEmpty = element.querySelector(".gftFreeGiftWrapper")?.children.length < 1; const isGfgBogoWrapperIsEmpty = element.querySelector(".gfgBogoWrapper")?.children.length < 1; const isGfgBulkDiscountWidgetHTMLWrapperEmpty = element.querySelector(".gfgBulkDiscountWidgetHTMLWrapper")?.children.length < 1 || element.querySelector(".gfgBulkDiscountWidgetHTML")?.children.length < 1; const isGfgCountDiscountEmpty = element.querySelector(".gfgCountDiscount")?.children.length < 1 ?? true; const isTieredDiscountWrapperEmpty = element.querySelector(".gfgThisIsTieredDiscountOnProductPage")?.children.length < 1 ?? true; let volDiscountWrapperEmpty = isVolDiscountWrapperPresentIsEmpty; if (isGfgBulkDiscountWidgetHTMLWrapperEmpty && isGfgCountDiscountEmpty) { volDiscountWrapperEmpty = true; } if (!isTieredDiscountWrapperEmpty) { volDiscountWrapperEmpty = false; } if ( volDiscountWrapperEmpty && isGftFreeGiftWrapperPresentIsEmpty && isGfgBulkDiscountWidgetHTMLWrapperEmpty && isGfgBogoWrapperIsEmpty ) { const existingBlock = element.querySelector(".gfgPoweredByLabelBlock"); if (existingBlock) existingBlock.remove(); return; } const existingPoweredByBlock = element.querySelector(".gfgPoweredByLabelBlock"); if (!existingPoweredByBlock) { element.appendChild(gfgPoweredByLabelBlock.cloneNode(true)); } else { existingPoweredByBlock.innerHTML = ""; existingPoweredByBlock.appendChild(gfgPoweredByLabelBlock.cloneNode(true)); } }); } catch (error) { gfg.utility.debugConsole("Error in addPoweredByBlock:", error); } }, getProductPageHandle: function () { if ("product" === gfg.state.page_type && window.shopifyLiquidValuesApp7Ext && window.shopifyLiquidValuesApp7Ext.product.handle) { // let pattern = /(?<=\\/products\\/)((?!\\?|\\$).)+/g // if(window && window.location && window.location.href){ // return window.location.href.match(pattern)[0] // } gfg.state.productPageHandle = shopifyLiquidValuesApp7Ext.product.handle return shopifyLiquidValuesApp7Ext.product.handle }else if("product" === gfg.state.page_type && window.location.pathname.includes("/products/")){ const urlRef = Object.fromEntries(new URLSearchParams(window.location)) let productHandle = urlRef.pathname.split("/products/")[1]; if (productHandle && productHandle.includes("?")) { productHandle = productHandle.split("?")[0]; } gfg.state.productPageHandle = productHandle return productHandle } return undefined }, getProductPageId: function () { if(window.shopifyLiquidValuesApp7Ext && window.shopifyLiquidValuesApp7Ext.product.productId){ gfg.state.productId = shopifyLiquidValuesApp7Ext.product.productId; return shopifyLiquidValuesApp7Ext.product.productId; } if (window?.meta && window?.meta?.product && window?.meta?.product?.id) { gfg.state.productPageId = window?.meta?.product?.id return window?.meta?.product?.id } return undefined; }, getSelectedVariant: function () { try { if ("product" === gfg.state.page_type) { let activeCodes = gfg.settings.app.activeVariantCodes; if(activeCodes.indexOf("1") >= 0){ const params = Object.fromEntries(new URLSearchParams(location.search)) if(params && params.variant){ return params.variant } } if(activeCodes.indexOf("2") >= 0){ if (window?.ShopifyAnalytics && window?.ShopifyAnalytics?.meta && window?.ShopifyAnalytics?.meta?.selectedVariantId) { for(let i = 0; i < window?.ShopifyAnalytics?.meta?.product?.variants?.length; i++){ if(window?.ShopifyAnalytics?.meta?.product?.variants[i]?.id == window?.ShopifyAnalytics?.meta?.selectedVariantId){ return window?.ShopifyAnalytics?.meta?.selectedVariantId } } } } if(activeCodes.indexOf("4") >= 0){ if (window?.shopifyLiquidValuesApp7Ext && shopifyLiquidValuesApp7Ext.selected_or_first_available_variant) { return shopifyLiquidValuesApp7Ext.selected_or_first_available_variant.id } } if(activeCodes.indexOf("3") >= 0){ if (document.querySelector('[name="id"]') && document.querySelector('[name="id"]').value) { return document.querySelector('[name="id"]').value } } return undefined } } catch (error) { gfg.utility.debugConsole("error in getSelectedVariant", error); return undefined; } }, getProductQuantity: function () { if (document.querySelector('[name="quantity"]') && document.querySelector('[name="quantity"]').value) { if(Number(document.querySelector('[name="quantity"]').value)){ return Number(document.querySelector('[name="quantity"]').value) }else{ return 1 } }else { return 1 } }, getElements: function (settings) { return { addToCartBtn: document.querySelector(gfg.selectors.addToCart), addToCartButtonCloned: undefined, checkoutBtn: document.querySelectorAll(gfg.selectors.checkoutBtn), cartForm: document.querySelectorAll(gfg.selectors.cartForm), productPageWrapperV2: gfg.utility.getWrapperSkeleton("PRODUCT_PAGE"), cartPageWrapperV2: gfg.utility.getWrapperSkeleton("CART_PAGE"), buyNowBtn: document.querySelector(gfg.selectors.buyNowBtn), quantityBtn: gfg.selectors.quantityBtnSelectors, cartDrawer: document.querySelector(gfg.selectors.sideCartSelectors), } }, initialize: async function () { let tmpCartSettings; if(window && window?.kite_app_data && window?.kite_app_data?.userData) { tmpCartSettings = window.kite_app_data } else { tmpCartSettings = await gfg.f.getSettings(); } gfg.f.consoleAdvertisement(); gfg.f.setSettings(tmpCartSettings) gfg.f.updateSettingsBasedOnLanguage(); gfg.f.setSelectors() gfg.f.applyImpFileCssStyling(); gfg.f.setCustomStyling() gfg.state.page_type = gfg.f.getPageType(); gfg.elements = gfg.f.getElements(gfg.settings); if ("" === gfg.state.page_type) return false; gfg.utility.setLanguageLocale(); return gfg.f.bootstrap(gfg.settings); }, globalListener : async function (settings) { let isIntervalActive = false //if app is disabled reurn if(gfg.state && gfg.state.activeCampaignName == "EMPTY"){ gfg.utility.getUrlRewardCampaignName() } if(gfg.state && gfg.state.activeCustomerData == "EMPTY"){ await gfg.utility.setCustomerSpecificData(); // check conditioin and update cart attribute gfg.utility.updateCartAttributeWithCustomerData(); } try{ if (settings.app.disableApp) { return } else { gfg.utility.debugConsole('inside else of global listener') //setTIMOUT FOR API CALLS // setTimeout(() => { if (gfg.settings.app.disableApiCallListen == false) { try{ gfg.utility.listenForApiCalls(settings) // gfg.utility.listenForAjaxApiCalls(settings) gfg.utility.listenForXmlHttpApiCalls(settings) }catch(error) { // debugConsole gfg.utility.debugConsole("error in listenForApiCalls", error) } } else { gfg.utility.debugConsole("listenForApiCalls disabled") // not listening for api calls } // gfg.utility.listenForFormSubmits(); // gfg.utility.interceptFetchRequest() // gfg.utility.interceptXMLHttpRequest() // }, 800); gfg.utility.checkGfgDebugMode(); if ("product" === gfg.state.page_type) { gfg.productPage.init(settings); } if (settings.app.disableSideCart) { if ("cart" === gfg.state.page_type) { gfg.cartPage.init(settings) } } else { gfg.cartPage.init(settings) } } let runProcessFreeGiftCount = 0; setInterval(async () => { if (!isIntervalActive) { // gfg.utility.debugConsole("gfg-globalListener-active") isIntervalActive = true // gfg.gfgVolDiscount.actions.handleQuantityUpdate(); gfg.gfgVolDiscount.actions.listenQuantityUpdates(); gfg.gfgVolDiscount.f.listenVariantChangeForVolDiscountProductPage(); if(settings.app.enablingApiFromSetInterval || settings.app.disableApiCallListen){ // if (url.includes('app=gfgfreegift')) { // return ; // } // var cartData = undefined; // if (cartData) { // gfg.state.cartData = cartData; // } else { // gfg.state.cartData = await gfg.utility.getCart(); // } // gfg.gfgFreeGift.f.checkForFreeGift(cartData) await gfg.utility.callchecksAfterApiCalls() } await gfg.utility.syncRewardCampaignName(); let productPageWrapperInserted = false; let cartPageWrapperInserted = false; if ("product" === gfg.state.page_type && gfg.elements.addToCartBtn && document.querySelectorAll(gfg.selectors.productPageWrapperV2).length == 0) { gfg.utility.debugConsole("productPage-insertWrapperIntoPage1") gfg.productPage.f.insertWrapperIntoPage(settings) productPageWrapperInserted = true; } let checkoutBtnEle = document.querySelectorAll(gfg.selectors.checkoutBtn) // insert cartPage wrapper if cartPage is initialized if (checkoutBtnEle.length > 0 && document.querySelectorAll(gfg.selectors.cartPageWrapperV2).length == 0) { gfg.utility.debugConsole("cartPage-insertWrapperIntoPage") gfg.cartPage.f.insertWrapperIntoPage(settings); cartPageWrapperInserted = true; } gfg.cartPage.f.insertSideCartWrappersIntoPage(settings); // handle shipping discount reinitialization if((productPageWrapperInserted || cartPageWrapperInserted) && gfg.state?.shouldInitShippingDiscountAgain && gfgShippingDiscountV2){ gfg.state.shouldInitShippingDiscountAgain = false; gfgShippingDiscountV2.init(); } // handle unified widget(goal based) discount reinitialization if((productPageWrapperInserted || cartPageWrapperInserted) && gfg.state?.shouldInitUnifiedDiscountAgain){ gfg.state.shouldInitUnifiedDiscountAgain = false; gfg.gfgUnifiedWidget.init(gfg.settings , "PRODUCT_PAGE"); gfg.gfgUnifiedWidget.init(gfg.settings , "CART_PAGE"); } let _cartPageWrapper = document.querySelector(gfg.selectors.cartPageWrapperV2); let isGftFreeGiftWrapperEmpty = _cartPageWrapper?.querySelector('.gftFreeGiftWrapper'); //runProcessFreeGiftCount if(isGftFreeGiftWrapperEmpty?.hasChildNodes() && checkoutBtnEle.length > 0 && runProcessFreeGiftCount == 0){ // if(isGftFreeGiftWrapperEmpty.length < 1 && checkoutBtnEle.length > 0 && runProcessFreeGiftCount == 0){ runProcessFreeGiftCount = 1; gfg.utility.debugConsole("running process free gift") gfg.utility.debugConsole("runProcessFreeGiftCount") // await gfg.utility.callchecksAfterApiCalls() // // await gfg.gfgFreeGift.f.processFreeGift(); // await gfg.gfgFreeGift.checkForFreeGift(); await gfg.gfgFreeGift.f.checkForFreeGift(); // if (localStorage.getItem("runForceFully") == "true") { // setTimeout(async () => { // await gfg.gfgFreeGift.f.processFreeGift(); // }, 1000); // } } // Select the button let gfgFreeGiftMsgRowButton = document.querySelectorAll(".gfgFreeGiftMsgRowButton"); if (gfgFreeGiftMsgRowButton && gfgFreeGiftMsgRowButton.length == 1 && gfg.state.gfgFreeGiftMsgRowButton === false) { gfg.state.gfgFreeGiftMsgRowButton = truncate; // Assuming truncate is defined elsewhere gfg.utility.debugConsole("gfgFreeGiftMsgRowButton click behavior"); // Add event listener for 'click' event document.querySelector(".gfgFreeGiftMsgRowButton").addEventListener('click', function(e) { gfg.utility.debugConsole("button clicked"); // Select the message row let gfgFreeGiftMsg = document.querySelector(".gfgFreeGiftMsgRow"); // Check if the element exists and toggle its display style if (gfgFreeGiftMsg) { gfgFreeGiftMsg.style.display = gfgFreeGiftMsg.style.display === "none" ? "block" : "none"; } }); } isIntervalActive = false } }, 1000) }catch(error){ gfg.utility.debugConsole("globalListenerError" , error) } }, executeCustomScriptOnLoadFn: function(){ try { const customScript = gfg.settings.app.executeCustomScriptOnLoad; if(customScript){ eval(customScript); } } catch (error) { gfg.utility.debugConsole("error in executeCustomScriptOnLoadFn", error); } }, checkIfVisitingFromCountryRequiredForFreeGift: function() { try { const allFreeGiftCampaigns = gfg.settings.freeGifts || []; for (let i = 0; i < allFreeGiftCampaigns.length; i++) { const freeGiftData = allFreeGiftCampaigns[i]; const freeGiftEligibilityRules = freeGiftData?.conditionsData?.conditionsList || []; for (let i = 0; i < freeGiftEligibilityRules.length; i++) { const rule = freeGiftEligibilityRules[i]; if (rule?.ruleType === "countrySelects") { return true; } } } return false; } catch (error) { gfg.utility.debugConsole("error in checkIfVisitingCountryRequiredForFreeGift fn", error); } }, checkIfVisitingFromCountryRequiredForDiscount: function() { try { const discountData = gfg.settings.discounts; for (let i = 0; i < discountData.length; i++) { const discount = discountData[i]; const discountEligibilityRules = discount?.conditionsData?.conditionsList || []; for (let j = 0; j < discountEligibilityRules.length; j++) { const rule = discountEligibilityRules[j]; if (rule?.ruleType === "countrySelects") { return true; } } } return false; } catch (error) { gfg.utility.debugConsole("error in checkIfVisitingFromCountryRequiredForDiscount fn", error); } }, checkIfVisitingFromCountryRequired: function(){ try { let isVisitingFromCountryRequired = false; const isVisitingFromCountryRequiredForFreeGift = gfg.f.checkIfVisitingFromCountryRequiredForFreeGift(); let isVisitingFromCountryRequiredForDiscount; // for vol/tiered/buy x for y amt // if free gift is not required to be shown based on country, then only check for discounts if(!isVisitingFromCountryRequiredForFreeGift){ isVisitingFromCountryRequiredForDiscount = gfg.f.checkIfVisitingFromCountryRequiredForDiscount(); } // if either of the free gift or discount requires visiting from country, then set it to true if(isVisitingFromCountryRequiredForFreeGift || isVisitingFromCountryRequiredForDiscount){ isVisitingFromCountryRequired = true; } return isVisitingFromCountryRequired; } catch (error) { gfg.utility.debugConsole("error in checkIfVisitingFromCountryRequired fn", error); } }, applyImpFileCssStyling: function() { try { const maxIntervalCount = 10; let counter = 0; const intervalId = setInterval(() => { if (counter > maxIntervalCount) { clearInterval(intervalId); return; } counter++; const slideCartAppSelector = document.querySelectorAll("#slidecarthq, .slidecarthq"); const condition1 = slideCartAppSelector.length > 1; // both selectors are present const condition2 = window && !window?.location?.pathname?.includes("/cart"); if (!condition1 || !condition2) { return; } const cssFilePath = 'https://free-gift-app7.s3.us-east-2.amazonaws.com/Storefront/freeGiftLogicv1Imp.css'; fetch(cssFilePath) .then(response => response.text()) .then(cssContent => { const styleTag = document.createElement('style'); styleTag.type = 'text/css'; styleTag.id = "freeGiftLogicv1Imp"; styleTag.setAttribute('data-source-name',"gfgFreeGift"); if (styleTag.styleSheet) { styleTag.styleSheet.cssText = cssContent; } else { styleTag.appendChild(document.createTextNode(cssContent)); } document.head.appendChild(styleTag); gfg.f.setCustomStyling(); clearInterval(intervalId); // clear interval once css is successfully applied }) .catch(error => { gfg.utility.debugConsole("error in applyImpFileCssStyling fn", error); }); }, 1000); } catch (error) { gfg.utility.debugConsole("error in applyImpFileCssStyling fn", error); } }, handleSkaiLamaSideCartUpdate: async function (data) { try { let success = false; let cartData = data // Initial cart.js call try { if(!cartData){ const response = await fetch("/cart.js?app=gfgfreegift"); cartData = await response.json(); } } catch (error) { gfg.utility.debugConsole("Error fetching cart data:", error); return false; } try { window.Rebuy.Cart.init(); window.Rebuy.SmartCart.show(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole('Error initializing and showing Rebuy Cart:', error); } // Case 17 try { smeCartCall(0); // or smeCartCall(1); window.openSmeCart(); success = true; return success; } catch (error) { gfg.utility.debugConsole('Error calling and opening Cart upsell slide cart drawer:', error); success = false; } try { window.SLIDECART_UPDATE(); window.SLIDECART_OPEN(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole('Error calling and opening Cart upsell slide cart drawer:', error); } //not working // if (document.querySelector('.easy-slide-cart') && document.querySelector('.slide-cart-body') && typeof CustomEvent === 'function') { // try { // setTimeout(()=>{ // window.dispatchEvent(new CustomEvent("SLIDECARTY:refresh")); // window.dispatchEvent(new CustomEvent("SLIDECARTY:open")); // success = true; // return success; // }, 400) // } catch (error) { // gfg.utility.debugConsole('Error refreshing and opening Slide Carty:', error); // success = false; // } // } if (typeof refreshCart == 'function') { try { window.SLIDECART_UPDATE(); success = true; return success; } catch (error) { try { refreshCart(cartData); } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } } if (typeof window.SLIDECART_UPDATE === "function") { try { window.SLIDECART_UPDATE(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (typeof window.fcsb !== "undefined" && typeof window.fcsb.openMiniCart === "function" && typeof window.fcsb.fetchCart === "function") { try { window.fcsb.fetchCart(); setTimeout(() => { window.fcsb.openMiniCart(); }, 500); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (typeof triggerCartOpen === "function") { try { triggerCartOpen(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (document.querySelector('#offcanvas-cart')) { try { bootstrap.Offcanvas.getOrCreateInstance('#offcanvas-cart').show(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (typeof window.theme !== "undefined" && typeof window.theme.ajaxCart !== "undefined" && typeof window.theme.ajaxCart.update === "function") { try { window.theme.ajaxCart.update(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (typeof window.icartCartActivityEvent === "function") { try { window.icartCartActivityEvent(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } try { document.dispatchEvent(new CustomEvent("theme:popup:open")) } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", e) } try { document.dispatchEvent(new Event("theme:popup:open")) } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", e) } try { document.dispatchEvent(new Event("theme:cart:update")) } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", e) } try { document.dispatchEvent(new Event("theme:drawer:open")) } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", e) } try { document.dispatchEvent(new CustomEvent("theme:cart:update")) } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", e) } try { document.dispatchEvent(new CustomEvent("theme:drawer:open")) } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", e) } try { document.dispatchEvent(new CustomEvent("cart:refresh")) } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", e) } try { document.dispatchEvent(new Event("cart:refresh")) } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", e) } try { document.dispatchEvent(new CustomEvent('cart:build')); } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", e) } try { document.dispatchEvent(new CustomEvent('obsidian:upsell:refresh')); document.dispatchEvent(new CustomEvent('obsidian:upsell:open')); } catch (e) { success = false; gfg.utility.debugConsole("Error while updating cart", e) } try { document.documentElement.dispatchEvent(new CustomEvent("cart:refresh", { bubbles: true })); } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } if (typeof window.HsCartDrawer !== "undefined" && typeof window.HsCartDrawer.updateSlideCart === "function") { globalDebounce("hscartdrawer", function() { try { window.HsCartDrawer.updateSlideCart(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } }, 100); } if (typeof window.HS_SLIDE_CART_OPEN !== "undefined" && typeof window.HS_SLIDE_CART_OPEN === "function") { globalDebounce("hscartdraweropen", function() { try { window.HS_SLIDE_CART_OPEN(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } }, 100); } if (typeof theme !== "undefined" && typeof theme.Cart !== "undefined" && typeof theme.Cart.updateCart === "function") { try { theme.Cart.updateCart(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (typeof window.updateMiniCartContents === "function") { try { window.updateMiniCartContents(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (typeof window.loadEgCartDrawer === "function") { try { window.loadEgCartDrawer(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } try { document.dispatchEvent(new CustomEvent("cart:build")); } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } try { document.dispatchEvent(new CustomEvent("cart:open")); } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } // try // { // document.documentElement.dispatchEvent(new CustomEvent("product:added", // { // bubbles: true, // detail: // { // source: "N9_Upsells", // quantity: 1 // } // })); // } // catch (error) // { // success = false; // gfg.utility.debugConsole("Error while updating cart", error); // } try { if (typeof window.cart !== "undefined" && typeof window.cart.getCart !== "undefined" && typeof window.cart.openCartDropdown !== "undefined") { window.cart.getCart(); window.cart.openCartDropdown(); success = true; return success; } } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } try { if (typeof window.ajaxCart !== "undefined") { window.ajaxCart.load(); success = true; return success; } } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } try { document.dispatchEvent(new CustomEvent("obsidian:upsell:refresh")); document.dispatchEvent(new CustomEvent("obsidian:upsell:open")); } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } let tn9 = document.getElementById("site-cart"); if (tn9 !== null) { try { tn9.show(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (typeof CartJS !== "undefined" && typeof CartJS.getCart === "function") { try { CartJS.getCart(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (typeof window.SLIDECART_OPEN !== "undefined") { setTimeout(function() { try { window.SLIDECART_OPEN(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } }, 500); } if (typeof Shopify !== "undefined" && typeof Shopify.theme !== "undefined" && typeof Shopify.theme.jsAjaxCart !== "undefined" && typeof Shopify.theme.jsAjaxCart.updateView === "function") { try { Shopify.theme.jsAjaxCart.updateView(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (typeof window.theme !== "undefined" && typeof window.theme.MiniCart !== "undefined" && typeof window.theme.MiniCart.update === "function") { try { theme.MiniCart.update(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } } if (typeof window.openCart !== "undefined" && typeof window.monster_setCartItems !== "undefined") { try { window.openCart(); window.monster_setCartItems(cartData.items); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.Shopify !== "undefined" && typeof window.Shopify.onCartUpdate === "function") { try { window.Shopify.onCartUpdate(); if (Shopify.onCartUpdate.toString().indexOf('There are now') === -1) { window.Shopify.onCartUpdate(cartData, true); success = true; return success; } } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof slate !== 'undefined' && typeof slate.cart !== 'undefined' && typeof slate.cart.updateCart == 'function') { try { slate.cart.updateCart(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof Shopify !== 'undefined' && typeof Shopify.updateQuickCart !== 'undefined') { try { Shopify.updateQuickCart(cartData); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof bcActionList !== 'undefined' && typeof bcActionList.atcBuildMiniCartSlideTemplate === 'function') { try { bcActionList.atcBuildMiniCartSlideTemplate(cartData); if (typeof openMiniCart === 'function') { openMiniCart(); success = true; return success; } } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.SATCB !== 'undefined' && typeof window.SATCB.Helpers !== 'undefined' && typeof window.SATCB.Helpers.openCartSlider === 'function') { try { setTimeout(function() { window.SATCB.Helpers.openCartSlider(); }, 500); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof Shopify !== 'undefined' && typeof Shopify.updateCartInfo !== 'undefined' && document.querySelectorAll('.top-cart-holder .cart-target form .cart-info .cart-content').length > 0) { try { Shopify.updateCartInfo(cartData, '.top-cart-holder .cart-target form .cart-info .cart-content'); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } try { let event = new CustomEvent("wetheme-toggle-right-drawer", { detail: { type: 'cart', forceOpen: undefined, params: { cart: cartData }, }, }); document.documentElement.dispatchEvent(event); } catch (error) { success = false; gfg.utility.debugConsole(error); } if (typeof window.vndHlp !== 'undefined' && typeof window.vndHlp.refreshCart === 'function') { try { window.vndHlp.refreshCart(cartData); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.renderCart === 'function') { try { window.renderCart(cartData); if (cartData.items.length > 0) { let cart = document.querySelector('.mini-cart.is-empty'); if (cart !== null) { cart.classList.remove('is-empty'); } } success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } try { document.dispatchEvent(new CustomEvent('theme:cart:change', { detail: { cart: cartData, cartCount: cartData.item_count }, bubbles: true })) } catch (error) { success = false; gfg.utility.debugConsole(error); } if (typeof window.cartStore !== 'undefined' && typeof window.cartStore.setState === 'function') { try { window.cartStore.setState( { justAdded: {}, popupActive: true, item_count: cartData.item_count, items: cartData.items, cart: cartData }); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof theme !== 'undefined' && typeof theme.Cart !== 'undefined' && typeof theme.Cart.setCurrentData === 'function') { try { theme.Cart.setCurrentData(cartData); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.halo !== 'undefined' && typeof window.halo.updateSidebarCart === 'function') { try { window.halo.updateSidebarCart(cartData); let sideBarCartIcon = document.querySelector('[cartData-cart-sidebar]'); if (sideBarCartIcon !== null) { sideBarCartIcon.click(); } success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.Shopify !== 'undefined' && typeof window.Shopify.theme !== 'undefined' && typeof window.Shopify.theme.ajaxCart !== 'undefined' && typeof window.Shopify.theme.ajaxCart.updateView === 'function') { try { Shopify.theme.ajaxCart.updateView( { cart_url: '/cart' }, cartData); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.theme !== 'undefined' && typeof window.theme.cart !== 'undefined' && typeof window.theme.cart.updateAllHtml === 'function') { try { window.theme.cart.updateAllHtml(); window.theme.cart.updateTotals(cartData); document.querySelector('.header--cart-toggle').click(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof monster_setCartItems === 'function') { try { monster_setCartItems(cartData.items); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.refreshCartContents !== 'undefined') { try { window.refreshCartContents(cartData); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } try { let miniCartOuterbox = document.querySelector('.minicart__outerbox'); if (miniCartOuterbox !== null && typeof window.cartContentUpdate === 'function') { sectionsToRender = miniCartOuterbox.dataset.section; fetch('/cart?sections=' + sectionsToRender, { method: 'GET', cache: 'no-cache', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' } }).then(function(sectionsData) { try { return sectionsData.clone().json().then(function(p) { cartData.sections = p; window.cartContentUpdate(cartData, miniCartOuterbox, sectionsToRender); }); success = true; return success; } catch (e) { success = false; gfg.utility.debugConsole(e); } }); } } catch (error) { success = false; gfg.utility.debugConsole(error); } if (document.querySelectorAll('.sp-cart .sp-dropdown-toggle').length > 0 && typeof Shopify !== 'undefined' && typeof Shopify.getCart === 'function') { try { Shopify.getCart(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } try { let cartDrawerForm = document.querySelector('form.cart-drawer'); if (cartDrawerForm !== null) { let cartDrawerInputs = document.querySelectorAll('.cart-drawer input'); if (cartDrawerInputs.length > 0) { cartDrawerInputs[0].dispatchEvent(new Event('blur')); setTimeout(function() { cartDrawerInputs[0].dispatchEvent(new Event('input')); }, 350); success = true; return success; } } } catch (error) { success = false; gfg.utility.debugConsole(error); } try { let cartDrawer = document.querySelector('m-cart-drawer'); if (cartDrawer !== null && typeof cartDrawer.onCartDrawerUpdate === 'function') { cartDrawer.onCartDrawerUpdate(); if (typeof cartDrawer.open === 'function') { cartDrawer.open(); } success = true; return success; } } catch (error) { success = false; gfg.utility.debugConsole(error); } let siteCart = document.getElementById('site-cart'); if (siteCart !== null) { try { siteCart.show(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.CD_REFRESHCART !== 'undefined') { try { window.CD_REFRESHCART(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.CD_OPENCART !== 'undefined') { setTimeout(function() { try { window.CD_OPENCART(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } }, 500); } if (typeof window.buildCart === 'function') { try { window.buildCart(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.PXUTheme !== 'undefined' && typeof window.PXUTheme.jsAjaxCart !== 'undefined' && typeof window.PXUTheme.jsAjaxCart.updateView === 'function') { try { window.PXUTheme.jsAjaxCart.updateView(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } if (typeof window.theme !== 'undefined' && typeof window.theme.addedToCartHandler === 'function') { try { window.theme.addedToCartHandler(cartData); success = true; return success; } catch (error) { //success = false; gfg.utility.debugConsole(error); } } try { let event = new Event('tcustomizer-event-cart-change'); document.dispatchEvent(event); } catch (error) { success = false; gfg.utility.debugConsole(error); } try { let event = new CustomEvent('apps:product-added-to-cart'); document.dispatchEvent(event); } catch (error) { success = false; gfg.utility.debugConsole(error); } try { document.dispatchEvent(new CustomEvent("cart:refresh:opend")); } catch (error) { success = false; gfg.utility.debugConsole(error); } try { document.dispatchEvent(new CustomEvent('dispatch:cart-drawer:refresh', { bubbles: true })); setTimeout(function() { document.dispatchEvent(new CustomEvent('dispatch:cart-drawer:open')); }, 500); } catch (error) { success = false; gfg.utility.debugConsole(error); } if (typeof window.theme !== 'undefined' && typeof window.theme.updateCartSummaries === 'function') { try { window.theme.updateCartSummaries(); success = true; return success; } catch (error) { success = false; gfg.utility.debugConsole(error); } } try { let cartNotification = document.querySelector("cart-notification") || document.querySelector("cart-drawer"); if (cartNotification && typeof cartNotification.renderContents === "function") { const sectionsResponse = await fetch("/cart?sections=cart-notification-product,cart-notification-button,cart-icon-bubble,cart-drawer,cart-notification-content", { method: "GET", cache: "no-cache", credentials: "same-origin", headers: { "Content-Type": "application/json" } }); const sectionsData = await sectionsResponse.json(); if (cartData && cartData.item_count) { let renderData = { sections: sectionsData, key: cartData.items[0] && cartData.items[0].key }; cartNotification.renderContents(renderData); } else { const cartCountBubble = document.querySelector(".cart-count-bubble"); if (cartCountBubble) cartCountBubble.remove(); } let cartDrawerElement = document.querySelector("cart-drawer"); if (cartDrawerElement && cartDrawerElement.classList.contains('is-empty') && cartData.items.length != 0) { cartDrawerElement.classList.remove('is-empty'); } success = true; return success; gfg.utility.debugConsole("Case 1 executed"); return "REFRESH"; } } catch (error) { success = false; gfg.utility.debugConsole(error); } try { window.dispatchEvent(new Event("update_cart")); } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } try { let kaktusc = document.querySelector("#kaktusc-app"); let icon_buble = document.querySelector("#cart-icon-bubble"); if (kaktusc !== null) { if (icon_buble !== null) icon_buble.click(); } } catch (error) { success = false; gfg.utility.debugConsole("Error while updating cart", error); } return success; // If no case matches or executes successfully gfg.utility.debugConsole("No matching cart update method found or executed successfully"); return false; } catch (error) { gfg.utility.debugError("error in handleSkaiLamaSideCartUpdate. ", error); return false; } }, cutOffshouldInitAgainConditionsForUnifiedAndShipping: function () { try { /*we are using this function to eliminate that shouldInitAgain conditions we added earlier to solve side cart widget behaviour problem in shipping discount and unified widget for 3-4 customers. This is being called infinitely sometimes for customers which is a bad practice.*/ /* As we haved added side cart selectors features, I guess that should solve this problem for new customers */ const oldCustomerCutoffDate = new Date("2024-11-27"); const userCreatedAt = new Date(gfg.settings.merchantInfo.createdAt); if(userCreatedAt > oldCustomerCutoffDate){ return true; } return false; } catch (error) { gfg.utility.debugError("error in cutOffshouldInitAgainConditionsForUnifiedAndShipping:", error); return false; } }, consoleAdvertisement: function() { try { setTimeout(()=>{ const shouldShowAdvertisement = gfg?.settings?.app?.showConsoleAdvertisement; if(shouldShowAdvertisement){ let appLink = "https://r.skailama.com/kite-install-CM/"; let appMessage = "Kite - All-in-one discount & free gift app:"; let textStyle = "font-weight: 600; color: black; font-size: 14px;"; let linkStyle = "font-weight: normal; color: #007BFF; text-decoration: underline; cursor: pointer; font-size: 14px;"; console.log(`%c${appMessage} %c${appLink}`, textStyle, linkStyle); } },4000); } catch (error) { gfg.utility.debugConsole("error in consoleAdvertisement", error); } }, freeGiftDataTransformation: function (campaigns = []) { const transformedCampaigns = JSON.parse(JSON.stringify(campaigns)); try { for (let i = 0; i < transformedCampaigns.length; i++) { const campaignData = transformedCampaigns[i]; const rulesList = campaignData.rulesList; for (let j = 0; j < rulesList.length; j++) { const ruleData = rulesList[j]; ruleData.ruleId = ruleData.ruleType + `_${j}`; } } } catch (error) { gfg.utility.debugConsole("error in freeGiftDataTransformation", error); } finally{ return transformedCampaigns; } } }, utility: { getLocale: function () { if (window.Shopify && window.Shopify.locale) { return window.Shopify.locale }else{ return "en" } }, setLanguageLocale: function () { let locale = gfg.utility.getLocale() if(gfg.settings.languageData && gfg.settings.languageData.languageMode == "SINGLE"){ locale = "en" } if(!gfg.settings.languageData[locale]){ locale = "en" } gfg.settings.languageData = gfg.settings.languageData[locale] }, getUrlRewardCampaignName: function () { let activeCampaignName = ""; if(gfg.state.activeCampaignName != "EMPTY"){ return gfg.state.activeCampaignName; } let campaginString = gfg.settings?.urlSearchString.split("kite_campaign=") if(campaginString && campaginString.length > 1){ let campaignName = campaginString[1].split("&")[0] if(campaignName){ gfg.state.activeCampaignName = campaignName; sessionStorage.setItem("kite_campaign", campaignName) return campaignName }else{ return "" } } if(sessionStorage.getItem("kite_campaign")){ activeCampaignName = sessionStorage.getItem("kite_campaign") gfg.state.activeCampaignName = activeCampaignName; return activeCampaignName; } return ""; }, syncRewardCampaignName: async function (){ if (gfg.state.activeCampaignName != "" && gfg.state.activeCampaignName != "EMPTY") { let urlRewardCampaignName = gfg.state.activeCampaignName; // let rewardCampaign = gfg.settings.discounts.find((campaign) => { // let campaignData = JSON.parse(campaign); // return campaignData.urlBasedCampaign && campaignData.urlBasedCampaign.value && campaignData.urlBasedCampaign.value == urlRewardCampaignName; // }); // gfg.settings.rewardCampaigns = rewardCampaign; if (!gfg.state.setCampaignUrlattribute) { gfg.state.setCampaignUrlattribute = true; await gfg.utility.updateCart({ attributes: { kite_campaign: gfg.state.activeCampaignName } }); } } return; }, getDate: function (date) { let d = new Date(date); let month = "" + (d.getMonth() + 1); let day = "" + d.getDate(); let year = d.getFullYear(); if (month.length < 2) month = "0" + month; if (day.length < 2) day = "0" + day; return [year, month, day].join("-"); }, addToCart: async function (data) { try { const url = "/cart/add.js?app=gfgfreegift"; const options = { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(data) }; const response = await fetch(url, options); if (!response.ok) { throw new Error('Network response was not ok'); } const result = await response.json(); return true; } catch (error) { gfg.utility.debugError("gfg-utility-addToCart"); gfg.utility.debugError(error); return false } }, updateCart: async function (data) { try { const url = "/cart/update.js?app=gfgfreegift"; const options = { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(data) }; const response = await fetch(url, options); if (!response.ok) { throw new Error('Network response was not ok'); } const result = await response.json(); return result; } catch (error) { gfg.utility.debugError("gfg-utility-updateCart"); gfg.utility.debugError(error); return false } }, changeCart: async function (data) { try { const url = "/cart/change.js?app=gfgfreegift"; const options = { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(data) }; const response = await fetch(url, options); if (!response.ok) { throw new Error('Network response was not ok'); } const result = await response.json(); return true } catch (error) { gfg.utility.debugError("gfg-utility-changeCart"); gfg.utility.debugError(error); return false } }, getProductDataV2: function (productName) { try { let languageValue = window?.Shopify?.routes?.root ? window.Shopify.routes.root : "/"; return new Promise(async(res, rej) => { if(gfg.settings.app?.productHandlesAreTranslated){ const productTranslateHandle = await gfg.utility.getProductTranslatedHandle(productName, languageValue); if(productTranslateHandle && productTranslateHandle != ""){ productName = productTranslateHandle; } } // fetch product data fetch(languageValue + "products/" + productName + ".js?app=gfgfreegift") .then(response => response.json()) .then(product => { gfg.utility.debugConsole("success-productName: ", productName) res(product) }) .catch(error => { gfg.utility.debugConsole("fail-productName: ", productName); res(false); }) }); } catch (error) { gfg.utility.debugError("gfg-utility-getProductDataV2"); gfg.utility.debugError(error); return false } }, addToCartV2: function (data) { try { const isKiteUniqueIdRequired = gfg.settings.app?.isKiteUniqueIdRequired; if(isKiteUniqueIdRequired){ const itemsWithUniqueIds = gfg.utility.appendKiteUniqueIdToItemsProperty(data.items); data = {items: itemsWithUniqueIds}; } return new Promise((res, rej) => { fetch("/cart/add.js?app=gfgfreegift", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(data) }).then(response => { gfg.utility.debugConsole("success-/cart/add.js"); res(true); }).catch(error => { gfg.utility.debugConsole("fail-/cart/add.js"); res(false); }) }) return result; } catch (error) { gfg.utility.debugError("gfg-utility-addToCartV2"); gfg.utility.debugError(error); return false } }, clearCart: function (data) { try { return new Promise(async(res, rej) => { fetch("/cart/clear.js?app=gfgfreegift", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(data) }).then(response => { gfg.utility.debugConsole("success-/cart/clear.js"); res(true); }).catch(error => { gfg.utility.debugConsole("fail-/cart/clear.js"); res(false); }) }) return result; } catch (error) { gfg.utility.debugError("gfg-utility-clearCart"); gfg.utility.debugError(error); return false } }, getCart: async function (data) { try { const url = "/cart.js?app=gfgfreegift"; const response = await fetch(url); const result = await response.json(); gfg.utility.refreshFreeGiftCartData(result) return result } catch (error) { gfg.utility.debugError("gfg-utility-getCart"); gfg.utility.debugError(error); return false } }, isCartEmpty: function () { if (gfg.state.cartData && gfg.state.cartData.items.length <= 0) { return true; } else { return false } }, cloneAddToCartBtn: function () { }, renderLanguageValue: function (parent) { if (parent){ return parent.value; } return; }, slider: { state: { slideIndex: 0, }, }, isMobileView: function () { if (window.innerWidth < 768) { return true; } else { return false; } }, updateCart: async function (cartData) { try { const url = "/cart/update.js?app=gfgfreegift"; const options = { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(cartData) }; const response = await fetch(url, options); const result = await response.json(); return result; } catch (error) { gfg.utility.debugConsole("error in shopifyUtility.updateCart", error) // throw error return false } }, getCurrencySymbol: function () { if (window && window.Shopify && window.Shopify.currency && window.Shopify.currency.active) { // let symbol = gfg.settings.merchantInfo.multipleCurrenciesInfo[window.Shopify.currency.active]?.symbol || Shopify.currency.active; let symbol = gfg.settings.merchantInfo.multipleCurrenciesInfo[window.Shopify.currency.active]?.symbol || CURRENCY_SYMBOLS[window.Shopify.currency.active] || Shopify.currency.active; return symbol; } }, getActiveCurrencyRate : function(){ let currencyRate = 1; if(window.Shopify && window.Shopify.currency && window.Shopify.currency.rate){ currencyRate = window.Shopify.currency.rate; } return currencyRate; }, getAmountInActiveCurrency: function (amount) { if(!amount || amount == "" || amount == null || amount == undefined) { return 0; } if(window && window.Shopify && window.Shopify.currency && window.Shopify.currency.rate) { let rate = window.Shopify.currency.rate; if(rate == "1.0") { return amount; }else{ return parseFloat(parseFloat(amount) * parseFloat(rate)).toFixed(2); } } }, checkIfBrandingShouldBeVisible: function (type) { try { const isVolDiscountWrapperEmpty = document.querySelector(".gfgVolDiscountWrapper")?.children.length < 1; const isFreeGiftWrapperEmpty = document.querySelector(".gftFreeGiftWrapper")?.children.length < 1; const isBulkDiscountWrapperEmpty = document.querySelector(".gfgBulkDiscountWidgetHTMLWrapper")?.children.length < 1; const isBogoWrapperEmpty = document.querySelector(".gfgBogoWrapper")?.children.length < 1; if (isVolDiscountWrapperEmpty && isFreeGiftWrapperEmpty && isBulkDiscountWrapperEmpty && isBogoWrapperEmpty) { return false; } const merchantInfo = gfg.settings?.merchantInfo; if (!merchantInfo?.isSubscription || !merchantInfo?.isSubscription.name) { return true; } if ( merchantInfo.isSubscription?.name?.includes("Free") && (!type || type !== "checkout") ) { return true; } return false; } catch (err) { gfg.utility.debugConsole("Error in checkIfBrandingShouldBeVisible:", err); return true; } }, renderPoweredByLabel: function() { if (false && gfg.utility.checkIfBrandingShouldBeVisible()) { let brandingLink = "https://apps.shopify.com/kite-free-gift"; const appInstalledDate = gfg?.settings?.merchantInfo?.createdAt; const startDate = new Date("2024-09-01"); const endDate = new Date("2024-09-30"); if (appInstalledDate && new Date(appInstalledDate) >= startDate && new Date(appInstalledDate) <= endDate) { brandingLink = "https://www.skailama.com/app/kite"; } const gfgPoweredByLabel = document.createElement("a"); gfgPoweredByLabel.href = brandingLink; gfgPoweredByLabel.target = "_blank"; gfgPoweredByLabel.style.cssText = "text-align:end; display:block; color:black; font-size:14px; text-decoration:none;"; gfgPoweredByLabel.textContent = "✨Powered By Kite✨"; return gfgPoweredByLabel; } else { return null; } }, formatPrice: function (price) { try { if (window && window.Shopify && window.Shopify.currency && window.Shopify.currency.active) { //find the currency symbol from gfg.settings.merchantInfo.multipleCurrencies[window.Shopify.currency.active] get the symbol let currencySymbol = gfg.utility.getCurrencySymbol(); return currencySymbol + "" + parseFloat(price / 100).toFixed(2) } } catch(err) { gfg.utility.debugConsole(err); } }, formatPriceWithoutSymbol: function (price) { if (window && window.Shopify && window.Shopify.currency && window.Shopify.currency.active) { //find the currency symbol from gbb.settings.merchantInfo.multipleCurrencies[window.Shopify.currency.active] get the symbol return parseFloat(price / 100).toFixed(2) } else { return parseFloat(price / 100).toFixed(2) } }, refreshFreeGiftCartData: function (cartData) { try { let freeGiftsPresentInCart = []; if (cartData && cartData.items && cartData.items.length > 0) { // let freeGifts = gfg.settings.freeGifts; for(let i=0; i 0) { for (let i = 0; i < product.variants.length; i++) { product.variants[i].variant_id = product.variants[i].id; product.variants[i].image = product.variants[i].featured_image?.src; if (!product.variants[i].image) { product.variants[i].image = product.featured_image } if(extraInfo == undefined || product.variants[i].title == "" || product?.variants?.length == 1) { product.variants[i].title = product.variants[i].name } else if(!extraInfo.shouldVariantTitleBeConvertedToProductTitle) { product.variants[i].title = product.variants[i].title } product.variants[i].product_id = product.id if(product.selling_plan_groups) { //product.variants[i].sellingPlanDetails = gbb.utility.getSellingPlanDetailsForVariant(product?.selling_plan_groups, product.variants[i]?.selling_plan_allocations) product.variants[i].selling_plan_groups = product.selling_plan_groups || []; product.variants[i].selling_plan_allocations = product?.variants[i]?.selling_plan_allocations || []; } productsWithIdAsKey[product.variants[i].id] = product.variants[i]; } } //if product has no variants else { productsWithIdAsKey[product.id] = product; } } return productsWithIdAsKey; }catch(err){ gfg.utility.debugConsole(err); return {}; } }, convertFromStoreCurrencyToCustomer : function(amount) { try { let activeCurrencyRate = gfg.utility.getActiveCurrencyRate(); let convertedAmount = parseFloat(amount * activeCurrencyRate).toFixed(2); return convertedAmount; } catch(err) { gfg.utility.debugConsole(err) } }, checkIfClickIsAllowed_sastaDebounce : function(selector,delay=500){ try { const currentTime = new Date().getTime(); let lastClickTimestamps = gfg.state.lastClickTimestamps const previousClickTime = lastClickTimestamps.get(selector) || 0; const timeDifference = currentTime - previousClickTime; if (timeDifference < delay) { gfg.utility.debugConsole("time difference:" + timeDifference + "ms") return false; } lastClickTimestamps.set(selector, currentTime); gfg.state.lastClickTimestamps = lastClickTimestamps; return true; } catch (error) { gfg.utility.debugConsole("error in checkIfClickIsAllowed_sastaDebounce", error) return true; } }, convertArrayToObject : function(array, key) { try { let obj = {}; for(let i=0; i { // Log the response data try { if (typeof response === 'string') { await gfg.utility.callchecksAfterApiCalls(url, response); }else{ response.clone().text().then(async (data) => { await gfg.utility.callchecksAfterApiCalls(url, data); }); } return response; } catch (error) { gfg.utility.debugError("Error in response data: ", error); return response; } }); } else { // If the URL doesn't contain "/cart", call the original fetch function directly return originalFetch.apply(this, arguments); } }; } catch (error) { gfg.utility.debugError("Error in listenForApiCalls: ", error); } }, listenForAjaxApiCalls: function () { try { // Save a reference to the original gfg.$.ajax function var originalAjax = gfg.$.ajax; // Override the gfg.$.ajax function gfg.$.ajax = function(reqObj, options) { let url = reqObj.url; // Log the request URL gfg.utility.debugConsole("gfg Request URL: " + url); // Check if the URL contains "/cart" if ( url && typeof url == "string" && ( url.includes('/cart/change') || url.includes('graphql.json') || // url.includes('/cart.js') || url.includes('/cart/add') || url.includes('/cart/update') || url.includes('/cart/clear') ) ) { // Call the original gfg.$.ajax function to make the request return originalAjax.apply(this, arguments).then(async function(response) { // Log the response data try { if (typeof response === 'string') { await gfg.utility.callchecksAfterApiCalls(url, response); }else{ response.clone().text().then(async (data) => { await gfg.utility.callchecksAfterApiCalls(url, data); }); } return response; } catch (error) { gfg.utility.debugConsole("Error in ajax response data: ", error); return response; } }); } else { // If the URL doesn't contain "/cart", call the original gfg.$.ajax function directly return originalAjax.apply(this, arguments); } }; } catch (error) { gfg.utility.debugConsole("Error in listenForAjaxApiCalls: ", error); } }, listenForXmlHttpApiCalls: function() { // Save a reference to the original XMLHttpRequest constructor try { gfg.utility.debugConsole('inside xml http api call'); const OriginalXMLHttpRequest = window.XMLHttpRequest; // Override the XMLHttpRequest constructor window.XMLHttpRequest = function() { const xhr = new OriginalXMLHttpRequest(); // Save references to the original methods const originalOpen = xhr.open; const originalSend = xhr.send; // Override the open method to store the URL xhr.open = function(method, url) { // Store the URL in the xhr object xhr._url = url; // Log the request URL // gfg.utility.debugConsole("XMLHttpRequest open url", url); gfg.utility.debugConsole("XMLHttpRequest Request URL: " + url); // Call the original open method return originalOpen.apply(this, arguments); }; // Override the send method xhr.send = function(data) { // Check if the URL contains "/cart" immediately if ( xhr._url && typeof xhr._url == "string" && ( xhr._url.includes('/cart/change') || xhr._url.includes('graphql.json') || // xhr._url.includes('/cart.js') || xhr._url.includes('/cart/add') || xhr._url.includes('/cart/update') || xhr._url.includes('/cart/clear')) ) { // Override the onreadystatechange event handler const originalOnReadyStateChange = xhr.onreadystatechange; xhr.onreadystatechange = async function() { if (xhr.readyState == XMLHttpRequest.DONE || xhr.readyState == 4) { // Log the response data const response = xhr.responseText; try { // const response = xhr.responseText; //gfg.utility.debugConsole("XMLHttpRequest Response Data", response); // Perform your desired actions with the response data if (typeof response === 'string') { gfg.utility.debugConsole(" callchecksAfterApiCalls for" , xhr._url); await gfg.utility.callchecksAfterApiCalls(xhr._url, response); // return response; } else { response.clone().text().then(async (data) => { await gfg.utility.callchecksAfterApiCalls(xhr._url, data); }); return response; } } catch (error) { gfg.utility.debugConsole("Error in XMLHttpRequest response data: ", error); return response; } } // Call the original onreadystatechange event handler if (typeof originalOnReadyStateChange === 'function') { originalOnReadyStateChange.apply(xhr, arguments); } }; } // Call the original send method return originalSend.apply(this, arguments); }; return xhr; }; } catch (error) { gfg.utility.debugConsole("Error in listenForXmlHttpApiCalls: ", error); } }, listenForXmlHttpApiCallsNew: function() { try { gfg.utility.debugConsole('inside xml http api call'); const OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = function() { const xhr = new OriginalXMLHttpRequest(); const originalOpen = xhr.open; const originalSend = xhr.send; xhr.open = function(method, url, ...args) { xhr._url = url; gfg.utility.debugConsole("XMLHttpRequest Request URL: " + url); originalOpen.call(xhr, method, url, ...args); }; xhr.send = function(data) { const originalOnReadyStateChange = xhr.onreadystatechange || (() => {}); xhr.onreadystatechange = async function(...args) { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr._url && typeof xhr._url === "string" && (xhr._url.includes('/cart/change') || xhr._url.includes('/cart/add') || xhr._url.includes('/cart/update') || xhr._url.includes('/cart/clear'))) { try { const response = xhr.responseText; // Your custom logic here await gfg.utility.callchecksAfterApiCalls(xhr._url, response); } catch (error) { gfg.utility.debugConsole("Error in XMLHttpRequest response data: ", error); } } } originalOnReadyStateChange.apply(this, args); }; originalSend.call(xhr, data); }; return xhr; }; } catch (error) { gfg.utility.debugConsole("Error in listenForXmlHttpApiCalls: ", error); } }, // listenForFormSubmits:function() { // const forms = document.querySelectorAll('form'); // forms.forEach(form => { // const action = form.getAttribute('action'); // if (action.includes('/cart/change') || action.includes('/cart/add') || action.includes('/cart/update') || action.includes('/cart/clear')) { // gfg.utility.debugConsole("gfg Form Action: " + action); // event.preventDefault(); // form.addEventListener('submit', async (event) => { // try { // // form.submit(); // //place a timeout here to wait for the form to submit // await new Promise(resolve => setTimeout(resolve, 1000)); // gfg.utility.debugConsole("form after submit:"); // // callchecks after api calls should only happen after the form is submitted. // await gfg.utility.callchecksAfterApiCalls(action, undefined); // } catch (error) { // gfg.utility.debugConsole("Error in ajax response data: ", error); // } // }); // } // }); // }, interceptFetchRequest(matches, cb) { const originalFetch = fetch window.fetch = function (input, init) { return originalFetch(input, init).then(async (res) => { if (input && typeof input == "string" && ( input.includes('graphql.json') || input.includes('/cart/change') || input.includes('/cart/add') || input.includes('/cart/update') || input.includes('/cart/clear'))) { // Call the original fetch function to make the request await gfg.utility.callchecksAfterApiCalls(input, res); } return Promise.resolve(res) }) } }, interceptXMLHttpRequest(matches, cb) { const originalOpen = XMLHttpRequest.prototype.open XMLHttpRequest.prototype.open = function () { this.addEventListener('load', async function () { if (input && typeof input == "string" && // input.includes("/cart.js") && ( input.includes('graphql.json') || input.includes('/cart/change') || input.includes('/cart/add') || input.includes('/cart/update') || input.includes('/cart/clear'))) { // Call the original fetch function to make the request await gfg.utility.callchecksAfterApiCalls(input, res); } }) originalOpen.apply(this, arguments) } }, callchecksAfterApiCalls: async function (url, data) { try { if (url && typeof url =="string" && url.includes('app=gfgfreegift')) { return data; } let cartData = undefined; if(gfg?.settings?.app?.considerRequestListenerData){ cartData = gfg.utility.validateAndParseCartData(data); } if (cartData) { gfg.state.cartData = cartData; } else { gfg.state.cartData = await gfg.utility.getCart(); // let relevantCartDataForFreeGiftEligibility = gfg.gfgFreeGift.utility.filterCartDataBasedOnSettings(gfg.state.cartData); // gfg.state.gfgFreeGiftCartData = relevantCartDataForFreeGiftEligibility; cartData = gfg.state.cartData; gfg.gfgVolDiscount.actions.handleQuantityUpdate(); } gfg.gfgFreeGift.f.checkForFreeGift(cartData); gfg.gfgVolDiscount.init(gfg.settings ,"CART_PAGE"); gfg.gfgVolDiscount.actions.handleQuantityUpdate(); gfg.gfgUnifiedWidget.init(gfg.settings , "PRODUCT_PAGE") gfg.gfgUnifiedWidget.init(gfg.settings , "CART_PAGE") try { if(gfgShippingDiscountV2){ gfgShippingDiscountV2.init(); } } catch (error) { gfg.utility.debugConsole("error in gfgShippingDiscountV2.init", error); } try { if(gfgCustomDiscount){ gfgCustomDiscount.init(); } } catch (error) { gfg.utility.debugConsole("error in gfgCustomDiscount.init", error); } } catch (e) { gfg.utility.debugConsole("gfg Response data: ", data); } }, combineObjects: function (obj1, obj2) { const combinedObject = {}; // Copy properties from the first object for (let key in obj1) { if (obj1.hasOwnProperty(key)) { combinedObject[key] = obj1[key]; } } // Copy properties from the second object for (let key in obj2) { if (obj2.hasOwnProperty(key)) { combinedObject[key] = obj2[key]; } } return combinedObject; }, debugConsole: function(...messages){ try{ let flag = gfg.state.CONSTANT_DEBUG_FLAG; if(flag == false){ return; } if(flag == true){ for (let message of messages) { console.log(message); } return; } let isDebug = localStorage.getItem("debug"); if (isDebug) { for (let message of messages) { console.log(message); } gfg.state.CONSTANT_DEBUG_FLAG = true }else{ gfg.state.CONSTANT_DEBUG_FLAG = false } }catch(err){ console.error( 'error inside debugConsole ->' , err) } }, debugError: function(...messages){ try{ let flag = gfg.state.CONSTANT_DEBUG_FLAG; if(flag == false){ return; } if(flag == true){ for (let message of messages) { console.error(message); } return; } let isDebug = localStorage.getItem("debug"); if (isDebug) { gfg.state.CONSTANT_DEBUG_FLAG = true; for (let message of messages) { console.error(message); } }else{ gfg.state.CONSTANT_DEBUG_FLAG = false } }catch(err){ console.error( 'error inside the debugError function ->' , err) } }, setCustomerSpecificData: async function(){ let customerId = undefined; let isCustomerLoggedInBool = false let customerTags = []; let activeCustomerData = {} let visitingFromCountry; if(window.shopifyLiquidValuesApp7Ext && window.shopifyLiquidValuesApp7Ext.customer){ activeCustomerData = shopifyLiquidValuesApp7Ext.customer } if(activeCustomerData.email != null){ customerId = activeCustomerData.id; customerTags = activeCustomerData?.customerTags || []; isCustomerLoggedInBool = true } // check if countrySelects rule created for either free gift or discount const checkIfVisitingFromCountryRequired = gfg.f.checkIfVisitingFromCountryRequired(); if(checkIfVisitingFromCountryRequired){ visitingFromCountry = await gfg.utility.getVisitingFromCountry(); } gfg.state.activeCustomerData = { customerId: customerId, customerTags: customerTags, isCustomerLoggedInBool: isCustomerLoggedInBool, visitingFromCountry: visitingFromCountry } }, updateCartAttributeWithCustomerData: async function(){ try{ // freeGiftConditionChecker // let isFreeGiftConditionMet = gfg.gfgFreeGift.f.gfgFreeGiftCheckCustomerConditions(); // let isVolumeDiscountConditionMet = true; // volumenDiscountChecker gfg.gfgVolDiscount.f.removeInactiveCampaigns(); // if(gfg.gfgVolDiscount.state.customerSpecificDiscount.length == 0){ // isVolumeDiscountConditionMet = false; // } // let result = isFreeGiftConditionMet || isVolumeDiscountConditionMet; // if any true update cart data // if(result){ // update cart let customerData = gfg.state.activeCustomerData; const dataToBeUpdated = { attributes: { _loggedInId: customerData?.customerId || null, _customerTags: customerData?.customerTags || [], _visitingFromCountry: customerData?.visitingFromCountry || null } } await gfg.utility.updateCart(dataToBeUpdated); // }else{ // await gfg.utility.updateCart({ attributes:{ _loggedInId: null, _customerTags: null }}); // } }catch(err){ gfg.utility.debugConsole(err) } }, redirectToPage: async function(location){ window.location.href = location }, checkIfTwoArrayHasCommonElement: function(arr1, arr2){ for (let i = 0; i < arr1.length; i++) { for (let j = 0; j < arr2.length; j++) { if (arr1[i] === arr2[j]) { return true; } } } return false; }, getQuantityValueFromQuantitySelector: function(){ try { // Add class "gfgHide" to the element document.querySelector(gfg.elements.quantityBtn).classList.add("gfgHide"); let quantitySelectorEle = document.querySelector(gfg.elements.quantityBtn); // Check if it is an input element, if not find the input inside it let quantitySelectorEleInput = (quantitySelectorEle.tagName.toLowerCase() !== "input") ? quantitySelectorEle.querySelector("input") : null; // If an input element was found, update the quantitySelectorEle if (quantitySelectorEleInput) { quantitySelectorEle = quantitySelectorEleInput; } let quantityValue; // If quantitySelectorEle is a single element, check if it's an input and get its value if (quantitySelectorEle && quantitySelectorEle.tagName.toLowerCase() === "input") { quantityValue = quantitySelectorEle.value; } return quantityValue; } catch (error) { gfg.utility.debugConsole("error in getQuantityValueFromQuantitySelector", error); } }, formatPriceWithSeparator: function(price){ // this function format the price first for example 10.00 to 10 and if 10.50 to 10.50 then apply thousand separator and decimal separator. try { price = parseFloat(price / 100); // price comes in shopify format so divide by 100 first. // if for example price is 10.00 then convert it too 10 if (price % 1 === 0) { // Checks if the number is an integer price = price.toString(); } else { price = price.toFixed(2); // Keep two decimal places if it's not an integer } const activeCurrencyCode = gfg.utility.getActiveCurrencyCode(); const thousandSeparator = gfg.settings.merchantInfo.multipleCurrenciesInfo[activeCurrencyCode]?.thousandsSeparator || gfg.settings?.merchantInfo?.currencyInfo?.thousandsSeparator || ","; const decimalSeparator = gfg.settings.merchantInfo.multipleCurrenciesInfo[activeCurrencyCode]?.decimalSeparator || gfg.settings?.merchantInfo?.currencyInfo?.decimalSeparator || "."; // Convert the price to a string splitting integer and decimal parts let [integerPart, decimalPart] = price.toString().split('.'); // Replace the thousand separator according to the locale integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator); // Reconstruct the price with the correct decimal separator (if there's a decimal part) const formattedPrice = decimalPart ? integerPart + decimalSeparator + decimalPart : integerPart; return formattedPrice; } catch (error) { gfg.utility.debugConsole("error in formatPriceWithSeparator", error); return price; } }, getActiveCurrencyCode: function(){ if(window.Shopify.currency.active){ return window.Shopify.currency.active; } return gfg.settings.merchantInfo.currencyInfo.code; }, getProductTranslatedHandle: function(productName, languageValue){ return new Promise(async(res, rej) => { try { const url = languageValue + "products/" + productName; const response = await fetch(url); if(!response.ok){ throw new Error("Network response was not ok"); } // response.url = response.url.trim().endsWith("/") ? response.url.slice(0, -1) : response.url; let urlReturned = response.url; // Remove the last character if it is a '/' if (urlReturned[urlReturned.length - 1] === "/") { urlReturned = urlReturned.substring(0, urlReturned.length - 1); } gfg.utility.debugConsole("urlReturned", urlReturned); // Extract the last path segment and get the string before the first '.' let newHandle = urlReturned.split("/").pop().split(".")[0]; // gfg.utility.debugConsole("newHandle", newHandle); gfg.utility.debugConsole("newHandle", newHandle); res(newHandle); } catch (error) { gfg.utility.debugConsole('error in getProductTranslatedHandle', error); res(false); } }) }, checkGfgDebugMode: function() { try { const urlParams = new URLSearchParams(window.location.search); // if _gfgDebugMode set to true in the URL, update the cart attribute with _gfgDebugMode if (urlParams.get('_gfgDebugMode') === 'true') { var formData = new FormData(); formData.append("attributes[_gfgDebugMode]", true); fetch(window.Shopify.routes.root + 'cart/update.js', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { gfg.utility.debugConsole(`Cart update successful: ${data}`); }) .catch(error => { gfg.utility.debugConsole(`Error updating cart: ${error}`); }); } } catch (error) { gfg.utility.debugConsole(`Error in checkGfgDebugMode: ${error}`); } }, getFontWeightValue: function(fontWeight) { try { const fontWeights = { bold: "700", medium: "600", regular: "400", }; return fontWeights[fontWeight] || fontWeight; } catch (error) { gfg.utility.debugConsole("error in getFontWeightValue", error); return fontWeight; } }, getFontSizeValue: function(fontSize) { try { if(typeof fontSize == "string" && !fontSize?.includes("px")){ return fontSize +"px"; } return fontSize; } catch (error) { gfg.utility.debugConsole("error in getFontSizeValue", error); } }, getFirstRenderCartData: async function(){ try { let cartData = window?.shopifyLiquidValuesApp7Ext?.cartData || false; // incase cartData is not present in the window object then lets fetch via getCart. if(!cartData){ cartData = await gfg.utility.getCart(); } return cartData; } catch (error) { gfg.utility.debugConsole("error in getFirstRenderCartData", error); } }, getCountry : function(){ // this function will return the current country of the store. // otherwise it will return US as default country try { if(window?.Shopify && window.Shopify?.country){ return window.Shopify.country; } return "US"; } catch (error) { gfg.utility.debugConsole("error in getCountry", error); } }, getVisitingFromCountry : async function(){ let visitingFromCountry; try { // if visitingFromCountry is already present in the local storage then return it. // otherwise fetch it from the api and store it in the local storage. const isLocalStorageExists = window && window.localStorage ? true : false; if(isLocalStorageExists){ visitingFromCountry = localStorage.getItem("visitingFromCountry"); if(visitingFromCountry){ return visitingFromCountry; } } const apiURL = "https://get.geojs.io/v1/ip/geo.json"; const response = await fetch(apiURL); if(!response.ok){ throw new Error("Error while fetching the visiting from country"); } const data = await response.json(); visitingFromCountry = data?.country_code ; if(isLocalStorageExists){ localStorage.setItem("visitingFromCountry", visitingFromCountry); } } catch (error) { gfg.utility.debugConsole("error in getVisitingFromCountry", error); } finally{ return visitingFromCountry; } }, getRegionalLocaleUrl : function(){ let regionalLocale = ""; try { let localePresentInUrl = window.location.pathname.split("/") || ""; // Get the current locale from Shopify let currentShopifyLocale = Shopify.locale || ""; // Check if the Shopify locale and the locale present in the URL match or if one includes the other if (currentShopifyLocale && currentShopifyLocale !== "" && localePresentInUrl) { if (currentShopifyLocale === localePresentInUrl[1]) { regionalLocale = `/${currentShopifyLocale}`; } else if (localePresentInUrl[1].includes(currentShopifyLocale)) { // This case handles when the locale is a subset like 'en-us' in the URL being 'en' regionalLocale = `/${localePresentInUrl[1]}`; } else { // If there's no match or inclusion, regionalLocale remains an empty string } } } catch (error) { gfg.utility.debugConsole("error in getRegionalLocaleUrl", error); } finally{ return regionalLocale; } }, getHrefForProductCollectionHandle: function(type, handle){ const basePath = type == "product" ? "/products/" : "/collections/"; let url = basePath + handle; try { const isRegionalLocaleUrlRequiredForHref = gfg.settings.app?.isRegionalLocaleUrlRequiredForHref; if(isRegionalLocaleUrlRequiredForHref){ url = gfg.utility.getRegionalLocaleUrl() + url; } } catch (error) { gfg.utility.debugConsole("getHrefForProductCollectionHandle", error); } finally{ return url; } }, findWrapperElement: function(feature, wrapperType, promotion_id, returnType = "JS") { let wrapperElement = []; try { const featuresWrapperMap = gfg.state.featuresWrapperMap; const isSideCartContext = gfg.state.page_type !== "cart" && (wrapperType === "CART_PAGE" || wrapperType === "SIDE_CART"); let noAppBlockFoundFunction = gfg.productPage.f.insertWrapperIntoPage; let archivedAppBlockSelector = PRODUCT_PAGE_APP_BLOCK_SELECTOR; let pageSpecificSelector = ".gfgProductPageWrapperV2"; let featureWrapperKey = isSideCartContext ? `${feature}-SIDE_CART-${promotion_id}` : `${feature}-${wrapperType}-${promotion_id}`; let featureSpecificWrapperSelector; let featureSpecificAppBlockSelector; let featureSpecificSideCartWrapperSelector; let featureSpecificSideCartWrapper; let isFeatureSpecificSideCartSelectorProvidedInAdmin; if (wrapperType === "CART_PAGE" || wrapperType === "SIDE_CART") { pageSpecificSelector = ".gfgCartPageWrapperV2"; archivedAppBlockSelector = CART_PAGE_APP_BLOCK_SELECTOR; noAppBlockFoundFunction = gfg.cartPage.f.insertWrapperIntoPage; } switch (feature) { case "FREE_GIFT": featureSpecificAppBlockSelector = FREE_GIFT_APP_BLOCK_SELECTOR; featureSpecificWrapperSelector = ".gftFreeGiftWrapper"; featureSpecificSideCartWrapperSelector = FREEGIFT_SIDE_CART_WRAPPER_SELECTOR; featureSpecificSideCartWrapper = FREEGIFT_SIDE_CART_WRAPPER; isFeatureSpecificSideCartSelectorProvidedInAdmin = gfg.settings.app?.freeGiftSideCartSelector; break; case "VOLUME_DISCOUNT": featureSpecificAppBlockSelector = VOLUME_DISCOUNT_APP_BLOCK_SELECTOR; featureSpecificWrapperSelector = ".gfgVolDiscountWrapper"; featureSpecificSideCartWrapperSelector = VOLUME_DISCOUNT_SIDE_CART_WRAPPER_SELECTOR; featureSpecificSideCartWrapper = VOLUME_DISCOUNT_SIDE_CART_WRAPPER; isFeatureSpecificSideCartSelectorProvidedInAdmin = gfg.settings.app?.volumeDiscountSideCartSelector; break; case "BOGO": featureSpecificAppBlockSelector = BOGO_APP_BLOCK_SELECTOR; featureSpecificWrapperSelector = ".gfgBogoWrapper"; featureSpecificSideCartWrapperSelector = '' isFeatureSpecificSideCartSelectorProvidedInAdmin = false; break; case "UNIFIED": featureSpecificAppBlockSelector = UNIFIED_APP_BLOCK_SELECTOR; featureSpecificWrapperSelector = ".gfgUnifiedDiscountWrapper"; featureSpecificSideCartWrapperSelector = UNIFIED_SIDE_CART_WRAPPER_SELECTOR; featureSpecificSideCartWrapper = UNIFIED_SIDE_CART_WRAPPER; isFeatureSpecificSideCartSelectorProvidedInAdmin = gfg.settings.app?.unifiedSideCartSelector; break; case "CUSTOM_DISCOUNT": featureSpecificAppBlockSelector = CUSTOM_DISCOUNT_APP_BLOCK_SELECTOR; featureSpecificWrapperSelector = ".gfgCustomDiscountWrapper"; featureSpecificSideCartWrapperSelector = CUSTOM_DISCOUNT_SIDE_CART_WRAPPER_SELECTOR; featureSpecificSideCartWrapper = CUSTOM_DISCOUNT_SIDE_CART_WRAPPER; isFeatureSpecificSideCartSelectorProvidedInAdmin = gfg.settings.app?.customDiscountSideCartSelector; break; case "SHIPPING_DISCOUNT": featureSpecificAppBlockSelector = SHIPPING_DISCOUNT_APP_BLOCK_SELECTOR; featureSpecificWrapperSelector = ".gfgShippingDiscountWrapper"; featureSpecificSideCartWrapperSelector = SHIPPING_DISCOUNT_SIDE_CART_WRAPPER_SELECTOR; featureSpecificSideCartWrapper = SHIPPING_DISCOUNT_SIDE_CART_WRAPPER; isFeatureSpecificSideCartSelectorProvidedInAdmin = gfg.settings.app?.shippingDiscountSideCartSelector; break; default: break; } const appBlockElementsV3 = Array.from(document.querySelectorAll(featureSpecificAppBlockSelector)); if (appBlockElementsV3.length > 0 && !isSideCartContext) { let isBlockIdMatched = false; appBlockElementsV3.forEach(appBlockElement => { const blockId = JSON.parse(appBlockElement.getAttribute("data-setting"))?.blockId; if (blockId && blockId == promotion_id) { wrapperElement = appBlockElement; isBlockIdMatched = true; } }); if (!isBlockIdMatched) { wrapperElement = appBlockElementsV3; } featuresWrapperMap[featureWrapperKey] = "V3(feature specific block)"; } else if (isFeatureSpecificSideCartSelectorProvidedInAdmin && isSideCartContext) { let sideCartSelectorElementV4 = document.querySelector(featureSpecificSideCartWrapperSelector); // if selector is not found then lets insert it at least. if(!sideCartSelectorElementV4){ gfg.cartPage.f.insertSideCartWrappersIntoPage(); sideCartSelectorElementV4 = document.querySelector(featureSpecificSideCartWrapperSelector); } // if still side cart selector is not found then lets grab it via variable(bcz not available in dom) // we are doing this to handle side cart widget disappear issue in few unexpected cases. if(!sideCartSelectorElementV4){ sideCartSelectorElementV4 = featureSpecificSideCartWrapper; } wrapperElement = sideCartSelectorElementV4 ? [sideCartSelectorElementV4] : wrapperElement; featuresWrapperMap[featureWrapperKey] = "V4(feature specific side cart wrapper)"; } else if (document.querySelector(archivedAppBlockSelector)) { const mainContainer = document.querySelector(`${archivedAppBlockSelector}${pageSpecificSelector}`); const matchedElement = mainContainer?.querySelector(featureSpecificWrapperSelector); wrapperElement = matchedElement ? [matchedElement] : []; featuresWrapperMap[featureWrapperKey] = "V2(archived app block)"; } else if(gfg.state.page_type === "product" || gfg.state.page_type === "cart" || isSideCartContext) { noAppBlockFoundFunction(); const mainContainer = document.querySelector(`${pageSpecificSelector}`); let matchedElement = mainContainer?.querySelector(featureSpecificWrapperSelector); // if still cart page wrapper/selector is not found then lets grab it via variable(bcz not available in dom) // we are doing this to handle side cart widget disappear issue in few unexpected cases. if(!matchedElement && isSideCartContext){ matchedElement = gfg.elements.cartPageWrapperV2?.querySelector(featureSpecificWrapperSelector); } wrapperElement = matchedElement ? [matchedElement] : []; featuresWrapperMap[featureWrapperKey] = "V1(default selector)"; } gfg.state.featuresWrapperMap = featuresWrapperMap; } catch (error) { gfg.utility.debugConsole("error in findWrapperElement", error); } finally { return wrapperElement; } }, BXGYActionsAfterAddToCart: function(){ try { // this is not a global script, just variable name looks like that because of bad calls taken, this is a buyxgety(new dynamic bogo script). const global_afterAddToCartScript = gfg.settings.app?.global_afterAddToCartScript; if(global_afterAddToCartScript){ eval(global_afterAddToCartScript); } else{ gfg.gfgFreeGift.f.updateCartState(); } } catch (error) { gfg.utility.debugConsole("error in BXGYActionsAfterAddToCart", error); } }, compareDates: function(date1, date2) { try { const d1 = date1 instanceof Date ? date1 : new Date(date1); const d2 = date2 instanceof Date ? date2 : new Date(date2); if (isNaN(d1.getTime()) || isNaN(d2.getTime())) { throw new Error("Invalid date format"); } if (d1 > d2) return 1; if (d1 < d2) return -1; return 0; } catch (error) { gfg.utility.debugConsole("Error in compareDates:", error); return null; } }, // injectWrapperRelativeToSelector: function(wrapperHTML, selector, insertAbove = true) { // try { // const targetElement = document.querySelector(selector); // if (targetElement) { // const position = insertAbove ? 'beforebegin' : 'afterend'; // targetElement.insertAdjacentHTML(position, wrapperHTML); // } else { // console.warn(`Target element not found for selector: ${selector}`); // } // } catch (error) { // gfg.utility.debugConsole("error in injectWrapperRelativeToSelector", error); // } // }, injectWrapperRelativeToSelector: function(wrapperElement, selector, insertAbove = true) { try { const targetElement = document.querySelector(selector); if (targetElement) { const position = insertAbove ? 'beforebegin' : 'afterend'; if (!document.body.contains(wrapperElement)) { targetElement.insertAdjacentElement(position, wrapperElement); } else { console.warn('Wrapper element is already in the DOM, skipping injection.'); } } else { console.warn(`Target element not found for selector: ${selector}`); } } catch (error) { gfg.utility.debugConsole("error in injectWrapperRelativeToSelector", error); } }, validateAndParseCartData: function(data) { // this function check if the data is cart data and parse it & return null if it is not cart data let cartData = null; try { cartData = typeof data === 'string' ? JSON.parse(data) : data; if ( !(typeof cartData === 'object' && cartData !== null && 'token' in cartData && Array.isArray(cartData.items)) ) { cartData = null; // Reset if validation fails } } catch (error) { gfg.utility.debugConsole("validateAndParseCartData:", error); cartData = null; } finally { return cartData; } }, getWrapperSkeleton: function(pageType){ try { const wrapper = document.createElement("div"); const wrapperChildHTML = '
'; if(pageType === "PRODUCT_PAGE"){ wrapper.classList.add("gfgPageWrapper", "gfgProductPageWrapperV2", "gfgUnifiedDiscountWrapper"); } else if(pageType === "CART_PAGE"){ wrapper.classList.add("gfgPageWrapper", "gfgCartPageWrapperV2", "gfgUnifiedDiscountWrapper"); } wrapper.innerHTML = wrapperChildHTML; return wrapper; } catch (error) { gfg.utility.debugConsole("error in getWrapperSkeleton", error); } }, dataMappingFromGraphql: function (cleanedData) { try { const convertPlanNameToId = (planName) => { // let base64Str = btoa(planName); let base64Str = btoa(encodeURIComponent(planName)); let id = "KITE_" + base64Str; return id; }; const getAllMetafieldValuesInArray = (productData) => { // productData.forEach(node => { const metafields = []; Object.keys(productData).forEach((key) => { if (key.startsWith("metafield_") && productData?.[key]) { metafields.push(productData[key]); } }); return metafields; }; const transformSellingPlans = (sellingPlanGroups) => { let sellingPlanGroupsFlattened = []; let tempArray = []; // let flattendData = .graphQlUtility.flattenGraphQLResponse({ data: { nodes: sellingPlanGroups } }); let flattendData = sellingPlanGroups; tempArray = flattendData.map((item) => { return { id: convertPlanNameToId(item.name), name: item.name, description: null, options: item.options.map((option, index) => ({ name: option.name, position: index + 1, value: option.value, })), selling_plans: item.sellingPlans?.map((plan) => { return { id: parseInt(plan?.id?.split("/").pop()), gid: plan?.id, option: plan?.option, name: plan?.name, price_adjustments: plan?.priceAdjustments?.map((element, index) => { let adjustmentType = element?.adjustmentValue?.price ? "price" : element?.adjustmentValue?.adjustmentAmount ? "fixed_amount" : "percentage"; let _adjustmentValue = adjustmentType == "percentage" ? element?.adjustmentValue?.adjustmentPercentage : adjustmentType == "price" ? element?.adjustmentValue?.price?.amount : element?.adjustmentValue?.adjustmentAmount?.amount; return { orderCount: element.orderCount, position: index + 1, value_type: adjustmentType, value: adjustmentType == "percentage" ? parseFloat(_adjustmentValue) : parseFloat(_adjustmentValue) * 100, }; }), }; }), recurring_deliveries: item.recurringDeliveries, }; }); sellingPlanGroupsFlattened.push(tempArray); return sellingPlanGroupsFlattened.flat(); }; const getSellingPlansGroupId = (sellingPlansGroup, sellingPlanId) => { for (let i = 0; i < sellingPlansGroup?.length; i++) { let currGroupData = sellingPlansGroup[i]; let foundSellingPlan = currGroupData?.selling_plans?.find((sellingPlan) => sellingPlan?.id == sellingPlanId); if (foundSellingPlan) { return currGroupData?.id; } } }; const transformSellingPlanAllocation = (sellingPlanAllocations, sellingPlansGroup) => { // let response = gbbMix.graphQlUtility.flattenGraphQLResponse(sellingPlanAllocations); let response = sellingPlanAllocations; response = response.map((el) => { let sellingPlanId = parseInt(el?.node?.sellingPlan?.id?.split("/").pop()); return { compare_at_price: parseFloat(el?.node?.priceAdjustments[0]?.compareAtPrice?.amount) * 100, per_delivery_price: parseFloat(el?.node?.priceAdjustments[0]?.perDeliveryPrice?.amount) * 100, price: parseFloat(el?.node?.priceAdjustments[0]?.price?.amount) * 100, selling_plan_id: sellingPlanId, selling_plan_group_id: getSellingPlansGroupId(sellingPlansGroup, sellingPlanId) || null, price_adjustments: [{ position: 1, price: parseFloat(el?.node?.priceAdjustments[0]?.price?.amount) * 100 }], }; }); return response; }; let newProductArray = JSON.parse(JSON.stringify(cleanedData)); let returningArray = []; for (let i = 0; i < cleanedData.length; i++) { const originalProduct = newProductArray[i]; // Initialize currProduct as an empty object const currProduct = {}; // Assigning necessary fields to currProduct const splitProductId = originalProduct.id.split("/"); const pureProductId = parseInt(splitProductId[splitProductId.length - 1]); currProduct["id"] = pureProductId; currProduct["title"] = originalProduct?.title; currProduct["description"] = originalProduct?.description; currProduct["created_at"] = originalProduct?.createdAt; currProduct["handle"] = originalProduct?.handle; currProduct["vendor"] = originalProduct?.vendor; currProduct["tags"] = originalProduct?.tags; currProduct["available"] = originalProduct?.availableForSale; currProduct["featured_image"] = originalProduct?.featuredImage?.originalSrc; currProduct["type"] = originalProduct?.productType; currProduct["images"] = originalProduct?.images?.map((item) => gfg.utility.trimHttps(item?.originalSrc) ); currProduct["media"] = originalProduct?.images?.map((item, index) => ({ alt: item.alt, computedPosition: index + 1, gid: item.id, id: item.id?.split("/").pop(), src: item?.originalSrc, })); currProduct["compare_at_price"] = (originalProduct?.compareAtPriceRange?.maxVariantPrice?.amount || originalProduct?.compareAtPriceRange?.minVariantPrice?.amount) * 100 || null; currProduct["price"] = (originalProduct?.priceRange?.maxVariantPrice?.amount || originalProduct?.priceRange?.minVariantPrice?.amount) * 100; currProduct["selling_plan_groups"] = []; // Initialize variants array currProduct["variants"] = []; currProduct["metafields"] = getAllMetafieldValuesInArray(originalProduct); const ogVariants = originalProduct.variants; // Process variants for (let j = 0; j < ogVariants.length; j++) { const tempOptions = ogVariants[j]?.selectedOptions || []; const variantId = parseInt(ogVariants[j].id.split("/").pop()); const variant = { "id": variantId, "title": ogVariants[j].title, "available": ogVariants[j].availableForSale, "price": parseFloat(ogVariants[j].price.amount) * 100, "options": tempOptions.map((item) => item.value), "option1": tempOptions[0]?.value || null, "option2": tempOptions[1]?.value || null, "option3": tempOptions[2]?.value || null, "public_title": tempOptions.map((item) => item.value).join(" / "), "name": ogVariants[j].title === "Default Title" ? currProduct["title"] : currProduct["title"] + " - " + ogVariants[j].title, "featured_image": { "id": ogVariants[j]?.image?.id?.split("/").pop(), "src": ogVariants[j]?.image?.originalSrc, }, "compare_at_price": ogVariants[j].compareAtPrice ? parseFloat(ogVariants[j].compareAtPrice.amount) * 100 : null, "selling_plan_allocations": [], }; currProduct["variants"].push(variant); } // Push the fully constructed currProduct to the returningArray returningArray.push(currProduct); } return returningArray; } catch (error) { gfg.utility.debugConsole("error in dataMappingFromGraphQL ", error); } }, trimHttps: function(url) { try { if (url.startsWith("https:")) { return url.substring(6); // Remove the first 6 characters ("https:") } return url; // Return the original string if it doesn't start with "https:" } catch (error) { gfg.utility.debugConsole("error in trimHttps", error); } }, appendKiteUniqueIdToItemsProperty: function(items = []){ try { items = items.map((item)=>{ if(item?.hasOwnProperty("_kite_uid")){ delete item["_kite_uid"]; } item.properties["_kite_uid"] = gfg.utility.randomIdGenerator(20); return item; }) return items; } catch (error) { gfg.utility.debugConsole("error in appendKiteUniqueIdToItemsProperty", error); } }, randomIdGenerator: function(length){ try { let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const charactersLength = characters.length; for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } catch (error) { gfg.utility.debugConsole("error in randomIdGenerator", error); } }, generateMetafieldQueries: function(metafields) { return metafields.map((metafield) => { const { key, namespace } = metafield; return `metafield_${namespace}_${key}: metafield(key:"${key}", namespace:"${namespace}"){ id key value description }`; }).join(' '); } }, productPage: { init: async function (settings) { gfg.utility.debugConsole("productPage-init") gfg.productPage.f.insertWrapperIntoPage(settings) gfg.gfgFreeGift.init(settings, "PRODUCT_PAGE") gfg.gfgVolDiscount.init(settings, "PRODUCT_PAGE") gfg.gfgBogoFeature.init(settings, "PRODUCT_PAGE") gfg.gfgUnifiedWidget.init(settings , "PRODUCT_PAGE"); }, f: { insertWrapperIntoPage: function (settings) { const isProductPageAppBlockPresent = document.querySelector(".gfgProductPageAppBlock"); if (isProductPageAppBlockPresent) { gfg.utility.debugConsole("product page app block present"); return; } const isProductPage = gfg.state.page_type === "product"; const addToCartButton = gfg.elements.addToCartBtn; const productPageWrapperExists = document.querySelector(gfg.selectors.productPageWrapperV2); if (isProductPage && addToCartButton && !productPageWrapperExists) { const btn = addToCartButton; if (btn.offsetParent) { // Check visibility const parent = btn.parentNode; const targetElement = gfg.elements.productPageWrapperV2; parent.insertBefore( targetElement, gfg.settings.app.addAfterAddTocartBtn ? btn.nextSibling : btn ); } } }, }, actions: { insertUpsellModal: function () { alert("popModal for upsell action") }, }, }, cartPage: { init: async function (settings) { gfg.utility.debugConsole("cartPage-init") gfg.cartPage.f.insertSideCartWrappersIntoPage(settings) gfg.cartPage.f.insertWrapperIntoPage(settings) gfg.gfgFreeGift.init(settings, "CART_PAGE") gfg.gfgVolDiscount.init(settings, "CART_PAGE") gfg.gfgBogoFeature.init(settings, "CART_PAGE") gfg.gfgUnifiedWidget.init(settings , "CART_PAGE") }, f: { insertWrapperIntoPage: function (settings) { const isCartPageAppBlockPresent = document.querySelector(".gfgCartPageAppBlock"); if (isCartPageAppBlockPresent) { gfg.utility.debugConsole("Cart page app block present"); return; } const checkoutButtons = document.querySelectorAll(gfg.selectors.checkoutBtn); const isCartPageWrapperPresent = document.querySelector(gfg.selectors.cartPageWrapperV2); if (!checkoutButtons.length || isCartPageWrapperPresent) return; return new Promise((resolve) => { checkoutButtons.forEach((button) => { if (!button.offsetParent) return; // Skip invisible buttons const { theme_store_id } = window.Shopify?.theme || {}; const isDawnTheme = theme_store_id === gfg.constants.themesIds.DAWN_THEME; const wrapper = gfg.elements.cartPageWrapperV2; if (isDawnTheme) { button.parentNode.parentNode.insertBefore(wrapper, button.parentNode); } else if (gfg.settings.app.addAftercheckoutBtn) { button.parentNode.insertBefore(wrapper, button.nextSibling); } else { button.parentNode.insertBefore(wrapper, button); } }); resolve(); }); } , insertSideCartWrappersIntoPage: async function(settings) { try { if(gfg.state.page_type === "cart"){ return; } const features = [ { selector: gfg.settings.app?.freeGiftSideCartSelector, insertAbove: gfg.settings.app?.freeGiftSideCartWrapperAboveSelector, wrapper: FREEGIFT_SIDE_CART_WRAPPER, wrapperSelector: FREEGIFT_SIDE_CART_WRAPPER_SELECTOR }, { selector: gfg.settings.app?.volumeDiscountSideCartSelector, insertAbove: gfg.settings.app?.volumeDiscountSideCartWrapperAboveSelector, wrapper: VOLUME_DISCOUNT_SIDE_CART_WRAPPER , wrapperSelector: VOLUME_DISCOUNT_SIDE_CART_WRAPPER_SELECTOR }, { selector: gfg.settings.app?.unifiedSideCartSelector, insertAbove: gfg.settings.app?.unifiedSideCartWrapperAboveSelector, wrapper: UNIFIED_SIDE_CART_WRAPPER , wrapperSelector: UNIFIED_SIDE_CART_WRAPPER_SELECTOR }, { selector: gfg.settings.app?.customDiscountSideCartSelector, insertAbove: gfg.settings.app?.customDiscountSideCartWrapperAboveSelector, wrapper: CUSTOM_DISCOUNT_SIDE_CART_WRAPPER , wrapperSelector: CUSTOM_DISCOUNT_SIDE_CART_WRAPPER_SELECTOR }, { selector: gfg.settings.app?.shippingDiscountSideCartSelector, insertAbove: gfg.settings.app?.shippingDiscountSideCartWrapperAboveSelector, wrapper: SHIPPING_DISCOUNT_SIDE_CART_WRAPPER , wrapperSelector: SHIPPING_DISCOUNT_SIDE_CART_WRAPPER_SELECTOR } ]; features.forEach(feature => { if (feature.selector && !document.querySelector(feature.wrapperSelector)) { gfg.utility.injectWrapperRelativeToSelector( feature.wrapper, feature.selector, feature.insertAbove ); } }); } catch (error) { gfg.utility.debugConsole("error in insertSideCartWrappersIntoPage", error); } }, }, events: { ajaxSuccess: function (cartSettings) { return; } } }, gfgFreeGift: { state:{ freeGiftsShopifyData: [], freeGiftsShopifyDataByHandles: {}, freeGiftShopifyDataByProductIds: {}, freeGiftsShopifyDataByVariantIds: {}, superiorTier: undefined, prepareUIStateArray: ["CONDITION_NOT_MET", "CONDITION_NOT_MET", "CONDITION_NOT_MET", "CONDITION_NOT_MET", "CONDITION_NOT_MET", "CONDITION_NOT_MET", "CONDITION_NOT_MET", "CONDITION_NOT_MET", "CONDITION_NOT_MET", "CONDITION_NOT_MET"], isCartUpdatedByUs: false, isEventListenerRegisteredArray: [] , isAccordionArray: [true, true, true, true, true, true, true, true, true, true], isToastPresent: true, CURRENT_QTY_BUY_ANY_PRODUCT_FROM_COLLECTION_Y: [], CURRENT_QTY_BUY_PRODUCT_X: [], CURRENT_TOTAL_FOR_SPEND_X_IN_COLLECTION_Y: [], isCustomerConditionMet: true, isFirstRenderForFreeGift: true, widgetAccordionExpandedArr: [], validFreeGiftTiersArray: [], // each index of array will have array of valid free gift tiers. inValidFreeGiftTiersArray: [], // each index of array will have array of valid free gift tiers. AllFreeGiftTiersArray: [], // each index of array will have array of valid free gift tiers. campaignWiseFreeGiftsFromCartData: [], paginationIndexArrayCampaignWise: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], gfgFreeGiftPrepareChildUIArrCampaignWise: [[], [], [], [], [], [], [], [], [], []] }, init: async function (settings, parent) { try{ // let isFreeGiftConditionMet = gfg.gfgFreeGift.state.isCustomerConditionMet; // if(isFreeGiftConditionMet == false){ // return; // } // let isURLBasedCampaignisActive = gfg.gfgFreeGift.f.gfgCheckForActiveURLBasedCampaign(); // if(!isURLBasedCampaignisActive){ // return; // } gfg.gfgFreeGift.f.setInitialStates(settings); await gfg.gfgFreeGift.f.gfgGetAllFreeGiftData() gfg.gfgFreeGift.f.checkForFreeGift(); }catch(e){ gfg.utility.debugConsole("error in gfgFreeGift init", e) } }, initialize: async function (settings, parent) { // let productHandle = gfg.f.getProductPageHandle(settings) }, f: { checkForFreeGift: async function (apicartData) { let cartDataToProcess; const fetchDataForFirstRenderInFreeGiftOnCartPage = gfg.settings.app?.fetchDataForFirstRenderInFreeGiftOnCartPage; if( gfg.state.isCheckForFreeGiftTriggered) { gfg.state.checkForFreeGift = true return } gfg.state.isCheckForFreeGiftTriggered = true if(apicartData){ cartDataToProcess = apicartData; } else{ /* the first newly added check is to solve the problem of multiple free gifts being added on product page to cart page navigation on clicking on add to cart button on product page*/ if(gfg.gfgFreeGift.state?.isFirstRenderForFreeGift && gfg.state.page_type === "cart" && fetchDataForFirstRenderInFreeGiftOnCartPage){ cartDataToProcess = await gfg.utility.getCart(); gfg.gfgFreeGift.state.isFirstRenderForFreeGift = false; } else if(gfg.gfgFreeGift.state?.isFirstRenderForFreeGift){ cartDataToProcess = await gfg.utility.getFirstRenderCartData(); gfg.utility.refreshFreeGiftCartData(cartDataToProcess); gfg.gfgFreeGift.state.isFirstRenderForFreeGift = false; } else{ cartDataToProcess = await gfg.utility.getCart(); } } await gfg.gfgFreeGift.f.processFreeGift(cartDataToProcess); // set to false, so that checkForFreeGift can be triggered again gfg.state.isCheckForFreeGiftTriggered = false // call again if checkForFreeGift is triggered while executing this function if( gfg.state.checkForFreeGift) { gfg.state.checkForFreeGift = false gfg.gfgFreeGift.f.checkForFreeGift() } }, processFreeGift: async function (cartData) { try { const allFreeGiftCampaigns = gfg.settings.freeGifts || []; for(let i=0; i= startDateTime_UTC && currentDateUTC <= endDateTime_UTC) { gfg.utility.debugConsole('Campaign is active'); return true; } else { gfg.utility.debugConsole('Campaign is not active'); return false; } } return true; } catch (err) { gfg.utility.debugError("checkIfFreeGiftCampaignScheduleIsActive", err) return true; } }, processAddingValidFreeGiftsToCart_multipleFreeGift : async function(validFreeGiftTiers, freeGiftCampaignIndex){ let results = []; let validFreeGiftTiersToBeAddedToCart = JSON.parse(JSON.stringify(validFreeGiftTiers)) let allValidFreeGiftTiers_afterCheckingCart = gfg.gfgFreeGift.f.getAllValidFreeGiftTiers(validFreeGiftTiersToBeAddedToCart, freeGiftCampaignIndex) // discard the one that is already in cart // use gfg.state.freeGiftsCartDataMap_productId // now whatever is left we just add the first variant of those many let dataForFirstVariants = await gfg.gfgFreeGift.utility.getFirstVariantSelectedWithProperties(allValidFreeGiftTiers_afterCheckingCart); const filteredFreeGifts = gfg.gfgFreeGift.f.filterFreeGiftsToAutoAddOnceOnly(dataForFirstVariants, freeGiftCampaignIndex); dataForFirstVariants = filteredFreeGifts; if(dataForFirstVariants.length == 0){ return }else { const cutOffDate = new Date("2024-10-16"); const AddMultipleFreeGiftsInOneAPICall = gfg.settings.app?.AddMultipleFreeGiftsInOneAPICall || false; const userCreatedAt = gfg?.settings?.merchantInfo?.createdAt; const isUserCreatedAtDateBeforeCutOffDate = gfg.utility.compareDates(userCreatedAt, cutOffDate); const runOldLogic = (isUserCreatedAtDateBeforeCutOffDate === 1 || AddMultipleFreeGiftsInOneAPICall === true) ? false : true; if(runOldLogic){ for(let i=0; i ({ ...itemValue, ...itemValue.properties })); if (itemsToBeAdded.length > 0) { const output = await gfg.gfgFreeGift.f.gfgAddFreeGiftsToCartV2(itemsToBeAdded, freeGiftCampaignIndex); if (output) { itemsToBeAdded.forEach(item => { gfg.gfgFreeGift.f.updateAutoAddedFreeGiftList({ variantId: item.variantId, ruleId: item?.properties?._rule_id }, freeGiftCampaignIndex); }); results.push(true); } results.push(false); } } } // if any one of them is true then return true if (results.includes(true)) { return true } return }, isProductAllowedToBeAddedToCart: function(productId, freeGiftCampaignIndex){ let { validFreeGiftTiers } = gfg.gfgFreeGift.f.gfgFreeGiftAllOfferStatus(freeGiftCampaignIndex); let productData = gfg.state.freeGiftsCartDataMap_productId[productId]; if (productData) { // If product data exists, update the ruleIdsAlreadyInCart ruleIdsAlreadyInCart.push(productData.properties["_rule_id"]); // Remove any tiers with this rule ID from the valid free gift tiers validFreeGiftTiers = validFreeGiftTiers.filter(tier => { return tier.ruleId !== productData.properties["_rule_id"]; }); // Since product data exists, this product isn't allowed to be added again return false; }else{ // check if its sibling is already in cart validFreeGiftTiers = validFreeGiftTiers.filter(tier => { return tier.ruleId !== productData.properties["_rule_id"]; }); } }, gfgHandleAutoAddEnabled: async function(freeGiftCampaignIndex, cartData){ let { validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers } = gfg.gfgFreeGift.f.gfgFreeGiftAllOfferStatus(freeGiftCampaignIndex); let freeGiftsFromCart = gfg.gfgFreeGift.f.gfgFindAllFreeGiftsFromCart(gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex], freeGiftCampaignIndex) if(validFreeGiftTiers.length == 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_NOT_MET" if(freeGiftsFromCart.length > 0){ await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsFromCart, undefined, freeGiftCampaignIndex) } } if(inValidFreeGiftTiers.length > 0){ // remove all free gifts which are part of freegift teiers // if present in cart // remove All the invalid free gifts from cart let freeGiftsToBeRemovedFromCart = gfg.gfgFreeGift.f.freeGiftsToBeRemovedFromCart(inValidFreeGiftTiers, cartData, freeGiftCampaignIndex); await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsToBeRemovedFromCart, undefined, freeGiftCampaignIndex); }; let isGiftAdded; if(validFreeGiftTiers.length > 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_MET" if(freeGiftsFromCart.length > 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_FULFILLED" } gfg.gfgFreeGift.f.gfgFreeGiftSuperiorTier(validFreeGiftTiers) let superiortierFreeGiftVariantId = gfg.gfgFreeGift.f.getSuperiorTierFreeGift(); const superiorTierFreeGiftRuleId = gfg.gfgFreeGift.state.superiorTier?.ruleId; let isSuperiorTierFreeGiftAlreadyInCart = gfg.gfgFreeGift.f.checkIfSuperiorTierFreeGiftAlreadyInCart(freeGiftsFromCart, superiortierFreeGiftVariantId) if(isSuperiorTierFreeGiftAlreadyInCart){ await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsFromCart, superiortierFreeGiftVariantId, freeGiftCampaignIndex) }else{ await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsFromCart, undefined, freeGiftCampaignIndex) const filteredFreeGifts = gfg.gfgFreeGift.f.filterFreeGiftsToAutoAddOnceOnly( [ { variantId: superiortierFreeGiftVariantId, properties:{ _rule_id: superiorTierFreeGiftRuleId } } ], freeGiftCampaignIndex ); if(filteredFreeGifts.length > 0){ const freeGiftProductData = { variantId: filteredFreeGifts[0].variantId, ruleId: superiorTierFreeGiftRuleId } superiortierFreeGiftVariantId = filteredFreeGifts[0].variantId; isGiftAdded = await gfg.gfgFreeGift.f.gfgAddSuperiorTierFreeGiftToCart(freeGiftProductData, freeGiftCampaignIndex); gfg.gfgFreeGift.f.updateAutoAddedFreeGiftList({ variantId: superiortierFreeGiftVariantId, ruleId: superiorTierFreeGiftRuleId }, freeGiftCampaignIndex); } } } let latestCartDataAfterAddingFreeGift; if(isGiftAdded == true){ // gfg.state.cartData = await gfg.gfgFreeGift.utility.getCart(); // gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = await gfg.gfgFreeGift.utility.getCart(freeGiftCampaignIndex); latestCartDataAfterAddingFreeGift = await gfg.utility.getCart(); const parsedCartData = JSON.parse(JSON.stringify(latestCartDataAfterAddingFreeGift)); gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = gfg.gfgFreeGift.utility.filterCartDataBasedOnSettings(parsedCartData, freeGiftCampaignIndex); gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_FULFILLED" } let freeGiftMsgHtml = await gfg.gfgFreeGift.f.gfgFreeGiftPrepareUI(validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers, freeGiftCampaignIndex); gfg.gfgFreeGift.f.insertIntoPageWrapper(freeGiftMsgHtml, freeGiftCampaignIndex); gfg.gfgFreeGift.f.gfgFreeGiftContainerOverflow() gfg.gfgFreeGift.f.registerEvents(freeGiftCampaignIndex) if(gfg.gfgFreeGift.state.isCartUpdatedByUs){ await gfg.gfgFreeGift.f.updateCartState(null, null, null,latestCartDataAfterAddingFreeGift) } }, gfgHandleAutoAddEnabled_multiplyWithTrigger: async function(freeGiftCampaignIndex, cartData){ try { const { validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers } = gfg.gfgFreeGift.f.gfgFreeGiftAllOfferStatus(freeGiftCampaignIndex); const freeGiftsFromCart = gfg.gfgFreeGift.f.gfgFindAllFreeGiftsFromCart(gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex], freeGiftCampaignIndex); let isGiftAdded; // if no valid free gift tiers then remove all free gifts from cart if found if(validFreeGiftTiers.length === 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_NOT_MET"; if(freeGiftsFromCart.length > 0){ await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsFromCart, undefined, freeGiftCampaignIndex) } } // if few tiers are invalid then remove free gifts from cart for those tiers if found if(inValidFreeGiftTiers.length > 0){ let freeGiftsToBeRemovedFromCart = gfg.gfgFreeGift.f.freeGiftsToBeRemovedFromCart(inValidFreeGiftTiers, cartData, freeGiftCampaignIndex); await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsToBeRemovedFromCart, undefined, freeGiftCampaignIndex); } if(validFreeGiftTiers.length > 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_MET"; if(freeGiftsFromCart.length > 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_FULFILLED"; } gfg.gfgFreeGift.f.gfgFreeGiftSuperiorTier(validFreeGiftTiers) let superiortierFreeGiftVariantId = gfg.gfgFreeGift.f.getSuperiorTierFreeGift(); const superiorTierFreeGiftRuleId = gfg.gfgFreeGift.state.superiorTier?.ruleId; const superiorTierFreeGiftProductId = gfg.gfgFreeGift.state.superiorTier?.freeGiftProduct[0]?.productId; const calculatedFreeGiftChanges = gfg.gfgFreeGift.f.calculateFreeGiftChangesFor_multiplyFreeGiftTrigger(freeGiftCampaignIndex, validFreeGiftTiers, gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex], freeGiftsFromCart); const requiredChanges = calculatedFreeGiftChanges.filter(item => item.productId == superiorTierFreeGiftProductId)?.[0]; if(requiredChanges){ const operationType = requiredChanges.type; const freeGiftProductData = { variantId: superiortierFreeGiftVariantId, ruleId: requiredChanges.ruleId, quantity: requiredChanges.quantity } if(operationType === "ADD"){ isGiftAdded = await gfg.gfgFreeGift.f.gfgAddSuperiorTierFreeGiftToCart(freeGiftProductData, freeGiftCampaignIndex); } else if(operationType === "UPDATE"){ const isUpdated = await gfg.utility.updateCart({updates: requiredChanges.update}); gfg.gfgFreeGift.state.isCartUpdatedByUs = isUpdated ? true : false; } } } let latestCartDataAfterAddingFreeGift; if(isGiftAdded == true){ latestCartDataAfterAddingFreeGift = await gfg.utility.getCart(); const parsedCartData = JSON.parse(JSON.stringify(latestCartDataAfterAddingFreeGift)); gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = gfg.gfgFreeGift.utility.filterCartDataBasedOnSettings(parsedCartData, freeGiftCampaignIndex); gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_FULFILLED" } let freeGiftMsgHtml = await gfg.gfgFreeGift.f.gfgFreeGiftPrepareUI(validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers, freeGiftCampaignIndex); gfg.gfgFreeGift.f.insertIntoPageWrapper(freeGiftMsgHtml, freeGiftCampaignIndex); gfg.gfgFreeGift.f.gfgFreeGiftContainerOverflow(); gfg.gfgFreeGift.f.registerEvents(freeGiftCampaignIndex); if(gfg.gfgFreeGift.state.isCartUpdatedByUs){ await gfg.gfgFreeGift.f.updateCartState(null, null, null,latestCartDataAfterAddingFreeGift) } } catch (error) { gfg.utility.debugConsole("error in gfgHandleAutoAddEnabled_multiplyWithTrigger", error); } }, gfgHandleAutoAddDisabled: async function(freeGiftCampaignIndex, cartData){ let { validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers } = gfg.gfgFreeGift.f.gfgFreeGiftAllOfferStatus(freeGiftCampaignIndex); let freeGiftsFromCart = gfg.gfgFreeGift.f.gfgFindAllFreeGiftsFromCart(gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex]) if(validFreeGiftTiers.length == 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_NOT_MET" if(freeGiftsFromCart.length > 0){ await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsFromCart, undefined, freeGiftCampaignIndex) } } if(inValidFreeGiftTiers.length > 0){ // remove all free gifts which are part of freegift teiers // if present in cart // remove All the invalid free gifts from cart let freeGiftsToBeRemovedFromCart = gfg.gfgFreeGift.f.freeGiftsToBeRemovedFromCart(inValidFreeGiftTiers, cartData, freeGiftCampaignIndex) // await gfg.gfgFreeGift.utility.removeCartItemsFromCart(freeGiftsToBeRemovedFromCart) await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsToBeRemovedFromCart, undefined, freeGiftCampaignIndex) }; if(validFreeGiftTiers.length > 0){ if(freeGiftsFromCart.length > 0){ let checkIfValidFreeGiftIsThereInCart = gfg.gfgFreeGift.f.checkIfValidFreeGiftIsThereInCart(freeGiftsFromCart, validFreeGiftTiers) if(checkIfValidFreeGiftIsThereInCart){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_FULFILLED" }else{ await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsFromCart, undefined, freeGiftCampaignIndex) gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_MET" } }else{ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_MET" } } let freeGiftMsgHtml = await gfg.gfgFreeGift.f.gfgFreeGiftPrepareUI(validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers, freeGiftCampaignIndex); gfg.gfgFreeGift.f.insertIntoPageWrapper(freeGiftMsgHtml, freeGiftCampaignIndex) gfg.gfgFreeGift.f.gfgFreeGiftContainerOverflow(); gfg.gfgFreeGift.f.registerEvents(freeGiftCampaignIndex) if(gfg.gfgFreeGift.state.isCartUpdatedByUs){ gfg.gfgFreeGift.f.updateCartState() } }, gfgHandleAutoAddEnabled_multipleFreeGift: async function(freeGiftCampaignIndex, cartData){ let { validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers } = gfg.gfgFreeGift.f.gfgFreeGiftAllOfferStatus(freeGiftCampaignIndex); let freeGiftsFromCart = gfg.gfgFreeGift.f.gfgFindAllFreeGiftsFromCart(gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex]) if(inValidFreeGiftTiers.length > 0){ // remove all free gifts which are part of freegift teiers // if present in cart // remove All the invalid free gifts from cart let freeGiftsToBeRemovedFromCart = gfg.gfgFreeGift.f.freeGiftsToBeRemovedFromCart(inValidFreeGiftTiers, cartData, freeGiftCampaignIndex) // await gfg.gfgFreeGift.utility.removeCartItemsFromCart(freeGiftsToBeRemovedFromCart) await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsToBeRemovedFromCart, undefined, freeGiftCampaignIndex) }; if(validFreeGiftTiers.length == 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_NOT_MET" if(freeGiftsFromCart.length > 0){ await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsFromCart, undefined, freeGiftCampaignIndex) } } let isGiftAdded = false; if(validFreeGiftTiers.length > 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_MET" if(freeGiftsFromCart.length > 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_FULFILLED" } isGiftAdded = await gfg.gfgFreeGift.f.processAddingValidFreeGiftsToCart_multipleFreeGift(validFreeGiftTiers, freeGiftCampaignIndex) } let latestCartDataAfterAddingFreeGift; if (isGiftAdded == true) { // gfg.state.cartData = await gfg.gfgFreeGift.utility.getCart(); // gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = await gfg.gfgFreeGift.utility.getCart(freeGiftCampaignIndex); latestCartDataAfterAddingFreeGift = await gfg.utility.getCart(); const parsedCartData = JSON.parse(JSON.stringify(latestCartDataAfterAddingFreeGift)); gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = gfg.gfgFreeGift.utility.filterCartDataBasedOnSettings(parsedCartData, freeGiftCampaignIndex); gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_FULFILLED" } let freeGiftMsgHtml = await gfg.gfgFreeGift.f.gfgFreeGiftPrepareUI(validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers, freeGiftCampaignIndex); gfg.gfgFreeGift.f.insertIntoPageWrapper(freeGiftMsgHtml, freeGiftCampaignIndex) gfg.gfgFreeGift.f.gfgFreeGiftContainerOverflow(); gfg.gfgFreeGift.f.registerEvents(freeGiftCampaignIndex); if(gfg.gfgFreeGift.state.isCartUpdatedByUs){ await gfg.gfgFreeGift.f.updateCartState(null, null, null, latestCartDataAfterAddingFreeGift); } }, gfgHandleAutoAddDisabled_multipleFreeGift: async function(freeGiftCampaignIndex, cartData){ let { validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers } = gfg.gfgFreeGift.f.gfgFreeGiftAllOfferStatus(freeGiftCampaignIndex); let freeGiftsFromCart = gfg.gfgFreeGift.f.gfgFindAllFreeGiftsFromCart(gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex]); if(inValidFreeGiftTiers.length > 0){ let freeGiftsToBeRemovedFromCart = gfg.gfgFreeGift.f.freeGiftsToBeRemovedFromCart(inValidFreeGiftTiers, cartData, freeGiftCampaignIndex); // if(freeGiftsToBeRemovedFromCart?.length > 0 && validFreeGiftTiers.length > 0){ // // only exclusive free gifts products should be removed // freeGiftsToBeRemovedFromCart = gfg.gfgFreeGift.f.gfgGetExclusiveFreeGiftsToBeRemovedFromCart(validFreeGiftTiers, freeGiftsToBeRemovedFromCart) // } await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsToBeRemovedFromCart, undefined, freeGiftCampaignIndex) }; if(validFreeGiftTiers.length == 0){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_NOT_MET" if(freeGiftsFromCart.length > 0){ await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsFromCart, undefined, freeGiftCampaignIndex) } } if(validFreeGiftTiers.length > 0){ if(freeGiftsFromCart.length > 0){ let checkIfValidFreeGiftIsThereInCart = gfg.gfgFreeGift.f.checkIfValidFreeGiftIsThereInCart(freeGiftsFromCart, validFreeGiftTiers) if(checkIfValidFreeGiftIsThereInCart){ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_FULFILLED" }else{ await gfg.gfgFreeGift.f.gfgRemoveAllFreeGiftProductsExceptGiven(freeGiftsFromCart, undefined, freeGiftCampaignIndex) gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_MET" } }else{ gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_MET" } } let freeGiftMsgHtml = await gfg.gfgFreeGift.f.gfgFreeGiftPrepareUI(validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers, freeGiftCampaignIndex); gfg.gfgFreeGift.f.insertIntoPageWrapper(freeGiftMsgHtml, freeGiftCampaignIndex) gfg.gfgFreeGift.f.gfgFreeGiftContainerOverflow(); gfg.gfgFreeGift.f.registerEvents(freeGiftCampaignIndex) if(gfg.gfgFreeGift.state.isCartUpdatedByUs){ gfg.gfgFreeGift.f.updateCartState() } }, gfgFreeGiftFindAndUpdateInArray: function(id, updateValue, dataArray){ let found = false; for (let i = 0; i < dataArray.length; i++) { if (dataArray[i].id === id) { dataArray[i].value = updateValue; found = true; return {id: id, value: updateValue} break; } } if (!found) { dataArray.push({ id: id, value: updateValue }); } }, gfgFreeGiftFindInArray: function(id, dataArray){ for (let i = 0; i < dataArray.length; i++) { if (dataArray[i].id === id) { return dataArray[i].value; } } // Return null (or any other default value) if the id is not found in the array return 0; }, gfgAddSuperiorTierFreeGiftToCart:async function(freeGiftProductData, freeGiftCampaignIndex){ return await gfg.gfgFreeGift.f.gfgAddFreeGiftToCart({ variantId: freeGiftProductData.variantId, _rule_id: freeGiftProductData.ruleId, quantity: freeGiftProductData?.quantity || 1 }, freeGiftCampaignIndex) }, gfgAddFreeGiftToCart:async function(freeGiftProduct, freeGiftCampaignIndex){ try { const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; let items = []; let currentCartItems = gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex].items; //just check that the freeGiftInCart is in stock or notl let isCurrentVariantInStock = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds && gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[freeGiftProduct.variantId]?.available || false; if(!isCurrentVariantInStock){ return false } let defaultPropertyInFreeGift = "Free Gift" let freeGiftLineItemProperties = { _free_product: "true", _rule_id: freeGiftProduct?._rule_id || defaultPropertyInFreeGift, _kite_promo_name : settings?.discountData_shopifyResponse?.title || settings?.name }; // check if freeGiftProduct is already in cart let freeGiftProductInCart = currentCartItems.filter((product) => { const condition1 = product.variant_id == freeGiftProduct.variantId; const condition2 = product?.properties?._rule_id === freeGiftProduct?._rule_id; const condition3 = product?.properties?._kite_promo_name === freeGiftLineItemProperties._kite_promo_name return condition1 && condition2 && condition3; // return product.variant_id == freeGiftProduct.variantId }) if (freeGiftProductInCart.length > 0) { for (let i = 0; i < freeGiftProductInCart.length; i++) { let isSameTierItemAlreadyInCart = freeGiftProductInCart[i].properties["_rule_id"] == freeGiftProduct?._rule_id let isRuleTierDefault = freeGiftProductInCart[i].properties["_rule_id"] == defaultPropertyInFreeGift if(isSameTierItemAlreadyInCart && !isRuleTierDefault){ gfg.utility.debugConsole("already in cart with free gift. not adding it again"); continue; } let freeGiftProductInCartLineItemKey = freeGiftProductInCart[i].key; let currentQuantity = freeGiftProductInCart[i].quantity; let items = { id: freeGiftProductInCartLineItemKey, properties: { ...freeGiftProductInCart[i]?.properties, ...freeGiftLineItemProperties }, // quantity: currentQuantity }; // use changeCart let freeGiftProductData = await gfg.utility.changeCart(items); //add the same product again but with quantity 1 // and no properties items = [] items.push({ id: freeGiftProduct.variantId, quantity: currentQuantity }) freeGiftProductData = await gfg.utility.addToCartV2({ items: items }) if (freeGiftProductData) { gfg.gfgFreeGift.state.isCartUpdatedByUs = true; } else { return false; // If any update fails, return false } } return true; // If all updates succeed, return true }else{ items.push({ id: freeGiftProduct.variantId, quantity: freeGiftProduct?.quantity || 1, properties: freeGiftLineItemProperties }) let freeGiftProductData = await gfg.utility.addToCartV2({ items: items }) if(freeGiftProductData){ gfg.gfgFreeGift.state.isCartUpdatedByUs = true return true } return false } } catch (error) { gfg.utility.debugConsole("gfgAddFreeGiftToCart", error) return false; } }, getSuperiorTierFreeGift: function(){ let superiorTier = gfg.gfgFreeGift.state.superiorTier; let freeGiftProduct = superiorTier.freeGiftProduct; // engineer the below code to run on a loop of freeGiftProduct array and use gfg.state.freeGiftsShopifyDataByVariantIds to check if they are in stock or not //--------------------------------------------------------------- // ATTENTION: this code is no longer required as we filter valid free gift tiers based on stock availability in the beginning //--------------------------------------------------------------- // for (let i = 0; i < freeGiftProduct.length; i++) { // for (let j = 0; j < freeGiftProduct[i].variants.length; j++) { // let variantId = freeGiftProduct[i].variants[j].variantId; // let variantData = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[variantId]; // if (variantData && variantData.available == true) { // return variantId; // } // } // } let superiortierFreeGiftVariantId = freeGiftProduct[0].variants && freeGiftProduct[0].variants.length > 0 && freeGiftProduct[0].variants[0].variantId return superiortierFreeGiftVariantId }, getAllValidFreeGiftTiers: function(validFreeGiftTiers, freeGiftCampaignIndex){ let allValidFreeGiftProductIds = [] let alValidFreeGiftTiers = [] for(let i=0; i< validFreeGiftTiers.length; i++){ let freeGiftProduct = validFreeGiftTiers[i].freeGiftProduct; //check if this tier already has a product in cart let ruleId = validFreeGiftTiers[i].ruleId let freeGiftsFromCart = gfg.gfgFreeGift.state.campaignWiseFreeGiftsFromCartData[freeGiftCampaignIndex] let freeGiftsFromCartForThisRuleId = freeGiftsFromCart.filter((product) => { return product.properties["_rule_id"] == ruleId }) if (freeGiftsFromCartForThisRuleId.length > 0) { // if yes then remove this tier from validFreeGiftTiers continue; }else { // if no then add this tier to allValidFreeGiftTiers alValidFreeGiftTiers.push(validFreeGiftTiers[i]) } // add all the free gift products to array } return alValidFreeGiftTiers; // return allValidFreeGiftProductIds }, gfgGetAllFreeGiftData: async function(){ // gfg.gfgFreeGift.state.freeGiftsShopifyDatafired = true; if(gfg.gfgFreeGift.state.freeGiftsShopifyData.length > 0){ return; } //check in session storage let freeGiftsShopifyDataFromSessionStorage = sessionStorage.getItem("gfgFreeGiftsShopifyData") let freeGiftsShopifyDataFromSessionStorageByHandle; let freeGiftsShopifyDataFromSessionStorageByProductId; if(freeGiftsShopifyDataFromSessionStorage && freeGiftsShopifyDataFromSessionStorage.length > 0){ freeGiftsShopifyDataFromSessionStorageByHandle = gfg.utility.convertArrayToObject(JSON.parse(freeGiftsShopifyDataFromSessionStorage), "handle") freeGiftsShopifyDataFromSessionStorageByProductId = gfg.utility.convertArrayToObject(JSON.parse(freeGiftsShopifyDataFromSessionStorage), "id") } let counterForHandlesPickedFromSessionStorage = 0; let productHandleArray = []; const productIdsArray = []; const storeFrontAccessToken = gfg?.settings?.merchantInfo?.storefrontAccessToken; const allFreeGiftCampaigns = gfg.settings.freeGifts || []; for(let i=0; i { if(freeGiftsShopifyDataFromSessionStorageByProductId && freeGiftsShopifyDataFromSessionStorageByProductId[productId]){ products.push(freeGiftsShopifyDataFromSessionStorageByProductId[productId]); return false; } return true; }); if(productIdsAfterFilter.length > 0){ const productGids = productIdsAfterFilter.map((productId)=> `gid://shopify/Product/${productId}`); const productsData = await gfg.customDiscountStorefrontApis.getProductsDataByIdWithAjaxResponse(productGids); products.push(...productsData); } gfg.gfgFreeGift.state.freeGiftsShopifyData = products } else{ const promises = productHandleArray.map(async (handle) => { // check if freeGiftsShopifyDataFromSessionStorageByHandle[handle] is there or not if(freeGiftsShopifyDataFromSessionStorageByHandle && freeGiftsShopifyDataFromSessionStorageByHandle[handle]){ counterForHandlesPickedFromSessionStorage++; return freeGiftsShopifyDataFromSessionStorageByHandle[handle] }else{ const productData = gfg.utility.getProductDataV2(handle) return productData; } }); gfg.gfgFreeGift.state.freeGiftsShopifyData = await Promise.all(promises) } // gfg.gfgFreeGift.state.freeGiftsShopifyData remove undefined and null and false values gfg.gfgFreeGift.state.freeGiftsShopifyData = gfg.gfgFreeGift.state.freeGiftsShopifyData.filter(item => item); gfg.utility.debugConsole("counterForHandlesPickedFromSessionStorage", counterForHandlesPickedFromSessionStorage) let freeGiftsShopifyData = JSON.parse(JSON.stringify(gfg.gfgFreeGift.state.freeGiftsShopifyData)) // convert array to an object with the key as handlevariantId gfg.gfgFreeGift.state.freeGiftsShopifyDataByHandles = gfg.utility.convertArrayToObject(freeGiftsShopifyData, "handle") gfg.gfgFreeGift.state.freeGiftShopifyDataByProductIds = gfg.utility.convertArrayToObject(freeGiftsShopifyData, "id") gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds = gfg.utility.createMapForVariantId(gfg.gfgFreeGift.state.freeGiftsShopifyDataByHandles) sessionStorage.setItem("gfgFreeGiftsShopifyData", JSON.stringify(gfg.gfgFreeGift.state.freeGiftsShopifyData)) }, gfgFreeGiftSuperiorTier: function(validFreeGiftTiers){ gfg.gfgFreeGift.state.superiorTier = validFreeGiftTiers[0] if(validFreeGiftTiers.length > 1){ for(let i=1; i< validFreeGiftTiers.length; i++){ let variantsExist = validFreeGiftTiers[i].freeGiftProduct[0] && validFreeGiftTiers[i].freeGiftProduct[0].variants && validFreeGiftTiers[i].freeGiftProduct[0].variants.length > 0; if(variantsExist){ // let nextSuperiorTierFreeGift = parseFloat(validFreeGiftTiers[i].freeGiftProduct[0].variants[0].price) let nextSuperiorTierFreeGift = validFreeGiftTiers[i].freeGiftProduct[0]; let nextSuperiorTierFreeGiftPrice = 0; if(nextSuperiorTierFreeGift){ for (let k = 0; k < nextSuperiorTierFreeGift.variants.length; k++) { let variant = nextSuperiorTierFreeGift.variants[k]; let currentVariantId = variant.variantId; let currentVariantData = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[currentVariantId]; if(currentVariantData && currentVariantData.available == true){ nextSuperiorTierFreeGiftPrice = parseFloat(variant.price); break; } } } // let currentSuperiorTierFreeGift = gfg.gfgFreeGift.state.superiorTier?.freeGiftProduct[0]?.variants[0]?.price || 0; let currentSuperiorTierFreeGift = gfg.gfgFreeGift.state.superiorTier.freeGiftProduct[0]; let currentSuperiorTierFreeGiftPrice = 0; if(currentSuperiorTierFreeGift){ for (let k = 0; k < currentSuperiorTierFreeGift.variants.length; k++) { let variant = currentSuperiorTierFreeGift.variants[k]; let currentVariantId = variant.variantId; let currentVariantData = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[currentVariantId]; if(currentVariantData && currentVariantData.available == true){ currentSuperiorTierFreeGiftPrice = parseFloat(variant.price); break; } } } let superiorTierFreeGift = parseFloat(currentSuperiorTierFreeGiftPrice) if(nextSuperiorTierFreeGiftPrice > superiorTierFreeGift){ gfg.gfgFreeGift.state.superiorTier = validFreeGiftTiers[i] } } } } gfg.utility.debugConsole("validFreeGiftTiers") }, gfgRemoveAllFreeGiftProductsExceptGiven: async function(freeGiftsFromCart, superiortierFreeGiftVariantId, freeGiftCampaignIndex){ const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; const currentCampaignPromoName = settings?.discountData_shopifyResponse?.title || settings?.name; if(freeGiftsFromCart.length == 0){ return } let freeGiftProductVariantDataArray = [] for(let i=0; i< freeGiftsFromCart.length; i++){ if(superiortierFreeGiftVariantId && superiortierFreeGiftVariantId == freeGiftsFromCart[i].variant_id){ continue } else if(freeGiftsFromCart[i].properties?.["_kite_promo_name"] != currentCampaignPromoName){ // if the free gift was not added by current campaign then don't push it for removal. continue } else{ freeGiftProductVariantDataArray.push([String(freeGiftsFromCart[i].key)]) } } if(freeGiftProductVariantDataArray.length > 0){ let freeGiftProductVariantDataObj = {} //freeGiftProductVariantDataArray convert to object for(let i=0; i< freeGiftProductVariantDataArray.length; i++){ let key = freeGiftProductVariantDataArray[i] freeGiftProductVariantDataObj[key] = 0 } let cartDataAfterUpdate = await gfg.utility.updateCart({ updates: freeGiftProductVariantDataObj}) if(cartDataAfterUpdate){ // gfg.state.cartData = await gfg.gfgFreeGift.utility.getCart(); // gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = await gfg.gfgFreeGift.utility.getCart(freeGiftCampaignIndex); gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = gfg.gfgFreeGift.utility.filterCartDataBasedOnSettings(cartDataAfterUpdate, freeGiftCampaignIndex) gfg.gfgFreeGift.state.isCartUpdatedByUs = true return true }else{ return false } } }, sortFreeGiftByVariantPrice: function(allFreeGiftsArray) { const n = allFreeGiftsArray.length; for (let i = 0; i < n - 1; i++) { let swapped = false; for (let j = 0; j < n - i - 1; j++) { let variantsExist_i = allFreeGiftsArray[i].freeGiftProduct[0] && allFreeGiftsArray[i].freeGiftProduct[0].variants && allFreeGiftsArray[i].freeGiftProduct[0].variants.length > 0; let variantsExist_j = allFreeGiftsArray[j].freeGiftProduct[0] && allFreeGiftsArray[j].freeGiftProduct[0].variants && allFreeGiftsArray[j].freeGiftProduct[0].variants.length > 0; if(variantsExist_i && variantsExist_j ){ const priceA = allFreeGiftsArray[j].freeGiftProduct[0].variants[0].price; const priceB = allFreeGiftsArray[j + 1].freeGiftProduct[0].variants[0].price; if (priceA < priceB) { const temp = allFreeGiftsArray[j]; allFreeGiftsArray[j] = allFreeGiftsArray[j + 1]; allFreeGiftsArray[j + 1] = temp; swapped = true; } } } if (!swapped) { break; } } }, checkIfValidFreeGiftIsThereInCart: function(freeGiftsFromCart, validFreeGiftTiers){ // if free gift variant let validFreeGiftProductVariantIds = [] for(let i=0; i< validFreeGiftTiers.length; i++){ let freeGiftProductVariantData = gfg.gfgFreeGift.f.getFreeGiftProductVariantsDataId(validFreeGiftTiers[i].freeGiftProduct); //expand freeGiftProductVariantData and push to validFreeGiftProductVariantIds for(let j=0; j< freeGiftProductVariantData.length; j++){ freeGiftProductVariantData[j] = parseInt(freeGiftProductVariantData[j]); validFreeGiftProductVariantIds.push(freeGiftProductVariantData[j]) } } //check if atleast one valid free gift is there in cart let isThereValidFreeGiftInCart = false for(let i=0; i< freeGiftsFromCart.length; i++){ let cartItem = freeGiftsFromCart[i] if(cartItem && cartItem.properties && cartItem.properties["_free_product"] && validFreeGiftProductVariantIds.includes(cartItem.variant_id)){ isThereValidFreeGiftInCart = true } } return isThereValidFreeGiftInCart }, getFreeGiftProductVariantsDataId: (freeGiftProducts)=>{ let allProductVariantIds = []; for(let i=0; i{ allProductVariantIds.push(variant.variantId); }) } return allProductVariantIds; }, checkIfSuperiorTierFreeGiftAlreadyInCart: function(freeGiftsFromCart, superiortierFreeGiftVariantId){ let isSuperiorTierFreeGiftAlreadyInCart = false for(let i=0; i< freeGiftsFromCart.length; i++){ let cartItem = freeGiftsFromCart[i] if(cartItem && cartItem.properties && cartItem.properties["_free_product"] && cartItem.variant_id == superiortierFreeGiftVariantId){ isSuperiorTierFreeGiftAlreadyInCart = true } } return isSuperiorTierFreeGiftAlreadyInCart }, gfgFindAllFreeGiftsFromCart: function(cartData){ let freeGiftsFromCart = []; for(let i=0; i< cartData.items.length; i++){ let cartItem = cartData.items[i]; if(cartItem && cartItem.properties && cartItem.properties["_free_product"]){ freeGiftsFromCart.push(cartItem); } } return freeGiftsFromCart; }, freeGiftsToBeRemovedFromCart: function(inValidFreeGiftTiers, cartData, freeGiftCampaignIndex){ try { const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; const currentCampaignPromoName = settings?.discountData_shopifyResponse?.title || settings?.name; let freeGiftsProductDataBeRemovedFromCart = [] for(let i=0; i < inValidFreeGiftTiers.length; i++){ let freeGiftProduct = inValidFreeGiftTiers[i].freeGiftProduct; for(let j=0; j< freeGiftProduct.length; j++){ freeGiftsProductDataBeRemovedFromCart.push({ freeGiftProduct: freeGiftProduct[j], ruleData: inValidFreeGiftTiers[i] // ruleData related to freeGiftProduct }); } } let freeGiftsToBeRemovedFromCart = [] for(let i=0; i< freeGiftsProductDataBeRemovedFromCart.length; i++){ // use cartData let freeGiftProduct = freeGiftsProductDataBeRemovedFromCart[i].freeGiftProduct; const ruleData = freeGiftsProductDataBeRemovedFromCart[i].ruleData; const ruleIdFromInvalidTierFreeGiftProduct = ruleData.ruleId; freeGiftProduct.variants.map((variant)=>{ let variant_id = variant.variantId; // let variantDataInCart = gfg.state.freeGiftsCartDataMap_variantId[variant_id]; const freeGiftItems = gfg.gfgFreeGift.f.gfgFindAllFreeGiftsFromCart(cartData); freeGiftItems.forEach((item)=>{ if(item.variant_id == variant_id && item?.properties?._rule_id === ruleIdFromInvalidTierFreeGiftProduct && item?.properties?._kite_promo_name === currentCampaignPromoName ){ freeGiftsToBeRemovedFromCart.push(item); } }) // if(variantDataInCart // && Object.keys(variantDataInCart).length > 0 // && ruleIdFromInvalidTierFreeGiftProduct === ruleIdFromVariantDataInCart // ){ // freeGiftsToBeRemovedFromCart.push(variantDataInCart); // } }) } return freeGiftsToBeRemovedFromCart; } catch (error) { gfg.utility.debugError("freeGiftsToBeRemovedFromCart", error) } }, gfgFreeGiftAllOfferStatus: function(freeGiftCampaignIndex){ let rulesList = gfg.settings.freeGifts[freeGiftCampaignIndex].rulesList; let validFreeGiftTiers = []; let inValidFreeGiftTiers = []; for(let i=0; i < rulesList.length ; i++){ let ruleListItem = rulesList[i] // const freeGiftProductVariantData = gfg.gfgFreeGift.f.getFreeGiftProductVariantsData(ruleListItem.freeGiftProduct); // ruleListItem.freeGiftsVariantsArr = freeGiftProductVariantData; let checkifFreeGiftConditionIsMetCnt = gfg.gfgFreeGift.f.checkifFreeGiftConditionIsMet(ruleListItem, gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex], i, freeGiftCampaignIndex); if (checkifFreeGiftConditionIsMetCnt) { validFreeGiftTiers.push(ruleListItem); }else{ inValidFreeGiftTiers.push(ruleListItem) } } gfg.gfgFreeGift.state.validFreeGiftTiersArray[freeGiftCampaignIndex] = validFreeGiftTiers; gfg.gfgFreeGift.state.inValidFreeGiftTiersArray[freeGiftCampaignIndex] = inValidFreeGiftTiers; // gfg.gfgFreeGift.f.sortFreeGiftByVariantPrice(rulesList) gfg.gfgFreeGift.state.AllFreeGiftTiersArray[freeGiftCampaignIndex] = rulesList; return { validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers: rulesList } }, gfgFreeGiftGetValidTierProductIds: function (validFreeGiftTiers){ const productIds = []; for (const tier of validFreeGiftTiers) { for (const product of tier.freeGiftProduct) { productIds.push(product.productId); } } return productIds; }, gfgGetValidTiersFreeGiftProductData : function(validFreeGiftTiers){ const validTiersFreeGiftProductData = []; try { for (const tier of validFreeGiftTiers) { for (const product of tier.freeGiftProduct) { validTiersFreeGiftProductData.push({ productId: product.productId, associatedRuleData: tier }); } } return validTiersFreeGiftProductData; } catch (error) { gfg.utility.debugConsole("gfgGetValidTiersFreeGiftProductData", error) } finally{ return validTiersFreeGiftProductData; } }, gfgFreeGiftPrepareParentUI: async function(validFreeGiftTiers, inValidFreeGiftTiers, configData, freeGiftCampaignIndex) { const isAccordion = gfg.gfgFreeGift.state.isAccordionArray[freeGiftCampaignIndex]; // Create container elements for the UI const gfgFreeGiftMsgParentContainerForDropDown = document.createElement("div"); const gfgFreeGiftMsgContainerForAccordion = document.createElement("div"); const gfgFreeGiftOptionsContainerDiv = document.createElement("div"); let gfgFreeGiftSelectDiv = document.createElement("div"); // Set common class names gfgFreeGiftMsgParentContainerForDropDown.classList.add('gfgFreeGiftMsgParentContainerForDropDown'); gfgFreeGiftMsgParentContainerForDropDown.id = `FREEGIFTCAMPAIGN-WIDGET-${freeGiftCampaignIndex}`; gfgFreeGiftMsgContainerForAccordion.classList.add('gfgFreeGiftMsgContainerForAccordion', `gfgFreeGiftMsgContainerForAccordion-${freeGiftCampaignIndex}`); gfgFreeGiftOptionsContainerDiv.classList.add("gfgFreeGiftOptionsContainerDiv"); gfgFreeGiftSelectDiv.classList.add('gfgFreeGiftSelectDiv', `gfgFreeGiftSelectDiv-${freeGiftCampaignIndex}`); if (isAccordion || (gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] == "CONDITION_FULFILLED")) { // Accordion-based UI elements const gfgFreeGiftMsgIcon = document.createElement("div"); const gfgFreeGiftMsgIconImageElement = document.createElement("img"); const gfgFreeGiftMsgTextContainer = document.createElement("div"); const gfgFreeGiftMsgTitle = document.createElement("div"); const gfgFreeGiftDropDownButton = document.createElement("div"); const gfgFreeGiftDropDownButtonImageEle = document.createElement("img"); // Add classes and attributes to icons, text, and buttons gfgFreeGiftMsgIcon.classList.add('gfgFreeGiftMsgIcon'); gfgFreeGiftMsgIconImageElement.setAttribute("src", configData.icon); gfgFreeGiftMsgIconImageElement.setAttribute("alt", "icon"); gfgFreeGiftMsgIconImageElement.classList.add('gfgFreeGiftMsgIconImageElement'); gfgFreeGiftMsgIcon.appendChild(gfgFreeGiftMsgIconImageElement); gfgFreeGiftMsgTextContainer.classList.add('gfgFreeGiftMsgTextContainer'); gfgFreeGiftMsgTitle.classList.add('gfgFreeGiftMsgTitle'); gfgFreeGiftMsgTitle.innerHTML = configData.title; gfgFreeGiftMsgTitle.style.fontWeight = "700"; gfgFreeGiftMsgTitle.style.fontSize = "14px"; gfgFreeGiftDropDownButton.classList.add("gfgFreeGiftDropDownButton", `gfgFreeGiftDropDownButton-${freeGiftCampaignIndex}`); gfgFreeGiftDropDownButtonImageEle.classList.add("gfgFreeGiftDropDownButtonImageEle"); gfgFreeGiftDropDownButtonImageEle.setAttribute("src", 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(CONSTANT_ARROW_SVG_APP7EXT)); // Handle widget expansion if needed if (gfg.gfgFreeGift.state.widgetAccordionExpandedArr[freeGiftCampaignIndex]) { gfgFreeGiftDropDownButton.classList.add("gfgFreeGiftDropDownButtonRotationClass"); gfgFreeGiftMsgContainerForAccordion.classList.add("gfgFreeGiftMsgContainerForAccordion-Expanded"); } // Append elements to the dropdown button gfgFreeGiftDropDownButton.appendChild(gfgFreeGiftDropDownButtonImageEle); // Append title and icon (if any) to the select div gfgFreeGiftMsgTextContainer.appendChild(gfgFreeGiftMsgTitle); if (configData.icon) { gfgFreeGiftSelectDiv.appendChild(gfgFreeGiftMsgIcon); gfgFreeGiftSelectDiv.style.gridTemplateColumns = "50px 1fr 50px"; } else { gfgFreeGiftSelectDiv.style.gridTemplateColumns = "1fr 0.5fr"; } // Append text and dropdown button (if needed) gfgFreeGiftSelectDiv.appendChild(gfgFreeGiftMsgTextContainer); if (isAccordion) { gfgFreeGiftSelectDiv.appendChild(gfgFreeGiftDropDownButton); } } else { // For non-accordion UI, prepare single offer validFreeGiftTiers = JSON.parse(JSON.stringify(validFreeGiftTiers)); // deep clone gfgFreeGiftSelectDiv = await gfg.gfgFreeGift.f.gfgFreeGiftSingleOfferPrepareUI(validFreeGiftTiers, configData, freeGiftCampaignIndex); } // Check if it's a single offer scenario const checkIfSingleOffer = !(isAccordion || gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] == "CONDITION_FULFILLED"); // Object to send to handle custom CSS for widget const htmlElementsToSendObj = { "gfgFreeGiftOptionsContainerDiv": gfgFreeGiftOptionsContainerDiv, "gfgFreeGiftSingleOffer": checkIfSingleOffer ? gfgFreeGiftSelectDiv : undefined, "gfgFreeGiftSelectDiv": checkIfSingleOffer ? undefined : gfgFreeGiftSelectDiv, "gfgFreeGiftMsgContainerForAccordion": gfgFreeGiftMsgContainerForAccordion }; gfg.gfgFreeGift.f.handleCustomCssForWidget(htmlElementsToSendObj, freeGiftCampaignIndex); // Return final elements return { gfgFreeGiftMsgParentContainerForDropDown, gfgFreeGiftMsgContainerForAccordion, gfgFreeGiftOptionsContainerDiv, gfgFreeGiftSelectDiv }; }, gfgFreeGiftSingleOfferPrepareUI: async function (validFreeGiftTiers, configData, freeGiftCampaignIndex) { validFreeGiftTiers = JSON.parse(JSON.stringify(validFreeGiftTiers)); const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; const allFreeGiftTiers = settings.rulesList; const userConfigData = settings.configuration; const allFreeGifts = settings.rulesList[0].freeGiftProduct; let freeGiftInsideCart; const validTierProductIds = gfg.gfgFreeGift.f.gfgFreeGiftGetValidTierProductIds(validFreeGiftTiers); const gfgSingleOffergiftContainerDiv = document.createElement("div"); gfgSingleOffergiftContainerDiv.classList.add("gfgSingleOffergiftContainerDiv"); let tierLengthToBeIterated = settings.isAutoAdd ? 1 : allFreeGifts.length; const widgetTitleBarNode = this.prepareFreeGiftWidgetTitleBar(freeGiftCampaignIndex); for (let i = 0; i < tierLengthToBeIterated; i++) { let product = allFreeGifts[i]; product["shopifyData"] = gfg.gfgFreeGift.state.freeGiftShopifyDataByProductIds[product.productId]; const imagePath = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[product?.variants[0]?.variantId]?.image || gfg.gfgFreeGift.utility.getFreeGiftProductModifiedBasicFieldData(product, "image"); product["title"] = gfg.gfgFreeGift.utility.getFreeGiftProductModifiedBasicFieldData(product, "title"); const isFreeGiftValid = validTierProductIds.includes(product.productId); const tier = allFreeGiftTiers[0]; // freeGiftInsideCart = gfg.gfgFreeGift.f.gfgFreeGiftGetFreeProductInCart(tier, freeGiftCampaignIndex); freeGiftInsideCart = gfg.gfgFreeGift.f.getFreeGiftProductDataInsideCartBasedOnRuleId(tier.ruleId, freeGiftCampaignIndex); const optionsConfigData = gfg.gfgFreeGift.f.gfgFreeGiftSetupConfigData(isFreeGiftValid, configData, 0, tier, product, freeGiftCampaignIndex); const gfgFreeGiftSingleOfferSelectDiv = document.createElement("div"); gfgFreeGiftSingleOfferSelectDiv.classList.add("gfgFreeGiftSingleOfferSelectDiv"); const gfgFreeGiftMsgIcon = document.createElement("div"); gfgFreeGiftMsgIcon.classList.add("gfgFreeGiftMsgIcon"); const gfgFreeGiftMsgIconImageElementOfItem = document.createElement("img"); gfgFreeGiftMsgIconImageElementOfItem.setAttribute("src", imagePath); gfgFreeGiftMsgIconImageElementOfItem.classList.add("gfgFreeGiftMsgIconImageElementOfItem"); gfgFreeGiftMsgIconImageElementOfItem.setAttribute("alt", "icon"); const gfgFreeGiftMsgTextContainer = document.createElement("div"); gfgFreeGiftMsgTextContainer.classList.add("gfgFreeGiftMsgTextContainer"); const gfgFreeGiftMsgTitle = document.createElement("div"); gfgFreeGiftMsgTitle.classList.add("gfgFreeGiftMsgTitle"); gfgFreeGiftMsgTitle.innerHTML = optionsConfigData.title; const gfgFreeGiftMsgSubTitle = document.createElement("div"); gfgFreeGiftMsgSubTitle.classList.add("gfgFreeGiftMsgSubTitle"); gfgFreeGiftMsgSubTitle.innerHTML = optionsConfigData.subtitle; const gfgFreeGiftMsgPillBox = this.gfgFreeGiftWidgetPreparePill(freeGiftCampaignIndex); const imageId = `FREEGIFTCAMPAIGN-${freeGiftCampaignIndex}-PRODUCTID-${product.productId}-IMG-${i}`; const imageIdSelector = '#' + imageId; gfgFreeGiftMsgIconImageElementOfItem.setAttribute("id", imageId); const shouldInjectClaimButton = !settings?.isAutoAdd || (settings?.isAutoAdd && settings?.isAutoAddFreeGiftOnceOnly); let variants = product.variants.filter((variant) => { if (variant.variantId) { let variantData = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[variant.variantId]; if (variantData && variantData.available) { return variant; } } }); gfgFreeGiftSingleOfferSelectDiv.setAttribute("product-id", product.productId); gfgFreeGiftSingleOfferSelectDiv.setAttribute("rule-id-tier", tier.ruleId); if (variants.length == 0) { product.shopifyData.available = false; } if (product.shopifyData && product.shopifyData.available == false) { gfgFreeGiftSingleOfferSelectDiv.classList.add("gfgFreeGiftOutOfStock"); } let variantSelect; const variantSelectInputId = `FREEGIFTCAMPAIGN-${freeGiftCampaignIndex}-PRODUCTID-${product.productId}-SELECT-${i}`; const variantSelectUniqueSelector = `#${variantSelectInputId}`; if (!freeGiftInsideCart && isFreeGiftValid && variants.length > 1) { variantSelect = document.createElement("select"); variantSelect.classList.add("gfgFreeGiftVariantSelect", `gfgFreeGiftVariantSelect${i}`); variantSelect.setAttribute("id", variantSelectInputId); variants.forEach(variant => { const optionSelect = document.createElement("option"); optionSelect.classList.add("gfgFreeGiftVariantOption"); optionSelect.value = variant?.variantId; optionSelect.textContent = variant?.title || "XX"; variantSelect.appendChild(optionSelect); }); } const gfgFreeGiftClaimButton = document.createElement("div"); gfgFreeGiftClaimButton.classList.add("gfgFreeGiftClaimButton", `gfgFreeGiftClaimButton${i}`); const buttonId = `FREEGIFTCAMPAIGN-${freeGiftCampaignIndex}-PRODUCTID-${product.productId}-CLAIMBUTTON-${i}`; gfgFreeGiftClaimButton.setAttribute("id", buttonId); gfgFreeGiftClaimButton.setAttribute("data-rule-id", tier.ruleId); gfgFreeGiftClaimButton.setAttribute("data-product-id", product.productId); gfgFreeGiftClaimButton.setAttribute("data-button-id", buttonId); let divsForMessaging = { gfgFreeGiftMsgTitle, gfgFreeGiftMsgSubTitle }; const buttonUniqueSelector = `#${buttonId}`; document.body.addEventListener("click", function (event) { if (event.target && event.target.matches(buttonUniqueSelector)) { if (gfg.utility.checkIfClickIsAllowed_sastaDebounce(event.target)) { gfg.gfgFreeGift.f.gfgFreeGiftClaimButtonClickAction(event, product, i, validFreeGiftTiers, freeGiftCampaignIndex); } else { gfg.utility.debugConsole("ignored click"); } } }); document.body.addEventListener("change", function (event) { if (event.target && event.target.matches(variantSelectUniqueSelector)) { event.preventDefault(); const currSelectedVariantId = event.target.value; const imageLink = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[currSelectedVariantId].image; const gfgFreeGiftMsgIconImageElementOfItem = document.querySelector(imageIdSelector); if (gfgFreeGiftMsgIconImageElementOfItem) { gfgFreeGiftMsgIconImageElementOfItem.setAttribute("src", imageLink); } } }); gfg.gfgFreeGift.f.setUpClaimButton(gfgFreeGiftClaimButton, userConfigData, isFreeGiftValid, freeGiftInsideCart, product, divsForMessaging, freeGiftCampaignIndex, tier); const htmlElementsToSendObj = { "gfgFreeGiftMsgTitleSingleOffer": gfgFreeGiftMsgTitle, "gfgFreeGiftMsgSubTitleSingleOffer": gfgFreeGiftMsgSubTitle, }; gfg.gfgFreeGift.f.handleCustomCssForWidget(htmlElementsToSendObj, freeGiftCampaignIndex); gfgFreeGiftMsgIcon.appendChild(gfgFreeGiftMsgIconImageElementOfItem); if (gfgFreeGiftMsgPillBox) { gfgFreeGiftMsgTextContainer.appendChild(gfgFreeGiftMsgPillBox); } gfgFreeGiftMsgTextContainer.appendChild(gfgFreeGiftMsgTitle); if (variantSelect == null) { gfgFreeGiftMsgTextContainer.appendChild(gfgFreeGiftMsgSubTitle); } else { gfgFreeGiftMsgTextContainer.appendChild(variantSelect); gfgFreeGiftMsgTextContainer.appendChild(gfgFreeGiftMsgSubTitle); } gfgFreeGiftSingleOfferSelectDiv.appendChild(gfgFreeGiftMsgIcon); gfgFreeGiftSingleOfferSelectDiv.appendChild(gfgFreeGiftMsgTextContainer); if (shouldInjectClaimButton) { gfgFreeGiftSingleOfferSelectDiv.appendChild(gfgFreeGiftClaimButton); } if (widgetTitleBarNode) { gfgSingleOffergiftContainerDiv.appendChild(widgetTitleBarNode); } gfgSingleOffergiftContainerDiv.appendChild(gfgFreeGiftSingleOfferSelectDiv); } return gfgSingleOffergiftContainerDiv; }, setUpClaimButton: function (claimButton, userConfig, isValid,freeGiftProductDataInsideCartForThisTier, product, divsForMessaging, freeGiftCampaignIndex, tierData) { try { const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; let { gfgFreeGiftMsgTitle, gfgFreeGiftMsgSubTitle } = divsForMessaging; let isProductStockAvailable = product?.shopifyData ? product.shopifyData.available : true; userConfig.addtionalFields.outOfStockSubtitle = userConfig.addtionalFields.outOfStockSubtitle || "Out of stock"; let productInsideCartForThisTier = freeGiftProductDataInsideCartForThisTier?.productId; const productInsideCartForThisTierRuleId = freeGiftProductDataInsideCartForThisTier?.properties?._rule_id; if (isProductStockAvailable === false) { gfgFreeGiftMsgSubTitle.classList.add("gfgFreeGiftOutOfStock", "gfgFreeGiftMsgSubTitleOutOfStock"); gfgFreeGiftMsgSubTitle.textContent = userConfig.addtionalFields.outOfStockSubtitle; return; } else { gfgFreeGiftMsgSubTitle.classList.remove("gfgFreeGiftOutOfStock", "gfgFreeGiftMsgSubTitleOutOfStock"); } if (!isValid) { claimButton.textContent = userConfig.addtionalFields.claimText; claimButton.classList.add("gfgFreeGiftInvalidProductClaimButton"); } else if (isValid && productInsideCartForThisTier) { claimButton.textContent = userConfig.addtionalFields.claimText; claimButton.classList.add("gfgFreeGiftValidProductInactiveClaimButton"); } else if (isValid && productInsideCartForThisTier == null) { claimButton.textContent = userConfig.addtionalFields.claimText; claimButton.classList.add("gfgFreeGiftClaimButtonAddToCart", "gfgFreeGiftReadyToClaimButton"); this.handleCustomCssForWidget({ "gfgFreeGiftReadyToClaimButton": claimButton }, freeGiftCampaignIndex); gfgFreeGiftMsgSubTitle.textContent = userConfig?.addtionalFields?.conditionMetCartSubtitle; } if (product.productId == productInsideCartForThisTier && tierData?.ruleId === productInsideCartForThisTierRuleId) { claimButton.textContent = userConfig.addtionalFields.claimedText; claimButton.classList.add('gfgFreeGiftActiveFreeGiftClaimButton'); this.handleCustomCssForWidget({ "gfgFreeGiftActiveFreeGiftClaimButton": claimButton }); let pillContainer = gfg.gfgFreeGift.f.gfgFreeGiftCreatePill(userConfig.addtionalFields.claimedCartSubtitle, isValid); gfgFreeGiftMsgSubTitle.innerHTML = pillContainer.outerHTML; gfgFreeGiftMsgTitle = document.createElement('div'); gfgFreeGiftMsgTitle.classList.add('gfgFreeGiftMsgTitle'); gfgFreeGiftMsgTitle.innerHTML = userConfig.addtionalFields.claimedCartTitle; gfgFreeGiftMsgSubTitle.classList.remove('gfgFreeGiftMsgSubTitleNoteTextColor'); } else if (isValid && product.productId != productInsideCartForThisTier && productInsideCartForThisTier != null) { gfgFreeGiftMsgSubTitle.style.display = "none"; gfg.utility.debugConsole("Another product from this tier has already been claimed"); } if (settings?.isAutoAdd && !settings?.isMultipleFreeGiftAllowed && settings?.isAutoAddFreeGiftOnceOnly == true) { const superiorTierFreeGiftVariantId = Number(gfg.gfgFreeGift.f.getSuperiorTierFreeGift()); const superiorTierFreeGiftProductId = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[superiorTierFreeGiftVariantId]?.product_id; const classesToRemove = [ "gfgFreeGiftInvalidProductClaimButton", "gfgFreeGiftValidProductInactiveClaimButton", "gfgFreeGiftClaimButtonAddToCart", "gfgFreeGiftReadyToClaimButton", "gfgFreeGiftActiveFreeGiftClaimButton" ]; classesToRemove.forEach(classToRemove => claimButton.classList.remove(classToRemove)); const isSameProduct = superiorTierFreeGiftProductId == product.productId; const isNotInCart = superiorTierFreeGiftProductId != productInsideCartForThisTier; const isInCart = superiorTierFreeGiftProductId == productInsideCartForThisTier; let newHtml; let classesToAdd = []; if (isValid && superiorTierFreeGiftProductId && isSameProduct && isNotInCart) { newHtml = userConfig.addtionalFields.claimText; classesToAdd = ['gfgFreeGiftClaimButtonAddToCart', 'gfgFreeGiftReadyToClaimButton']; } else if (isValid && superiorTierFreeGiftProductId && isSameProduct && isInCart) { newHtml = userConfig.addtionalFields.claimedText; classesToAdd = ['gfgFreeGiftValidProductInactiveClaimButton', 'gfgFreeGiftActiveFreeGiftClaimButton']; } else { newHtml = userConfig.addtionalFields.claimText; classesToAdd = ["gfgFreeGiftInvalidProductClaimButton"]; this.handleCustomCssForWidget({ "gfgFreeGiftInvalidProductClaimButton": claimButton }, freeGiftCampaignIndex); } claimButton.textContent = newHtml; classesToAdd.forEach(classToAdd => claimButton.classList.add(classToAdd)); } } catch (error) { gfg.utility.debugConsole("error in setUpClaimButton fn", error); } }, gfgFreeGiftContainerOverflow: function(){ try { return; } catch (error) { gfg.utility.debugError("gfgFreeGiftContainerOverflow", error) } }, gfgFreeGiftPrepareChildUI: async function(product, validFreeGiftTiers, inValidFreeGiftTiers, tierCount, tierData, configData, counter, freeGiftCampaignIndex) { const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; const currentCampaignPromoName = settings?.discountData_shopifyResponse?.title || settings?.name; const AllFreeGiftTiers = settings.rulesList; const allFreeGiftsShopifyData = gfg.gfgFreeGift.state.freeGiftsShopifyData; const userConfigData = settings.configuration; // const validTierProductIds = gfg.gfgFreeGift.f.gfgFreeGiftGetValidTierProductIds(validFreeGiftTiers); const validTiersFreeGiftProductData = gfg.gfgFreeGift.f.gfgGetValidTiersFreeGiftProductData(validFreeGiftTiers); const tier = tierData; // const freeGiftInsideCart = gfg.gfgFreeGift.f.gfgFreeGiftGetFreeProductInCart(tier, freeGiftCampaignIndex); const freeGiftInsideCart = gfg.gfgFreeGift.f.getFreeGiftProductDataInsideCartBasedOnRuleId(tier.ruleId, freeGiftCampaignIndex); // const freeGiftItemsInCart = gfg.gfgFreeGift.f.gfgFindAllFreeGiftsFromCart(gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex], freeGiftCampaignIndex); // const freeGiftInsideCart = freeGiftItemsInCart.find(item => // item.properties?._rule_id === tier.ruleId && // item.properties?._kite_promo_name === currentCampaignPromoName // )?.product_id || null; product["shopifyData"] = gfg.gfgFreeGift.state.freeGiftShopifyDataByProductIds[product.productId]; const imagePath = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[product?.variants[0]?.variantId]?.image || gfg.gfgFreeGift.utility.getFreeGiftProductModifiedBasicFieldData(product, "image"); product["title"] = gfg.gfgFreeGift.utility.getFreeGiftProductModifiedBasicFieldData(product, "title"); // let isFreeGiftValid = validTierProductIds.includes(product.productId); let isFreeGiftValid ; validTiersFreeGiftProductData.forEach(freeGiftProduct => { if(freeGiftProduct.productId == product.productId && freeGiftProduct.associatedRuleData.ruleId === tier.ruleId ){ isFreeGiftValid = true; } }); gfg.utility.debugConsole(isFreeGiftValid); const optionsConfigData = gfg.gfgFreeGift.f.gfgFreeGiftSetupConfigData(isFreeGiftValid, configData, tierCount, tier, product, freeGiftCampaignIndex); const gfgFreeGiftMsgOptionRow = document.createElement("div"); gfgFreeGiftMsgOptionRow.classList.add("gfgFreeGiftMsgOptionRow"); gfgFreeGiftMsgOptionRow.setAttribute("rule-id-tier", tier.ruleId); gfgFreeGiftMsgOptionRow.setAttribute("product-id", product.productId); const gfgFreeGiftMsgIconImageElementOfItem = document.createElement("img"); gfgFreeGiftMsgIconImageElementOfItem.setAttribute("src", imagePath); gfgFreeGiftMsgIconImageElementOfItem.classList.add("gfgFreeGiftMsgIconImageElementOfItem"); gfgFreeGiftMsgIconImageElementOfItem.setAttribute("alt", "icon"); const gfgFreeGiftMsgIcon = document.createElement("div"); gfgFreeGiftMsgIcon.classList.add("gfgFreeGiftMsgIcon"); gfgFreeGiftMsgIcon.appendChild(gfgFreeGiftMsgIconImageElementOfItem); const gfgFreeGiftMsgTitle = document.createElement("div"); gfgFreeGiftMsgTitle.classList.add("gfgFreeGiftMsgTitle"); gfgFreeGiftMsgTitle.innerHTML = optionsConfigData.title; const gfgFreeGiftMsgSubTitle = document.createElement("div"); gfgFreeGiftMsgSubTitle.classList.add("gfgFreeGiftMsgSubTitle"); gfgFreeGiftMsgSubTitle.innerHTML = ""; let showMsgSubTitle = true; if(freeGiftInsideCart && freeGiftInsideCart?.properties?._rule_id !== tier.ruleId){ showMsgSubTitle = false; } if(showMsgSubTitle){ gfgFreeGiftMsgSubTitle.innerHTML = optionsConfigData.subtitle; } const imageId = `FREEGIFTCAMPAIGN-${freeGiftCampaignIndex}-PRODUCTID-${product.productId}-IMG-${counter}`; const imageIdSelector = '#' + imageId; gfgFreeGiftMsgIconImageElementOfItem.setAttribute("id", imageId); const gfgFreeGiftMsgPillBox = this.gfgFreeGiftWidgetPreparePill(freeGiftCampaignIndex); const shouldInjectClaimButton = !settings?.isAutoAdd || (settings?.isAutoAdd && settings?.isAutoAddFreeGiftOnceOnly); let variants = product.variants.filter((variant) => { if (variant.variantId) { let variantData = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[variant.variantId]; if (variantData && variantData.available) { return variant; } } }); if (!product.shopifyData) { product.shopifyData = {}; } if (variants.length === 0) { product.shopifyData.available = false; } if (product.shopifyData.available === false) { gfgFreeGiftMsgOptionRow.classList.add("gfgFreeGiftOutOfStock"); } let variantSelect; const variantSelectInputId = 'FREEGIFTCAMPAIGN-' + freeGiftCampaignIndex + '-PRODUCTID-' + product.productId + '-SELECT-' + counter; const variantSelectUniqueSelector = '#' + variantSelectInputId; if (freeGiftInsideCart === null && isFreeGiftValid && variants.length > 1) { variantSelect = document.createElement("select"); variantSelect.classList.add("gfgFreeGiftVariantSelect"); variantSelect.classList.add("gfgFreeGiftVariantSelect" + counter); variantSelect.setAttribute("id", variantSelectInputId); variants.forEach((variant) => { const optionText = variant.title || "XX"; const optionSelect = document.createElement("option"); optionSelect.classList.add("gfgFreeGiftVariantOption"); optionSelect.setAttribute("value", variant.variantId); optionSelect.textContent = optionText; variantSelect.appendChild(optionSelect); }); } const gfgFreeGiftClaimButton = document.createElement("div"); gfgFreeGiftClaimButton.classList.add("gfgFreeGiftClaimButton"); gfgFreeGiftClaimButton.classList.add("gfgFreeGiftClaimButton" + counter); const buttonId = 'FREEGIFTCAMPAIGN-' + freeGiftCampaignIndex + '-PRODUCTID-' + product.productId + '-CLAIMBUTTON-' + counter; gfgFreeGiftClaimButton.setAttribute("id", buttonId); const buttonUniqueSelector = '#' + buttonId; function buttonClickHandler(event) { let ele = buttonUniqueSelector; if (gfg.utility.checkIfClickIsAllowed_sastaDebounce(ele)) { gfg.gfgFreeGift.f.gfgFreeGiftClaimButtonClickAction(event, product, counter, validFreeGiftTiers, freeGiftCampaignIndex); } else { gfg.utility.debugConsole("ignored click"); } } document.body.addEventListener('click', function (event) { if (event.target && event.target.matches(buttonUniqueSelector)) { buttonClickHandler(event); } }); function handleVariantChange(event, imageIdSelector) { event.preventDefault(); const variantSelectElement = event.target; const currSelectedVariantId = variantSelectElement.value; const imageLink = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[currSelectedVariantId].image; const gfgFreeGiftMsgIconImageElementOfItem = document.querySelector(imageIdSelector); gfgFreeGiftMsgIconImageElementOfItem.setAttribute('src', imageLink); } document.body.addEventListener('change', function (event) { const variantSelectElement = event.target; if (variantSelectElement && variantSelectElement.matches(variantSelectUniqueSelector)) { handleVariantChange(event, imageIdSelector); } }); let divsForMessaging = { gfgFreeGiftMsgTitle, gfgFreeGiftMsgSubTitle, }; gfg.gfgFreeGift.f.setUpClaimButton(gfgFreeGiftClaimButton, userConfigData, isFreeGiftValid, freeGiftInsideCart, product, divsForMessaging, freeGiftCampaignIndex, tier); const htmlElementsToSendObj = { "gfgFreeGiftMsgTitle": gfgFreeGiftMsgTitle, "gfgFreeGiftMsgSubTitle": gfgFreeGiftMsgSubTitle, }; gfg.gfgFreeGift.f.handleCustomCssForWidget(htmlElementsToSendObj, freeGiftCampaignIndex); const gfgFreeGiftMsgTextContainer = document.createElement("div"); gfgFreeGiftMsgTextContainer.classList.add("gfgFreeGiftMsgTextContainer"); if (gfgFreeGiftMsgPillBox) { gfgFreeGiftMsgTextContainer.appendChild(gfgFreeGiftMsgPillBox); } gfgFreeGiftMsgTextContainer.appendChild(gfgFreeGiftMsgTitle); if (variantSelect) gfgFreeGiftMsgTextContainer.appendChild(variantSelect); gfgFreeGiftMsgTextContainer.appendChild(gfgFreeGiftMsgSubTitle); gfgFreeGiftMsgOptionRow.appendChild(gfgFreeGiftMsgIcon); gfgFreeGiftMsgOptionRow.appendChild(gfgFreeGiftMsgTextContainer); if (shouldInjectClaimButton) { gfgFreeGiftMsgOptionRow.appendChild(gfgFreeGiftClaimButton); } return gfgFreeGiftMsgOptionRow; }, gfgFreeGiftPrepareUI: async function(validFreeGiftTiers, inValidFreeGiftTiers, AllFreeGiftTiers, freeGiftCampaignIndex){ // let validFreeGiftTiers = validFreeGiftTiers; // let inValidFreeGiftTiers = inValidFreeGiftTiers; let configData = {} let userConfigData = gfg.settings.freeGifts[freeGiftCampaignIndex].configuration let allProductsData = gfg.gfgFreeGift.state.freeGiftsShopifyData; let isAccordion = gfg.gfgFreeGift.state.isAccordionArray[freeGiftCampaignIndex]; let widgetTitleBarNode = false; let prevNextButton = false; gfg.utility.debugConsole('inside current prepare ui') let superiorTier = gfg.gfgFreeGift.state.superiorTier; // gfg.utility.debugConsole(superiorTier, 'superior tier') // gfg.utility.debugConsole(validFreeGiftTiers , 'valid free gift tiers') // let freeGiftInsideCart = gfg.gfgFreeGift.f.gfgFreeGiftGetFreeProductInCart(null, freeGiftCampaignIndex); let freeGiftInsideCart = gfg.gfgFreeGift.f.getFreeGiftProductDataInsideCartBasedOnRuleId(null, freeGiftCampaignIndex); if(AllFreeGiftTiers.length === 1 && AllFreeGiftTiers[0].freeGiftProduct.length === 1){ gfg.gfgFreeGift.state.isAccordionArray[freeGiftCampaignIndex] = false; isAccordion = false } configData = gfg.gfgFreeGift.f.prepareConfigData(userConfigData, freeGiftInsideCart, freeGiftCampaignIndex) let { gfgFreeGiftMsgParentContainerForDropDown, gfgFreeGiftMsgContainerForAccordion, gfgFreeGiftOptionsContainerDiv, gfgFreeGiftSelectDiv } = await gfg.gfgFreeGift.f.gfgFreeGiftPrepareParentUI(validFreeGiftTiers, inValidFreeGiftTiers, configData, freeGiftCampaignIndex) if(isAccordion){ let htmlContent = ""; widgetTitleBarNode = this.prepareFreeGiftWidgetTitleBar(freeGiftCampaignIndex); let gfgFreeGiftPrepareChildUIArr = await gfg.gfgFreeGift.f.gfgFreeGiftPrepareChildUIArr(AllFreeGiftTiers, configData, freeGiftCampaignIndex); gfg.gfgFreeGift.state.gfgFreeGiftPrepareChildUIArrCampaignWise[freeGiftCampaignIndex] = gfgFreeGiftPrepareChildUIArr; prevNextButton = this.prepareFreeGiftWidgetPrevNextButton(freeGiftCampaignIndex, gfgFreeGiftPrepareChildUIArr); if(prevNextButton){ htmlContent = this.getHtmlContentFromPagination(freeGiftCampaignIndex, gfgFreeGiftPrepareChildUIArr); gfgFreeGiftOptionsContainerDiv.innerHTML = htmlContent; } else{ const htmlContent = gfgFreeGiftPrepareChildUIArr.map(element => element.outerHTML).join(''); gfgFreeGiftOptionsContainerDiv.innerHTML = htmlContent; } } // if title bar is available then only append it if(widgetTitleBarNode){ gfgFreeGiftMsgContainerForAccordion.append(widgetTitleBarNode); } gfgFreeGiftMsgContainerForAccordion.append(gfgFreeGiftOptionsContainerDiv); if(prevNextButton){ gfgFreeGiftMsgContainerForAccordion.append(prevNextButton); } gfgFreeGiftMsgParentContainerForDropDown.append(gfgFreeGiftMsgContainerForAccordion) gfgFreeGiftMsgParentContainerForDropDown.append(gfgFreeGiftSelectDiv) return gfgFreeGiftMsgParentContainerForDropDown; }, gfgFreeGiftPrepareChildUIArr: async function(AllFreeGiftTiers, configData, freeGiftCampaignIndex){ let gfgFreeGiftPrepareChildUIArr = [] let counter = 0 for (let i = 0; i < AllFreeGiftTiers.length ; i++) { let tier = AllFreeGiftTiers[i]; let isAutoAdd = gfg.settings.freeGifts[freeGiftCampaignIndex].isAutoAdd let freeGiftProductArray = tier.freeGiftProduct; let tierLengthToBeIterated = 1; if(!isAutoAdd){ tierLengthToBeIterated = freeGiftProductArray.length } for(let k=0; k < tierLengthToBeIterated; k++){ let product = freeGiftProductArray[k]; let gfgFreeGiftMsgOptionRow = await gfg.gfgFreeGift.f.gfgFreeGiftPrepareChildUI(product, gfg.gfgFreeGift.state.validFreeGiftTiersArray[freeGiftCampaignIndex], gfg.gfgFreeGift.state.inValidFreeGiftTiersArray[freeGiftCampaignIndex], i, tier, configData, counter, freeGiftCampaignIndex); // gfgFreeGiftMsgOptionRow gfgFreeGiftPrepareChildUIArr.push(gfgFreeGiftMsgOptionRow); counter++; } } return gfgFreeGiftPrepareChildUIArr }, gfgFreeGiftCreatePill: function(title, isFreeGiftValid) { let color; if (isFreeGiftValid == true) { color = '#90EE90'; } else { color = '#75ffff'; } gfg.utility.debugConsole(title); let pillContainer = document.createElement('div'); pillContainer.classList.add('gfgFreeGiftPill-container'); let pillSegment = document.createElement('div'); pillSegment.classList.add('gfgFreeGiftPill-segment'); pillContainer.appendChild(pillSegment); let pillCenter = document.createElement('div'); pillCenter.classList.add('gfgFreeGiftPill-segment'); pillCenter.innerHTML = title; pillContainer.appendChild(pillCenter); pillSegment = document.createElement('div'); pillSegment.classList.add('gfgFreeGiftPill-segment'); pillContainer.appendChild(pillSegment); return pillContainer; }, gfgFreeGiftSetupConfigData: function(isFreeGiftValid, configData, iterator, tier, product, freeGiftCampaignIndex){ let optionsConfigData = {}; let tierConfigs = gfg.settings.freeGifts[freeGiftCampaignIndex].configuration.tierConfig[iterator]; let userConfigData = gfg.settings.freeGifts[freeGiftCampaignIndex].configuration let shopName = window.Shopify.shop const freeGiftCartData = gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex]; if(tier.ruleType == "BUY_PRODUCT_X"){ let FREE_GIFT_PRODUCT = product?.title || "XX"; let PRODUCT_QUANTITY = tier?.minProducts || "XX"; // let PRODUCT = tier?.productList[0].title || "XX"; // [1].productList[0].title // let PRODUCT_HANDLE = tier?.productList[0].handle || "XX"; // [1].productList[0].title let PRODUCT_LIST_TITLE = []; let PRODUCT_LIST_HANDLE = []; let PRODUCT_LIST = tier?.productList || []; if(PRODUCT_LIST.length > 0){ PRODUCT_LIST.forEach((product,index)=>{ // after 4th product add ellipsis if(index > 3){ PRODUCT_LIST_TITLE.push("..."); return; } PRODUCT_LIST_TITLE.push(product.title) PRODUCT_LIST_HANDLE.push(product.handle) }) } let PRODUCT = PRODUCT_LIST_TITLE.join(", "); if(PRODUCT_LIST.length > 1){ // add "(" and ")" to the product list PRODUCT = "(" + PRODUCT + ")" // PRODUCT = PRODUCT_LIST_TITLE.join(", "); } let PRODUCT_HANDLE = PRODUCT_LIST_HANDLE.join(", "); let CURRENT_QTY_BUY_PRODUCT_X = gfg.gfgFreeGift.f.gfgFreeGiftFindInArray(iterator, gfg.gfgFreeGift.state.CURRENT_QTY_BUY_PRODUCT_X) let REMAINING_QUANTITY = parseInt(PRODUCT_QUANTITY) - CURRENT_QTY_BUY_PRODUCT_X // optionsConfigData.title = optionsConfigData.title.replace("{{FREE_GIFT_PRODUCT}}", FREE_GIFT_PRODUCT); // optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{FREE_GIFT_PRODUCT}}", FREE_GIFT_PRODUCT); let tierConfigStringified = JSON.stringify(tierConfigs.conditionNotMet); optionsConfigData = JSON.parse(tierConfigStringified); optionsConfigData.title = optionsConfigData.title.replace("{{PRODUCT_QUANTITY}}", PRODUCT_QUANTITY); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{PRODUCT_QUANTITY}}", PRODUCT_QUANTITY); optionsConfigData.title = optionsConfigData.title.replace("{{PRODUCT}}", PRODUCT); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{PRODUCT}}", PRODUCT); // optionsConfigData.title = optionsConfigData.title.replace("{{PRODUCT_LINK}}", `${PRODUCT}`); // if PRODUCT_LIST_HANDLE is more than one then add a link to all products // let prepareaAnchorTags = "" // if(PRODUCT_LIST_HANDLE.length > 1){ // PRODUCT_LIST_HANDLE.forEach((handle, index)=>{ // // add a small space between each product // if(index > 0){ // prepareaAnchorTags += ", " // } // prepareaAnchorTags += `${PRODUCT_LIST_TITLE[index]}` // }) // }else{ // prepareaAnchorTags = `${PRODUCT}` // } const prepareaAnchorTags = gfg.gfgFreeGift.f.prepareAnchorTagsForBuyProductXRule({ rule:tier, PRODUCT_LIST_TITLE, PRODUCT_LIST_HANDLE, PRODUCT_HANDLE, PRODUCT }) optionsConfigData.title = optionsConfigData.title.replace("{{PRODUCT_LINK}}", prepareaAnchorTags); // optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{PRODUCT_LINK}}", `${PRODUCT}`); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{PRODUCT_LINK}}", prepareaAnchorTags); optionsConfigData.title = optionsConfigData.title.replace("{{FREE_GIFT_PRODUCT}}", FREE_GIFT_PRODUCT); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{FREE_GIFT_PRODUCT}}", FREE_GIFT_PRODUCT); // remaining qty optionsConfigData.title = optionsConfigData.title.replace("{{REMAINING_QUANTITY}}", REMAINING_QUANTITY); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{REMAINING_QUANTITY}}", REMAINING_QUANTITY); optionsConfigData.title = optionsConfigData.title.replace( "{{FREE_GIFT_PRODUCT_LINK}}", gfg.gfgFreeGift.utility.prepareTextInAnchorTag('PRODUCT_PAGE_HANDLE', FREE_GIFT_PRODUCT, product?.handle) ) optionsConfigData.icon = optionsConfigData.icon } if(tier.ruleType == "SPEND_X"){ let FREE_GIFT_PRODUCT = product?.title || "XX"; let minAmount = tier?.minimumCartValue || "0" minAmount = parseFloat(minAmount) let minAmountUserCurrency = gfg.utility.convertFromStoreCurrencyToCustomer(minAmount) // let REMAINING_AMOUNT = minAmountUserCurrency - (gfg.state.gfgFreeGiftCartData.items_subtotal_price/100) || '-1'; let REMAINING_AMOUNT = minAmountUserCurrency - (freeGiftCartData.total_price/100) || '-1'; // handle negative amount value in widget if(REMAINING_AMOUNT < 0){ REMAINING_AMOUNT = parseFloat(minAmountUserCurrency) + (freeGiftCartData.total_discount/100) - (freeGiftCartData.total_price/100); } let CURRENCY = gfg.utility.getCurrencySymbol() || "$"; REMAINING_AMOUNT = parseFloat(REMAINING_AMOUNT).toFixed(2) if(gfg.state?.formatPriceViaCustomScript){ REMAINING_AMOUNT *= 100; REMAINING_AMOUNT = gfg.utility.formatPriceWithSeparator(REMAINING_AMOUNT); } let tierConfigStringified = JSON.stringify(tierConfigs.conditionNotMet); optionsConfigData = JSON.parse(tierConfigStringified); optionsConfigData.title = optionsConfigData.title.replace("{{REMAINING_AMOUNT}}", REMAINING_AMOUNT); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{REMAINING_AMOUNT}}", REMAINING_AMOUNT); optionsConfigData.title = optionsConfigData.title.replace("{{CURRENCY}}", CURRENCY); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{CURRENCY}}", CURRENCY); optionsConfigData.title = optionsConfigData.title.replace("{{FREE_GIFT_PRODUCT}}", FREE_GIFT_PRODUCT); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{FREE_GIFT_PRODUCT}}", FREE_GIFT_PRODUCT); optionsConfigData.title = optionsConfigData.title.replace( "{{FREE_GIFT_PRODUCT_LINK}}", gfg.gfgFreeGift.utility.prepareTextInAnchorTag('PRODUCT_PAGE_HANDLE', FREE_GIFT_PRODUCT, product?.handle) ) optionsConfigData.icon = optionsConfigData.icon } if(tier.ruleType == "SPEND_X_IN_COLLECTION_Y"){ let FREE_GIFT_PRODUCT = product?.title || "XX"; let minAmount = tier?.minimumCartValue || "0" minAmount = parseFloat(minAmount) let minAmountUserCurrency = gfg.utility.convertFromStoreCurrencyToCustomer(minAmount) minAmountUserCurrency = parseFloat(minAmountUserCurrency) let REMAINING_AMOUNT_FROM_COLLECTION = gfg.gfgFreeGift.f.gfgFreeGiftFindInArray(iterator, gfg.gfgFreeGift.state.CURRENT_TOTAL_FOR_SPEND_X_IN_COLLECTION_Y) let REMAINING_AMOUNT = minAmountUserCurrency - REMAINING_AMOUNT_FROM_COLLECTION; REMAINING_AMOUNT = parseFloat(REMAINING_AMOUNT).toFixed(2) let CURRENCY = gfg.utility.getCurrencySymbol() || "$"; if(gfg.state?.formatPriceViaCustomScript){ REMAINING_AMOUNT *= 100; REMAINING_AMOUNT = gfg.utility.formatPriceWithSeparator(REMAINING_AMOUNT); } let COLLECTION_LIST_TITLE = []; let COLLECTION_LIST_HANDLE = []; let COLLECTION_LIST = tier?.collection || []; if (COLLECTION_LIST.length > 0) { COLLECTION_LIST.forEach((collection,index) => { // after 4th product add ellipsis if(index > 3){ COLLECTION_LIST_TITLE.push("..."); return; } COLLECTION_LIST_TITLE.push(collection.title); COLLECTION_LIST_HANDLE.push(collection.handle); }); } let COLLECTION = COLLECTION_LIST_TITLE.join(", "); if (COLLECTION_LIST.length > 1) { COLLECTION = "(" + COLLECTION + ")"; } let COLLECTION_HANDLE = COLLECTION_LIST_HANDLE.join(", "); let tierConfigStringified = JSON.stringify(tierConfigs.conditionNotMet); optionsConfigData = JSON.parse(tierConfigStringified); optionsConfigData.title = optionsConfigData.title.replace("{{REMAINING_AMOUNT}}", REMAINING_AMOUNT); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{REMAINING_AMOUNT}}", REMAINING_AMOUNT); optionsConfigData.title = optionsConfigData.title.replace("{{CURRENCY}}", CURRENCY); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{CURRENCY}}", CURRENCY); // optionsConfigData.title = optionsConfigData.title.replace("{{COLLECTION}}", COLLECTION); // optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{COLLECTION}}", COLLECTION); optionsConfigData.title = optionsConfigData.title.replace("{{COLLECTION}}", COLLECTION); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{COLLECTION}}", COLLECTION); let prepareaAnchorTagsForCollections = ""; if (COLLECTION_LIST_HANDLE.length > 1) { COLLECTION_LIST_HANDLE.forEach((handle, index) => { if (index > 0) { prepareaAnchorTagsForCollections += ", "; } // prepareaAnchorTagsForCollections += `${COLLECTION_LIST_TITLE[index]}`; prepareaAnchorTagsForCollections += ` ${COLLECTION_LIST_TITLE[index]} `; }); } else { // prepareaAnchorTagsForCollections = `${COLLECTION}`; prepareaAnchorTagsForCollections = ` ${COLLECTION} `; } // optionsConfigData.title = optionsConfigData.title.replace("{{COLLECTION_LINK}}", `${COLLECTION}`); // optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{COLLECTION_LINK}}", `${COLLECTION}`); optionsConfigData.title = optionsConfigData.title.replace("{{COLLECTION_LINK}}", prepareaAnchorTagsForCollections); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{COLLECTION_LINK}}", prepareaAnchorTagsForCollections); optionsConfigData.title = optionsConfigData.title.replace("{{FREE_GIFT_PRODUCT}}", FREE_GIFT_PRODUCT); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{FREE_GIFT_PRODUCT}}", FREE_GIFT_PRODUCT); optionsConfigData.title = optionsConfigData.title.replace( "{{FREE_GIFT_PRODUCT_LINK}}", gfg.gfgFreeGift.utility.prepareTextInAnchorTag('PRODUCT_PAGE_HANDLE', FREE_GIFT_PRODUCT, product?.handle) ) optionsConfigData.icon = optionsConfigData.icon } if(tier.ruleType == "BUY_ANY_PRODUCT_FROM_COLLECTION_Y"){ // let COLLECTION = tier?.collection[0].title || "XX"; // let COLLECTION_HANDLE = tier?.collection[0].handle || "XX"; let FREE_GIFT_PRODUCT = product?.title || "XX"; let PRODUCT_QUANTITY = tier?.minProducts || "XX"; let CURRENT_QTY_BUY_ANY_PRODUCT_FROM_COLLECTION_Y = gfg.gfgFreeGift.f.gfgFreeGiftFindInArray(iterator, gfg.gfgFreeGift.state.CURRENT_QTY_BUY_ANY_PRODUCT_FROM_COLLECTION_Y) let REMAINING_QUANTITY = parseInt(PRODUCT_QUANTITY) - CURRENT_QTY_BUY_ANY_PRODUCT_FROM_COLLECTION_Y let tierConfigStringified = JSON.stringify(tierConfigs.conditionNotMet); let COLLECTION_LIST_TITLE = []; let COLLECTION_LIST_HANDLE = []; let COLLECTION_LIST = tier?.collection || []; if (COLLECTION_LIST.length > 0) { COLLECTION_LIST.forEach((collection,index) => { // after 4th product add ellipsis if(index > 3){ COLLECTION_LIST_TITLE.push("..."); return; } COLLECTION_LIST_TITLE.push(collection.title); COLLECTION_LIST_HANDLE.push(collection.handle); }); } let COLLECTION = COLLECTION_LIST_TITLE.join(", "); if (COLLECTION_LIST.length > 1) { COLLECTION = "(" + COLLECTION + ")"; } let COLLECTION_HANDLE = COLLECTION_LIST_HANDLE.join(", "); optionsConfigData = JSON.parse(tierConfigStringified); // optionsConfigData.title = optionsConfigData.title.replace("{{PRODUCT}}", PRODUCT); // optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{PRODUCT}}", PRODUCT); optionsConfigData.title = optionsConfigData.title.replace("{{FREE_GIFT_PRODUCT}}", FREE_GIFT_PRODUCT); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{FREE_GIFT_PRODUCT}}", FREE_GIFT_PRODUCT); optionsConfigData.title = optionsConfigData.title.replace( "{{FREE_GIFT_PRODUCT_LINK}}", gfg.gfgFreeGift.utility.prepareTextInAnchorTag('PRODUCT_PAGE_HANDLE', FREE_GIFT_PRODUCT, product?.handle) ) optionsConfigData.title = optionsConfigData.title.replace("{{COLLECTION}}", COLLECTION); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{COLLECTION}}", COLLECTION); let prepareaAnchorTagsForCollections = ""; if (COLLECTION_LIST_HANDLE.length > 1) { COLLECTION_LIST_HANDLE.forEach((handle, index) => { if (index > 0) { prepareaAnchorTagsForCollections += ", "; } // prepareaAnchorTagsForCollections += `${COLLECTION_LIST_TITLE[index]}`; prepareaAnchorTagsForCollections += ` ${COLLECTION_LIST_TITLE[index]} `; }); } else { // prepareaAnchorTagsForCollections = `${COLLECTION}`; prepareaAnchorTagsForCollections = ` ${COLLECTION} `; } optionsConfigData.title = optionsConfigData.title.replace("{{COLLECTION_LINK}}", prepareaAnchorTagsForCollections); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{COLLECTION_LINK}}", prepareaAnchorTagsForCollections); // optionsConfigData.title = optionsConfigData.title.replace("{{COLLECTION}}", COLLECTION); // optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{COLLECTION}}", COLLECTION); // optionsConfigData.title = optionsConfigData.title.replace("{{COLLECTION_LINK}}", `${COLLECTION}`); // optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{COLLECTION_LINK}}", `${COLLECTION}`); optionsConfigData.title = optionsConfigData.title.replace("{{REMAINING_QUANTITY}}", REMAINING_QUANTITY); optionsConfigData.subtitle = optionsConfigData.subtitle.replace("{{REMAINING_QUANTITY}}", REMAINING_QUANTITY); optionsConfigData.icon = optionsConfigData.icon } if(isFreeGiftValid == true){ // optionsConfigData.subtitle = "Condition success"; userConfigData = gfg.settings.freeGifts[freeGiftCampaignIndex].configuration.addtionalFields // optionsConfigData.title = userConfigData.claimedCartTitle }else{ // optionsConfigData.title = userConfigData.addtionalFields.conditionNotMetText } // gfg.utility.debugConsole(optionsConfigData) return optionsConfigData }, gfgFreeGiftCreateMessageToast: function (event, freeGiftCampaignIndex) { try { const userConfigData = gfg.settings.freeGifts[freeGiftCampaignIndex].configuration; document.querySelectorAll('.gfgFreeGiftToast').forEach(toast => toast.remove()); const message = userConfigData.addtionalFields.alreadyClaimedText; const toast = document.createElement('div'); toast.classList.add('gfgFreeGiftToast'); toast.textContent = message; const parentElement = event.currentTarget.parentElement; if (parentElement) { parentElement.appendChild(toast); setTimeout(() => { toast.remove(); }, 5000); } } catch (error) { gfg.utility.debugConsole("Error in gfgFreeGiftCreateMessageToast:", error); } }, gfgFreeGiftGetFreeProductInCart: function(ruleData, freeGiftCampaignIndex){ let productId = null; let items = gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex].items if(!gfg.settings.freeGifts[freeGiftCampaignIndex].isMultipleFreeGiftAllowed){ for (const item of items) { if (item.properties && item.properties._free_product == "true" ) { productId = item.product_id; break; } } }else if(gfg.settings.freeGifts[freeGiftCampaignIndex].isMultipleFreeGiftAllowed && ruleData){ productId = gfg.gfgFreeGift.utility.getProductIdFromRuleId(ruleData.ruleId, freeGiftCampaignIndex) } return productId; }, checkifFreeGiftConditionIsMet: function (ruleData, cartData, iterator, freeGiftCampaignIndex) { if(ruleData.ruleType == "BUY_PRODUCT_X"){ let validProductList = []; const validProductVariantsList = []; ruleData.productList.forEach(product => { validProductList.push(product.productId) }) ruleData.productList.forEach(product => { product.variants.forEach(variant => { validProductVariantsList.push(variant.variantId) }) }) //check if condition is true let returnQty = 0 for(let i = 0; i < cartData.items.length; i++){ let cartItem = cartData.items[i] if(cartItem && cartItem.properties && cartItem.properties["_free_product"]){ continue } const conditionToCheckOnBasisOfProductId = validProductList.indexOf((""+cartItem.product_id)) >= 0; const conditionToCheckOnBasisOfVariantId = validProductVariantsList.indexOf((""+cartItem.variant_id)) >= 0; // if variant selction is enabled then check for product Id && variantId // else check for product id if(ruleData?.isProductXVariantSelectionEnabled === true){ if(conditionToCheckOnBasisOfProductId && conditionToCheckOnBasisOfVariantId){ returnQty += parseInt(cartItem.quantity) } } else{ if(conditionToCheckOnBasisOfProductId){ returnQty += parseInt(cartItem.quantity) } } } if(returnQty >= ruleData.minProducts){ return parseInt(returnQty / ruleData.minProducts) }else{ return 0 } } else if(ruleData.ruleType == "BUY_ANY_PRODUCT_FROM_COLLECTION_Y"){ let validCollectionList = [] ruleData.collectionsData.forEach(collection => { validCollectionList.push(collection) }) let returnQty = 0 //check if condition is true for(let i = 0; i < cartData.items.length; i++){ let cartItem = cartData.items[i] if(cartItem && cartItem.properties && cartItem.properties["_free_product"]){ continue } if(gfg.f.checkIfCartItemIsPartOfValidCollectionList(cartItem,validCollectionList)){ returnQty += parseInt(cartItem.quantity) } } // gfg.gfgFreeGift.state.CURRENT_QTY_BUY_ANY_PRODUCT_FROM_COLLECTION_Y = returnQty gfg.gfgFreeGift.f.gfgFreeGiftFindAndUpdateInArray(iterator, returnQty, gfg.gfgFreeGift.state.CURRENT_QTY_BUY_ANY_PRODUCT_FROM_COLLECTION_Y) if(returnQty >= ruleData.minProducts){ return parseInt(returnQty / ruleData.minProducts) }else{ return 0 } } else if(ruleData.ruleType == "SPEND_X_IN_COLLECTION_Y"){ let validCollectionList = [] ruleData.collectionsData.forEach(collection => { validCollectionList.push(collection) }) //check if condition is true let totalCartValue =0; for(let i = 0; i < cartData.items.length; i++){ let cartItem = cartData.items[i] if(cartItem && cartItem.properties && cartItem.properties["_free_product"]){ continue } if(gfg.f.checkIfCartItemIsPartOfValidCollectionList(cartItem,validCollectionList)){ // const cartItemPrice= gfg.utility.formatPriceWithoutSymbol(cartItem.price) const cartItemPrice= gfg.utility.formatPriceWithoutSymbol(cartItem.discounted_price) totalCartValue += cartItemPrice * cartItem.quantity } } // gfg.gfgFreeGift.state.CURRENT_TOTAL_FOR_SPEND_X_IN_COLLECTION_Y = totalCartValue gfg.gfgFreeGift.f.gfgFreeGiftFindAndUpdateInArray(iterator, totalCartValue, gfg.gfgFreeGift.state.CURRENT_TOTAL_FOR_SPEND_X_IN_COLLECTION_Y) if(totalCartValue >= gfg.utility.convertFromStoreCurrencyToCustomer(ruleData.minimumCartValue)){ return 1; } }else if(ruleData.ruleType == "SPEND_X"){ let totalCartValue =0; const config = gfg.settings.freeGifts[freeGiftCampaignIndex]; for(let i = 0; i < cartData.items.length; i++){ let cartItem = cartData.items[i] if(cartItem && cartItem.properties && cartItem.properties["_free_product"]){ continue } // const cartItemPrice= gfg.utility.formatPriceWithoutSymbol(cartItem.final_price) let cartItemPrice; if(config?.isUnifiedWidget && !config?.shouldUseDiscountedSubtotal) { cartItemPrice = gfg.utility.formatPriceWithoutSymbol(cartItem.price) } else { cartItemPrice = gfg.utility.formatPriceWithoutSymbol(cartItem.discounted_price) } totalCartValue += cartItemPrice * cartItem.quantity } if(totalCartValue >= gfg.utility.convertFromStoreCurrencyToCustomer(ruleData.minimumCartValue)){ return 1; } } return 0 }, prepareConfigData: function(userConfigData, freeGiftInsideCart, freeGiftCampaignIndex){ let configData = {} if(gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] == "CONDITION_NOT_MET"){ // configData.icon = userConfigData.globalConfig.conditionNotMet.icon || "https://cdn-icons-png.flaticon.com/512/3209/3209955.png" ; // take from gfg configData.icon = userConfigData.globalConfig.conditionNotMet.icon; configData.title = userConfigData.globalConfig.conditionNotMet.title; configData.subtitle = userConfigData.globalConfig.conditionNotMet.subtitle; configData.buttonText = userConfigData.addtionalFields.claimText configData.buttonBgColor = "" }else if(gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] == "CONDITION_FULFILLED"){ // configData.icon = userConfigData.globalConfig.conditionFulFilled.icon || "https://cdn-icons-png.flaticon.com/512/3209/3209955.png"; configData.icon = userConfigData.globalConfig.conditionFulFilled.icon; configData.title = userConfigData.globalConfig.conditionFulFilled.title; configData.subtitle = userConfigData.globalConfig.conditionFulFilled.subtitle; configData.buttonText = userConfigData.addtionalFields.claimText configData.buttonBgColor = "gray" }else if(gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] == "CONDITION_MET"){ // configData.icon = userConfigData.globalConfig.conditionInProgress.icon || "https://cdn-icons-png.flaticon.com/512/3209/3209955.png"; // take from gfg configData.icon = userConfigData.globalConfig.conditionInProgress.icon ; configData.title = userConfigData.globalConfig.conditionInProgress.title; configData.subtitle = userConfigData.globalConfig.conditionInProgress.subtitle; configData.buttonText = userConfigData.addtionalFields.claimText configData.buttonBgColor = "" } if(freeGiftInsideCart == null){ configData.buttonBgColor = "black" }else if(freeGiftInsideCart != null){ configData.buttonBgColor = "gray" } return configData }, refreshCartPageSection : async function(uniqueHtmlId,selectorRef) { let sectionHtmlTags = 'div[id^="shopify-section"]'; //check div ids are more than 1 //find all the divs with id starting with shopify-section // const divsWithShopifySection = find const divsWithShopifySection = document.querySelectorAll(sectionHtmlTags); if(divsWithShopifySection.length > 1){ for(let i = 0; i < divsWithShopifySection.length; i++){ let possibleCartSectionId = divsWithShopifySection[i].getAttribute('id'); if (possibleCartSectionId.includes(uniqueHtmlId)) { possibleCartSectionId = "#" + possibleCartSectionId; await gfg.gfgFreeGift.f.updateSectionContent(possibleCartSectionId,selectorRef); return true; // break out of .each loop after finding the cart section } // else if last item and no cart secton found then reload the page else if(i == divsWithShopifySection.length - 1){ window.location.reload(); } } // }); }else{ window.location.reload(); return; } }, updateCartState: async function(t, e, r, cartData) { //t is card data //e is even //refresh the cart gfg.gfgFreeGift.state.isCartUpdatedByUs = false; // if(gfg.settings.app.enablingApiFromSetInterval){ // gfg.gfgFreeGift.state.isCartUpdatedByUs = false; // } // xxxxxxxxx------------------------handle via script first If exists - starts ----------------------------------xxxxxxxx // because it's been nightmare to turn on/off toggle, because of false cases of old side cart code checks const executeCustomScriptAfterFreeGiftAddition = gfg.settings.app?.executeCustomScriptAfterFreeGiftAddition; const cutoffDateForOldCustomers = new Date("2024-12-09"); const userCreatedAt = new Date(gfg?.settings?.merchantInfo?.createdAt); if(executeCustomScriptAfterFreeGiftAddition && executeCustomScriptAfterFreeGiftAddition.trim() !== "" && window.location.pathname !== "/cart" && userCreatedAt > cutoffDateForOldCustomers ){ eval(executeCustomScriptAfterFreeGiftAddition); return; } // xxxxxxxxx------------------------handle via script first If exists - ends ----------------------------------xxxxxxxx // xxxxxxxxx------------------------Side cart update new code - starts ----------------------------------xxxxxxxx if (gfg?.settings?.app?.fireNewSideCartRefreshCodeFirst && window.location.pathname !== "/cart") { let slCartUpdateResult = await gfg.f.handleSkaiLamaSideCartUpdate(cartData); if (slCartUpdateResult) { return slCartUpdateResult; } } // xxxxxxxxx------------------------Side cart update new code - ends ----------------------------------xxxxxxxx async function refreshThePage(t, e) { try { if (gfg.settings.app.executeCustomScriptAfterFreeGiftAddition) { // gfg.settings.app.executeCustomScriptAfterFreeGiftAddition(); // execute the custom script eval(gfg.settings.app.executeCustomScriptAfterFreeGiftAddition); } if("/cart" === window.location.pathname || window.location.pathname === i + "cart"){ const uniqueCartItemsId = gfg.settings.app.cartPageItemsSectionId; const cartPageItemsSelector = gfg.settings.app.cartPageItemsSelector; await gfg.gfgFreeGift.f.refreshCartPageSection(uniqueCartItemsId,cartPageItemsSelector); // await gfg.gfgFreeGift.f.checkForFreeGift(); // await gfg.gfgFreeGift.f.checkForFreeGift(); return; } const sideCartSectionId = gfg.settings.app.sideCartSectionId; const sideCartSectionSelector = gfg.settings.app.sideCartSectionSelector; if(sideCartSectionId && sideCartSectionSelector){ await gfg.gfgFreeGift.f.updateSidecartSection(sideCartSectionId,sideCartSectionSelector); } // await gfg.gfgFreeGift.f.checkForFreeGift(); // await gfg.gfgFreeGift.f.checkForFreeGift(); return; } catch (t) { window.location.href = window.location.href.toString() gfg.utility.debugError("Failed to reload page using href assignment!", t), window.location.reload() } } // if this flg is set directly fire the refresh function don't check for default side cart which is present below. // this is used to avoid wrong mismatch of side cart code causing not execution of custom script written in refreshThePage function. const skipDefaultSideCartCheck = gfg.settings.app?.skipDefaultSideCartCheck; if(skipDefaultSideCartCheck){ return refreshThePage(t, e); } var n = this; var i = window.Shopify && window.Shopify.routes ? window.Shopify.routes.root : "/"; if ("/cart" === window.location.pathname || window.location.pathname === i + "cart") { await refreshThePage(t, e); } //type check the function function hn(t) { return hn = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) { return typeof t } : function(t) { return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t }, hn(t) } function f(message) { gfg.utility.debugConsole(message); } function z(message){ gfg.utility.debugConsole("z-function-",message); } try { var o, a, c, d, u, l, p, s, m, g, h, y; if(typeof window.HS_SLIDE_CART_UPDATE === "function" && document.querySelector(".hs-site-cart-popup-layout, .hs-header-layout")) return window.HS_SLIDE_CART_UPDATE(), f("Update drawer - iACart cart upsell cart drawer"), !1; if(window.Rebuy && window.Rebuy.Cart && document.querySelector(".rebuy-cart__flyout, .rebuy-cart__flyout-body")) return window.Rebuy.Cart.init(), f("Update drawer - Rebuy"), !1; if(window.Spurit && document.querySelector(".spurit-occ3__slide-drawer")) return window.Spurit.OneClickCheckout3.cartDrawer.refresh(), f("Update drawer - Cartly Slide Cart Drawer"), !1; if(typeof window.smeCartCall === "function" && document.querySelector(".salemaximize__drawer-side, .salemaximize__inner")) return window.smeCartCall(0), f("Update drawer - Cart upsell slide cart drawer"), !1; if (typeof window.SLIDECART_UPDATE === "function" && document.querySelector("#slidecarthq div")) return window.SLIDECART_UPDATE(), f("Update drawer - Slide Cart Drawer By AMP"), !1; if(typeof window.dispatchEvent === "function" && document.querySelector(".easy-slide-cart, .slide-cart-body")) return window.dispatchEvent(new CustomEvent("SLIDECARTY:refresh")), f("Update drawer - slide carty upsell & gift"), !1; if(typeof window.dispatchEvent === "function" && document.querySelector(".qsc2-drawer, .qsc2-drawer-body")) return document.dispatchEvent(new Event("ajax-cart:changed")), f("Update drawer - slide Cart, sticky add to cart"), !1; if(typeof window.updateQuickCart === "function" && document.querySelector(".quick-cart__container")) return window.updateQuickCart(), f("Update drawer updateQuickCart"), !1; if ("function" == typeof window.upcartRegisterAddToCart && document.querySelector(".upcart-product-item")) return window.upcartRegisterAddToCart(), f("Update drawer upcart app - upcartRegisterAddToCart"), !1; if(window.sharedFunctions && typeof window.sharedFunctions.updateSidebarCart === "function" && document.querySelector(".halo-sidebar")) return window.sharedFunctions.updateSidebarCart({"key":"value"}), f("Update drawer - Halo Sidebar Theme"), !1; if (window.HsCartDrawer && "function" == typeof window.HsCartDrawer.updateSlideCart && document.querySelector(".hs-site-cart-popup-layout, .hs-header-layout")) return window.HsCartDrawer.updateSlideCart(), !1; if (!window.ignoreRebuyDrawer && window.Rebuy && "object" === hn(window.Rebuy.Cart) && "function" == typeof window.Rebuy.Cart.fetchCart && document.querySelector("#rebuy-cart")) return window.Rebuy.Cart.fetchCart(), f("Update drawer Rebuy"), !1; if (window.SATCB && "object" === hn(window.SATCB.Widgets) && "object" === hn(window.SATCB.Widgets.CartSlider) && "function" == typeof window.SATCB.Widgets.CartSlider.openSlider && document.querySelector(".satcb-cs")) return window.SATCB.Widgets.CartSlider.openSlider(), f("Update drawer SATCB"), !1; if (t && "function" == typeof window.SLIDECART_SET_CART && document.querySelector("#slidecarthq div")) return window.SLIDECART_SET_CART(t), f("Update drawer SLIDECART_SET_CART"), !1; if (window.sellify && "object" === hn(window.sellify.ucd) && "object" === hn(window.sellify.ucd.helpers) && "object" === hn(window.sellify.ucd.helpers.ShopifyAPI) && "function" == typeof window.sellify.ucd.helpers.ShopifyAPI.getCart && document.querySelector("#sellify-ucd-cart-drawer")) return window.sellify.ucd.helpers.ShopifyAPI.getCart(window.sellify.ucd.helpers.ajaxCart.buildCart), f("Update drawer sellify"), !1; var w = window.csapps ? document.querySelector("[data-csapp_line_wrapper] .cart-quantity-wrap input[data-id]:not([readonly])") : null; if (w) return t && t.item_count ? (w.dispatchEvent(new Event("change", { bubbles: !0 })), f("Update drawer aiod cart app"), !1) : (f("Update drawer aiod cart app - empty cart = refresh"), refreshThePage(t, e)); if ("function" == typeof window.CD_REFRESHCART && document.querySelector("#cart-drawer-app .cd-cart")) return window.CD_REFRESHCART(), f("Update drawer CD_REFRESHCART"), !1; if ("function" == typeof window.BoostPFS && "object" === hn(window.BoostPFS.Utils) && document.querySelector(".boost-pfs-minicart-wrapper")) return f("Update drawer not supported for BoostPFS drawer. Refresh!"), refreshThePage(t, e); if ("function" == typeof window.openeamcart && document.querySelector("#shopify-section-eam-cart")) return window.openeamcart(), f("Update drawer openeamcart"), !1; if (t && void 0 !== window.vndHlp && "function" == typeof window.vndHlp.refreshCart) return window.vndHlp.refreshCart(t), f("Update drawer vndHlp.refreshCart"), !1; if (t && window.Cart && "function" == typeof window.Cart.buildCart) return window.Cart.buildCart(t), f("Update drawer Cart.buildCart"), !1; if (t && "function" == typeof window.buildCart && document.querySelector("#mini__cart.yv_side_drawer_wrapper")) return window.buildCart(t), f("Update drawer window.buildCart"), !1; if (window.cartNotification && "function" == typeof window.cartNotification.getCart && document.querySelector("#cart-notification")) return window.cartNotification.getCart(), f("Update drawer cartNotification"), !1; if ("function" == typeof window.do_cart_refresh) return window.do_cart_refresh(!1), f("Update drawer do_cart_refresh"), !1; if (window.theme && "function" == typeof window.theme.CartDrawer && window.theme.CartDrawer.toString().includes("new theme.Drawers")) return setTimeout((function() {return new window.theme.CartDrawer}), 250), f("Update drawer theme CartDrawer"), !1; if (null !== (o = window.theme) && void 0 !== o && null !== (a = o.settings) && void 0 !== a && a.cart_drawer && document.querySelector("#Cart-Drawer")) { if (!t || !t.item_count) return f("Update drawer #Cart-Drawer no items need to refresh"), refreshThePage(t, e); var v = document.createElement("input"); return v.style.display = "none", v.classList.add("qty"), v.dataset.index = "1", v.value = t.items[0].quantity, document.querySelector("#CartDrawerItem-1").appendChild(v), v.dispatchEvent(new Event("change", { bubbles: !0 })), f("Update drawer #Cart-Drawer"), !1 } if (window.Shopify && window.Shopify.theme && ("Expanse" === window.Shopify.theme.name || 902 === window.Shopify.theme.theme_store_id) && document.querySelector("#HeaderCart.site-header__drawer")) return document.dispatchEvent(new Event("cart:build")), f("Update drawer cart:build"), !1; if (t && "function" == typeof window.refreshCart) return window.refreshCart(t), f("Update drawer window.refreshCart"), !1; if ("undefined" != typeof slate && void 0 !== slate.cart && "function" == typeof slate.cart.updateCart) return slate.cart.updateCart(), f("Update drawer slate.cart.updateCart"), !1; if (t && "undefined" != typeof Shopify && "function" == typeof Shopify.updateQuickCart) return Shopify.updateQuickCart(t), f("Update drawer Shopify.updateQuickCart"), !1; if (t && void 0 !== window.bcActionList && "function" == typeof window.bcActionList.atcBuildMiniCartSlideTemplate) return window.bcActionList.atcBuildMiniCartSlideTemplate(t), "function" == typeof window.openMiniCart && window.openMiniCart(), f("Update drawer bcActionList"), !1; if (t && "undefined" != typeof Shopify && void 0 !== Shopify.updateCartInfo && document.querySelector(".top-cart-holder .cart-target form .cart-info .cart-content")) return Shopify.updateCartInfo(t, ".top-cart-holder .cart-target form .cart-info .cart-content"), f("Update drawer Shopify.updateCartInfo"), !1; if (t && "undefined" != typeof Shopify && void 0 !== Shopify.updateCartInfo && document.querySelector("#cart-info #cart-content")) return Shopify.updateCartInfo(t, "#cart-info #cart-content"), f("Update drawer Shopify.updateCartInfo, selector 2"), !1; if (window.theme && "object" === hn(window.theme.cart) && "function" == typeof window.theme.cart._updateCart && "function" == typeof window.$) return window.theme.cart._updateCart({}), document.body.dispatchEvent(new Event("updateCart")) , document.dispatchEvent(new Event("cart:build")), f("Update drawer cart:build + updateCart"), !1; if (window.theme && "function" == typeof window.theme.refreshCart) return window.theme.refreshCart(), f("Update drawer theme.refreshCart"), !1; if (document.querySelector("#sidebar-cart.Drawer form.Cart.Drawer__Content")) return setTimeout((function() { var t = new Event("product:added"); t.detail = {}, t.detail.quantity = 0, document.dispatchEvent(t) }), 250), setTimeout((function() { document.documentElement.dispatchEvent(new Event("cart:refresh")) }), 500), f("Update drawer BOOMR product:added / cart:refresh"), !1; if ("function" == typeof window.updateQtyCart && "function" == typeof window.$ && document.querySelector("#sidebar-cart.cart-drawer .cart-content[data-cart-content]")) return fetch("/cart?view=drawer×tamp=" + Date.now(), { credentials: "same-origin", method: "GET" }).then((function(t) { t.text().then((function(t) { document.querySelectorAll("[data-cart-content]").forEach(el => el.innerHTML = t); })) })), f("Update drawer #sidebar-cart.cart-drawer"), !1; if (document.querySelector("form#mini-cart .mini-cart__content .mini-cart__line-item")) return setTimeout((function() { return document.documentElement.dispatchEvent(new Event("cart:refresh")) }), 500), f("Update drawer custom cart-drawer elem form#mini-cart"), !1; var b = z("shopify_cart_state"); if (t && b && document.querySelector("form.cart-drawer")) { J("shopify_cart_state", JSON.stringify(t)); var S = new Event("storage"); return S.key = "shopify_cart_state", window.dispatchEvent(S), f("Update drawer BOOMR shopify_cart_state"), !1 } if (document.querySelector(["#ajaxifyModal #ajaxifyCart", "#ajaxifyDrawer #ajaxifyCart", ".fixed-cart-wrap #slidedown-cart", ".sidebar-drawer-container .sidebar-drawer"].join(","))) return t && t.item_count ? window.forceUpdateModalCart ? (f("Update drawer using custom forceUpdateModalCart"), window.forceUpdateModalCart(), !1) : (gfg.utility.debugConsole("All-in-One Free Gift on Cart: forceUpdateModalCart not set, but was expected."), refreshThePage(t, e)) : (gfg.utility.debugConsole("All-in-One Free Gift on Cart: forceUpdateModalCart reload due to empty cart."), refreshThePage(t, e)); if (window.theme && "object" === hn(window.theme.Cart) && "function" == typeof window.theme.Cart.updateCart) return window.theme.Cart.updateCart(), f("Update drawer Cart updateCart"), !1; if (t && "function" == typeof window.render_cart_drawer && window.render_cart_drawer.toString().includes("render_cart_drawer(cart, target, oldQtd, id_variant)")) return window.render_cart_drawer(t, jQuery(".list-products"), 0, ""), f("Update drawer render_cart_drawer"), !1; if (window.cart && "function" == typeof window.cart.getCart && "function" == typeof window.cart.closeCartDropdown && "function" == typeof window.cart.openCartDropdown && document.getElementById("cart-dropdown")) return window.cart.getCart(), f("Update drawer cart.getCart, #cart-dropdown"), !1; if (window.cart && "function" == typeof window.cart.getCart && document.querySelector(".cart-drawer")) return window.cart.getCart(), f("Update drawer cart.getCart, .cart-drawer"), !1; if (window.ajaxCart && "function" == typeof window.ajaxCart.load) return window.ajaxCart.load(), f("Update drawer ajaxCart load"), !1; if (window.Shopify && "object" === hn(window.Shopify.theme) && "object" === hn(window.Shopify.theme.jsAjaxCart) && "function" == typeof window.Shopify.theme.jsAjaxCart.updateView) return window.Shopify.theme.jsAjaxCart.updateView(), f("Update drawer jsAjaxCart updateView"), !1; if (window.Shopify && "object" === hn(window.Shopify.theme) && "object" === hn(window.Shopify.theme.ajaxCart) && "function" == typeof window.Shopify.theme.ajaxCart.init && document.querySelector(".js-mini-cart-trigger")) return document.querySelector(".js-mini-cart-trigger").dispatchEvent(new Event("click")), f("Update drawer js-mini-cart-trigger"), !1; if (window.theme && "object" === hn(window.theme.ajaxCart) && "function" == typeof window.theme.ajaxCart.update && document.querySelector("#CartDrawer.drawer")) return window.theme.ajaxCart.update(), f("Update drawer theme.ajaxCart.update"), !1; if (window.Shopify && "function" == typeof window.Shopify.addItem && "function" == typeof window.jQuery && document.querySelector(".cart-flyout .cart-flyout__content")) return jQuery.get("/cart?view=json", (function(t) { jQuery(".cart-flyout").html(t) })), f("Update drawer g-addtoicart cart-flyout"), !1; if (t && window.wetheme && "function" == typeof window.wetheme.toggleRightDrawer) return window.wetheme.toggleRightDrawer("cart", !0, { cart: t }), f("Update drawer toggleRightDrawer"), !1; if (window.gfTheme && "function" == typeof window.gfTheme.getCart) return window.gfTheme.getCart((function() {})), f("Update drawer gfTheme"), !1; if (t && z("cartCurrentData") && document.querySelector(".popup__body .js-popup-cart-ajax")) return J("cartCurrentData", JSON.stringify(t)), setTimeout((function() { return J("cartCurrentData", JSON.stringify(t)) }), 100), setTimeout((function() { return J("cartCurrentData", JSON.stringify(t)) }), 1e3), f("Update drawer cartCurrentData in local storage"), !1; if (document.querySelector("cart-drawer#mini-cart form#mini-cart-form, #shopify-section-mini-cart cart-drawer#mini-cart")) return t && t.item_count ? (setTimeout((function() { return document.documentElement.dispatchEvent(new Event("cart:refresh")) }), 750), f("Update drawer custom cart-drawer elem"), !1) : (f("When cart is empty custom cart-drawer elem's event may not work. Refresh!"), refreshThePage(t, e)); if (window.CartJS && "function" == typeof window.CartJS.getCart && document.querySelector("#cart-drawer,#cartDrawer")) return setTimeout((function() { return window.CartJS.getCart(null) }), 500), f("Update drawer CartJS getCart"), !1; if ("function" == typeof window.update_cart && document.querySelector("#custom-drawer-cart")) return window.update_cart(), f("Update drawer custom-drawer-cart"), !1; if (window.fcsb && "function" == typeof window.fcsb.fetchCart && document.querySelector("#sticky-app-client") && document.querySelector('#sticky-app-client [data-cl="mini-cart"]')) return window.fcsb.fetchCart(), f("Update drawer fcsb"), !1; if (window.theme && "function" == typeof window.theme.updateCartSummaries) return window.theme.updateCartSummaries(), f("Update drawer theme.updateCartSummaries"), !1; if (window.BT && "function" == typeof window.BT.updateHeaderCartHtml) return window.BT.updateHeaderCartHtml(!0), f("Update drawer BT.updateHeaderCartHtml"), !1; if (window.geckoShopify && "function" == typeof window.geckoShopify.GetCartData) return document.querySelectorAll(".jsccount").forEach((function(t) { return t.innerHTML = "" })), window.geckoShopify.GetCartData(1, 1), f("Update drawer geckoShopify.GetCartData"), !1; if (window.theme && "object" === hn(window.theme.classes) && "function" == typeof window.theme.classes.CoreCart && document.querySelector('[data-view="cart"] .cart--root')) return document.querySelector('[data-view="cart"] .cart--root').dispatchEvent(new Event("update-html")), f("Update drawer cart--root"), !1; if (window.theme && "function" == typeof window.theme.cart && "function" == typeof window.theme.cart.updateTotals && "function" == typeof(null === (c = document.querySelector('[data-view="cart"] .cart--root')) || void 0 === c ? void 0 : c.updateHtml)) return t && t.item_count ? (document.querySelector('[data-view="cart"] .cart--root').updateHtml(), f("Update drawer cartRoot.updateHtml"), !1) : (f("When cart is empty cartRoot.updateHtml does not work. Refresh!"), refreshThePage(t, e)); if (window.theme && "object" === hn(window.theme.classes) && "function" == typeof window.theme.classes.FrameworkCart && document.querySelector('.cart--root[data-js-class="Cart"]')) { var C = document.querySelector('.cart--root[data-js-class="Cart"]'); return C.dispatchEvent(new Event("updateHtml", { bubbles: !0 })), C.dispatchEvent(new Event("update-html", { bubbles: !0 })), f("Update drawer cart--root updateHtml/update-html event"), !1 } var q = window.CartDrawer ? document.querySelector("#shopify-section-cart-drawer cart-drawer cart-drawer-items, #CartDrawer.cart-drawer cart-drawer-items") : null; if (q && q.onChange) { if (t && t.items.length) { var A = { target: { dataset: { index: 1 }, value: t.items[0].quantity } }; return q.onChange(A), _("#CartDrawer-LineItemError-1 {display: none;}"), f('Update drawer customCartDrawerItems["onChange"]'), !1 } return f('Update drawer customCartDrawerItems["onChange"] - no items, force refresh!'), refreshThePage(t, e) } var E = window.themeVariables ? document.querySelector("#shopify-section-cart-drawer cart-drawer, .shopify-section cart-drawer") : null; if (E && "function" == typeof E._onCartRefreshListener) return E._onCartRefreshListener(), f("Update drawer #shopify-section-cart-drawer cart-drawer"), !1; var P = window.theme && "object" === hn(window.theme.CartDrawerSection) ? document.querySelector(".cart-drawer-modal cart-form.cart-drawer") : null; if (P && "function" == typeof P.refresh) return P.refresh(), f("Update drawer .cart-drawer-modal cart-form.cart-drawer"), !1; var O = window.CartDrawer ? document.querySelector("#Drawer-Cart cart-drawer") : null; if (O && "function" == typeof O.updateCart) return O.updateCart(), f("Update drawer #Drawer-Cart cart-drawer updateCart"), !1; var k, T, x, j, D, L = window.Shopify && "function" == typeof window.Shopify.CountryProvinceSelector ? document.querySelector("#main-cart-items quantity-input .quantity__input:not([readonly])") : null; if (L && "object" === hn(L.parentElement.changeEvent)) { if (!t || !t.item_count) return f("Update drawer quantity-input .quantity__input - empty cart = refresh"), refreshThePage(t, e); for (var I = parseInt(L.getAttribute("data-index")), N = 0, R = 1; R <= t.items.length; R++) { var G, M = null === (G = t.items[R - 1].handle) || void 0 === G ? void 0 : G.includes("docapp-free-gift"); if (M && R <= I && N++, !M && R < I && N--, !M && R >= I) break } return L.setAttribute("data-index", (I + N).toString()), L.dispatchEvent(L.parentElement.changeEvent), _("#main-cart-footer .cart-drawer__cart-error, mini-cart.cart-drawer .cart-item__error {display: none;}"), f("Update drawer quantity-input .quantity__input"), !1 } if ("function" == typeof window.showCart && document.querySelector(".drawer .drawer_container")) return window.showCart(), f("Update drawer showCart"), !1; if (window.WAU && "object" === hn(window.WAU.AjaxCart) && "function" == typeof window.WAU.AjaxCart.init && "function" == typeof window.WAU.AjaxCart.showDrawer && document.querySelector('#slideout-ajax-cart[data-wau-slideout="ajax-cart"] #mini-cart') && document.querySelector(".js-mini-cart-trigger.js-slideout-open")) return window.WAU.AjaxCart.hideDrawer({ cart_action: "drawer" }), setTimeout((function() { return document.querySelector(".js-mini-cart-trigger.js-slideout-open").dispatchEvent(new Event("click")) }), 400), f("Update drawer WAU - close + click"), !1; if ("function" == typeof window.fetchCart && document.querySelector(".cart-flyout .cart-drawer")) return window.fetchCart(), f("Update drawer fetchCart"), !1; if (window.elessiShopify && "function" == typeof window.elessiShopify.initAddToCart && document.querySelector(".cart__popup, .jas-mini-cart.jas-push-menu")) return t && t.item_count ? (window.elessiShopify.initAddToCart(), f("Update drawer elessiShopify.initAddToCart"), !1) : (f("Update drawer elessiShopify.initAddToCart - empty cart = refresh"), refreshThePage(t, e)); if (window.Shopify && "object" === hn(window.Shopify.theme) && "object" === hn(window.Shopify.theme.sections) && "object" === hn(window.Shopify.theme.sections.registered) && "object" === hn(window.Shopify.theme.sections.registered.cart) && document.querySelector(".cart__drawer .drawer__body")) return document.dispatchEvent(new Event("theme:cart:reload")), f("Update drawer Pipeline theme:cart:reload"), !1; if ("function" == typeof window.$ && window.theme && "function" == typeof window.theme.cartUpdatePopup && "function" == typeof window.theme.cartUpdatePopupModel && document.querySelector("#CartDrawer")) return document.body.dispatchEvent(new Event("completeChangeItem.ajaxCart")), f("Update drawer completeChangeItem.ajaxCart"), !1; if (window.wetheme && "object" === hn(window.wetheme.cartDrawer) && "function" == typeof window.wetheme.cartDrawer.updateCartDrawer && document.querySelector("#cartSlideoutWrapper")) return window.wetheme.cartDrawer.updateCartDrawer(t), f("Update drawer updateCartDrawer"), !1; if (window.iopCart && "object" === hn(window.iopCart.api) && "function" == typeof window.iopCart.api.refreshCart && document.querySelector("#iop-cart-root")) return window.iopCart.api.refreshCart(), f("Update drawer iopCart"), !1; if (window.theme && "object" === hn(window.theme.AjaxCart) && "function" == typeof window.theme.AjaxCart.fetch && document.querySelector("#AjaxCartDrawer")) return window.theme.AjaxCart.fetch(), f("Update drawer theme.AjaxCart.fetch"), !1; if (window.theme && "function" == typeof window.theme.Cart && document.querySelector(".side-cart-popup [data-quantity-input]:not([readonly])")) return t && t.items.length ? (document.querySelector(".side-cart-popup [data-quantity-input]:not([readonly])").dispatchEvent(new Event("change", { bubbles: !0 })), f("Update drawer side-cart-popup change event"), !1) : (f("Update drawer side-cart-popup change event - no items, force refresh!"), refreshThePage(t, e)); if (window.theme && window.theme.dropdown && "function" == typeof window.theme.ajax_cart_dropdown && document.querySelector("#cart-dropdown")) return window.theme.ajax_cart_dropdown(), f("Update drawer ajax_cart_dropdown"), !1; if ("function" == typeof CartItems && document.querySelector("#drawer-cart")) return document.dispatchEvent(new Event("ajaxProduct:added")), f("Update drawer ajaxProduct:added"), _("#drawer-cart .cart-item__details .cart-item__error {display: none;}"), !1; if ("function" == typeof(null === (d = window.PXUTheme) || void 0 === d || null === (u = d.jsAjaxCart) || void 0 === u ? void 0 : u.updateView) && document.querySelector("#theme-ajax-cart")) return setTimeout((function() { return window.PXUTheme.jsAjaxCart.updateView() }), 250), f("Update drawer PXUTheme.jsAjaxCart.updateView"), !1; if ("function" == typeof(null === (l = window.ctzn_global) || void 0 === l ? void 0 : l.refreshCart) && document.querySelector("#cart-content")) return window.ctzn_global.refreshCart(), f("Update drawer ctzn_global.refreshCart"), !1; if ("object" === ("undefined" == typeof store ? "undefined" : hn(store)) && "function" == typeof(null === (p = store) || void 0 === p ? void 0 : p.getCart) && document.querySelector("#drawer-items")) return store.getCart(), f("Update drawer store.getCart"), !1; if (null !== (s = window.Avatar) && void 0 !== s && null !== (m = s.theme) && void 0 !== m && null !== (g = m.sections) && void 0 !== g && null !== (h = g.SliderCart) && void 0 !== h && null !== (y = h.instance) && void 0 !== y && y.refreshCartSlider && document.querySelector('[data-section-type="slider-cart"]')) return null === (k = window.Avatar) || void 0 === k || null === (T = k.theme) || void 0 === T || null === (x = T.sections) || void 0 === x || null === (j = x.SliderCart) || void 0 === j || null === (D = j.instance) || void 0 === D || D.refreshCartSlider(), f("Update drawer Avatar.theme"), !1; var H = "function" == typeof CartItems ? document.querySelector("mini-cart") : null; if (H) return t && t.item_count ? (H.onChange({ target: { dataset: { index: 1 }, value: t.items[0].quantity } }), _("#MiniCart-Line-item-error-1 {display: none;}"), f("Update drawer athensThemeMiniCart"), !1) : (f("Update drawer athensThemeMiniCart - empty cart = refresh"), refreshThePage(t, e)); var B = document.querySelector("sidebar-drawer#site-cart .cart-item input.qty:not([readonly])"); if (B) return t && t.item_count ? (B.dispatchEvent(new Event("input", { bubbles: !0 })), f("Update drawer sidebar-drawer#site-cart .cart-item .qty"), !1) : (f("Update drawer sidebar-drawer#site-cart .cart-item .qty - empty cart = refresh"), refreshThePage(t, e)); var F = [".cart-drawer[data-cart-drawer] input.quantity:not([readonly])", "#dropdown-cart input.item-quantity:not([readonly])", ".halo-sidebar .previewCart input.quantity:not([readonly])", "form.mini-cart .mini-cart__content input.quantity-selector__value:not([readonly])", '#cart-modal-form-body .cart-modal-qty[type="text"]:not([readonly])', ".drawer .cart-drawer__content-container .cart__popup-qty--input:not([readonly])", ".side-cart-item input.quantity__input:not([readonly])", ".top-bar .cart-container .mini-cart__item input[data-cart-quantity-input]:not([readonly])", "#t4s-mini_cart .t4s-mini_cart__item input[data-action-change]:not([readonly])"], W = document.querySelector(F.join(",")); if (t && W) return t.item_count ? (setTimeout((function() { var r = document.querySelector(F.join(",")); if (!r) return f("Update drawer failed due to missing element after timeout. Force refresh!"), n.refreshThePage(t, e); var i = r.getAttribute("docapp-data-protected"), o = null; if (t.items.forEach((function(t, e) { o || i && i.includes(t.variant_id) && (o = e + 1) })), o) { var a = r.getAttribute("data-line"); U(a) && a < 1e3 && r.setAttribute("data-line", o); var c = r.getAttribute("data-line-id"); U(c) && c < 1e3 && r.setAttribute("data-line-id", o); var d = r.getAttribute("data-product_id"); U(d) && d < 1e3 && r.setAttribute("data-product_id", o); var u = r.closest("[data-line-item-id]"); if (u) { var l = u.getAttribute("data-line-item-id"); U(l) && l < 1e3 && u.setAttribute("data-line-item-id", o) } var p = r.closest("[data-line]"); if (p) { var s = p.getAttribute("data-line"); U(s) && s < 1e3 && p.setAttribute("data-line", o) } var m = r.closest("[data-cart-item][data-line-id]"); if (m) { var _ = m.getAttribute("data-line-id"); U(_) && _ < 1e3 && m.setAttribute("data-line-id", o) } } r.dispatchEvent(new Event("change", { bubbles: !0 })) }), 150), f("Update drawer cartModalQtyNonGiftChangeSelectors match pending..."), !1) : (f("Update drawer cartModalQtyNonGiftChangeSelectors - empty cart = refresh"), refreshThePage(t, e)); if (window.freeGiftCartUpsellProAppDisableRefreshExceptOnCart) return f("Refresh disabled except on cart page. END"), !1; if (document.querySelector([".go-cart__drawer", ".ajax-cart__drawer.js-ajax-cart-drawer", "mini-cart.cart-drawer .mini-cart", ".halo-sidebar .previewCart", '.nt_mini_cart .mini_cart_items input[name="updates[]"]', ".widget_shopping_cart .mini_cart_item input.custom-qty", '.mini-products-list .item .qty-group input[name="updates[]"]', "#monster-upsell-cart", ".cart-flyout__inner .quick-cart__items .quick-cart__quantity", ".quick-cart__cart .quick-cart__item .quick-cart__qty", ".quick-cart__cart .quick-cart__item .quick-cart__button", "#shopify-section-quick-cart .quick-cart__items .quantity-input__input", ".flyout__content .cart-drawer", '#right-drawer-slot [x-data="ThemeModule_CartItems"] input[\\@change]', '[data-cart-row][data-cart-item-key] input[name="updates[]"][\\@change]', '#modals-rightDrawer [x-data="ThemeModule_CartItems"]', ".cart-mini[data-cart-mini] .cart-mini-sidebar"].join(","))) return f("Update drawer force refresh due to unsupported element"), refreshThePage(t, e); if (t && window.Shopify && "function" == typeof window.Shopify.onCartUpdate && !window.Shopify.onCartUpdate.toString().includes("{alert(")) return window.Shopify.onCartUpdate(t), f("Update drawer Shopify onCartUpdate"), !1; if (document.querySelector(["#cart-summary-overlay", ".cart-summary-overlay .cart-summary-overlay__actions a.to-cart", ".atc-banner--container[data-atc-banner]"].join(",")) || window.freeGiftCartUpsellProAppDisableRefreshExceptOnCart) return f("Update drawer not required due to found element/variable."), !1; var V = document.querySelector(".site-header__cart #CartCount"); if (V) return t && (V.innerHTML = t.item_count), f("Update drawer not required on Simple."), !1; var K = document.querySelectorAll("cart-notification #cart-notification #cart-notification-button"); if (K.length) return t && (K.forEach((function(e) { return e.innerHTML = e.innerHTML.replace(/\d+/, t.item_count) })), document.querySelectorAll(".cart-count-bubble span[aria-hidden]").forEach((function(e) { return e.innerHTML = t.item_count }))), f("Update drawer not required on Dawn."), !1 if(typeof window.RefreshCart === "function") return window.RefreshCart(), f("Update drawer RefreshCart"), !1; if(document.querySelector("cart-drawer, #CartDrawer")){ // Future Ref ->>>>>> use window.BOOMR.themeName to get actual theme name rather using Shopify.theme.name return gfg.gfgFreeGift.f.updateSidecartSection("cart-drawer", "#CartDrawer", false), f("Update drawer"), !1; } } catch (t) { f("Update drawer - ERROR!!!"), gfg.utility.debugError("Attempted to update drawer cart, Error: ", t) } return f("Update drawer - no integration found."), refreshThePage(t, e) }, updateSectionContent : async function(htmlIdOfSection,selectorRef, onErrorReload = true) { //the format is shopify-section- pop based on shopify-section- // let sectionId = htmlIdOfSection.split("shopify-section-").pop(); // only pop if it is there in the string let sectionId = htmlIdOfSection.split("shopify-section-").length > 1 ? htmlIdOfSection.split("shopify-section-").pop() : htmlIdOfSection; return new Promise((resolve, reject) => { const url = `/${gfg.utility.getLocale()}/?section_id=${sectionId}&app=gfgfreegift`; fetch(url) .then(response => response.text()) .then(htmlResponse => { const targetElement = document.querySelector(selectorRef); if (window.location.pathname === "/cart") { if (targetElement) { targetElement.innerHTML = htmlResponse; } } else { const tempDiv = document.createElement("div"); tempDiv.innerHTML = htmlResponse; const updatedContent = tempDiv.querySelector(selectorRef)?.innerHTML; if (targetElement && updatedContent) { targetElement.innerHTML = updatedContent; } } resolve(); }) .catch(error => { // gfg.utility.debugConsole('Failed to fetch section content for:', sectionId); // window.location reload the page if(onErrorReload){ window.location.reload(); } resolve(); }) }); }, updateSidecartSection : async function(sideCartSectionID, selectorRef, onErrorReload = true) { await gfg.gfgFreeGift.f.updateSectionContent(sideCartSectionID, selectorRef, onErrorReload); }, insertIntoPageWrapper: function (freeGiftHTML, freeGiftCampaignIndex) { const promotionId = gfg.settings.freeGifts[freeGiftCampaignIndex]._id; let showNotifcationSettings = gfg.settings.freeGifts[freeGiftCampaignIndex].showFreeGiftNotificationSettings; let showOnthisProductPage = false; if(showNotifcationSettings && showNotifcationSettings.productPages) { showOnthisProductPage = true; } if(showNotifcationSettings && showNotifcationSettings.specificProductPages && showNotifcationSettings.specificProduct && showNotifcationSettings.specificProduct.length && showNotifcationSettings.specificProduct.length > 0) { let currentProductPageId = gfg.f.getProductPageId() if(currentProductPageId != "undefined") { let validProductIds = showNotifcationSettings.specificProduct.map(function (item) { return parseInt(item.productId); }); if(validProductIds.includes(currentProductPageId)) { showOnthisProductPage = true; } } } if(showNotifcationSettings && showNotifcationSettings?.specificCollectionPages && showNotifcationSettings?.specificCollectionData && showNotifcationSettings?.specificCollectionData?.length && showNotifcationSettings.specificCollectionData.length > 0) { let currentProductPageId = gfg.f.getProductPageId() if(currentProductPageId != "undefined") { let collectionsList = showNotifcationSettings.specificCollectionData; for(let i=0; i x.productId === currentProductPageId)){ showOnthisProductPage = true break } } } } if(showOnthisProductPage) { let gftFreeGiftWrapperProductEle = gfg.utility.findWrapperElement("FREE_GIFT", "PRODUCT_PAGE", promotionId); if( "product"=== gfg.state.page_type && gftFreeGiftWrapperProductEle.length == 0){ // lets insertIntoPageWrapper in productPageWrapperV2 gfg.productPage.f.insertWrapperIntoPage() gftFreeGiftWrapperProductEle = document.querySelectorAll(".gfgProductPageWrapperV2 .gftFreeGiftWrapper"); } const freeGiftHTMLClone = freeGiftHTML.cloneNode(true); gftFreeGiftWrapperProductEle.forEach((element) => { const widgetPresent = element.querySelector(`#FREEGIFTCAMPAIGN-WIDGET-${freeGiftCampaignIndex}`); if (widgetPresent) { widgetPresent.replaceWith(freeGiftHTMLClone); } else { element.appendChild(freeGiftHTMLClone); } }); } if(showNotifcationSettings && showNotifcationSettings.cartPage) { let gftFreeGiftWrapperCartEle = gfg.utility.findWrapperElement("FREE_GIFT", "CART_PAGE", promotionId); if(gftFreeGiftWrapperCartEle.length == 0){ gftFreeGiftWrapperCartEle = document.querySelectorAll(".gfgCartPageWrapperV2 .gftFreeGiftWrapper"); } const freeGiftHTMLClone = freeGiftHTML.cloneNode(true); gftFreeGiftWrapperCartEle.forEach((element) => { const widgetPresent = element.querySelector(`#FREEGIFTCAMPAIGN-WIDGET-${freeGiftCampaignIndex}`); if (widgetPresent) { widgetPresent.replaceWith(freeGiftHTMLClone); } else { element.appendChild(freeGiftHTMLClone); } }); } // renderPoweredByLabel gfg.f.addPoweredByBlock(); // insert into parent element // gfg.elements.gfgCartGiftMsgAndWrapWrapperParent.find(".gfgGiftMsgAndWrapWrapperInnerEle").append(settings.giftingOptions.shopifyPageinnerHTML); //cartPageText // insert final element into productPageWrapperV2 // gfg.elements.cartPageWrapperV2.find(".gfgCartUpsellWrapper").append(gfg.elements.gfgCartGiftMsgAndWrapWrapperParent); // gfg.elements.cartPageWrapperV2.find(".gftFreeGiftWrapper").html(freeGiftHTML); }, gfgFreeGiftClaimButtonClickAction: async function(event, product, counter,validFreeGiftTiers, freeGiftCampaignIndex){ try { if(gfg.settings.freeGifts[freeGiftCampaignIndex].isMultipleFreeGiftAllowed){ //JSON.parse(JSOn.stringiyf) all the arguments pass product = JSON.parse(JSON.stringify(product)) counter = JSON.parse(JSON.stringify(counter)) validFreeGiftTiers = gfg.gfgFreeGift.state.validFreeGiftTiersArray[freeGiftCampaignIndex] return await gfg.gfgFreeGift.f.gfgFreeGiftClaimButtonClickAction_multipleFreeGifts(event, product, counter,validFreeGiftTiers, freeGiftCampaignIndex) } let userConfigData = gfg.settings.freeGifts[freeGiftCampaignIndex].configuration gfg.utility.debugConsole(product) if(gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] == "CONDITION_FULFILLED"){ gfg.utility.debugConsole('inside click button') gfg.gfgFreeGift.f.gfgFreeGiftCreateMessageToast(event, freeGiftCampaignIndex); return } if(gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] != "CONDITION_MET" ){ return } if(!event.target.classList.contains('gfgFreeGiftClaimButtonAddToCart')){ return } let variantId = product.variants[0].variantId const ruleIdTier = event.target.closest('.gfgFreeGiftSingleOfferSelectDiv')?.getAttribute('rule-id-tier') || event.target.closest('.gfgFreeGiftMsgOptionRow')?.getAttribute('rule-id-tier'); let selectData = event.target.parentElement.querySelector('.gfgFreeGiftVariantSelect' + counter)?.value; if(typeof selectData != 'undefined'){ variantId = selectData } event.target.textContent = userConfigData.addtionalFields.addingText; let isGiftAdded = await gfg.gfgFreeGift.f.gfgAddSuperiorTierFreeGiftToCart({ variantId: variantId, ruleId: ruleIdTier }, freeGiftCampaignIndex); let latestCartDataAfterAddingFreeGift; if(isGiftAdded == true){ // gfg.state.cartData = await gfg.gfgFreeGift.utility.getCart(); // gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = await gfg.gfgFreeGift.utility.getCart(freeGiftCampaignIndex); latestCartDataAfterAddingFreeGift = await gfg.utility.getCart(); const parsedCartData = JSON.parse(JSON.stringify(latestCartDataAfterAddingFreeGift)); gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = gfg.gfgFreeGift.utility.filterCartDataBasedOnSettings(parsedCartData, freeGiftCampaignIndex); gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_FULFILLED" gfg.gfgFreeGift.f.handleWidgetAccordionOnFreeGiftClaim(freeGiftCampaignIndex); let freeGiftMsgHtml = await gfg.gfgFreeGift.f.gfgFreeGiftPrepareUI(gfg.gfgFreeGift.state.validFreeGiftTiersArray[freeGiftCampaignIndex], gfg.gfgFreeGift.state.inValidFreeGiftTiersArray[freeGiftCampaignIndex], gfg.gfgFreeGift.state.AllFreeGiftTiersArray[freeGiftCampaignIndex], freeGiftCampaignIndex); gfg.gfgFreeGift.f.insertIntoPageWrapper(freeGiftMsgHtml, freeGiftCampaignIndex); gfg.gfgFreeGift.f.gfgFreeGiftContainerOverflow() gfg.gfgFreeGift.f.registerEvents(freeGiftCampaignIndex) } // gfg.utility.debugConsole('claim button clicked ', variantId, counter, selectData ); if(gfg.gfgFreeGift.state.isCartUpdatedByUs){ await gfg.gfgFreeGift.f.updateCartState(null, null, null, latestCartDataAfterAddingFreeGift); } } catch (error) { gfg.utility.debugConsole("error in gfgFreeGiftClaimButtonClickAction", error); } }, gfgFreeGiftClaimButtonClickAction_multipleFreeGifts: async function(event, product, counter,validFreeGiftTiers, freeGiftCampaignIndex){ const validTierProductIds = gfg.gfgFreeGift.f.gfgFreeGiftGetValidTierProductIds(validFreeGiftTiers); let isFreeGiftValid = validTierProductIds.includes(product.productId); if(!isFreeGiftValid){ return } // alert(`Free Gift Added to Cart, the value of the free gift is ${isFreeGiftValid}`) gfg.utility.debugConsole("validTierProductIds", validTierProductIds, product.productId, isFreeGiftValid); let userConfigData = gfg.settings.freeGifts[freeGiftCampaignIndex].configuration gfg.utility.debugConsole(product) let ruleIdTier = event.target.closest('.gfgFreeGiftMsgOptionRow')?.getAttribute('rule-id-tier') || event.target.closest('.gfgFreeGiftSingleOfferSelectDiv')?.getAttribute('rule-id-tier'); let variantId = product.variants[0].variantId let freeGiftProductData = { variantId: variantId, _rule_id: ruleIdTier, }; //getProductIdFromRuleIdTier let productId = gfg.gfgFreeGift.utility.getProductIdFromRuleId(ruleIdTier, freeGiftCampaignIndex); if (productId) { gfg.gfgFreeGift.f.gfgFreeGiftCreateMessageToast(event, freeGiftCampaignIndex); return; } //find the parent class known as gfgFreeGiftMsgOptionRow and then get the attr rule-id-tier let selectData = event.target .parentElement .querySelector('.gfgFreeGiftVariantSelect' + counter)?.value; // gfg.utility.debugConsole(selectData, 'selectData') if(typeof selectData != 'undefined'){ variantId = selectData freeGiftProductData.variantId = variantId } event.target.textContent = userConfigData.addtionalFields.addingText; let isGiftAdded = await gfg.gfgFreeGift.f.gfgAddFreeGiftToCart(freeGiftProductData, freeGiftCampaignIndex); let latestCartDataAfterAddingFreeGift; if(isGiftAdded == true){ // gfg.state.cartData = await gfg.gfgFreeGift.utility.getCart(); // gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = await gfg.gfgFreeGift.utility.getCart(freeGiftCampaignIndex); latestCartDataAfterAddingFreeGift = await gfg.utility.getCart(); const parsedCartData = JSON.parse(JSON.stringify(latestCartDataAfterAddingFreeGift)); gfg.state.gfgFreeGiftCartData[freeGiftCampaignIndex] = gfg.gfgFreeGift.utility.filterCartDataBasedOnSettings(parsedCartData, freeGiftCampaignIndex); gfg.gfgFreeGift.state.prepareUIStateArray[freeGiftCampaignIndex] = "CONDITION_FULFILLED"; gfg.gfgFreeGift.f.handleWidgetAccordionOnFreeGiftClaim(freeGiftCampaignIndex); let freeGiftMsgHtml = await gfg.gfgFreeGift.f.gfgFreeGiftPrepareUI(gfg.gfgFreeGift.state.validFreeGiftTiersArray[freeGiftCampaignIndex], gfg.gfgFreeGift.state.inValidFreeGiftTiersArray[freeGiftCampaignIndex], gfg.gfgFreeGift.state.AllFreeGiftTiersArray[freeGiftCampaignIndex], freeGiftCampaignIndex); gfg.gfgFreeGift.f.insertIntoPageWrapper(freeGiftMsgHtml, freeGiftCampaignIndex); gfg.gfgFreeGift.f.gfgFreeGiftContainerOverflow() gfg.gfgFreeGift.f.registerEvents(freeGiftCampaignIndex) } // gfg.utility.debugConsole('claim button clicked ', variantId, counter, selectData ); if(gfg.gfgFreeGift.state.isCartUpdatedByUs){ await gfg.gfgFreeGift.f.updateCartState(null, null, null, latestCartDataAfterAddingFreeGift); } }, gfgFreeGiftCheckCustomerConditions:function(freeGiftCampaignIndex){ try{ let conditions = gfg.settings.freeGifts[freeGiftCampaignIndex].conditionsData.conditionsList let conditionOperator = gfg.settings.freeGifts[freeGiftCampaignIndex].conditionsData.conditionsOperator if(conditions.length >= 1){ let checkConditionFlag = gfg.gfgFreeGift.f.gfgCheckConditionOutcome(conditions,conditionOperator); gfg.gfgFreeGift.state.isCustomerConditionMet = checkConditionFlag; return checkConditionFlag; } // when no condition setted up; return true; }catch(err){ gfg.utility.debugConsole('gfgFreeGiftCheckCustomerConditions ', err); } }, gfgCheckConditionOutcome: function(conditions, conditionOperator){ // map over conditions, for each condition fire respective function using switchcase, and record answer on an array // use this array to evaluate, wether it passes or not on basis of conditionOperator let resultantValue = []; let result = false; let operatorType = conditionOperator; for(let i=0; i < conditions.length; i++){ const currRule = conditions[i]; const ruleType = conditions[i].ruleType; switch(ruleType){ case "customerTags": { const val = gfg.gfgFreeGift.f.gfgCheckConditionForCustomerTags(currRule) || false; resultantValue.push(val); break; } case "isCustomerLoggedIn": { const val = gfg.gfgFreeGift.f.gfgCheckConditionForCustomerLoggedIn(currRule) || false; resultantValue.push(val); break; } case "countrySelects": { const val = gfg.gfgFreeGift.f.gfgCheckConditionForCountry(currRule); resultantValue.push(val); break; } default: { resultantValue.push(false); break; } } } // performs the AND operation on the resultantValue array function checkIfAllTrue(booleanArray) { for (let i = 0; i < booleanArray.length; i++) { if (booleanArray[i] == false) { return false; } } return true; } result = checkIfAllTrue(resultantValue); return result; }, gfgCheckConditionForCustomerLoggedIn: function(condition){ // gfg.utility.debugConsole('gfgCheckConditionForCustomerLoggedIn ==> ', condition) // return true; try{ let res = false; let customerData = gfg.state.activeCustomerData; let isLoggedIn = customerData.isCustomerLoggedInBool; if(condition.ruleValue.value == "yes"){ res = isLoggedIn ? true : false; }else{ res = isLoggedIn ? false : true; } return res; }catch(err){ gfg.utility.debugConsole('gfgCheckConditionForCustomerLoggedIn ', err); } }, gfgCheckConditionForCustomerTags: function(condition){ try{ let res = false; const customerData = gfg.state.activeCustomerData; const customerTags = customerData?.customerTags || []; const conditionTags = condition.ruleValue.tags; // check for customer include tags if(condition.ruleValue.operatorType == "is" ){ res = gfg.gfgFreeGift.f.gfgCheckConditionForCustomerIncludeTags(conditionTags, customerTags); } // check for customer exclude tags else if(condition.ruleValue.operatorType == "isNot" ){ res = gfg.gfgFreeGift.f.gfgCheckConditionForCustomerExcludeTags(conditionTags, customerTags); } return res; }catch(err){ gfg.utility.debugConsole( 'gfgCheckConditionForCustomerTags', err); } }, gfgCheckConditionForCustomerIncludeTags: function(conditionTags, customerTags){ try { return gfg.utility.checkIfTwoArrayHasCommonElement(conditionTags, customerTags) } catch (error) { gfg.utility.debugConsole('error from gfgCheckConditionForCustomerIncludeTags', error); } }, gfgCheckConditionForCustomerExcludeTags: function(conditionTags, customerTags){ try { const isLoggedIn = gfg.gfgFreeGift.f.gfgCheckIfCustomerLoggedIn(); // if customer is not logged in then widget should be shown if(!isLoggedIn){ return true; } const isAnyExcludedTagMatches = gfg.utility.checkIfTwoArrayHasCommonElement(conditionTags, customerTags); return !isAnyExcludedTagMatches; } catch (error) { gfg.utility.debugConsole('error from gfgCheckConditionForCustomerExcludeTags', error); } }, gfgCheckForActiveURLBasedCampaign: function(freeGiftCampaignIndex){ try { const freeGiftsData = gfg.settings.freeGifts[freeGiftCampaignIndex]; const urlBasedCampaign = freeGiftsData?.urlBasedCampaign; const isCampaignUrlEnabled = freeGiftsData?.isCampaignUrlEnabled; if(!urlBasedCampaign){ return true; } let activeCampaignName = gfg.state.activeCampaignName; if(isCampaignUrlEnabled == true && urlBasedCampaign && activeCampaignName === urlBasedCampaign.value){ return true; } if(!isCampaignUrlEnabled || !urlBasedCampaign){ return true; } return false; } catch (error) { gfg.utility.debugConsole('gfgCheckForActiveURLBasedCampaigns ', error); } }, gfgCheckIfCustomerLoggedIn: function(){ // this function checks if the customer is logged in or not. let customerData = gfg.state.activeCustomerData; let isLoggedIn = customerData.isCustomerLoggedInBool; return isLoggedIn; }, handleCustomCssForWidget: function(variablesObj, freeGiftCampaignIndex){ try { const getFontWeightValue = (fontStyle) => { if(fontStyle === "bold"){ return "700"; }else if(fontStyle === "medium"){ return "600"; } else{ return "400"; } } const widgetConfiguration = gfg.settings.freeGifts[freeGiftCampaignIndex]?.widgetConfiguration; if (!widgetConfiguration || Object.keys(widgetConfiguration).length === 0) { return; } const { colorConfig, fontConfig } = widgetConfiguration; // Define CSS configurations for each key as an object const cssConfigurations = { "gfgFreeGiftOptionsContainerDiv": { "background-color": colorConfig?.boxBgColor, "--FREEGIFT-SCROLLBAR-THUMB-BG-COLOR": colorConfig?.borderColor // we are updating css variable value here to handle scrollbar bg color dynamically }, "gfgFreeGiftSelectDiv": { "border": `2px solid ${colorConfig?.borderColor}`, "background-color": colorConfig?.boxBgColor }, "gfgFreeGiftMsgTitle": { "color": colorConfig?.titleColor, "font-weight": getFontWeightValue(fontConfig?.titleFontStyle), "font-size": gfg.utility.getFontSizeValue(fontConfig?.titleFontSize) }, "gfgFreeGiftMsgSubTitle": { "color": colorConfig?.subtitleColor || "##777575", "font-weight": getFontWeightValue(fontConfig?.subtitleFontStyle) || "600", "font-size": `${fontConfig?.subtitleFontSize}px` }, "gfgFreeGiftSingleOffer": { "background-color": colorConfig?.boxBgColor, "border": `2px solid ${colorConfig?.borderColor}` }, "gfgFreeGiftMsgTitleSingleOffer":{ "color": colorConfig?.titleColor, "font-weight": getFontWeightValue(fontConfig?.titleFontStyle), "font-size": `${fontConfig?.titleFontSize}px`, }, "gfgFreeGiftMsgSubTitleSingleOffer": { "color": colorConfig?.subtitleColor, "font-weight": getFontWeightValue(fontConfig?.subtitleFontStyle), "font-size": `${fontConfig?.subtitleFontSize}px`, }, "gfgFreeGiftReadyToClaimButton":{ "color": colorConfig?.claimBtnTextColor, "background-color": colorConfig?.claimBtnBgColor, "font-weight": getFontWeightValue(fontConfig?.claimBtnTextFontStyle), "font-size": `${fontConfig?.claimBtnTextFontSize}px`, }, "gfgFreeGiftMsgContainerForAccordion":{ "border": `2px solid ${colorConfig?.borderColor}` }, "gfgFreeGiftActiveFreeGiftClaimButton":{ "background-color": "transparent", "color": colorConfig?.claimBtnBgColor, "border-color": colorConfig?.claimBtnBgColor }, "gfgFreeGiftInvalidProductClaimButton":{ "background-color": "#e5e5e5", "color":"white", "pointer-events": "none" } }; // Apply CSS configurations based on the key Object.keys(variablesObj).forEach(key => { if (!variablesObj[key]) { return; } const cssObj = cssConfigurations[key]; if (cssObj) { const element = variablesObj[key]; Object.entries(cssObj).forEach(([property, value]) => { element.style[property] = value; }); } }); } catch (error) { gfg.utility.debugConsole(error?.message); } }, registerEvents: function (freeGiftCampaignIndex) { if (!gfg.gfgFreeGift.state.isEventListenerRegisteredArray[freeGiftCampaignIndex]) { gfg.gfgFreeGift.state.isEventListenerRegisteredArray[freeGiftCampaignIndex] = true; const index = freeGiftCampaignIndex; document.body.addEventListener('click', function (event) { const targetElement = event.target.closest(`.gfgFreeGiftSelectDiv-${index}`); if (targetElement) { const parent = targetElement.parentElement; gfg.utility.debugConsole(targetElement); gfg.utility.debugConsole('button clicked!'); const isAccordion = gfg.gfgFreeGift.state.isAccordionArray[index]; if (isAccordion === true) { targetElement.classList.toggle('gfgFreeGiftSelectDivExpanded'); const dropdownButton = document.querySelector(`.gfgFreeGiftDropDownButton-${index}`); if (dropdownButton) { dropdownButton.classList.toggle('gfgFreeGiftDropDownButtonRotationClass'); } const accordionContainer = parent.querySelector(`.gfgFreeGiftMsgContainerForAccordion-${index}`); if (accordionContainer) { accordionContainer.classList.toggle('gfgFreeGiftMsgContainerForAccordion-Expanded'); } gfg.gfgFreeGift.f.changeAccordionHandlingVariableStateOnUserEvent(index); } gfg.gfgFreeGift.f.gfgFreeGiftContainerOverflow(); } }); } // handle Pagination events if ( gfg?.settings?.app?.enableFreeGiftWidgetPagination && gfg?.gfgFreeGift?.state?.gfgFreeGiftPrepareChildUIArrCampaignWise[freeGiftCampaignIndex]?.length > FREE_GIFT_PAGINATION_ITEMS_PER_PAGE ) { const widgetCampaignIdSelector = `#FREEGIFTCAMPAIGN-WIDGET-${freeGiftCampaignIndex}`; const OptionsContainerSelector = `${widgetCampaignIdSelector} .gfgFreeGiftOptionsContainerDiv`; const prevButtonSelector = `${widgetCampaignIdSelector}-prevButton`; const nextButtonSelector = `${widgetCampaignIdSelector}-nextButton`; const totalItems = gfg.gfgFreeGift.state.gfgFreeGiftPrepareChildUIArrCampaignWise[freeGiftCampaignIndex].length; const prevButtons = document.querySelectorAll(prevButtonSelector); const nextButtons = document.querySelectorAll(nextButtonSelector); // ✅ Remove existing event listeners before adding new ones prevButtons.forEach((button) => { button.removeEventListener('click', handlePrevClick); // Remove any existing listener button.addEventListener('click', handlePrevClick); // Attach fresh listener }); nextButtons.forEach((button) => { button.removeEventListener('click', handleNextClick); // Remove any existing listener button.addEventListener('click', handleNextClick); // Attach fresh listener }); function handlePrevClick(event) { event.stopPropagation(); event.preventDefault(); let currentIndex = gfg.gfgFreeGift.state.paginationIndexArrayCampaignWise[freeGiftCampaignIndex]; if (currentIndex > 0) { currentIndex -= FREE_GIFT_PAGINATION_ITEMS_PER_PAGE; gfg.gfgFreeGift.state.paginationIndexArrayCampaignWise[freeGiftCampaignIndex] = currentIndex; updatePagination(); } } function handleNextClick(event) { event.stopPropagation(); event.preventDefault(); let currentIndex = gfg.gfgFreeGift.state.paginationIndexArrayCampaignWise[freeGiftCampaignIndex]; if (currentIndex + FREE_GIFT_PAGINATION_ITEMS_PER_PAGE < totalItems) { currentIndex += FREE_GIFT_PAGINATION_ITEMS_PER_PAGE; gfg.gfgFreeGift.state.paginationIndexArrayCampaignWise[freeGiftCampaignIndex] = currentIndex; updatePagination(); } } function updatePagination() { const containers = document.querySelectorAll(OptionsContainerSelector); let currentIndex = gfg.gfgFreeGift.state.paginationIndexArrayCampaignWise[freeGiftCampaignIndex]; const gfgFreeGiftPrepareChildUIArr = gfg.gfgFreeGift.state.gfgFreeGiftPrepareChildUIArrCampaignWise[freeGiftCampaignIndex]; const visibleItems = gfgFreeGiftPrepareChildUIArr.slice(currentIndex, currentIndex + FREE_GIFT_PAGINATION_ITEMS_PER_PAGE); const newHTML = visibleItems.map((element) => element.outerHTML).join(''); containers.forEach((container) => { container.innerHTML = newHTML; // Update all instances }); if (!prevButtons.length || !nextButtons.length) return; prevButtons.forEach((prevButton) => { prevButton.disabled = currentIndex === 0; }); nextButtons.forEach((nextButton) => { nextButton.disabled = currentIndex + FREE_GIFT_PAGINATION_ITEMS_PER_PAGE >= totalItems; }); } } }, gfgGetExclusiveFreeGiftsToBeRemovedFromCart: function (validFreeGiftTiers, freeGiftsToBeRemovedFromCart){ try { const exclusiveFreeGiftsToBeRemovedFromCart = [] const validTierFreeGiftsProductsArray = [] // push free gifts from all valid tiers to validTierFreeGiftsProductsArray for(let i=0; i< validFreeGiftTiers.length; i++){ const validFreeGiftTier = validFreeGiftTiers[i]; const freeGiftProduct = validFreeGiftTier.freeGiftProduct; for(let j=0; j< freeGiftProduct.length; j++){ validTierFreeGiftsProductsArray.push(freeGiftProduct[j]); } } // Check if each free gift to be removed from cart are exclusive or not for(let i=0; i< freeGiftsToBeRemovedFromCart.length; i++){ const freeGiftToBeRemovedProduct = freeGiftsToBeRemovedFromCart[i]; let isThisFreeGiftToBeRemovedExclusive = true; for(let j=0; j< validTierFreeGiftsProductsArray.length; j++){ // if this free gift to be removed is not exclusive then break the loop if(isThisFreeGiftToBeRemovedExclusive == false){ break; } const validFreeGiftProduct = validTierFreeGiftsProductsArray[j]; // check at product level if(freeGiftToBeRemovedProduct.product_id == validFreeGiftProduct.productId){ const freeGiftToBeRemovedVariantId = freeGiftToBeRemovedProduct.variant_id; const validFreeGiftVariantsArray = validFreeGiftProduct.variants; // check at variant level for(let k=0; k< validFreeGiftVariantsArray.length; k++){ const validFreeGiftVariant = validFreeGiftVariantsArray[k]; if(freeGiftToBeRemovedVariantId == validFreeGiftVariant.variantId){ isThisFreeGiftToBeRemovedExclusive = false; break; } } } } if(isThisFreeGiftToBeRemovedExclusive){ exclusiveFreeGiftsToBeRemovedFromCart.push(freeGiftToBeRemovedProduct); } } return exclusiveFreeGiftsToBeRemovedFromCart; } catch (error) { gfg.utility.debugConsole('error from gfgGetExclusiveFreeGiftsToBeRemovedFromCart', error); // if error occurs then return empty array(no free gifts to be removed from cart) return []; } }, prepareFreeGiftWidgetTitleBar: function(freeGiftCampaignIndex) { try { const freeGiftSettingData = gfg.settings.freeGifts[freeGiftCampaignIndex]; const isWidgetTitleBarEnabled = freeGiftSettingData?.isWidgetTitleBarEnabled; const titleBarText = freeGiftSettingData?.configuration?.addtionalFields?.titleBarText || "Available Free Gifts!!"; const widgetTitleBarNode = document.createElement("div"); widgetTitleBarNode.classList.add('gfgFreeGiftWidgetTitleBar'); const widgetConfiguration = freeGiftSettingData?.widgetConfiguration; const cssObj = { "background-color": widgetConfiguration?.colorConfig?.titleBarBgColor, "color": widgetConfiguration?.colorConfig?.titleBarTextColor, "font-size": gfg.utility.getFontSizeValue(widgetConfiguration?.fontConfig?.titleBarFontSize), "font-weight": gfg.utility.getFontWeightValue(widgetConfiguration?.fontConfig?.titleBarFontStyle) }; if (isWidgetTitleBarEnabled !== true || !titleBarText || titleBarText?.trim() === "") { return false; } widgetTitleBarNode.textContent = titleBarText; for (const [key, value] of Object.entries(cssObj)) { widgetTitleBarNode.style[key] = value; } return widgetTitleBarNode; } catch (error) { gfg.utility.debugConsole('error from prepareFreeGiftWidgetTitleBar', error); return false; } }, gfgFreeGiftWidgetPreparePill: function(freeGiftCampaignIndex) { try { const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; const pillImage = settings?.configuration?.addtionalFields?.pillIcon; const pillTitle = settings?.configuration?.addtionalFields?.pillText || "FREE GIFT"; const pillBoxInnerHtml = ` ${pillImage && pillImage?.trim() !== "" ? `` : ""} ${pillTitle} `; const gfgFreeGiftMsgPillBox = document.createElement("span"); gfgFreeGiftMsgPillBox.classList.add("gfgFreeGiftMsgPillBox"); gfgFreeGiftMsgPillBox.innerHTML = pillBoxInnerHtml; const widgetConfiguration = settings?.widgetConfiguration; const cssObj = { "background-color": widgetConfiguration?.colorConfig?.pillBgColor, "color": widgetConfiguration?.colorConfig?.pillTextColor, "font-size": gfg.utility.getFontSizeValue(widgetConfiguration?.fontConfig?.pillFontSize), "font-weight": gfg.utility.getFontWeightValue(widgetConfiguration?.fontConfig?.pillFontStyle) }; // don't show pill box if it is disabled if (settings?.isWidgetPillEnabled !== true) { return false; } // Apply styles to the pill box for (const [key, value] of Object.entries(cssObj)) { if (value) { gfgFreeGiftMsgPillBox.style[key] = value; } } return gfgFreeGiftMsgPillBox; } catch (error) { gfg.utility.debugConsole('error from gfgFreeGiftWidgetPreparePill', error); return false; } }, setInitialStates: function (settings) { try { // set all initial states here for free gift, inside loop for each campaign const allFreeGiftCampaigns = settings.freeGifts || []; for(let i=0; i< allFreeGiftCampaigns.length; i++){ const freeGiftCampaignIndex = i; // gfg.gfgFreeGift.f.setFreeGiftDefaultExpandedState(freeGiftCampaignIndex); } } catch (error) { gfg.utility.debugConsole('Error in setInitialStates fn', error); } }, changeAccordionHandlingVariableStateOnUserEvent: function (freeGiftCampaignIndex) { try { const isAccordionOpen = document.querySelectorAll('.gfgFreeGiftSelectDivExpanded').length > 0 && document.querySelector(`.gfgFreeGiftDropDownButton-${freeGiftCampaignIndex}`)?.classList.contains('gfgFreeGiftDropDownButtonRotationClass') && document.querySelector(`.gfgFreeGiftMsgContainerForAccordion-${freeGiftCampaignIndex}`)?.classList.contains('gfgFreeGiftMsgContainerForAccordion-Expanded'); gfg.gfgFreeGift.state.widgetAccordionExpandedArr[freeGiftCampaignIndex] = isAccordionOpen; } catch (error) { gfg.utility.debugConsole('changeAccordionHandlingVariableStateOnUserEvent', error); } }, prepareAnchorTagsForBuyProductXRule: function(data) { const { rule, PRODUCT_HANDLE, PRODUCT, PRODUCT_LIST_HANDLE, PRODUCT_LIST_TITLE } = data; let prepareaAnchorTags = ""; function generateAnchorTag(handle, title, productList) { const VARIANTS_TEXT_LIMIT = 50; const product = productList.find(product => product.handle === handle); const productVariants = product?.variants || null; let variantsText = ''; if (productVariants) { const variantTitles = productVariants.map(variant => variant.variantTitle); let displayedVariants = variantTitles.slice(0, 2); // Get up to 2 variants let variantString = displayedVariants.join(', '); // Check if the combined length of variant titles exceeds the limit if (variantString.length > VARIANTS_TEXT_LIMIT) { variantString = `${displayedVariants[0]}...`; // Limit to the first variant and '...' } else if (variantTitles.length > 2) { // Append '...' if there are more than 2 variants and the length is within limit variantString += '...'; } variantsText = ` (${variantString})`; } // return ` // ${title} // ${variantsText} // `; return ` ${title} ${variantsText} `; } function generateProductLinks(handles, titles, productList, includeVariants) { return handles.map((handle, index) => { let anchorTag = ''; if (includeVariants) { anchorTag = generateAnchorTag(handle, titles[index], productList); } else { // anchorTag = `${titles[index]}`; anchorTag = ` ${titles[index]} `; } return (index > 0 ? ", " : "") + anchorTag; }).join(""); } try { const includeVariants = rule?.isProductXVariantSelectionEnabled; if (PRODUCT_LIST_HANDLE?.length > 1) { prepareaAnchorTags = generateProductLinks(PRODUCT_LIST_HANDLE, PRODUCT_LIST_TITLE, rule?.productList, includeVariants); } else { if (includeVariants) { prepareaAnchorTags = generateAnchorTag(PRODUCT_HANDLE, PRODUCT, rule?.productList); } else { // prepareaAnchorTags = `${PRODUCT}`; prepareaAnchorTags = ` ${PRODUCT} `; } } return prepareaAnchorTags; } catch (error) { gfg.utility.debugConsole('prepareAnchorTagsForBuyProductXRule', error); return prepareaAnchorTags; } }, gfgCheckConditionForCountry: function(condition){ let response = false; try { const {operatorType, countries} = condition.ruleValue; const currentCountryOfStore = gfg.state.activeCustomerData?.visitingFromCountry; if(operatorType === "is"){ response = countries.includes(currentCountryOfStore); } else if(operatorType === "isNot"){ response = !countries.includes(currentCountryOfStore); } return response; } catch (error) { gfg.utility.debugConsole('gfgCheckConditionForCountry', error); return response; } }, filterFreeGiftsToAutoAddOnceOnly: function(freeGifts, freeGiftCampaignIndex) { try { const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; const allFreeGifts = freeGifts || []; const autoAddedFreeGiftList = JSON.parse(window.sessionStorage.getItem(`FREEGIFTCAMPAIGN-${freeGiftCampaignIndex}-AUTOADDEDFREEGIFTLIST`)) || []; if (settings?.isAutoAddFreeGiftOnceOnly !== true) { return allFreeGifts; } return allFreeGifts.filter((item) => { if(!autoAddedFreeGiftList.find(list => list.variantId == item.variantId && list.ruleId === item.properties?._rule_id)) { return true; } }); } catch (error) { gfg.utility.debugConsole('error in filterFreeGiftsToAutoAdd', error); return freeGifts; } } , updateAutoAddedFreeGiftList: function(productData, freeGiftCampaignIndex) { try { const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; if (settings?.isAutoAddFreeGiftOnceOnly === true && window && window.sessionStorage ) { const existingList = JSON.parse(window.sessionStorage.getItem(`FREEGIFTCAMPAIGN-${freeGiftCampaignIndex}-AUTOADDEDFREEGIFTLIST`)) || []; const {variantId, ruleId} = productData; const checkIfProductIsInList = existingList.find(item => item.variantId == variantId && item.ruleId === ruleId); if(!checkIfProductIsInList){ existingList.push({variantId, ruleId}); window.sessionStorage.setItem(`FREEGIFTCAMPAIGN-${freeGiftCampaignIndex}-AUTOADDEDFREEGIFTLIST`, JSON.stringify(existingList)); } } } catch (error) { gfg.utility.debugConsole("error in updateAutoAddedFreeGiftList", error); } }, setFreeGiftDefaultExpandedState: function(freeGiftCampaignIndex){ try { const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; const isWidgetAccordionExpanded = gfg.settings.app?.isWidgetAccordionExpandedByDefault_FREE_GIFT || settings?.isWidgetExpandedByDefault || false; gfg.gfgFreeGift.state.widgetAccordionExpandedArr[freeGiftCampaignIndex] = isWidgetAccordionExpanded; } catch (error) { gfg.utility.debugConsole('Error in setFreeGiftDefaultExpandedState fn', error); } }, handleWidgetAccordionOnFreeGiftClaim: function(freeGiftCampaignIndex){ try { const hideAccordionOnClaim = gfg.settings.app?.hideAccordionOnClaim_FREE_GIFT || false; if(hideAccordionOnClaim){ const index = freeGiftCampaignIndex; const element = document.querySelector(`.gfgFreeGiftSelectDiv-${index}`); element.click(); // fire gfgFreeGiftSelectDiv click registered event. } } catch (error) { gfg.utility.debugConsole("err in handleWidgetAccordionOnFreeGiftClaim", error); } }, gfgAddFreeGiftsToCartV2: async function(freeGiftProducts = [], freeGiftCampaignIndex) { try { const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; const defaultPropertyInFreeGift = "Free Gift"; const promoName = settings?.discountData_shopifyResponse?.title || settings?.name; const itemsToBeAdded = []; for (const product of freeGiftProducts) { const isCurrentVariantInStock = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds?.[product.variantId]?.available; if (isCurrentVariantInStock) { itemsToBeAdded.push({ id: product.variantId, quantity: 1, properties: { _free_product: "true", _rule_id: product._rule_id || defaultPropertyInFreeGift, _kite_promo_name: promoName } }); } } if (itemsToBeAdded.length > 0) { const result = await gfg.utility.addToCartV2({items: itemsToBeAdded}); if (result) { gfg.gfgFreeGift.state.isCartUpdatedByUs = true; return true; } } return false; } catch (error) { gfg.utility.debugConsole('Error in gfgAddFreeGiftsToCartV2 fn', error); return false; } }, getFreeGiftProductDataInsideCartBasedOnRuleId: function(ruleId, freeGiftCampaignIndex){ try { let data = null; try { const currentCampaignPromoName = gfg.gfgFreeGift.utility.getCurrentPromoName(freeGiftCampaignIndex); let cartItems = gfg.gfgFreeGift.state.campaignWiseFreeGiftsFromCartData[freeGiftCampaignIndex]; cartItems.forEach(function (item) { const condition1 = item.properties?._free_product == "true"; let condition2 = item.properties?._rule_id == ruleId; const condition3 = item.properties?._kite_promo_name == currentCampaignPromoName; if(!gfg.settings.freeGifts[freeGiftCampaignIndex].isMultipleFreeGiftAllowed){ condition2 = true; } if(condition1 && condition2 && condition3){ data = { productId: item.product_id, variantId: item.variant_id, quantity: item.quantity, properties: item.properties } } }) } catch (error) { gfg.utility.debugConsole('Error in getFreeGiftProductDataInsideCartBasedOnRuleId', error); } finally{ return data } } catch (error) { } }, calculateFreeGiftChangesFor_multiplyFreeGiftTrigger: function(freeGiftCampaignIndex, validFreeGiftTiers, cartData, freeGiftsFromCart){ try { const changes = []; for(let i = 0; i < validFreeGiftTiers.length; i++) { const validFreeGiftTier = validFreeGiftTiers[i]; const freeGiftProduct = validFreeGiftTier.freeGiftProduct[0]; let netRequiredQuantity = 1; // default 1 let availableFreeGiftItemInCart = { quantity: 0, keys: [] }; netRequiredQuantity = gfg.gfgFreeGift.f.calculateNetRequiredQuantityFor_multiplyFreeGiftTrigger(freeGiftCampaignIndex, validFreeGiftTier, cartData); freeGiftsFromCart.forEach(function(item) { if(item.properties?._rule_id === validFreeGiftTier.ruleId && item.product_id == freeGiftProduct.productId) { availableFreeGiftItemInCart.quantity += item.quantity; availableFreeGiftItemInCart.keys.push({ key: item.key, quantity: item.quantity }); } }); if (availableFreeGiftItemInCart.quantity > netRequiredQuantity) { // Case 1: More gifts in cart than required, remove excess availableFreeGiftItemInCart.keys.sort((a, b) => b.quantity - a.quantity); // Sort descending by quantity let updateObject = {}; for(let j = 0; j < availableFreeGiftItemInCart.keys.length; j++) { let item = availableFreeGiftItemInCart.keys[j]; if(netRequiredQuantity > 0) { if(item.quantity <= netRequiredQuantity) { netRequiredQuantity -= item.quantity; } else { updateObject[item.key] = netRequiredQuantity; netRequiredQuantity = 0; } } else { updateObject[item.key] = 0; } } changes.push({ type: "UPDATE", productId: freeGiftProduct.productId, ruleId: validFreeGiftTier.ruleId, update: updateObject }); } else if (availableFreeGiftItemInCart.quantity < netRequiredQuantity && availableFreeGiftItemInCart.quantity > 0) { // Case 2: Less gifts in cart than required, increase quantity let missingQuantity = netRequiredQuantity - availableFreeGiftItemInCart.quantity; let keyToUpdate = availableFreeGiftItemInCart.keys[0]; // Pick the first available key changes.push({ type: "UPDATE", productId: freeGiftProduct.productId, ruleId: validFreeGiftTier.ruleId, update: { [keyToUpdate.key]: keyToUpdate.quantity + missingQuantity } }); } else if(availableFreeGiftItemInCart.quantity === 0) { // Case 3: No free gift in cart, need to add changes.push({ type: "ADD", productId: freeGiftProduct.productId, variantId: freeGiftProduct.variantId, ruleId: validFreeGiftTier.ruleId, quantity: netRequiredQuantity }); } } return changes; } catch (error) { gfg.utility.debugConsole('Error in calculateFreeGiftChangesFor_multiplyFreeGiftTrigger function', error); } }, calculateNetRequiredQuantityFor_multiplyFreeGiftTrigger: function(freeGiftCampaignIndex, ruleData, cartData){ const freeGiftCampaignSettings = gfg.settings.freeGifts[freeGiftCampaignIndex]; let netRequiredQuantity = 1; try { switch(ruleData.ruleType){ case "SPEND_X":{ const minimumCartValue = Number(ruleData.minimumCartValue); const config = gfg.settings.freeGifts[freeGiftCampaignIndex]; let totalCartValue = 0; for(let i = 0; i < cartData.items.length; i++){ let cartItem = cartData.items[i] if(cartItem && cartItem.properties && cartItem.properties["_free_product"]){ continue } // const cartItemPrice= gfg.utility.formatPriceWithoutSymbol(cartItem.final_price) let cartItemPrice; if(config?.isUnifiedWidget && !config?.shouldUseDiscountedSubtotal) { cartItemPrice = gfg.utility.formatPriceWithoutSymbol(cartItem.price) } else { cartItemPrice = gfg.utility.formatPriceWithoutSymbol(cartItem.discounted_price) } totalCartValue += cartItemPrice * cartItem.quantity } netRequiredQuantity = Math.floor(totalCartValue / minimumCartValue); } break; case "BUY_PRODUCT_X":{ const minProducts = Number(ruleData.minProducts); let totalMatchedProductsQuantity = 0; let validProductList = []; const validProductVariantsList = []; ruleData.productList.forEach(product => { validProductList.push(product.productId) }) ruleData.productList.forEach(product => { product.variants.forEach(variant => { validProductVariantsList.push(variant.variantId) }) }) //check if condition is true for(let i = 0; i < cartData.items.length; i++){ let cartItem = cartData.items[i] if(cartItem && cartItem.properties && cartItem.properties["_free_product"]){ continue } const conditionToCheckOnBasisOfProductId = validProductList.indexOf((""+cartItem.product_id)) >= 0; const conditionToCheckOnBasisOfVariantId = validProductVariantsList.indexOf((""+cartItem.variant_id)) >= 0; // if variant selction is enabled then check for product Id && variantId // else check for product id if(ruleData?.isProductXVariantSelectionEnabled === true){ if(conditionToCheckOnBasisOfProductId && conditionToCheckOnBasisOfVariantId){ totalMatchedProductsQuantity += parseInt(cartItem.quantity) } } else{ if(conditionToCheckOnBasisOfProductId){ totalMatchedProductsQuantity += parseInt(cartItem.quantity) } } } netRequiredQuantity = Math.floor(totalMatchedProductsQuantity / minProducts); } break; case "SPEND_X_IN_COLLECTION_Y":{ const minimumCartValue = Number(ruleData.minimumCartValue); let validCollectionList = [] ruleData.collectionsData.forEach(collection => { validCollectionList.push(collection) }) //check if condition is true let totalCartValue =0; for(let i = 0; i < cartData.items.length; i++){ let cartItem = cartData.items[i] if(cartItem && cartItem.properties && cartItem.properties["_free_product"]){ continue } if(gfg.f.checkIfCartItemIsPartOfValidCollectionList(cartItem,validCollectionList)){ // const cartItemPrice= gfg.utility.formatPriceWithoutSymbol(cartItem.price) const cartItemPrice= gfg.utility.formatPriceWithoutSymbol(cartItem.discounted_price) totalCartValue += cartItemPrice * cartItem.quantity } } netRequiredQuantity = Math.floor(totalCartValue / minimumCartValue); } break; case "BUY_ANY_PRODUCT_FROM_COLLECTION_Y":{ const minProducts = Number(ruleData.minProducts); let totalMatchedProductsQuantity = 0; let validCollectionList = [] ruleData.collectionsData.forEach(collection => { validCollectionList.push(collection) }) let returnQty = 0 //check if condition is true for(let i = 0; i < cartData.items.length; i++){ let cartItem = cartData.items[i] if(cartItem && cartItem.properties && cartItem.properties["_free_product"]){ continue } if(gfg.f.checkIfCartItemIsPartOfValidCollectionList(cartItem,validCollectionList)){ totalMatchedProductsQuantity += parseInt(cartItem.quantity) } } netRequiredQuantity = Math.floor(totalMatchedProductsQuantity / minProducts); } break; } // if netRequired quantity is more than max then we new netRequired quantity will be equal to max const maxQuantity = Number(freeGiftCampaignSettings?.maxQuantityForMultiplyFreeGiftWithTrigger) || 1; if(netRequiredQuantity > maxQuantity){ netRequiredQuantity = maxQuantity; } } catch (error) { gfg.utility.debugConsole('Error in calculateNetRequiredQuantityFor_multiplyFreeGiftTrigger fn', error); } finally{ return netRequiredQuantity; } }, prepareFreeGiftWidgetPrevNextButton: function(freeGiftCampaignIndex, gfgFreeGiftPrepareChildUIArr) { try { const freeGiftSettingData = gfg.settings.freeGifts[freeGiftCampaignIndex]; const isPrevNextButtonEnabled = gfg.settings.app?.enableFreeGiftWidgetPagination; if(!isPrevNextButtonEnabled || gfgFreeGiftPrepareChildUIArr.length <= FREE_GIFT_PAGINATION_ITEMS_PER_PAGE){ return false; } const prevNextButtonContainer = document.createElement("div"); const prevButton = document.createElement("button"); const nextButton = document.createElement("button"); prevNextButtonContainer.classList.add("prevNextButtonContainer"); prevButton.setAttribute("id", `FREEGIFTCAMPAIGN-WIDGET-${freeGiftCampaignIndex}-prevButton`); nextButton.setAttribute("id", `FREEGIFTCAMPAIGN-WIDGET-${freeGiftCampaignIndex}-nextButton`); prevButton.classList.add("prevButton"); nextButton.classList.add("nextButton"); // Add Bold Left Chevron SVG const prevChevron = document.createElement("span"); const chevronIcon = ` `; prevChevron.innerHTML = chevronIcon; prevChevron.classList.add("chevronIcon"); // Add Bold Right Chevron SVG const nextChevron = document.createElement("span"); nextChevron.innerHTML = chevronIcon; nextChevron.classList.add("chevronIcon"); // Append icons and text to buttons prevButton.appendChild(prevChevron); prevButton.appendChild(document.createTextNode("Previous")); nextButton.appendChild(document.createTextNode("Next")); nextButton.appendChild(nextChevron); // Disable buttons based on pagination state const currentIndex = gfg.gfgFreeGift.state.paginationIndexArrayCampaignWise[freeGiftCampaignIndex]; const isPrevDisabled = currentIndex === 0; const isNextDisabled = currentIndex + FREE_GIFT_PAGINATION_ITEMS_PER_PAGE >= gfgFreeGiftPrepareChildUIArr.length; prevButton.disabled = isPrevDisabled; nextButton.disabled = isNextDisabled; prevNextButtonContainer.appendChild(prevButton); prevNextButtonContainer.appendChild(nextButton); return prevNextButtonContainer; } catch (error) { gfg.utility.debugConsole('Error in prepareFreeGiftWidgetPrevNextButton fn', error); } }, getHtmlContentFromPagination: function(freeGiftCampaignIndex, gfgFreeGiftPrepareChildUIArr){ try { const currentIndex = gfg.gfgFreeGift.state.paginationIndexArrayCampaignWise[freeGiftCampaignIndex]; const visibleItems = gfgFreeGiftPrepareChildUIArr.slice(currentIndex, currentIndex + FREE_GIFT_PAGINATION_ITEMS_PER_PAGE); const newHTML = visibleItems.map(element => element.outerHTML).join(''); return newHTML; } catch (error) { gfg.utility.debugConsole('Error in getHtmlContentFromPagination fn', error); } }, }, utility:{ removeCartItemsFromCart: async function (cartItems) { if(cartItems.length == 0){ return } //now cartItem have something known as key which is unique for each item in cart //we need to remove all the items from cart which are in cartItems let cartItemData = cartItems.map(function (item) { return {id: item.key, quantity: 0}; }); // lets send that in data to changeCart(data) //write code to remove line Item keys from cart let data = cartItemData; let response = await gfg.utility.changeCart(data); if(response){ gfg.gfgFreeGift.state.isCartUpdatedByUs = true } else { gfg.gfgFreeGift.state.isCartUpdatedByUs = false } return response; }, modifySettingsForRuleIds:function(freeGiftCampaignIndex){ let rulesList = gfg.settings.freeGifts[freeGiftCampaignIndex].rulesList rulesList.forEach(function (item,index) { item.ruleId = item.ruleType + "-" + (index+1) }) gfg.settings.freeGifts[freeGiftCampaignIndex].rulesList = rulesList }, getFirstVariantSelectedWithProperties: async function (validFreeGiftTiers) { //juST ADD THE FIRST VARIANT FROM EACH TIER let freeGiftsToBeAddedToCart = [] validFreeGiftTiers.forEach(function (item) { let freeGiftProduct = item.freeGiftProduct; for (let i = 0; i < freeGiftProduct.length; i++) { for (let j = 0; j < freeGiftProduct[i].variants.length; j++) { let variantId = freeGiftProduct[i].variants[j].variantId; let variantData = gfg.gfgFreeGift.state.freeGiftsShopifyDataByVariantIds[variantId]; variantData["variantId"] = variantId; if (variantData && variantData.available == true) { freeGiftsToBeAddedToCart.push({variantData: variantData, ruleId: item.ruleId}) break; } } } // freeGiftsToBeAddedToCart.push({variantData:item.freeGiftProduct[0].variants[0],ruleId:item.ruleId}) }); //now we have all the free gifts to be added to cart //lets add them to cart //lets prepare the data here; let cartItemData = freeGiftsToBeAddedToCart.map(function (item) { return { variantId: item.variantData.variantId, quantity: 1, properties: { _free_product: "true", _rule_id: item.ruleId, } }; }); return cartItemData; // lets send that in data to addToCart(data) }, isProductInFreeGiftCart : function (productId) { //use the object gfg.state.freeGiftCartData_productId let freeGiftCartData_productId = gfg.state.freeGiftsCartDataMap_productId // is an object if(freeGiftCartData_productId[productId] && Object.keys(freeGiftCartData_productId[productId]).length > 0){ return true } return false }, isVariantInFreeGiftCart : function (variantId) { //use the object gfg.state.freeGiftCartData_variantId let freeGiftCartData_variantId = gfg.state.freeGiftsCartDataMap_variantId // is an object if(freeGiftCartData_variantId[variantId] && Object.keys(freeGiftCartData_variantId[variantId]).length > 0){ return true } return false }, isRuleIdProductAlreadyInCart : function (ruleId, freeGiftCampaignIndex) { // use the gfg.state.freeGiftCartData.items object let cartItems = gfg.gfgFreeGift.state.campaignWiseFreeGiftsFromCartData[freeGiftCampaignIndex]; let isRuleIdProductAlreadyInCart = false cartItems.forEach(function (item) { if(item.properties._rule_id == ruleId){ isRuleIdProductAlreadyInCart = true } }) return isRuleIdProductAlreadyInCart }, getProductIdFromRuleId : function (ruleId, freeGiftCampaignIndex) { let productId = null try { let cartItems = gfg.gfgFreeGift.state.campaignWiseFreeGiftsFromCartData[freeGiftCampaignIndex]; cartItems.forEach(function (item) { if(item.properties._rule_id == ruleId){ productId = item.product_id } }) return productId } catch (error) { gfg.utility.debugConsole('Error in getProductIdFromRuleId fn', error); return productId; } }, getCart : async function (freeGiftCampaignIndex) { let cartData = await gfg.utility.getCart() let filteredData = gfg.gfgFreeGift.utility.filterCartDataBasedOnSettings(cartData, freeGiftCampaignIndex); return filteredData // return cartData }, filterCartDataBasedOnSettings: function (cartData, freeGiftCampaignIndex) { let config = gfg.settings.freeGifts[freeGiftCampaignIndex]; const currentFreeGiftPromoName = config?.discountData_shopifyResponse?.title || config?.name; if (!config) { return cartData; // Return original cartData if there's no configuration } let excludeSubscriptionProducts = config.freeGiftEligibility == "EXCLUDE_SUBSCRIPTION_PRODUCTS"; let includeOnlySubscriptionProducts = config.freeGiftEligibility == "INCLUDE_ONLY_SUBSCRIPTION_PRODUCTS"; let allowAllProducts = config.freeGiftEligibility == "ALL_PRODUCTS" || (!excludeSubscriptionProducts && !includeOnlySubscriptionProducts); // if(allowAllProducts){ // return cartData // } let filteredCartData = { ...cartData, items: [], total_price: 0, total_weight: 0, // total_discount: 0, items_subtotal_price: 0, requires_shipping: false }; for (let i = 0; i < cartData.items.length; i++) { let item = cartData.items[i]; let isFreeProduct = item.properties && item.properties["_free_product"] == "true"; // if _Gifted property is set then it's a free product. _Gifted property comes from Easy auto add to cart app. isFreeProduct = isFreeProduct || Boolean(item.properties && item.properties["_Gifted"]); let shouldIncludeItem = isFreeProduct || (!excludeSubscriptionProducts && !includeOnlySubscriptionProducts); // Include by default if isFreeProduct or neither condition is set let productIsSubscription = item && item.selling_plan_allocation && item.selling_plan_allocation.selling_plan; if (!isFreeProduct) { if (excludeSubscriptionProducts) { shouldIncludeItem = !productIsSubscription; } else if (includeOnlySubscriptionProducts) { shouldIncludeItem = productIsSubscription; } } if(isFreeProduct){ if(item.properties?.["_kite_promo_name"] != currentFreeGiftPromoName){ shouldIncludeItem = false } // item_price should be zero // item.quantity shuld be 1 // item.dscounted price should be 0 // item.original_price should be 0 item.price = 0 // item.quantity = 1 item.discounted_price = 0 item.original_price = 0 } if (shouldIncludeItem) { // Inline logic to add item to filteredCartData filteredCartData.items.push(item); filteredCartData.total_price += (item.discounted_price || item.price) * item.quantity; filteredCartData.total_weight += item.quantity * item.grams; // filteredCartData.total_discount += (item.discounted_price || item.price) * item.quantity; // filteredCartData.total_discount += (item.discounted_price || item.price) * item.quantity; filteredCartData.items_subtotal_price += item.original_price * item.quantity; filteredCartData.requires_shipping = filteredCartData.requires_shipping || item.requires_shipping; } } // filteredCartData.items_subtotal_price -= filteredCartData.total_discount; filteredCartData.item_count = filteredCartData.items.length; return filteredCartData; }, prepareTextInAnchorTag: function (pageType, text, handle) { // pageType: it can be PRODUCT_PAGE_HANDLE or COLLECTION_PAGE_HANDLE // text: it is the text that needs to be shown in the anchor tag // handle: it is the handle of the product or collection let preFixUrl; if(pageType == "PRODUCT_PAGE_HANDLE"){ preFixUrl = "/products/" } // return `${text}` return `${text}` }, getFreeGiftProductModifiedBasicFieldData: function (product, property) { /* this function reads & returns the data for basic widget properties such as image & title from the product["shopifyData"] to cover the case if free gift products get modified. */ if(property == "image"){ const imagePath = product["shopifyData"]?.images?.length > 0 ? product["shopifyData"].images[0] :(product.images.length === 0 ? 'https://d1cjetlwgplgi5.cloudfront.net/public/freeGiftDymmyImage.png' : product.images[0].originalSrc ); return imagePath; } else if(property == "title"){ return product["shopifyData"]?.title || product.title; } }, getCurrentPromoName: function(freeGiftCampaignIndex){ let promoName = ""; try { const settings = gfg.settings.freeGifts[freeGiftCampaignIndex]; promoName = settings?.discountData_shopifyResponse?.title || settings?.name; } catch (error) { gfg.utility.debugConsole('getCurrentPromoName', error); } finally{ return promoName; } }, getCampaignWiseFreeGiftsFromCartData: function(cartData, freeGiftCampaignIndex){ try { // this function provides only free gifts data from cart data for a specific campaign // this function will return array of free gifts const currentPromoName = gfg.gfgFreeGift.utility.getCurrentPromoName(freeGiftCampaignIndex); const freegifts = cartData.items.filter(item => (item.properties && item.properties["_free_product"] == "true" && item.properties["_kite_promo_name"] == currentPromoName)); return freegifts; } catch (error) { gfg.utility.debugConsole('Error in getCampaignWiseFreeGiftsFromCartData fn', error); } }, updateCampaignWiseFreeGiftsDataFromCart: function(cartData){ try { const allFreeGiftCampaigns = gfg.settings.freeGifts || []; for(let i=0; i< allFreeGiftCampaigns.length; i++){ const freeGiftCampaignIndex = i; gfg.gfgFreeGift.state.campaignWiseFreeGiftsFromCartData[freeGiftCampaignIndex] = gfg.gfgFreeGift.utility.getCampaignWiseFreeGiftsFromCartData(cartData, freeGiftCampaignIndex); } } catch (error) { gfg.utility.debugConsole('Error in updateCampaignWiseFreeGiftsDataFromCart fn', error); } }, }, actions: { } }, gfgVolDiscount: { state:{ isAddToCartButtonOverwrite: false, isCartUpdatedByUs: false, customerSpecificDiscount: [], defaultTierSelectedQuantity: null, isDefaultTierSelectionDone: false, currentSelectedVariant: null, }, init: async function (settings, parent) { try{ gfg.gfgVolDiscount.initialize(settings, parent) }catch(error){ gfg.utility.debugConsole(error) } }, initialize: async function (settings, parent) { gfg.gfgVolDiscount.f.removeInactiveCampaigns(); gfg.f.getProductPageHandle(settings); gfg.f.getProductPageId(settings); if (parent == "PRODUCT_PAGE") { let volDiscountDataForProductPage = await gfg.gfgVolDiscount.f.getVolDiscountDataForProductPage(); if(volDiscountDataForProductPage){ let gfgVolDiscountPageHtml = gfg.gfgVolDiscount.f.prepareUI(parent,volDiscountDataForProductPage) gfg.gfgVolDiscount.f.insertIntoPageWrapper(gfgVolDiscountPageHtml, parent) } } if (parent == "CART_PAGE") { let gfgVolDiscountCartPageHtml = await gfg.gfgVolDiscount.f.prepareBulkDiscountRulesWidgets(settings) gfg.gfgVolDiscount.f.insertIntoPageWrapper(gfgVolDiscountCartPageHtml, parent) } }, f: { insertIntoPageWrapper: function (gfgVolDiscountPageHtml, parent) { try { if(gfgVolDiscountPageHtml){ if (parent === "PRODUCT_PAGE") { let gfgVolDiscountWrapperProductEle = gfg.utility.findWrapperElement("VOLUME_DISCOUNT", "PRODUCT_PAGE", null); gfgVolDiscountWrapperProductEle.forEach((element) => { element.innerHTML = ''; element.innerHTML = gfgVolDiscountPageHtml.outerHTML; }); } else if (parent === "CART_PAGE") { let gfgBulkDiscountWidgetHTMLEle = gfg.utility.findWrapperElement("VOLUME_DISCOUNT", "CART_PAGE", null); gfgBulkDiscountWidgetHTMLEle.forEach((element) => { element.innerHTML = ''; element.innerHTML = gfgVolDiscountPageHtml.outerHTML; }); } gfg.f.addPoweredByBlock(); } } catch (error) { gfg.utility.debugConsole(error); } }, searchObjectById: function(array, idToSearch) { for (let i = 0; i < array.length; i++) { if (array[i].id == idToSearch) { return array[i]; // Found the object, return it } } return null; // If the ID was not found, return null }, removeInactiveCampaigns : function () { try{ let allDiscounts = JSON.parse(JSON.stringify(gfg.settings.discounts)); let modifiedDiscounts = []; // now if they have a flag knonw as isCampaignUrlEnabled and if it is true then, // match the activeCampaignName with the value in urlBasedCampaign.value; // if they dont match then remove it from the list. // if they have isCampaignUrlEnabled as false, then let it be there in the list if (allDiscounts && allDiscounts.length > 0) { for(let i=0; i { const moreText = '....'; const basePath = productType === "COLLECTIONS" ? "/collections/" : "/products/"; const productTypeForHrefFn = productType === "COLLECTIONS" ? "collection" : "product"; let texts = ""; let linkTexts = ""; const truncatedArray = titleHandleArray.slice(0, 4); const titles = truncatedArray.map(item => item.title); texts = titles.join(", "); linkTexts = truncatedArray.map(item => { // return `${item.title}`; return `${item.title}`; }).join(", "); if (titleHandleArray.length > 4) { texts += ' ' + moreText; linkTexts += ' ' + moreText; } return { texts, linkTexts }; } const replacePlaceholders = (type, data) => { const titleHandleArray = data.map(item => ({ title: item.title, handle: item.handle })); const { texts, linkTexts } = prepareTextsAndLinks(titleHandleArray, type); const placeholders = ["{{" + type + "}}", "{{" + type + "_LINKS}}", "{{" + type.slice(0, -1) + "}}", "{{" + type.slice(0, -1) + "_LINK}}"]; placeholders.forEach(placeholder => { text = text.replace(placeholder, placeholder.includes("_LINK") ? linkTexts : texts); }); } if (discountProductType === "COLLECTIONS") { const collections = currBulkDiscount?.disProducts?.collections || []; replacePlaceholders("COLLECTIONS", collections); } else if (discountProductType === "SELECTED_PRODUCTS") { const selectedProducts = currBulkDiscount?.disProducts?.products || []; replacePlaceholders("PRODUCTS", selectedProducts); } return text; } catch (error) { gfg.utility.debugConsole('Error from replaceVolDiscountProdPageVars:', error); } } , prepareUIDataWrapper: function(discount) { const configObject = discount.configuration; const productPageData = discount.productPageData; const variant = gfg.f.getSelectedVariant(); const variantObject = this.searchObjectById(productPageData.variants, variant); const symbol = gfg.utility.getCurrencySymbol(); let discountTiers = []; gfg.gfgVolDiscount.state.currentSelectedVariant = variantObject; const calculateDiscountData = (rule, i, totalPrice, conditionText) => { let discountPrice; let text; let currencySymbol = gfg.utility.getCurrencySymbol(); let priceLabel = ' '; let priceValue = 0; if (discount.disValueType === "FIXED_DIS" ) { discountPrice = parseFloat(gfg.utility.getAmountInActiveCurrency(rule.disValue)); if (discount.conditionType === "COUNT" && discount.fixedDiscountType == "APPLY_TOTAL_ON_EACH_PRODUCT") { discountPrice *= parseInt(rule.conditionValue); } text = configObject.tiers[i].label .replace("{{CONDITION}}", conditionText) .replace("{{DISCOUNT}}", symbol + discountPrice) .replaceAll("{{CURRENCY}}", currencySymbol) .replace("{{DISCOUNT_AMOUNT}}", discountPrice) // if custom script is added to format pricing then format the price if(gfg.state?.formatPriceViaCustomScript){ let discountPriceForTextProperty = discountPrice * 100; let conditionTextForTextProperty = conditionText * 100; discountPriceForTextProperty = gfg.utility.formatPriceWithSeparator(discountPriceForTextProperty); conditionTextForTextProperty = gfg.utility.formatPriceWithSeparator(conditionTextForTextProperty); if(discount.conditionType === "COUNT"){ text = configObject.tiers[i].label .replace("{{CONDITION}}", conditionText) .replace("{{DISCOUNT}}", symbol + discountPriceForTextProperty) .replaceAll("{{CURRENCY}}", currencySymbol) .replace("{{DISCOUNT_AMOUNT}}", discountPriceForTextProperty); } else if(discount.conditionType === "SUBTOTAL"){ text = configObject.tiers[i].label .replace("{{CONDITION}}", conditionTextForTextProperty) .replace("{{DISCOUNT}}", symbol + discountPriceForTextProperty) .replaceAll("{{CURRENCY}}", currencySymbol) .replace("{{DISCOUNT_AMOUNT}}", discountPriceForTextProperty); } } priceLabel = (totalPrice - discountPrice) > 0 ? symbol + (totalPrice - discountPrice) : ' '; priceValue = (totalPrice - discountPrice) > 0 ? (totalPrice - discountPrice) : 0; } else if (discount.disValueType === "PERCENTAGE_DIS") { const percent = parseFloat(rule.disValue); discountPrice = (variantObject?.price / 100) * (percent / 100); if (discount.conditionType === "COUNT") { discountPrice *= parseInt(rule.conditionValue); } text = configObject.tiers[i].label .replace("{{CONDITION}}", conditionText) .replace("{{DISCOUNT}}", percent + '%') .replace("{{CURRENCY}}", currencySymbol); // if custom script is added to format pricing then format the price if(gfg.state?.formatPriceViaCustomScript){ let conditionTextForTextProperty = conditionText * 100; conditionTextForTextProperty = gfg.utility.formatPriceWithSeparator(conditionTextForTextProperty); if(discount.conditionType === "SUBTOTAL"){ text = configObject.tiers[i].label.replace("{{CONDITION}}", conditionTextForTextProperty).replace("{{DISCOUNT}}", percent + '%').replace("{{CURRENCY}}", currencySymbol); } } priceLabel = (totalPrice - discountPrice) > 0 ? symbol + (totalPrice - discountPrice) : ' '; priceValue = (totalPrice - discountPrice) > 0 ? (totalPrice - discountPrice) : 0; } else if (discount.disValueType === "FIXED_TOTAL"){ discountPrice = parseFloat(gfg.utility.getAmountInActiveCurrency(rule.disValue)); if (discount.conditionType === "COUNT" && discount.fixedDiscountType == "APPLY_TOTAL_ON_EACH_PRODUCT") { discountPrice *= parseInt(rule.conditionValue); } text = configObject.tiers[i].label .replace("{{CONDITION}}", conditionText) .replace("{{DISCOUNT}}", discountPrice) .replaceAll("{{CURRENCY}}", currencySymbol) .replace("{{DISCOUNT_AMOUNT}}", discountPrice) .replace("{{PRODUCT_QUANTITY}}", conditionText); // if custom script is added to format pricing then format the price if(gfg.state?.formatPriceViaCustomScript){ let discountPriceForTextProperty = discountPrice * 100; let conditionTextForTextProperty = conditionText * 100; discountPriceForTextProperty = gfg.utility.formatPriceWithSeparator(discountPriceForTextProperty); conditionTextForTextProperty = gfg.utility.formatPriceWithSeparator(conditionTextForTextProperty); if(discount.conditionType === "COUNT"){ text = configObject.tiers[i].label .replace("{{CONDITION}}", conditionText) .replace("{{DISCOUNT}}", discountPriceForTextProperty) .replaceAll("{{CURRENCY}}", currencySymbol) .replace("{{DISCOUNT_AMOUNT}}", discountPriceForTextProperty) .replace("{{PRODUCT_QUANTITY}}", conditionText); } else if(discount.conditionType === "SUBTOTAL"){ text = configObject.tiers[i].label .replace("{{CONDITION}}", conditionTextForTextProperty) .replace("{{DISCOUNT}}", symbol + discountPriceForTextProperty) .replaceAll("{{CURRENCY}}", currencySymbol) .replace("{{DISCOUNT_AMOUNT}}", discountPriceForTextProperty) .replace("{{PRODUCT_QUANTITY}}", conditionText); } } priceLabel = symbol + discountPrice; priceValue = discountPrice; } text = gfg.gfgVolDiscount.f.replaceVolDiscountProdPageVars(discount, rule, text) return { priceLabel, priceValue, quantitylabel: discount.conditionType === "COUNT" ? parseInt(rule.conditionValue) : '', strikethroughLabel: symbol + totalPrice, strikethroughValue : parseFloat(totalPrice).toFixed(2), disValueType: discount.disValueType, discountValue: rule.disValue, discountPrice: discountPrice, text: text, label: configObject.tiers[i].label }; }; if (discount.conditionType === "COUNT") { discountTiers = []; discount.rules.forEach((rule, i) => { const qty = parseInt(rule.conditionValue); const totalPrice = (qty * (variantObject.price / 100)); discountTiers.push(calculateDiscountData(rule, i, totalPrice, qty)); }); } else if (discount.conditionType === "SUBTOTAL") { discountTiers = []; discount.rules.forEach((rule, i) => { const subtotal = parseFloat(gfg.utility.getAmountInActiveCurrency(rule.conditionValue)); const totalPrice = subtotal; discountTiers.push(calculateDiscountData(rule, i, subtotal, totalPrice)); }); } return { discountTitle: configObject.tierListTitle, discountTiers: discountTiers, note: configObject.note, colors: configObject.colors, conditionType: discount.conditionType, disValueType: discount.disValueType, defaultSelectedTierIndex: discount?.defaultSelectedTier?.tierIndex !== undefined ? discount.defaultSelectedTier.tierIndex : "NONE", mostPopularSelectedTierIndex: discount?.mostPopularSelectedTier?.tierIndex !== undefined ? discount.mostPopularSelectedTier.tierIndex : "NONE", }; }, prepareUI: function (parent, volDiscountDataForProductPage) { let data = volDiscountDataForProductPage.prouctUiDataToBeShown; let symbol = gfg.utility.getCurrencySymbol(); let disValueType = data.disValueType; let colors = data?.colors; let textColor = colors?.text; let borderColor = colors?.border; let backgroundColor = colors?.background; const configuration = volDiscountDataForProductPage?.configuration; const mostPopularSelectedTierData = volDiscountDataForProductPage?.mostPopularSelectedTier; const isUnifiedWidget = volDiscountDataForProductPage?.isUnifiedWidget; if (configuration?.isEnabled === false || isUnifiedWidget) { const gfgFVolDiscountContainer = document.createElement('div'); gfgFVolDiscountContainer.classList.add('gfgVolDiscountContainer'); return gfgFVolDiscountContainer; } if (data.conditionType === "COUNT") { const gfgFVolDiscountContainer = document.createElement('div'); gfgFVolDiscountContainer.classList.add('gfgVolDiscountContainer', 'gfgCountDiscount'); const titleDiv = document.createElement('div'); titleDiv.classList.add('titleDiv'); titleDiv.innerHTML = data.discountTitle; const noteDiv = document.createElement('div'); noteDiv.classList.add('gfgVolDiscountNoteDiv'); noteDiv.innerHTML = data.note; const gridDiv = document.createElement('div'); gridDiv.classList.add('gridDiv'); for (let i = 0; i < data.discountTiers.length; i++) { let discountTier = data.discountTiers[i]; let qtyLabel = discountTier.text; let priceLabel = parseFloat(discountTier.priceValue).toFixed(2); let strikethroughValue = discountTier.strikethroughValue; if (gfg.state?.formatPriceViaCustomScript) { priceLabel = gfg.utility.formatPriceWithSeparator(priceLabel * 100); strikethroughValue = gfg.utility.formatPriceWithSeparator(strikethroughValue * 100); } priceLabel = symbol + priceLabel; const boxDiv = document.createElement('div'); boxDiv.classList.add('gfgGridBox'); boxDiv.setAttribute("discount-tier", i + 1); boxDiv.style.backgroundColor = backgroundColor; boxDiv.style.border = `1px solid ${borderColor}`; const radioSelectionDiv = document.createElement('div'); radioSelectionDiv.classList.add('gfgRadioSelection'); radioSelectionDiv.setAttribute("discount-tier", i + 1); const radioBtn = document.createElement('input'); radioBtn.classList.add('radioButton'); radioBtn.type = "radio"; radioBtn.name = "dicountTierBtn"; radioBtn.setAttribute("discount-tier", i + 1); radioBtn.value = data.discountTiers[i].quantitylabel; const gfgRadioSelectionLabelDiv = document.createElement('div'); gfgRadioSelectionLabelDiv.classList.add('gfgRadioSelectionLabel'); gfgRadioSelectionLabelDiv.innerHTML = " "; const qtyLabelDiv = document.createElement('div'); qtyLabelDiv.classList.add('gfgQtyLabel'); qtyLabelDiv.innerHTML = qtyLabel; qtyLabelDiv.style.color = textColor; radioSelectionDiv.append(radioBtn, gfgRadioSelectionLabelDiv); const priceDiv = document.createElement('div'); priceDiv.classList.add("gfgPricesDiv"); const compareAtPrice = document.createElement('div'); compareAtPrice.classList.add("gfgCompareAtPrice"); compareAtPrice.innerHTML = strikethroughValue; const costDiv = document.createElement('div'); costDiv.classList.add("gfgCostLabel"); costDiv.innerHTML = priceLabel; priceDiv.append(compareAtPrice, costDiv); const labelAndPriceDiv = document.createElement('div'); labelAndPriceDiv.classList.add("gfgLabelAndPriceDiv"); labelAndPriceDiv.append(qtyLabelDiv, priceDiv); boxDiv.append(radioSelectionDiv, labelAndPriceDiv); if (i == data.defaultSelectedTierIndex) { boxDiv.classList.add('gfgGridBoxSelected'); // radioBtn.checked = true; radioBtn.defaultChecked = true; gfg.gfgVolDiscount.state.defaultTierSelectedQuantity = data.discountTiers[i].quantitylabel; gfg.gfgVolDiscount.actions.handleQuantityUpdate(); } if (i == data.mostPopularSelectedTierIndex) { const mostPopularTagDiv = gfg.gfgVolDiscount.f.prepareUIForMostPopularTag(mostPopularSelectedTierData); boxDiv.append(mostPopularTagDiv); } document.body.addEventListener('click', function (event) { const gridBox = event.target.closest('.gfgGridBox'); // Match the closest .gfgGridBox if (gridBox) { event.stopPropagation(); event.stopImmediatePropagation(); const discountTier = gridBox.getAttribute("discount-tier"); const radioBtn = gridBox.querySelector('.radioButton'); if (gridBox.classList.contains('gfgGridBoxSelected')) { gridBox.classList.remove('gfgGridBoxSelected'); if (radioBtn) radioBtn.checked = false; gfg.gfgVolDiscount.state.triggerResetCount = true; } else { document.querySelectorAll('.gfgGridBox').forEach(box => { box.classList.remove('gfgGridBoxSelected'); }); document.querySelectorAll('.radioButton').forEach(radio => { radio.checked = false; }); gridBox.classList.add('gfgGridBoxSelected'); if (radioBtn) radioBtn.checked = true; } gfg.gfgVolDiscount.actions.handleQuantityUpdate(); } }); gridDiv.append(boxDiv); } const htmlElementsToSendObj = { "VOLUME_DISCOUNT_PRODUCT_PAGE_TITLE_BAR": titleDiv, }; this.handleCustomCssForWidget(htmlElementsToSendObj, volDiscountDataForProductPage); gfgFVolDiscountContainer.append(titleDiv, gridDiv); if (data.note?.trim() !== "") { gfgFVolDiscountContainer.append(noteDiv); } return gfgFVolDiscountContainer; } else { return this.prepareBulkUI(parent, volDiscountDataForProductPage); } }, prepareBulkUI: function (parent, volDiscountDataForProductPage) { let data = volDiscountDataForProductPage.prouctUiDataToBeShown; gfg.utility.debugConsole(data); let note = data?.note; let discountTitle = data?.discountTitle; let colors = data?.colors; let textColor = colors?.text; let borderColor = colors?.border; let backgroundColor = colors?.background; const gfgFVolDiscountContainer = document.createElement('div'); gfgFVolDiscountContainer.classList.add('gfgVolDiscountContainer', 'gfgThisIsTieredDiscountOnProductPage'); Object.assign(gfgFVolDiscountContainer.style, { backgroundColor: "", color: "", display: "grid", padding: "5px", textAlign: "center", }); const titleDiv = document.createElement('div'); titleDiv.classList.add('gfgTitleDiv'); titleDiv.innerHTML = discountTitle; Object.assign(titleDiv.style, { fontWeight: "bolder", textAlign: "center", fontSize: "20px", margin: "5px 0px", }); const gridDiv = document.createElement('div'); gridDiv.classList.add('gfgGridDiv'); Object.assign(gridDiv.style, { border: "black solid 1px", borderRadius: "5px", textAlign: "center", borderColor: borderColor, backgroundColor: backgroundColor, }); const noteDiv = document.createElement('div'); noteDiv.classList.add('gfgNoteDiv'); noteDiv.innerHTML = note; Object.assign(noteDiv.style, { margin: "20px 0px 10px 0px", color: textColor, }); for (let i = 0; i < data.discountTiers.length; i++) { let text = data.discountTiers[i].text; const boxDiv = document.createElement('div'); boxDiv.classList.add('gfgGridBox'); boxDiv.innerHTML = text; Object.assign(boxDiv.style, { textAlign: "center", padding: "10px", margin: "5px 0px", fontSize: "15px", color: textColor, }); gridDiv.appendChild(boxDiv); } if (note?.trim() !== "") { gridDiv.appendChild(noteDiv); } gfgFVolDiscountContainer.append(titleDiv, gridDiv); return gfgFVolDiscountContainer; }, getVolDiscountDataForProductPage: async function() { let productPageId = gfg.state.productPageId let productPageHandle = gfg.state.productPageHandle const storeFrontAccessToken = gfg?.settings?.merchantInfo?.storefrontAccessToken if(!productPageId){ productPageId = gfg.f.getProductPageId(); } if(!productPageHandle){ productPageHandle = gfg.f.getProductPageHandle(); } let discounts = gfg.settings.discounts let productPageData = undefined if(productPageId && storeFrontAccessToken){ const productGid = `gid://shopify/Product/${productPageId}`; const productData = await gfg.customDiscountStorefrontApis.getProductsDataByIdWithAjaxResponse([productGid]); productPageData = productData[0]; } else if(productPageHandle){ productPageData = await gfg.utility.getProductDataV2(productPageHandle) } if(!productPageData){ return undefined } if(discounts && discounts.length > 0) { }else{ return } let validVolDiscount = undefined let maxFirstTierVolDiscount = undefined //As One product could be present in multiple discount campagin, find which one give the minimum finalPrice for(let i = 0; i < discounts.length; i++) { let discount = discounts[i] if(discount.isEnabled == false){ continue } if(discount?.isEBIntegrationEnabled){ continue } //check if eb integration enabled return let checkIfThisDiscountIsForThisProductPage = undefined //check if this discount is for this product page if yes calculate the final price if(discount?.disProducts?.type == "ALL_PRODUCTS") { checkIfThisDiscountIsForThisProductPage = true } if(discount?.disProducts?.type == "COLLECTIONS") { // let calculateFirstTierFinalPrice = gfg.gfgVolDiscount.f.calculateFirstTierFinalPrice(discount, productPageData) let collections = discount?.disProducts?.collectionsData || [] for(let k=0; k < collections?.length; k++){ let products = collections[k]?.productList || [] for(let j = 0; j < products?.length; j++) { let product = products[j] if(product?.id == productPageId || product?.handle == productPageHandle) { checkIfThisDiscountIsForThisProductPage = true break } } } } if(discount?.disProducts?.type == "SELECTED_PRODUCTS") { let products = discount?.disProducts?.products for(let j = 0; j < products.length; j++) { let product = products[j] if(product?.productId == productPageId || product?.handle == productPageHandle) { checkIfThisDiscountIsForThisProductPage = true break } } } if(checkIfThisDiscountIsForThisProductPage){ let currFirstTierVolDiscount = parseFloat(discount.rules[0].disValue) if(maxFirstTierVolDiscount == undefined || currFirstTierVolDiscount > maxFirstTierVolDiscount ) { maxFirstTierVolDiscount = currFirstTierVolDiscount validVolDiscount = discount discount.productPageData = productPageData; validVolDiscount.prouctUiDataToBeShown = gfg.gfgVolDiscount.f.prepareUIDataWrapper(discount); } } } gfg.utility.debugConsole(validVolDiscount, 'valid vol discount') gfg.gfgVolDiscount.state.validVolDiscount = validVolDiscount; return validVolDiscount }, prepareBulkDiscountRulesWidgets: async function(settings) { try { const gfgBulkDiscountWidgetHTMLWrapper = document.createElement('div'); gfgBulkDiscountWidgetHTMLWrapper.classList.add('gfgBulkDiscountWidgetHTMLWrapper'); const gfgBulkDiscountWidgetHTML = document.createElement('div'); gfgBulkDiscountWidgetHTML.classList.add('gfgBulkDiscountWidgetHTML'); let discounts = settings?.discounts; if(!settings?.discounts || settings.discounts.length == 0) { return; } gfg.state.cartData = await gfg.utility.getCart() for(let i = 0; i < discounts.length; i++) { let currDiscount = discounts[i]; if(currDiscount?.cartWidgetConfiguration?.isEnabled) { const singleBulkDiscountWidget = gfg.gfgVolDiscount.f.prepareSingleBulkDiscountRulesWidget(currDiscount); if(singleBulkDiscountWidget){ gfgBulkDiscountWidgetHTML.append(singleBulkDiscountWidget); } gfgBulkDiscountWidgetHTMLWrapper.append(gfgBulkDiscountWidgetHTML); } } return gfgBulkDiscountWidgetHTMLWrapper; } catch(err) { gfg.utility.debugConsole("err inside renderAllDiscountRuleWidgets", err); } }, prepareSingleBulkDiscountRulesWidget: function (currBulkDiscount) { try { const gfgBulkDiscountSingleWidgetHTML = document.createElement('div'); gfgBulkDiscountSingleWidgetHTML.classList.add('gfgBulkDiscountSingleWidgetHTML'); const gfgBulkDiscountSingleWidgetWrapper = document.createElement('div'); gfgBulkDiscountSingleWidgetWrapper.classList.add('gfgBulkDiscountSingleWidgetWrapper'); const currDiscountIdx = gfg.gfgVolDiscount.f.getIndexOfRuleThatCanBeAppliedAtCurrCartState(currBulkDiscount); let nextDiscountRuleIndex; if (currDiscountIdx === currBulkDiscount.rules.length - 1) { return; } else if (currDiscountIdx === -1) { nextDiscountRuleIndex = 0; } else { nextDiscountRuleIndex = currDiscountIdx + 1; } const gfgBulkDiscountSingleWidgetTitle = document.createElement('div'); gfgBulkDiscountSingleWidgetTitle.classList.add('gfgBulkDiscountSingleWidgetTitle'); const title = gfg.gfgVolDiscount.f.replaceVolDiscountWidgetVariables( currBulkDiscount, currBulkDiscount?.cartWidgetConfiguration?.tierConfig[nextDiscountRuleIndex]?.conditionNotMet?.title, nextDiscountRuleIndex ); gfgBulkDiscountSingleWidgetTitle.innerHTML = title; const gfgBulkDiscountSingleWidgetSubTitle = document.createElement('div'); gfgBulkDiscountSingleWidgetSubTitle.classList.add('gfgBulkDiscountSingleWidgetSubTitle'); const subtitle = gfg.gfgVolDiscount.f.replaceVolDiscountWidgetVariables( currBulkDiscount, currBulkDiscount?.cartWidgetConfiguration?.tierConfig[nextDiscountRuleIndex]?.conditionNotMet?.subtitle, nextDiscountRuleIndex ); gfgBulkDiscountSingleWidgetSubTitle.innerHTML = subtitle; const gfgBulkDiscountSingleWidgetPillBox = this.gfgPrepareBulkDiscountSingleWidgetPill(currBulkDiscount); if (!(title || subtitle)) { return; } const htmlElementsToSendObj = { gfgBulkDiscountSingleWidgetHTML, gfgBulkDiscountSingleWidgetSubTitle, }; this.handleCustomCssForWidget(htmlElementsToSendObj, currBulkDiscount); gfgBulkDiscountSingleWidgetWrapper.appendChild(gfgBulkDiscountSingleWidgetTitle); if (subtitle && typeof subtitle === 'string' && subtitle.trim() !== '') { gfgBulkDiscountSingleWidgetWrapper.appendChild(gfgBulkDiscountSingleWidgetSubTitle); } gfgBulkDiscountSingleWidgetHTML.appendChild(gfgBulkDiscountSingleWidgetWrapper); if (gfgBulkDiscountSingleWidgetPillBox) { gfgBulkDiscountSingleWidgetHTML.appendChild(gfgBulkDiscountSingleWidgetPillBox); } return gfgBulkDiscountSingleWidgetHTML; } catch (err) { gfg.utility.debugConsole('err inside prepareSingleBulkDiscountRulesWidget:', err); } }, replaceVolDiscountWidgetVariables: function(currBulkDiscountData, text, nextDiscountRuleIndex) { try { let currBulkDiscount = JSON.parse(JSON.stringify(currBulkDiscountData)); let _cartData = gfg.state.cartData; let CURRENCY = gfg.utility.getCurrencySymbol() || "$"; if(currBulkDiscount.disProducts.type == "COLLECTIONS"){ let COLLECTIONS = currBulkDiscount?.disProducts.collections.map(collection => collection.title).join(', '); // let COLLECTIONS_LINKS = currBulkDiscount?.disProducts.collections.map(collection => `${collection.title}`).join(', '); let COLLECTIONS_LINKS = currBulkDiscount?.disProducts.collections.map(collection => `${collection.title}`).join(', '); // count how many of them are there in the collecton using the "," seperator and then attach ellipsis when more than 4 if(COLLECTIONS.split(',').length > 4){ COLLECTIONS = COLLECTIONS.split(',').slice(0, 4).join(', ') + "..." //same with links COLLECTIONS_LINKS = COLLECTIONS_LINKS.split(',').slice(0, 4).join(', ') + "..." } text = text.replace("{{COLLECTIONS}}", COLLECTIONS); text = text.replace("{{COLLECTIONS_LINKS}}", COLLECTIONS_LINKS); text = text.replace("{{COLLECTION_LINK}}",COLLECTIONS_LINKS); } if(currBulkDiscount.disProducts.type == "SELECTED_PRODUCTS"){ let PRODUCTS = currBulkDiscount?.disProducts.products.map(product => product.title).join(', '); // let PRODUCTS_LINKS = currBulkDiscount?.disProducts.products.map(product => `${product.title}`).join(', '); let PRODUCTS_LINKS = currBulkDiscount?.disProducts.products.map(product => `${product.title}`).join(', '); // count how many of them are there in the collecton using the "," seperator and then attach ellipsis when more than 4 if(PRODUCTS.split(',').length > 4){ PRODUCTS = PRODUCTS.split(',').slice(0, 4).join(', ') + "..." //same with links PRODUCTS_LINKS = PRODUCTS_LINKS.split(',').slice(0, 4).join(', ') + "..." } // if variant selection is allowed then get the products and links for the selected variants if(currBulkDiscount.disProducts?.allowVariantSelection){ const { PRODUCTS: variantProducts, PRODUCTS_LINKS: variantProductsLinks } = this.getProductsAndLinksForVariantSelectedProducts(currBulkDiscount); PRODUCTS = variantProducts; PRODUCTS_LINKS = variantProductsLinks; } text = text.replace("{{PRODUCTS}}", PRODUCTS); text = text.replace("{{PRODUCTS_LINKS}}", PRODUCTS_LINKS); } if(currBulkDiscount.conditionType == "COUNT") { let conditionValue = parseInt(currBulkDiscount.rules[nextDiscountRuleIndex].conditionValue); let REMAINING_QUANTITY = 0; let PRODUCT_QUANTITY = conditionValue; if(currBulkDiscount.disProducts.type == "ALL_PRODUCTS") { // let cartQty = _cartData?.item_count || 0; const allProductsData = this.getDataOfAllProductsInCart(currBulkDiscount); let cartQty = allProductsData.totalCount; REMAINING_QUANTITY = conditionValue - cartQty; } else if(currBulkDiscount.disProducts.type == "COLLECTIONS") { let collectionCartData = this.getDataOfProductsPresentInCartFromThisCollection(currBulkDiscount); let totalProductsInCollection = collectionCartData.totalProductsInCollection; REMAINING_QUANTITY = conditionValue - totalProductsInCollection; } else if(currBulkDiscount.disProducts.type == "SELECTED_PRODUCTS") { let productsCartData = this.getDataOfProductsPresentInCartFromThisListOfProducts(currBulkDiscount); let totalProductsInList = productsCartData?.totalProductsInList REMAINING_QUANTITY = conditionValue - totalProductsInList; } text = text.replace("{{PRODUCT_QUANTITY}}", PRODUCT_QUANTITY); text = text.replace("{{REMAINING_QUANTITY}}", REMAINING_QUANTITY); } if(currBulkDiscount.conditionType == "SUBTOTAL") { let conditionValue = parseFloat(currBulkDiscount.rules[nextDiscountRuleIndex].conditionValue); conditionValue = gfg.utility.convertFromStoreCurrencyToCustomer(conditionValue) let REMAINING_AMOUNT = 0; if(currBulkDiscount.disProducts.type == "ALL_PRODUCTS") { // let _totalValue = parseFloat(_cartData.total_price / 100); // let _totalValue = parseFloat(_cartData.original_total_price / 100); const allProductsData = this.getDataOfAllProductsInCart(currBulkDiscount); let _totalValue = allProductsData?.totalValue; REMAINING_AMOUNT = conditionValue - _totalValue; } else if(currBulkDiscount.disProducts.type == "COLLECTIONS") { let collectionCartData = this.getDataOfProductsPresentInCartFromThisCollection(currBulkDiscount); let totalValueOfCollection = collectionCartData.totalValueOfCollection; REMAINING_AMOUNT = conditionValue - totalValueOfCollection; } else if(currBulkDiscount.disProducts.type == "SELECTED_PRODUCTS") { let productsCartData = this.getDataOfProductsPresentInCartFromThisListOfProducts(currBulkDiscount); let totalValueOfProducts = productsCartData.totalValueOfProducts; REMAINING_AMOUNT = conditionValue - totalValueOfProducts; } REMAINING_AMOUNT = parseFloat(REMAINING_AMOUNT).toFixed(2) // if format price via custom script is enabled then format the price if(gfg.state?.formatPriceViaCustomScript){ REMAINING_AMOUNT = REMAINING_AMOUNT * 100; // in shopify format REMAINING_AMOUNT = gfg.utility.formatPriceWithSeparator(REMAINING_AMOUNT); } text = text.replace("{{REMAINING_AMOUNT}}", REMAINING_AMOUNT); } let DISCOUNT = parseFloat(currBulkDiscount.rules[nextDiscountRuleIndex].disValue); // if the discount is fixed then convert its value into the active currency if(currBulkDiscount.disValueType == "FIXED_DIS" || currBulkDiscount.disValueType === "FIXED_TOTAL") { DISCOUNT = parseFloat(gfg.utility.getAmountInActiveCurrency(DISCOUNT)); // if format price via custom script is enabled then format the price if(gfg.state?.formatPriceViaCustomScript){ DISCOUNT = DISCOUNT * 100; // in shopify format DISCOUNT = gfg.utility.formatPriceWithSeparator(DISCOUNT); } } text = text.replace(/{{CURRENCY}}/g, CURRENCY); text = text.replace("{{DISCOUNT}}", DISCOUNT); return text; } catch(err) { gfg.utility.debugConsole("err inside replaceVolDiscountWidgetVariables", err); } }, getIndexOfRuleThatCanBeAppliedAtCurrCartState: function(currBulkDiscount) { try { let isQtyBasedDiscount = false; let isValueBasedDiscount = false; if (currBulkDiscount?.conditionType == "COUNT") { isQtyBasedDiscount = true; } else if (currBulkDiscount?.conditionType == "SUBTOTAL") { isValueBasedDiscount = true; } let i = 0; let lastSatisfyingIndex = -1; while (i < currBulkDiscount.rules.length) { let currRule = currBulkDiscount.rules[i]; let conditionValue = parseFloat(currRule.conditionValue); if (isQtyBasedDiscount) { if (currBulkDiscount.disProducts.type == "ALL_PRODUCTS") { // let _cartData = gfg.state.cartData; // let _totalProducts = _cartData.item_count; const allProductsData = this.getDataOfAllProductsInCart(currBulkDiscount); let _totalProducts = allProductsData?.totalCount; if (_totalProducts >= conditionValue) { lastSatisfyingIndex = i; } else { break; } } else if (currBulkDiscount.disProducts.type == "COLLECTIONS") { let collectionData = this.getDataOfProductsPresentInCartFromThisCollection(currBulkDiscount); let totalProductsInCollection = collectionData.totalProductsInCollection; if (totalProductsInCollection >= conditionValue) { lastSatisfyingIndex = i; } else { break; } } else if (currBulkDiscount.disProducts.type == "SELECTED_PRODUCTS") { let productsData = this.getDataOfProductsPresentInCartFromThisListOfProducts(currBulkDiscount); let totalProductsInList = productsData.totalProductsInList; if (totalProductsInList >= conditionValue) { lastSatisfyingIndex = i; } else { break; } } } else if (isValueBasedDiscount) { const _conditionValue = parseFloat(gfg.utility.convertFromStoreCurrencyToCustomer(conditionValue)); if (currBulkDiscount.disProducts.type == "ALL_PRODUCTS") { // let _cartData = gfg.state.cartData; // let _totalValue = parseFloat(_cartData.total_price / 100); // let _totalValue = parseFloat(_cartData.original_total_price / 100); const allProductsData = this.getDataOfAllProductsInCart(currBulkDiscount); let _totalValue = allProductsData?.totalValue; if (_totalValue >= _conditionValue) { lastSatisfyingIndex = i; } else { break; } } else if (currBulkDiscount.disProducts.type == "COLLECTIONS") { let collectionData = this.getDataOfProductsPresentInCartFromThisCollection(currBulkDiscount); let totalValueOfCollection = collectionData.totalValueOfCollection; totalValueOfCollection = parseFloat(totalValueOfCollection); if (totalValueOfCollection >= _conditionValue) { lastSatisfyingIndex = i; } else { break; } } else if (currBulkDiscount.disProducts.type == "SELECTED_PRODUCTS") { let productsData = this.getDataOfProductsPresentInCartFromThisListOfProducts(currBulkDiscount); let totalValueOfProducts = productsData.totalValueOfProducts; totalValueOfProducts = parseFloat(totalValueOfProducts); if (totalValueOfProducts >= _conditionValue) { lastSatisfyingIndex = i; } else { break; } } } else { // If the condition is not satisfied, break the loop break; } i++; } // `lastSatisfyingIndex` will now hold the index of the last rule for which the condition satisfies return lastSatisfyingIndex; } catch(err) { gfg.utility.debugConsole("err inside getIndexOfRuleThatCanBeAppliedAtCurrCartState:", err); } }, getCurrentQuantitySelection: function() { const selectedQuantity = document.querySelector('input[name="dicountTierBtn"]:checked')?.value; if (!selectedQuantity && gfg.gfgVolDiscount.state.triggerResetCount) { gfg.gfgVolDiscount.state.triggerResetCount = false; return 1; } return selectedQuantity; }, addToCartButtonOverwrite: function () { try { gfg.gfgVolDiscount.state.isAddToCartButtonOverwrite = true; gfg.elements.addToCartBtn.setAttribute("type", "button"); gfg.elements.addToCartBtn.disabled = false; gfg.elements.addToCartBtn.classList.add("gfgAddToCartBtn"); gfg.elements.addToCartBtn.removeEventListener("click", handleAddToCartClick); async function handleAddToCartClick(event) { if (event.stopImmediatePropagation) { event.stopImmediatePropagation(); } const buttonText = gfg.elements.addToCartBtn.textContent; const currentVariant = gfg.f.getSelectedVariant(); const currentQuantitySelection = gfg.gfgVolDiscount.f.getCurrentQuantitySelection(); const data = { id: currentVariant, quantity: currentQuantitySelection, }; gfg.utility.debugConsole(data, "data"); const spinner = document.createElement("div"); spinner.innerHTML = CONSTANT_LOADING_SPINNER_SVG; gfg.elements.addToCartBtn.appendChild(spinner); const addedToCart = await gfg.utility.addToCart(data); gfg.gfgVolDiscount.state.addToCartClicked = true; const spinnerElement = gfg.elements.addToCartBtn.querySelector(".gfgLoadingSpinner"); if (spinnerElement) { spinnerElement.remove(); } if (addedToCart) { gfg.elements.addToCartBtn.classList.remove("gfgDisabled"); gfg.gfgVolDiscount.f.executeScriptAfterAddToCart(); } else { gfg.elements.addToCartBtn.classList.remove("gfgDisabled"); } gfg.gfgVolDiscount.state.addToCartClicked = false; } gfg.elements.addToCartBtn.addEventListener("click", handleAddToCartClick); } catch (error) { gfg.utility.debugConsole("error inside addToCartButtonOverwrite", error); } }, executeScriptAfterAddToCart: function () { try{ // find cart-drawer and add active class to it // refresh cart drawer section idgf if(gfg.settings.app.executeScriptAfterAddToCart){ eval(gfg.settings.app.executeScriptAfterAddToCart) } }catch(err){ gfg.utility.debugConsole("err inside executeScriptAfterAddToCart", err) } }, getDataOfProductsPresentInCartFromThisCollection_Archive: function(currBulkDiscount) { try { let _cartData = gfg.state.cartData; let totalProductsInCollection = 0; let totalValueOfCollection = 0; let collectionData = currBulkDiscount.disProducts.collectionsData; collectionData?.forEach(collection => { collection?.productList?.forEach(productInCollection => { // Find the matching product in the cart let matchingCartItem = _cartData?.items?.find(cartItem => cartItem.product_id === productInCollection.productId); if (matchingCartItem) { totalProductsInCollection += matchingCartItem.quantity; let finalItemPrice = Number(parseFloat(matchingCartItem.price / 100)); finalItemPrice = finalItemPrice * matchingCartItem.quantity; totalValueOfCollection += finalItemPrice; } }); }); return { totalProductsInCollection, totalValueOfCollection }; } catch (err) { gfg.utility.debugConsole("err inside getDataOfProductsPresentInCartFromThisCollection_Archive", err); return { totalProductsInCollection: 0, totalValueOfCollection: 0} } }, getDataOfProductsPresentInCartFromThisCollection: function(currBulkDiscount) { try { let _cartData = gfg.state.cartData; let totalProductsInCollection = 0; let totalValueOfCollection = 0; let collectionData = currBulkDiscount.disProducts.collectionsData; const relavantCartItems = []; // loop through the cart items and store relavant cart items for (let i = 0; i < _cartData?.items?.length; i++) { const cartItem = _cartData?.items[i]; // Check cartItem eligibility for subscription products too const isCartItemRelevant = this.checkCartItemRelevancyInCaseOfSubscriptionProducts(currBulkDiscount, cartItem); if (!isCartItemRelevant) { continue; } collectionsLoop: for (let j = 0; j < collectionData?.length; j++) { const collection = collectionData[j]; for (let k = 0; k < collection?.productList?.length; k++) { const productInCollection = collection.productList[k]; if (cartItem.product_id == productInCollection.productId) { relavantCartItems.push(cartItem); // Break out of the collections loop break collectionsLoop; } } } } // Calculate the total products and value of the collection for (let i = 0; i < relavantCartItems.length; i++) { const cartItem = relavantCartItems[i]; totalProductsInCollection += cartItem.quantity; let finalItemPrice = Number(parseFloat(cartItem.price / 100)); finalItemPrice = finalItemPrice * cartItem.quantity; totalValueOfCollection += finalItemPrice; } return { totalProductsInCollection, totalValueOfCollection }; } catch (err) { gfg.utility.debugConsole("err inside getDataOfProductsPresentInCartFromThisCollection:", err); return { totalProductsInCollection: 0, totalValueOfCollection: 0} } }, getDataOfProductsPresentInCartFromThisListOfProducts: function(currBulkDiscount) { try { let cartData = gfg.state.cartData; const productIdsInCart = cartData.items.map(item => item.product_id); const allowVariantSelection = currBulkDiscount?.disProducts?.allowVariantSelection; let totalProductsInList = 0; let totalValueOfProducts = 0; for (const product of currBulkDiscount.disProducts.products) { if (productIdsInCart.includes(parseInt(product.productId))) { for (const item of cartData.items) { // check if variant selection is enabled, if enabled then check if the variant is present in the cart // if not then continue to the next item if(allowVariantSelection){ const productVariantIds = product.variants.map(variant => variant.variantId); const formattedVariantId = String(item.variant_id); if(!productVariantIds.includes(formattedVariantId)){ continue; } } // Check cartItem eligibility for subscription products too. If Item is not relevant then continue to next item const isCartItemRelevant = this.checkCartItemRelevancyInCaseOfSubscriptionProducts(currBulkDiscount, item); if(!isCartItemRelevant){ continue; } if (item.product_id == product.productId) { totalProductsInList += item.quantity; let finalItemPrice = Number(parseFloat(item.price / 100)); finalItemPrice = finalItemPrice * item.quantity; totalValueOfProducts += finalItemPrice } } } } return { totalProductsInList, totalValueOfProducts }; } catch(err) { gfg.utility.debugConsole("err inside getDataOfProductsPresentInCartFromThisListOfProducts", err); return { totalProductsInList: 0, totalValueOfProducts: 0} } }, gfgVolumeDiscountFilter: function(modifiedDiscounts){ let filteredData = []; let customerSpecificDiscount = []; let discounts = modifiedDiscounts || gfg.settings.discounts; if(discounts.length == 0){ return; } //iterate through all the discounts and find the one that is enabled for(let i = 0; i < discounts.length; i++){ const customerData = gfg.state.activeCustomerData; // if(length of conditionsLength array is greater then 1) if(discounts[i].conditionsData.conditionsList.length > 0){ let conditionOperator = discounts[i].conditionsData.conditionsOperator; let conditionsList = discounts[i].conditionsData.conditionsList; let isDiscountValid = gfg.gfgFreeGift.f.gfgCheckConditionOutcome(conditionsList, conditionOperator); if(isDiscountValid){ filteredData.push(discounts[i]); customerSpecificDiscount.push(discounts[i]); } }else{ // if length of conditionsLength array is 0 filteredData.push(discounts[i]); if(customerData.isCustomerLoggedInBool){ customerSpecificDiscount.push(discounts[i]); } } // if(customerData.isCustomerLoggedInBool){ // }else{ // // if length of conditionsLength array is 0 // if(discounts[i].conditionsData.conditionsList.length == 0){ // filteredData.push(discounts[i]); // } // } } gfg.gfgVolDiscount.state.customerSpecificDiscount = customerSpecificDiscount; return filteredData; }, gfgVolumeDiscountCheckConditions: function(){ try{ }catch(err){ gfg.utility.debugConsole('gfgVolumeDiscountCheckConditions ', err); } }, DiscountTierSelect_DselectOnQuantityChanges: function(currentValueOfQuantitySelector){ try { const selectedTierWidgetQuantity = gfg.gfgVolDiscount.f.getCurrentQuantitySelection(); if(!currentValueOfQuantitySelector || !selectedTierWidgetQuantity){ return ; } if(currentValueOfQuantitySelector != selectedTierWidgetQuantity){ document.querySelectorAll('.gfgGridBox').forEach((element) => { element.classList.remove('gfgGridBoxSelected'); }); document.querySelectorAll('.radioButton').forEach((radioButton) => { radioButton.checked = false; }); } } catch (error) { gfg.utility.debugConsole("error inside DiscountTierSelect_DselectOnQuantityChanges", error); } }, prepareUIForMostPopularTag: function (mostPopularSelectedTierData) { try { const mostPopularTagContainer = document.createElement('div'); mostPopularTagContainer.classList.add('gfgMostPopularTagContainer'); if (mostPopularSelectedTierData?.badgeStyle === "simple") { const simpleRibbonBadge = document.createElement('div'); simpleRibbonBadge.classList.add('gfgSimpleRibbonBadge'); simpleRibbonBadge.innerHTML = mostPopularSelectedTierData?.title; mostPopularTagContainer.classList.add('gfgTemplateSimpleRibbonBadge'); Object.assign(simpleRibbonBadge.style, { backgroundColor: mostPopularSelectedTierData?.customization?.bgColor, color: mostPopularSelectedTierData?.customization?.titleColor, }); mostPopularTagContainer.appendChild(simpleRibbonBadge); } return mostPopularTagContainer; } catch (error) { gfg.utility.debugConsole("error inside prepareUIForMostPopularTag", error); } }, listenVariantChangeForVolDiscountProductPage: function(){ try { // Listen variant change after 1 second for volume discount & if there is a change then reinitialize the vol discount for product page if(gfg && gfg?.state?.page_type == "product"){ const checkIfValidVolDiscountExist = gfg.gfgVolDiscount?.state?.validVolDiscount; const currentSelectedVariantId = gfg.gfgVolDiscount?.state?.currentSelectedVariant?.id; const checkIfThisIsVolumeNotTieredDiscount = gfg.gfgVolDiscount?.state?.validVolDiscount?.conditionType == "COUNT" ? true : false; /* The reason for checking also if this is volume not tiered discount is because in tiered discount widget we don't show product pricing so no need to reintialize the discount*/ if(checkIfValidVolDiscountExist && checkIfThisIsVolumeNotTieredDiscount && currentSelectedVariantId){ const selectedVariant = gfg.f.getSelectedVariant(); // if there is a change in variant then reinitialize the vol discount if(selectedVariant != currentSelectedVariantId){ gfg.gfgVolDiscount.init(gfg.settings, "PRODUCT_PAGE"); } } } } catch (error) { gfg.utility.debugConsole("error inside listenVariantChangeForVolDiscountProductPage", error); } }, gfgFilterActiveScheduledDiscountCampaigns: function(discounts){ try { if(!discounts || discounts?.length === 0){ return []; } const modifiedDiscounts = discounts.filter(discount => { const campaignScheduleData = discount?.campaignScheduleData; // If there is no campaign schedule data or the campaign is not scheduled, include the discount if (!campaignScheduleData || campaignScheduleData?.campaignSchedule != "SCHEDULED") { return true; } // If the campaign is scheduled, check if the current date falls within the start and end dates if(campaignScheduleData?.campaignSchedule == "SCHEDULED"){ let currentDateUTC = new Date().toISOString(); let startDateTime_UTC = campaignScheduleData.startDateTime_UTC; let endDateTime_UTC = campaignScheduleData.endDateTime_UTC; if (currentDateUTC >= startDateTime_UTC && currentDateUTC <= endDateTime_UTC) { return true; } } }); return modifiedDiscounts; } catch (error) { gfg.utility.debugConsole("error inside gfgFilterActiveScheduledDiscountCampaigns", error); return discounts; } }, getDataOfAllProductsInCart: function(discount){ try { const cartData = gfg.state.cartData; let totalCount = 0; let totalValue = 0; const relevantCartItems = []; for (let i = 0; i < cartData?.items?.length; i++) { const item = cartData.items[i]; // handle subscription products eligiblity too. const isCartItemRelevant = this.checkCartItemRelevancyInCaseOfSubscriptionProducts(discount, item); if(isCartItemRelevant){ relevantCartItems.push(item); } } // Calculate the total products and value of the products for (let i = 0; i < relevantCartItems.length; i++) { const item = relevantCartItems[i]; totalCount += item.quantity; let finalItemPrice = Number(parseFloat(item.price / 100)); finalItemPrice = finalItemPrice * item.quantity; totalValue += finalItemPrice; } return { totalCount, totalValue }; } catch (error) { gfg.utility.debugConsole("error inside getDataOfAllProductsInCart", error); } }, checkCartItemRelevancyInCaseOfSubscriptionProducts: function(discount, cartItem){ try { let isItemEligible = true; if(discount?.subscriptionProductsEligibility === "INCLUDE_ONLY_SUBSCRIPTION_PRODUCTS" && !cartItem?.selling_plan_allocation?.selling_plan?.id){ isItemEligible = false; } else if(discount?.subscriptionProductsEligibility === "EXCLUDE_SUBSCRIPTION_PRODUCTS" && cartItem?.selling_plan_allocation?.selling_plan?.id){ isItemEligible = false; } return isItemEligible; } catch (error) { gfg.utility.debugConsole("error inside checkCartItemRelevancyInCaseOfSubscriptionProducts", error); return true; } }, handleCustomCssForWidget: function(variablesObj, discountSettings){ try { const productPageColorConfigs = discountSettings?.configuration?.colors; const productPageFontConfigs = discountSettings?.configuration?.fontConfig; const cartPageColorConfigs = discountSettings?.cartWidgetConfiguration?.globalConfig?.customisations; const cartPageFontConfigs = discountSettings?.cartWidgetConfiguration?.globalConfig?.fontConfig; const cssConfigurations = { "VOLUME_DISCOUNT_PRODUCT_PAGE_TITLE_BAR":{ "background-color": productPageColorConfigs?.titleBarBgColor, "color": productPageColorConfigs?.titleBarTextColor, "font-size": gfg.utility.getFontSizeValue(productPageFontConfigs?.titleBarTextFontSize), "font-weight": gfg.utility.getFontWeightValue(productPageFontConfigs?.titleBarTextFontWeight) }, "gfgBulkDiscountSingleWidgetPill":{ "background-color": cartPageColorConfigs?.pillBgColor, "color": cartPageColorConfigs?.pillTextColor, "font-size": gfg.utility.getFontSizeValue(cartPageFontConfigs?.pillTextFontSize), "font-weight": gfg.utility.getFontWeightValue(cartPageFontConfigs?.pillTextFontWeight) }, "gfgBulkDiscountSingleWidgetHTML":{ "background-color": cartPageColorConfigs?.backgroundColor, "color": cartPageColorConfigs?.textColor, "border-color": cartPageColorConfigs?.borderColor }, "gfgBulkDiscountSingleWidgetSubTitle":{ "border-top-color": cartPageColorConfigs?.borderColor } }; // Apply CSS configurations based on the key // Object.keys(variablesObj).forEach(key => { // if (!variablesObj[key]) { // return; // } // const cssObj = cssConfigurations[key]; // if (cssObj) { // variablesObj[key].css(cssObj); // } // }); Object.keys(variablesObj).forEach(key => { if (!variablesObj[key]) { return; } const cssObj = cssConfigurations[key]; if (cssObj) { const element = variablesObj[key]; Object.keys(cssObj).forEach(cssKey => { element.style[cssKey] = cssObj[cssKey]; }); } }); } catch (error) { gfg.utility.debugConsole("error inside - GFG Volume Discount- handleCustomCssForWidget", error); } }, gfgPrepareBulkDiscountSingleWidgetPill: function (currBulkDiscount) { try { const pillBox = document.createElement('div'); pillBox.classList.add('gfgBulkDiscountSingleWidgetPill'); const pillIcon = currBulkDiscount?.cartWidgetConfiguration?.cartPageWidgetIcons?.pillIcon || "https://free-gift-app7.s3.us-east-2.amazonaws.com/public/discountPillcon2.svg"; const pillTitle = currBulkDiscount?.cartWidgetConfiguration?.cartPageWidgetTexts?.pillText || "DISCOUNT"; const pillBoxInnerHtml = ` ${pillTitle} `; if (currBulkDiscount?.cartWidgetConfiguration?.isWidgetPillEnabled !== true) { return false; } this.handleCustomCssForWidget({ "gfgBulkDiscountSingleWidgetPill": pillBox }, currBulkDiscount); pillBox.innerHTML = pillBoxInnerHtml; return pillBox; } catch (error) { gfg.utility.debugConsole("error inside gfgPrepareBulkDiscountSingleWidgetPill", error); } }, getProductsAndLinksForVariantSelectedProducts: function(currBulkDiscount){ try { const selectedProducts = currBulkDiscount.disProducts.products; let productList = JSON.parse(JSON.stringify(selectedProducts)); // show maximum 4 products only if (selectedProducts.length > 4) { productList = productList.slice(0, 4); } const result = productList.map(product => { const productName = product.title; const variants = product?.variants || []; const variantTitles = variants.slice(0, 2).map(variant => variant?.title).filter(title => title); let plainText = `${productName}`; // let anchorTagText = `${productName}` let anchorTagText = `${productName}`; // if at least one variant title is present, then add the variant titles to the product name otherwise // return the product name / productLink as it is. if(variantTitles.length > 0){ let variantsString = variantTitles.join(', '); if (variants.length > 2) { variantsString += '...'; } plainText = `${productName}(${variantsString})`, anchorTagText = ` ${productName}(${variantsString}) ` return {plainText, anchorTagText}; } return {plainText, anchorTagText}; }); let PRODUCTS = result.map(item => item.plainText).join(', '); let PRODUCTS_LINKS = result.map(item => item.anchorTagText).join(', '); if(selectedProducts.length > 4){ PRODUCTS += ' ...'; PRODUCTS_LINKS += ' ...'; } return {PRODUCTS, PRODUCTS_LINKS}; } catch (error) { gfg.utility.debugConsole("error inside getProductsAndLinksForVariantSelectedProducts", error); } } }, actions: { handleQuantityUpdate: function () { let selectedQuantity; if (document.querySelector(".gfgCountDiscount")) { selectedQuantity = gfg.gfgVolDiscount.f.getCurrentQuantitySelection(); } else if ( gfg.gfgVolDiscount.state.defaultTierSelectedQuantity && gfg.gfgVolDiscount.state.isDefaultTierSelectionDone == false ) { selectedQuantity = gfg.gfgVolDiscount.state.defaultTierSelectedQuantity; gfg.gfgVolDiscount.state.isDefaultTierSelectionDone = true; } else { return; } if (isNaN(selectedQuantity)) { return; } const quantityButtons = document.querySelectorAll(gfg.elements.quantityBtn); let shouldCallOverwrite = true; quantityButtons.forEach((quantityButton) => { quantityButton.classList.add("gfgHide"); let quantitySelectorEle = quantityButton; if (quantitySelectorEle.tagName.toLowerCase() !== "input") { quantitySelectorEle = quantityButton.querySelector("input"); } if (quantitySelectorEle && quantitySelectorEle.tagName.toLowerCase() === "input") { quantitySelectorEle.value = selectedQuantity; // Set live value quantitySelectorEle.setAttribute("value", selectedQuantity); // Update DOM attribute shouldCallOverwrite = false; } }); if(shouldCallOverwrite && gfg.gfgVolDiscount.state.isAddToCartButtonOverwrite === false){ gfg.gfgVolDiscount.f.addToCartButtonOverwrite(); } }, listenQuantityUpdates: function(){ try { const currentValueOfQuantity = gfg.utility.getQuantityValueFromQuantitySelector(); gfg.gfgVolDiscount.f.DiscountTierSelect_DselectOnQuantityChanges(currentValueOfQuantity); } catch (error) { gfg.utility.debugConsole("error inside listenQuantityUpdates", error); } } } }, gfgBogoFeature:{ state:{ isEnabled: false, shopName: "", rules: [], configuration: {}, textConfig: {}, showBogoNotificationSettings: {}, schedulerSettings: {}, gfgBogoProductsShopifyDataByVariantIds: {}, gfgBogoProductsCustomerGetsShopifyDataByVariantIds: {}, gfgBogoProductsShopifyDataByHandles: {}, bogoProductsShopifyData: [], bogoProductCustomerGetsShopifyData: [], isCartUpdatedByUs: false, bucketCount: 0, cartData: {}, fallBackImageUrl: 'https://d1cjetlwgplgi5.cloudfront.net/public/freeGiftDymmyImage.png', multiLangData: {}, activeBogoIndex: 0, }, init: async function (settings, parent) { try{ let productPageHandle = gfg.state.productPageHandle; let productPageId = gfg.state.productPageId; let bogoArray = gfg.settings.boGoFeature; if (bogoArray.length == 0) { gfg.utility.debugConsole("bogo array is empty"); return; } if(!productPageHandle){ productPageHandle = gfg.f.getProductPageHandle(); gfg.state.productPageHandle = productPageHandle; } if(!productPageId){ productPageId = gfg.f.getProductPageId(); gfg.state.productPageId = productPageId; } await gfg.gfgBogoFeature.f.gfgGetBogoFeatureoData(productPageHandle, productPageId); gfg.gfgBogoFeature.f.gfgBogoChangeLanguageConfigs(); gfg.gfgBogoFeature.initialize(settings, parent); gfg.utility.debugConsole("finally running bogo feature"); gfg.f.addPoweredByBlock(); gfg.gfgBogoFeature.f.registerEvents(); }catch(error){ gfg.utility.debugConsole("error inside bogo init", error) } }, initialize: async function (settings, parent) { try{ if (parent == "PRODUCT_PAGE" ) { // gfg.utility.debugConsole("page handle", gfg.state.productPageHandle) let productPageHandle = gfg.state.productPageHandle let activeBogoIndex = gfg.gfgBogoFeature.state.activeBogoIndex; if(!productPageHandle){ productPageHandle = gfg.f.getProductPageHandle(); } ifBogoProductValid = gfg.gfgBogoFeature.f.gfgCheckIfProductValidForBogo(productPageHandle) let checkIfBogoCampaignScheduleIsActive = gfg.gfgBogoFeature.f.checkIfBogoCampaignScheduleIsActive(); let isEBIntegrationEnabled = gfg.settings.boGoFeature[activeBogoIndex].isEBIntegrationEnabled; const isBogoWidgetAllowedOnProductPage = gfg.settings.boGoFeature[activeBogoIndex]?.showBoGoNotificationSettings?.customerBuysProdOrCollection; const areAllConditionsMet = ifBogoProductValid && checkIfBogoCampaignScheduleIsActive && !isEBIntegrationEnabled && isBogoWidgetAllowedOnProductPage !=false; if(areAllConditionsMet){ let htmlContent = gfg.gfgBogoFeature.f.gfgBogoFeaturePrepareUI(ifBogoProductValid); gfg.gfgBogoFeature.f.insertIntoPageWrapper(htmlContent, parent); gfg.utility.debugConsole("render on prod page") } } }catch(error){ gfg.utility.debugConsole("error inside bogo initialize", error) } }, f: { insertIntoPageWrapper: function (gfgMsgHtml, parent) { try { if (parent === "PRODUCT_PAGE") { const gfgBogoFeatureWrapperProductEle = gfg.utility.findWrapperElement("BOGO", "PRODUCT_PAGE", null); const clonedHtml = gfgMsgHtml.cloneNode(true).outerHTML; // Clone once and get the outerHTML gfgBogoFeatureWrapperProductEle.forEach((element) => { element.innerHTML = clonedHtml; // Set the innerHTML directly }); } else if (parent === "CART_PAGE") { // Logic for CART_PAGE can be implemented here if needed } // gfg.f.addPoweredByBlock(); // Uncomment if this functionality needs to be retained } catch (error) { gfg.utility.debugConsole(error); } }, gfgBogoChangeLanguageConfigs: function () { try{ if(gfg.settings.languageData){ let locale = gfg.utility.getLocale(); if(gfg.settings.languageData && gfg.settings.languageData.languageMode == "SINGLE"){ return; } if(!gfg.settings.languageData[locale]){ return; } gfg.settings.boGoFeature[0].textConfig = gfg.settings.languageData[locale].bogoFeature.textConfig; } }catch(error){ gfg.utility.debugConsole("error inside gfgBogoChangeLanguageConfigs", error) } }, gfgGetBogoFeatureoData: async function(productPageHandle, productPageId){ try{ if(gfg?.gfgBogoFeature?.state?.bogoProductsShopifyData.length > 0){ return; } // let cartData = await gfg.utility.getCart(); // get filtered cartData from cartData // gfg.gfgBogoFeature.state.cartData = await gfg.gfgBogoFeature.f.getCartData() //check in session storage let gfgBogoProductsShopifyDataFromSessionStorage = sessionStorage.getItem("gfgBogoProductsShopifyData") let gfgBogoProductsShopifyDataFromSessionStorageByHandle; let gfgBogoGetProductsShopifyDataFromSessionStorageByHandle let activeProductHandle = productPageHandle; let activeProductId = productPageId; let activeBogoIndex = gfg.gfgBogoFeature.f.getActiveBogoIndex(activeProductHandle); // if(gfgBogoProductsShopifyDataFromSessionStorage && gfgBogoProductsShopifyDataFromSessionStorage.length > 0){ // gfgBogoProductsShopifyDataFromSessionStorageByHandle = gfg.utility.convertArrayToObject(JSON.parse(gfgBogoProductsShopifyDataFromSessionStorage), "handle") // } // let counterForHandlesPickedFromSessionStorage = 0; let productHandleArray = []; let productGetArray = []; let rules = gfg.settings.boGoFeature[activeBogoIndex].rules; let bogoBuyProductsDataHandleArray = []; let bogoBuyProductsShopifyData = []; let bogoProductCustomerGetsShopifyDataArray = []; for(let i=0; i< rules.length; i++){ // let { // bogoBuyProductsShopifyDataByHandles, // tempBogoBuyProductsShopifyData, // activeProductHandleArray // } = await gfg.gfgBogoFeature.f.gfgBogoPrepareDataForCustomerBuys(rules[i], activeProductHandle); // let { // currentProductGetArray, // tempBogoGetProductsShopifyData, // } = await gfg.gfgBogoFeature.f.gfgBogoPrepareDataForCustomerGets(rules[i], activeProductHandleArray, i, activeBogoIndex); let [customerBuysData , customerGetsData] = await Promise.all( [ gfg.gfgBogoFeature.f.gfgBogoPrepareDataForCustomerBuys(rules[i], activeProductHandle) , await gfg.gfgBogoFeature.f.gfgBogoPrepareDataForCustomerGets(rules[i], activeProductHandle , i, activeBogoIndex, activeProductId) ] ); let { bogoBuyProductsShopifyDataByHandles , tempBogoBuyProductsShopifyData , activeProductHandleArray } = customerBuysData; let { currentProductGetArray , tempBogoGetProductsShopifyData } = customerGetsData; productHandleArray = [...productHandleArray, ...activeProductHandleArray]; productGetArray = [...productGetArray, ...currentProductGetArray]; bogoProductCustomerGetsShopifyDataArray.push(tempBogoGetProductsShopifyData); bogoBuyProductsShopifyData.push(tempBogoBuyProductsShopifyData); bogoBuyProductsDataHandleArray.push(bogoBuyProductsShopifyDataByHandles); } gfg.gfgBogoFeature.state.gfgBogoProductsShopifyDataByHandles = bogoBuyProductsDataHandleArray; gfg.gfgBogoFeature.state.bogoProductsShopifyData = bogoBuyProductsShopifyData; gfg.gfgBogoFeature.state.bogoProductCustomerGetsShopifyData = bogoProductCustomerGetsShopifyDataArray; sessionStorage.setItem("gfgBogoProductsShopifyData", JSON.stringify(gfg.gfgBogoFeature.state.bogoProductsShopifyData)) }catch(error){ gfg.utility.debugConsole("error in function gfgGetBogoFeatureoData", error) } }, gfgBogoPrepareDataForCustomerBuys: async function(rule, activeProductHandle){ try{ const storeFrontAccessToken = gfg?.settings?.merchantInfo?.storefrontAccessToken; let productPageId = gfg.state.productPageId; if(!productPageId){ productPageId = gfg.f.getProductPageId(); gfg.state.productPageId = productPageId; } let currentProductHandleArray = []; let customerBuysData = rule.customerBuysData; let productArray = customerBuysData.products; let collectionsArray = customerBuysData.collectionsData; for(j = 0; j< productArray.length; j++){ let handle = productArray[j].handle; let productId = productArray[j].productId; currentProductHandleArray.push({handle , productId}); } for(j = 0; j< collectionsArray.length; j++){ for(k = 0; k< collectionsArray[j].productList.length; k++){ let handle = collectionsArray[j].productList[k].handle; let productId = collectionsArray[j].productList[k].productId; currentProductHandleArray.push({handle , productId}); } } let isCurrentProductHandlePresent = currentProductHandleArray.some(obj => obj.handle == activeProductHandle); let isCurrentProductIdPresent = currentProductHandleArray.some(obj => obj.productId == productPageId); if(!isCurrentProductHandlePresent && !isCurrentProductIdPresent){ return; } let activeProductHandleArray = [activeProductHandle] const activeProductIdsArray = [productPageId] let tempBogoBuyProductsShopifyData = []; if(storeFrontAccessToken){ const activeProductGids = activeProductIdsArray.map((productId)=>`gid://shopify/Product/${productId}`); const productsData = await gfg.customDiscountStorefrontApis.getProductsDataByIdWithAjaxResponse(activeProductGids); tempBogoBuyProductsShopifyData = productsData; } else{ const promises = activeProductHandleArray.map(async (activeProductHandle) => { // check if freeGiftsShopifyDataFromSessionStorageByHandle[handle] is there or not // if(gfgBogoProductsShopifyDataFromSessionStorageByHandle && gfgBogoProductsShopifyDataFromSessionStorageByHandle[activeProductHandle]){ // // counterForHandlesPickedFromSessionStorage++; // return gfgBogoProductsShopifyDataFromSessionStorageByHandle[activeProductHandle] // }else{ const productData = gfg.utility.getProductDataV2(activeProductHandle) return productData; // } }); tempBogoBuyProductsShopifyData = await Promise.all(promises); } // to remove out of stock products -> filter out false values tempBogoBuyProductsShopifyData = tempBogoBuyProductsShopifyData.filter(value => value !== false); // filter out for the variants that are present in rules let bogoShopifyData = gfg.gfgBogoFeature.f.gfgBogoFilterForActiveVariants(tempBogoBuyProductsShopifyData, rule.customerBuysData.products); tempBogoBuyProductsShopifyData = bogoShopifyData; let bogoProductsShopifyData = JSON.parse(JSON.stringify(tempBogoBuyProductsShopifyData)) // convert array to an object with the key as handle-name let bogoBuyProductsShopifyDataByHandles = gfg.utility.convertArrayToObject(bogoProductsShopifyData, "handle"); // convert to an object with key as variant id let currentCustomerBuysVariantIdMap = gfg.utility.createMapForVariantId(bogoBuyProductsShopifyDataByHandles) let customerBuysVariantIdMap = gfg.gfgBogoFeature.state.gfgBogoProductsShopifyDataByVariantIds; gfg.gfgBogoFeature.state.gfgBogoProductsShopifyDataByVariantIds = gfg.utility.combineObjects(currentCustomerBuysVariantIdMap, customerBuysVariantIdMap); return { bogoBuyProductsShopifyDataByHandles, tempBogoBuyProductsShopifyData, activeProductHandleArray } }catch(error){ gfg.utility.debugConsole("error in function gfgBogoPrepareDataForCustomerBuys", error) } }, gfgBogoPrepareDataForCustomerGets:async function(rule, activeProductHandle, ruleCounter, activeBogoIndex, activeProductId){ try{ const storeFrontAccessToken = gfg?.settings?.merchantInfo?.storefrontAccessToken; let customerBuysData = rule.customerBuysData; let activeProductHandleArray = [activeProductHandle] const activeProductIdsArray = [activeProductId] let productArray = customerBuysData.products; let bogoRule = rule.bogoRule; let productArrayGets = rule.customerGets let collectionsArray = customerBuysData.collectionsData; let productGetArray = []; let productGetIdsArray = []; let tempBogoGetProductsShopifyData = []; if(bogoRule == "BUY_X_GET_Y"){ for(j = 0; j< productArrayGets.length; j++){ let handle = rule.customerGets[j].product.handle; const productId = rule.customerGets[j].product.productId; productGetArray.push(handle); productGetIdsArray.push(productId); } }else{ gfg.settings.boGoFeature[activeBogoIndex].rules[ruleCounter].customerGets[0].product = gfg.settings.boGoFeature[activeBogoIndex].rules[ruleCounter].customerBuysData.products; productGetArray = activeProductHandleArray; productGetIdsArray = activeProductIdsArray; } if(storeFrontAccessToken){ const productGetGids = productGetIdsArray.map((productId)=>`gid://shopify/Product/${productId}`); const productsData = await gfg.customDiscountStorefrontApis.getProductsDataByIdWithAjaxResponse(productGetGids); tempBogoGetProductsShopifyData = productsData; } else{ const promisesForGetProducts = productGetArray.map(async (handle) => { const productData = gfg.utility.getProductDataV2(handle) return productData; // } }); tempBogoGetProductsShopifyData = await Promise.all(promisesForGetProducts) } // to remove out of stock products -> filter out false values tempBogoGetProductsShopifyData = tempBogoGetProductsShopifyData.filter(value => value !== false); // filter out the variants that are present in rules let customerBogoData = gfg.gfgBogoFeature.f.gfgBogoFilterForActiveVariantsForCustomerGets(tempBogoGetProductsShopifyData, rule.customerGets[0].product, bogoRule); tempBogoGetProductsShopifyData = customerBogoData; let bogoProductCustomerGetsShopifyData = JSON.parse(JSON.stringify(tempBogoGetProductsShopifyData)) // convert array to an object with the key as handle-name let gfgBogoProductsCustomerGetsShopifyDataByHandles = gfg.utility.convertArrayToObject(bogoProductCustomerGetsShopifyData, "handle") // convert to an object with key as variant id let currentCustomerGetsVariantIdMap = gfg.utility.createMapForVariantId(gfgBogoProductsCustomerGetsShopifyDataByHandles); let customerGetsVariantIdMap = gfg.gfgBogoFeature.state.gfgBogoProductsCustomerGetsShopifyDataByVariantIds; gfg.gfgBogoFeature.state.gfgBogoProductsCustomerGetsShopifyDataByVariantIds = gfg.utility.combineObjects(currentCustomerGetsVariantIdMap, customerGetsVariantIdMap); return { currentProductGetArray: productGetArray, tempBogoGetProductsShopifyData } }catch(error){ gfg.utility.debugConsole("error in function gfgBogoPrepareDataForCustomerGets", error) } }, gfgBogoFilterForActiveVariants: function(shopifyData, rulesData){ //only filtering products not collections, since collection products have all variants try{ const bogoProductsShopifyData = shopifyData; const customerBuysData = rulesData; let filteredProducts = []; // Create a Set of variant IDs from customerBuysData for efficient lookup for(let i = 0; i < bogoProductsShopifyData.length; i++) { let product = bogoProductsShopifyData[i]; // select variantType for finding if product originally has multiple variants or not if(product.variants.length > 1){ product.variantType = "MULTIPLE"; }else{ product.variantType = "SINGLE"; } let equivalentProduct = customerBuysData.find(p => p.productId == product.id); if(equivalentProduct){ for(let j = 0; j < product.variants.length; j++) { let variant = product.variants[j]; let variantId = variant.id; // check if given variant with variant id exists in equivalentProduct let equivalentVariant = equivalentProduct.variants.find(v => v.variantId == variantId); if(!equivalentVariant) { product.variants.splice(j, 1); j--; } } } filteredProducts.push(product); } return filteredProducts; }catch(error){ gfg.utility.debugConsole("error in function gfgBogoFilterForActiveVariants", error); } }, gfgBogoFilterForActiveVariantsForCustomerGets: function(shopifyData, rulesData, bogoRule){ try{ if(bogoRule == "BUY_X_GET_Y"){ const bogoProductsShopifyData = shopifyData; const productData = rulesData; let filteredProducts = []; for(let i=0; i< bogoProductsShopifyData.length; i++){ let product = bogoProductsShopifyData[i]; // select variantType for finding if product originally has multiple variants or not if(product.variants.length > 1){ product.variantType = "MULTIPLE"; }else{ product.variantType = "SINGLE"; } for(let j=0; j< product.variants.length; j++){ let variant = product.variants[j]; let equivalentVariant = productData.variants.find(v => v.variantId == variant.id); if(!equivalentVariant){ product.variants.splice(j, 1); j--; } } filteredProducts.push(product); } return filteredProducts }else{ return gfg.gfgBogoFeature.f.gfgBogoFilterForActiveVariants(shopifyData, rulesData) } }catch(error){ gfg.utility.debugConsole("error in function gfgBogoFilterForActiveVariantsForCustomerGets", error); } }, gfgCheckIfProductValidForBogo:function(productPageHandle){ // check if productPageHandle is present gfgBogoProductsShopifyDataByHandles // if present then return true try{ let activeBogoIndex = gfg.gfgBogoFeature.state.activeBogoIndex; let isHandlePresent = false let gfgBogoProductsShopifyDataByHandles = gfg.gfgBogoFeature.state.gfgBogoProductsShopifyDataByHandles; let rules = gfg.settings.boGoFeature[activeBogoIndex].rules; for(let i=0; i< gfgBogoProductsShopifyDataByHandles.length; i++){ let activeRule = rules[i]; let bogoProductsOfRule = gfgBogoProductsShopifyDataByHandles[i]; isHandlePresent = Object.keys(bogoProductsOfRule).includes(productPageHandle); if (isHandlePresent) { gfg.utility.debugConsole(`The handle '${productPageHandle}' is present.`); let product = bogoProductsOfRule[productPageHandle]; product.rule = activeRule; product.ruleIndex = i; return product; } else { gfg.utility.debugConsole(`The handle '${productPageHandle}' is not present.`); } } return isHandlePresent; }catch(error){ gfg.utility.debugConsole("error in gfgCheckIfProductValidForBogo", error) } }, checkIfBogoProductPresentOfGivenRule: function(items, bogoProducts){ // search in items, for item with properties _bogo_product: true try{ let matchingItems = []; const bogoProductsInCartOnly = items.filter(item => item.properties && item.properties._bogo_product == "true"); gfg.utility.debugConsole("bogoProductsInCartOnly", bogoProductsInCartOnly); bogoProductsInCartOnly.forEach(item => { bogoProducts.forEach(cond => { cond.variants.forEach(variant => { if (variant.variantId == item.variant_id && item.quantity >= cond.quantity) { matchingItems.push({ item, quantity: item.quantity, availedCount: parseInt(item.quantity / cond.quantity) }); } }); }); }); return matchingItems; }catch(error){ gfg.utility.debugConsole("error in checkIfBogoProductPresentOfGivenRule", error) } }, getActiveBogoIndex: function(activeProductHandle){ try { let bogoArray = gfg.settings.boGoFeature; let productPageId = gfg.state.productPageId; if(!productPageId){ productPageId = gfg.f.getProductPageId(); gfg.state.productPageId = productPageId; } for(let i=0; i obj.handle == activeProductHandle); let isCurrentProductIdPresent = currentProductHandleArray.some(obj => obj.productId == productPageId); if(isCurrentProductHandlePresent || isCurrentProductIdPresent){ gfg.gfgBogoFeature.state.activeBogoIndex = i; return i; } } } return -1; } catch (err) { gfg.utility.debugConsole("err inside getActiveBogo:", err); } }, gfgAddBogoProductToCart: async function(productObject){ try{ let items = []; let currentCartItems = gfg.state.gfgFreeGiftCartData.items; //just check that the freeGiftInCart is in stock or notl let isCurrentVariantInStock = gfg.gfgBogoFeature.state.gfgBogoProductsCustomerGetsShopifyDataByVariantIds && gfg.gfgBogoFeature.state.gfgBogoProductsCustomerGetsShopifyDataByVariantIds[productObject.product.variant_id]?.available || false; if (!isCurrentVariantInStock) { return false } let BogoProductInCart = currentCartItems.filter((product) => { // do it based on variant Id return product.variant_id == productObject.product.variantId }) if (BogoProductInCart.length > 0) { for (let i = 0; i < BogoProductInCart.length; i++) { let BogoProductInCartLineItemKey = BogoProductInCart[i].key; let currentQuantity = BogoProductInCart[i].quantity; let items = { id: BogoProductInCartLineItemKey, }; // use changeCart let bogoProductData = await gfg.utility.changeCart(items); //add the same product again but with quantity 1 // and no properties items = [] items.push({ id: productObject.product.variantId, quantity: currentQuantity }) bogoProductData = await gfg.utility.addToCartV2({ items: items }) if (bogoProductData) { gfg.gfgBogoFeature.state.isCartUpdatedByUs = true; } else { return false; // If any update fails, return false } } return true; // If all updates succeed, return true } else { items.push({ id: productObject.product.variant_id, quantity: productObject.quantity || 1, }) let bogoProductData = await gfg.utility.addToCartV2({ items: items }) if (bogoProductData) { gfg.gfgBogoFeature.state.isCartUpdatedByUs = true return true } return false } }catch(error){ gfg.utility.debugConsole("gfgAddBogoProductToCart", error) return false; } }, gfgBogoFeaturePrepareUI: function (productObject) { try { const activeBogoIndex = gfg.gfgBogoFeature.state.activeBogoIndex; const configs = gfg.settings.boGoFeature[activeBogoIndex].configuration; const gfgBogoContainer = document.createElement("div"); gfgBogoContainer.classList.add("gfgBogoContainer"); gfgBogoContainer.style.borderColor = configs.borderColor || "#CDCDCD"; gfgBogoContainer.style.color = configs.fontColor || "#000000"; gfgBogoContainer.style.backgroundColor = configs.bgColor || "#FFFFFF"; const gfgBogoTitleContainer = gfg.gfgBogoFeature.f.gfgBogoFeaturePrepareUITitle(); const gfgStackedUI = gfg.gfgBogoFeature.f.gfgBogoFeaturePrepareStackedUI(productObject); const notificationMessage = gfg.gfgBogoFeature.f.gfgBogoPrepareNotificationUI(); gfgBogoContainer.appendChild(gfgBogoTitleContainer); gfgBogoContainer.appendChild(gfgStackedUI); gfgBogoContainer.appendChild(notificationMessage); return gfgBogoContainer; } catch (error) { gfg.utility.debugConsole("error in gfgBogoFeaturePrepareUI", error); } }, checkIfBogoCampaignScheduleIsActive: function(){ try { // use campaignScheduleData object of free gift and check if it is active or not let activeBogoIndex = gfg.gfgBogoFeature.state.activeBogoIndex; let campaignScheduleData = gfg.settings.boGoFeature[activeBogoIndex].campaignScheduleData; if(!campaignScheduleData){ return true } if (campaignScheduleData?.campaignSchedule != "SCHEDULED"){ return true } if(campaignScheduleData?.campaignSchedule == "SCHEDULED"){ let currentDateUTC = new Date().toISOString(); let startDateTime_UTC = campaignScheduleData.startDateTime_UTC; let endDateTime_UTC = campaignScheduleData.endDateTime_UTC; if (currentDateUTC >= startDateTime_UTC && currentDateUTC <= endDateTime_UTC) { gfg.utility.debugConsole('Campaign is active'); return true; } else { gfg.utility.debugConsole('Campaign is not active'); return false; } } return true; } catch (err) { gfg.utility.debugError("checkIfBogoCampaignScheduleIsActive", err) return true; } }, gfgBogoPrepareNotificationUI: function () { try { const notificationMessageContainer = document.createElement("div"); notificationMessageContainer.classList.add("gfgBogoNotificationMessageContainerUI"); const notificationMessage = document.createElement("div"); notificationMessage.classList.add("gfgBogoNotificationMessage"); notificationMessageContainer.appendChild(notificationMessage); notificationMessageContainer.classList.add("gfgNotificationInactive"); return notificationMessageContainer; } catch (error) { gfg.utility.debugConsole("error in gfgBogoPrepareNotificationUI", error); } }, gfgBogoCreateNotificationMessage: function (message) { try { const notificationMessage = document.querySelector(".gfgBogoNotificationMessageContainerUI"); const notifTextDiv = document.querySelector(".gfgBogoNotificationMessage"); if (notifTextDiv && notificationMessage) { notifTextDiv.textContent = message; notificationMessage.classList.add("gfgBogoNotificationMessageContainer"); notificationMessage.classList.add("gfgNotificationActive"); notificationMessage.classList.remove("gfgNotificationInactive"); } } catch (error) { gfg.utility.debugConsole("Error in gfgBogoCreateNotificationMessage:", error); } }, gfgBogoFeaturePrepareUITitle: function () { let activeBogoIndex = gfg.gfgBogoFeature.state.activeBogoIndex; const titleConfigs = gfg.settings.boGoFeature[activeBogoIndex].textConfig?.title || "Buy More Get More"; const colorConfigs = gfg.settings.boGoFeature[activeBogoIndex]?.configuration?.titleBgColor || "#2C2A41"; try { const gfgBogoTitleContainer = document.createElement("div"); gfgBogoTitleContainer.classList.add("gfgBogoTitleContainer"); gfgBogoTitleContainer.style.backgroundColor = colorConfigs; const gfgBogoTitle = document.createElement("div"); gfgBogoTitle.classList.add("gfgBogoTitle"); const gfgBogoTitleHeader = document.createElement("div"); gfgBogoTitleHeader.classList.add("gfgBogoTitleHeader"); gfgBogoTitleHeader.innerHTML = titleConfigs; gfgBogoTitle.appendChild(gfgBogoTitleHeader); gfgBogoTitleContainer.appendChild(gfgBogoTitle); return gfgBogoTitleContainer; } catch (error) { gfg.utility.debugConsole("error in gfgBogoFeaturePrepareUITitle", error); } }, gfgBogoFeaturePrepareStackedUI: function (productObject) { try { const rule = productObject?.rule; const activeBogoIndex = gfg.gfgBogoFeature.state.activeBogoIndex; const textConfigs = gfg.settings.boGoFeature[activeBogoIndex].textConfig; const colorConfigs = gfg.settings.boGoFeature[activeBogoIndex].configuration?.claimBtnBgColor || "#2C2A41"; const availText = textConfigs?.claimButtonText || "Click To Avail"; const gfgBogoFeatureStackContainer = document.createElement("div"); gfgBogoFeatureStackContainer.classList.add("gfgBogoFeatureStackContainer"); const gfgBogoCustomerBuysContainer = gfg.gfgBogoFeature.f.gfgBogoFeaturePrepareUIBuyProductSection(productObject); const gfgBogoCustomerGetsContainer = gfg.gfgBogoFeature.f.gfgBogoFeaturePrepareUICustomerGetsSection(productObject); const gfgButtonActionsContainer = document.createElement("div"); gfgButtonActionsContainer.classList.add("gfgButtonActionsContainer"); const gfgBogoActionButton = document.createElement("div"); gfgBogoActionButton.classList.add("gfgBogoActionButton", "validActionButton"); gfgBogoActionButton.textContent = availText; gfgBogoActionButton.style.backgroundColor = colorConfigs; const additionalNote = document.createElement("div"); additionalNote.classList.add("gfgBogoAdditionalNote"); const additionalNoteText = "Note: You can avail discount on the same variant as the one that you buy."; additionalNote.textContent = additionalNoteText; gfgButtonActionsContainer.appendChild(gfgBogoActionButton); if ( rule?.bogoRule === "BUY_X_GET_X" && rule?.customerBuysData?.isCustomerBuyProductsVariantSelectionEnabled ) { gfgButtonActionsContainer.appendChild(additionalNote); } gfgBogoFeatureStackContainer.appendChild(gfgBogoCustomerBuysContainer); gfgBogoFeatureStackContainer.appendChild(gfgBogoCustomerGetsContainer); gfgBogoFeatureStackContainer.appendChild(gfgButtonActionsContainer); return gfgBogoFeatureStackContainer; } catch (error) { gfg.utility.debugConsole("error in gfgBogoFeaturePrepareStackedUI", error); } }, gfgBogoFeaturePrepareUIBuyProductSection: function (productObject) { try { const rule = productObject.rule; const gfgBogoBuyProductContainer = document.createElement("div"); gfgBogoBuyProductContainer.classList.add("gfgBogoFeaturePrepareUICustomerBuysSection"); const gfgProductCard = gfg.gfgBogoFeature.f.gfgBogoFeatureBuyProductCardPrepareUI( productObject, rule.customerBuysData.qty ); gfgBogoBuyProductContainer.appendChild(gfgProductCard); return gfgBogoBuyProductContainer; } catch (error) { gfg.utility.debugConsole("error in gfgBogoFeaturePrepareUIBuyProductSection", error); } }, gfgBogoFeatureCreateOperatorForCard: function (operatorText) { try { let operatorTextSrc = "https://d1cjetlwgplgi5.cloudfront.net/public/%2B.svg"; let gfgBogoFeatureCreateConditionForCardContainer = document.createElement("div"); gfgBogoFeatureCreateConditionForCardContainer.classList.add("gfgBogoFeatureCreateOperatorForCard"); let gfgBogoFeatureCreateLine = document.createElement("div"); gfgBogoFeatureCreateLine.classList.add("gfgBogoFeatureCreateLine"); let gfgBogoFeatureCreateCapsule = document.createElement("div"); gfgBogoFeatureCreateCapsule.classList.add("gfgBogoFeatureCreateCapsule"); let gfgBogoFeatureCreateCapsuleContentContainer = document.createElement("div"); gfgBogoFeatureCreateCapsuleContentContainer.classList.add("gfgBogoFeatureCreateCapsuleContentContainer"); let gfgBogoFeatureCreateCapsuleContent = document.createElement("img"); gfgBogoFeatureCreateCapsuleContent.classList.add("gfgBogoFeatureCreateCapsuleContent"); gfgBogoFeatureCreateCapsuleContent.setAttribute("src", operatorTextSrc); gfgBogoFeatureCreateCapsuleContentContainer.appendChild(gfgBogoFeatureCreateCapsuleContent); gfgBogoFeatureCreateCapsule.appendChild(gfgBogoFeatureCreateCapsuleContentContainer); gfgBogoFeatureCreateLine.appendChild(gfgBogoFeatureCreateCapsule); gfgBogoFeatureCreateConditionForCardContainer.appendChild(gfgBogoFeatureCreateLine); return gfgBogoFeatureCreateConditionForCardContainer; } catch (error) { gfg.utility.debugConsole("error in gfgBogoFeatureCreateOperatorForCard", error); } }, gfgBogoFeatureBuyProductCardPrepareUI: function (productData, quantity) { try { const activeBogoIndex = gfg.gfgBogoFeature.state.activeBogoIndex; const pillText = gfg.settings?.boGoFeature[activeBogoIndex]?.textConfig?.pillText || quantity; const textConfig = gfg.settings.boGoFeature[activeBogoIndex].textConfig; const imagePath = productData.images.length === 0 ? 'https://d1cjetlwgplgi5.cloudfront.net/public/freeGiftDymmyImage.png' : productData.images[0]; const gfgBuyProductCardContainer = document.createElement("div"); gfgBuyProductCardContainer.classList.add("gfgBuyProductCardContainer"); const gfgProductImageContainer = document.createElement("div"); gfgProductImageContainer.classList.add("gfgProductImageContainer"); const gfgProductImage = document.createElement("img"); gfgProductImage.classList.add("gfgProductImage"); gfgProductImage.setAttribute("src", imagePath); gfgProductImageContainer.appendChild(gfgProductImage); const gfgBuyProductDetailSectionContainer = document.createElement("div"); gfgBuyProductDetailSectionContainer.classList.add("gfgBuyProductDetailSectionContainer"); const gfgBuyProductHeader = document.createElement("div"); gfgBuyProductHeader.classList.add("gfgBuyProductHeader"); gfgBuyProductHeader.textContent = productData.title; const gfgBuyProductVariantContainer = document.createElement("div"); gfgBuyProductVariantContainer.classList.add("gfgBuyProductVariantContainer"); const gfgBuyProductVariantHeader = document.createElement("div"); gfgBuyProductVariantHeader.classList.add("gfgBuyProductVariantHeader"); const gfgBuyProductVariantSelect = document.createElement("select"); gfgBuyProductVariantSelect.classList.add("gfgBuyProductVariantSelect"); productData.variants.forEach((variant) => { if (variant.available === true) { const price = variant.price / 100; const gfgBuyProductVariantOption = document.createElement("option"); gfgBuyProductVariantOption.classList.add("gfgBuyProductVariantOption"); gfgBuyProductVariantOption.textContent = variant?.public_title || variant?.title; gfgBuyProductVariantOption.setAttribute("value", price); gfgBuyProductVariantOption.setAttribute("data-variant-id", variant.variant_id); gfgBuyProductVariantOption.setAttribute("data-count", quantity); gfgBuyProductVariantSelect.appendChild(gfgBuyProductVariantOption); } }); if (productData.variantType === "SINGLE") { gfgBuyProductVariantContainer.classList.add("gfgVariantContainerHidden"); } gfgBuyProductVariantHeader.appendChild(gfgBuyProductVariantSelect); gfgBuyProductVariantContainer.appendChild(gfgBuyProductVariantHeader); gfgBuyProductDetailSectionContainer.append(gfgBuyProductHeader, gfgBuyProductVariantContainer); const gfgBuyProductPriceContainer = document.createElement("div"); gfgBuyProductPriceContainer.classList.add("gfgBuyProductPriceContainer"); const gfgBuyProductPriceContainerBox = document.createElement("div"); gfgBuyProductPriceContainerBox.classList.add("gfgBuyProductPriceContainerBox"); const currencySymbol = gfg.utility.getCurrencySymbol(); let price = productData.variants[0].price / 100; let productPrice = `${currencySymbol}${price.toFixed(2)}`; if (gfg.state?.formatPriceViaCustomScript) { const formattedPrice = gfg.utility.formatPriceWithSeparator(price * 100); productPrice = `${currencySymbol}${formattedPrice}`; } const gfgBuyProductPriceContainerBoxDiscountedPrice = document.createElement("div"); gfgBuyProductPriceContainerBoxDiscountedPrice.classList.add("gfgBuyProductPriceContainerBoxDiscountedPrice"); gfgBuyProductPriceContainerBoxDiscountedPrice.textContent = productPrice; gfgBuyProductPriceContainerBox.appendChild(gfgBuyProductPriceContainerBoxDiscountedPrice); gfgBuyProductPriceContainer.appendChild(gfgBuyProductPriceContainerBox); const gfgBuyProductQuantityCapsule = gfg.gfgBogoFeature.f.gfgRenderBuyProductTextPill(pillText); gfgBuyProductPriceContainer.appendChild(gfgBuyProductQuantityCapsule); gfgBuyProductDetailSectionContainer.appendChild(gfgBuyProductPriceContainer); const gfgBuyProductAddToCartButtonContainer = document.createElement("div"); gfgBuyProductAddToCartButtonContainer.classList.add("gfgBuyProductAddToCartButtonContainer"); const gfgBuyProductAddToCartButton = document.createElement("div"); gfgBuyProductAddToCartButton.classList.add("gfgBuyProductAddToCartButton"); gfgBuyProductAddToCartButton.textContent = textConfig.addText; gfgBuyProductAddToCartButtonContainer.appendChild(gfgBuyProductAddToCartButton); gfgBuyProductCardContainer.appendChild(gfgProductImageContainer); gfgBuyProductCardContainer.appendChild(gfgBuyProductDetailSectionContainer); return gfgBuyProductCardContainer; } catch (error) { gfg.utility.debugConsole("error in gfgBogoFeatureBuyProductCardPrepareUI", error); } }, gfgRenderBuyProductTextPill: function (quantity) { try { const gfgBuyProductTextPillContainer = document.createElement("div"); gfgBuyProductTextPillContainer.classList.add("gfgBuyProductTextPillContainer"); const gfgBuyProductTextPillText = document.createElement("div"); gfgBuyProductTextPillText.classList.add("gfgBuyProductTextPillText"); gfgBuyProductTextPillText.textContent = `Qty ${quantity} `; gfgBuyProductTextPillContainer.appendChild(gfgBuyProductTextPillText); return gfgBuyProductTextPillContainer; } catch (error) { gfg.utility.debugConsole("error in gfgRenderBuyProductTextPill", error); } }, triggerUpdateActivities: function(){ try{ const redirectToCart = gfg.settings.app.redirectToCartAfterBogoAddition; const redirectToCheckout = gfg.settings.app.redirectToCheckoutAfterBogoAddition; const redirectTo = redirectToCart ? '/cart' : redirectToCheckout ? '/checkout': null; // if custom script is written then it will excute that, no redirection will happen. if (gfg.settings.app.executeCustomScriptAfterBogoAddition) { eval(gfg.settings.app.executeCustomScriptAfterBogoAddition); } else if(redirectTo) { gfg.utility.redirectToPage(redirectTo); } }catch(error){ gfg.utility.debugConsole("error in triggerUpdateActivities", error); } }, gfgBogoFeaturePrepareUICustomerGetsSection: function (productObject) { try { const rule = productObject.rule; const customerGets = productObject.rule.customerGets; const activeBogoIndex = gfg.gfgBogoFeature.state.activeBogoIndex; const textConfig = gfg.settings.boGoFeature[activeBogoIndex].textConfig; const operatorText = textConfig?.bogoGetOperatorText || "+"; const gfgBogoFeaturePrepareUICustomerGetsSection = document.createElement("div"); gfgBogoFeaturePrepareUICustomerGetsSection.classList.add("gfgBogoFeaturePrepareUICustomerGetsSection"); customerGets.forEach((customerGet) => { const gfgRenderCustomerGetsProductCardPrepareUI = gfg.gfgBogoFeature.f.gfgRenderCustomerGetsProductCardPrepareUI( customerGet, rule.bogoRule, productObject ); const gfgBogoFeaturePrepareUICustomerGetsSectionDivider = gfg.gfgBogoFeature.f.gfgBogoFeatureCreateOperatorForCard(operatorText); gfgBogoFeaturePrepareUICustomerGetsSection.appendChild(gfgBogoFeaturePrepareUICustomerGetsSectionDivider); gfgBogoFeaturePrepareUICustomerGetsSection.appendChild(gfgRenderCustomerGetsProductCardPrepareUI); }); return gfgBogoFeaturePrepareUICustomerGetsSection; } catch (error) { gfg.utility.debugConsole("error in gfgBogoFeaturePrepareUICustomerGetsSection", error); } }, gfgRenderCustomerGetsProductCardPrepareUI: function (data, bogoRule, productObject) { try { let activeBogoIndex = gfg.gfgBogoFeature.state.activeBogoIndex; let pillText = gfg.settings?.boGoFeature[activeBogoIndex]?.textConfig?.pillText || data.qty; let productData = data.product; let bogoProductCustomerGetsShopifyData = gfg.gfgBogoFeature.state.bogoProductCustomerGetsShopifyData; bogoProductCustomerGetsShopifyData = bogoProductCustomerGetsShopifyData[productObject.ruleIndex]; let product = bogoProductCustomerGetsShopifyData.find( (product) => product.handle === productData.handle || product.id === productData.productId ); if (bogoRule === "BUY_X_GET_X") { product = productObject; } let quantity = data.qty; let discountValue = parseFloat(data.discountValue); let discountType = data.discountType; let currencySymbol = gfg.utility.getCurrencySymbol(); let gfgRenderCustomerGetsProductCardPrepareUI = document.createElement("div"); gfgRenderCustomerGetsProductCardPrepareUI.classList.add("gfgRenderCustomerGetsProductCardPrepareUI"); let gfgProductImageContainer = document.createElement("div"); gfgProductImageContainer.classList.add("gfgProductImageContainer"); let gfgProductImage = document.createElement("img"); gfgProductImage.classList.add("gfgProductImage"); gfgProductImage.setAttribute("src", product.images[0] || ""); gfgProductImageContainer.appendChild(gfgProductImage); let gfgCustomerGetsProductContent = document.createElement("div"); gfgCustomerGetsProductContent.classList.add("gfgCustomerGetsProductContent"); let gfgCustomerGetsProductTitleContainer = document.createElement("div"); gfgCustomerGetsProductTitleContainer.classList.add("gfgCustomerGetsProductTitleContainer"); gfgCustomerGetsProductTitleContainer.textContent = product.title; gfgCustomerGetsProductContent.appendChild(gfgCustomerGetsProductTitleContainer); let gfgBuyProductVariantContainer = document.createElement("div"); gfgBuyProductVariantContainer.classList.add("gfgCustomerGetsVariantContainer"); let gfgBuyProductVariantHeader = document.createElement("div"); gfgBuyProductVariantHeader.classList.add("gfgBuyProductVariantHeader"); let gfgBuyProductVariantSelect = document.createElement("select"); gfgBuyProductVariantSelect.classList.add("gfgBuyProductVariantSelectForCustomerGets"); product.variants.forEach((variant) => { if (variant.available === true) { let price = variant.price / 100; let gfgBuyProductVariantOption = document.createElement("option"); gfgBuyProductVariantOption.classList.add("gfgBuyProductVariantOption"); gfgBuyProductVariantOption.textContent = variant.title; gfgBuyProductVariantOption.value = price; // gfgBuyProductVariantOption.setAttribute("data-variantid", variant.variantId); gfgBuyProductVariantOption.setAttribute("data-variant-id", variant.id); gfgBuyProductVariantOption.setAttribute("data-count", quantity); if (discountType === "PERCENTAGE") { let discountedPriceOfProduct = price - (price * discountValue) / 100; if (gfg.state?.formatPriceViaCustomScript) { discountedPriceOfProduct = currencySymbol + gfg.utility.formatPriceWithSeparator(discountedPriceOfProduct * 100); } else { discountedPriceOfProduct = currencySymbol + discountedPriceOfProduct.toFixed(2); } gfgBuyProductVariantOption.setAttribute("data-discounted-price", discountedPriceOfProduct); } else if (discountType === "AMOUNT") { let discountedPriceOfProduct = price - discountValue; if (gfg.state?.formatPriceViaCustomScript) { discountedPriceOfProduct = currencySymbol + gfg.utility.formatPriceWithSeparator(discountedPriceOfProduct * 100); } else { discountedPriceOfProduct = currencySymbol + discountedPriceOfProduct.toFixed(2); } gfgBuyProductVariantOption.setAttribute("data-discounted-price", discountedPriceOfProduct); } gfgBuyProductVariantSelect.appendChild(gfgBuyProductVariantOption); } }); if (product.variantType === "SINGLE") { gfgBuyProductVariantContainer.classList.add("gfgVariantContainerHidden"); } gfgBuyProductVariantHeader.appendChild(gfgBuyProductVariantSelect); gfgBuyProductVariantContainer.appendChild(gfgBuyProductVariantHeader); let gfgBuyProductPriceContainer = document.createElement("div"); gfgBuyProductPriceContainer.classList.add("gfgBuyProductPriceContainerForCustomerGets"); let gfgBuyProductPriceContainerBox = document.createElement("div"); gfgBuyProductPriceContainerBox.classList.add("gfgBuyProductPriceContainerBox"); let gfgBogoGetProductsPillText = gfg.gfgBogoFeature.f.gfgRenderBuyProductTextPill(pillText); let price = product.variants[0].price / 100; let discountedPriceOfProduct = price; if (discountType === "PERCENTAGE") { discountedPriceOfProduct = price - (price * discountValue) / 100; } else if (discountType === "AMOUNT") { discountedPriceOfProduct = price - discountValue; } let gfgBuyProductPriceContainerBoxDiscountedPrice = document.createElement("div"); gfgBuyProductPriceContainerBoxDiscountedPrice.classList.add("gfgBuyProductPriceContainerBoxDiscountedPrice", "gfgBogoRedTextClass"); gfgBuyProductPriceContainerBoxDiscountedPrice.textContent = currencySymbol + discountedPriceOfProduct.toFixed(2); let gfgBuyProductPriceContainerBoxOriginalPrice = document.createElement("div"); gfgBuyProductPriceContainerBoxOriginalPrice.classList.add("gfgBuyProductPriceContainerBoxOriginalPrice"); gfgBuyProductPriceContainerBoxOriginalPrice.textContent = currencySymbol + price.toFixed(2); if (discountValue !== 0 && discountValue !== undefined) { gfgBuyProductPriceContainerBoxOriginalPrice.classList.add("gfgBuyProductPriceContainerBoxOriginalPriceStriked"); gfgBuyProductPriceContainerBox.append( gfgBuyProductPriceContainerBoxDiscountedPrice, gfgBuyProductPriceContainerBoxOriginalPrice, gfgBogoGetProductsPillText ); } else { gfgBuyProductPriceContainerBox.append(gfgBuyProductPriceContainerBoxOriginalPrice); } gfgBuyProductPriceContainer.append(gfgBuyProductVariantContainer, gfgBuyProductPriceContainerBox); gfgCustomerGetsProductContent.appendChild(gfgBuyProductPriceContainer); gfgRenderCustomerGetsProductCardPrepareUI.append(gfgProductImageContainer, gfgCustomerGetsProductContent); return gfgRenderCustomerGetsProductCardPrepareUI; } catch (error) { gfg.utility.debugConsole("error in gfgRenderCustomerGetsProductCardPrepareUI", error); } }, registerEvents: function(){ document.addEventListener('click', async function (event) { if(event.target.matches('.gfgBogoActionButton')){ const actionButton = event.target; if (!actionButton) return; event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); const activeBogoIndex = gfg.gfgBogoFeature.state.activeBogoIndex; const textConfig = gfg.settings.boGoFeature[activeBogoIndex].textConfig; const buttonText = { adding: textConfig?.buttonText?.adding || "Adding...", added: textConfig?.buttonText?.added || "Added", outOfStock: textConfig?.buttonText?.outOfStock || "Out of Stock", failedNotification: textConfig?.failedMessageNotification || "Promotion not applied, please check cart" }; actionButton.textContent = buttonText.adding; actionButton.classList.add('invalidActionButton'); const container = document.querySelector('.gfgCustomerGetsProductContent'); const selectedVariant = container.querySelector('.gfgBuyProductVariantSelectForCustomerGets'); const variantId = selectedVariant.selectedOptions[0].getAttribute('data-variant-id'); const quantity = parseFloat(selectedVariant.selectedOptions[0].getAttribute('data-count')); const selectedCustomerVariant = document.querySelector('.gfgBuyProductVariantSelect'); const customerVariantId = selectedCustomerVariant.selectedOptions[0].getAttribute('data-variant-id'); const selectedProductCount = parseFloat(selectedCustomerVariant.selectedOptions[0].getAttribute('data-count')); const productDetails = gfg.gfgBogoFeature.state.gfgBogoProductsCustomerGetsShopifyDataByVariantIds[variantId]; gfg.utility.debugConsole("Product ->", productDetails); let bogoSuccess = true; try { const bogoAdded = await gfg.utility.addToCart({ id: productDetails.variant_id, quantity }); if (!bogoAdded) bogoSuccess = false; const customerAdded = await gfg.utility.addToCart({ id: customerVariantId, quantity: selectedProductCount }); if (!customerAdded) bogoSuccess = false; } catch (error) { gfg.utility.debugConsole("Error while adding to cart:", error); bogoSuccess = false; } if (!bogoSuccess) { gfg.gfgBogoFeature.f.gfgBogoCreateNotificationMessage(buttonText.failedNotification); actionButton.textContent = buttonText.outOfStock; } else { actionButton.textContent = buttonText.added; } gfg.gfgBogoFeature.f.triggerUpdateActivities(); } }); document.body.addEventListener('change', function (event) { if (event.target.matches('.gfgBuyProductVariantSelect')){ try { event.preventDefault(); const parent = event.target.parentElement.parentElement; const selectedVariant = event.target; const selectedPrice = parseFloat(selectedVariant.value); const variantId = selectedVariant.selectedOptions[0].getAttribute('data-variant-id'); const variantIdMap = gfg.gfgBogoFeature.state.gfgBogoProductsShopifyDataByVariantIds; const productDetails = variantIdMap[variantId]; gfg.utility.debugConsole("productDetails ->", productDetails); const gfgBuyProductPriceContainerBoxDiscountedPrice = parent.closest('.gfgBuyProductDetailSectionContainer').querySelector('.gfgBuyProductPriceContainerBoxDiscountedPrice'); const userCurrency = gfg.utility.getCurrencySymbol(); let formattedPrice = selectedPrice; if (gfg.state?.formatPriceViaCustomScript) { let _selectedPrice = selectedPrice * 100; _selectedPrice = gfg.utility.formatPriceWithSeparator(_selectedPrice); formattedPrice = _selectedPrice; } gfgBuyProductPriceContainerBoxDiscountedPrice.textContent = userCurrency + formattedPrice; const cardContainer = parent?.closest('.gfgBuyProductCardContainer'); const imageContainer = cardContainer?.querySelector('.gfgProductImageContainer'); const imageTag = imageContainer?.querySelector('.gfgProductImage'); imageTag.setAttribute('src', 'https:' + gfg.utility.trimHttps(productDetails.image)); } catch (error) { gfg.utility.debugConsole("error in registerEvents -> onChange -> gfgBuyProductVariantSelect", error); } } }); document.body.addEventListener('change', function (event) { if (event.target.matches('.gfgBuyProductVariantSelectForCustomerGets')) { try { event.preventDefault(); const parent = event.target.parentElement.parentElement; const cardContainer = parent?.closest('.gfgRenderCustomerGetsProductCardPrepareUI'); if (!parent || !cardContainer) return; const selectedVariant = parent.querySelector('.gfgBuyProductVariantSelectForCustomerGets'); const selectedPrice = selectedVariant?.value; const discountedPrice = selectedVariant?.selectedOptions[0]?.getAttribute('data-discounted-price'); const variantId = selectedVariant?.selectedOptions[0]?.getAttribute('data-variant-id'); const variantIdMap = gfg.gfgBogoFeature.state.gfgBogoProductsCustomerGetsShopifyDataByVariantIds; const productDetails = variantIdMap[variantId]; const gfgBuyProductPriceContainerBoxDiscountedPrice = cardContainer.querySelector('.gfgBuyProductPriceContainerBoxDiscountedPrice'); const gfgBuyProductPriceContainerBoxOriginalPrice = cardContainer.querySelector('.gfgBuyProductPriceContainerBoxOriginalPrice'); const imageTag = cardContainer.querySelector('.gfgProductImageContainer .gfgProductImage'); const userCurrency = gfg.utility.getCurrencySymbol(); let formattedSelectedPrice = selectedPrice; if (gfg.state?.formatPriceViaCustomScript) { const _selectedPrice = selectedPrice * 100; formattedSelectedPrice = gfg.utility.formatPriceWithSeparator(_selectedPrice); } if (gfgBuyProductPriceContainerBoxDiscountedPrice) { gfgBuyProductPriceContainerBoxDiscountedPrice.textContent = discountedPrice; } if (gfgBuyProductPriceContainerBoxOriginalPrice) { gfgBuyProductPriceContainerBoxOriginalPrice.textContent = `${userCurrency}${formattedSelectedPrice}`; } if (imageTag && productDetails?.image) { imageTag.setAttribute('src','https:' + gfg.utility.trimHttps(productDetails.image)); } } catch (error) { gfg.utility.debugError("Error in onChange -> gfgBuyProductVariantSelectForCustomerGets", error); } } }); } }, actions: {}, }, customDiscountValidationFunctions: { updateCartAttributesWithTotalAmountWithoutFreeGift: async function (cartData) { try { const attributesObject = cartData.attributes; const calculatedDiscountedCartTotal = Number(gfg.customDiscountValidationFunctions.getAmountOfGivenProductsWithoutFreeGift(cartData.items)); if(attributesObject && attributesObject["_kite_cfAdditionalData"]) { let kiteCfAdditionalData = JSON.parse(attributesObject["_kite_cfAdditionalData"]); const attributeDiscountedValue = kiteCfAdditionalData.totalAmountWithoutFreeGift; if(calculatedDiscountedCartTotal === attributeDiscountedValue) { return; } } const attributeValue = { totalAmountWithoutFreeGift: calculatedDiscountedCartTotal } const dataToBeUpdated = { attributes: { _kite_cfAdditionalData: JSON.stringify(attributeValue), } } await gfg.utility.updateCart(dataToBeUpdated); } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 updateCartAttributesWithTotalAmountWithoutFreeGift fn", error); } }, checkForActiveCampaign: function (discountData) { try { const campaignScheduleData = discountData?.campaignScheduleData; // If there is no campaign schedule data or the campaign is not scheduled, include the discount if (!campaignScheduleData || campaignScheduleData?.campaignSchedule != "SCHEDULED") { return true; } // If the campaign is scheduled, check if the current date falls within the start and end dates if (campaignScheduleData?.campaignSchedule == "SCHEDULED") { let currentDateUTC = new Date().toISOString(); let startDateTime_UTC = campaignScheduleData.startDateTime_UTC; let endDateTime_UTC = campaignScheduleData.endDateTime_UTC; if (currentDateUTC >= startDateTime_UTC && currentDateUTC <= endDateTime_UTC) { return true; } } return false; } catch (error) { gfg.utility.debugConsole("Error inside gfgdiscountDataV2 checkForActiveCampaign fn", error); } }, checkCustomDiscountWidgetIsRelevantToCurrentPage: async function (discountData, pageType) { try { let widgetSettings; if(discountData.isUnifiedWidget) { widgetSettings = discountData; } else { widgetSettings = discountData?.widgetSettings } const rulesResultToShowWidget = await gfg.customDiscountValidationFunctions.checkRulesToHandleWidgetVisibility(discountData); if(!rulesResultToShowWidget){ return false; } const allProductPages = pageType === "PRODUCT_PAGE" && widgetSettings?.displaySettings?.productPages; const specificProductPages = pageType === "PRODUCT_PAGE" && widgetSettings?.displaySettings?.specificProductPages; const specificCollectionPages = pageType === "PRODUCT_PAGE" && widgetSettings?.displaySettings?.specificCollectionPages; const cartPage = pageType === "CART_PAGE" && widgetSettings?.displaySettings?.cartPage; const sideCart = pageType === "SIDE_CART" && widgetSettings?.displaySettings?.sideCart; if (cartPage) { return true; } if (sideCart) { return true; } if (allProductPages) { return true; } if (specificProductPages) { const specificProduct = widgetSettings.displaySettings.specificProducts; const currProductPageHandle = gfg.f.getProductPageHandle(); const currProductPageProductId = gfg.f.getProductPageId(); for (let product of specificProduct) { const handle = product.handle; const productId = product.productId; if (currProductPageHandle === handle || currProductPageProductId === productId) { return true; } } } if (specificCollectionPages) { const specificCollection = widgetSettings.displaySettings.specificCollections; const currProductPageCollections = window.shopifyLiquidValuesApp7Ext.product?.collections || []; if (currProductPageCollections.length === 0) { return false; } for (let collection of specificCollection) { const handle = collection.handle; const collectionId = collection.id.replace("gid://shopify/Collection/", ""); const isValidCollection = currProductPageCollections.find( (collection) => collection.handle == handle || collection.id == collectionId ); if (isValidCollection) { return true; } } } return false; } catch (error) { gfg.utility.debugConsole("Error inside checkCustomDiscountWidgetIsRelevantToCurrentPage fn", error); } }, checkRulesToHandleWidgetVisibility: async function (discountData) { let result = true; try { let { rulesData } = discountData; if(discountData.isUnifiedWidget) { rulesData = discountData.customerRulesData; } const rulesOperator = rulesData.rulesGlobalList[0].rulesOperator; const rulesList = rulesData.rulesGlobalList[0].rulesList; const evaluateRules = []; for(let rule of rulesList){ switch(rule.ruleType){ // currently handling widget visibility of widget for Shipping rules only & for other rules it will return true case "shippingCountry": evaluateRules.push(await gfg.customDiscountValidationFunctions.validateShippingRule(null,rule)); break; case "customerTags": evaluateRules.push(gfg.customDiscountValidationFunctions.checkIfCustomerTagsConditionMet(null,rule)); break; case "isCustomerLoggedIn": evaluateRules.push(gfg.customDiscountValidationFunctions.checkIfCustomerLoggedInConditionMet(null,rule)); break; default: evaluateRules.push(true); } } if(rulesOperator === "AND"){ result = evaluateRules.every((curr) => curr); } else{ result = evaluateRules.some((curr) => curr); } } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkRulesToHandleWidgetVisibility fn", error); } finally{ return result; } }, verifyCustomDiscountRules: async function (customDiscount, cartData) { try { const rulesOperator = customDiscount.rulesData.rulesGlobalList[0].rulesOperator; const rulesList = customDiscount.rulesData.rulesGlobalList[0].rulesList; let evaluateRules = []; if(rulesList.length === 0) { evaluateRules.push(true); } for (let rule of rulesList) { if(customDiscount.isUnifiedWidget) { rule.isUnifiedWidget = true; rule.discountType = rule.discountSettings.type } if(customDiscount?.discountFunctionType && customDiscount.discountFunctionType == "SHIPPING_DISCOUNT" && customDiscount?.advancedSettings?.onlyUseWidget) { rule.onlyUseWidget = true } let isRuleVerfied = await gfg.customDiscountValidationFunctions.checkRuleGroup(rule, cartData); evaluateRules.push(isRuleVerfied); } let verificationConditionMet = false; if (rulesOperator === "AND") { verificationConditionMet = evaluateRules.every(Boolean); } else { verificationConditionMet = evaluateRules.some(Boolean); } for (let i = 0; i < evaluateRules.length; i++) { let widgetSettings = customDiscount; let isConditionMet = evaluateRules[i]; if(!customDiscount.isUnifiedWidget && customDiscount?.widgetSettings) { customDiscount.widgetSettings.titleBar.conditionMet = verificationConditionMet; customDiscount.widgetSettings.rulesData.rulesGlobalList[0].finalCheckBox.conditionMet = verificationConditionMet; widgetSettings = customDiscount.widgetSettings; } if(customDiscount.widgetSettings || customDiscount.isUnifiedWidget) { widgetSettings.rulesData.rulesGlobalList[0].rulesList[i].conditionMet = isConditionMet; widgetSettings.rulesData.rulesGlobalList[0].rulesList[i].ruleValue = rulesList[i].ruleValue; widgetSettings.rulesData.rulesGlobalList[0].rulesList[i].ruleType = rulesList[i].ruleType; } } return verificationConditionMet; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 verifyCustomDiscountRules fn", error); } }, getQtyOfGivenProducts: function (items) { try { let totalQuantity = 0; for(let i=0; i total + line.quantity, 0); } else if (tierType === "CART_SUBTOTAL") { // Use the subtotal amount for comparison comparisonValue = parseFloat(cartData?.original_total_price); } else if (tierType === "DISCOUNTABLE_ITEMS_QUANTITY") { // Sum the quantities of all discountable items comparisonValue = validLineItems.reduce((total, item) => total + item.itemQty, 0); } else if (tierType === "DISCOUNTABLE_ITEMS_SUBTOTAL") { // Sum the total prices of all discountable items //comparisonValue = validLineItems.reduce((total, item) => total + (item.productVariant.quantity * item.itemPrice), 0); comparisonValue = validLineItems.reduce((total, item) => total + (item.itemQty * item.itemPrice), 0); } // Iterate through the tiers list to find the applicable discount tier for (const tier of tiersList) { const tierCondition = parseFloat(tier.tierCondition); // Check if the comparison value meets the tier condition if (comparisonValue >= tierCondition) { // If so, update the valid tier to the current tier validTier = tier; } else { // Stop checking further tiers since they are sorted in ascending order break; } } return validTier; } catch(err) { gfg.utility.debugConsole("err inside getValidTieredDiscountValue", err); } }, checkIfCartSubTotalConditionMet: function (cartData, ruleData) { try { let { operatorType, value } = ruleData.ruleValue; const currencyRate = gfg.utility.getActiveCurrencyRate(); value = value * currencyRate; let total = cartData.items_subtotal_price / 100; if(ruleData?.isUnifiedWidget || ruleData?.onlyUseWidget) { total = this.getAmountOfGivenProductsWithoutFreeGift(cartData.items); } const remainingSubtotalValue = (value - total >= 0 ? value - total : 0).toFixed(2); let dynamicProgressBarWidth = (total / value).toFixed(2) * 100; let isConditionSatisfied = false; switch (operatorType) { case "equalTo": isConditionSatisfied = total === Number(value); dynamicProgressBarWidth = dynamicProgressBarWidth <= 100 ? dynamicProgressBarWidth : 100; break; case "greaterThanOrEqualTo": isConditionSatisfied = total >= Number(value); dynamicProgressBarWidth = dynamicProgressBarWidth <= 100 ? dynamicProgressBarWidth : 100; break; case "lessThanOrEqualTo": isConditionSatisfied = total <= Number(value); dynamicProgressBarWidth = isConditionSatisfied ? 100 : 0; break; default: isConditionSatisfied = false; } ruleData.ruleValue.remainingSubtotalValue = remainingSubtotalValue; ruleData.ruleValue.dynamicProgressBarWidth = dynamicProgressBarWidth; return isConditionSatisfied; } catch (err) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkIfCartSubTotalConditionMet fn", err); return false; } }, checkIfCartQuantityConditionMet: function (cartData, ruleData) { try { let { operatorType, value } = ruleData.ruleValue; let totalQuantity = cartData.item_count; if(ruleData?.isUnifiedWidget) { totalQuantity = this.getQtyOfGivenProductsWithoutFreeGift(cartData.items); } const remainingQuantityValue = value - totalQuantity >= 0 ? value - totalQuantity : 0; let dynamicProgressBarWidth = (totalQuantity / value).toFixed(2) * 100; let isConditionSatisfied = false; switch (operatorType) { case "equalTo": isConditionSatisfied = totalQuantity === Number(value); dynamicProgressBarWidth = dynamicProgressBarWidth <= 100 ? dynamicProgressBarWidth : 100; break; case "greaterThanOrEqualTo": isConditionSatisfied = totalQuantity >= Number(value); dynamicProgressBarWidth = dynamicProgressBarWidth <= 100 ? dynamicProgressBarWidth : 100; break; case "lessThanOrEqualTo": isConditionSatisfied = totalQuantity <= Number(value); dynamicProgressBarWidth = isConditionSatisfied ? 100 : 0; break; default: isConditionSatisfied = false; } ruleData.ruleValue.remainingQuantityValue = remainingQuantityValue; ruleData.ruleValue.dynamicProgressBarWidth = dynamicProgressBarWidth; return isConditionSatisfied; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkIfCartQuantityConditionMet fn", error); } }, checkIfCartCurrencyConditionMet: function (cartData, ruleData) { try { const { currencies, operatorType } = ruleData.ruleValue; const currencyCode = cartData.currency; if (operatorType === "is" && currencies.includes(currencyCode)) { ruleData.ruleValue.dynamicProgressBarWidth = 100; return true; } if (operatorType === "isNot" && !currencies.includes(currencyCode)) { ruleData.ruleValue.dynamicProgressBarWidth = 100; return true; } ruleData.ruleValue.dynamicProgressBarWidth = 0; return false; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkIfCartCurrencyConditionMet fn", error); return false; } }, checkIfAttributesConditionMet: function (cartData, ruleData) { try { const { attributeKey, attributeValue } = ruleData.ruleValue; let qualifiedCartValue = attributeValue.value; let qualifiedCartKey = attributeKey.value; const cartAttributesObj = cartData.attributes; if (Object.keys(cartAttributesObj).length === 0) { ruleData.ruleValue.qualifiedCartKey = qualifiedCartKey; ruleData.ruleValue.qualifiedCartValue = qualifiedCartValue; ruleData.ruleValue.dynamicProgressBarWidth = 0; return false; } if (attributeKey.operatorType === "hasAnyValue") { ruleData.ruleValue.qualifiedCartKey = qualifiedCartKey; ruleData.ruleValue.qualifiedCartValue = qualifiedCartValue; ruleData.ruleValue.dynamicProgressBarWidth = 100; return Object.keys(cartAttributesObj).length > 0; } if (attributeKey.operatorType === "is" && !cartAttributesObj[attributeKey.value]) { ruleData.ruleValue.qualifiedCartKey = qualifiedCartKey; ruleData.ruleValue.qualifiedCartValue = qualifiedCartValue; ruleData.ruleValue.dynamicProgressBarWidth = 0; return false; } const cartAttributeValue = cartAttributesObj[attributeKey.value]; let isConditionSatisfied = false; switch (attributeValue.operatorType) { case "is": isConditionSatisfied = cartAttributeValue === attributeValue.value; break; case "isNot": isConditionSatisfied = cartAttributeValue !== attributeValue.value; break; case "contains": { let _cartAttributeValue = JSON.parse(JSON.stringify(cartAttributeValue)); _cartAttributeValue = _cartAttributeValue.toLowerCase(); isConditionSatisfied = _cartAttributeValue?.includes(attributeValue.value.toLowerCase()); break; } case "doesNotContain": { let _cartAttributeValue = JSON.parse(JSON.stringify(cartAttributeValue)); _cartAttributeValue = _cartAttributeValue.toLowerCase(); isConditionSatisfied = !_cartAttributeValue?.includes(attributeValue.value.toLowerCase()); break; } default: isConditionSatisfied = false; } ruleData.ruleValue.qualifiedCartKey = qualifiedCartKey; ruleData.ruleValue.qualifiedCartValue = qualifiedCartValue; ruleData.ruleValue.dynamicProgressBarWidth = isConditionSatisfied ? 100 : 0; return isConditionSatisfied; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkIfAttributesConditionMet fn", error); return false; } }, validateCartRule: function (cartData, ruleData) { try { switch (ruleData.ruleType) { case "cartSubtotal": return gfg.customDiscountValidationFunctions.checkIfCartSubTotalConditionMet(cartData, ruleData); case "cartQuantity": return gfg.customDiscountValidationFunctions.checkIfCartQuantityConditionMet(cartData, ruleData); case "cartCurrency": return gfg.customDiscountValidationFunctions.checkIfCartCurrencyConditionMet(cartData, ruleData); case "cartAttributes": return gfg.customDiscountValidationFunctions.checkIfAttributesConditionMet(cartData, ruleData); default: gfg.utility.debugConsole(`Unsupported CART ruleType: ${ruleData.ruleType}`); return false; } } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 validateCartRule fn", error); return false; } }, checkProductCondition: function (lineItem, ruleData) { try { let itemId = lineItem.variant_id || lineItem.id; let isEligible = false; const products = ruleData.ruleValue.products.filter((curr) => curr.productId == lineItem.product_id); let qualifiedProductObj = { title: ruleData.ruleValue.products[0].title, handle: ruleData.ruleValue.products[0].handle, variantTitle: ruleData.ruleValue.products[0].variants[0].variantTitle, }; for (let product of products) { const variants = product.variants; let isVariantFound = false; let variantTitle = variants[0].variantTitle; for (let variant of variants) { if (variant.variantId == itemId) { isEligible = true; isVariantFound = true; variantTitle = variant.variantTitle; break; } } if (isVariantFound) { qualifiedProductObj = { title: product.title, handle: product.handle, variantTitle }; break; } } ruleData.ruleValue.qualifiedProductObj = qualifiedProductObj; const isConditionSatisfied = ruleData.ruleValue.operatorType === "include" ? isEligible : !isEligible; return isConditionSatisfied; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkProductCondition fn", error); return false; } }, checkCollectionCondition_Old: function (lineItem, ruleData) { try { const collections = ruleData.ruleValue.collections; let qualifiedCollectionObj = { title: ruleData.ruleValue.collections[0].title, handle: ruleData.ruleValue.collections[0].handle }; const collectionsData = ruleData.ruleValue.collectionsData; let isEligible = false; for (let i = 0; i < collections.length; i++) { let collection = collections[i]; const collectionData = collectionsData[i]; const productList = collectionData.productList; let itemId = lineItem.product_id; let idsToMatch = productList.map((curr) => (curr.productId ? curr.productId + "" : curr.id + "")); isEligible = idsToMatch.includes(itemId + ""); if (isEligible && ruleData.ruleValue.operatorType === "include") { qualifiedCollectionObj = { title: collection.title, handle: collection.handle }; break; } } ruleData.ruleValue.qualifiedCollectionObj = qualifiedCollectionObj; const isConditionSatisfied = ruleData.ruleValue.operatorType === "include" ? isEligible : !isEligible; return isConditionSatisfied; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkCollectionCondition fn", error); return false; } }, checkCollectionCondition: function (lineItem, ruleData) { try { const collections = ruleData.ruleValue.collections; let qualifiedCollectionObj = { title: ruleData.ruleValue.collections[0].title, handle: ruleData.ruleValue.collections[0].handle }; let isEligible = false; for (let i = 0; i < collections.length; i++) { let collection = collections[i]; let collectionId = collection.id; let lineItemsCollections = lineItem.latestShopifyData.collections.map((curr) => curr.id); isEligible = lineItemsCollections.includes(collectionId); if (isEligible && ruleData.ruleValue.operatorType === "include") { qualifiedCollectionObj = { title: collection.title, handle: collection.handle }; break; } } ruleData.ruleValue.qualifiedCollectionObj = qualifiedCollectionObj; const isConditionSatisfied = ruleData.ruleValue.operatorType === "include" ? isEligible : !isEligible; return isConditionSatisfied; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkCollectionCondition fn", error); return false; } }, checkProductTypeCondition: function (lineItem, ruleData) { try { const typesToMatch = ruleData.ruleValue.types; const productType = lineItem.latestShopifyData.productType || ""; const isEligible = typesToMatch.includes(productType); ruleData.ruleValue.productType = isEligible ? productType : typesToMatch[0]; return ruleData.ruleValue.operatorType === "include" ? isEligible : !isEligible; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkProductTypeCondition fn", error); } }, checkProductTypeCondition_Old: function (lineItem, ruleData) { try { const typesToMatch = ruleData.ruleValue.types; const productType = lineItem.latestShopifyData.type || ""; const isEligible = typesToMatch.includes(productType); ruleData.ruleValue.productType = isEligible ? productType : typesToMatch[0]; return ruleData.ruleValue.operatorType === "include" ? isEligible : !isEligible; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkProductTypeCondition_Old fn", error); } }, checkTagCondition: function (lineItem, ruleData) { try { const tagsToMatch = ruleData.ruleValue.tags; const productTags = lineItem.latestShopifyData.tags || []; let matchingTag = tagsToMatch[0]; const isEligible = productTags.some((tagInfo) => { for (tag of tagsToMatch) { if (tagInfo === tag) { matchingTag = tag; return true; } } return false; }); ruleData.ruleValue.tagName = matchingTag; return ruleData.ruleValue.operatorType === "include" ? isEligible : !isEligible; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkTagCondition fn", error); } }, checkSubscriptionCondition: function (lineItem, ruleData) { try { const productHasSubscription = lineItem?.selling_plan_allocation?.selling_plan?.options?.length > 0 || false; const isConditionSatisfied = ruleData.ruleValue.operatorType === "include" ? Boolean(productHasSubscription) : !Boolean(productHasSubscription); return isConditionSatisfied; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkSubscriptionCondition fn", error); } }, checkLineAttributeCondition: function (lineItem, ruleData) { try { const { attributeKey, attributeValue } = ruleData.ruleValue; let qualifiedLineValue = attributeValue.value; let qualifiedLineProperty = attributeKey.value; const lineAttributeObj = lineItem.properties; if (attributeKey.operatorType === "hasAnyValue" && Object.keys(lineAttributeObj).length > 0) { ruleData.ruleValue.qualifiedLineValue = qualifiedLineValue; ruleData.ruleValue.qualifiedLineProperty = qualifiedLineProperty; ruleData.ruleValue.dynamicProgressBarWidth = 100; return true; } const lineAttributeValue = lineAttributeObj[attributeKey.value]; if (!lineAttributeValue) { ruleData.ruleValue.qualifiedLineValue = qualifiedLineValue; ruleData.ruleValue.qualifiedLineProperty = qualifiedLineProperty; return false; } let isConditionSatisfied = false; switch (attributeValue.operatorType) { case "is": isConditionSatisfied = lineAttributeValue === attributeValue.value; break; case "isNot": isConditionSatisfied = lineAttributeValue !== attributeValue.value; break; case "contains": isConditionSatisfied = lineAttributeValue.toLowerCase().includes(attributeValue.value.toLowerCase()); break; case "doesNotContain": isConditionSatisfied = !lineAttributeValue.toLowerCase().includes(attributeValue.value.toLowerCase()); break; default: isConditionSatisfied = false; } ruleData.ruleValue.qualifiedLineValue = qualifiedLineValue; ruleData.ruleValue.qualifiedLineProperty = qualifiedLineProperty; return isConditionSatisfied; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkLineAttributeCondition fn", error); return false; } }, compareMetrics: function (ruleData, cartValue) { try { let { qualifierOperatorType, qualifierValue } = ruleData.ruleValue; let dynamicProgressBarWidth = (cartValue / qualifierValue).toFixed(2) * 100; let isConditionSatisfied = false; qualifierValue = Number(qualifierValue); switch (qualifierOperatorType) { case "equalTo": isConditionSatisfied = cartValue === qualifierValue; dynamicProgressBarWidth = dynamicProgressBarWidth <= 100 ? dynamicProgressBarWidth : 100; break; case "greaterThanOrEqualTo": isConditionSatisfied = cartValue >= qualifierValue; dynamicProgressBarWidth = dynamicProgressBarWidth <= 100 ? dynamicProgressBarWidth : 100; break; case "lessThanOrEqualTo": isConditionSatisfied = cartValue <= qualifierValue; dynamicProgressBarWidth = isConditionSatisfied ? 100 : 0; break; case "greaterThan": isConditionSatisfied = cartValue > qualifierValue; dynamicProgressBarWidth = (cartValue / (qualifierValue + 1)).toFixed(2) * 100; dynamicProgressBarWidth = dynamicProgressBarWidth <= 100 ? dynamicProgressBarWidth : 100; dynamicProgressBarWidth = dynamicProgressBarWidth; break; case "lessThan": isConditionSatisfied = cartValue < qualifierValue; dynamicProgressBarWidth = isConditionSatisfied ? 100 : 0; break; default: gfg.utility.debugConsole("Unsupported comparison type:", qualifierOperatorType); isConditionSatisfied = false; } const remainingValue = qualifierValue - cartValue; ruleData.ruleValue.remainingValue = remainingValue; ruleData.ruleValue.dynamicProgressBarWidth = dynamicProgressBarWidth; return isConditionSatisfied; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 compareMetrics fn", error); return false; } }, getQtyOfGivenDistinctProducts: function (items) { try { return items.length; } catch (err) { console.error("Error inside getQtyOfGivenDistinctProducts", err); return 0; } }, evaluateProductMetrics: function (finalProducts, ruleData, cartData) { let { qualifierType, qualifierValue } = ruleData.ruleValue; if (!qualifierType || qualifierType == "none") { return true; } let result = false; let totalValue = 0; try { // Determine total value based on metric type if (qualifierType === "quantity") { totalValue = finalProducts.reduce((sum, item) => sum + parseInt(item?.quantity || 0), 0); } else if (qualifierType === "distinctQuantity") { totalValue = gfg.customDiscountValidationFunctions.getQtyOfGivenDistinctProducts(finalProducts); } else if (qualifierType === "amount") { const currencyRate = gfg.utility.getActiveCurrencyRate(); qualifierValue = qualifierValue * currencyRate; if(ruleData?.onlyUseWidget) { totalValue = finalProducts.reduce((sum, item) => sum + parseFloat(item?.original_line_price / 100 || 0), 0); } else { totalValue = finalProducts.reduce((sum, item) => sum + parseFloat(item?.line_price / 100 || 0), 0); } } // Compare the calculated total value against the rule's metric result = gfg.customDiscountValidationFunctions.compareMetrics(ruleData, totalValue); return result; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 evaluateProductMetrics fn", error); return false; } }, validateProductRule: async function (cartData, ruleData) { try { const shouldIncludeItemForMetricsArr = (isValid, operatorType) => { return (operatorType === "include" && isValid) || (operatorType === "exclude" && !isValid); }; let matchingProducts = []; const storefrontAccessPresent = gfg.settings.merchantInfo.storefrontAccessToken ? true : false; switch (ruleData.ruleType) { case "products": case "productVariants": if (cartData.items.length === 0) { let qualifiedProductObjProductsAndVariants = { title: ruleData.ruleValue.products[0].title, handle: ruleData.ruleValue.products[0].handle, variantTitle: ruleData.ruleValue.products[0].variants[0].variantTitle, }; ruleData.ruleValue.qualifiedProductObj = qualifiedProductObjProductsAndVariants; ruleData.ruleValue.dynamicProgressBarWidth = 0; } cartData.items.forEach((lineItem) => { const isProductValid = gfg.customDiscountValidationFunctions.checkProductCondition(lineItem, ruleData); if (shouldIncludeItemForMetricsArr(isProductValid, ruleData.ruleValue.operatorType)) { matchingProducts.push(lineItem); } }); break; case "collections": if (cartData.items.length === 0) { let qualifiedCollectionObjCollection = { title: ruleData.ruleValue.collections[0].title, handle: ruleData.ruleValue.collections[0].handle, }; ruleData.ruleValue.qualifiedCollectionObj = qualifiedCollectionObjCollection; ruleData.ruleValue.dynamicProgressBarWidth = 0; } if (storefrontAccessPresent) { await gfg.customDiscountValidationFunctions.getLatestCartItemsProductData(cartData); } cartData.items.forEach((lineItem) => { const isCollectionValid = storefrontAccessPresent ? gfg.customDiscountValidationFunctions.checkCollectionCondition(lineItem, ruleData) : gfg.customDiscountValidationFunctions.checkCollectionCondition_Old(lineItem, ruleData); if (shouldIncludeItemForMetricsArr(isCollectionValid, ruleData.ruleValue.operatorType)) { matchingProducts.push(lineItem); } }); break; case "productTypes": if (cartData.items.length === 0) { ruleData.ruleValue.productType = ruleData.ruleValue.types[0]; ruleData.ruleValue.dynamicProgressBarWidth = 0; } await gfg.customDiscountValidationFunctions.getLatestCartItemsProductData(cartData); cartData.items.forEach((lineItem) => { const isTypeValid = storefrontAccessPresent ? gfg.customDiscountValidationFunctions.checkProductTypeCondition(lineItem, ruleData) : gfg.customDiscountValidationFunctions.checkProductTypeCondition_Old(lineItem, ruleData); if (shouldIncludeItemForMetricsArr(isTypeValid, ruleData.ruleValue.operatorType)) { matchingProducts.push(lineItem); } }); break; case "productTags": if (cartData.items.length === 0) { ruleData.ruleValue.tagName = ruleData.ruleValue.tags[0]; ruleData.ruleValue.dynamicProgressBarWidth = 0; } await gfg.customDiscountValidationFunctions.getLatestCartItemsProductData(cartData); cartData.items.forEach((lineItem) => { const isTagValid = gfg.customDiscountValidationFunctions.checkTagCondition(lineItem, ruleData); if (shouldIncludeItemForMetricsArr(isTagValid, ruleData.ruleValue.operatorType)) { matchingProducts.push(lineItem); } }); break; case "productVendors": // await gfg.customDiscountValidationFunctions.getLatestCartItemsProductData(cartData); // cartData.items.forEach((lineItem) => { // const isTypeValid = checkProductTypeCondition(lineItem, ruleData); // if (shouldIncludeItemForMetricsArr(isTypeValid, ruleData.ruleValue.operatorType)) { // matchingProducts.push(lineItem); // } // }); // break; case "productHasSubscription": if (cartData.items.length === 0) { ruleData.ruleValue.dynamicProgressBarWidth = 0; } cartData.items.forEach((lineItem) => { const isSubscriptionValid = gfg.customDiscountValidationFunctions.checkSubscriptionCondition(lineItem, ruleData); if (shouldIncludeItemForMetricsArr(isSubscriptionValid, ruleData.ruleValue.operatorType)) { matchingProducts.push(lineItem); } }); break; case "lineAttributes": if (cartData.items.length === 0) { let qualifiedLineValue = ruleData.ruleValue.attributeValue.value; let qualifiedLineProperty = ruleData.ruleValue.attributeKey.value; ruleData.ruleValue.qualifiedLineValue = qualifiedLineValue; ruleData.ruleValue.qualifiedLineProperty = qualifiedLineProperty; ruleData.ruleValue.dynamicProgressBarWidth = 0; } cartData.items.forEach((lineItem) => { const isAttributeValid = gfg.customDiscountValidationFunctions.checkLineAttributeCondition(lineItem, ruleData); if (shouldIncludeItemForMetricsArr(isAttributeValid, ruleData.ruleValue.operatorType)) { matchingProducts.push(lineItem); } }); break; default: gfg.utility.debugConsole(`Unsupported PRODUCT ruleType: ${ruleData.ruleType}`); return false; } if (ruleData.ruleValue.operatorType === "exclude" && ruleData.ruleValue.qualifierType === "none") { return matchingProducts.length === 0; } return gfg.customDiscountValidationFunctions.evaluateProductMetrics(matchingProducts, ruleData, cartData); } catch (error) { gfg.utility.debugConsole(`Error in validateProductRule: ${error}`); return false; } }, validateProductRuleForDiscountableItems: async function (cartData, ruleData, lineItem) { try { const storefrontAccessPresent = gfg.settings.merchantInfo.storefrontAccessToken ? true : false; const getNewLineItem = (_cartData, lineItemId) => { return _cartData?.items.filter((ele) => ele.id == lineItemId)?.[0] } switch (ruleData.ruleType) { case "allProducts": return true; case "products": case "productVariants": const isProductValid = gfg.customDiscountValidationFunctions.checkProductCondition(lineItem, ruleData); return isProductValid; case "collections": { if (storefrontAccessPresent) { await gfg.customDiscountValidationFunctions.getLatestCartItemsProductData(cartData); } let newLineItem = getNewLineItem(cartData, lineItem.id); const isCollectionValid = storefrontAccessPresent ? gfg.customDiscountValidationFunctions.checkCollectionCondition(newLineItem, ruleData) : gfg.customDiscountValidationFunctions.checkCollectionCondition_Old(newLineItem, ruleData); return isCollectionValid; } case "productTypes": { await gfg.customDiscountValidationFunctions.getLatestCartItemsProductData(cartData); let newLineItem = getNewLineItem(cartData, lineItem.id); const isTypeValid = storefrontAccessPresent ? gfg.customDiscountValidationFunctions.checkProductTypeCondition(newLineItem, ruleData) : gfg.customDiscountValidationFunctions.checkProductTypeCondition_Old(newLineItem, ruleData); return isTypeValid; } case "productTags": { await gfg.customDiscountValidationFunctions.getLatestCartItemsProductData(cartData); let newLineItem = getNewLineItem(cartData, lineItem.id); const isTagValid = gfg.customDiscountValidationFunctions.checkTagCondition(newLineItem, ruleData); return isTagValid; } case "productVendors": // await gfg.f.getLatestCartItemsProductData(cartData); // cartData.items.forEach((lineItem) => { // const isTypeValid = checkProductTypeCondition(lineItem, ruleData); // if (shouldIncludeItemForMetricsArr(isTypeValid, ruleData.ruleValue.operatorType)) { // matchingProducts.push(lineItem); // } // }); // break; case "productHasSubscription": const isSubscriptionValid = gfg.customDiscountValidationFunctions.checkSubscriptionCondition(lineItem, ruleData); return isSubscriptionValid; case "lineAttributes": const isAttributeValid = gfg.customDiscountValidationFunctions.checkLineAttributeCondition(lineItem, ruleData); return isAttributeValid; default: gfg.utility.debugConsole(`Unsupported PRODUCT ruleType: ${ruleData.ruleType}`); return false; } } catch (error) { gfg.utility.debugConsole(`Error in validateProductRule: ${error}`); return false; } }, checkIfCustomerTagsConditionMet: function (cartData, ruleData) { try { const customerTags = window?.shopifyLiquidValuesApp7Ext?.customer?.customerTags; let { operatorType, tags: ruleTags } = ruleData.ruleValue; let qualifiedTag = ruleTags[0]; let isPresent = false; if(!customerTags && operatorType == "isNot") { ruleData.ruleValue.qualifiedTag = qualifiedTag; ruleData.ruleValue.dynamicProgressBarWidth = 0; return true; } if(!customerTags && operatorType == "is") { ruleData.ruleValue.qualifiedTag = qualifiedTag; ruleData.ruleValue.dynamicProgressBarWidth = 0; return false; } if (!customerTags) { ruleData.ruleValue.qualifiedTag = qualifiedTag; ruleData.ruleValue.dynamicProgressBarWidth = 0; return false; } switch (operatorType) { case "is": isPresent = customerTags.some((tagInfo) => ruleTags.includes(tagInfo)); break; case "isNot": isPresent = !customerTags.some((tagInfo) => ruleTags.includes(tagInfo)); break; case "contains": for (let customerTag of customerTags) { for (let ruleTag of ruleTags) { if (customerTag.toLowerCase().includes(ruleTag.toLowerCase())) { qualifiedTag = ruleTag; isPresent = true; break; } } } isPresent = false; break; case "doesNotContain": for (let customerTag of customerTags) { for (let ruleTag of ruleTags) { if (customerTag.toLowerCase().includes(ruleTag.toLowerCase())) { qualifiedTag = ruleTag; isPresent = false; break; } } } isPresent = true; break; default: isPresent = false; } ruleData.ruleValue.qualifiedTag = qualifiedTag; ruleData.ruleValue.dynamicProgressBarWidth = isPresent ? 100 : 0; return isPresent; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkIfCustomerTagsConditionMet fn", error); return false; } }, checkIfCustomerLoggedInConditionMet: function (cartData, ruleData) { try { const isCustomerLoggedIn = window.shopifyLiquidValuesApp7Ext.customer.id ? true : false; const expectedLoginStatus = ruleData.ruleValue.value; if (expectedLoginStatus === "yes") { ruleData.ruleValue.dynamicProgressBarWidth = isCustomerLoggedIn ? 100 : 0; return isCustomerLoggedIn; } if (expectedLoginStatus === "no") { ruleData.ruleValue.dynamicProgressBarWidth = !isCustomerLoggedIn ? 100 : 0; return !isCustomerLoggedIn; } ruleData.ruleValue.dynamicProgressBarWidth = 0; return false; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkIfCustomerLoggedInConditionMet fn", error); return false; } }, validateCustomerRule: function (cartData, ruleData) { try { switch (ruleData.ruleType) { case "customerTags": return gfg.customDiscountValidationFunctions.checkIfCustomerTagsConditionMet(cartData, ruleData); case "isCustomerLoggedIn": return gfg.customDiscountValidationFunctions.checkIfCustomerLoggedInConditionMet(cartData, ruleData); default: gfg.utility.debugConsole(`Unsupported CUSTOMER ruleType: ${ruleData.ruleType}`); return false; } } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 validateCustomerRule fn", error); } }, checkIfShippingCountryConditionMet: async function (cartData, ruleData) { try { let { operatorType, countries } = ruleData.ruleValue; // const shippingCountryCode = gfg.utility.getCountry(); // Now shipping country Code = customer visiting country Code; not taking from shopify. const shippingCountryCode = await gfg.utility.getVisitingFromCountry(); let qualifiedCountry = countries[0]; if (operatorType === "include") { // Check if any delivery country is included in the list of specified countries. const isPresent = countries.includes(shippingCountryCode && shippingCountryCode.toUpperCase()); if (isPresent) { qualifiedCountry = shippingCountryCode; } ruleData.ruleValue.qualifiedCountry = qualifiedCountry; ruleData.ruleValue.dynamicProgressBarWidth = isPresent ? 100 : 0; return isPresent; } else if (operatorType === "exclude") { // Check if all delivery countries are not in the list of specified countries. ruleData.ruleValue.qualifiedCountry = qualifiedCountry; return !countries.includes(shippingCountryCode && shippingCountryCode.toUpperCase()); } return false; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkIfShippingCountryConditionMet fn", error); } }, validateShippingRule: function (cartData, ruleData) { try { switch (ruleData.ruleType) { case "shippingCountry": return gfg.customDiscountValidationFunctions.checkIfShippingCountryConditionMet(cartData, ruleData); default: gfg.utility.debugConsole(`Unsupported SHIPPING ruleType: ${ruleData.ruleType}`); return false; } } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 validateShippingRule fn", error); } }, checkRuleGroup: async function (currentRule, cartData) { try { switch (currentRule.type) { case "CART": return gfg.customDiscountValidationFunctions.validateCartRule(cartData, currentRule); case "PRODUCT": return gfg.customDiscountValidationFunctions.validateProductRule(cartData, currentRule); case "CUSTOMER": return gfg.customDiscountValidationFunctions.validateCustomerRule(cartData, currentRule); case "SHIPPING": return gfg.customDiscountValidationFunctions.validateShippingRule(cartData, currentRule); default: gfg.utility.debugConsole(`Unsupported rule type: ${currentRule.type}`); return false; } } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkRuleGroup fn", error); } }, verifyIndividualRule: async function (ruleData, cartData) { try { const ruleType = ruleData.ruleType; const ruleValue = ruleData.ruleValue; const type = ruleData.type; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 verifyIndividualRule fn", error); } }, getLatestCartItemsProductData: async function (cartData) { try { if (cartData.items.length === 0) { return; } const productIds = []; const productHandles = []; const shopName = gfg.settings.merchantInfo.shopName; const storefrontAccessPresent = !!gfg.settings.merchantInfo.storefrontAccessToken; const cachedData = JSON.parse(sessionStorage.getItem(`customFunctionProductData-${shopName}`)) || {}; // Extract product IDs, handles, and map their data cartData.items.forEach((item) => { const { product_id, handle, line_price, quantity } = item; productIds.push(product_id); productHandles.push(handle); }); // Fetch product data, using cache if available const productIdsPromise = productIds.map((productId, index) => { if (cachedData[productId]) { return Promise.resolve(cachedData[productId]); } else { const latestData = storefrontAccessPresent ? gfg.customDiscountStorefrontApis.getProductsDataById([`gid://shopify/Product/${productId}`]) : gfg.utility.getProductDataV2(productHandles[index]); return latestData; } }); // Wait for all product data fetches to complete const allProductsData = await Promise.all(productIdsPromise); // Update cart items with the latest Shopify data and update the cache cartData.items.forEach((currCartItem, index) => { const productId = currCartItem.product_id; const latestData = allProductsData[index]; if (!cachedData[productId]) { cachedData[productId] = latestData; } currCartItem.latestShopifyData = latestData; }); // Update session storage cache sessionStorage.setItem(`customFunctionProductData-${shopName}`, JSON.stringify(cachedData)); } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 getLatestCartItemsProductData fn", error); } }, getProductsDataByProductIds: async function (productIds) { try { let shopName = window.Shopify.shop; const storefrontAccessPresent = !!gfg.settings.merchantInfo.storefrontAccessToken; const cachedData = JSON.parse(sessionStorage.getItem(`customFunctionProductData-${shopName}`)) || {}; const productIdsPromise = productIds.map((productId, index) => { let productGid = `gid://shopify/Product/${productId}` if (cachedData[productGid]) { return Promise.resolve(cachedData[productGid]); } else { const latestData = storefrontAccessPresent ? gfg.customDiscountStorefrontApis.getProductsDataById([productGid]) : gfg.utility.getProductDataV2(productHandles[index]); return latestData; } }); const allProductsData = await Promise.all(productIdsPromise); allProductsData.forEach((product) => { const productId = product?.id; if(!cachedData[productId]) { cachedData[productId] = product; } }) sessionStorage.setItem(`customFunctionProductData-${shopName}`, JSON.stringify(cachedData)); return allProductsData } catch (error) { gfg.utility.debugConsole("Error inside getProductsDataByProductIds fn", error); } }, getProductsDataFromCollectionIds: async function (collectionIds) { try { let shopName = window.Shopify.shop; const storefrontAccessPresent = !!gfg.settings.merchantInfo.storefrontAccessToken; const cachedData = JSON.parse(sessionStorage.getItem(`customFunctionProductData-${shopName}`)) || {}; let allProductsData = []; for(let i=0; i= 10) { break; } const collectionId = collectionIds[i]; const collectionData = await gfg.customDiscountStorefrontApis.getCollectionsDataById([collectionId]); allProductsData = [...allProductsData, ...collectionData?.[0]?.products] } allProductsData?.forEach((product) => { const productId = product?.id; if(!cachedData[productId]) { cachedData[productId] = product; } }) sessionStorage.setItem(`customFunctionProductData-${shopName}`, JSON.stringify(cachedData)); return allProductsData; } catch (error) { gfg.utility.debugConsole("Error inside getProductsDataFromCollectionIds fn", error); } }, getProductsDataByProductTags: async function (productTags) { try { let allProductsData = [] let shopName = window.Shopify.shop; const cachedData = JSON.parse(sessionStorage.getItem(`customFunctionProductData-${shopName}`)) || {}; for(let i=0; i= 10) { break; } const productTag = productTags[i]; const response = await gfg.customDiscountStorefrontApis.getProductsDataByTagName(productTag); const productsData = response?.products.filter((product) => product.tags.includes(productTag)) allProductsData = [...allProductsData, ...productsData] } allProductsData?.forEach((product) => { const productId = product?.id; if(!cachedData[productId]) { cachedData[productId] = product; } }) sessionStorage.setItem(`customFunctionProductData-${shopName}`, JSON.stringify(cachedData)); return allProductsData; } catch (error) { gfg.utility.debugConsole("Error inside getProductsDataByProductTags fn", error); } }, getProductsDataByProductTypes: async function (productTypes) { try { let allProductsData = [] let shopName = window.Shopify.shop; const cachedData = JSON.parse(sessionStorage.getItem(`customFunctionProductData-${shopName}`)) || {}; for(let i=0; i= 10) { break; } const productType = productTypes[i]; const response = await gfg.customDiscountStorefrontApis.getProductsDataByProductType(productType); const productsData = response?.products.filter((product) => product.productType === productType) allProductsData = [...allProductsData, ...productsData] } allProductsData?.forEach((product) => { const productId = product?.id; if(!cachedData[productId]) { cachedData[productId] = product; } }) sessionStorage.setItem(`customFunctionProductData-${shopName}`, JSON.stringify(cachedData)); return allProductsData; } catch (error) { gfg.utility.debugConsole("Error inside getProductsDataByProductTypes fn", error); } } }, customDiscountStorefrontApis: { flattenGraphQLResponse: function (response) { try { gfg.utility.debugConsole("response", response); const nodes = response.data ? response.data.nodes : []; gfg.utility.debugConsole("flattened-just-node", nodes); const flattenedNodes = nodes.map((node) => { if (node) { const flattenedNode = {}; Object.keys(node).forEach((key) => { const value = node[key]; if (value && typeof value === "object") { if (value.edges) { flattenedNode[key] = value.edges.map((edge) => edge.node); } else if (value.node) { flattenedNode[key] = value.node; } else { flattenedNode[key] = value; } } else { flattenedNode[key] = value; } }); gfg.utility.debugConsole("flattenedNode", flattenedNode); return flattenedNode; } }); gfg.utility.debugConsole("flattenedNodes", flattenedNodes); return flattenedNodes; } catch (error) { gfg.utility.debugConsole("Error inside gfgCustomDiscount flattenGraphQLResponse fn", error); } }, flattenGraphQLResponseV2 : function (response) { try { gfg.utility.debugConsole("response", response); function processValue(value) { if (Array.isArray(value)) { return value.map(processValue); } if (typeof value === 'object' && value !== null) { if ('edges' in value) { return processValue(value.edges); } if ('node' in value) { return processValue(value.node); } if ('nodes' in value) { return processValue(value.nodes); } const result = {}; for (const [key, val] of Object.entries(value)) { result[key] = processValue(val); } return result; } return value; } return processValue(response); } catch (error) { gfg.utility.debugConsole("Error inside gfgCustomDiscount flattenGraphQLResponseV2 fn", error); } }, makeGraphQLApiCall: async function (query, variables) { try { if(variables.languageCode === "ZH-TW") { variables.languageCode = "ZH_TW"; //to hangle language code issue from shopify } const { shopName, storefrontAccessToken } = gfg.settings.merchantInfo; const SHOP_DOMAIN = shopName; const STOREFRONT_ACCESS_TOKEN = storefrontAccessToken; const response = await fetch(`https://${SHOP_DOMAIN}/api/2023-04/graphql.json?skipListener=true`, { method: "POST", headers: { "Content-Type": "application/json", "X-Shopify-Storefront-Access-Token": STOREFRONT_ACCESS_TOKEN, }, body: JSON.stringify({ query, variables }), }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const data = await response.json(); let cleanedData = gfg.customDiscountStorefrontApis.flattenGraphQLResponseV2(data); return cleanedData; } catch (error) { gfg.utility.debugConsole("Error inside gfgCustomDiscount makeGraphQLApiCall fn", error); } }, getProductsDataById: async function (productIds) { try { const query = `query test($ids: [ID!]!, $countryCode: CountryCode!, $languageCode: LanguageCode!) @inContext(country: $countryCode, language: $languageCode) { nodes(ids: $ids) { ... on Product{ id availableForSale title handle productType collections(first: 25) { edges { node { id } } } featuredImage{ originalSrc } tags vendor compareAtPriceRange{ maxVariantPrice{ amount currencyCode } minVariantPrice{ amount currencyCode } } priceRange{ maxVariantPrice{ amount currencyCode } minVariantPrice{ amount currencyCode } } variants(first: 100) { edges { node { id title price{ amount currencyCode } currentlyNotInStock compareAtPrice{ amount currencyCode } image { originalSrc } selectedOptions{ name value } availableForSale } } } } } }`; const variables = { ids: productIds, countryCode: window?.Shopify?.country || "IN", languageCode: window?.Shopify?.locale?.toUpperCase() || "EN", }; if(variables.languageCode === "ZH-TW") { variables.languageCode = "ZH_TW"; //to hangle language code issue from shopify } try { const { shopName, storefrontAccessToken } = gfg.settings.merchantInfo; const SHOP_DOMAIN = shopName; const STOREFRONT_ACCESS_TOKEN = storefrontAccessToken; const response = await fetch(`https://${SHOP_DOMAIN}/api/2023-04/graphql.json?skipListener=true`, { method: "POST", headers: { "Content-Type": "application/json", "X-Shopify-Storefront-Access-Token": STOREFRONT_ACCESS_TOKEN, }, body: JSON.stringify({ query, variables }), }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const data = await response.json(); let cleanedData = gfg.customDiscountStorefrontApis.flattenGraphQLResponse(data); return cleanedData[0]; } catch (error) { gfg.utility.debugConsole("Error:", error); } } catch (err) { gfg.utility.debugConsole("Error inside gfgCustomDiscount getProductsDataById fn", err); } }, getCollectionsDataById: async function (collectionIds) { try { const query = `query test($ids: [ID!]!, $countryCode: CountryCode!, $languageCode: LanguageCode!) @inContext(country: $countryCode, language: $languageCode) { nodes(ids: $ids) { ... on Collection{ title id products(first: 10) { edges { node { id availableForSale title handle productType collections(first: 25) { edges { node { id } } } featuredImage { originalSrc } tags vendor compareAtPriceRange { maxVariantPrice { amount currencyCode } minVariantPrice { amount currencyCode } } priceRange { maxVariantPrice { amount currencyCode } minVariantPrice { amount currencyCode } } variants(first: 100) { edges { node { id title price { amount currencyCode } currentlyNotInStock compareAtPrice { amount currencyCode } image { originalSrc } selectedOptions { name value } availableForSale } } } } } } } } }`; const variables = { ids: collectionIds, countryCode: window?.Shopify?.country || "IN", languageCode: window?.Shopify?.locale?.toUpperCase() || "EN", }; const response = await gfg.customDiscountStorefrontApis.makeGraphQLApiCall(query, variables); return response?.data; } catch (err) { gfg.utility.debugConsole("Error inside gfgCustomDiscount getCollectionsDataById fn", err); } }, getProductsDataByTagName: async function (productTag) { try { const query = `query GetProductsByTags($tag: String!) { products(first: 15, query: $tag) { edges { node { id availableForSale title handle productType collections(first: 25) { edges { node { id } } } featuredImage { originalSrc } tags vendor compareAtPriceRange { maxVariantPrice { amount currencyCode } minVariantPrice { amount currencyCode } } priceRange { maxVariantPrice { amount currencyCode } minVariantPrice { amount currencyCode } } variants(first: 100) { edges { node { id title price { amount currencyCode } currentlyNotInStock compareAtPrice { amount currencyCode } image { originalSrc } selectedOptions { name value } availableForSale } } } } } } }`; const variables = { tag: productTag, countryCode: window?.Shopify?.country || "IN", languageCode: window?.Shopify?.locale?.toUpperCase() || "EN", }; const response = await gfg.customDiscountStorefrontApis.makeGraphQLApiCall(query, variables); return response?.data; } catch (err) { gfg.utility.debugConsole("Error inside gfgCustomDiscount getProductsDataByTagName fn", err); } }, getProductsDataByProductType: async function (productType) { try { const query = `query GetProductsByTypes($product_type: String!) { products(first: 15, query: $product_type) { edges { node { id availableForSale title handle productType collections(first: 25) { edges { node { id } } } featuredImage { originalSrc } tags vendor compareAtPriceRange { maxVariantPrice { amount currencyCode } minVariantPrice { amount currencyCode } } priceRange { maxVariantPrice { amount currencyCode } minVariantPrice { amount currencyCode } } variants(first: 100) { edges { node { id title price { amount currencyCode } currentlyNotInStock compareAtPrice { amount currencyCode } image { originalSrc } selectedOptions { name value } availableForSale } } } } } } }`; const variables = { product_type: productType, countryCode: window?.Shopify?.country || "IN", languageCode: window?.Shopify?.locale?.toUpperCase() || "EN", }; const response = await gfg.customDiscountStorefrontApis.makeGraphQLApiCall(query, variables); return response?.data; } catch (err) { gfg.utility.debugConsole("Error inside gfgCustomDiscount getProductsDataByProductType fn", err); } }, getProductsDataByIdWithAjaxResponse: async function(productIds){ try { const metafields = gfg.settings.app?.metafieldNameSpaceAndKeys || []; const metafieldQueries = metafields.length > 0 ? gfg.utility.generateMetafieldQueries(metafields) : ""; const query = `query test($ids: [ID!]!, $countryCode: CountryCode!, $languageCode: LanguageCode!) @inContext(country: $countryCode, language: $languageCode) { nodes(ids: $ids) { ... on Product{ id availableForSale title handle createdAt description ${metafieldQueries ? metafieldQueries : ""} descriptionHtml productType onlineStoreUrl options{ id name values } featuredImage{ id originalSrc transformedSrc(maxWidth: 800, maxHeight: 800, crop: CENTER) } updatedAt tags totalInventory vendor requiresSellingPlan compareAtPriceRange{ maxVariantPrice{ amount currencyCode } minVariantPrice{ amount currencyCode } } priceRange{ maxVariantPrice{ amount currencyCode } minVariantPrice{ amount currencyCode } } media(first:100){ edges{ node{ id alt previewImage{ url id } } } } images(first:100){ edges{ node{ id originalSrc transformedSrc(maxWidth: 800, maxHeight: 800, crop: CENTER) } } } variants(first: 100) { edges { node { id sku title price{ amount currencyCode } weight weightUnit requiresShipping currentlyNotInStock compareAtPrice{ amount currencyCode } quantityAvailable selectedOptions{ name value } availableForSale image { id originalSrc transformedSrc(maxWidth: 800, maxHeight: 800, crop: CENTER) } } } } } } }`; const variables = { ids: productIds, countryCode: window?.Shopify?.country || "IN", languageCode: window?.Shopify?.locale?.toUpperCase()?.split("-")[0] || "EN", }; const response = await gfg.customDiscountStorefrontApis.makeGraphQLApiCall(query, variables); const cleanedData = response.data.filter((item) => item != null && item != undefined); const productsData = gfg.utility.dataMappingFromGraphql(cleanedData); return productsData; } catch (error) { gfg.utility.debugConsole("Error inside getProductsDataByIdWithAjaxResponse fn", error); } } }, gfgUnifiedWidget: { state: { isFirstRenderForUnifiedWidget: true, }, init: async function(settings, parent){ try { await this.initialize(settings, parent); } catch (error) { gfg.utility.debugConsole(error); } }, initialize: async function(settings, parent){ // const allUnifiedWidgets = settings.unifiedWidget; let unifiedWidgetSettings = settings?.unifiedWidgets; if (parent == "PRODUCT_PAGE") { let productPage let preparedDataObj = await gfg.gfgUnifiedWidget.f.prepareUI(settings, parent) gfg.gfgUnifiedWidget.f.insertIntoPageWrapper(preparedDataObj, parent) gfg.utility.debugConsole("PRODUCT_PAGE-variantListToBeShownOnProductPage") } if (parent == "CART_PAGE") { let preparedDataObj = await gfg.gfgUnifiedWidget.f.prepareUI(settings, parent) gfg.gfgUnifiedWidget.f.insertIntoPageWrapper(preparedDataObj, parent) gfg.utility.debugConsole("CART_PAGE-gfgUnifiedWidgetCartPageHtml") } }, f: { prepareUI: async function(settings, parent) { try { const allUnifiedWidgets = settings?.unifiedWidgets let preparedUiArray = []; let prepredUnifiedWidgetData = []; let cartData; if(gfg.gfgUnifiedWidget.state.isFirstRenderForUnifiedWidget) { cartData = await gfg.utility.getFirstRenderCartData(); gfg.state.cartData = cartData; gfg.gfgUnifiedWidget.state.isFirstRenderForUnifiedWidget = false; } else if(gfg.state.cartData){ cartData = gfg.state.cartData; } else { cartData = await gfg.utility.getCart(); gfg.state.cartData = cartData; } if(allUnifiedWidgets.length > 0) { await gfg.customDiscountValidationFunctions.updateCartAttributesWithTotalAmountWithoutFreeGift(cartData); } for(let i=0; i < allUnifiedWidgets?.length; i++){ let unifiedWidgetData = allUnifiedWidgets[i]; if(!unifiedWidgetData || !unifiedWidgetData?.isEnabled){ return; } const isActiveCampaign = gfg.customDiscountValidationFunctions.checkForActiveCampaign(unifiedWidgetData); if (!isActiveCampaign) { continue; } unifiedWidgetData.isUnifiedWidget = true; const isRelevantToCurrentPage = await gfg.customDiscountValidationFunctions.checkCustomDiscountWidgetIsRelevantToCurrentPage(unifiedWidgetData, parent); if (!isRelevantToCurrentPage) { continue; } await gfg.customDiscountValidationFunctions.verifyCustomDiscountRules(unifiedWidgetData, cartData); let gfgDiscountPreparedUI = await gfg.gfgUnifiedWidget.f.gfgUnifiedWidgetPrepareUI(unifiedWidgetData ,cartData, parent); preparedUiArray.push(gfgDiscountPreparedUI) prepredUnifiedWidgetData.push(unifiedWidgetData); } return {preparedUiArray, prepredUnifiedWidgetData}; //gfg.gfgUnifiedWidget.f.insertIntoPageWrapper(preparedUiArray, parent); } catch(err) { gfg.utility.debugConsole("Error inside gfgUnifiedWidget prepareUI fn", err); } }, checkMultipleLanguagePresent: function (data) { try { let keysArr = data ? Object.keys(data) : []; const keysToSkip = ["conditionMetIconUrl", "conditionNotMetIconUrl", "conditionMet" , "showOnWidget"]; keysArr = keysArr.filter((curr) => !keysToSkip.includes(curr)); return keysArr.length > 1; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 checkMultipleLanguagePresent fn", error); } }, getNextConditionNotMetOffer: function(unifiedWidgetData) { try { let rulesList = unifiedWidgetData?.rulesData?.rulesGlobalList[0]?.rulesList; for(let i=0; i${currencySymbol}` ) .replace( "{{DISCOUNT_VALUE}}", `${nextOfferDiscountValue}` ) .replace( "{{REMAINING_AMOUNT}}", `${nextOfferCondtionValue}` ) .replace( "{{REMAINING_QUANTITY}}", `${nextOfferRemainingQuantity}` ) .replace( "{{NEXT_TIER_TITLE}}", `${nextConditionNotMetOfferText}` ); const titleBarUI = this.renderTitleBarUI(titleBarHeading, unifiedWidgetData.styleSettings); gfgUnfiedWgtTopSectionContainer.innerHTML = ""; gfgUnfiedWgtTopSectionContainer.appendChild(titleBarUI); let layoutType = unifiedWidgetData.styleSettings.templateType || "SINGLE_RULE_LAYOUT"; let stepperBarGeneratedUI = null; if (layoutType === "SINGLE_RULE_LAYOUT") { stepperBarGeneratedUI = this.renderSingleRuleProgressBarUI(unifiedWidgetData, cartData); } gfgUnifiedWgtBottomSectionContainer.appendChild(stepperBarGeneratedUI); gfgUnifiedWgtParentContainer.appendChild(gfgUnfiedWgtTopSectionContainer); gfgUnifiedWgtParentContainer.appendChild(gfgUnifiedWgtBottomSectionContainer); return gfgUnifiedWgtParentContainer; } catch (err) { gfg.utility.debugConsole("Error inside gfgUnifiedWidget gfgUnifiedWidgetPrepareUI fn", err); } }, getDiscountTypeIconSvg: function(rule) { try { let offerType = rule?.discountSettings?.type; switch(offerType){ case "DISCOUNT": { return UNIFIED_WIDGET_DISCOUNT_ICON; } case "FREE_GIFT": { return UNIFIED_WIDGET_FREE_GIFT_ICON; } case "SHIPPING_DISCOUNT": { return UNIFIED_WIDGET_SHIPPING_DISCOUNT_ICON; } } } catch(err) { gfg.utility.debugConsole("Error inside gfgUnifiedWidget getDiscountTypeIconSvg fn", err); } }, getIconImageElement: function (rule, ruleIconText) { try { const iconDiv = document.createElement("div"); iconDiv.classList.add("gfgHorizontalStepperProgressBarIcon"); const unifiedWidgetSvgs = [ "UNIFIED_WIDGET_DISCOUNT_ICON", "UNIFIED_WIDGET_FREE_GIFT_ICON", "UNIFIED_WIDGET_SHIPPING_DISCOUNT_ICON" ]; const isIconADefaultSvg = !rule?.discountSettings?.icon || unifiedWidgetSvgs.includes(rule?.discountSettings?.icon?.conditionMetIconUrl); if (isIconADefaultSvg) { const iconSvgString = this.getDiscountTypeIconSvg(rule); const tempContainer = document.createElement('div'); tempContainer.innerHTML = iconSvgString.trim(); iconDiv.appendChild(tempContainer.firstChild); iconDiv.setAttribute("data", ruleIconText.iconFill); const paths = iconDiv.querySelectorAll("path"); paths.forEach((path) => { path.style.fill = ruleIconText.iconFill; }); } else { const iconImg = document.createElement("img"); iconImg.classList.add("gfgHorizontalStepperProgressBarIcon"); iconImg.setAttribute("src", rule.discountSettings.icon.conditionMetIconUrl); iconDiv.appendChild(iconImg); } return iconDiv; } catch (err) { gfg.utility.debugConsole("Error inside gfgUnifiedWidget getIconImageElement fn", err); } }, renderSingleRuleProgressBarUI: function (discountData, cartData) { try { const currLocale = gfg.gfgUnifiedWidget.f.checkMultipleLanguagePresent( discountData.rulesData.rulesGlobalList[0].rulesList[0].discountSettings.title ) ? gfg.utility.getLocale() : "en"; const styleSettings = discountData.styleSettings; const { widgetBodyFontSize, widgetBodyFontWeight, widgetBodyTextColor } = styleSettings; const fontWeightValue = gfg.utility.getFontWeightValue(widgetBodyFontWeight); const rulesList = discountData.rulesData.rulesGlobalList[0].rulesList.filter((curr) => curr); const currencySymbol = gfg.utility.getCurrencySymbol(); const totalRules = rulesList.length; const satisfiedRules = rulesList.filter(rule => rule.conditionMet).length; const progressBarWidth = (satisfiedRules / totalRules) * 100; const iconInProgressFillColor = JSON.parse(JSON.stringify(styleSettings?.iconInProgressFillColor)); const iconSuccessFillColor = JSON.parse(JSON.stringify(styleSettings?.iconSuccessFillColor)); const ruleIconAndTextArr = rulesList.map((curr) => { const isTrue = curr.conditionMet || false; const iconFill = isTrue ? iconSuccessFillColor : iconInProgressFillColor; const iconWrapperBackground = isTrue ? styleSettings?.progressBarSuccessFillColor : styleSettings?.progressBarInProgressFillColor; let text = curr.discountSettings.title[currLocale] || curr.discountSettings.title["en"]; let conditionValue = curr?.ruleValue?.value; const currencyRate = gfg.utility.getActiveCurrencyRate(); conditionValue = conditionValue * currencyRate; text = text.replace("{{CURRENCY}}", currencySymbol) .replace("{{DISCOUNT_VALUE}}", gfg.gfgUnifiedWidget.f.getDiscountValue(discountData, curr)) .replace("{{REMAINING_AMOUNT}}", curr?.ruleValue?.remainingSubtotalValue) .replace("{{CONDITION_VALUE}}", conditionValue); return { iconFill, iconWrapperBackground, text, isTrue }; }); const gfgUnifiedWgtProgressBarIconTextMessageWrapper = document.createElement("div"); gfgUnifiedWgtProgressBarIconTextMessageWrapper.classList.add("gfgUnifiedWgtProgressBarIconTextMessageWrapper"); const gfgHorizontalStepperProgressBarContainer = document.createElement("div"); gfgHorizontalStepperProgressBarContainer.classList.add("gfgHorizontalStepperProgressBarContainer"); const progressBarSuccessFillColor = styleSettings.progressBarSuccessFillColor || "#00BA00"; const progressBarInProgressFillColor = styleSettings.progressBarInProgressFillColor || "#B9B9B9"; const gfgHorizontalStepperProgressBarStickParentContainer = document.createElement("div"); gfgHorizontalStepperProgressBarStickParentContainer.classList.add("gfgHorizontalStepperProgressBarStickParentContainer"); const gfgHorizontalStepperProgressBarStickWrapper = document.createElement("div"); gfgHorizontalStepperProgressBarStickWrapper.classList.add("gfgHorizontalStepperProgressBarStickWrapper"); gfgHorizontalStepperProgressBarStickWrapper.style.backgroundColor = progressBarInProgressFillColor; const gfgHorizontalProgressBar = document.createElement("div"); gfgHorizontalProgressBar.classList.add("gfgHorizontalProgressBar"); gfgHorizontalProgressBar.style.backgroundColor = progressBarSuccessFillColor; gfgHorizontalStepperProgressBarStickWrapper.appendChild(gfgHorizontalProgressBar); gfgHorizontalStepperProgressBarStickParentContainer.appendChild(gfgHorizontalStepperProgressBarStickWrapper); ruleIconAndTextArr.forEach((ruleIconText, index) => { const gfgHorizontalStepperProgressBarItem = document.createElement("div"); gfgHorizontalStepperProgressBarItem.classList.add("gfgHorizontalStepperProgressBarItem"); const iconWrapperBackground = ruleIconText?.iconWrapperBackground; const iconWrapper = document.createElement("div"); iconWrapper.classList.add("gfgHorizontalStepperProgressBarIconWrapper"); iconWrapper.style.backgroundColor = iconWrapperBackground; const iconImg = this.getIconImageElement(rulesList[index], ruleIconText); const textMessage = document.createElement("div"); textMessage.classList.add("gfgHorizontalStepperProgressBarText"); textMessage.style.fontSize = `${widgetBodyFontSize}px`; textMessage.style.fontWeight = fontWeightValue; textMessage.style.color = widgetBodyTextColor; textMessage.innerHTML = ruleIconText.text; iconWrapper.appendChild(iconImg); gfgHorizontalStepperProgressBarItem.appendChild(iconWrapper); gfgHorizontalStepperProgressBarItem.appendChild(textMessage); gfgHorizontalStepperProgressBarContainer.appendChild(gfgHorizontalStepperProgressBarItem); }); gfgHorizontalStepperProgressBarContainer.appendChild(gfgHorizontalStepperProgressBarStickParentContainer); if (rulesList.length == 1) { gfgHorizontalStepperProgressBarContainer.style.display = "grid"; gfgHorizontalStepperProgressBarContainer.style.gridAutoFlow = "column"; gfgHorizontalStepperProgressBarContainer.style.justifyContent = "end"; } if (rulesList.length >= 2) { gfgHorizontalStepperProgressBarContainer.children[0].style.flexGrow = "1"; } if (rulesList.length >= 3) { gfgHorizontalStepperProgressBarContainer.children[1].style.flexGrow = "4"; } if (rulesList.length >= 4) { gfgHorizontalStepperProgressBarContainer.children[0].style.flexGrow = "2"; gfgHorizontalStepperProgressBarContainer.children[2].style.flexGrow = "4"; } gfgUnifiedWgtProgressBarIconTextMessageWrapper.appendChild(gfgHorizontalStepperProgressBarContainer); return gfgUnifiedWgtProgressBarIconTextMessageWrapper; } catch (error) { gfg.utility.debugConsole("Error inside gfgDiscountV2 renderSingleRuleProgressBarUI fn", error); } }, renderTitleBarUI: function (titleBarHeading, styleSettings) { try { const titleBarTextContainer = document.createElement("div"); titleBarTextContainer.classList.add("titleBarTextContainer"); if (titleBarHeading) { const titleBarMainHeading = document.createElement("div"); titleBarMainHeading.classList.add("titleBarMainHeading"); if (styleSettings?.widgetBodyTextColor) { titleBarMainHeading.style.color = styleSettings.widgetBodyTextColor; } titleBarMainHeading.innerHTML = titleBarHeading; titleBarTextContainer.appendChild(titleBarMainHeading); } return titleBarTextContainer; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 renderTitleBarUI function", error); } }, insertIntoPageWrapper: function(preparedDataObj, parent) { try { // Define the selector based on the parent context const gfgUnifiedWidgetWrapperProductEle = gfg.utility.findWrapperElement("UNIFIED", parent, null); // Check if the element exists and has children; if so, clear them if (gfgUnifiedWidgetWrapperProductEle) { Array.from(gfgUnifiedWidgetWrapperProductEle).forEach(element => { while (element.firstChild) { element.removeChild(element.firstChild); } }); } // Check if gfgUnifiedWidgetWrapperProductEle is present // If not, set shouldInitUnifiedDiscountAgain to true and exit if ((!gfgUnifiedWidgetWrapperProductEle || gfgUnifiedWidgetWrapperProductEle.length === 0) && !gfg.f.cutOffshouldInitAgainConditionsForUnifiedAndShipping()) { gfg.state.shouldInitUnifiedDiscountAgain = true; return; } // Append new UI elements preparedDataObj?.preparedUiArray?.forEach((uiElement, index) => { const clone = uiElement.cloneNode(true); // Clone the element Array.from(gfgUnifiedWidgetWrapperProductEle).forEach(element => { element.appendChild(clone); gfg.gfgUnifiedWidget.f.handleDynamicProgressBar( clone, preparedDataObj.prepredUnifiedWidgetData[index], parent ); }); }); } catch (error) { gfg.utility.debugConsole("Error in insertIntoPageWrapper function:", error); } }, handleDynamicProgressBar: function(uiElement, unifiedWidgetData, parent) { try { const cartData = gfg.state.cartData; const currencyRate = gfg.utility.getActiveCurrencyRate(); const satisfiedRules = []; let lastSatisfiedRuleIndex = -1; let lastUnsatisfiedRuleIndex = unifiedWidgetData?.rulesData?.rulesGlobalList[0]?.rulesList?.length; const rulesList = unifiedWidgetData?.rulesData?.rulesGlobalList[0]?.rulesList; for (let i = 0; i < rulesList?.length; i++) { if (rulesList[i]?.conditionMet) { satisfiedRules.push(rulesList[i]); lastSatisfiedRuleIndex = i; } else { lastUnsatisfiedRuleIndex = i; break; } } const gfgHorizontalStepperProgressBarItem = uiElement.querySelectorAll(".gfgHorizontalStepperProgressBarItem"); const gfgHorizontalStepperProgressBarStickWrapper = uiElement.querySelector(".gfgHorizontalStepperProgressBarStickWrapper"); const widthOfLastStepperProgressBarItem = gfgHorizontalStepperProgressBarItem[gfgHorizontalStepperProgressBarItem.length - 1].clientWidth; gfgHorizontalStepperProgressBarStickWrapper.style.width = `calc(100% - ${widthOfLastStepperProgressBarItem / 2}px)`; const gfgHorizontalProgressBar = uiElement.querySelector(".gfgHorizontalProgressBar"); if (lastSatisfiedRuleIndex !== -1) { let totalWidth = 0; for (let i = 0; i < lastSatisfiedRuleIndex; i++) { totalWidth += gfgHorizontalStepperProgressBarItem[i].clientWidth; } totalWidth += gfgHorizontalStepperProgressBarItem[lastSatisfiedRuleIndex].clientWidth / 2; if (rulesList.length === 1) { totalWidth = gfgHorizontalStepperProgressBarStickWrapper.clientWidth; } if (lastUnsatisfiedRuleIndex !== rulesList.length) { let width = gfgHorizontalStepperProgressBarItem[lastSatisfiedRuleIndex].clientWidth / 2; width += lastUnsatisfiedRuleIndex !== rulesList.length - 1 ? gfgHorizontalStepperProgressBarItem[lastUnsatisfiedRuleIndex].clientWidth / 2 : gfgHorizontalStepperProgressBarItem[lastUnsatisfiedRuleIndex].clientWidth / 2; const satisfiedRuleData = rulesList[lastSatisfiedRuleIndex]; const unsatisfiedRuleData = rulesList[lastUnsatisfiedRuleIndex]; let value; let total; if (unifiedWidgetData?.cartRuleType === "cartQuantity") { value = unsatisfiedRuleData?.ruleValue?.value - satisfiedRuleData?.ruleValue?.value; total = gfg.customDiscountValidationFunctions.getQtyOfGivenProductsWithoutFreeGift(cartData.items) - satisfiedRuleData?.ruleValue?.value; } else { value = (unsatisfiedRuleData?.ruleValue?.value - satisfiedRuleData?.ruleValue?.value) * currencyRate; total = gfg.customDiscountValidationFunctions.getAmountOfGivenProductsWithoutFreeGift(cartData.items) - (satisfiedRuleData?.ruleValue?.value * currencyRate); } total = Math.max(total, 0); const pricePercentage = Math.min(Math.round((total / value) * 100), 100); const progressBarWidth = Math.round(width * (pricePercentage / 100)); totalWidth += progressBarWidth; } gfgHorizontalProgressBar.style.width = `${totalWidth}px`; } else { const firstRule = rulesList[0]; let value; let total; if (unifiedWidgetData?.cartRuleType === "cartQuantity") { value = firstRule?.ruleValue?.value; total = gfg.customDiscountValidationFunctions.getQtyOfGivenProductsWithoutFreeGift(cartData.items); } else { value = firstRule?.ruleValue?.value * currencyRate; total = gfg.customDiscountValidationFunctions.getAmountOfGivenProductsWithoutFreeGift(cartData.items); } const width = rulesList.length > 1 ? gfgHorizontalStepperProgressBarItem[0].clientWidth / 2 : gfgHorizontalStepperProgressBarStickWrapper.clientWidth; const pricePercentage = Math.min(Math.round((total / value) * 100), 100); const progressBarWidth = Math.round(width * (pricePercentage / 100)); gfgHorizontalProgressBar.style.width = `${progressBarWidth}px`; } } catch (err) { gfg.utility.debugConsole("Error inside gfgUnifiedWidget handleDynamicProgressBar fn", err); } }, getDiscountValue: function (unifiedWidgetData, nextConditionNotMetOffer) { try { const currencyRate = gfg.utility.getActiveCurrencyRate(); const value = nextConditionNotMetOffer.discountSettings.value; let discountValue = unifiedWidgetData.discountMode === "PERCENTAGE" ? value : (value * currencyRate).toFixed(2); const formattedDiscountValue = discountValue //.endsWith(".00") ? discountValue.slice(0, -3) : discountValue; return formattedDiscountValue; } catch (error) { gfg.utility.debugConsole("Error inside gfgShippingDiscountV2 getDiscountValue fn", error); } }, } } } window.gfg = gfg; let gfgCodeActive = false; document.addEventListener("DOMContentLoaded", function(event) { //do work // check if its bundle builder product execute the rest of the flow gfg.utility.debugConsole("GFG FREE GIFT") if(gfgCodeActive == false){ gfgCodeActive = true; // gfgUtils.f.loadJquery(function (jqueryRefObj) { // gfg.$ = jqueryRefObj; // gfg.f.initialize(gfg.$); // }) gfg.f.initialize(); } }); setTimeout(function(){ try{ if(gfgCodeActive == false){ gfgCodeActive = true; // gfgUtils.f.loadJquery(function (jqueryRefObj) { // gfg.$ = jqueryRefObj; // gfg.f.initialize(gfg.$); // }) gfg.f.initialize(); } }catch(err){ gfg.utility.debugConsole("err before gfg inititalize", err) } }, 3000)