๐Ÿ’“ To My Grandson Granddaughter Gift Lettering Keychain

$12.98
$25.45
-$12.47
Style:  Silver one for grandson
Type:  A
Quantity
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("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(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: '1950524' }, 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(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(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(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);
class SpzCustomDiscountBundle extends SPZ.BaseElement { constructor(element) { super(element); this.xhr_ = SPZServices.xhrFor(this.win); this.variant_id = '603ad1ae-2146-4150-93fd-c7af39e11eb2'; 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 = 'f410ee44-2242-44a0-b333-60a9a2dc0931'; const productType = 'default'; const variantId = this.variant_id; 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.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: '1950524' }, product_id: 'f410ee44-2242-44a0-b333-60a9a2dc0931' } 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 == 'f410ee44-2242-44a0-b333-60a9a2dc0931') { 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);

Description

๐Ÿ”ฅ99.3% of customers bought 4 or more for their loved ones!

โญUnique gift for your special one, you won't find in the malls!

  • ๐ŸšขSHIPPING WORLDWIDE
  • ๐Ÿ’ฏPayments Via PayPal® and CreditCard.
  • ๐Ÿ˜ŠIf you are not satisfied within 60 days, you can return it for free.
  • โญFast Returns>> 100% Money Back Guarantee.
  • ๐Ÿ†Free One Years Product Warranty

โค๏ธ Have you been looking for a special gift to commemorate your relationship?

๐Ÿ˜How about a delicate and fun keepsake silver keyring?--“ Inspirational gift for children "

๐ŸŒžThis cute keyring is sure to get a smile.It's also a gift that can be treasured for years to come.

๐ŸŽIs this what you say to each other every day and never get tired of ? Then you can't miss it. It will bring smile even laugh for him/her.๐Ÿ˜And 99.3% Reviewers Recommends Buy 4 Or More!

๐ŸŽThis keyring is also ๐Ÿ‘จ‍๐Ÿ‘ฉ‍๐Ÿ‘ง‍๐Ÿ‘ฆGifts for my son and daughter's keychain parents inspirational birthday gifts for sons and daughters for teenage boys and girls๐Ÿ’•

 ๐ŸŽThis keyring is the best gift to show your love to your special one, and it also the best proof of your relationship. Come and get it ! ๐ŸŽThis keyring is the best gift to show your love to your special one, and it also the best proof of your relationship. Come and get it ! 

Family means putting your arms around each other and being there. Our Personalized Keychain is perfect for grandson or granddaughter to celebrate your love or show your support for them. Choose the letter of your grandson and granddaughter for a dedicated keychain with a beautiful message.

FEATURES

  • 100% brand new and high quality

  • The design is simple, casual, fashionable and popular, and this is a very good surname letter keychain for boys and girls

  • Unique design, more distinctive

  • Exquisite and unique product design, especially suitable for you strong and sturdy Wearing this keychain can make you more personal

SPECIFICATIONS

  • Material: Stainless steel
  • Diameter: 50*28*1.8 mm
  • Weight: about 25 grams
  • Gender: grandson/granddaughter
  • Package: 1 * keychain

Click On "ADD TO CART" To Get Yours Now!

โœˆ Worldwide Shipping โœˆ  


 


 

 

 

OUR GUARANTEE

๐Ÿ“ฆ Insured Worldwide Shipping: Each order includes real-time tracking details and insurance coverage in the unlikely event that a package gets lost or stolen in transit.

๐Ÿ’ฐ Money-Back Guarantee: If your items arrive damaged or become defective within 30 days of normal usage, we will gladly issue a replacement or refund.

โœ‰๏ธ 24/7 Customer Support: We have a team of live reps ready to help and answer any questions you have within a 24-hour time frame, 7 days a week. Email: hezizi0215@gmail.com

๐Ÿ”’ Safe & Secure Checkouts: We use state-of-the-art SSL Secure encryption to keep your personal and financial information 100% protected.

Free Delivery over $59.99. Processing Time: 1-5 Working Days.Estimated Arrival: 7-20 Working Days.  
For more details see Shipping & Returns. Any questions or helps, Please send an email to hezizi0215@gmail.com
Thank you for shopping at Xuebazy !