const TAG = "spz-custom-product-automatic"; class SpzCustomProductAutomatic extends SPZ.BaseElement { constructor(element) { super(element); this.variant_id = '403e67de-8f00-47fc-87ef-1d6baea9b986'; this.isRTL = SPZ.win.document.dir === 'rtl'; } 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 = '08109a1c-5626-4a4e-ab12-2a71651a0f68'; 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 == '08109a1c-5626-4a4e-ab12-2a71651a0f68' && 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(); }); } 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 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"]; // 是否跳转落地页配置 const redirection = item.dataset["redirection"] === "true"; // 跳转到落地页 if (redirection && appDiscountUtils.inProductBody(this.element)) { this.win.open(`/promotions/discount-default/${discountId}`); } } }) } } /** * 使用 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 = "403e67de-8f00-47fc-87ef-1d6baea9b986"; // 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 == '08109a1c-5626-4a4e-ab12-2a71651a0f68' && 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: "08109a1c-5626-4a4e-ab12-2a71651a0f68", 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);

Print Casual Short Sleeve Black T-Shirt

$21.99
color:  As shown
size:  S
Quantity

Description

Description

Product Details

  • Material: Cotton Blend
  • Pattern Type: Print / Letter
  • Sleeve Type: Short Sleeve
  • Style: Casual
  • Occasion: Daily

shipping info

Return info

If you're not happy with your purchase for any reason, please Contact Us at service@Chicmature.com directly, and we will offer you solutions according to your case.

Return policy
Online purchases (Final sale items and gifts excluded) made through Chicmature are valid for exchange or refund within 14 days from the date you've received all your item(s). Items must be unworn, unwashed and unaltered, come with all original tags and their original packaging. The original shipping cost and the insurance (if any) are non-refundable.

To be eligible, please make sure that.

-The product is in its original packaging

-The product isn't used or damaged

-Buyer is responsible for return shipping cost.

How do I return an item?
Step 1
Submit items rxchange/return request to customer service via service@Chicmature.com.

Step 2

Explain the product you want to return and the return reason.

Step 3
Prepare your package.

Step 4
Deliver your package.

Most returns are processed within 5 business days after we receive your package.

We’ll issue the refund to your wallet in amount of few days if we are not otherwise informed to refund to your payment account in advance. Wallet balance can be used on your next purchase or be withdrawn to your payment account. Once your refund has been issued, you will receive a confirmation email.

We do not accept any request of exchange&return once the "specials" are sold.

Purchase Not Eligible for Return:

-Final sale item(s) is not eligible for return or exchange.

-Swimwear is not eligible for return or exchange.

-Swimwear can only be returned/exchanged if it is defective/damaged or wrong item.

-You must email us a picture showing the problem/defect when you submitting the return/exchange request.

After you receive confirmation from our customer service, please send the product along with the product list which includes the product ID. A tracking No. of the returning parcel is required; we will deal with the product exchange or refund after we get your returning parcel.

Damaged items

If you received a damaged product, please notify us immediately for assistance.

Order Cancellation

We offer full refund if the order is cancelled within 24 hours of your purchase.

You should submit an order cancellation request to our customer service via service@Chicmature.com once you decide to cancel the order.

For orders cancelled after 24 hours of purchase but have not been shipped, we will offer partial refund after charging a 15% cancellation fee.

We will NOT accept order cancellation request if the orders have been shipped.

HOW TO ISSUE A REFUND OR EXCHANGE AFTER I RETURN THE ITEM(S)?

Refund or exchange will be available as soon as once we receive the return parcel and confirm the item is intact.

Can I return to the address on the received package?

No, the address on the package is the overseas transshipment warehouse of the logistics party. You need to return the items to our warehouse, and you will get authorization from us by email with our return address after you submit your return request.

Where can I return the item to ?
Products will be returned to our Chinese Return Center.

What shipping company can I choose for return?
Usually you can use any shipping carrier to ship the parcels back to us . You are supposed to choose the cheaper method like postal shipping, which is best and convenient for both of us .

Refunds:
The refund time will depend on the payment method you used for your order.

PayPal refunds: 3 business days.
Credit card refunds: 7-14 business days.
FYI: Sometimes it will take longer time (maybe 1 to 2 weeks depending on which CC company is ) to process the refund for the bank if your original payment method is credit card.

Exchanges:It will take up 3 business days for us to arrange the reshipment for you.

If you haven't received a refund yet, first check your bank account again.

Then contact your credit card company, it may take some time before your refund is officially posted. Next contact your bank. There is often some processing time before a refund is posted.

If you’ve done all of this and you still have not received your refund yet, please contact us at service@Chicmature.com.

If you're not happy with your purchase for any reason, please contact us at service@chicmature.com directly, and we will offer you solutions according to your case.

Return policy
Online purchases (Final sale items and gifts excluded) made through chicmature are valid for exchange or refund within 14 days from the date you've received all your item(s). Items must be unworn, unwashed and unaltered, come with all original tags and their original packaging. The original shipping cost and the insurance (if any) are non-refundable.

To be eligible, please make sure that.

-The product is in its original packaging

-The product isn't used or damaged

-Buyer is responsible for return shipping cost.

How do I return an item?
Step 1
Submit items exchange/return request to customer service via service@chicmature.com.

Step 2

Explain the product you want to return and the return reason.

Step 3
Prepare your package.

Step 4
Deliver your package.

Most returns are processed within 5 business days after we receive your package.

We’ll issue the refund to your wallet in amount of few days if we are not otherwise informed to refund to your payment account in advance. Wallet balance can be used on your next purchase or be withdrawn to your payment account. Once your refund has been issued, you will receive a confirmation email.

We do not accept any request of exchange&return once the "specials" are sold.

Purchase Not Eligible for Return:

-Final sale item(s) is not eligible for return or exchange.

-Swimwear is not eligible for return or exchange.

-Swimwear can only be returned/exchanged if it is defective/damaged or wrong item.

-You must email us a picture showing the problem/defect when you submitting the return/exchange request.

After you receive confirmation from our customer service, please send the product along with the product list which includes the product ID. A tracking No. of the returning parcel is required; we will deal with the product exchange or refund after we get your returning parcel.

Damaged items

If you received a damaged product, please notify us immediately for assistance.

Order Cancellation

We offer full refund if the order is cancelled within 24 hours of your purchase.

You should submit an order cancellation request to our customer service via service@chicmature.com once you decide to cancel the order.

For orders cancelled after 24 hours of purchase but have not been shipped, we will offer partial refund after charging a 15% cancellation fee.

We will NOT accept order cancellation request if the orders have been shipped.

HOW TO ISSUE A REFUND OR EXCHANGE AFTER I RETURN THE ITEM(S)?

Refund or exchange will be available as soon as once we receive the return parcel and confirm the item is intact.

Can I return to the address on the received package?

No, the address on the package is the overseas transshipment warehouse of the logistics party. You need to return the items to our warehouse, and you will get authorization from us by email with our return address after you submit your return request.

Where can I return the item to ?
Products will be returned to our Chinese Return Center.

What shipping company can I choose for return?
Usually you can use any shipping carrier to ship the parcels back to us . You are supposed to choose the cheaper method like postal shipping, which is best and convenient for both of us .

Refunds:
The refund time will depend on the payment method you used for your order.

PayPal refunds: 3 business days.
Credit card refunds: 7-14 business days.
FYI: Sometimes it will take longer time (maybe 1 to 2 weeks depending on which CC company is ) to process the refund for the bank if your original payment method is credit card.

Exchanges:It will take up 3 business days for us to arrange the reshipment for you.

If you haven't received a refund yet, first check your bank account again.

Then contact your credit card company, it may take some time before your refund is officially posted. Next contact your bank. There is often some processing time before a refund is posted.

If you’ve done all of this and you still have not received your refund yet, please contact us at service@chicmature.com.