โจMatching Gift Brand Packaging Box๐
โจMatching Gift Brand Packaging Box๐
lockme tender LV bag Apple iPhone wallet cases fashion
lockme tender LV bag Apple iPhone wallet cases fashion
โจ THE COLLECTOR'S PRIVILEGE
Elevate your daily aesthetic across our entire store.
${(function () {
const automatic_discount_list = originData.automatic_discount_list;
// ๆพ็คบ็ฑปๅ
const DISPLAY_TYPE = {
DTE_FOLD: 'DTE_FOLD', // ๆๅ
DTE_TILE: 'DTE_TILE' // ๅนณ้บ
}
const DEFAULT_CONFIG = {
BG: 'rgba(235, 57, 27, 0.04)',
TEXT_COLOR: '#EB391B',
BORDER_COLOR: 'rgb(235, 57, 27)',
ADD_TO_CART_BG: 'transparent',
ADD_TO_CART_TEXT_COLOR: 'rgb(235, 57, 27)',
ADD_TO_CART_BORDER_COLOR: 'rgb(235, 57, 27)',
};
// ๆฌๅฐ่ทณ่ฝฌๅคๅฎ(ไธไพ่ตๅ
จๅฑ appDiscountUtils,ๆจกๆฟๆฒ็ฎฑไธๅฏ่ง)
const __resolveHref = (s, landing) => {
if (!s || !s.is_redirection) return '';
const link = typeof s.link === 'string' ? s.link.trim() : '';
if (link && /^https?:\/\//i.test(link)) return link;
return landing || '';
};
const isExist = automatic_discount_list?.length > 0 && automatic_discount_list.some(item => item.discount[0].product_enabled);
// ๅฆๆๆฒกๆไปปไฝ่ชๅจๆๆฃ๏ผๅ้่๏ผ้ฒๆญขgapๅ ไฝ
if (!isExist) {
return `
`;
} else {
return `
${(function () {
return automatic_discount_list.map((item) => {
// ๆจก็็ฑปๅ
const template_type = item.discount[0].template_type;
// ๆฏๅฆๆพ็คบ่ชๅจๆๆฃ
const is_show_automatic_discount = item.discount[0].product_enabled;
// ๆๆฃๅพๆ
const discount_icon = item.discount_icon;
// ็ฌฌไธไธช่ชๅจๆๆฃ
const first_automatic_discount = item.discount[0];
// ๆพ็คบๆๅ ๅฑ็คบ
const isFold = (item.discount[0].display_type || DISPLAY_TYPE.DTE_FOLD) === DISPLAY_TYPE.DTE_FOLD;
// ๆๆฌๆฐ็ป
const text_arr = item.discount[0].config.texts;
// ๆกไปถๅผๆฐ็ป
const condition_values = item?.discount[0]?.condition_values || [];
// ่ฝๅฐ้กต้พๆฅ
const first_landing_url = `/promotions/discount-default/${first_automatic_discount.discount_id}`;
// ไธๆฎตๅผ่ทณ่ฝฌๅณ็ญ: ๆ็ป่ทณ่ฝฌ URL,็ฉบๅญ็ฌฆไธฒ่กจ็คบไธ่ทณ
const finalHref = __resolveHref(first_automatic_discount, first_landing_url);
// ่ชๅจๆๆฃๆปๆฐ
const automatic_discount_total = item.discount.length;
// ๆฏๅฆๆพ็คบๆๆฃๅพๆ
const isHasDiscountIcon = discount_icon ? true : false;
// ๆฏๅฆๆพ็คบๆๆฃๅพๆ ไธๆจก็็ฑปๅไธไธบtagๅadd_to_cart
const isHasDiscountIconWithNoTag = (template_type != 'tag' && template_type != 'add_to_cart' && isHasDiscountIcon)? true : false;
// ๆๆฌ้ข่ฒ
let text_color = DEFAULT_CONFIG.TEXT_COLOR;
// ่ๆฏ้ข่ฒ
const bgFn = (curBg) => template_type === "text" ? "transparent" : curBg;
let bg_color = bgFn(DEFAULT_CONFIG.BG);
// ่พนๆก้ข่ฒ
const borderFn = (curBorder) => template_type == "tag" ? curBorder : "initial";
let border_color = borderFn(DEFAULT_CONFIG.BORDER_COLOR);
// ๆจก็้
็ฝฎ
let template_config = first_automatic_discount.template_config;
// ไธ้ฎๅ ่ดญๆ ทๅผ
let addToCartBtnBgColor = DEFAULT_CONFIG.ADD_TO_CART_BG;
let addToCartBtnTextColor = DEFAULT_CONFIG.ADD_TO_CART_TEXT_COLOR;
let addToCartBtnBorderColor = DEFAULT_CONFIG.ADD_TO_CART_BORDER_COLOR;
// ๅ
ๅบๆนๆก
try {
if(template_config.length !== 0){
template_config = JSON.parse(template_config);
text_color= isHasDiscountIconWithNoTag ? template_config.color[template_type].icon_text_color : template_config.color[template_type].text_color;
bg_color = bgFn(template_config.color[template_type].background_color);
const arrayRgba = bg_color.split(",");
arrayRgba.splice(3, 1, " 1)");
border_color = borderFn(`${arrayRgba.join(",")}`);
addToCartBtnTextColor = template_config.color[template_type].button_text_color;
addToCartBtnBorderColor = template_config.color[template_type].button_border_color;
addToCartBtnBgColor = template_config.color[template_type].button_background_color;
}
} catch (error) {
console.error('template_config_error', error);
template_config = {
color: {
[template_type]: {
icon_text_color: DEFAULT_CONFIG.TEXT_COLOR,
text_color: DEFAULT_CONFIG.TEXT_COLOR,
background_color: DEFAULT_CONFIG.BG
}
}
};
}
// ๆ ็ญพ
const isTag = template_type == 'tag';
// ๆๅญๅๆจชๅน
const isTextAndBanner = template_type == 'text' || template_type == 'banner';
// ๆฏๅฆไธ้ฎๅ ่ดญ
const isAddToCart = template_type == 'add_to_cart';
// ๆๅญๆ ทๅผ
const textStyle = `color: ${text_color}; background-color: transparent; border: none;`;
// ๆ ็ญพๆ ทๅผ
const labelStyle = `color: ${text_color};border: 1px solid ${border_color};background-color:${bg_color};padding: 4px;`;
// ๆจชๅน
ๆ ทๅผ
const bannerStyle = `color: ${text_color};border: none; background-color:${bg_color}`;
// ไธ้ฎๅ ่ดญๅไธชๅฎนๅจๆ ทๅผ๏ผๅชๅ
ๅซๅจๆๆ ทๅผ๏ผ
const addToCartSingleContainerStyle = `color: ${text_color}; background-color:${bg_color};`;
// ไธ้ฎๅ ่ดญๆ้ฎๆ ทๅผ๏ผๅชๅ
ๅซ้
็ฝฎ็ๅจๆๆ ทๅผ๏ผ
const addToCartBtnStyle = `color: ${addToCartBtnTextColor}; background-color:${addToCartBtnBgColor}; border:1px solid ${addToCartBtnBorderColor};`;
// ๅคๅฑๆ ทๅผๅจๆ ็ญพๆ ทๅผไธไธๅฑ็คบ้ข่ฒ้
็ฝฎ๏ผ้คๅผๆ ็ญพ็ฑปๅ๏ผ้ข่ฒ้ฝๅฏไปฅๅจๅคๅฑ่ฆ็
let outerStyle = '';
if (template_type == 'text') {
outerStyle = textStyle;
} else if (template_type == 'tag') {
outerStyle = "border: none;";
} else if (template_type == 'banner') {
outerStyle = bannerStyle;
}
/**
* 1. ๆ ็ญพไธๅฎๆฏๅ็ฌๆ ทๅผๅฑ็คบ็
* 2. ๆๅ ๏ผๆจชๅๅธๅฑ๏ผๆๅญๅๆจชๅน
๏ผๅๅนถๆไธ่กๆๆฌ๏ผ ๆ ็ญพ๏ผๅ็ฌๆ ทๅผๅค็
* 3. ๅนณ้บ๏ผ็บตๅๅธๅฑ๏ผๆๅญใๆจชๅน
ๅๆ ็ญพ๏ผ ๆ ็ญพ๏ผๅ็ฌๆ ทๅผๅค็๏ผไธ้ฎๅ ่ดญ้ป่ฎค้ฝๆฏๅนณ้บ
*/
let txtHtml = ``;
if (isFold) {
if(isTag) {
// ๆ ็ญพ
const spanText = text_arr.map((text) => {
return `
${text}`;
}).join('');
txtHtml = `
${spanText}
`;
} else {
// ๆๅญๅๆจชๅน
txtHtml = `
${first_automatic_discount.config.text}
`;
}
} else {
// ๆๅญๅๆจชๅน
, ไฝๆ ็ญพๆ่ชๅทฑ็ๆ ทๅผ๏ผไธไธ้ฎๅ ่ดญๆๅ็ฌๆ ทๅผ
const spanText = text_arr.map((text, index) => {
const condition_value = condition_values[index];
if(isAddToCart) {
return `
${text}
`
} else {
return `
${text}`;
}
}).join('');
// ้ฝๆฏ็บตๅๅธๅฑ๏ผๆ ็ญพๆ้ด่ท
txtHtml = `
${spanText}
`;
}
/**
* ๆพ็คบๅพๆ ็ๅคๆญ
*/
const discount_type = item.discount_type;
const isShowRebateIcon = ["DT_REBATE_CTQ_OTP", "DT_REBATE_CTQ_OTR", "DT_REBATE_CTA_OTP", "DT_REBATE_CTA_OTR", "DT_M_N_DISCOUNT"].includes(discount_type) && isTextAndBanner
const isShowBxgyIcon = ["DT_BUY_ONE_GET_ONE", "DT_BUY_X_GET_Y"].includes(discount_type)
const isShowBundleIcon = ["DT_CLASSIC_BUNDLE","DT_MIX_MATCH_BUNDLE"].includes(discount_type);
/**
* ๆธฒๆไธๆๆกๆๆฝๅฑ็ๆๆฃๅ่กจ
*/
const discount_list_html = (curItem) => {
return `
${function() {
return curItem.discount.map(childItem => {
const childLandingUrl = `/promotions/discount-default/${childItem.discount_id}`;
const childFinalHref = __resolveHref(childItem, childLandingUrl);
childItem.__finalHref = childFinalHref;
return childFinalHref
? `
`
: `
`;
}).join('');
}()}
`;
}
return `
${txtHtml}
${finalHref ? `
` : ''}
${discount_list_html(item)}
${function() {
return text_arr.map((text) => {
return `
${text}
`;
}).join('');
}()}
`;
}).join('');
})()}
`
}
})()}
const TAG = "spz-custom-product-automatic";
class SpzCustomProductAutomatic extends SPZ.BaseElement {
constructor(element) {
super(element);
this.variant_id = '66c83c06-7208-4066-9b66-fd2ced9812f3';
this.isRTL = SPZ.win.document.dir === 'rtl';
this.isAddingToCart_ = false; // ๅ ่ดญไธญ็ถๆ
}
static deferredMount() {
return false;
}
buildCallback() {
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.templates_ = SPZServices.templatesForDoc(this.element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.setupAction_();
this.viewport_ = this.getViewport();
}
mountCallback() {
this.init();
// ็ๅฌไบไปถ
this.bindEvent_();
}
async init() {
this.handleFitTheme();
const data = await this.getDiscountList();
this.renderApiData_(data);
}
async getDiscountList() {
const productId = '8e0c4c20-76d1-49e6-8a96-195f1fecb173';
const variantId = this.variant_id;
const productType = 'default';
const reqBody = {
product_id: productId,
variant_id: variantId,
discount_method: "DM_AUTOMATIC",
customer: {
customer_id: window.C_SETTINGS.customer.customer_id,
email: window.C_SETTINGS.customer.customer_email
},
product_type: productType
}
const url = `/api/storefront/promotion/display_setting/text/list`;
const data = await this.xhr_.fetchJson(url, {
method: "post",
body: reqBody
}).then(res => {
return res;
}).catch(err => {
this.setContainerDisabled(false);
})
return data;
}
async renderDiscountList() {
this.setContainerDisabled(true);
const data = await this.getDiscountList();
this.setContainerDisabled(false);
// ้ๆฐๆธฒๆ ๆๅจ้ฎ้ขๅค็
this.renderApiData_(data);
}
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
async renderApiData_(data) {
const parentDiv = document.querySelector('.automatic_discount_container');
const newTplDom = await this.getRenderTemplate(data);
if (parentDiv) {
parentDiv.innerHTML = '';
parentDiv.appendChild(newTplDom);
} else {
console.log('automatic_discount_container is null');
}
}
doRender_(data) {
const renderData = data || {};
return this.templates_
.findAndRenderTemplate(this.element, renderData)
.then((el) => {
this.clearDom();
this.element.appendChild(el);
});
}
async getRenderTemplate(data) {
const renderData = data || {};
return this.templates_
.findAndRenderTemplate(this.element, { ...renderData, isRTL: this.isRTL })
.then((el) => {
this.clearDom();
return el;
});
}
setContainerDisabled(isDisable) {
const automaticDiscountEl = document.querySelector('.automatic_discount_container_outer');
if(isDisable) {
automaticDiscountEl.setAttribute('disabled', '');
} else {
automaticDiscountEl.removeAttribute('disabled');
}
}
// ็ปๅฎไบไปถ
bindEvent_() {
window.addEventListener('click', (e) => {
let containerNodes = document.querySelectorAll(".automatic-container .panel");
let bool;
Array.from(containerNodes).forEach((node) => {
if(node.contains(e.target)){
bool = true;
}
})
// ๆฏๅฆpopover้ขๆฟ็นๅป่ๅด
if (bool) {
return;
}
if(e.target.classList.contains('drowdown-icon') || e.target.parentNode.classList.contains('drowdown-icon')){
return;
}
const nodes = document.querySelectorAll('.automatic-container');
Array.from(nodes).forEach((node) => {
node.classList.remove('open-dropdown');
})
// ๅ
ผๅฎนไธป้ข
this.toggleProductSticky(true);
})
// ็ๅฌๅไฝๅๅ
document.addEventListener('dj.variantChange', async(event) => {
// ้ๆฐๆธฒๆ
const variant = event.detail.selected;
if (variant.product_id == '8e0c4c20-76d1-49e6-8a96-195f1fecb173' && variant.id != this.variant_id) {
this.variant_id = variant.id;
this.renderDiscountList();
}
});
}
// ๅ
ผๅฎนไธป้ข
handleFitTheme() {
// top ๅฑๆงๅฝฑๅๆๅจ
let productInfoEl = null;
if (window.SHOPLAZZA.theme.merchant_theme_name === 'Wind' || window.SHOPLAZZA.theme.merchant_theme_name === 'Flash') {
productInfoEl = document.querySelector('.product-info-body .product-sticky-container');
} else if (window.SHOPLAZZA.theme.merchant_theme_name === 'Hero') {
productInfoEl = document.querySelector('.product__info-wrapper .properties-content');
}
if(productInfoEl){
productInfoEl.classList.add('force-top-auto');
}
}
// ๅ
ผๅฎน wind/flash /hero ไธป้ข (stickyๅฑๆงๅฝฑๅ popover ๅฑ็บงๅฑ็คบ, ไผ่ขซๅ
ถไปๅ
็ด ่ฆ็)
toggleProductSticky(isSticky) {
let productInfoEl = null;
if (window.SHOPLAZZA.theme.merchant_theme_name === 'Wind' || window.SHOPLAZZA.theme.merchant_theme_name === 'Flash') {
productInfoEl = document.querySelector('.product-info-body .product-sticky-container');
} else if (window.SHOPLAZZA.theme.merchant_theme_name === 'Hero') {
productInfoEl = document.querySelector('.product__info-wrapper .properties-content');
}
if(productInfoEl){
if(isSticky) {
// ่ฟๅ่ฏฅไธป้ขๅๆ็stickyๅฑๆงๅผ
productInfoEl.classList.remove('force-position-static');
return;
}
productInfoEl.classList.toggle('force-position-static');
}
}
setupAction_() {
this.registerAction('handleDropdown', (invocation) => {
const discount_id = invocation.args.discount_id;
const nodes = document.querySelectorAll('.automatic-container');
Array.from(nodes).forEach((node) => {
if(node.getAttribute('id') != `automatic-${discount_id}`) {
node.classList.remove('open-dropdown');
}
})
const $discount_item = document.querySelector(`#automatic-${discount_id}`);
$discount_item && $discount_item.classList.toggle('open-dropdown');
// ๅ
ผๅฎนไธป้ข
this.toggleProductSticky();
});
// ๅ ่ดญไบไปถ
this.registerAction('handleAddToCart', (invocation) => {
// ้ปๆญขไบไปถๅๆณก
const event = invocation.event;
if (event) {
event.stopPropagation();
event.preventDefault();
}
// ๅฆๆๆญฃๅจๅ ่ดญไธญ๏ผ็ดๆฅ่ฟๅ
if (this.isAddingToCart_) {
return;
}
const quantity = invocation.args.quantity || 1;
this.addToCart(quantity);
});
}
// ๅ ่ดญๆนๆณ
async addToCart(quantity) {
// ่ฎพ็ฝฎๅ ่ดญไธญ็ถๆ
this.isAddingToCart_ = true;
const productId = '8e0c4c20-76d1-49e6-8a96-195f1fecb173';
const variantId = this.variant_id;
const url = '/api/cart';
const reqBody = {
product_id: productId,
variant_id: variantId,
quantity: quantity
};
try {
const data = await this.xhr_.fetchJson(url, {
method: 'POST',
body: reqBody
});
// ่งฆๅๅ ่ดญๆๅๆ็คบ
this.triggerAddToCartToast_();
return data;
} catch (error) {
error.then(err=>{
this.showToast_(err?.message || err?.errors?.[0] || 'Unknown error');
})
} finally {
// ๆ ่ฎบๆๅๅคฑ่ดฅ๏ผ้ฝ้็ฝฎๅ ่ดญ็ถๆ
this.isAddingToCart_ = false;
}
}
showToast_(message) {
const toastEl = document.querySelector("#apps-match-drawer-add_to_cart_toast");
if (toastEl) {
SPZ.whenApiDefined(toastEl).then((apis) => {
apis.showToast(message);
});
}
}
// ่งฆๅๅ ่ดญๆๅๆ็คบ
triggerAddToCartToast_() {
// ๅฆๆไธป้ขๆ่ชๅทฑ็ๅ ่ดญๆ็คบ๏ผๅไธๆพ็คบ
const themeAddToCartToastEl = document.querySelector('#add-cart-event-proxy');
if (themeAddToCartToastEl) return;
// ๆพ็คบๅบ็จ็ๅ ่ดญๆๅๆ็คบ
this.showToast_("Added successfully");
}
triggerEvent_(name, data) {
const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {});
this.action_.trigger(this.element, name, event);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
}
SPZ.defineElement(TAG, SpzCustomProductAutomatic);
class SpzCustomDiscountBundle extends SPZ.BaseElement {
constructor(element) {
super(element);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
mountCallback() {
// ๅไธ้กตๅฏ่ฝๆๅคไธช block ๅ่ชๆธฒๆๆฌ snippet๏ผๅฏผ่ด้ป่พๅ
็ด spz-custom-discount-toast(#appsAddCartToastFunc) ้ๅคใ
// ไป
ไฟ็ DOM ไธญ็ฌฌไธไธชๅฎไพ๏ผๅ
ถไฝ้ๅคๅฎไพ็งป้ค่ช่บซ๏ผไฟ่ฏ้ป่พๅ
็ด ๅๅ
ถ action ๅผ็จ(appsAddCartToastFunc)ๅฏไธใ
const funcs = document.querySelectorAll('#appsAddCartToastFunc');
if (funcs.length > 1 && this.element !== funcs[0]) {
this.element.remove();
return;
}
// ๅ
จๅฑๆๆฃ toast ็ๅผนๅบ็นๅๆฃๅจๅคไธชๆจกๆฟ/็ปไปถ้๏ผๅซๅฃฐๆๅผ @atcError๏ผ๏ผๆ ๆณ้ไธๅจๅผนๅบๅๅ็ฝฎ๏ผ
// ๆ
ๆ่ฝฝๆถๅน็ญๅฐๅป้ๅนถๆๅฐ body๏ผๅ ่ดญ toast ๆนไธบๅผนๅบๅๆ้ๅป้๏ผ่ง showAddToCartToast๏ผ
this.ensureSingleToastInBody_('cart_match_discount_toast_wrap');
}
unmountCallback() {}
// ๅไธ้กต้ขๅฏ่ฝๆๅคไธช block ๅ่ชๆธฒๆๆฌ toast snippet๏ผๅฆๅ่ฏฆ็ discount_automatic + ่ดญ็ฉ่ฝฆๆฝๅฑ้็ๆๆฃๆจชๅน
๏ผ๏ผ
// ๅฏผ่ด toast ๅคๅฑๅบ็ฐ้ๅค idใ้ๅค id ไธ getElementById/querySelector ๅ SPZ ๅจไฝๅผ็จ้ฝๅชๅฝไธญ็ฌฌไธไธช๏ผ
// ไธ่ขซๅ
ณ่ฟๆฝๅฑ็้ฃไปฝไผ่ขซๆฝๅฑ็ transform/overflow ่ฃๅช/้ไฝใ่ฟ้ๅจๆ่ฝฝๆถๅน็ญๅป้๏ผ
// ๅชไฟ็ไธไปฝใ็งป้คๅคไฝ็๏ผๅนถๆไฟ็็ๆๅฐ body๏ผbody ๆฏ position:fixed ๆๅฎๅ
จ็่ฝ็น๏ผ้ฟๅ
่ขซไปปไฝ็ฅๅ
่ฃๅช๏ผใๅฏๅๅค่ฐ็จใ
ensureSingleToastInBody_(id) {
const els = Array.from(document.querySelectorAll('#' + id));
if (!els.length) return;
els.slice(1).forEach((el) => el.remove());
const keep = els[0];
if (keep.parentNode !== document.body) {
document.body.appendChild(keep);
}
}
// ไธป้ข่ดญ็ฉ่ฝฆๆฝๅฑๆฏๅฆๆๅผ
isInCartDrawer_() {
return !!document.querySelector('[data-section-type="cart_drawer"] spz-sidebar[open]');
}
setupAction_() {
this.registerAction('showAddToCartToast', () => {
// ๆฝๅฑๅ
ๅ ่ดญ๏ผไธป้ขๆฌๅฐฑไธไผๆๅ ่ดญๆๆ๏ผ็ปไธๅผนๆไปถ่ชๅทฑ็ toast
// ้ๆฝๅฑ๏ผไธป้ขๆๅ ่ดญไปฃ็ๅๆฒฟ็จไธป้ขๅ ่ดญๆๆ๏ผๅฆๅๆไปถๅ
ๅบ
const proxyEl = document.getElementById('add-cart-event-proxy');
const inDrawer = this.isInCartDrawer_();
if (!inDrawer && proxyEl) {
return;
}
// ๅผนๅบๅๆ้ๅป้ๅนถๆๅฐ body๏ผๅน็ญ๏ผ๏ผ้ฟๅ
้ๅค id ๅฝไธญ้ๅฏน่ฑกๆ่ขซๆฝๅฑ่ฃๅช/้ไฝ
this.ensureSingleToastInBody_('apps_add_cart_toast_wrap');
const toastEl = document.querySelector('#apps-match-drawer-add_to_cart_toast')
SPZ.whenApiDefined(toastEl).then((apis) => {
apis.showToast("Added successfully");
});
});
}
buildCallback() {
this.setupAction_();
};
}
SPZ.defineElement('spz-custom-discount-toast', SpzCustomDiscountBundle);
${function(){
const isRTL = originData.isRTL;
const isMobile = originData.isMobile;
const inProductDetail = originData.inProductDetail;
if (!inProductDetail) {
return `
Flash sale cannot be displayed here. Please move it to the product detail area.
(This prompt will not be displayed on the client-side)
`;
}
const flashsaleData = originData.flashsaleData;
const image_domain = originData.image_domain;
const discount_info = flashsaleData.discount_info;
const setting = flashsaleData.product_setting;
if (!discount_info || !setting) return ``;
// ๆฌๅฐ่ทณ่ฝฌๅคๅฎ(ไธไพ่ตๅ
จๅฑ appDiscountUtils,ๆจกๆฟๆฒ็ฎฑไธๅฏ่ง)
// is_redirection ๅผๅฏๅณๅฏ่ทณ(landing ๅ
ๅบ);link ้ๆณๆถ้ๅ landing
const __canRedirect = (s) => !!(s && s.is_redirection);
const displayType = setting.display_type;
const banner = setting.banner;
const productDisplay = setting.product_display;
const bannerConfig = JSON.parse(banner.config);
const productDisplayConfig = JSON.parse(productDisplay.config);
const colorConfig = productDisplayConfig.color;
const countdownConfig = productDisplayConfig.countdown;
let titleIcon = ``;
let bgImg = ``;
const deg = `${isRTL ? -90 : 90}deg`;
const { banner_bg_start, banner_bg_end, banner_text } = colorConfig;
let bgStyle = `background: linear-gradient(${deg}, ${banner_bg_start} 0%, ${banner_bg_end} 100%);`;
let bannerColor = `color: ${banner_text};`
if (banner.type === "TYPE_CUSTOM") {
const { desktop, mobile, image_render } = bannerConfig;
const bgSize = image_render === "fill" ? "background-size: cover;background-position: center;" : "background-position: center;background-size: auto 100%;";
if (isMobile && mobile) {
bgStyle = `background: URL(${image_domain + mobile});${bgSize}`;
} else if (!isMobile && desktop) {
bgStyle = `background: URL(${image_domain + desktop});${bgSize}`;
}
} else {
if (banner.type === "TYPE_ONE") {
titleIcon = productDisplay.text ? `
` : "";
bgImg = ``
}
if (banner.type === "TYPE_TWO") {
titleIcon = productDisplay.text ? `
` : ""
}
}
const { sale_bar_background_color, progress_sale_bar_background_color_start, progress_sale_bar_background_color_end } = colorConfig;
const rate = discount_info.discount_sales_rate;
const progressBarStyle = `background: linear-gradient(${deg}, ${progress_sale_bar_background_color_start} 0%, ${progress_sale_bar_background_color_end} 100%);`;
const saleCount = productDisplay.sales_progress.format === "FORMAT_NUMBER" ? discount_info.discount_sales : `${rate}%`;
const progressBarDom = productDisplay.sales_progress.enabled && rate > 0 ? `
` : ``;
const { countdown_bg, countdown_text } = colorConfig;
const { end_opened, end_format } = countdownConfig;
const tempMap = {
"DD_SSS": "DD:HH:mm:ss:SSS",
"HH_SSS": "HH:mm:ss:SSS",
"DD_ss": "DD:HH:mm:ss",
"HH_ss": "HH:mm:ss"
}
const isShowDD = [tempMap.DD_SSS, tempMap.DD_ss].includes(end_format);
const isShowSSS = [tempMap.DD_SSS, tempMap.HH_SSS].includes(end_format);
const countdown = discount_info.ends_remaining_seconds;
const countdownDom = end_opened ? `
${function() {
if (banner.type === "TYPE_TWO") return `
`
return ``;
}()}
` : ``;
const flashSaleDesc = discount_info.limit_user_product_discount > -1 ? `
Promo products limited to ${discount_info.limit_user_product_discount} item per person
` : "";
return `
${bgImg}
${titleIcon}
${productDisplay.text}
${progressBarDom}
${countdownDom}
${flashSaleDesc}
`}()}
${function(){
const dd = data.dd; const hh = data.hh; const mm = data.mm; const ss = data.ss; const sss = data.SSS;
const hours = data.d * 24 + data.h;
return `
${dd}D
ยท
${hours}
${hh}
:
${mm}
:
${ss}
.
${sss}
`
}()}
class SpzCustomDiscountFlashsale extends SPZ.BaseElement {
constructor(element) {
super(element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.getFlashSaleApi = "\/api\/storefront\/promotion\/flashsale\/display_setting\/product_setting";
this.timer = null;
this.variantId = "66c83c06-7208-4066-9b66-fd2ced9812f3";
// ไฟ้ๆดปๅจๆฐๆฎ
this.flashsaleData = {}
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
buildCallback() {
this.templates_ = SPZServices.templatesForDoc();
this.viewport_ = this.getViewport();
// ๆ่ฝฝbindๅฝๆฐ ่งฃๅณthisๆๅ้ฎ้ข
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
this.switchVariant = this.switchVariant.bind(this);
}
mountCallback() {
// ่ทๅๆฐๆฎ
this.getData();
this.element.onclick = (e) => {
const cur = this.win.document.querySelector(".app_discount_flashsale_desc");
const setting = this.flashsaleData.product_setting;
const landingUrl = `/promotions/discount-default/${this.flashsaleData.discount_info.id}`;
const finalUrl = appDiscountUtils.resolveDiscountHref(setting, landingUrl);
if (finalUrl && appDiscountUtils.inProductBody(this.element) && e.target !== cur) {
this.win.open(finalUrl, '_blank', 'noopener');
}
}
// ็ปๅฎ
this.viewport_.onResize(this.resize);
// ็ๅฌๅญๆฌพๅผๅๆข๏ผ้ๆฐๆธฒๆ
this.win.document.addEventListener('dj.variantChange', this.switchVariant);
}
unmountCallback() {
// ่งฃ็ป
this.viewport_.removeResize(this.resize);
this.win.document.removeEventListener('dj.variantChange', this.switchVariant);
// ๆธ
้คๅฎๆถๅจ
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
resize() {
if (this.timer) {
clearTimeout(this.timer)
this.timer = null;
}
this.timer = setTimeout(() => {
this.render();
}, 200)
}
switchVariant(event) {
const variant = event.detail.selected;
if (variant.product_id == '8e0c4c20-76d1-49e6-8a96-195f1fecb173' && variant.id != this.variantId) {
this.variantId = variant.id;
this.getData();
}
}
getData() {
const reqBody = {
product_id: "8e0c4c20-76d1-49e6-8a96-195f1fecb173",
product_type: "default",
variant_id: this.variantId
}
this.flashsaleData = {};
this.win.fetch(this.getFlashSaleApi, {
method: "POST",
body: JSON.stringify(reqBody),
headers: {
"Content-Type": "application/json"
}
}).then(async (response) => {
if (response.ok) {
this.flashsaleData = await response.json();
this.render();
} else {
this.clearDom();
}
}).catch(err => {
this.clearDom();
});
}
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
render() {
this.templates_
.findAndRenderTemplate(this.element, {
isMobile: appDiscountUtils.judgeMobile(),
isRTL: appDiscountUtils.judgeRTL(),
inProductDetail: appDiscountUtils.inProductBody(this.element),
flashsaleData: this.flashsaleData,
image_domain: this.win.SHOPLAZZA.image_domain,
})
.then((el) => {
this.clearDom();
this.element.appendChild(el);
})
}
}
SPZ.defineElement('spz-custom-discount-flashsale', SpzCustomDiscountFlashsale);
${function(){
// ่ทๅๅบ็ก้
็ฝฎๆฐๆฎ
const isRTL = originData.isRTL; // ๆฏๅฆไปๅณๅฐๅทฆๆพ็คบ
const isMobile = originData.isMobile; // ๆฏๅฆ็งปๅจ็ซฏ
const inProductDetail = originData.inProductDetail; // ๆฏๅฆๅจๅๅ่ฏฆๆ
้กต
const image_domain = originData.image_domain; // ๅพ็ๅๅ
const copyBtnClass = originData.copyBtnClass; // ๅคๅถๆ้ฎ็ฑปๅ
const copyClass = originData.copyClass; // ๅคๅถๅ
ๅฎน็ฑปๅ
// ไผๆ ็ ๅ่กจ
const list = originData.discountCodeData.list || [];
if (list.length === 0) {
return ``;
}
// ๆพ็คบๆจกๅผ: ๅนณ้บๆๆๅ
const isTiled = originData.discountCodeData.display_type === "DTE_TILE";
// ่ทๅ็ฌฌไธไธช้
็ฝฎไฝไธบ้ป่ฎค้
็ฝฎ
const productSetting = list[0].product_setting;
const { template_type, template_config } = productSetting;
const { text, tag, banner, coupon } = template_config.color;
// ไผๆ ๅธๆ ทๅผ้
็ฝฎ
const {
coupon_border_color, // ่พนๆก้ข่ฒ
coupon_background_color, // ่ๆฏ่ฒ่ตทๅง่ฒ
coupon_background_color_end, // ่ๆฏ่ฒ็ปๆ่ฒ
coupon_color, // ๆๅญ้ข่ฒ
coupon_button_background_color_start, // ๆ้ฎ่ๆฏ่ตทๅง่ฒ
coupon_button_background_color_end, // ๆ้ฎ่ๆฏ็ปๆ่ฒ
coupon_button_color // ๆ้ฎๆๅญ้ข่ฒ
} = coupon;
// ้ข่ฒ้ๆๅบฆ่ฝฌๆขๅฝๆฐ
const colorToRGBA = (color, alpha) => {
if (color.startsWith('#')) {
const hex = color.slice(1);
const r = parseInt(hex.slice(0, 2), 16);
const g = parseInt(hex.slice(2, 4), 16);
const b = parseInt(hex.slice(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
else if (color.includes('rgb')) {
const rgb = color.slice(color.indexOf('(') + 1, color.indexOf(')')).split(',');
const r = parseInt(rgb[0]);
const g = parseInt(rgb[1]);
const b = parseInt(rgb[2]);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
else {
return color
}
}
// ๆธฒๆๅนณ้บๆ ทๅผ็ไผๆ ๅธๅ่กจ
const renderTiledList = (list, isFold = false) => {
const rate = isRTL ? '34%' : '66%'; // RTLๅธๅฑๆถ่ฐๆดๅๅฒ็บฟไฝ็ฝฎ
let curDom = `
`;
// ๅพช็ฏๆธฒๆไผๆ ๅธๅ่กจ
for(const item of list) {
curDom += `
${item.discount_text}
${(isFold || item.product_setting.show_effective_date) && +item.ends_at !== -1 ? `${item.starts_at} - ${item.ends_at}` : ""}
`
}
return curDom;
}
let Dom = ``;
// ๆ นๆฎๆพ็คบๆจกๅผ้ๆฉๆธฒๆๆนๅผ
if (isTiled || list.length === 1) {
// ๆ นๆฎๆจกๆฟ็ฑปๅๆธฒๆไธๅๆ ทๅผ
switch(template_type) {
// ๆๆฌๆ ทๅผ
case 'text': {
Dom = `
${function(){
let textDom = '';
for(const item of list) {
textDom += `
${ item.discount_text }
Code:
${ item.code }
`
}
return textDom;
}()}
`;
break;
}
// ๆ ็ญพๆ ทๅผ
case 'tag': {
const { text_color, background_color } = tag;
Dom = `
${function(){
let textDom = '';
for(const item of list) {
textDom += `
${ item.discount_text }
Code:
${ item.code }
`;
}
return textDom;
}()}
`
break;
}
// ๆจชๅน
ๆ ทๅผ
case 'banner': {
Dom = `
${function(){
let textDom = '';
for(const item of list) {
textDom += `
${ item.discount_text }
Code:
${ item.code }
`;
}
return textDom;
}()}
`;
break;
}
// ไผๆ ๅธๆ ทๅผ
case 'coupon': {
Dom = `
${renderTiledList(list)}
`
break;
}
}
} else {
// ๆๅ ๆจกๅผๆ ทๅผ
const foldStyle = `
`;
// ๅชๆพ็คบๅ3ไธชไผๆ ๅธ
const showList = list.slice(0, 3);
let couponDom = "";
for(const item of showList) {
couponDom += `
${item.discount_text}
`
}
// PC็ซฏๅผน็ช
const webModal = `
${function(){
return renderTiledList(list, true);
}()}
`
// ็งปๅจ็ซฏไพง่พนๆ
const mobileModal = `
`
couponDom += `
Click to claim
${isMobile ? mobileModal : webModal}
`;
Dom = `
${foldStyle}
${couponDom}
`
}
return `
${Dom}
`;
}()}
/**
* ไผๆ ็ ็ปไปถๆจกๅ็ฑป
* ๅค็ไผๆ ็ ็ๆพ็คบๅไบคไบ้ป่พ
*/
class SpzCustomDiscountCodeModel extends SPZ.BaseElement {
constructor(element) {
super(element);
// ๅคๅถๆ้ฎๅๅ
ๅฎน็็ฑปๅ
this.copyBtnClass = "discount_code_btn"
this.copyClass = "discount_code_value"
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
// ๅๅงๅๆๅก
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.templates_ = SPZServices.templatesForDoc(this.element);
this.xhr_ = SPZServices.xhrFor(this.win);
}
/**
* ๆธฒๆไผๆ ็ ็ปไปถ
* @param {Object} data - ๆธฒๆๆฐๆฎ
*/
doRender_(data) {
return this.templates_
.findAndRenderTemplate(this.element,
Object.assign(this.getDefaultData(), data)
)
.then((el) => {
this.clearDom();
this.element.appendChild(el);
// ็ปๅฎๅคๅถไปฃ็ ๅ่ฝ
this.copyCode(el, data);
});
}
/**
* ่ทๅๆธฒๆๆจกๆฟ
* @param {Object} data - ๆธฒๆๆฐๆฎ
*/
getRenderTemplate(data) {
const renderData = Object.assign(this.getDefaultData(), data);
return this.templates_
.findAndRenderTemplate(this.element, renderData)
.then((el) => {
this.clearDom();
return el;
});
}
/**
* ๆธ
้คDOMๅ
ๅฎน
*/
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
/**
* ่ทๅ้ป่ฎคๆฐๆฎ
* @returns {Object} ้ป่ฎคๆฐๆฎๅฏน่ฑก
*/
getDefaultData() {
return {
isMobile: appDiscountUtils.judgeMobile(),
isRTL: appDiscountUtils.judgeRTL(),
image_domain: this.win.SHOPLAZZA.image_domain,
copyBtnClass: this.copyBtnClass,
copyClass: this.copyClass
}
}
/**
* ๅคๅถไผๆ ็ ๅ่ฝ
* @param {Element} el - ๅฝๅๅ
็ด
*/
copyCode(el) {
const copyBtnList = el.querySelectorAll(`.${this.copyBtnClass}`);
if (copyBtnList.length > 0) {
copyBtnList.forEach(item => {
item.onclick = async () => {
// ็กฎไฟ่ทๅๆญฃ็กฎ็ๅ
็ด ๅๅ
ๅฎน
const codeElement = item.querySelector(`.${this.copyClass}`);
if (!codeElement) return;
// ่ทๅ็บฏๆๆฌๅ
ๅฎน
const textToCopy = codeElement.innerText.trim();
// ๅฐ่ฏไฝฟ็จ็ฐไปฃAPI๏ผๅฆๆๅคฑ่ดฅๅไฝฟ็จๅค็จๆนๆก
try {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(textToCopy);
} else {
throw new Error('Clipboard API not available');
}
// ๆพ็คบๅคๅถๆๅๆ็คบ
this.showCopySuccessToast(textToCopy, el);
} catch (err) {
console.error('Modern clipboard API failed, trying fallback...', err);
// ไฝฟ็จๅค็จๅคๅถๆนๆก
this.fallbackCopy(textToCopy, el);
}
const discountId = item.dataset["discountId"];
// ่ทณ่ฝฌๅณ็ญ: is_redirection + link(ๅฏ้่ฆ็)
const setting = {
is_redirection: item.dataset["redirection"] === "true",
link: item.dataset["link"],
};
const landingUrl = `/promotions/discount-default/${discountId}`;
const finalUrl = appDiscountUtils.resolveDiscountHref(setting, landingUrl);
if (finalUrl && appDiscountUtils.inProductBody(this.element)) {
this.win.open(finalUrl, '_blank', 'noopener');
}
}
})
}
}
/**
* ไฝฟ็จ execCommand ็ๅคๅถๆนๆก
* @param {string} codeText - ่ฆๅคๅถ็ๆๆฌ
* @param {Element} el - ๅฝๅๅ
็ด
*/
fallbackCopy(codeText, el) {
const textarea = this.win.document.createElement('textarea');
textarea.value = codeText;
// ่ฎพ็ฝฎๆ ทๅผไฝฟๆๆฌๆกไธๅฏ่ง
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
textarea.style.top = '0';
// ๆทปๅ readonly ๅฑๆง้ฒๆญข็งปๅจ็ซฏ่ๆ้ฎ็ๅผนๅบ
textarea.setAttribute('readonly', 'readonly');
this.win.document.body.appendChild(textarea);
textarea.focus();
textarea.select();
try {
this.win.document.execCommand('copy');
// ๆพ็คบๅคๅถๆๅๆ็คบ
this.showCopySuccessToast(codeText, el);
} catch (err) {
console.error('Copy failed:', err);
}
this.win.document.body.removeChild(textarea);
}
/**
* ๅๅปบ Toast ๅ
็ด
* @returns {Element} ๅๅปบ็ Toast ๅ
็ด
*/
createToastEl_() {
const toast = document.createElement('ljs-toast');
toast.setAttribute('layout', 'nodisplay');
toast.setAttribute('hidden', '');
toast.setAttribute('id', 'discount-code-toast');
toast.style.zIndex = '1051';
return toast;
}
/**
* ๆ่ฝฝ Toast ๅ
็ด ๅฐ body
* @returns {Element} ๆ่ฝฝ็ Toast ๅ
็ด
*/
mountToastToBody_() {
const existingToast = this.win.document.getElementById('discount-code-toast');
if (existingToast) {
return existingToast;
}
const toast = this.createToastEl_();
this.win.document.body.appendChild(toast);
return toast;
}
/**
* ๅคๅถๆๅ็ๆ้
* @param {string} codeText - ่ฆๅคๅถ็ๆๆฌ
* @param {Element} el - ๅฝๅๅ
็ด
*/
showCopySuccessToast(codeText, el) {
const $toast = this.mountToastToBody_();
SPZ.whenApiDefined($toast).then(toast => {
toast.showToast("Discount code copied !");
this.codeCopyInSessionStorage(codeText);
});
}
/**
* ๅคๅถไผๆ ็ ๆๅๅ่ฆๅญไธไปฝๅฐๆฌๅฐๅญๅจไธญ๏ผ่ดญ็ฉ่ฝฆไฝฟ็จ
* @param {string} codeText - ่ฆๅคๅถ็ๆๆฌ
*/
codeCopyInSessionStorage(codeText) {
try {
sessionStorage.setItem('other-copied-coupon', codeText);
} catch (error) {
console.error(error)
}
}
}
// ๆณจๅ่ชๅฎไนๅ
็ด
SPZ.defineElement('spz-custom-discount-code-model', SpzCustomDiscountCodeModel);
${function(){
return `
Discount code cannot be displayed here. Please move it to the product detail area.
(This prompt will not be displayed on the client-side)
`;
}()}
/**
* Custom discount code component that handles displaying and managing discount codes
* @extends {SPZ.BaseElement}
*/
class SpzCustomDiscountCode extends SPZ.BaseElement {
constructor(element) {
super(element);
// API endpoint for fetching discount codes
this.getDiscountCodeApi = "\/api\/storefront\/promotion\/code\/list";
// Debounce timer for resize events
this.timer = null;
// Current variant ID
this.variantId = "66c83c06-7208-4066-9b66-fd2ced9812f3";
// Store discount code data
this.discountCodeData = {}
}
/**
* Check if layout is supported
* @param {string} layout - Layout type
* @return {boolean}
*/
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
/**
* Initialize component after build
*/
buildCallback() {
this.templates_ = SPZServices.templatesForDoc();
this.viewport_ = this.getViewport();
// Bind methods to maintain context
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
this.switchVariant = this.switchVariant.bind(this);
}
/**
* Setup component when mounted
*/
mountCallback() {
this.getData();
// Add event listeners
this.viewport_.onResize(this.resize);
this.win.document.addEventListener('dj.variantChange', this.switchVariant);
}
/**
* Cleanup when component is unmounted
*/
unmountCallback() {
this.viewport_.removeResize(this.resize);
this.win.document.removeEventListener('dj.variantChange', this.switchVariant);
// ๆธ
้คๅฎๆถๅจ
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
/**
* Handle resize events with debouncing
*/
resize() {
if (this.timer) {
clearTimeout(this.timer)
this.timer = null;
}
this.timer = setTimeout(() => {
if (appDiscountUtils.inProductBody(this.element)) {
this.render();
} else {
this.renderSkeleton();
}
}, 200);
}
/**
* Handle variant changes
* @param {Event} event - Variant change event
*/
switchVariant(event) {
const variant = event.detail.selected;
if (variant.product_id == '8e0c4c20-76d1-49e6-8a96-195f1fecb173' && variant.id != this.variantId) {
this.variantId = variant.id;
this.getData();
}
}
/**
* Fetch discount code data from API
*/
getData() {
if (appDiscountUtils.inProductBody(this.element)) {
const reqBody = {
product_id: "8e0c4c20-76d1-49e6-8a96-195f1fecb173",
variant_id: this.variantId,
product_type: "default",
}
if (!reqBody.product_id || !reqBody.variant_id) return;
this.discountCodeData = {};
this.win.fetch(this.getDiscountCodeApi, {
method: "POST",
body: JSON.stringify(reqBody),
headers: {
"Content-Type": "application/json"
}
}).then(async (response) => {
if (response.ok) {
let data = await response.json();
if (data.list && data.list.length > 0) {
data.list[0].product_setting.template_config = JSON.parse(data.list[0].product_setting.template_config);
// Format timestamps to local timezone
const zone = this.win.SHOPLAZZA.shop.time_zone;
data.list = data.list.map(item => {
if(+item.ends_at !== -1) {
item.ends_at = appDiscountUtils.convertTimestampToFormat(+item.ends_at, zone);
}
item.starts_at = appDiscountUtils.convertTimestampToFormat(+item.starts_at, zone);
return item;
});
}
this.discountCodeData = data;
this.render();
} else {
this.clearDom();
}
}).catch(err => {
console.error("discount_code", err)
this.clearDom();
});
} else {
this.renderSkeleton();
}
}
/**
* Clear component DOM except template
*/
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
/**
* Render discount codes with formatted dates
*/
render() {
// Render using discount code model
SPZ.whenApiDefined(document.querySelector('#spz_custom_discount_code_model')).then(renderApi => {
renderApi.doRender_({
discountCodeData: this.discountCodeData
})
}).catch(err => {
this.clearDom();
})
}
renderSkeleton() {
// Render template for non-product pages
this.templates_
.findAndRenderTemplate(this.element, {
isMobile: appDiscountUtils.judgeMobile()
})
.then((el) => {
this.clearDom();
this.element.appendChild(el);
})
.catch(err => {
this.clearDom();
});
}
}
// Register custom element
SPZ.defineElement('spz-custom-discount-code', SpzCustomDiscountCode);
Please select a Choose a color
${function(){
return `
Please select a Choose a color
`;
}()}
Please select a Choose a model
${function(){
return `
Please select a Choose a model
`;
}()}
Product was out of stock.
Product is unavailable.
The current produc does not participate any Rebate. Switch the participating product to check the design.
(This prompt will not be displayed on the client-side.)
${function() {
const show = rebate.format_rules.length > data.maxShowCount;
return `
${rule}
${function() {
if(!show) return "";
return `
`;
}()}
`;
}()}
${originData.rebate.format_rules.join(", ")}
var theme = window.C_SETTINGS && C_SETTINGS.theme && C_SETTINGS.theme.merchant_theme_name;
var isFlash = /Flash/gi.test(theme);
var isGeek = /Geek/gi.test(theme);
var isNova23 = /Nova 2023/gi.test(theme);
var isWind = /Wind/gi.test(theme);
var isOnePage = /OnePage/gi.test(theme);
var isHero = /Hero/gi.test(theme);
var isBoost = /Boost/gi.test(theme);
var isEva = /Eva/gi.test(theme);
var isFarida = /Farida/gi.test(theme);
var isPluto = /Pluto/gi.test(theme);
var isLifeStyle = /Life Style/gi.test(theme);
if(window.self === window.top) {
(window.disabled_exts ||=[]).push('product_detail_rebate');
}
class SpzRebateComponent extends SPZ.BaseElement {
constructor(element) {
super(element);
}
xhr_ = SPZServices.xhrFor(this.win);
viewport_ = this.getViewport();
action_ = null;
lang = document.documentElement.lang || 'en-US';
landPage = "\/promotions\/rebate\/";
pageType = 1;
cart = [];
initData = null;
rebateInfo = null;
renderData = null;
footerImage = `${this.win.SHOPLAZZA["image_domain"]}oss/operation/e8ebb03dbb710457ca3b4b6a70898ab2.svg`;
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
this.initData = this.getProduct();
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.registerAction("triggerGetRenderData", () => {
const event = SPZUtils.Event.create(this.win, "triggerGetRenderData", this.renderData);
this.action_.trigger(this.element, "getRenderData", event);
});
this.registerAction("bindPropagation", () => {
document.querySelector(".product_detail_rebate_list").addEventListener("click", e => {
e.stopPropagation();
this.win.sa &&
this.win.sa.track("plugin_rebate_promotion_click", {
plugin_timestamp: Date.now(),
plugin_location: "info",
product_id: this.initData.product.id,
discount_id: this.rebateInfo.discount_list.map((item) => item.discount_id)[0],
});
});
});
}
async mountCallback() {
document.addEventListener("dj.variantChange", e => {
const data = e.detail;
if (document.querySelector("#product-select-modal.show")) return;
this.initData = this.getProductJson(data);
if (this.initData && this.initData.product && data.product && this.initData.product.id === data.product.id) {
this.initRebate(this.initData, true);
} else {
this.getRebateInfo();
}
});
document.addEventListener("dj.addToCart", e => {
const v = e.detail;
this.rebateInfo &&
this.win.sa &&
this.win.sa.track("plugin_rebate_atc", {
variant_discount_id: this.getVariantDiscountId(v.variant_id).map(item => item.discount_id),
discount_ids: this.rebateInfo.discount_list.map(item => item.discount_id),
variant_id: v.variant_id,
product_id: v.product_id,
price: v.item_price,
number: v.number,
});
});
await this.getRebateInfo();
setTimeout(()=>{
if (document.querySelector(".plugin-container__bottom-fixed")) {
this.showDiscountPopupsInfoBar();
} else {
this.win.addEventListener("extloaded", () => {
this.showDiscountPopupsInfoBar();
});
}
},1000)
}
getProductJson = (mergeData = {}) => {
const productJson = document.querySelector("#product-json");
let productJsonData = {};
if (productJson && productJson.textContent) {
try {
productJsonData = JSON.parse(productJson.textContent);
} catch (e) {}
}
// ๆทฑๅบฆๅๅนถๅฝๆฐ
const deepMerge = (target, source) => {
if (source === null || source === undefined) {
return target;
}
if (typeof source !== 'object' || Array.isArray(source)) {
return source;
}
const result = { ...target };
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (
typeof source[key] === 'object' &&
source[key] !== null &&
!Array.isArray(source[key]) &&
typeof target[key] === 'object' &&
target[key] !== null &&
!Array.isArray(target[key])
) {
result[key] = deepMerge(target[key], source[key]);
} else {
result[key] = source[key];
}
}
}
return result;
};
return deepMerge(productJsonData, mergeData);
}
getProduct = (() => {
document.addEventListener("dj.variantChange", e => {
if (!e.detail || !e.detail.product) return;
let productJsonData = getProductJson(e.detail);
if (this.win.jQuery && this.win.jQuery.fn && this.win.jQuery(document).data("djproduct") && productJsonData) {
this.win.jQuery(document).data("djproduct", productJsonData);
}
});
return () => {
let productData = null;
if (this.win.jQuery && this.win.jQuery.fn) {
try {
let product = this.win.jQuery(document).data("djproduct");
if (product) {
productData = JSON.parse(JSON.stringify(product));
} else {
productData = null;
}
} catch (error) {
productData = null;
}
}
if (!productData) {
const productJson = document.querySelector("#product-json");
productData = (productJson && productJson.textContent && JSON.parse(productJson.textContent)) || null;
}
return productData;
};
})();
clearRebateInfoDom = () => {
// 1. ๆธ
้ค apis.render ๆธฒๆ็ DOM (app_rebate_section)
const rebateSection = document.getElementById('app_rebate_section');
if (rebateSection) {
const rebateRuleSection = rebateSection.querySelector('.rebate_rule_section');
if (rebateRuleSection) {
rebateRuleSection.remove();
}
}
// 2. ๆธ
้ค templates_.renderTemplate ๆธฒๆ็ DOM (app_rebate_block)
const rebateBlock = document.getElementById('app_rebate_block');
if (rebateBlock) {
const appRebateList = rebateBlock.querySelector('.app_rebate_list');
if (appRebateList) {
appRebateList.remove();
}
}
// 3. ๆธ
้ค insertProductDetailRebateTag ๆๅ
ฅ็ DOM
// ๆธ
้คๆๆ rebate-tag ๅ
็ด
document.querySelectorAll('.slider-discount-tag.dj_skin_product_title.rebate-tag').forEach(tag => {
tag.remove();
});
// ็งป้ค data-rebate-tag ๅฑๆง
const productContainer = document.querySelector('.product-details, .product-details, .page_container, .product-images, [data-section-type="product"]');
if (productContainer && productContainer.hasAttribute('data-rebate-tag')) {
productContainer.removeAttribute('data-rebate-tag');
}
};
initRebate = this.win.SPZCore.Types.debounce(
this.win,
(async (data) => {
let discount_list = Object.assign([], this.rebateInfo?.discount_list);
/* ๆๅญๅๅ็ๅคๅฐๅฏนไผๆ ไฟกๆฏ่ฟ่กๆๅบ */
discount_list &&
discount_list.sort((a, b) => {
return b.variant_ids.length - a.variant_ids.length;
});
/* ้ไธญๅญๅๅๆถ ็ญ้ๅญๅๅ็ไผๆ ไฟกๆฏ */
if (data.selected && data.selected.id) {
discount_list = this.getVariantDiscountId(data.selected.id);
}
/* ๆ ๆปกๅไฟกๆฏ */
if (!(discount_list && discount_list.length)) {
this.clearRebateInfoDom();
return;
}
const isSection = !!document.querySelector(
`div[data-section-type^="shoplazza://apps/publicapp/blocks/rebate"] #rebate_custom_component`
);
if (
(this.rebateInfo.rebate_type == "sku" && data && data.selected && data.selected.id) ||
this.rebateInfo.rebate_type == "spu"
) {
let nowLandpage = this.landPage;
if (discount_list[0]) {
nowLandpage = this.landPage + discount_list[0].discount_id || "";
}
const info = {
rebate: discount_list[0],
maxShowCount: this.win.innerWidth > 768 ? 3 : 1,
landPage: nowLandpage,
modalFooterImg: `url(${`${this.win.SHOPLAZZA["image_domain"]}oss/operation/e8ebb03dbb710457ca3b4b6a70898ab2.svg`})`,
};
this.renderData = info;
if(isSection) {
SPZ.whenApiDefined(
document.getElementById("app_rebate_section")
).then(apis => {
apis.render(info, true);
});
} else {
// ้ๆฐๆธฒๆ ๆๅจ้ฎ้ขๅค็
this.templates_ = SPZServices.templatesForDoc();
const newTplDom = await this.templates_.renderTemplate(document.querySelector('#appRebateBlockTpl'), info)
const parentDiv = document.querySelector('#app_rebate_block');
const oldDom = parentDiv.querySelector('.app_rebate_list');
if(oldDom){
parentDiv.replaceChild(newTplDom, oldDom);
} else {
parentDiv.appendChild(newTplDom);
}
}
}
this.insertProductDetailRebateTag(this.rebateInfo.tag);
var pluginCurrencyEvent = new CustomEvent("plugin_currency_update");
document.dispatchEvent(pluginCurrencyEvent);
}).bind(this),
10
);
getRebateInfo = async () => {
if (this.initData && this.initData.product && this.initData.product.id) {
var variant_ids = this.initData.product.variants.map(variant => variant.id);
const res = await this.xhr_.fetchJson(
"\/api\/discount-rebate\/product-discount",
{
method: "POST",
body: {
product_id: this.initData.product.id,
product_type: this.initData.product.product_type,
variant_ids: variant_ids,
},
}
);
if (!SPZCore.Types.isEmptyObject(res.rebate_info)) {
res.rebate_info.tag = res.tag;
res.rebate_info.rebate_type = res.rebate_type;
this.rebateInfo = res.rebate_info;
this.initRebate(this.initData);
} else {
if (this.win.top !== this.win.self) {
const noActivity = document.getElementById("no-rebate-activity");
noActivity && (noActivity["style"].display = "block");
}
}
}
};
getVariantDiscountId = (variant_id) => {
if (!variant_id || !this.rebateInfo) return [];
var rebateId = this.rebateInfo.variant_discount_map[variant_id];
return this.rebateInfo.discount_list.filter(item => item.discount_id == rebateId) || [];
};
insertProductDetailRebateTag = (tag) => {
if (!tag) return
// ๆงๅคๆญ้ป่พ
const productSelectModal = document.querySelector('#product-select-modal');
if (productSelectModal && productSelectModal.classList.contains('show')) {
return;
}
setTimeout(() => {
var $tag_container = [];
if (isNova23) {
$tag_container = document.querySelectorAll('.product-details .product-images-container');
} else if (isFlash) {
$tag_container = document.querySelectorAll('.product-detail .product-images .product-main-images-container');
} else if (isGeek) {
$tag_container = document.querySelectorAll('.product-images #product-images-inner-container spz-carousel .i-spzhtml-slide-item');
} else if (isWind) {
$tag_container = document.querySelectorAll('.product-detail .product-images-container .i-spzhtml-slides-container');
} else if (isOnePage) {
$tag_container = document.querySelectorAll('.product-details .product-main-images');
} else if (isHero) {
$tag_container = document.querySelectorAll('.product-detail #product-images-container #product-images-carousel .spz-carousel-slide');
} else if (isBoost) {
$tag_container = document.querySelectorAll('.boost-product-detail .product-image__layout-list .slides .slides-item .product-info__slide .slider-zoom');
} else if (isEva) {
$tag_container = document.querySelectorAll('.page_container [data-section-type="product"] .support-slick');
} else if (isFarida) {
$tag_container = document.querySelectorAll('.product-details .product-images-container');
} else if (isLifeStyle) {
$tag_container = document.querySelectorAll('.page_container [data-section-type="product_detail"] .sep-slider,.support-slick');
} else if (isPluto) {
$tag_container = document.querySelectorAll('.page_container [data-section-type="product_detail"] .sep-slider,.support-slick');
}
if($tag_container.length === 0) return;
// ็ปๅ็ฅฅ้กตๆทปๅ ๆปก้ๆไปถ็ๆ ่ฏๅฑๆง
const $product_container = document.querySelector('.product-details, .product-details, .page_container, .product-images, [data-section-type="product"]')
if($product_container) {
$product_container.setAttribute('data-rebate-tag', 'true');
}
// ้จๅไธป้ข้่ฆ่ฐๆดๆ ทๅผ
if (isWind) {
Array.from($tag_container).forEach(container => {
container.style.position = 'relative';
});
}
document.querySelectorAll('.slider-discount-tag.dj_skin_product_title.rebate-tag').forEach(tag => tag.remove());
// ้ๅๆๆๅฎนๅจๅนถๆๅ
ฅๆ ็ญพ
Array.from($tag_container).forEach(container => {
container.insertAdjacentHTML('beforeend', `<div class="slider-discount-tag dj_skin_product_title rebate-tag">${tag}</div>`);
});
}, 1000)
};
fetchInfoBar = async () => {
let discount_ids = [];
if (this.pageType === 1) {
discount_ids = this.rebateInfo && this.rebateInfo.discount_list.map(item => item.discount_id);
} else if (this.pageType === 38) {
discount_ids = [this.win.rebateObj.rebateCollection_id] || [];
}
const productObj = this.getProduct();
const { cart } = await this.xhr_.fetchJson('/api/cart')
return this.xhr_.fetchJson("\/api\/discount-rebate\/global-text", {
method: "POST",
body: {
product_type: productObj && productObj.product && productObj.product.product_type,
line_items: (cart?.line_items || []).map(item => ({
variant_id: item.variant_id,
product_id: item.product_id,
quantity: item.quantity,
price: item.price,
selected: !item.unchecked,
})),
discount_ids: discount_ids,
},
});
};
renderBottomBanner = res => {
if (!res.tips) return;
document.querySelector(".discount__info-bar")?.remove();
var bar_style = `background:linear-gradient(90deg,${res.config.background_color_start},${res.config.background_color_end}); color:${res.config.color};`;
let data = { tips: res.tips, landPage: this.landPage + res.id, bar_style };
const html = SPZCore.Dom.htmlFor(this.element);
const banner = html([
`<a impr="1" imprevt="1" id="rebate_bottom_bar" href=${data.landPage} class="discount__info-bar text-truncate" data-activity-type="rebate" style="${data.bar_style}">${data.tips}</a>`,
]);
document.querySelector(".plugin-container__bottom-fixed").appendChild(banner);
const pluginCurrencyEvent = new CustomEvent("plugin_currency_update");
document.dispatchEvent(pluginCurrencyEvent);
if (res.id) {
var trackParams = {
page: this.pageType,
discount_id: res.id,
product_id: this.getProduct()?.product.id,
};
banner.addEventListener("click", () => {
this.win.sa &&
this.win.sa.track("plugin_rebate_promotion_click", {
plugin_timestamp: Date.now(),
plugin_location: "bottom_bar",
product_id: trackParams.product_id,
discount_id: trackParams.discount_id,
});
});
this.win.sa && this.win.sa.track("plugin_rebate_banner_pv", trackParams);
}
};
showDiscountPopupsInfoBar = () => {
if ([13, 14, 19, 30, 31].includes(this.pageType)) return;
if (document.querySelector(".plugin-container__bottom-fixed .discount__info-bar")) return;
this.fetchInfoBar().then(this.renderBottomBanner);
document.addEventListener("dj.cartChange", () => {
this.fetchInfoBar().then(this.renderBottomBanner);
});
};
}
SPZ.defineElement("spz-custom-rebate", SpzRebateComponent);
${function(){
return `
`
} ()}
${function(){
const { original_price, received_discounts, picked_qty } = data;
const button_text = originData.setting.button.text;
const button_config = JSON.parse(originData.setting.button.config);
const button_action = originData.setting.button.redirect_page;
const text = originData.setting.price_text_config.text;
const price_config = JSON.parse(originData.setting.price_text_config.config);
const price_text = text.replace(/\{picked_qty\}/g, `${picked_qty}`).replace(/\{original_price\}/g, ``).replace(/\{received_discounts\}/g, ``);
return `
${price_text}
${button_text}
`
}()}
${function(){
return `
`
} ()}
x ${data.discount_min_purchase_qty}
${function() {
const images = data.images || [];
const selectedVariant = data.variants.find(v => (v.available && v.is_hit_discount == true)) || data.variants[0];
const selectedIndex = !!selectedVariant ? images.findIndex(img => img.src === (selectedVariant.image && selectedVariant.image.src)) : 0;
const initialSlide = selectedIndex === -1 ? 0 : selectedIndex;
return `
${images.map((image, index) => `
`).join('')}
${images.map(image => { const imageWidth = image.width || 450; const imageHeight = image.height || 450; return ` ` }).join('')}
`;
}()}
${function() {
const productData = data;
const limit_purchase = data.limit_purchase || 0;
let product_change_event = '';
let mouse_over_event = '';
let mouse_out_event = '';
const product_options = productData.options.filter(Boolean) || [];
for (let opt of product_options) {
const nameEscape = opt.name.replace(/\/|\\|\s|\'|\"|`|\<|\>/g, '');
product_change_event = product_change_event + `apps-discount-quick-shop-selected-variant-${opt.id}.rerender(data=event.selectedValues.${opt.name});`;
mouse_over_event = mouse_over_event + `@${nameEscape}Mouseover="apps-discount-quick-shop-selected-variant-${opt.id}.rerender(data=event);"`;
mouse_out_event = mouse_out_event + `@${nameEscape}Mouseout="apps-discount-quick-shop-selected-variant-${opt.id}.rerender(data=event.selectData.${opt.name});"`;
}
const selectedVariant = productData.variants.find(v => (v.available && v.is_hit_discount == true)) || productData.variants[0];
const statusLan = ((selectedVariant && !selectedVariant.available) || (!selectedVariant && !productData.available)) ?
"Sold out" :
"Add to cart";
const status = (
(selectedVariant && !selectedVariant.available) ||
(!selectedVariant && !data.available)) ? 'soldout' : 'available';
return `
${data.title || data.brief}
Add ${productData.discount_min_purchase_qty} items for discount
`;
}()}
${function() {
const selectedVariant = data.variant || data.variants[0];
const image = selectedVariant.image || data.product.image;
const imageWidth = image?.width || 120;
const imageHeight = image?.height || 120;
return `
`
}()}
${function() {
const defaultVariant = data.variants?.find(v => (v.available && v.is_hit_discount == true)) || data.variants?.[0];
const selectedVariant = data.variant || defaultVariant;
const isHasRrice = (selectedVariant.price || selectedVariant.price == 0) ? true : false;
if(selectedVariant.flash_sale_info && selectedVariant.flash_sale_info.discount_price) {
selectedVariant.price = selectedVariant.flash_sale_info.discount_price;
}
if(data.flash_sale_info && data.flash_sale_info.discount_price) {
data.price = data.flash_sale_info.discount_price;
}
return !!selectedVariant ? `
` : `
-
`;
}()}
${function(){
const defaultVariant = data.variants?.find(v => (v.available && v.is_hit_discount == true)) || data.variants?.[0];
const selectedVariant = data.variant || defaultVariant;
let show_flashsale_limit_tip = false;
let limit_user_product_discount;
if(selectedVariant.flash_sale_info && selectedVariant.flash_sale_info?.limit_user_product_type != "LUPT_NO_LIMIT" && selectedVariant.flash_sale_info?.limit_user_product_discount > 0) {
show_flashsale_limit_tip = true;
limit_user_product_discount = selectedVariant.flash_sale_info?.limit_user_product_discount;
}
if(data.flash_sale_info && data.flash_sale_info?.limit_user_product_type != "LUPT_NO_LIMIT" && data.flash_sale_info?.limit_user_product_discount > 0) {
show_flashsale_limit_tip = true;
limit_user_product_discount = data.flash_sale_info?.limit_user_product_discount;
}
return `
Promo products limited to ${limit_user_product_discount} item per person
`
}()}
${function() {
const currentProduct = data.product;
return (currentProduct.options || []).map((option, index) => {
const optionName = option.name || '';
const optionId = option.id || '';
const position = `option${index + 1}`;
return `
`;
}).join('')
}()}
${function() {
const value = (data.originData && data.originData.value) || data.value;
const isHasValue = value ? true : false;
return `
${value}
`
}()}
${(function() {
const productsInfo = data.product_info && data.product_info.product ? data.product_info.product : data;
return productsInfo.map(product => {
let price = product.price || 0;
let priceMin = product.price_min || 0;
let priceMax = product.price_max || 0;
let compareAtPriceMax = product.compare_at_price_max || 0;
let compareAtPrice = product.compare_at_price || 0;
let title = product.title || '';
let id = product.id || '';
let url = product.url || '';
let type = product.type || '';
let is_sold_out = false;
if (product.available == false && product.inventory_policy != 'continue') {
is_sold_out = true;
}
const soldOutLang1 = "Sold out";
const soldOutLang2 = "Sold out";
const discountType = data.discount_info ? data.discount_info.discount_type : product.discount_type;
const defaultVariantTitle = product.variants[0]?.title.replace('-', '/');
const variantDiscountInfo = product.variants[0]?.discount_info || {};
let discount_min_purchase_qty = 0;
if (discountType === "DT_CLASSIC_BUNDLE" && data.discount_info.enable_min_purchase_qty) {
discount_min_purchase_qty = data.discount_info.min_purchase_qty_type === "spu" ? product.discount_min_purchase_qty : product.variants[0].discount_info.discount_min_purchase_qty;
}
let imageWidth;
if (product.image.width) {
imageWidth = product.image.width;
} else {
imageWidth = "300px";
}
let imageHeight;
if (product.image.height) {
imageHeight= product.image.height;
} else {
imageHeight = "300px";
}
if (product.published) {
return `
${function(){
if (soldOutLang1){
return `
${soldOutLang1}
`
}else{
return `
${soldOutLang2}
`
}
}()}
x ${discount_min_purchase_qty}
`
} else {
return ``;
}
}).join('');
})()}
// ๅๅๅผน็ชไธ้ฆ้กต้ๆถไฟ้ๅก็ๅ
ฑ็จๆ ทๅผ id "discount-match-drawer"๏ผไผไบง็้ๅค idใ
// ็จๅผน็ชๆ น่็นไธไธ็จ็ js- ๅ็ผ้ฉๅญ็ฑปๅฏไธๅฎไฝไฝ็จๅๆ น๏ผ้ฟๅ
ๅฝไธญ้ฆ้กตๅก็ๅฏผ่ดๅผน็ชๅ
ๅ
็ด ๆฅ่ฏขๅคฑ่ดฅใ
const getDiscountMatchPopupEl = () => document.querySelector('.js-discount-match-popup');
class SpzCustomDiscountBundleProducts extends SPZ.BaseElement {
constructor(element) {
super(element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.getDiscountPriceApi = "\/api\/storefront\/promotion\/calculate\/discounted_price";
this.buyNowApi = "\/api\/checkout\/order";
this.batchAtcApi = "\/api\/cart\/batch";
// ๆฌพๅผไฟกๆฏ้ๅ
this.productStyleInfo = [];
// ๅผน็ชๅ
้ๆฉๆฌพๅผ้ๅ
this.modalVariantInfo = [];
this.show_classic_bundle_spu_style = false;
this.bundleProducts = []; //ๆ็ปๅๅ
this.bundleConfig = {}; //ไธๆนๆ้ฎ้
็ฝฎ
this.discountId = "";
this.discountType = "";
this.discountInfo = "";
this.lineItems = [];
this.tempCss = {};
this.renderQuickShop_ = this.win.SPZCore.Types.debounce(this.win, this.renderQuickShopModal.bind(this), 500);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
this.setupAction_();
};
init(data = []) {
this.productStyleInfo = data;
}
handleRequestError_(data) {
this.showToast(data?.message || data?.errors?.[0] || 'Unknown error');
};
showToast(message) {
SPZ.whenApiDefined(document.getElementById("cart_match_discount_toast")).then((apis) => {
apis.showToast(message);
});
}
//ๅค้จ็ปไปถ่ฐ็จไผ ๅผ
setBundleData(products, config = "", id = "", type = "", info = {}) {
this.bundleProducts = products;
if(config) {
this.bundleConfig = config;
this.discountId = id;
this.discountType = type;
this.discountInfo = info;
this.show_classic_bundle_spu_style = type === 'DT_CLASSIC_BUNDLE' && info.enable_min_purchase_qty && info.min_purchase_qty_type == 'spu';
// ็ปๅ
ธๆ็ปๅๅงๅๅๅๆฐๆฎ
if(type == 'DT_CLASSIC_BUNDLE') {
this.productStyleInfo = products.map((item) => {
return this.getFilteredVariants_(item, 'single');
});
}
}
}
handleChangeSort() {
const result = this.productStyleInfo.reduce((map, item) => {
if (!map[item.product_id]) {
map[item.product_id] = [];
}
map[item.product_id].push(item);
return map;
}, {});
Object.values(result).forEach((item) => {
this.handleSpzVariantRender_(item, item[0].product_id);
this.handleProductOption_(item[0].product_id, true);
});
}
// ่ฐ็จspz-tag็ปไปถ็doRenderๆนๆณ
handleSpzVariantRender_(data, id) {
const spzVariantTag = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionSpzVariantTags-${id}`);
spzVariantTag && SPZ.whenApiDefined(spzVariantTag).then((api) => {
api.render(data, true);
});
}
// ๆง่ก็ปๅ
ธๆ็ปๆไฝ่ดญไนฐๆฐ้ๆดๆฐ
handleMinPurchaseQtyUpdate_(data, id) {
const minPruchaseQty = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionMinPurchaseQty-${id}`);
minPruchaseQty && SPZ.whenApiDefined(minPruchaseQty).then((api) => {
api.render(data, true);
});
}
// ๆดๆฐไปทๆ ผ
updateProductPrice_(data) {
const bottomBtnContainer = SPZCore.Dom.scopedQuerySelector(getDiscountMatchPopupEl() || document.body, `#promotionBottomContainer`);
if (data.length == 0) {
bottomBtnContainer && SPZ.whenApiDefined(bottomBtnContainer).then((api) => {
const renderInfo = {
setting: this.bundleConfig,
...{
original_price: 0,
received_discounts: 0,
picked_qty: 0
}
}
api.render({original_price: 0, received_discounts: 0}, true);
});
return;
}
const reqBody = {
discount_id: this.discountId,
customer: {
customer_id: '',
email: '',
},
sales_channel: {
sale_channel_type: "online",
sale_channel_id: '1319604'
},
line_items: data
}
// ๅฆๆๅทฒ็ปๆไธไธช่ฏทๆฑๅจ็ญๅพ
๏ผ้ฃไนๅๆถ่ฟไธช่ฏทๆฑ
if (this.debounceTimer) {
clearTimeout(this.debounceTimer);
}
this.debounceTimer = setTimeout(() => {
this.xhr_.fetchJson(this.getDiscountPriceApi, {
method: "post",
body: reqBody
}).then((res)=>{
// ๆดๆฐๅๅๅ่กจไปทๆ ผ
Object.keys(res.line_items).forEach((key) => {
const currentProductPrice = SPZCore.Dom.scopedQuerySelector(document.body, `#appDiscountProductPrice-${key}`);
currentProductPrice && SPZ.whenApiDefined(currentProductPrice).then((api) => {
api.render(res.line_items[key], true);
});
});
// ๆดๆฐๅบ้จๆ้ฎๆปไปท/ๆปๆๆฃไปท
const picked_qty = data.reduce((acc, item) => {
return acc + item.quantity;
}, 0);
bottomBtnContainer && SPZ.whenApiDefined(bottomBtnContainer).then((api) => {
const data = {
setting: this.bundleConfig,
...{
...res.total_price,
picked_qty
}
}
api.render(data, true);
});
}).catch((err)=>{
this.handleRequestError_(err);
}).finally(()=>{
})
}, 100);
}
// ่ฟๅๅๅไปทๆ ผ
resetProductPrice_(data) {
const {price, compare_at_price, id} = data;
const currentProductPrice = SPZCore.Dom.scopedQuerySelector(document.body, `#appDiscountProductPrice-${id}`);
currentProductPrice && SPZ.whenApiDefined(currentProductPrice).then((api) => {
api.render({total_received_discounts: price, total_price: compare_at_price}, true);
});
}
//ๅค็ไธselector็ปไปถ็ไบคไบ
handleProductOption_(productId, show) {
const currentProductOption = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionSelectOption-${productId}`);
if (!currentProductOption) {
return;
};
currentProductOption.toggleAttribute('show', show);
const isSelected = currentProductOption.hasAttribute('selected');
// !show ๅๆถ้ไธญ
// !isSelected ้ไธญๅๅ
if (!show || !isSelected) {
const productSelector = SPZCore.Dom.scopedQuerySelector(getDiscountMatchPopupEl() || document.body, `#promotionProductSelector`);
productSelector && SPZ.whenApiDefined(productSelector).then((api) => {
api.toggle_({ option: productId, value: show });
});
}
}
// ๆททๆญๅผน็ชๅ
็ๅ็ซฏๅบๅญๆ ก้ช
handleModalInventoryCheck_(data) {
if(this.discountType == 'DT_MIX_MATCH_BUNDLE' || this.discountType == 'DT_CLASSIC_BUNDLE') {
const currentVariantAddNum = this.modalVariantInfo.find((item) => item.variant_id == data.variant_id)?.quantity || 0;
const quickShopBody = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-shop-body');
if(!!data.variant && currentVariantAddNum == Number(data.variant.available_quantity)) {
quickShopBody && quickShopBody.setAttribute('status', 'soldout');
} else {
quickShopBody && quickShopBody.setAttribute('status', 'available');
}
} else {
return;
}
}
// ๆทปๅ ๅๅๅญๆฌพๅผ
renderVariantTag() {
let variantInfo;
const quickShopBody = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-shop-body');
quickShopBody && SPZ.whenApiDefined(quickShopBody).then((api) => {
variantInfo = api.getVariantsData();
const productId = variantInfo.product_id;
const variantId = variantInfo.variant_id;
const minPruchaseQtyRender = variantInfo.product.discount_min_purchase_qty || variantInfo.variant.discount_info.discount_min_purchase_qty;
if(this.discountType === 'DT_MIX_MATCH_BUNDLE') {
const index = this.productStyleInfo.findIndex((item) => item.variant_id == variantInfo.variant_id);
if (index != -1) {
this.productStyleInfo[index].quantity = Number(this.productStyleInfo[index].quantity) + Number(variantInfo.quantity);
this.updateProductPrice_(this.productStyleInfo);
} else {
this.productStyleInfo.push(this.getFilteredVariants_(variantInfo));
// ่ฅๅฝๅๅๅๅทฒ้ไธญ๏ผๆดๆฐๅๅไปทๆ ผ
const currentProductOption = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionSelectOption-${productId}`);
const isSelected = currentProductOption && currentProductOption.hasAttribute('selected');
isSelected && this.updateProductPrice_(this.productStyleInfo);
}
const selectedVariantsFilter = this.productStyleInfo.filter((item) => item.product_id == productId);
this.handleSpzVariantRender_(selectedVariantsFilter, productId);
this.handleProductOption_(productId, true);
} else {
if(this.discountInfo.enable_min_purchase_qty == true && this.discountInfo.min_purchase_qty_type == 'spu' && minPruchaseQtyRender > 1) {
const index = this.modalVariantInfo.findIndex((item) => item.variant_id == variantId);
if (index != -1) {
this.modalVariantInfo[index].quantity = Number(this.modalVariantInfo[index].quantity) + 1;
} else {
this.modalVariantInfo.push(this.getFilteredVariants_(variantInfo, 'classic_spu'));
}
const modalVariantTag = SPZCore.Dom.scopedQuerySelector(getDiscountMatchPopupEl() || document.body, '#promotionModalVariantTagRender');
modalVariantTag && SPZ.whenApiDefined(modalVariantTag).then((api) => {
api.render(this.modalVariantInfo, true);
});
this.handleModalInventoryCheck_(variantInfo);
const selectedVariantsNum = this.modalVariantInfo.reduce((acc, item) => {
return acc + item.quantity;
}, 0);
if(selectedVariantsNum == minPruchaseQtyRender) {
this.handleSpzVariantRender_([this.getFilteredVariants_(variantInfo)], productId);
this.productStyleInfo = this.productStyleInfo.filter((item) => item.product_id != productId).concat(this.modalVariantInfo);
const renderData = this.productStyleInfo.filter((item) => item.product_id == productId).map((item) => {
return {
...item,
is_classic_bundle_product_list_variant_tag: true
}
});
const classicSpuTag = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionClassicSpuTags-${productId}`);
classicSpuTag && SPZ.whenApiDefined(classicSpuTag).then((api) => {
api.render(renderData, true);
});
this.updateProductPrice_(this.productStyleInfo);
const quickView = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-view');
quickView && SPZ.whenApiDefined(quickView).then((api)=>{
api.close();
});
this.modalVariantInfo = [];
} else {
return;
}
}
// this.productStyleInfo ไธญๅทฒๅญๅจไธproductId, variantId้ฝ็ธๅ็ๅๅ ๅ็ดๆฅreturn ๅ
ณ้ญๅผน็ช
const isExist = this.productStyleInfo.some((item) => item.product_id == productId && item.variant_id == variantId);
if (isExist) {
const quickView = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-view');
quickView && SPZ.whenApiDefined(quickView).then((api)=>{
api.close();
});
return;
}
// ่ฅ this.productStyleInfo ไธญๅทฒๅญๅจไธproductId็ธๅ็ๅๅ๏ผๅไธๅๆทปๅ ๅฆๅๆฟๆข
const index = this.productStyleInfo.findIndex((item) => item.product_id == productId);
if (index != -1) {
this.productStyleInfo[index] = this.getFilteredVariants_(variantInfo);
} else {
this.productStyleInfo.push(this.getFilteredVariants_(variantInfo));
}
const selectedVariantsFilter = this.productStyleInfo.filter((item) => item.product_id == productId);
this.handleSpzVariantRender_(selectedVariantsFilter, productId);
this.handleMinPurchaseQtyUpdate_({discount_min_purchase_qty: minPruchaseQtyRender}, productId);
this.updateProductPrice_(this.productStyleInfo);
}
const quickView = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-view');
quickView && SPZ.whenApiDefined(quickView).then((api)=>{
api.close();
});
});
}
// ๅๅไฝ็นๅปๆทปๅ ๆ้ฎ
renderSingleVariant(data) {
const { product_id } = data;
const currentProduct = this.bundleProducts.find((product) => product.id == product_id);
// ่ฅๅฝๅๅๅๅทฒๅญๅจ๏ผๅไธๅๆทปๅ ่ๆฏๆดๆฐๆฐ้
const index = this.productStyleInfo.findIndex((item) => item.product_id == product_id);
if (index != -1) {
this.productStyleInfo[index].quantity = Number(this.productStyleInfo[index].quantity) + 1;
this.updateProductPrice_(this.productStyleInfo);
} else {
this.productStyleInfo.push(this.getFilteredVariants_(currentProduct, 'single'));
}
const renderProductArr = this.productStyleInfo.filter((item) => item.product_id == product_id);
this.handleSpzVariantRender_(renderProductArr, product_id);
this.handleProductOption_(product_id, true);
}
// ่ฟๆปค้ไธญๅๅ็ๅญๆฌพๅผ ่ทๅๆ็จ็ไฟกๆฏ product_id,variant_id,price,compare_at_price,quantity,title,variant_title
getFilteredVariants_(data, type = '') {
const { id, title, variants, inventory_tracking, inventory_policy, inventory_quantity, product_type } = data;
const { product_id, variant_id, variant, quantity, product, discount_min_purchase_qty } = data;
const isSingle = type == 'single';
const variantData = isSingle ? (variants[0] || data) : variant;
const productData = isSingle ? data : product;
let item_quantity = 0;
if (this.discountType === 'DT_MIX_MATCH_BUNDLE') {
item_quantity = isSingle ? 1 : Number(quantity);
} else if (type === 'classic_spu') {
item_quantity = 1;
} else {
item_quantity = discount_min_purchase_qty || productData.discount_min_purchase_qty || variantData.discount_info.discount_min_purchase_qty || 1;
}
return {
product_id: isSingle ? id : product_id,
variant_id: variantData?.id || '',
price: variantData?.price || '0.00',
compare_at_price: variantData?.compare_at_price || '0.00',
quantity: item_quantity,
inventory_tracking: productData.inventory_tracking,
inventory_policy: productData.inventory_policy,
inventory_quantity: productData.inventory_quantity,
product_type: productData.product_type || this.bundleProducts.find((item) => item.id == product_id)?.product_type || this.bundleProducts.find((item) => item.id == id)?.product_type || '',
title: productData.title,
variant_title: variantData?.options.map((option) => option.value).join('/') || '',
is_multi_style: productData.variants.length > 1,
}
}
handleLoading_ (event) {
const { type, action } = event;
const loadingElementId = type === 'product' ? '#discount-match-drawer-products_loading' : '#apps-discount-whole-loading';
const loadingElement = document.querySelector(loadingElementId);
if (loadingElement) {
SPZ.whenApiDefined(loadingElement).then((api) => {
if (action === 'show') {
api.show_();
} else {
api.close_();
}
});
}
}
handleSelectProduct(productArr) {
// ไปthis.productStyleInfo ่ฟๆปคๅบ้ไธญ็ๅๅ
const selectedProducts = this.productStyleInfo.filter((item) => productArr.includes(item.product_id));
this.updateProductPrice_(selectedProducts);
}
// ๆธฒๆๅ ่ดญๅผน็ชๅ
ๅฎน
async renderQuickShopModal(data){
this.handleLoading_({type: 'whole', action: 'show'});
this.xhr_.fetchJson(`/api/storefront/promotion/landing_page/product?product_id=${data.product_id}&discount_id=${this.discountId}&apply_scenario=1`, {
method: "get",
}).then(async(res)=>{
//flashไธป้ขๆพblockๆๅฑ็บง้ฎ้ข
if(/Flash/.test(window.C_SETTINGS.theme.merchant_theme_name) && document.querySelector(".productInfoSection")) {
this.tempCss.zIndex = document.querySelector(".product-info-body").style.zIndex;
document.querySelector('.product-info-body').style.zIndex="1048";
}
this.handleLoading_({type: 'whole', action: 'close'});
const $quickShop = await SPZ.whenApiDefined(document.querySelector('#apps-discount-quick-view-render'));
// ๅฎไน้ป่ฎคๆธฒๆ็ๅญๆฌพๅผ
const selectedVariant = res.product.variants.find((v)=> (v.available && v.is_hit_discount)) || res.product.variants[0];
let selectedValues = {};
selectedVariant.options.length && selectedVariant.options.forEach(item => {
selectedValues[item.name] = item.value;
})
// ้ป่ฎค้ไธญ็ ๅญๆฌพๅผใ options
res.product.defaultSelectValues = selectedValues;
let data = {...res.product, product:res.product, selectedVariant, show_classic_bundle_spu_style: this.show_classic_bundle_spu_style, discountType: this.discountType};
$quickShop.render(data);
// ๆๅผๅ ่ดญๅผน็ช
SPZ.whenApiDefined(document.querySelector(`#apps-discount-quick-view`)).then((api)=>{
api.open();
});
}).catch((err)=>{
this.handleLoading_({type: 'whole', action: 'close'});
})
}
// ่ทๅ้ไธญ็ๅๅids
getDefaultSelectorOptions_() {
try {
const selectedOptions = SPZCore.Dom.scopedQuerySelectorAll(document.body, '[id^="promotionSelectOption-"][selected]');
return SPZCore.Types.toArray(selectedOptions).map((item) => item.getAttribute('option'));
} catch (error) {
return [];
}
}
// ๅ ้คๅๅๅญๆฌพๅผ
deleteVariantTag(data) {
const { product_id, variant_id } = data;
if(this.discountInfo.enable_min_purchase_qty == true && this.discountInfo.min_purchase_qty_type == 'spu') {
const modalProductVariants = this.modalVariantInfo.filter((item) => item.product_id == product_id && item.variant_id != variant_id);
const modalVariantTag = SPZCore.Dom.scopedQuerySelector(getDiscountMatchPopupEl() || document.body, '#promotionModalVariantTagRender');
modalVariantTag && SPZ.whenApiDefined(modalVariantTag).then((api) => {
api.render(modalProductVariants, true);
});
this.handleModalInventoryCheck_(data);
this.modalVariantInfo = modalProductVariants;
return;
}
const currentProductVariants = this.productStyleInfo.filter((item) => item.product_id == product_id && item.variant_id != variant_id);
this.handleSpzVariantRender_(currentProductVariants, product_id);
// ๆดๆฐselectedVariants
this.productStyleInfo = this.productStyleInfo.filter((item) => item.variant_id != variant_id);
if(currentProductVariants.length > 0) {
// currentProductVariants ไธญๅช่ฆๆไธ้กนๆฏๅคๆฌพๅผๅๅ๏ผๅฐฑๆดๆฐไปทๆ ผ
const isMultiStyle = currentProductVariants.some((item) => item.is_multi_style);
if (!isMultiStyle) return;
this.handleProductOption_(product_id, true);
const selected = this.getDefaultSelectorOptions_();
this.updateProductPrice_(this.productStyleInfo.filter((item) => selected.includes(item.product_id)));
} else {
this.handleProductOption_(product_id, false);
this.resetProductPrice_(this.bundleProducts.find((item) => item.id == product_id));
}
}
// ๅ ่ดญๅผน็ชๆชๅไธๆดปๅจ ๅ ่ดญๆ้ฎไธๅฏ็นๅป TODO ๆๅบๆฅ
handleNotHitDiscount_(data) {
const $quickShopBody = document.querySelector('#apps-discount-quick-shop-body');
//ๅฝๅๅญๆกๅผๆชๅฝไธญๆดปๅจ
if(data.variant.is_hit_discount == false) {
$quickShopBody.setAttribute('variantstatus', 'notHitDiscount')
} else {
$quickShopBody.setAttribute('variantstatus', '')
}
}
setupAction_() {
// ๅญๆฌพๅผ ๆชๅไธๆดปๅจ
this.registerAction('handleNotHitDiscount', (invocation) => {
const data = invocation.args.data;
this.handleNotHitDiscount_(data);
});
// ๆธฒๆๅ ่ดญๅผน็ช
this.registerAction('renderQuickShop', (invocation) => {
const data = invocation.args;
this.renderQuickShop_(data);
});
this.registerAction('renderSingleVariant', (invocation) => {
const data = invocation.args;
this.renderSingleVariant(data);
});
this.registerAction('getVariantInfo', (invocation) => {
this.renderVariantTag();
});
this.registerAction('deleteVariantTag', (invocation) => {
const data = invocation.args;
this.deleteVariantTag(data);
});
this.registerAction('getSelectedProduct', (invocation) => {
const data = invocation.args.data;
this.handleSelectProduct(data);
});
//TODO ๅ ่ดญไธๅ้ป่พๅ็ฌๆ็ปไปถ
this.registerAction('handleClick', (data) => {
if(this.discountType == 'DT_CLASSIC_BUNDLE') {
this.lineItems = this.productStyleInfo;
} else {
const selectedOptions = SPZCore.Dom.scopedQuerySelectorAll(document.body, '[id^="promotionSelectOption-"]');
const idArr = [...selectedOptions].reduce((acc, item) => {
if (item.hasAttribute('selected')) {
const optionValue = item.getAttribute('option');
if (optionValue) {
acc.push(optionValue);
}
}
return acc;
}, []);
this.lineItems = this.productStyleInfo.filter((item) => idArr.includes(item.product_id));
}
const action = data.args.action === "cart";
if(action) {
//add to cart
this.xhr_
.fetchJson(this.batchAtcApi, {
method: 'POST',
body: {
line_items: this.lineItems.map((item) => {
return {
product_id: item.product_id,
variant_id: item.variant_id,
quantity: Number(item.quantity)
}
})
}
})
.then((data) => {
setTimeout(() => {
window.location.href = '/cart';
});
})
.catch(async (error) => {
await error.then((data) => {
this.handleRequestError_(data);
});
});
} else {
//checkout
this.xhr_
.fetchJson(this.buyNowApi, {
method: 'POST',
body: {
line_items: (this.lineItems || []).map((product) => {
return {
quantity: Number(product.quantity),
variant_id: product.variant_id,
note: product.note || '',
properties: product.properties || {}
}
}),
refer_info: { source: 'buy_now' }
}
})
.then(async (data) => {
if (data.state === 'success') {
window.location.href = data.data?.checkout_url;
}
this.handleRequestError_(data);
})
.catch(async (error) => {
await error.then((data) => {
this.handleRequestError_(data);
});
});
}
});
this.registerAction('resetModalVariantInfo', () => {
//flashไธป้ขๆพblockๆๅฑ็บง้ฎ้ข
if(/Flash/.test(window.C_SETTINGS.theme.merchant_theme_name) && document.querySelector(".productInfoSection")) {
document.querySelector('.product-info-body').style.zIndex = this.tempCss.zIndex;
}
this.modalVariantInfo = [];
});
this.registerAction('handleModalInventoryCheck', (invocation) => {
const data = invocation.args.data;
this.handleModalInventoryCheck_(data);
});
};
};
SPZ.defineElement('spz-custom-discount-bundle-products', SpzCustomDiscountBundleProducts);
${function(){
if(originData.discount_info.discount_id === "0") return;
const title = originData.product_setting.document.discount_text || '';
const title_color = JSON.parse(originData.product_setting.discount_text_config) || '';
const promotioUrl = '/promotions/discount-default/' + originData.discount_info.discount_id;
// ๆฌๅฐ่ทณ่ฝฌๅคๅฎ(ไธไพ่ตๅ
จๅฑ appDiscountUtils,ๆจกๆฟๆฒ็ฎฑไธๅฏ่ง)
const __resolveHref = (s, landing) => {
if (!s || !s.is_redirection) return '';
const link = typeof s.link === 'string' ? s.link.trim() : '';
if (link && /^https?:\/\//i.test(link)) return link;
return landing || '';
};
const finalHref = __resolveHref(originData.product_setting, promotioUrl);
let dom = originData ? `
` : `
`;
return dom;
}()}
class SpzCustomDiscountBundle extends SPZ.BaseElement {
constructor(element) {
super(element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.variant_id = '66c83c06-7208-4066-9b66-fd2ced9812f3';
this.discountCardApi = "\/api\/storefront\/promotion\/product_details_page\/card";
this.productsApi = "\/api\/storefront\/promotion\/product_page\/product\/list";
this.bundleRenderElement = "appDiscountProductBundle";
this.model = {
loading: false,
page: 2,
limit: 20,
params: {
count: 0,
has_more: false,
sort: {
by: "price",
direction: "asc"
}
}
}
this.discountId = "";
this.discountType = "";
this.bundleProducts = []; //ๆ็ปๆดปๅจๅๅ
this.buttomConfig = {};//ๆปไปทๅไธๆนๆ้ฎ้
็ฝฎ
this.renderDiscount = this.win.SPZCore.Types.debounce(this.win, this.discountHandel.bind(this) , 500);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
async getDiscountCardList() {
const productId = '8e0c4c20-76d1-49e6-8a96-195f1fecb173';
const productType = 'default';
const variantId = this.variant_id;
if(!productId || !variantId || !productType) {
return;
}
const reqBody = {
product_id: productId,
variant_id: variantId,
discount_types: ["DT_CLASSIC_BUNDLE","DT_MIX_MATCH_BUNDLE"],
discount_methods: ["DM_AUTOMATIC"],
customer: {
customer_id: '',
email: '',
},
product_type: productType
}
const data = await this.xhr_.fetchJson(this.discountCardApi, {
method: "post",
body: reqBody
}).then(res => {
return res;
}).catch(err => {
console.error(err);
})
return data;
};
async discountHandel() {
const $bundle = document.querySelector(".app-discount-bundle-inner");
$bundle && SPZCore.Dom.removeElement($bundle);
const data = await this.getDiscountCardList();
if(!data || !data.discount_info || data.discount_info.discount_id === "0") {
return;
}
//ๅ้่ตๅผ
this.bundleProducts = data.product_info.product;
this.buttomConfig = data.product_setting;
this.discountId = data.discount_info.discount_id;
this.discountType = data.discount_info.discount_type;
this.model.params ={
count: data.product_info.count,
has_more: data.product_info.has_more,
sort: data.product_info.sort
}
//็ปๆ็ป็ปไปถไผ ๅผ
SPZ.whenApiDefined(document.getElementById("appDiscountBundleProductsFunc")).then((api) => {
api.setBundleData(this.bundleProducts, this.buttomConfig, this.discountId, this.discountType, data.discount_info);
})
document.querySelector(".app_discount_bundle").dataset.discountType = data.discount_info.discount_type;
SPZ.whenApiDefined(document.getElementById(this.bundleRenderElement))
.then(apis => {
apis.render(data,true).then(() => {
SPZ.whenApiDefined(document.getElementById("bundleProductsRender")).then((api) => {
api.render(data,true).then(() => {
this.bindEvent_();
if(this.bundleProducts.length < 5) {
document.querySelector(".app-discount-bundle-arrow-left").style.display="none";
document.querySelector(".app-discount-bundle-arrow-right").style.display="none";
}
//็ปๅ
ธๆ็ปๆธฒๆๆ้ฎ
if(this.discountType === "DT_CLASSIC_BUNDLE") {
SPZ.whenApiDefined(document.getElementById("promotionBottomContainer")).then((api) => {
const buttonData = {
setting: this.buttomConfig,
...data.product_info.total_price
}
api.render(buttonData, true);
})
}
})
})
})
.then(() => {
document.querySelector(".app-discount-bundle-inner").classList.add("discount_bundle_" + data.product_setting.template_type || "vertical");
});
});
//ๆฌๅฐ่ฐ่ฏ ๆพๅ่ฏฆblock้
const isSection = document.querySelector(
'div[data-section-type^="shoplazza://apps/publicapp/blocks/discount_bundle/"] .app_discount_bundle'
);
if(!isSection) {
document.querySelector(".app_discount_bundle").classList.add("productInfoSection");
}
};
// ่ทๅๅ ่ฝฝ็ๅๅๆฐๆฎ๏ผๆผๆฅhtmlๆจกๆฟ
async loadData(cb) {
// ่ฏทๆฑๆฐๆฎ
this.model.loading = true;
//ๆฅ่ฏขๆดปๅจๅๅๆฅๅฃ
const reqBody = {
discount_id: this.discountId,
page: this.model.page,
limit: this.model.limit,
"apply_scenario": "AS_ENTITLED_PRODUCT",
sort: this.model.params.sort,
sales_channel: {
sale_channel_type: "online",
sale_channel_id: '1319604'
},
product_id: '8e0c4c20-76d1-49e6-8a96-195f1fecb173'
}
this.xhr_.fetchJson(this.productsApi, {
method: "post",
body: reqBody
}).then(async(res)=>{
const count = res.count;
this.model.params.has_more = res.has_more;
if (count > 0) {
this.model.page++;
if (res.products && res.products.length > 0) {
let products = res.products.map((product) => {
return {
...product,
url: appDiscountUtils.globalizePath(product.url),
image_padding_bottom: appDiscountUtils.image_padding_bottom(product.image.width, product.image.height,'no-limit'),
discount_type: this.discountType
}
});
// ่ทๅๅๅๅ่กจๆธฒๆๆจกๆฟ, domๆ่ฝฝ
const $content = document.querySelector(".app-discount-bundle-products");
this.templates_ = SPZServices.templatesForDoc();
this.templates_.renderTemplate(document.querySelector('#appDiscountBundleProductsTemplate'), products).then((el) => {
const childNodes = el.querySelectorAll('.as-render-product-item');
if (childNodes && childNodes.length > 0) {
$content.append(...childNodes);
}
}).then(() => {
//้ๆฐๆธฒๆljs-selector
const productSelector = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionProductSelector`);
productSelector && SPZ.whenApiDefined(productSelector).then((api) => {
api.init();
});
});
this.bundleProducts = [...this.bundleProducts, ...res.products];
SPZ.whenApiDefined(document.getElementById("appDiscountBundleProductsFunc")).then((api) => {
api.setBundleData(this.bundleProducts);
})
// ็ๅฌloadๅปๆ็ฐ่ฒ่ๆฏ
document.dispatchEvent(new CustomEvent('fire.load.img'));
// ่งฆๅๆๅ ่ฝฝ
cb && cb(products);
window.lazyLoadInstance && window.lazyLoadInstance.update();
}
}
this.model.loading = false;
}).catch((err)=>{
console.error(err);
this.model.loading = false;
})
};
setupAction_() {
this.registerAction('shiftMove', (data) => {
const $el = document.querySelector(".app-discount-bundle-products");
const action = data.args.direct === "right";
const scrollwidth = action ? $el.offsetWidth : -$el.offsetWidth;
$el.scrollBy({
left: scrollwidth,
behavior: 'smooth'
});
});
};
bindEvent_() {
// ็ๅฌๅญๆฌพๅผๅๆข๏ผ้ๆฐๆธฒๆ
document.addEventListener('dj.variantChange', async(event) => {
const variant = event.detail.selected;
if (variant.product_id == '8e0c4c20-76d1-49e6-8a96-195f1fecb173') {
this.variant_id = variant.id;
}
this.renderDiscount();
});
// ็ๅฌๆปๅจ๏ผ่ฏทๆฑๆฐๆฎ
const $el = document.querySelector(".app-discount-bundle-products");
if($el) {
$el.addEventListener("scroll", this.win.SPZCore.Types.debounce(
this.win,
() => {
const isLeft = $el.scrollLeft === 0;
const isRightEnd = $el.scrollLeft + $el.offsetWidth + 10 >= $el.scrollWidth;
const isBottomEnd = $el.scrollTop + $el.clientHeight + 10 >= $el.scrollHeight;
const isEnd = isBottomEnd && isRightEnd;
if(isEnd && this.model.params.has_more && !this.model.loading) {
this.loadData();
}
},
50
))
};
};
buildCallback() {
this.setupAction_();
};
mountCallback() {
this.renderDiscount();
this.bindEvent_();
};
}
SPZ.defineElement('spz-custom-discount-bundle', SpzCustomDiscountBundle);
The current item does not participate in the discount gift campaign. Switch the participating items to check the design.
(This prompt will not be displayed on the client-side)
- ๐Chic Lockme Tender Bag Design: Immerse yourself in the sophisticated world of Louis Vuitton with the iconic Lockme Tender Bag-inspired design. The distinctive leather texture, refined stitching, and the LV logo make a bold fashion statement, transforming your iPhone into a style accessory.
-
๐Premium Leather Construction: Crafted from high-quality Louis Vuitton leather, these cases exude luxury and durability. The supple texture not only feels exquisite to the touch but also provides reliable protection against scratches, minor impacts, and daily wear.
-
๐Slim Profile, Maximum Impact: Despite its multifunctionality, the wallet case maintains a slim profile, ensuring that your iPhone remains sleek and portable. The streamlined design adds a touch of sophistication to your device without compromising on practicality.
-
๐Signature LV Detailing: The subtle yet distinctive Louis Vuitton detailing, including the iconic monogram pattern and logo, showcases your appreciation for luxury and sets these wallet cases apart as a true fashion statement.
-
๐Limited Edition Appeal: Embrace exclusivity with the limited availability of these wallet cases. Indulge in a piece that not only elevates your iPhone but also reflects your discerning taste in fashion and your desire for unique, statement accessories.