diff --git a/extensions/datetime-widget/assets/datetime-widget.js b/extensions/datetime-widget/assets/datetime-widget.js index e8ecb5c..9d998b4 100644 --- a/extensions/datetime-widget/assets/datetime-widget.js +++ b/extensions/datetime-widget/assets/datetime-widget.js @@ -1 +1 @@ -"use strict";(()=>{var k=Object.defineProperty;var S=(i,t,e)=>t in i?k(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var c=(i,t,e)=>S(i,typeof t!="symbol"?t+"":t,e);var M="/apps/scheduling";function C(i){let t=Math.floor(i/60),e=i%60,n=t<12?"AM":"PM";return`${t%12===0?12:t%12}:${e.toString().padStart(2,"0")} ${n}`}function p(i){return h(i.slice(0,10))}function v(i){return i.arrivalRangeStart&&i.arrivalRangeEnd?`Arrives ${p(i.arrivalRangeStart)}\u2013${p(i.arrivalRangeEnd)}`:i.arrivalRangeStart?`Arrives from ${p(i.arrivalRangeStart)}`:i.arrivalRangeEnd?`Arrives by ${p(i.arrivalRangeEnd)}`:`${C(i.startMin)}\u2013${C(i.endMin)}`}function h(i){let[t,e,n]=i.split("-").map(Number);return new Date(Date.UTC(t,e-1,n)).toLocaleDateString(void 0,{weekday:"short",month:"short",day:"numeric",timeZone:"UTC"})}function E(i){let t=i.dataset,e=[];return t.showShipping==="true"&&e.push({value:"SHIPPING",label:t.labelShipping||"Shipping",attrLabel:t.attrLabelShipping||"Shipping date"}),t.showLocalDelivery==="true"&&e.push({value:"LOCAL_DELIVERY",label:t.labelLocalDelivery||"Local delivery",attrLabel:t.attrLabelLocalDelivery||"Delivery date"}),t.showPickup==="true"&&e.push({value:"PICKUP",label:t.labelPickup||"Pickup",attrLabel:t.attrLabelPickup||"Pickup date"}),{root:i,heading:t.heading||"",locationId:t.locationId||null,googleMapsApiKey:t.googleMapsApiKey||null,mode:t.mode==="preview"?"preview":"full",methods:e,labels:{chooseDate:t.labelChooseDate||"Choose a date",chooseTime:t.labelChooseTime||"Choose a time",noDates:t.labelNoDates||"No dates are available right now.",confirmed:t.labelConfirmed||"Confirmed for",change:t.labelChange||"Change",loading:t.labelLoading||"Loading available dates\u2026",error:t.labelError||"Couldn't load available dates. Please try again.",postalCodeLabel:t.labelPostalCode||"Enter your postal/ZIP code",postalCodeSubmit:t.labelPostalCodeSubmit||"Check availability",outOfArea:t.labelOutOfArea||"Sorry, we don't deliver to this address.",earliestPrefix:t.labelEarliestPrefix||"Earliest",deliveryAtCheckout:t.labelDeliveryAtCheckout||"Enter your address at checkout to see local delivery dates."}}}async function w(){var e;let t=await(await fetch("/cart.js",{headers:{Accept:"application/json"}})).json();return{token:t.token,lines:((e=t.items)!=null?e:[]).map(n=>{var a,o,r;return{vendor:(a=n.vendor)!=null?a:"",productType:(o=n.product_type)!=null?o:"",productId:`gid://shopify/Product/${n.product_id}`,variantId:`gid://shopify/ProductVariant/${(r=n.variant_id)!=null?r:n.id}`}})}}async function L(i,t,e,n){let a=new URLSearchParams({method:i,days:"14"});t&&a.set("locationId",t),n&&a.set("postalCode",n),e.lines.length>0&&(a.set("cartLines",JSON.stringify(e.lines.map(s=>({vendor:s.vendor,productType:s.productType})))),a.set("productIds",e.lines.map(s=>s.productId).join(",")),a.set("variantIds",e.lines.map(s=>s.variantId).join(",")));let o=await fetch(`${M}/availability?${a.toString()}`,{headers:{Accept:"application/json"}}),r=await o.json();if(!o.ok)throw new Error(r.error||`Request failed (${o.status})`);return r}async function _(i){let t=await fetch(`${M}/hold`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(i)}),e=await t.json();return!t.ok&&i.intent==="create"?{success:!1,error:e.error||"Slot unavailable"}:e}async function I(i,t,e){await fetch("/cart/update.js",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({attributes:{[i]:e,...t}})})}var f=null;function A(i){return f||(f=new Promise((t,e)=>{let n="__ddMapsReady";window[n]=()=>t();let a=document.createElement("script");a.src=`https://maps.googleapis.com/maps/api/js?key=${encodeURIComponent(i)}&callback=${n}`,a.async=!0,a.onerror=()=>e(new Error("Failed to load Google Maps")),document.head.appendChild(a)}),f)}async function P(i,t,e,n,a){try{await A(t);let o=window.google,r=new o.maps.Map(i,{center:{lat:e,lng:n},zoom:13});new o.maps.Marker({position:{lat:e,lng:n},map:r,title:a})}catch{i.hidden=!0}}var b=class{constructor(t){c(this,"config");c(this,"el",{heading:document.createElement("h3"),methodRow:document.createElement("div"),postalRow:document.createElement("div"),mapContainer:document.createElement("div"),dateRow:document.createElement("div"),timeRow:document.createElement("div"),status:document.createElement("p"),confirmation:document.createElement("div")});c(this,"selectedMethod",null);c(this,"selectedDate",null);c(this,"availability",null);c(this,"heldSlot",null);this.config=t}mount(){let{root:t,heading:e,methods:n}=this.config;if(t.classList.add("dd-widget--ready"),t.innerHTML="",n.length!==0){if(this.config.mode==="preview"){this.mountPreview();return}e&&(this.el.heading.className="dd-widget__heading",this.el.heading.textContent=e,t.appendChild(this.el.heading)),this.el.methodRow.className="dd-widget__row dd-widget__methods",this.el.postalRow.className="dd-widget__row dd-widget__postal",this.el.postalRow.hidden=!0,this.el.mapContainer.className="dd-widget__map",this.el.mapContainer.hidden=!0,this.el.dateRow.className="dd-widget__row dd-widget__dates",this.el.timeRow.className="dd-widget__row dd-widget__times",this.el.status.className="dd-widget__status",this.el.confirmation.className="dd-widget__confirmation",this.el.confirmation.hidden=!0,t.append(this.el.confirmation,this.el.methodRow,this.el.postalRow,this.el.mapContainer,this.el.dateRow,this.el.timeRow,this.el.status),n.length===1?this.selectMethod(n[0]):this.renderMethods()}}async mountPreview(){let{root:t,heading:e,methods:n}=this.config;e&&(this.el.heading.className="dd-widget__heading",this.el.heading.textContent=e,t.appendChild(this.el.heading));let a=document.createElement("ul");a.className="dd-widget__preview",t.appendChild(a);let o=await w().catch(()=>({token:"",lines:[]}));await Promise.all(n.map(async r=>{var d;let s=document.createElement("li");if(s.className="dd-widget__preview-item",r.value==="LOCAL_DELIVERY"){s.textContent=this.config.labels.deliveryAtCheckout,a.appendChild(s);return}s.textContent=this.config.labels.loading,a.appendChild(s);try{let g=await L(r.value,this.config.locationId,o),l=Object.keys((d=g.dates)!=null?d:{}).sort()[0];s.textContent=l?`${this.config.labels.earliestPrefix} ${r.label.toLowerCase()}: ${h(l)}`:`${r.label}: ${this.config.labels.noDates}`}catch{s.textContent=`${r.label}: ${this.config.labels.error}`}}))}renderMethods(){var t;this.el.methodRow.innerHTML="";for(let e of this.config.methods){let n=document.createElement("button");n.type="button",n.className="dd-widget__pill",n.textContent=e.label,n.setAttribute("aria-pressed",String(((t=this.selectedMethod)==null?void 0:t.value)===e.value)),n.addEventListener("click",()=>this.selectMethod(e)),this.el.methodRow.appendChild(n)}}async selectMethod(t){if(this.selectedMethod=t,this.selectedDate=null,this.el.timeRow.innerHTML="",this.el.dateRow.innerHTML="",this.el.mapContainer.hidden=!0,this.el.confirmation.hidden=!1,this.el.confirmation.hidden=!0,this.config.methods.length>1&&this.renderMethods(),t.value==="LOCAL_DELIVERY"){this.renderPostalCodeInput(t);return}this.el.postalRow.hidden=!0,await this.loadAvailability(t)}renderPostalCodeInput(t){this.el.postalRow.hidden=!1,this.el.postalRow.innerHTML="",this.el.status.textContent="";let e=document.createElement("input");e.type="text",e.className="dd-widget__input",e.placeholder=this.config.labels.postalCodeLabel,e.setAttribute("aria-label",this.config.labels.postalCodeLabel);let n=document.createElement("button");n.type="button",n.className="dd-widget__pill",n.textContent=this.config.labels.postalCodeSubmit,n.addEventListener("click",async()=>{let a=e.value.trim();a&&await this.loadAvailability(t,a)}),e.addEventListener("keydown",a=>{a.key==="Enter"&&n.click()}),this.el.postalRow.append(e,n)}async loadAvailability(t,e){this.el.status.textContent=this.config.labels.loading,this.el.dateRow.innerHTML="";try{let n=await w();if(this.availability=await L(t.value,this.config.locationId,n,e),!this.availability.locationId){this.el.status.textContent=this.availability.error||this.config.labels.outOfArea;return}t.value==="PICKUP"&&this.config.googleMapsApiKey&&this.showPickupMap(),this.renderDates()}catch{this.el.status.textContent=this.config.labels.error}}showPickupMap(){var e;let t=this.availability;!(t!=null&&t.locationLat)||!(t!=null&&t.locationLng)||!this.config.googleMapsApiKey||(this.el.mapContainer.hidden=!1,P(this.el.mapContainer,this.config.googleMapsApiKey,t.locationLat,t.locationLng,(e=t.locationName)!=null?e:""))}renderDates(){var e,n;let t=Object.keys((n=(e=this.availability)==null?void 0:e.dates)!=null?n:{}).sort();if(this.el.dateRow.innerHTML="",t.length===0){this.el.status.textContent=this.config.labels.noDates;return}this.el.status.textContent=this.config.labels.chooseDate;for(let a of t){let o=document.createElement("button");o.type="button",o.className="dd-widget__pill",o.textContent=h(a),o.setAttribute("aria-pressed",String(this.selectedDate===a)),o.addEventListener("click",()=>this.selectDate(a)),this.el.dateRow.appendChild(o)}}selectDate(t){var n,a;this.selectedDate=t;for(let o of Array.from(this.el.dateRow.children))o.setAttribute("aria-pressed",String(o.textContent===h(t)));let e=(a=(n=this.availability)==null?void 0:n.dates[t])!=null?a:[];this.el.timeRow.innerHTML="",this.el.status.textContent=this.config.labels.chooseTime;for(let o of e){let r=document.createElement("button");r.type="button",r.className="dd-widget__pill",r.textContent=v(o),r.addEventListener("click",()=>this.selectSlot(t,o)),this.el.timeRow.appendChild(r)}}async selectSlot(t,e){var s;let n=this.selectedMethod,a=this.availability,o=a.rate?` (${a.rate.label})`:"",r=e.arrivalRangeStart||e.arrivalRangeEnd?`Ships ${h(t)}, ${v(e)}${o}`:`${h(t)}, ${v(e)}${o}`;this.el.status.textContent=this.config.labels.loading;try{let d=await w(),g=await _({intent:"create",locationId:a.locationId,method:n.value,date:t,startMin:e.startMin,cartToken:d.token,cartLines:d.lines.map(m=>({vendor:m.vendor,productType:m.productType})),productIds:d.lines.map(m=>m.productId)});if(!g.success){this.el.status.textContent=g.error||this.config.labels.error,await this.selectMethod(n);return}this.heldSlot={locationId:a.locationId,method:n.value,date:t,startMin:e.startMin,cartToken:d.token,zoneId:(s=a.zoneId)!=null?s:null};let l={dd_method:n.value,dd_date:t,dd_start_min:String(e.startMin),dd_end_min:String(e.endMin),dd_location_id:a.locationId};a.zoneId&&(l.dd_zone_id=a.zoneId),a.rate&&(l.dd_rate_label=a.rate.label),e.arrivalRangeStart&&(l.dd_arrival_range_start=e.arrivalRangeStart),e.arrivalRangeEnd&&(l.dd_arrival_range_end=e.arrivalRangeEnd),await I(n.attrLabel,l,r),this.el.status.textContent="",this.el.methodRow.hidden=!0,this.el.postalRow.hidden=!0,this.el.mapContainer.hidden=!0,this.el.dateRow.hidden=!0,this.el.timeRow.hidden=!0,this.el.confirmation.hidden=!1,this.el.confirmation.innerHTML="";let y=document.createElement("p");y.textContent=`${this.config.labels.confirmed} ${r}`;let u=document.createElement("button");u.type="button",u.className="dd-widget__link",u.textContent=this.config.labels.change,u.addEventListener("click",()=>{this.heldSlot&&(_({intent:"release",...this.heldSlot}),this.heldSlot=null),this.el.methodRow.hidden=!1,this.el.dateRow.hidden=!1,this.el.timeRow.hidden=!1,this.el.confirmation.hidden=!0}),this.el.confirmation.append(y,u)}catch{this.el.status.textContent=this.config.labels.error}}},T=['form[action*="/cart"] button[name="checkout"]','form[action*="/cart"] input[name="checkout"]','[name="checkout"]',"#checkout",'a[href="/checkout"]'];function D(){for(let i of T){let t=document.querySelector(i);if(t)return t}return null}function $(){return window.location.pathname.replace(/\/+$/,"").endsWith("/cart")}function x(){if(!$()||document.querySelector("[data-dd-widget]"))return;let i=document.getElementById("dd-widget-cart-template");if(!i)return;let t=D();if(!t)return;let e=document.createElement("div");e.setAttribute("data-dd-widget",""),e.classList.add("dd-widget--cart-injected");for(let n of Array.from(i.attributes))n.name!=="id"&&e.setAttribute(n.name,n.value);t.insertAdjacentElement("beforebegin",e),new b(E(e)).mount()}function R(){document.querySelectorAll("[data-dd-widget]").forEach(t=>{new b(E(t)).mount()}),x()}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",R):R();})(); +"use strict";(()=>{var k=Object.defineProperty;var S=(i,t,e)=>t in i?k(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var c=(i,t,e)=>S(i,typeof t!="symbol"?t+"":t,e);var M="/apps/scheduling";function C(i){let t=Math.floor(i/60),e=i%60,n=t<12?"AM":"PM";return`${t%12===0?12:t%12}:${e.toString().padStart(2,"0")} ${n}`}function p(i){return h(i.slice(0,10))}function v(i){return i.arrivalRangeStart&&i.arrivalRangeEnd?`Arrives ${p(i.arrivalRangeStart)}\u2013${p(i.arrivalRangeEnd)}`:i.arrivalRangeStart?`Arrives from ${p(i.arrivalRangeStart)}`:i.arrivalRangeEnd?`Arrives by ${p(i.arrivalRangeEnd)}`:`${C(i.startMin)}\u2013${C(i.endMin)}`}function h(i){let[t,e,n]=i.split("-").map(Number);return new Date(Date.UTC(t,e-1,n)).toLocaleDateString(void 0,{weekday:"short",month:"short",day:"numeric",timeZone:"UTC"})}function I(i){if(!i||i.indexOf("&")===-1)return i;let t=document.createElement("textarea");return t.innerHTML=i,t.value}function E(i){let t=i.dataset,e=(a,o)=>{let r=t[a];return r?I(r):o},n=[];return t.showShipping==="true"&&n.push({value:"SHIPPING",label:e("labelShipping","Shipping"),attrLabel:e("attrLabelShipping","Shipping date")}),t.showLocalDelivery==="true"&&n.push({value:"LOCAL_DELIVERY",label:e("labelLocalDelivery","Local delivery"),attrLabel:e("attrLabelLocalDelivery","Delivery date")}),t.showPickup==="true"&&n.push({value:"PICKUP",label:e("labelPickup","Pickup"),attrLabel:e("attrLabelPickup","Pickup date")}),{root:i,heading:e("heading",""),locationId:t.locationId||null,googleMapsApiKey:t.googleMapsApiKey||null,mode:t.mode==="preview"?"preview":"full",methods:n,labels:{chooseDate:e("labelChooseDate","Choose a date"),chooseTime:e("labelChooseTime","Choose a time"),noDates:e("labelNoDates","No dates are available right now."),confirmed:e("labelConfirmed","Confirmed for"),change:e("labelChange","Change"),loading:e("labelLoading","Loading available dates\u2026"),error:e("labelError","Couldn't load available dates. Please try again."),postalCodeLabel:e("labelPostalCode","Enter your postal/ZIP code"),postalCodeSubmit:e("labelPostalCodeSubmit","Check availability"),outOfArea:e("labelOutOfArea","Sorry, we don't deliver to this address."),earliestPrefix:e("labelEarliestPrefix","Earliest"),deliveryAtCheckout:e("labelDeliveryAtCheckout","Enter your address at checkout to see local delivery dates.")}}}async function w(){var e;let t=await(await fetch("/cart.js",{headers:{Accept:"application/json"}})).json();return{token:t.token,lines:((e=t.items)!=null?e:[]).map(n=>{var a,o,r;return{vendor:(a=n.vendor)!=null?a:"",productType:(o=n.product_type)!=null?o:"",productId:`gid://shopify/Product/${n.product_id}`,variantId:`gid://shopify/ProductVariant/${(r=n.variant_id)!=null?r:n.id}`}})}}async function L(i,t,e,n){let a=new URLSearchParams({method:i,days:"14"});t&&a.set("locationId",t),n&&a.set("postalCode",n),e.lines.length>0&&(a.set("cartLines",JSON.stringify(e.lines.map(s=>({vendor:s.vendor,productType:s.productType})))),a.set("productIds",e.lines.map(s=>s.productId).join(",")),a.set("variantIds",e.lines.map(s=>s.variantId).join(",")));let o=await fetch(`${M}/availability?${a.toString()}`,{headers:{Accept:"application/json"}}),r=await o.json();if(!o.ok)throw new Error(r.error||`Request failed (${o.status})`);return r}async function _(i){let t=await fetch(`${M}/hold`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(i)}),e=await t.json();return!t.ok&&i.intent==="create"?{success:!1,error:e.error||"Slot unavailable"}:e}async function A(i,t,e){await fetch("/cart/update.js",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({attributes:{[i]:e,...t}})})}var f=null;function P(i){return f||(f=new Promise((t,e)=>{let n="__ddMapsReady";window[n]=()=>t();let a=document.createElement("script");a.src=`https://maps.googleapis.com/maps/api/js?key=${encodeURIComponent(i)}&callback=${n}`,a.async=!0,a.onerror=()=>e(new Error("Failed to load Google Maps")),document.head.appendChild(a)}),f)}async function T(i,t,e,n,a){try{await P(t);let o=window.google,r=new o.maps.Map(i,{center:{lat:e,lng:n},zoom:13});new o.maps.Marker({position:{lat:e,lng:n},map:r,title:a})}catch{i.hidden=!0}}var b=class{constructor(t){c(this,"config");c(this,"el",{heading:document.createElement("h3"),methodRow:document.createElement("div"),postalRow:document.createElement("div"),mapContainer:document.createElement("div"),dateRow:document.createElement("div"),timeRow:document.createElement("div"),status:document.createElement("p"),confirmation:document.createElement("div")});c(this,"selectedMethod",null);c(this,"selectedDate",null);c(this,"availability",null);c(this,"heldSlot",null);this.config=t}mount(){let{root:t,heading:e,methods:n}=this.config;if(t.classList.add("dd-widget--ready"),t.innerHTML="",n.length!==0){if(this.config.mode==="preview"){this.mountPreview();return}e&&(this.el.heading.className="dd-widget__heading",this.el.heading.textContent=e,t.appendChild(this.el.heading)),this.el.methodRow.className="dd-widget__row dd-widget__methods",this.el.postalRow.className="dd-widget__row dd-widget__postal",this.el.postalRow.hidden=!0,this.el.mapContainer.className="dd-widget__map",this.el.mapContainer.hidden=!0,this.el.dateRow.className="dd-widget__row dd-widget__dates",this.el.timeRow.className="dd-widget__row dd-widget__times",this.el.status.className="dd-widget__status",this.el.confirmation.className="dd-widget__confirmation",this.el.confirmation.hidden=!0,t.append(this.el.confirmation,this.el.methodRow,this.el.postalRow,this.el.mapContainer,this.el.dateRow,this.el.timeRow,this.el.status),n.length===1?this.selectMethod(n[0]):this.renderMethods()}}async mountPreview(){let{root:t,heading:e,methods:n}=this.config;e&&(this.el.heading.className="dd-widget__heading",this.el.heading.textContent=e,t.appendChild(this.el.heading));let a=document.createElement("ul");a.className="dd-widget__preview",t.appendChild(a);let o=await w().catch(()=>({token:"",lines:[]}));await Promise.all(n.map(async r=>{var d;let s=document.createElement("li");if(s.className="dd-widget__preview-item",r.value==="LOCAL_DELIVERY"){s.textContent=this.config.labels.deliveryAtCheckout,a.appendChild(s);return}s.textContent=this.config.labels.loading,a.appendChild(s);try{let g=await L(r.value,this.config.locationId,o),l=Object.keys((d=g.dates)!=null?d:{}).sort()[0];s.textContent=l?`${this.config.labels.earliestPrefix} ${r.label.toLowerCase()}: ${h(l)}`:`${r.label}: ${this.config.labels.noDates}`}catch{s.textContent=`${r.label}: ${this.config.labels.error}`}}))}renderMethods(){var t;this.el.methodRow.innerHTML="";for(let e of this.config.methods){let n=document.createElement("button");n.type="button",n.className="dd-widget__pill",n.textContent=e.label,n.setAttribute("aria-pressed",String(((t=this.selectedMethod)==null?void 0:t.value)===e.value)),n.addEventListener("click",()=>this.selectMethod(e)),this.el.methodRow.appendChild(n)}}async selectMethod(t){if(this.selectedMethod=t,this.selectedDate=null,this.el.timeRow.innerHTML="",this.el.dateRow.innerHTML="",this.el.mapContainer.hidden=!0,this.el.confirmation.hidden=!1,this.el.confirmation.hidden=!0,this.config.methods.length>1&&this.renderMethods(),t.value==="LOCAL_DELIVERY"){this.renderPostalCodeInput(t);return}this.el.postalRow.hidden=!0,await this.loadAvailability(t)}renderPostalCodeInput(t){this.el.postalRow.hidden=!1,this.el.postalRow.innerHTML="",this.el.status.textContent="";let e=document.createElement("input");e.type="text",e.className="dd-widget__input",e.placeholder=this.config.labels.postalCodeLabel,e.setAttribute("aria-label",this.config.labels.postalCodeLabel);let n=document.createElement("button");n.type="button",n.className="dd-widget__pill",n.textContent=this.config.labels.postalCodeSubmit,n.addEventListener("click",async()=>{let a=e.value.trim();a&&await this.loadAvailability(t,a)}),e.addEventListener("keydown",a=>{a.key==="Enter"&&n.click()}),this.el.postalRow.append(e,n)}async loadAvailability(t,e){this.el.status.textContent=this.config.labels.loading,this.el.dateRow.innerHTML="";try{let n=await w();if(this.availability=await L(t.value,this.config.locationId,n,e),!this.availability.locationId){this.el.status.textContent=this.availability.error||this.config.labels.outOfArea;return}t.value==="PICKUP"&&this.config.googleMapsApiKey&&this.showPickupMap(),this.renderDates()}catch{this.el.status.textContent=this.config.labels.error}}showPickupMap(){var e;let t=this.availability;!(t!=null&&t.locationLat)||!(t!=null&&t.locationLng)||!this.config.googleMapsApiKey||(this.el.mapContainer.hidden=!1,T(this.el.mapContainer,this.config.googleMapsApiKey,t.locationLat,t.locationLng,(e=t.locationName)!=null?e:""))}renderDates(){var e,n;let t=Object.keys((n=(e=this.availability)==null?void 0:e.dates)!=null?n:{}).sort();if(this.el.dateRow.innerHTML="",t.length===0){this.el.status.textContent=this.config.labels.noDates;return}this.el.status.textContent=this.config.labels.chooseDate;for(let a of t){let o=document.createElement("button");o.type="button",o.className="dd-widget__pill",o.textContent=h(a),o.setAttribute("aria-pressed",String(this.selectedDate===a)),o.addEventListener("click",()=>this.selectDate(a)),this.el.dateRow.appendChild(o)}}selectDate(t){var n,a;this.selectedDate=t;for(let o of Array.from(this.el.dateRow.children))o.setAttribute("aria-pressed",String(o.textContent===h(t)));let e=(a=(n=this.availability)==null?void 0:n.dates[t])!=null?a:[];this.el.timeRow.innerHTML="",this.el.status.textContent=this.config.labels.chooseTime;for(let o of e){let r=document.createElement("button");r.type="button",r.className="dd-widget__pill",r.textContent=v(o),r.addEventListener("click",()=>this.selectSlot(t,o)),this.el.timeRow.appendChild(r)}}async selectSlot(t,e){var s;let n=this.selectedMethod,a=this.availability,o=a.rate?` (${a.rate.label})`:"",r=e.arrivalRangeStart||e.arrivalRangeEnd?`Ships ${h(t)}, ${v(e)}${o}`:`${h(t)}, ${v(e)}${o}`;this.el.status.textContent=this.config.labels.loading;try{let d=await w(),g=await _({intent:"create",locationId:a.locationId,method:n.value,date:t,startMin:e.startMin,cartToken:d.token,cartLines:d.lines.map(m=>({vendor:m.vendor,productType:m.productType})),productIds:d.lines.map(m=>m.productId)});if(!g.success){this.el.status.textContent=g.error||this.config.labels.error,await this.selectMethod(n);return}this.heldSlot={locationId:a.locationId,method:n.value,date:t,startMin:e.startMin,cartToken:d.token,zoneId:(s=a.zoneId)!=null?s:null};let l={dd_method:n.value,dd_date:t,dd_start_min:String(e.startMin),dd_end_min:String(e.endMin),dd_location_id:a.locationId};a.zoneId&&(l.dd_zone_id=a.zoneId),a.rate&&(l.dd_rate_label=a.rate.label),e.arrivalRangeStart&&(l.dd_arrival_range_start=e.arrivalRangeStart),e.arrivalRangeEnd&&(l.dd_arrival_range_end=e.arrivalRangeEnd),await A(n.attrLabel,l,r),this.el.status.textContent="",this.el.methodRow.hidden=!0,this.el.postalRow.hidden=!0,this.el.mapContainer.hidden=!0,this.el.dateRow.hidden=!0,this.el.timeRow.hidden=!0,this.el.confirmation.hidden=!1,this.el.confirmation.innerHTML="";let y=document.createElement("p");y.textContent=`${this.config.labels.confirmed} ${r}`;let u=document.createElement("button");u.type="button",u.className="dd-widget__link",u.textContent=this.config.labels.change,u.addEventListener("click",()=>{this.heldSlot&&(_({intent:"release",...this.heldSlot}),this.heldSlot=null),this.el.methodRow.hidden=!1,this.el.dateRow.hidden=!1,this.el.timeRow.hidden=!1,this.el.confirmation.hidden=!0}),this.el.confirmation.append(y,u)}catch{this.el.status.textContent=this.config.labels.error}}},D=['form[action*="/cart"] button[name="checkout"]','form[action*="/cart"] input[name="checkout"]','[name="checkout"]',"#checkout",'a[href="/checkout"]'];function $(){for(let i of D){let t=document.querySelector(i);if(t)return t}return null}function x(){return window.location.pathname.replace(/\/+$/,"").endsWith("/cart")}function N(){if(!x()||document.querySelector("[data-dd-widget]"))return;let i=document.getElementById("dd-widget-cart-template");if(!i)return;let t=$();if(!t)return;let e=document.createElement("div");e.setAttribute("data-dd-widget",""),e.classList.add("dd-widget--cart-injected");for(let n of Array.from(i.attributes))n.name!=="id"&&e.setAttribute(n.name,n.value);t.insertAdjacentElement("beforebegin",e),new b(E(e)).mount()}function R(){document.querySelectorAll("[data-dd-widget]").forEach(t=>{new b(E(t)).mount()}),N()}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",R):R();})(); diff --git a/widget-src/datetime-widget/datetime-widget.ts b/widget-src/datetime-widget/datetime-widget.ts index 17c3202..efb6941 100644 --- a/widget-src/datetime-widget/datetime-widget.ts +++ b/widget-src/datetime-widget/datetime-widget.ts @@ -121,43 +121,60 @@ function formatDateLabel(dateIso: string): string { return date.toLocaleDateString(undefined, { weekday: "short", month: "short", day: "numeric", timeZone: "UTC" }); } +// Liquid's `| escape` filter turns `'` into `'` (and `&` into `&`, +// etc.) before the string lands in a data-* attribute. Depending on how the +// theme/section double-processes translations, that can survive into +// `dataset` still entity-encoded and then render literally when we assign it +// to `textContent`. Decode once here so labels always show as plain text. +function decodeEntities(value: string): string { + if (!value || value.indexOf("&") === -1) return value; + const el = document.createElement("textarea"); + el.innerHTML = value; + return el.value; +} + function readConfig(root: HTMLElement): WidgetConfig { const d = root.dataset; + const get = (key: string, fallback: string): string => { + const raw = d[key]; + return raw ? decodeEntities(raw) : fallback; + }; + const methods: WidgetConfig["methods"] = []; if (d.showShipping === "true") { - methods.push({ value: "SHIPPING", label: d.labelShipping || "Shipping", attrLabel: d.attrLabelShipping || "Shipping date" }); + methods.push({ value: "SHIPPING", label: get("labelShipping", "Shipping"), attrLabel: get("attrLabelShipping", "Shipping date") }); } if (d.showLocalDelivery === "true") { methods.push({ value: "LOCAL_DELIVERY", - label: d.labelLocalDelivery || "Local delivery", - attrLabel: d.attrLabelLocalDelivery || "Delivery date", + label: get("labelLocalDelivery", "Local delivery"), + attrLabel: get("attrLabelLocalDelivery", "Delivery date"), }); } if (d.showPickup === "true") { - methods.push({ value: "PICKUP", label: d.labelPickup || "Pickup", attrLabel: d.attrLabelPickup || "Pickup date" }); + methods.push({ value: "PICKUP", label: get("labelPickup", "Pickup"), attrLabel: get("attrLabelPickup", "Pickup date") }); } return { root, - heading: d.heading || "", + heading: get("heading", ""), locationId: d.locationId || null, googleMapsApiKey: d.googleMapsApiKey || null, mode: d.mode === "preview" ? "preview" : "full", methods, labels: { - chooseDate: d.labelChooseDate || "Choose a date", - chooseTime: d.labelChooseTime || "Choose a time", - noDates: d.labelNoDates || "No dates are available right now.", - confirmed: d.labelConfirmed || "Confirmed for", - change: d.labelChange || "Change", - loading: d.labelLoading || "Loading available dates…", - error: d.labelError || "Couldn't load available dates. Please try again.", - postalCodeLabel: d.labelPostalCode || "Enter your postal/ZIP code", - postalCodeSubmit: d.labelPostalCodeSubmit || "Check availability", - outOfArea: d.labelOutOfArea || "Sorry, we don't deliver to this address.", - earliestPrefix: d.labelEarliestPrefix || "Earliest", - deliveryAtCheckout: d.labelDeliveryAtCheckout || "Enter your address at checkout to see local delivery dates.", + chooseDate: get("labelChooseDate", "Choose a date"), + chooseTime: get("labelChooseTime", "Choose a time"), + noDates: get("labelNoDates", "No dates are available right now."), + confirmed: get("labelConfirmed", "Confirmed for"), + change: get("labelChange", "Change"), + loading: get("labelLoading", "Loading available dates…"), + error: get("labelError", "Couldn't load available dates. Please try again."), + postalCodeLabel: get("labelPostalCode", "Enter your postal/ZIP code"), + postalCodeSubmit: get("labelPostalCodeSubmit", "Check availability"), + outOfArea: get("labelOutOfArea", "Sorry, we don't deliver to this address."), + earliestPrefix: get("labelEarliestPrefix", "Earliest"), + deliveryAtCheckout: get("labelDeliveryAtCheckout", "Enter your address at checkout to see local delivery dates."), }, }; }