const LOCAL_STORAGE = "tl-cart-goal-local-storage";
class CartGoalEmbed {
constructor(cartGoalRules, giftSVG, discountSVG, freeShippingSVG, currencySymbol, cartTotal, template, defaultImage, showTrademark, productIdMapCollection, displaySettings, translation) {
this.giftSVG = giftSVG;
this.discountSVG = discountSVG;
this.freeShippingSVG = freeShippingSVG;
this.template = template;
this.defaultImage = defaultImage;
this.showTrademark = showTrademark;
this.productIdMapCollection = new Map(productIdMapCollection);
this.currency = currencySymbol;
this.currencyRate = 1;
if (Shopify && Shopify.currency) {
this.currency = Shopify.currency.active;
this.currencyRate = Number(Shopify.currency.rate);
}
this.cartTotal = cartTotal;
this.cartGoal = {};
const listRule = Object.values(cartGoalRules);
for (let i = listRule.length - 1; i >= 0; i--) {
const cartGoalRule = listRule[i];
if (cartGoalRule.status && this.checkActiveDate(cartGoalRule.start_at, cartGoalRule.end_at)) {
this.cartGoal = cartGoalRule;
break;
}
}
if (Object.keys(this.cartGoal).length) {
this.milestones = [];
if (this.cartGoal.milestones) {
this.milestones = this.cartGoal.milestones.map((milestone) => ({
...milestone,
cart_value: milestone.cart_value * this.currencyRate,
reward_value: milestone.discount_type === "decrease_amount" && milestone.reward_type !== this.REWARD_TYPE.FREE_GIFT ? milestone.reward_value * this.currencyRate : milestone.reward_value
}));
}
if (displaySettings && displaySettings.progress_bar) {
this.customColor = displaySettings.progress_bar.progress_bar_style;
this.containerStyle = displaySettings.progress_bar.container_style;
this.sectionRewardStyle = displaySettings.progress_bar.section_reward_style;
this.giftModalStyle = displaySettings.progress_bar.gift_modal_style;
this.cartDrawDisplay = displaySettings.progress_bar.cart_draw_display;
this.cartDisplay = displaySettings.progress_bar.cart_display;
this.currencyFormat = displaySettings.progress_bar.currency_format;
this.currencyDisplay = displaySettings.progress_bar.currency_display;
} else {
this.customColor = this.cartGoal?.color ? JSON.parse(this.cartGoal.color) : this.DEFAULT_STYLE_PROGRESS_BAR;
this.containerStyle = this.cartGoal?.container_style ? JSON.parse(this.cartGoal.container_style) : this.DEFAULT_STYLE_CONTAINER;
this.sectionRewardStyle = this.cartGoal?.section_reward_style ? JSON.parse(this.cartGoal.section_reward_style) : this.DEFAULT_STYLE_SECTION_REWARD;
this.giftModalStyle = this.cartGoal?.gift_modal_style ? JSON.parse(this.cartGoal.gift_modal_style) : this.DEFAULT_STYLE_GIFT_MODAL;
this.cartDrawDisplay = JSON.parse(this.cartGoal.cart_draw_display);
this.cartDisplay = JSON.parse(this.cartGoal.cart_display);
this.currencyFormat = this.cartGoal.currency_format;
this.currencyDisplay = JSON.parse(this.cartGoal.currency_display || "{}");
}
let customTranslation = null;
if (translation) {
const locale = Shopify?.locale || "en";
customTranslation = translation.progress_bar[locale] ? translation.progress_bar[locale] : null;
} else {
let sectionRewardStyle = this.cartGoal?.section_reward_style ? JSON.parse(this.cartGoal.section_reward_style) : this.DEFAULT_STYLE_SECTION_REWARD;
let giftModalStyle = this.cartGoal?.gift_modal_style ? JSON.parse(this.cartGoal.gift_modal_style) : this.DEFAULT_STYLE_GIFT_MODAL;
customTranslation = {
milestone: {
achieve_all: this.cartGoal.achieve_title
},
auto_apply_btn: {
gift: sectionRewardStyle.selected_gifts_button_text,
order_discount: sectionRewardStyle.apply_order_discount_button_text?.applied,
shipping_discount: sectionRewardStyle.apply_shipping_discount_button_text?.applied
},
manual_apply_btn: {
gift: {
before_apply: sectionRewardStyle.select_gifts_button_text,
after_apply: sectionRewardStyle.selected_gifts_button_text
},
order_discount: {
before_apply: sectionRewardStyle.apply_order_discount_button_text?.unapply,
after_apply: sectionRewardStyle.apply_order_discount_button_text?.applied
},
shipping_discount: {
before_apply: sectionRewardStyle.apply_shipping_discount_button_text?.unapply,
after_apply: sectionRewardStyle.apply_shipping_discount_button_text?.applied
}
},
gift_modal: {
title: giftModalStyle.title,
free_text_content: giftModalStyle.free_text_content,
confirm_btn: giftModalStyle.confirm_button_content,
cancel_btn: giftModalStyle.cancel_button_content,
warning_msg: giftModalStyle.warning_message
}
};
}
this.translation = customTranslation ? this.deepMergeObject(this.DEFAULT_TRANSLATION, customTranslation) : this.DEFAULT_TRANSLATION;
this.gifts = [];
this.position = [];
this.cartId = "";
this.isAppliedGiftDc = false;
this.itemIdsInCart = [];
this.giftIdMapPrice = /* @__PURE__ */ new Map();
this.appliedMilestoneIndex = -1;
this.currentGiftMilestoneIndexApplied = -1;
this.isClickButtonConfirm = false;
this.giftCommingAddIds = [];
this.passedMilestone = {
gift: -1,
indexOfPassedFreeGift: -1,
freeShipping: -1,
discount: -1,
lastest: -1
};
this.giftsIdMapQuantityInCart = /* @__PURE__ */ new Map();
this.appliedDiscounts = [];
let url = "/";
if (window.Shopify && window.Shopify.routes) {
url = window.Shopify.routes.root;
}
this.ROOT_SELECTOR_ELEMENT = `form[action='${url}cart']`;
this.ROOT_SELECTOR_POSITION = "afterbegin";
this.discountCode = {
product_discount: JSON.parse(this.cartGoal.product_discount).code,
order_discount: JSON.parse(this.cartGoal.order_discount).code,
shipping_discount: JSON.parse(this.cartGoal.shipping_discount).code
};
if (displaySettings && displaySettings.progress_bar && displaySettings.progress_bar.custom_css && displaySettings.progress_bar.custom_css.trim() !== "") {
this.applyCustomCss(displaySettings.progress_bar.custom_css);
}
this.applyCustomStyle();
this.getCartGoalsMarginValues();
this.initializeLocalStorage();
this.#getStoreAccess();
this.getDataFromAjax().then(() => {
this.getPassedMilestone();
this.renderAllCartGoals();
if (this.cartGoal.auto_remove_gift && this.giftsIdMapQuantityInCart.size && !this.isAppliedGiftDc) {
let cartTotalIncludeGift = this.cartTotal;
this.getPassedMilestone(cartTotalIncludeGift);
}
});
tlCartGoalEmbedOverride();
}
}
PROXY_URL = "apps/salepify";
API_VERSION = "2024-04";
PROPERTY = "_salepify-cart-upsell";
#storeAccessToken;
CART_GOAL_REWARD_STACK = {
ALL_MILESTONES: "all",
ONLY_LASTEST_MILESTONE: "lastest"
};
CART_GOAL_REWARD_TYPE = {
FREE_GIFT: "gift",
CART_DISCOUNT: "discount",
FREE_SHIPPING: "free_ship"
};
DEFAULT_STYLE_PROGRESS_BAR = {
title_label: "#303030",
milestone_label: "#303030",
filled_bar: "#9e58bb",
filter_bar_color: "invert(44%) sepia(24%) saturate(1498%) hue-rotate(238deg) brightness(90%) contrast(81%)"
};
DEFAULT_STYLE_CONTAINER = {
background_color: "#ffffff",
border_color: "#303030",
border_radius: 0,
border_width: 0,
opacity: 1
};
DEFAULT_STYLE_GIFT_MODAL = {
background_color: "#ffffff",
border_color: "#9e58bb",
button_color: "#9e58bb",
check_box_color: "#9e58bb",
free_text_color: "#9e58bb",
border_width: 0,
border_radius: 5
};
DEFAULT_STYLE_SECTION_REWARD = {
button_color: "#9e58bb",
button_selected_color: "#d9cdcd",
hide_claim_reward: false
};
TRIGGER_CONDITION = {
ALL: "all",
COLLECTION: "collection",
PRODUCT: "product"
};
DEFAULT_TRANSLATION = {
milestone: {
achieve_all: "Congratulation! you have achieved all milestones",
gift: {
title: "Free gift",
before_achieve: "You are {{amount}} away from getting {{title}}",
after_achieve: "Congratulations! You have unlocked a reward!"
},
order_discount: {
title: "Cart discount",
before_achieve: "You are {{amount}} away from getting {{title}}",
after_achieve: "Congratulations! You have unlocked a reward!"
},
shipping_discount: {
title: "Shipping discount",
before_achieve: "You are {{amount}} away from getting {{title}}",
after_achieve: "Congratulations! You have unlocked a reward!"
}
},
auto_apply_btn: {
gift: "Reward Claimed",
order_discount: "Reward Claimed",
shipping_discount: "Reward Claimed"
},
manual_apply_btn: {
gift: {
before_apply: "Select gifts",
after_apply: "Selected gifts"
},
order_discount: {
before_apply: "Apply Code",
after_apply: "Applied Code"
},
shipping_discount: {
before_apply: "Apply Code",
after_apply: "Applied Code"
}
},
gift_modal: {
title: "You can choose any {{amount}} rewards",
free_text_content: "Free",
confirm_btn: "Confirm",
cancel_btn: "Cancel",
warning_msg: "Select up to {{amount}} items only"
}
};
applyCustomCss = (custom_css) => {
var styleElement = document.getElementById("tl_custom_css_progress_bar");
if (!styleElement) {
styleElement = document.createElement("style");
styleElement.id = "tl_custom_css_progress_bar";
document.head.appendChild(styleElement);
}
styleElement.innerHTML = custom_css;
};
initializeLocalStorage = () => {
const initialTime = (/* @__PURE__ */ new Date()).getTime() + 24 * 3600 * 1e3;
let initialData = {
gift: -1,
discount: -1,
freeShipping: -1,
appliedDiscounts: [],
selectedGifts: [[]],
expired: initialTime
};
let tlCartGoalLocalStorage = localStorage.getItem(LOCAL_STORAGE);
if (!tlCartGoalLocalStorage || this.cartTotal <= 0) {
localStorage.setItem(LOCAL_STORAGE, JSON.stringify(initialData));
} else {
let tlCartGoalLocalStorageData = JSON.parse(tlCartGoalLocalStorage);
let expiredTime = tlCartGoalLocalStorageData.expired || 0;
if ((/* @__PURE__ */ new Date()).getTime() > expiredTime) {
localStorage.setItem(LOCAL_STORAGE, JSON.stringify(initialData));
} else {
let passedDiscount = tlCartGoalLocalStorageData.discount;
if (passedDiscount !== -1) {
let totalPrice = this.cartTotal;
let discountData = this.milestones?.[passedDiscount];
if (discountData?.discount_type) {
if (discountData.discount_type === "percentage") {
totalPrice = totalPrice / (100 - discountData.reward_value) * 100;
} else {
totalPrice = totalPrice + discountData.reward_value;
}
}
this.cartTotal = totalPrice;
}
this.position = tlCartGoalLocalStorageData.selectedGifts;
this.appliedDiscounts = tlCartGoalLocalStorageData.appliedDiscounts;
this.currentGiftMilestoneIndexApplied = tlCartGoalLocalStorageData.gift;
tlCartGoalLocalStorageData.expired = initialTime;
localStorage.setItem(LOCAL_STORAGE, JSON.stringify(tlCartGoalLocalStorageData));
}
}
};
getCartGoalsMarginValues = () => {
let n = this.milestones.length;
let marginValues = Array(n).fill(0);
marginValues[0] = 10;
marginValues[n - 1] = 99;
let dx = 90 / (n - 1);
for (let i = 1; i < n - 1; i++) {
marginValues[i] = Math.ceil(10 + dx * i);
}
return marginValues;
};
#getStoreAccess = async () => {
const getShopAccessReq = await fetch(window.Shopify.routes.root + `${this.PROXY_URL}/shop`);
const getShopAccessRes = await getShopAccessReq.json();
this.#storeAccessToken = getShopAccessRes.data;
};
getVariantData = async (nonGlobalId) => {
const idBase64 = btoa(`gid://shopify/ProductVariant/${nonGlobalId}`);
try {
const getVariantReq = await fetch(`https://${Shopify.shop}/api/${this.API_VERSION}/graphql.json`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Shopify-Storefront-Access-Token": this.#storeAccessToken
},
body: JSON.stringify({
query: ` query {
node(id: "${idBase64}") {
... on ProductVariant {
product {
id
collections(first: 250){
nodes {
id
}
}
}
}
}
}`
})
});
const getVariantRes = await getVariantReq.json();
if (getVariantRes.data) {
const listCollectionId = [];
getVariantRes.data.node.product.collections.nodes.map((collection) => {
listCollectionId.push(collection.id.split("/").pop());
});
const productId = getVariantRes.data.node.product.id.split("/").pop();
this.productIdMapCollection.set(productId, listCollectionId);
return getVariantRes.data.node;
} else {
return null;
}
} catch (error) {
console.log("Error when getVariantData - Cart Goal: ", error);
}
};
updateCartTotal = () => {
if (Object.keys(this.cartGoal).length) {
fetch("/cart.js").then((res) => res.json()).then(async (data) => {
let ratio = 1;
this.cartId = data.token;
for (let i = 0; i < data.items.length; i++) {
const item = data.items[i];
if (!isNaN(item.price / item.presentment_price)) {
ratio = item.price / item.presentment_price;
break;
}
}
let cartTotal = parseFloat(data.original_total_price) / ratio;
this.itemIdsInCart = [];
let totalAmount = 0;
if (this.cartGoal.trigger_condition == this.TRIGGER_CONDITION.PRODUCT) {
let productsData = JSON.parse(this.cartGoal.trigger_condition_ids);
let productIds = productsData.map((a) => a.shopify_id);
let deductedItemIds = [];
data.items.forEach((item) => {
const itemId = String(item.id);
if (productIds.includes(item.product_id.toString())) {
totalAmount += item.original_line_price / ratio;
if (this.giftsIdMapQuantityInCart.get(itemId) && !deductedItemIds.includes(itemId)) {
totalAmount -= item.price * Number(this.giftsIdMapQuantityInCart.get(itemId)) / ratio;
deductedItemIds.push(itemId);
}
}
this.itemIdsInCart.push(itemId);
});
cartTotal = totalAmount;
} else if (this.cartGoal.trigger_condition == this.TRIGGER_CONDITION.COLLECTION) {
let collectionsData = JSON.parse(this.cartGoal.trigger_condition_ids);
let collectionIds = collectionsData.map((a) => a.shopify_id);
let deductedItemIds = [];
for (let i = 0; i < data.items.length; i++) {
const item = data.items[i];
const itemId = String(item.id);
let collections = this.productIdMapCollection.get(item.product_id.toString());
if (!collections) {
await this.getVariantData(String(item.id));
collections = this.productIdMapCollection.get(item.product_id.toString());
}
if (collections) {
const setCollectionIds = new Set(collectionIds);
if (collections.some((item2) => setCollectionIds.has(item2))) {
totalAmount += item.original_line_price / ratio;
if (this.giftsIdMapQuantityInCart.get(itemId) && !deductedItemIds.includes(itemId)) {
totalAmount -= item.price * Number(this.giftsIdMapQuantityInCart.get(itemId)) / ratio;
deductedItemIds.push(itemId);
}
}
}
this.itemIdsInCart.push(itemId);
}
cartTotal = totalAmount;
} else {
let deductedItemIds = [];
data.items.map((item) => {
const itemId = String(item.id);
if (this.giftsIdMapQuantityInCart.get(itemId) && !deductedItemIds.includes(itemId)) {
cartTotal -= item.price * Number(this.giftsIdMapQuantityInCart.get(itemId)) / ratio;
deductedItemIds.push(itemId);
}
this.itemIdsInCart.push(itemId);
});
}
let giftVariants = this.gifts[this.passedMilestone.indexOfPassedFreeGift];
if (giftVariants) {
this.position[this.passedMilestone.gift] = [];
for (let i = 0; i < giftVariants.length; i++) {
this.itemIdsInCart.forEach((item) => {
if (giftVariants[i].id == item) {
this.position[this.passedMilestone.gift].push(i);
}
});
}
}
this.cartTotal = cartTotal;
this.getPassedMilestone();
this.trackingCartDrawerWhenAddtoCart();
});
this.renderAllCartGoals();
}
};
trackingCartDrawerWhenAddtoCart = () => {
this.updateAllCartGoals();
let targetNode;
const MAX_PARENTS_LEVEL = 2;
let currentLevel = 1;
if (this.cartDrawDisplay.selector) {
targetNode = document.querySelector(this.cartDrawDisplay.selector);
} else {
targetNode = document.querySelector(this.ROOT_SELECTOR_ELEMENT);
}
while (targetNode && currentLevel <= MAX_PARENTS_LEVEL) {
targetNode = targetNode.parentElement;
currentLevel++;
}
const config = { attributes: true, childList: true, subtree: true };
let timeID;
const callback = (mutationList, observer) => {
clearTimeout("timeID", timeID);
if (mutationList.length) {
if (mutationList[0].target.className.includes("tl__cart-goal__gift-modal") || mutationList[0].target.className.includes("tl__cart-goal__check-box")) {
observer.disconnect();
} else {
timeID = setTimeout(() => {
this.updateAllCartGoals();
observer.disconnect();
}, 500);
}
}
};
if (targetNode) {
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
}
};
hexToRgba(hex, alpha) {
hex = hex.replace(/^#/, "");
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha.toFixed(2)})`;
}
applyCustomStyle() {
if (Object.keys(this.customColor).length) {
document.documentElement.style.setProperty("--tl__cart-goal__filled-bar-color", this.customColor.filled_bar);
document.documentElement.style.setProperty("--tl__cart-goal__filter-bar-color", this.customColor.filter_bar_color);
document.documentElement.style.setProperty("--tl__cart-goal__milestone-label-color", this.customColor.milestone_label);
document.documentElement.style.setProperty("--tl__cart-goal__title_label-color", this.customColor.title_label);
}
if (Object.keys(this.containerStyle).length) {
document.documentElement.style.setProperty("--tl__cart-goal__container__background", this.hexToRgba(this.containerStyle.background_color, this.containerStyle?.opacity ? this.containerStyle.opacity : 1));
document.documentElement.style.setProperty("--tl__cart-goal__container__border-color", this.containerStyle.border_color);
document.documentElement.style.setProperty("--tl__cart-goal__container__border-width", `${this.containerStyle.border_width}px`);
document.documentElement.style.setProperty("--tl__cart-goal__container__border-radius", `${this.containerStyle.border_radius}px`);
}
if (Object.keys(this.sectionRewardStyle).length) {
document.documentElement.style.setProperty("--tl__cart-goal__section-reward__button-color", this.sectionRewardStyle.button_color);
document.documentElement.style.setProperty("--tl__cart-goal__section-reward__button-selected-color", this.sectionRewardStyle.button_selected_color);
}
if (Object.keys(this.giftModalStyle).length) {
document.documentElement.style.setProperty("--tl__cart-goal__gift-modal__free-text", this.giftModalStyle.free_text_color);
document.documentElement.style.setProperty("--tl__cart-goal__gift-modal__check-box", this.giftModalStyle.check_box_color);
document.documentElement.style.setProperty("--tl__cart-goal__gift-modal__background", this.giftModalStyle.background_color);
document.documentElement.style.setProperty("--tl__cart-goal__gift-modal__button-color", this.giftModalStyle.button_color);
document.documentElement.style.setProperty("--tl__cart-goal__gift-modal__border-color", this.giftModalStyle.border_color);
document.documentElement.style.setProperty("--tl__cart-goal__gift-modal__border-width", `${this.giftModalStyle.border_width}px`);
document.documentElement.style.setProperty("--tl__cart-goal__gift-modal__border-radius", `${this.giftModalStyle.border_radius}px`);
}
}
getProcessBarWidth = () => {
let marginValues = this.getCartGoalsMarginValues();
let nextMilestone;
let currentMilestone;
for (let i = 0; i < this.milestones.length; i++) {
nextMilestone = i;
if (this.cartTotal <= this.milestones[i].cart_value) {
break;
}
}
currentMilestone = nextMilestone - 1;
if (this.cartTotal >= this.milestones[this.milestones.length - 1].cart_value) {
return marginValues[this.milestones.length - 1];
}
if (currentMilestone > -1) {
let distanceBetweenTwoMilestones = this.milestones[nextMilestone].cart_value - this.milestones[currentMilestone].cart_value;
return marginValues[currentMilestone] + (this.cartTotal - this.milestones[currentMilestone].cart_value) / distanceBetweenTwoMilestones * (marginValues[nextMilestone] - marginValues[currentMilestone]);
} else {
return this.cartTotal / this.milestones[nextMilestone].cart_value * marginValues[nextMilestone];
}
};
getRewardTitleByType = (milestone) => {
let imgSrc, title, beforeAchieve, afterAchieve;
switch (milestone.reward_type) {
case "gift":
imgSrc = this.giftSVG;
title = this.translation.milestone.gift.title;
beforeAchieve = this.replaceVariables(this.translation.milestone.gift.before_achieve, milestone, title);
afterAchieve = this.replaceVariables(this.translation.milestone.gift.after_achieve, milestone, title);
break;
case "discount":
imgSrc = this.discountSVG;
title = this.translation.milestone.order_discount.title;
beforeAchieve = this.replaceVariables(this.translation.milestone.order_discount.before_achieve, milestone, title);
afterAchieve = this.replaceVariables(this.translation.milestone.order_discount.after_achieve, milestone, title);
break;
case "free_ship":
imgSrc = this.freeShippingSVG;
title = this.translation.milestone.shipping_discount.title;
beforeAchieve = this.replaceVariables(this.translation.milestone.shipping_discount.before_achieve, milestone, title);
afterAchieve = this.replaceVariables(this.translation.milestone.shipping_discount.after_achieve, milestone, title);
break;
}
return [title, beforeAchieve, afterAchieve, imgSrc];
};
replaceVariables(string, milestone, title) {
const cartValue = milestone.cart_value;
return string.replace(
/{{discount}}/g,
`${cartValue}
${milestone.discount_type === "percentage" ? `${cartValue}%` : this.formatMoney(cartValue * 100, this.currencyFormat, this.currencyDisplay)}`
).replace(/{{amount}}/g, this.formatMoney((cartValue - this.cartTotal) * 100, this.currencyFormat, this.currencyDisplay)).replace(/{{title}}/g, title);
}
getLeftAmountText = () => {
let milestone = null;
for (let i = 0; i < this.milestones.length; i++) {
if (this.cartTotal < this.milestones[i].cart_value) {
milestone = this.milestones[i];
break;
}
}
if (milestone && this.cartTotal < milestone.cart_value) {
const [title, beforeAchieve, afterAchieve, imgSrc] = this.getRewardTitleByType(milestone);
return beforeAchieve;
} else {
return this.translation.milestone.achieve_all;
}
};
applyDiscountCode = async (discountCode) => {
try {
let applyDiscounts = this.appliedDiscounts;
if (this.cartGoal.reward_stack === this.CART_GOAL_REWARD_STACK.ALL_MILESTONES) {
applyDiscounts.push(discountCode);
applyDiscounts = Array.from(new Set(applyDiscounts));
await fetch(
window.Shopify.routes.root + `${this.PROXY_URL}/cart-goal/apply-discount?cartId=${this.cartId}&discountCodes=${applyDiscounts.join(",")}`
);
} else {
applyDiscounts = [discountCode];
await fetch(`/discount/${discountCode}`);
}
this.appliedDiscounts = applyDiscounts;
} catch (e) {
console.log("Error when apply discount code", e);
}
};
renderAllCartGoals = () => {
let customRootElementCartPage = this.cartDisplay;
let customRootElementCartDraw = this.cartDrawDisplay;
let tlCartGoalLocalStorage = JSON.parse(localStorage.getItem(LOCAL_STORAGE));
if (document.querySelectorAll(".tl__cart-goal__container__drawer")) {
document.querySelectorAll(".tl__cart-goal__container__drawer").forEach((ele) => ele.remove());
}
if (customRootElementCartPage.selector || customRootElementCartDraw.selector) {
if (customRootElementCartPage.selector) {
if (customRootElementCartPage.position === "prepend") {
document.querySelectorAll(customRootElementCartPage.selector).forEach((ele, index) => {
let htmlObject = document.createElement("div");
htmlObject.classList.add("tl-custom-cart-goal-container");
htmlObject.innerHTML = this.renderCartGoal(index);
ele.prepend(htmlObject);
});
} else {
let position = customRootElementCartPage.position === "before" ? "beforebegin" : "afterend";
document.querySelectorAll(customRootElementCartPage.selector).forEach((ele, index) => ele.insertAdjacentHTML(position, this.renderCartGoal(index)));
}
}
if (customRootElementCartDraw.selector) {
let position;
if (customRootElementCartDraw.position === "prepend") {
position = "prepend";
document.querySelectorAll(customRootElementCartDraw.selector).forEach((ele, index) => {
let htmlObject = document.createElement("div");
htmlObject.classList.add("tl-custom-cart-goal-container");
htmlObject.innerHTML = this.renderCartGoal(index);
ele.prepend(htmlObject);
});
} else {
position = customRootElementCartDraw.position === "before" ? "beforebegin" : "afterend";
document.querySelectorAll(customRootElementCartDraw.selector).forEach((ele, index) => ele.insertAdjacentHTML(position, this.renderCartGoal(index)));
}
}
} else {
if (this.cartTotal === 0) {
this.ROOT_SELECTOR_POSITION = "beforebegin";
}
document.querySelectorAll(this.ROOT_SELECTOR_ELEMENT).forEach((ele, index) => {
ele.insertAdjacentHTML(this.ROOT_SELECTOR_POSITION, this.renderCartGoal(index));
});
}
if (this.passedMilestone.gift !== -1) {
tlCartGoalLocalStorage.selectedGifts[this.passedMilestone.gift]?.map((idx) => {
this.renderSelectedGift(this.passedMilestone.gift);
});
}
};
renderCartGoal = (cartGoalIndex) => {
if (document.querySelectorAll(this.ROOT_SELECTOR_ELEMENT).length || this.cartDrawDisplay.selector || this.cartDisplay.selector) {
let milestonesHTMLInCartDrawer = ``;
let closestGoal = -1;
let marginValues = this.getCartGoalsMarginValues();
this.milestones.map((milestone, index) => {
if (closestGoal === -1 && milestone.cart_value > this.cartTotal) {
closestGoal = index;
}
const [milestoneTitle, beforeAchieve, afterAchieve, imgSrc] = this.getRewardTitleByType(milestone);
milestonesHTMLInCartDrawer += `
${this.formatMoney(milestone.cart_value * 100, this.currencyFormat, this.currencyDisplay)}
${milestoneTitle}
`;
});
let trademarkHTMLInCartDrawer = this.showTrademark ? `
Powered by
Salepify App
` : "";
let cartGoalHTMLInCartDrawer = `
${this.getLeftAmountText(this.milestones[closestGoal])}
${milestonesHTMLInCartDrawer}
${this.renderReward(cartGoalIndex)}
${trademarkHTMLInCartDrawer}
`;
return cartGoalHTMLInCartDrawer;
}
};
updateAllCartGoals = () => {
let cartGoalsContainerElements = document.querySelectorAll(".tl__cart-goal__container__drawer");
if (cartGoalsContainerElements.length) {
cartGoalsContainerElements.forEach((ele, index) => {
let rewardsContainer = document.querySelector(`.tl__cart-goal__free-gift-container-${index}`);
if (rewardsContainer) {
rewardsContainer.innerHTML = this.updateCartGoal(index);
}
});
} else {
this.renderAllCartGoals();
}
};
updateCartGoal = (cartGoalIndex) => {
let processBars = document.querySelectorAll(".tl__cart-goal__goal-process__drawer");
processBars.forEach((ele) => {
ele.style.width = `${this.getProcessBarWidth()}%`;
});
let titles = document.querySelectorAll(".tl__cart-goal__reward-description__drawer");
if (titles.length) {
titles.forEach((ele) => ele.innerHTML = `${this.getLeftAmountText()}`);
}
let cartGoalElements = document.querySelectorAll(".tl__cart-goal__goal-check-point__drawer");
let cartGoalImgElements = document.querySelectorAll(".tl__cart-goal__goal-check-point__drawer img");
let cartGoalsValueElement = document.querySelectorAll(".tl__cart-goal__goal-check-point-value");
let cartGoalsTitleElement = document.querySelectorAll(".tl__cart-goal__goal-check-point-title");
let closestPoint = -1;
for (let i = 0; i < this.milestones.length; i++) {
if (closestPoint === -1 && this.milestones[i].cart_value > this.cartTotal) {
closestPoint = i;
}
if (this.cartTotal >= this.milestones[i].cart_value) {
if (cartGoalElements[i]) {
cartGoalElements[i].style.borderColor = "var(--tl__cart-goal__filled-bar-color)";
}
if (cartGoalElements[i + this.milestones.length]) {
cartGoalElements[i + this.milestones.length].style.borderColor = "var(--tl__cart-goal__filled-bar-color)";
}
if (cartGoalImgElements[i]) {
cartGoalImgElements[i].style.filter = "var(--tl__cart-goal__filter-bar-color)";
}
if (cartGoalImgElements[i + this.milestones.length]) {
cartGoalImgElements[i + this.milestones.length].style.filter = "var(--tl__cart-goal__filter-bar-color)";
}
} else {
if (cartGoalElements[i]) {
cartGoalElements[i].style.borderColor = "black";
}
if (cartGoalElements[i + this.milestones.length]) {
cartGoalElements[i + this.milestones.length].style.borderColor = "black";
}
if (cartGoalImgElements[i]) {
cartGoalImgElements[i].style.filter = "invert(0%) sepia(0%) saturate(3%) hue-rotate(177deg) brightness(100%) contrast(100%)";
}
if (cartGoalImgElements[i + this.milestones.length]) {
cartGoalImgElements[i + this.milestones.length].style.filter = "invert(0%) sepia(0%) saturate(3%) hue-rotate(177deg) brightness(100%) contrast(100%)";
}
}
if (cartGoalsValueElement[i]) {
cartGoalsValueElement[i].style.visibility = "";
}
if (cartGoalsValueElement[i + this.milestones.length]) {
cartGoalsValueElement[i + this.milestones.length].style.visibility = "";
}
if (cartGoalsTitleElement[i]) {
cartGoalsTitleElement[i].style.visibility = "";
}
if (cartGoalsTitleElement[i + this.milestones.length]) {
cartGoalsTitleElement[i + this.milestones.length].style.visibility = "";
}
if (closestPoint === i) {
if (cartGoalsValueElement[i]) {
cartGoalsValueElement[i].style.visibility = "visible";
}
if (cartGoalsValueElement[i + this.milestones.length]) {
cartGoalsValueElement[i + this.milestones.length].style.visibility = "visible";
}
if (cartGoalsTitleElement[i]) {
cartGoalsTitleElement[i].style.visibility = "visible";
}
if (cartGoalsTitleElement[i + this.milestones.length]) {
cartGoalsTitleElement[i + this.milestones.length].style.visibility = "visible";
}
}
}
return this.renderReward(cartGoalIndex);
};
showError(message) {
const blockErrors = document.querySelectorAll("#salepify-cart-goal-block-error");
blockErrors.forEach((element) => {
element.style = "display: flex; align-items: center;";
element.innerHTML = `
${message}
`;
});
setTimeout(() => {
blockErrors.forEach((element) => {
element.style = "display: none;";
});
}, "3000");
}
renderShippingReward = () => {
const tlCartGoalLocalStorage = JSON.parse(localStorage.getItem(LOCAL_STORAGE));
const aplliedFreeShipping = tlCartGoalLocalStorage.freeShipping !== -1;
const milestone = this.milestones[this.passedMilestone.freeShipping];
const [title, beforeAchieve, afterAchieve] = this.getRewardTitleByType(milestone);
return `
${this.cartGoal.auto_add_reward ? aplliedFreeShipping ? `
${this.translation.auto_apply_btn.shipping_discount}
` : `` : `
${!aplliedFreeShipping ? `${this.translation.manual_apply_btn.shipping_discount.before_apply}` : `${this.translation.manual_apply_btn.shipping_discount.after_apply}`}
`}
`;
};
renderCartDcReward = () => {
const tlCartGoalLocalStorage = JSON.parse(localStorage.getItem(LOCAL_STORAGE));
const aplliedCartDiscount = tlCartGoalLocalStorage.discount !== -1;
const milestone = this.milestones[this.passedMilestone.discount];
const [title, beforeAchieve, afterAchieve] = this.getRewardTitleByType(milestone);
return `
${this.cartGoal.auto_add_reward ? aplliedCartDiscount ? `
${this.translation.auto_apply_btn.order_discount}
` : `` : `
${!aplliedCartDiscount ? `${this.translation.manual_apply_btn.order_discount.before_apply}` : `${this.translation.manual_apply_btn.order_discount.after_apply}`}
`}
`;
};
renderFreeGiftReward = (cartGoalIndex) => {
const tlCartGoalLocalStorage = JSON.parse(localStorage.getItem(LOCAL_STORAGE));
const passedFreeGift = this.passedMilestone.gift;
const aplliedFreeGift = tlCartGoalLocalStorage.gift >= passedFreeGift;
let giftItemHTML = "";
let giftVariants = this.gifts[this.passedMilestone.indexOfPassedFreeGift];
giftVariants.map((variant, variantIndex) => {
giftItemHTML += `
${variant.name}
${this.formatMoney(variant.price, this.cartGoal.currency_format, this.cartGoal.currency_display)}
${this.translation.gift_modal.free_text_content}
${this.milestones[passedFreeGift].specific_quantity ? "x" + variant.specificQuantity + `${variant.specificQuantity > 1 ? " items" : " item"}` : "x1 item"}
`;
});
const milestone = this.milestones[passedFreeGift];
const [title, beforeAchieve, afterAchieve] = this.getRewardTitleByType(milestone);
return `
${this.cartGoal.auto_add_reward && giftVariants.length ? aplliedFreeGift ? `
${this.translation.auto_apply_btn.gift}
` : `` : `
${aplliedFreeGift ? `${this.translation.manual_apply_btn.gift.after_apply}` : `${this.translation.manual_apply_btn.gift.before_apply}`}
`}
${giftVariants.length !== 0 ? `
${this.translation.gift_modal.title.replace(
"{{amount}}",
`${this.milestones[passedFreeGift].reward_value}`
)}
${giftItemHTML}
${this.translation.gift_modal.cancel_btn}
${this.translation.gift_modal.confirm_btn}
` : `
Sorry, but there's no gift available
${this.translation.gift_modal.cancel_btn}
`}
`;
};
renderReward = (cartGoalIndex) => {
let innerHTML = "";
if (!this.sectionRewardStyle.hide_claim_reward) {
const { ALL_MILESTONES } = this.CART_GOAL_REWARD_STACK;
const { FREE_SHIPPING, FREE_GIFT } = this.CART_GOAL_REWARD_TYPE;
if (this.cartGoal.reward_stack == ALL_MILESTONES) {
const shippingRewardHTML = this.passedMilestone.freeShipping !== -1 ? this.renderShippingReward() : "";
const cartDcRewardHTML = this.passedMilestone.discount !== -1 ? this.renderCartDcReward() : "";
const freeGiftRewardHTML = this.passedMilestone.gift !== -1 ? this.renderFreeGiftReward(cartGoalIndex) : "";
innerHTML = `
${freeGiftRewardHTML}
${cartDcRewardHTML}
${shippingRewardHTML}
`;
} else if (this.passedMilestone.lastest !== -1) {
const lastestMileStoneIdx = this.passedMilestone.lastest;
const lastestMileStone = this.milestones[lastestMileStoneIdx];
innerHTML = lastestMileStone.reward_type == FREE_SHIPPING ? this.renderShippingReward() : lastestMileStone.reward_type == FREE_GIFT ? this.renderFreeGiftReward(cartGoalIndex) : this.renderCartDcReward();
}
}
return innerHTML;
};
getDataFromAjax = async () => {
let cartJsResponse = await fetch("/cart.js");
let cartData = await cartJsResponse.json();
let ratio = 1;
cartData.items.map((item) => {
if (item.price > 0) {
ratio = item.price / item.presentment_price;
}
});
let total = parseFloat(cartData.original_total_price) / ratio;
this.cartId = cartData.token;
cartData.items.forEach((item) => {
let itemId = String(item.id);
let itemQuantity = String(item.quantity);
if (item.original_price == 0 && item.properties[this.PROPERTY]) {
this.isAppliedGiftDc = true;
this.giftsIdMapQuantityInCart.set(itemId, itemQuantity);
} else {
item.discounts.forEach((discount) => {
if (discount.title === this.discountCode.product_discount) {
total -= parseFloat(discount.amount) / ratio;
this.isAppliedGiftDc = true;
this.giftsIdMapQuantityInCart.set(itemId, itemQuantity);
}
});
}
this.itemIdsInCart.push(itemId);
});
let totalAmount = 0;
if (this.cartGoal.trigger_condition == this.TRIGGER_CONDITION.PRODUCT) {
let productsData = JSON.parse(this.cartGoal.trigger_condition_ids);
let productIds = productsData.map((a) => a.shopify_id);
let deductedItemIds = [];
cartData.items.forEach((item) => {
if (productIds.includes(item.product_id.toString())) {
totalAmount += item.original_line_price / ratio;
const itemId = String(item.id);
if (this.giftsIdMapQuantityInCart.get(itemId) && !deductedItemIds.includes(itemId)) {
totalAmount -= item.price * Number(this.giftsIdMapQuantityInCart.get(itemId)) / ratio;
deductedItemIds.push(itemId);
}
}
});
total = totalAmount;
} else if (this.cartGoal.trigger_condition == this.TRIGGER_CONDITION.COLLECTION) {
let collectionsData = JSON.parse(this.cartGoal.trigger_condition_ids);
let collectionIds = collectionsData.map((a) => a.shopify_id);
let deductedItemIds = [];
cartData.items.forEach((item) => {
let collections = this.productIdMapCollection.get(item.product_id.toString());
const setCollectionIds = new Set(collectionIds);
if (collections.some((item2) => setCollectionIds.has(item2))) {
totalAmount += item.original_line_price / ratio;
const itemId = String(item.id);
if (this.giftsIdMapQuantityInCart.get(itemId) && !deductedItemIds.includes(itemId)) {
totalAmount -= item.price * Number(this.giftsIdMapQuantityInCart.get(itemId)) / ratio;
deductedItemIds.push(itemId);
}
}
});
total = totalAmount;
}
this.cartTotal = total;
let milestonesHaveGifts = this.milestones.filter((milestone) => {
return JSON.parse(milestone.gifts).length;
});
let giftsData = milestonesHaveGifts.map((milestone) => JSON.parse(milestone.gifts));
const data = milestonesHaveGifts.map((milestone) => JSON.parse(milestone.gifts));
let listHandle = [];
giftsData.map((arr) => listHandle = [...listHandle, ...arr]);
let formattedGiftsData = [];
listHandle = Array.from(new Set(listHandle.map((item) => item.handle)));
try {
let allGiftVariantsData = await Promise.all(listHandle.map(async (item) => {
let res = await fetch(window.Shopify.routes.root + `products/${item}.js`);
return await res.json();
}));
giftsData.map((gifts, index) => {
formattedGiftsData.push([]);
gifts.map((gift, idx) => {
allGiftVariantsData.map((product) => {
if (gift.handle === product.handle && product.available) {
product.variants.map((variant) => {
if (gift.id.includes(variant.id)) {
this.giftIdMapPrice.set(String(variant.id), variant.price);
variant.specificQuantity = data[index][idx].specificQuantity;
if (!variant.featured_image) {
if (product.featured_image) {
variant.featured_image = product.featured_image.src ? product.featured_image.src : product.featured_image;
} else {
variant.featured_image = this.defaultImage;
}
}
formattedGiftsData[index].push(JSON.parse(JSON.stringify(variant)));
}
});
}
});
});
});
this.gifts = [...formattedGiftsData];
} catch (e) {
console.log("Error when format gifts data:", e);
}
};
getPassedMilestone = async (cartTotal = this.cartTotal) => {
const passedMilestone = {
gift: -1,
indexOfPassedFreeGift: -1,
freeShipping: -1,
discount: -1,
lastest: -1
};
this.milestones.map((milestone, index) => {
if (milestone.cart_value <= cartTotal) {
passedMilestone.lastest = index;
switch (milestone.reward_type) {
case this.CART_GOAL_REWARD_TYPE.FREE_GIFT:
passedMilestone.gift = index;
passedMilestone.indexOfPassedFreeGift++;
break;
case this.CART_GOAL_REWARD_TYPE.CART_DISCOUNT:
passedMilestone.discount = index;
break;
case this.CART_GOAL_REWARD_TYPE.FREE_SHIPPING:
passedMilestone.freeShipping = index;
break;
}
}
});
let tlCartGoalLocalStorage = JSON.parse(localStorage.getItem(LOCAL_STORAGE));
this.passedMilestone = passedMilestone;
if (passedMilestone.discount === -1) {
tlCartGoalLocalStorage.discount = -1;
tlCartGoalLocalStorage.appliedDiscounts = tlCartGoalLocalStorage.appliedDiscounts.splice(
tlCartGoalLocalStorage.appliedDiscounts.indexOf(this.discountCode.order_discount),
1
);
}
if (passedMilestone.freeShipping === -1) {
tlCartGoalLocalStorage.freeShipping = -1;
tlCartGoalLocalStorage.appliedDiscounts = tlCartGoalLocalStorage.appliedDiscounts.splice(
tlCartGoalLocalStorage.appliedDiscounts.indexOf(this.discountCode.shipping_discount),
1
);
}
localStorage.setItem(LOCAL_STORAGE, JSON.stringify(tlCartGoalLocalStorage));
if (tlCartGoalLocalStorage.gift === -1 && this.giftsIdMapQuantityInCart.size || tlCartGoalLocalStorage.gift > passedMilestone.gift) {
if (this.cartGoal.auto_remove_gift) {
const res = await this.handleRemoveGift();
if (res.status == 200) {
if (!window.TLCustomEventCartGoal) {
window.location.reload();
} else if (window.TLCustomEventCartGoal == 1) {
window.dispatchEvent(new CustomEvent("TLCustomEvent:CartGoal-getPassedMilestone"));
}
}
}
} else if (tlCartGoalLocalStorage.gift < passedMilestone.gift) {
this.setLocalStorage("gift", -1);
}
if (this.cartGoal.reward_stack === this.CART_GOAL_REWARD_STACK.ONLY_LASTEST_MILESTONE && this.cartGoal.auto_add_reward) {
if (passedMilestone.discount > -1 || passedMilestone.freeShipping > -1 || passedMilestone.gift > -1) {
if (passedMilestone.discount > passedMilestone.freeShipping && passedMilestone.discount > passedMilestone.gift && tlCartGoalLocalStorage.discount != passedMilestone.discount) {
this.handleApplyDiscountCode();
} else if (passedMilestone.freeShipping > passedMilestone.discount && passedMilestone.freeShipping > passedMilestone.gift && tlCartGoalLocalStorage.freeShipping != passedMilestone.freeShipping) {
this.handleApplyFreeShippingCode();
} else if (passedMilestone.gift > passedMilestone.discount && passedMilestone.gift > passedMilestone.freeShipping && tlCartGoalLocalStorage.gift != passedMilestone.gift) {
this.handleAutoAddGift(passedMilestone.gift);
}
}
} else if (this.cartGoal.reward_stack === this.CART_GOAL_REWARD_STACK.ALL_MILESTONES && this.cartGoal.auto_add_reward) {
if (passedMilestone.discount > -1 && tlCartGoalLocalStorage.discount != passedMilestone.discount) {
await this.handleApplyDiscountCode();
}
if (passedMilestone.freeShipping > -1 && tlCartGoalLocalStorage.freeShipping != passedMilestone.freeShipping) {
await this.handleApplyFreeShippingCode();
}
if (passedMilestone.gift > -1 && tlCartGoalLocalStorage.gift != passedMilestone.gift) {
await this.handleAutoAddGift(passedMilestone.gift);
}
}
};
toggleGifts = (cartGoalIndex, isOpen = true) => {
let selector = `.tl__cart-goal__gift-modal-${cartGoalIndex}`;
let modal = document.querySelector(selector);
if (modal) {
if (isOpen) {
this.renderSelectedGift(this.passedMilestone.gift);
modal.style.display = "block";
this.getQuantitySelected();
} else {
modal.style.display = "none";
}
}
};
renderSelectedGift = (index) => {
let checkBoxes = document.querySelectorAll(`.tl__cart-goal__check-box-${index}`);
checkBoxes.forEach((ele) => ele.classList.remove("tl__cart-goal__check-box--active"));
checkBoxes.forEach((ele) => {
this.itemIdsInCart.forEach((item) => {
if (item == ele.getAttribute("tl__cart-goal_data_id")) {
ele.classList.add("tl__cart-goal__check-box--active");
}
});
});
this.position[this.passedMilestone.gift] = [];
for (let i = 0; i < this.gifts[this.passedMilestone.indexOfPassedFreeGift].length; i++) {
this.itemIdsInCart.forEach((item) => {
if (item == this.gifts[this.passedMilestone.indexOfPassedFreeGift][i].id) {
this.position[this.passedMilestone.gift].push(i);
}
});
}
};
getQuantitySelected = () => {
let countQuantity = 0;
let giftsData = JSON.parse(this.milestones[this.passedMilestone.gift].gifts);
const selectedQuantitys = document.querySelectorAll(".tl_selected_quantity");
this.position[this.passedMilestone.gift] = Array.from(new Set(this.position[this.passedMilestone.gift]));
this.position[this.passedMilestone.gift].map((item) => {
countQuantity += giftsData[item].specificQuantity ? giftsData[item].specificQuantity : 1;
});
selectedQuantitys.forEach((element) => {
if (countQuantity > this.milestones[this.passedMilestone.gift].reward_value) {
element.style = "border-radius: 40%; padding: 3px; background: #E8E7EC; font-weight: 600; color: red";
} else {
element.style = "border-radius: 40%; padding: 3px; background: #E8E7EC; font-weight: 600; color: black";
}
element.innerHTML = `${countQuantity}/${this.milestones[this.passedMilestone.gift].reward_value}`;
});
};
handleChangeGift = (index, variantIndex) => {
if (!this.position[index]) {
this.position[index] = [];
}
let existedIndex = this.position[index].indexOf(variantIndex);
if (existedIndex !== -1) {
this.position[index].splice(existedIndex, 1);
} else {
this.position[index].push(variantIndex);
}
let selectedBoxs = document.querySelectorAll(`.tl__cart-goal__check-box-${index}-${variantIndex}`);
selectedBoxs.forEach((ele) => {
if (ele.classList.contains("tl__cart-goal__check-box--active")) {
ele.classList.remove("tl__cart-goal__check-box--active");
} else {
ele.classList.add("tl__cart-goal__check-box--active");
}
});
this.getQuantitySelected();
};
handleAutoAddGift = async (index) => {
try {
const items = [];
let giftsData = JSON.parse(this.milestones[index].gifts);
giftsData.forEach((gift) => {
const itemId = gift.id.split("/")[4];
items.push({
"id": itemId,
"quantity": this.milestones[index].specific_quantity ? gift.specificQuantity : 1,
"properties": !gift.price ? { [this.PROPERTY]: this.cartGoal.name } : void 0
});
});
if (this.currentGiftMilestoneIndexApplied !== -1 && this.currentGiftMilestoneIndexApplied !== index) {
await this.handleRemoveGift();
}
if (items.length && this.gifts[this.passedMilestone.indexOfPassedFreeGift].length) {
await this.applyDiscountCode(this.discountCode.product_discount);
await fetch(window.Shopify.routes.root + "cart/add.js?app=salepify", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"items": items
})
});
this.setLocalStorage("gift", index);
if (!window.TLCustomEventCartGoal) {
window.location.reload();
} else if (window.TLCustomEventCartGoal == 1) {
window.dispatchEvent(new CustomEvent("TLCustomEvent:CartGoal-handleAutoAddGift"));
}
}
} catch (e) {
console.log("Error when auto add to cart", e);
}
};
handleAddtoCart = async (milestoneIndex, cartGoalIndex) => {
try {
const buttons = document.querySelectorAll(".tl__cart-goal__button-add-gift");
buttons.forEach((ele) => {
ele.innerHTML = ``;
ele.onclick = null;
});
let giftsData = JSON.parse(this.milestones[this.passedMilestone.gift].gifts);
let countQuantity = 0;
const items = [];
const listItemsIds = [];
this.position[this.passedMilestone.gift] = Array.from(new Set(this.position[this.passedMilestone.gift]));
this.position[this.passedMilestone.gift].map((item) => {
countQuantity += giftsData[item].specificQuantity ? giftsData[item].specificQuantity : 1;
});
let listSelected = document.querySelectorAll(`.tl__cart-goal__gift-modal-${cartGoalIndex} .tl__cart-goal__check-box--active`);
listSelected.forEach((ele) => {
if (ele.getAttribute("tl__cart-goal_data_id")) {
listItemsIds.push(ele.getAttribute("tl__cart-goal_data_id"));
}
});
this.position[milestoneIndex] = [];
listItemsIds.forEach((itemId) => {
for (let i = 0; i < giftsData.length; i++) {
if (giftsData[i].id.split("/")[4] == itemId) {
this.position[milestoneIndex].push(i);
}
}
});
this.position[milestoneIndex].map((item) => {
const itemId = giftsData[item].id.split("/")[4];
items.push({
"id": itemId,
"quantity": this.milestones[this.passedMilestone.gift].specific_quantity ? giftsData[item].specificQuantity : 1,
"properties": !item.price ? { [this.PROPERTY]: this.cartGoal.name } : void 0
});
});
if (countQuantity <= this.milestones[this.passedMilestone.gift].reward_value) {
await this.handleRemoveGift();
await this.applyDiscountCode(this.discountCode.product_discount);
if (items.length) {
await fetch(window.Shopify.routes.root + "cart/add.js?app=salepify", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"items": items
})
});
}
this.setLocalStorage("gift", milestoneIndex);
if (!window.TLCustomEventCartGoal) {
window.location.reload();
} else if (window.TLCustomEventCartGoal == 1) {
window.dispatchEvent(new CustomEvent("TLCustomEvent:CartGoal-handleAddtoCart"));
}
} else {
this.showError(this.translation.gift_modal.warning_msg.replace("{{amount}}", `${this.milestones[this.passedMilestone.gift].reward_value}`));
const passedFreeGift = this.passedMilestone.gift;
buttons.forEach((ele) => {
ele.innerHTML = this.translation.gift_modal.confirm_btn;
ele.onclick = function() {
window.tlCartGoalEmbed.handleAddtoCart(passedFreeGift, cartGoalIndex);
this.isClickButtonConfirm = true;
};
});
}
} catch (e) {
console.log("Error when add to cart", e);
}
};
handleRemoveGift = async () => {
try {
if (this.giftsIdMapQuantityInCart.size) {
let cartDataReq = await fetch("/cart.js");
let cartDataRes = await cartDataReq.json();
const updates = {};
let deductedQuantities = /* @__PURE__ */ new Map();
for (let i = 0; i < cartDataRes.items.length; i++) {
const item = cartDataRes.items[i];
const giftId = String(item.id);
if (this.giftsIdMapQuantityInCart.get(giftId)) {
const quantityInCart = this.giftsIdMapQuantityInCart.get(giftId);
if (quantityInCart) {
const alreadyDeducted = deductedQuantities.get(giftId) || 0;
const remainingToDeduct = quantityInCart - alreadyDeducted;
if (remainingToDeduct > 0) {
const quantityToDeduct = Math.min(item.quantity, remainingToDeduct);
updates[item.key] = item.quantity - quantityToDeduct;
deductedQuantities.set(giftId, alreadyDeducted + quantityToDeduct);
}
}
}
}
this.itemIdsInCart = [];
this.giftsIdMapQuantityInCart = /* @__PURE__ */ new Map();
this.setLocalStorage("gift", -1);
return await fetch(window.Shopify.routes.root + "cart/update.js?app=salepify", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ updates })
});
}
} catch (error) {
console.log("Error when handleRemoveGift: ", error);
}
};
handleApplyDiscountCode = async () => {
try {
let selector = ".tl-cart-goal-apply-discount-code-btn__cart-drawer";
document.querySelectorAll(selector).forEach((ele) => {
ele.innerHTML = `
`;
ele.style.pointerEvents = "none";
});
await this.applyDiscountCode(this.discountCode.order_discount);
if (this.cartGoal.reward_stack === this.CART_GOAL_REWARD_STACK.ONLY_LASTEST_MILESTONE) {
await this.handleRemoveGift();
}
this.setLocalStorage("discount", this.passedMilestone.discount);
if (!window.TLCustomEventCartGoal) {
window.location.reload();
} else if (window.TLCustomEventCartGoal == 1) {
window.dispatchEvent(new CustomEvent("TLCustomEvent:CartGoal-handleApplyDiscountCode"));
}
} catch (e) {
console.log("Error when apply discount code", e);
}
};
handleApplyFreeShippingCode = async () => {
try {
let selector = ".tl-cart-goal-apply-free-shipping-btn__cart-drawer";
document.querySelectorAll(selector).forEach((ele) => {
ele.innerHTML = `
`;
ele.style.pointerEvents = "none";
});
if (this.cartGoal.reward_stack === this.CART_GOAL_REWARD_STACK.ONLY_LASTEST_MILESTONE) {
await this.handleRemoveGift();
}
this.setLocalStorage("freeShipping", this.passedMilestone.freeShipping);
this.renderAllCartGoals();
} catch (e) {
console.log("Error when apply free shipping code", e);
}
};
setLocalStorage = (type, milestoneIndex) => {
let tlCartGoalLocalStorage = JSON.parse(localStorage.getItem(LOCAL_STORAGE));
if (this.cartGoal.reward_stack === this.CART_GOAL_REWARD_STACK.ONLY_LASTEST_MILESTONE && milestoneIndex !== -1) {
tlCartGoalLocalStorage.discount = -1;
tlCartGoalLocalStorage.freeShipping = -1;
tlCartGoalLocalStorage.gift = -1;
}
switch (type) {
case "gift":
tlCartGoalLocalStorage.gift = milestoneIndex;
tlCartGoalLocalStorage.selectedGifts = this.position;
if (milestoneIndex == -1) {
tlCartGoalLocalStorage.appliedDiscounts = tlCartGoalLocalStorage.appliedDiscounts.splice(
tlCartGoalLocalStorage.appliedDiscounts.indexOf(this.discountCode.product_discount),
1
);
}
break;
case "discount":
tlCartGoalLocalStorage.discount = milestoneIndex;
break;
case "freeShipping":
tlCartGoalLocalStorage.freeShipping = milestoneIndex;
break;
}
tlCartGoalLocalStorage.appliedDiscounts = this.appliedDiscounts;
localStorage.setItem(LOCAL_STORAGE, JSON.stringify(tlCartGoalLocalStorage));
};
isJson(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
deepMergeObject(a, b) {
const result = { ...a };
for (const key in b) {
if (b.hasOwnProperty(key)) {
if (a && typeof a[key] === "object" && typeof b[key] === "object" && !Array.isArray(a[key])) {
result[key] = this.deepMergeObject(a[key], b[key]);
} else if (b[key] !== void 0) {
result[key] = b[key];
}
}
}
return result;
}
formatMoney = function(t, currencyFormat, currencyDisplay) {
const regex = /\{\{amount\}\}/;
var e;
if (currencyDisplay?.[this.currency]?.display_format && regex.test(currencyDisplay[this.currency].display_format)) {
e = currencyDisplay[this.currency].display_format.replace("{{amount}}", currencyFormat ? `{{${currencyFormat}}}` : "{{amount_with_period_and_space_separator}}");
} else {
e = currencyFormat ? `{{${currencyFormat}}}${this.currency}` : `{{amount_with_period_and_space}}${this.currency}`;
}
function n(t2, e2) {
return void 0 === t2 ? e2 : t2;
}
function o(t2, e2, o2, i2) {
if (e2 = n(e2, 2), o2 = n(o2, ","), i2 = n(i2, "."), isNaN(t2) || null == t2)
return 0;
var r2 = (t2 = (t2 / 100).toFixed(e2)).split(".");
return r2[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1" + o2) + (r2[1] ? i2 + r2[1] : "");
}
"string" == typeof t && (t = t.replace(".", ""));
var i = "", r = /\{\{\s*(\w+)\s*\}\}/, a = e || this.money_format;
switch (a.match(r)[1]) {
case "amount":
i = o(t, 2);
break;
case "amount_no_decimals":
i = o(t, 0);
break;
case "amount_with_comma_separator":
i = o(t, 2, ".", ",");
break;
case "amount_with_space_separator":
i = o(t, 2, " ", ",");
break;
case "amount_with_period_and_space_separator":
i = o(t, 2, " ", ".");
break;
case "amount_no_decimals_with_comma_separator":
i = o(t, 0, ".", ",");
break;
case "amount_no_decimals_with_space_separator":
i = o(t, 0, " ");
break;
case "amount_with_apostrophe_separator":
i = o(t, 2, "'", ".");
}
return a.replace(r, i);
};
checkActiveDate = (startAt, endAt) => {
let activeDate = false;
if (new Date(startAt) <= /* @__PURE__ */ new Date()) {
if (endAt) {
if (new Date(endAt) > /* @__PURE__ */ new Date()) {
activeDate = true;
}
} else {
activeDate = true;
}
}
return activeDate;
};
checkGiftsInCart = async (cartData, lineChangeIndex, quantity) => {
this.giftsIdMapQuantityInCart = /* @__PURE__ */ new Map();
cartData.items.forEach((item, index) => {
if (index === lineChangeIndex && quantity === 0) {
this.setLocalStorage("gift", -1);
return;
}
let itemId = String(item.id);
let itemQuantity = String(item.quantity);
if (item.original_price == 0 && item.properties[this.PROPERTY]) {
this.giftsIdMapQuantityInCart.set(itemId, itemQuantity);
} else {
item.discounts.forEach((discount) => {
if (discount.title === this.discountCode.product_discount) {
if (index === lineChangeIndex && quantity > 0) {
itemQuantity = String(quantity);
}
this.giftsIdMapQuantityInCart.set(itemId, itemQuantity);
}
});
}
});
};
}
const tlCartGoalEmbedOverride = function() {
if (!window || !window.Shopify)
return;
const CartEvents = {
add: "TLCARTGOAL:add",
update: "TLCARTGOAL:update",
change: "TLCARTGOAL:change",
clear: "TLCARTGOAL:clear",
mutate: "TLCARTGOAL:mutate"
};
const ShopifyCartURLs = [
"/cart/add",
"/cart/update",
"/cart/change",
"/cart/clear",
"/cart/add.js",
"/cart/update.js",
"/cart/change.js",
"/cart/clear.js",
"/cart/add.js?upcart=1&opens_cart=maybe"
];
function isShopifyCartURL(url) {
if (url instanceof URL)
url = url.href;
if (typeof url == "object" && url.url)
url = url.url;
if (!url)
return false;
try {
let path = url.split("/").pop();
path = path.split("?").shift();
return ShopifyCartURLs.includes(`/cart/${path}`);
} catch (e) {
console.log("Not a normal URL: ", e);
return false;
}
}
function updateType(url) {
if (!url || url.includes("app=salepify"))
return false;
if (url.includes("cart/add")) {
return "add";
} else if (url.includes("cart/update")) {
return "update";
} else if (url.includes("cart/change")) {
return "change";
} else if (url.includes("cart/clear")) {
return "clear";
} else
return false;
}
function dispatchEvent(url, detail) {
if (typeof detail === "string") {
try {
detail = JSON.parse(detail);
} catch {
}
}
window.dispatchEvent(new CustomEvent(CartEvents.mutate, { detail }));
const type = updateType(url);
switch (type) {
case "add":
window.dispatchEvent(new CustomEvent(CartEvents.add, { detail }));
break;
case "update":
window.dispatchEvent(new CustomEvent(CartEvents.update, { detail }));
break;
case "change":
window.dispatchEvent(new CustomEvent(CartEvents.change, { detail }));
break;
case "clear":
window.dispatchEvent(new CustomEvent(CartEvents.clear, { detail }));
break;
}
}
function XHROverride() {
if (!window.XMLHttpRequest)
return;
const originalOpen = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function() {
const url = arguments[1];
this.addEventListener("load", function() {
if (isShopifyCartURL(url)) {
dispatchEvent(url, this.response);
}
});
return originalOpen.apply(this, arguments);
};
}
function fetchOverride() {
if (!window.fetch || typeof window.fetch !== "function")
return;
const originalFetch = window.fetch;
window.fetch = async function() {
let [resource, config] = [...arguments];
const response = originalFetch.apply(this, arguments);
if (isShopifyCartURL(arguments[0])) {
const cartDataReq = await originalFetch("/cart.js", {
method: "GET",
headers: {
"Content-Type": "application/json"
}
});
const cartDataRes = await cartDataReq.json();
isChangeCartLine = true;
let items = JSON.parse(JSON.stringify(cartDataRes.items));
let lineChangeIndex = null;
let quantity = 1;
if (!resource.includes("add")) {
const bodyArgument = JSON.parse(config.body);
let newLineQty = Number(bodyArgument.quantity);
if (bodyArgument.line) {
lineChangeIndex = Number(bodyArgument.line) - 1;
} else if (bodyArgument.id) {
items.map((item, index) => {
if (item.key === bodyArgument.id) {
lineChangeIndex = index;
}
});
} else if (bodyArgument.updates) {
const updates = bodyArgument.updates;
items.map((item, index) => {
if (updates[item.key] === item.quantity !== Number(updates[item.key])) {
lineChangeIndex = index;
newLineQty = Number(updates[item.key]);
}
});
}
quantity = newLineQty;
await window.tlCartGoalEmbed.checkGiftsInCart(cartDataRes, lineChangeIndex, quantity);
}
response.then((res) => {
res.clone().json().then((data) => dispatchEvent(res.url, data));
});
}
return response;
};
}
window.addEventListener("TLCARTGOAL:add", (event) => {
window.tlCartGoalEmbed.updateCartTotal();
});
window.addEventListener("TLCARTGOAL:change", (event) => {
window.tlCartGoalEmbed.updateCartTotal();
});
window.addEventListener("TLCARTGOAL:update", (event) => {
window.tlCartGoalEmbed.updateCartTotal();
});
fetchOverride();
XHROverride();
};
window.tlCartGoalEmbed = window.tlCartGoalEmbed || new CartGoalEmbed(
tlCartGoalRules,
tlCartGoalGiftSVG,
tlCartGoalDiscountSVG,
tlCartGoalFreeShippingSVG,
tlCartGoalCurrencySymbol,
tlCartGoalCartTotal,
tlCartGoalTemplate,
tlCartGoalDefaultImage,
tlCartGoalShowTrademark,
tlCartGoalProductIdMapCollection,
tlCartGoalDisplaySetting,
tlCartGoalTranslation
);