1import{Component}from"@theme/component";import{morphSection}from"@theme/section-renderer";import{fetchConfig}from"@theme/utilities";import{cartPerformance}from"@theme/performance";class CartDiscount extends Component{requiredRefs=["cartDiscountError","cartDiscountErrorMessage"];#activeFetch=null;#createAbortController(){this.#activeFetch&&this.#activeFetch.abort();const abortController=new AbortController;return this.#activeFetch=abortController,abortController}applyDiscount=async event=>{event.preventDefault(),event.stopPropagation();const eventTarget=event.target,form=eventTarget instanceof HTMLFormElement?eventTarget:eventTarget instanceof HTMLElement?eventTarget.closest("form"):null;if(!(form instanceof HTMLFormElement))return;const discountCode=form.querySelector('input[name="discount"]'),submitButton=form.querySelector(".cart-discount__button");if(!(discountCode instanceof HTMLInputElement)||typeof this.dataset.sectionId!="string")return;const discountCodeValue=discountCode.value.trim();if(!discountCodeValue){this.#showError("Please enter a discount code."),discountCode.focus();return}if(submitButton instanceof HTMLButtonElement&&submitButton.disabled)return;submitButton instanceof HTMLButtonElement&&(submitButton.disabled=!0,submitButton.setAttribute("aria-busy","true"));const abortController=this.#createAbortController();try{const existingDiscounts=this.#existingDiscounts();if(existingDiscounts.some(code=>code.toLocaleLowerCase()===discountCodeValue.toLocaleLowerCase())){this.#showError(`Discount code \u201C${discountCodeValue}\u201D has already been applied.`);return}this.#clearErrors();const config=fetchConfig("json",{body:JSON.stringify({discount:[...existingDiscounts,discountCodeValue].join(","),sections:[this.dataset.sectionId]})}),response=await fetch(Theme.routes.cart_update_url,{...config,signal:abortController.signal}),data=await response.json().catch(()=>({}));if(!response.ok)throw new Error(this.#getResponseError(data,`Unable to apply the discount code (HTTP ${response.status}).`));const returnedDiscount=(Array.isArray(data.discount_codes)?data.discount_codes:[]).find(discount=>discount.code?.toLocaleLowerCase()===discountCodeValue.toLocaleLowerCase());if(!returnedDiscount||returnedDiscount.applicable===!1){discountCode.value="",this.#showError(this.#getResponseError(data,`Discount code \u201C${discountCodeValue}
1\u201D is invalid, expired, or not applicable to the items in this cart.`));return}const newHtml=data.sections?.[this.dataset.sectionId];if(typeof newHtml!="string")throw new Error("Discount update did not return the cart section");const section=new DOMParser().parseFromString(newHtml,"text/html").getElementById(`shopify-section-${this.dataset.sectionId}`),discountCodes=section?.querySelectorAll(".cart-discount__pill")||[];if(section){const codes=Array.from(discountCodes).map(element=>element instanceof HTMLLIElement?element.dataset.discountCode:null).filter(Boolean);if(codes.length===existingDiscounts.length&&codes.every(code=>existingDiscounts.includes(code))&&returnedDiscount.applicable===!0){this.#handleDiscountError("shipping"),discountCode.value="";return}}await morphSection(this.dataset.sectionId,newHtml,{mode:this.closest(".cart-drawer")?"hydration":"full"})}catch(error){if(error instanceof DOMException&&error.name==="AbortError")return;console.error("Unable to apply cart discount",error),this.#showError(error instanceof Error?error.message:"Unable to apply the discount code. Please try again.")}finally{this.#activeFetch=null,submitButton instanceof HTMLButtonElement&&(submitButton.disabled=!1,submitButton.removeAttribute("aria-busy")),cartPerformance.measureFromEvent("discount-update:user-action",event)}};removeDiscount=async event=>{if(event.preventDefault(),event.stopPropagation(),event instanceof KeyboardEvent&&event.key!=="Enter"||!(event instanceof MouseEvent)||!(event.target instanceof HTMLElement)||typeof this.dataset.sectionId!="string")return;const pill=event.target.closest(".cart-discount__pill");if(!(pill instanceof HTMLLIElement))return;const removeButton=event.target.closest(".cart-discount__pill-remove");if(!(removeButton instanceof HTMLButtonElement)||removeButton.disabled)return;const discountCode=pill.dataset.discountCode;if(!discountCode)return;const existingDiscounts=this.#existingDiscounts(),index=existingDiscounts.indexOf(discountCode);if(index===-1)return;existingDiscounts.splice(index,1),removeButton.disabled=!0,removeButton.setAttribute("aria-busy","true"),pill.setAttribute("aria-busy","true");const abortController=this.#createAbortController();try{const config=fetchConfig("json",{body:JSON.stringify({discount:existingDiscounts.join(","),sections:[this.dataset.sectionId]})}),response=await fetch(Theme.routes.cart_update_url,{...config,signal:abortController.signal}),data=await response.json().catch(()=>({}));if(!response.ok)throw new Error(this.#getResponseError(data,`Unable to remove the discount code (HTTP ${response.status}).`));const newHtml=data.sections?.[this.dataset.sectionId];if(typeof newHtml!="string")throw new Error("Discount removal did not return the cart section");await morphSection(this.dataset.sectionId,newHtml,{mode:this.closest(".cart-drawer")?"hydration":"full"})}catch(error){if(error instanceof DOMException&&error.name==="AbortError")return;console.error("Unable to remove cart discount",error),this.#showError(error instanceof Error?error.message:"Unable to remove the discount code. Please try again.")}finally{this.#activeFetch=null,removeButton.isConnected&&(removeButton.disabled=!1,removeButton.removeAttribute("aria-busy"),pill.removeAttribute("aria-busy"))}};#handleDiscountError(type){this.#showError(type==="shipping"?"This shipping discount will be applied at checkout after you enter a delivery address.":"This discount code cannot be applied to your cart.")}#showError(message){const{cartDiscountError,cartDiscountErrorMessage}=this.refs;cartDiscountErrorMessage.textContent=message,cartDiscountErrorMessage.classList.remove("hidden"),cartDiscountError.classList.remove("hidden")}#clearErrors(){const{cartDiscountError,cartDiscountErrorMessage}=this.refs;cartDiscountError.classList.add("hidden"),cartDiscountErrorMessage.classList.add("hidden"),cartDiscountErrorMessage.textContent=""}#getResponseError(data,fallback){const errors=data?.errors;if(typeof errors=="string"&&errors.trim())return errors;if(errors&&typeof errors=="object"){const firstError=Object.values(errors).flat().find(value=>typeof value=="string"&&value.trim());if(typeof firstError=="string")return firstError}
1return typeof data?.description=="string"&&data.description.trim()?data.description:typeof data?.message=="string"&&data.message.trim()?data.message:fallback}#existingDiscounts(){const discountCodes=[],discountPills=this.querySelectorAll(".cart-discount__pill");for(const pill of discountPills)pill instanceof HTMLLIElement&&typeof pill.dataset.discountCode=="string"&&discountCodes.push(pill.dataset.discountCode);return discountCodes}}customElements.get("cart-discount-form-component")||customElements.define("cart-discount-form-component",CartDiscount); 2//# sourceMappingURL=/cdn/shop/t/60/assets/cart-discount.js.map?v=173630114163200004791786093163
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.