Sisal Bucket Cat Scratching Board – 2-in-1 Round Bed & Furniture Protector
Give your cat a cozy bed and a scratch-friendly surface—protect your furniture with style and comfort
144 sold
${function() {
const variantData = data.variant || {"id":"14b49dc6-b5fc-4293-96c1-af079307c1d6","product_id":"2155b57c-5648-4132-a5d5-c7e417e103bb","title":"","weight_unit":"kg","inventory_quantity":897,"sku":"","barcode":"","position":1,"option1":"","option2":"","option3":"","note":"","image":null,"wholesale_price":[{"price":329.99,"min_quantity":1}],"weight":"0.61","compare_at_price":"0","price":"329.99","retail_price":"0","available":true,"url":"\/products\/sisal-bucket-cat-scratching-board-2-in-1-round-bed-furniture-protector?variant=14b49dc6-b5fc-4293-96c1-af079307c1d6","available_quantity":999999999,"options":[],"off_ratio":"0","flashsale_info":{"variant_id":"14b49dc6-b5fc-4293-96c1-af079307c1d6","product_id":"","quantity":0,"discount_id":"","limit_time":0,"limit_buy":0,"user_limit_buy":0,"discount_sales":0,"discount_sales_rate":"","discount_stock":0,"ends_at":0,"starts_at":0,"allow_oversold":"","allocation_method":"","price":"329.99","compare_at_price":"","discount_price":"329.99","customary_saved_price":"","customary_off_ratio":"","discount_saved_price":"","discount_off_ratio":"0","use_before_price":false,"before_price":"","title":"","properties":"","color_setting_promotional_copy":"","discount_quantity":0,"is_need_split":false},"sales":144};
const saveType = "amount";
const productSaveLabel = true;
return `
-
${saveType == 'percent' ? `-${variantData.off_ratio}% ` : `- ` }
`; }()}
${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 = "14b49dc6-b5fc-4293-96c1-af079307c1d6";
// ไฟ้ๆดปๅจๆฐๆฎ
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 == '2155b57c-5648-4132-a5d5-c7e417e103bb' && variant.id != this.variantId) {
this.variantId = variant.id;
this.getData();
}
}
getData() {
const reqBody = {
product_id: "2155b57c-5648-4132-a5d5-c7e417e103bb",
product_type: "",
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);
const TAG = "spz-custom-product-automatic";
class SpzCustomProductAutomatic extends SPZ.BaseElement {
constructor(element) {
super(element);
this.variant_id = '14b49dc6-b5fc-4293-96c1-af079307c1d6';
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 = '2155b57c-5648-4132-a5d5-c7e417e103bb';
const variantId = this.variant_id;
const productType = '';
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 == '2155b57c-5648-4132-a5d5-c7e417e103bb' && 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 = '2155b57c-5648-4132-a5d5-c7e417e103bb';
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);
/**
* ไผๆ ็ ็ปไปถๆจกๅ็ฑป
* ๅค็ไผๆ ็ ็ๆพ็คบๅไบคไบ้ป่พ
*/
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);
/**
* 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 = "14b49dc6-b5fc-4293-96c1-af079307c1d6";
// 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 == '2155b57c-5648-4132-a5d5-c7e417e103bb' && 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: "2155b57c-5648-4132-a5d5-c7e417e103bb",
variant_id: this.variantId,
product_type: "",
}
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);
Add to cart
- $329.99
${function(){
const wholesale_enabled = false;
const qty = data.quantity || 1;
const currentSelectVariant = data.variant;
const defaultVariant = (data.product && data.product.variants && data.product.variants[0]) || Object.keys(data).length > 1 ? data : null;
const productVariant = {"id":"14b49dc6-b5fc-4293-96c1-af079307c1d6","product_id":"2155b57c-5648-4132-a5d5-c7e417e103bb","title":"","weight_unit":"kg","inventory_quantity":897,"sku":"","barcode":"","position":1,"option1":"","option2":"","option3":"","note":"","image":null,"wholesale_price":[{"price":329.99,"min_quantity":1}],"weight":"0.61","compare_at_price":"0","price":"329.99","retail_price":"0","available":true,"url":"\/products\/sisal-bucket-cat-scratching-board-2-in-1-round-bed-furniture-protector?variant=14b49dc6-b5fc-4293-96c1-af079307c1d6","available_quantity":999999999,"options":[],"off_ratio":"0","flashsale_info":{"variant_id":"14b49dc6-b5fc-4293-96c1-af079307c1d6","product_id":"","quantity":0,"discount_id":"","limit_time":0,"limit_buy":0,"user_limit_buy":0,"discount_sales":0,"discount_sales_rate":"","discount_stock":0,"ends_at":0,"starts_at":0,"allow_oversold":"","allocation_method":"","price":"329.99","compare_at_price":"","discount_price":"329.99","customary_saved_price":"","customary_off_ratio":"","discount_saved_price":"","discount_off_ratio":"0","use_before_price":false,"before_price":"","title":"","properties":"","color_setting_promotional_copy":"","discount_quantity":0,"is_need_split":false},"sales":144};
const variantData = currentSelectVariant || defaultVariant || productVariant;
const wholesale_price = variantData.wholesale_price || [];
if(wholesale_enabled && wholesale_price.length > 0) {
let wholesaleIndex = wholesale_price.findIndex(item => {
return item.min_quantity > qty;
});
if(wholesaleIndex < 0){
wholesaleIndex = wholesale_price.length - 1;
}else if(wholesaleIndex > 0){
wholesaleIndex = wholesaleIndex - 1;
}
const wholesalePrice = wholesale_price[wholesaleIndex] || '';
return `
`
}else {
const price = variantData && variantData.price;
return price != undefined ? `
` : ' ';
}
}()}
Buy it now
Product was out of stock.
Product is unavailable.
Vendor by:
Customer Reviews
No reviews yet, why don't you leave the first review?
Write a Review