notify-me-wl 1.4.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -9
- package/build/notify-me-wl.js +667 -0
- package/build/notify-me-wl.min.js +1 -0
- package/package.json +17 -3
- package/CLAUDE.md +0 -199
- package/index.html +0 -21
- package/index.js +0 -553
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(){"use strict";const e=[{code:"AF",name:"Afghanistan"},{code:"AX",name:"Åland Islands"},{code:"AL",name:"Albania"},{code:"DZ",name:"Algeria"},{code:"AS",name:"American Samoa"},{code:"AD",name:"Andorra"},{code:"AO",name:"Angola"},{code:"AI",name:"Anguilla"},{code:"AG",name:"Antigua and Barbuda"},{code:"AR",name:"Argentina"},{code:"AM",name:"Armenia"},{code:"AW",name:"Aruba"},{code:"AU",name:"Australia"},{code:"AT",name:"Austria"},{code:"AZ",name:"Azerbaijan"},{code:"BS",name:"Bahamas"},{code:"BH",name:"Bahrain"},{code:"BD",name:"Bangladesh"},{code:"BB",name:"Barbados"},{code:"BY",name:"Belarus"},{code:"BE",name:"Belgium"},{code:"BZ",name:"Belize"},{code:"BJ",name:"Benin"},{code:"BM",name:"Bermuda"},{code:"BT",name:"Bhutan"},{code:"BO",name:"Bolivia"},{code:"BA",name:"Bosnia and Herzegovina"},{code:"BW",name:"Botswana"},{code:"BR",name:"Brazil"},{code:"BN",name:"Brunei"},{code:"BG",name:"Bulgaria"},{code:"BF",name:"Burkina Faso"},{code:"BI",name:"Burundi"},{code:"CV",name:"Cabo Verde"},{code:"KH",name:"Cambodia"},{code:"CM",name:"Cameroon"},{code:"CA",name:"Canada"},{code:"KY",name:"Cayman Islands"},{code:"CF",name:"Central African Republic"},{code:"TD",name:"Chad"},{code:"CL",name:"Chile"},{code:"CN",name:"China"},{code:"CO",name:"Colombia"},{code:"KM",name:"Comoros"},{code:"CG",name:"Congo"},{code:"CD",name:"Congo, DR"},{code:"CK",name:"Cook Islands"},{code:"CR",name:"Costa Rica"},{code:"HR",name:"Croatia"},{code:"CU",name:"Cuba"},{code:"CW",name:"Curaçao"},{code:"CY",name:"Cyprus"},{code:"CZ",name:"Czech Republic"},{code:"DK",name:"Denmark"},{code:"DJ",name:"Djibouti"},{code:"DM",name:"Dominica"},{code:"DO",name:"Dominican Republic"},{code:"EC",name:"Ecuador"},{code:"EG",name:"Egypt"},{code:"SV",name:"El Salvador"},{code:"GQ",name:"Equatorial Guinea"},{code:"ER",name:"Eritrea"},{code:"EE",name:"Estonia"},{code:"SZ",name:"Eswatini"},{code:"ET",name:"Ethiopia"},{code:"FO",name:"Faroe Islands"},{code:"FJ",name:"Fiji"},{code:"FI",name:"Finland"},{code:"FR",name:"France"},{code:"GF",name:"French Guiana"},{code:"PF",name:"French Polynesia"},{code:"GA",name:"Gabon"},{code:"GM",name:"Gambia"},{code:"GE",name:"Georgia"},{code:"DE",name:"Germany"},{code:"GH",name:"Ghana"},{code:"GI",name:"Gibraltar"},{code:"GR",name:"Greece"},{code:"GL",name:"Greenland"},{code:"GD",name:"Grenada"},{code:"GP",name:"Guadeloupe"},{code:"GU",name:"Guam"},{code:"GT",name:"Guatemala"},{code:"GN",name:"Guinea"},{code:"GW",name:"Guinea-Bissau"},{code:"GY",name:"Guyana"},{code:"HT",name:"Haiti"},{code:"HN",name:"Honduras"},{code:"HK",name:"Hong Kong"},{code:"HU",name:"Hungary"},{code:"IS",name:"Iceland"},{code:"IN",name:"India"},{code:"ID",name:"Indonesia"},{code:"IR",name:"Iran"},{code:"IQ",name:"Iraq"},{code:"IE",name:"Ireland"},{code:"IM",name:"Isle of Man"},{code:"IL",name:"Israel"},{code:"IT",name:"Italy"},{code:"JM",name:"Jamaica"},{code:"JP",name:"Japan"},{code:"JE",name:"Jersey"},{code:"JO",name:"Jordan"},{code:"KZ",name:"Kazakhstan"},{code:"KE",name:"Kenya"},{code:"KI",name:"Kiribati"},{code:"KR",name:"Korea, South"},{code:"XK",name:"Kosovo"},{code:"KW",name:"Kuwait"},{code:"KG",name:"Kyrgyzstan"},{code:"LA",name:"Laos"},{code:"LV",name:"Latvia"},{code:"LB",name:"Lebanon"},{code:"LS",name:"Lesotho"},{code:"LR",name:"Liberia"},{code:"LY",name:"Libya"},{code:"LI",name:"Liechtenstein"},{code:"LT",name:"Lithuania"},{code:"LU",name:"Luxembourg"},{code:"MO",name:"Macao"},{code:"MG",name:"Madagascar"},{code:"MW",name:"Malawi"},{code:"MY",name:"Malaysia"},{code:"MV",name:"Maldives"},{code:"ML",name:"Mali"},{code:"MT",name:"Malta"},{code:"MH",name:"Marshall Islands"},{code:"MQ",name:"Martinique"},{code:"MR",name:"Mauritania"},{code:"MU",name:"Mauritius"},{code:"MX",name:"Mexico"},{code:"FM",name:"Micronesia"},{code:"MD",name:"Moldova"},{code:"MC",name:"Monaco"},{code:"MN",name:"Mongolia"},{code:"ME",name:"Montenegro"},{code:"MS",name:"Montserrat"},{code:"MA",name:"Morocco"},{code:"MZ",name:"Mozambique"},{code:"MM",name:"Myanmar"},{code:"NA",name:"Namibia"},{code:"NR",name:"Nauru"},{code:"NP",name:"Nepal"},{code:"NL",name:"Netherlands"},{code:"NC",name:"New Caledonia"},{code:"NZ",name:"New Zealand"},{code:"NI",name:"Nicaragua"},{code:"NE",name:"Niger"},{code:"NG",name:"Nigeria"},{code:"NU",name:"Niue"},{code:"MK",name:"North Macedonia"},{code:"NO",name:"Norway"},{code:"OM",name:"Oman"},{code:"PK",name:"Pakistan"},{code:"PW",name:"Palau"},{code:"PS",name:"Palestine"},{code:"PA",name:"Panama"},{code:"PG",name:"Papua New Guinea"},{code:"PY",name:"Paraguay"},{code:"PE",name:"Peru"},{code:"PH",name:"Philippines"},{code:"PL",name:"Poland"},{code:"PT",name:"Portugal"},{code:"PR",name:"Puerto Rico"},{code:"QA",name:"Qatar"},{code:"RE",name:"Réunion"},{code:"RO",name:"Romania"},{code:"RW",name:"Rwanda"},{code:"KN",name:"Saint Kitts and Nevis"},{code:"LC",name:"Saint Lucia"},{code:"VC",name:"Saint Vincent and the Grenadines"},{code:"WS",name:"Samoa"},{code:"SM",name:"San Marino"},{code:"SA",name:"Saudi Arabia"},{code:"SN",name:"Senegal"},{code:"RS",name:"Serbia"},{code:"SC",name:"Seychelles"},{code:"SL",name:"Sierra Leone"},{code:"SG",name:"Singapore"},{code:"SK",name:"Slovakia"},{code:"SI",name:"Slovenia"},{code:"SB",name:"Solomon Islands"},{code:"SO",name:"Somalia"},{code:"ZA",name:"South Africa"},{code:"SS",name:"South Sudan"},{code:"ES",name:"Spain"},{code:"LK",name:"Sri Lanka"},{code:"SD",name:"Sudan"},{code:"SR",name:"Suriname"},{code:"SE",name:"Sweden"},{code:"CH",name:"Switzerland"},{code:"SY",name:"Syria"},{code:"TW",name:"Taiwan"},{code:"TJ",name:"Tajikistan"},{code:"TZ",name:"Tanzania"},{code:"TH",name:"Thailand"},{code:"TL",name:"Timor-Leste"},{code:"TG",name:"Togo"},{code:"TO",name:"Tonga"},{code:"TT",name:"Trinidad and Tobago"},{code:"TN",name:"Tunisia"},{code:"TR",name:"Turkey"},{code:"TM",name:"Turkmenistan"},{code:"TC",name:"Turks and Caicos Islands"},{code:"TV",name:"Tuvalu"},{code:"UG",name:"Uganda"},{code:"UA",name:"Ukraine"},{code:"AE",name:"United Arab Emirates"},{code:"GB",name:"United Kingdom"},{code:"US",name:"United States"},{code:"UY",name:"Uruguay"},{code:"UZ",name:"Uzbekistan"},{code:"VU",name:"Vanuatu"},{code:"VE",name:"Venezuela"},{code:"VN",name:"Vietnam"},{code:"VG",name:"Virgin Islands, British"},{code:"VI",name:"Virgin Islands, U.S."},{code:"YE",name:"Yemen"},{code:"ZM",name:"Zambia"},{code:"ZW",name:"Zimbabwe"}];let n=null;async function a(e,a,o){let t="Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJRWlJkS3JabXJmMEk3WkhXRUtqNWRLTEhQanFubWJFeV9iNmpSbHdya1drIn0.eyJleHAiOjE3MjMwMzI3NzIsImlhdCI6MTcyMzAyOTE3MiwianRpIjoiNDJiNGYwM2QtMDNiNS00NmZlLTk5YmItZDQ2NTdhNjk5NGNiIiwiaXNzIjoiaHR0cHM6Ly9hdXRoLmF1LWF3cy50aGV3aXNobGlzdC5pby9hdXRoL3JlYWxtcy90d2NNYWluIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjI2YTIyNTAyLWRhNzQtNDhkMC1iZWFiLTgzY2E0YTlmMDdlOSIsInR5cCI6IkJlYXJlciIsImF6cCI6InR3Yy1wb3MtY2xpZW50Iiwic2Vzc2lvbl9zdGF0ZSI6IjQxYWQwMDc4LWVmYTItNGVjMi1hM2I2LTIzYjBkNDM3YjEzOCIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cHM6Ly9sb2NhbGhvc3QiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbInR3Yy1wb3MtdXNlciIsIm9mZmxpbmVfYWNjZXNzIiwidHdjLXN0b3JlLW93bmVyIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InRlbmFudGlkIHN0b3JlIHByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInRlbmFudGlkIjoidmlrdG9yaWEtd29vZHMiLCJuYW1lIjoiTWF0dCBIYW1wc2hpcmUiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJtYXR0QHRoZXdpc2hsaXN0LmlvIiwic3RvcmUiOiIyMDUiLCJnaXZlbl9uYW1lIjoiTWF0dCIsImZhbWlseV9uYW1lIjoiSGFtcHNoaXJlIiwiZW1haWwiOiJtYXR0QHRoZXdpc2hsaXN0LmlvIn0.iZkMgwH74njjXUWvImkJomHYr91Lr8ZGrZGwslEGcV3vbNuoNc5CocvNWW476o-LoSh-LsKf-MLiYN1XvOuPDF3fGoGCEbMh6_M0RJcrhVWogkj81fx4ukvDPCFIjgoDCV9WIuehV9dsSWa7E0irZeE6MUVhLwRIaTzKtxgzUUKrAqBtI_HKpyo8TUGQBiYlrc85QFUyuoKbKg-QaRn_SObRLDB8ooIBJvIlgklXQt1ZYBM2HUOc5L1bAQwfzcrWEvl6eYiQHXCSPqS0rPGoaGC6v5ydBo9VMxtVHGladDHLrO3Gt2BnIGMBoYrKTAmt7j0KABwPyB3CmAIwj_pOBQ";if("proxy"===a){const e=await async function(){if(n)return n;try{const e=await fetch("/apps/twc-sdk/auth/token",{method:"GET",headers:{Accept:"application/json"}}),a=await e.json().catch(()=>null);return e.ok&&a&&a.success&&a.data&&a.data.access_token?(n=a.data.access_token,n):null}catch(e){return console.error("Error fetching proxy access token:",e),null}}();if(!e)return{ok:!1,reason:"auth"};t=`Bearer ${e}`}try{return(await fetch("https://api.au-sandbox.thewishlist.io/services/wsservice/api/wishlist/items/customerInterest",{method:"POST",headers:{"Content-Type":"application/json",Authorization:t,"X-Twc-Tenant":o},body:JSON.stringify(e)})).ok?{ok:!0}:{ok:!1,reason:"error"}}catch(e){return console.error("Error submitting form:",e),{ok:!1,reason:"error"}}}const o={"notify-me":{text:"Register to receive a notification as soon as this item is back in stock",buttonText:"Notify Me"},"coming-soon":{text:"Register your interest to hear more about this item",buttonText:"Register Interest"}};function t(n){const{wrapper:t,openButton:c,config:i,productData:d,countryCtx:r}=n,{fields:m,type:l,authMode:s,tenant:u,marketId:p}=i,b=document.createElement("div");b.innerHTML='\n <div id="twc-nm-overlay" role="dialog" aria-modal="true" aria-labelledby="popup-title">\n <div class="twc-nm-card">\n <button type="button" id="popup-close" class="twc-nm-close" aria-label="Close">×</button>\n <h2 id="popup-title" class="twc-nm-title"></h2>\n <p id="popup-text" class="twc-nm-text"></p>\n <form id="popup-form" class="twc-nm-form">\n <div class="twc-nm-field">\n <label class="twc-nm-label" for="twc-nm-size">Size</label>\n <select class="twc-nm-select" id="twc-nm-size" name="select-size" required>\n <option value="" disabled selected>Select a size</option>\n </select>\n </div>\n </form>\n </div>\n </div>\n ',t.appendChild(b);const y=document.getElementById("twc-nm-overlay"),w=document.getElementById("popup-close"),h=document.getElementById("popup-title"),f=document.getElementById("popup-text"),g=document.querySelector("select[name='select-size']"),v=document.getElementById("popup-form");if(!(y&&w&&h&&f&&g&&v))return;f.innerText=o[l].text;const I=e.map(e=>`<option value="${e.code}"${e.code===r.countryCode?" selected":""}>${e.name}</option>`).join(""),C=(e,n,a)=>`<div class="twc-nm-field"><label class="twc-nm-label" for="${e}">${n}</label>${a}</div>`,x={email:C("twc-nm-email","Email",'<input class="twc-nm-input" id="twc-nm-email" name="email" type="email" placeholder="you@example.com" required />'),mobile:C("twc-nm-mobile","Mobile",'<input class="twc-nm-input" id="twc-nm-mobile" name="mobile" type="tel" placeholder="Mobile number" required />'),firstName:C("twc-nm-firstname","First name",'<input class="twc-nm-input" id="twc-nm-firstname" name="firstName" type="text" placeholder="First name" required />'),lastName:C("twc-nm-lastname","Last name",'<input class="twc-nm-input" id="twc-nm-lastname" name="lastName" type="text" placeholder="Last name" required />'),countryCode:C("twc-nm-country","Country",`<select class="twc-nm-select" id="twc-nm-country" name="countryCode"><option value="">Select country</option>${I}</select>`),provinceCode:C("twc-nm-province","State / Province",`<input class="twc-nm-input" id="twc-nm-province" name="provinceCode" type="text" placeholder="State / province code" value="${r.provinceCode||""}" />`)};m.forEach(e=>{x[e]&&v.insertAdjacentHTML("beforeend",x[e])}),v.insertAdjacentHTML("beforeend",'<div class="twc-nm-checks">\n <label class="twc-nm-check"><input type="checkbox" name="mailList" /> Email me store updates</label>\n <label class="twc-nm-check"><input type="checkbox" name="mailListSms" /> Text me store updates</label>\n </div>'),v.insertAdjacentHTML("beforeend",'<div id="popup-status" class="twc-nm-status" role="status" aria-live="polite" hidden></div>'),v.insertAdjacentHTML("beforeend",`<button type="submit" class="twc-nm-submit">${o[l].buttonText}</button>`);const M=document.getElementById("popup-status"),S=v.querySelector(".twc-nm-submit");if(!M||!S)return;function N(e,n){M.textContent=n,M.className=`twc-nm-status twc-nm-status--${e}`,M.hidden=!1}function k(){M.hidden=!0,M.textContent=""}const L=e=>{const n=v.querySelector(e);return n?n.value:""},G=e=>{const n=v.querySelector(e);return!!n&&n.checked};let E=!1,B=null;function T(e){"Escape"===e.key&&A()}function A(){y.classList.remove("is-open"),document.body.style.overflow="",document.removeEventListener("keydown",T),k(),B&&"function"==typeof B.focus&&B.focus()}c.addEventListener("click",function(){if(B=document.activeElement,y.classList.add("is-open"),document.body.style.overflow="hidden",document.addEventListener("keydown",T),!d)return v.hidden=!0,void N("error","Product information is unavailable. Please refresh the page.");h.textContent=d.title,E||((d.variants||[]).forEach(e=>{const n=document.createElement("option");n.value=e.title,n.textContent=e.title,g.appendChild(n)}),E=!0);const e=v.querySelector("select, input");e&&e.focus()}),w.addEventListener("click",A),y.addEventListener("click",e=>{e.target===y&&A()}),v.addEventListener("submit",async e=>{e.preventDefault();const n=((null==d?void 0:d.variants)||[]).find(e=>e.title===g.value);if(!n)return void N("error","Please select a size.");const o={variantRef:n.id,email:L("input[name='email']"),subscribe:G("input[name='mailList']"),subscribeSms:G("input[name='mailListSms']")};if("coming-soon"===l?o.comingSoon=!0:o.notifyMe=!0,m.includes("firstName")&&(o.firstName=L("input[name='firstName']")),m.includes("lastName")&&(o.lastName=L("input[name='lastName']")),m.includes("mobile")&&(o.mobile=L("input[name='mobile']")),m.includes("countryCode")){const e=L("select[name='countryCode']");e&&(o.countryCode=e)}else r.countryCode&&(o.countryCode=r.countryCode);if(m.includes("provinceCode")){const e=L("input[name='provinceCode']");e&&(o.provinceCode=e)}else r.provinceCode&&(o.provinceCode=r.provinceCode);p&&(o.marketId=p),k();const t=S.textContent||"";S.disabled=!0,S.textContent="Sending…";try{const e=await a(o,s,u);e.ok?(N("success","You're on the list. We'll be in touch."),setTimeout(A,1500)):"auth"===e.reason?N("error","Please log in to your account to continue."):N("error","Something went wrong. Please try again.")}finally{S.disabled=!1,S.textContent=t}})}document.addEventListener("DOMContentLoaded",()=>{const e=document.getElementById("notification-widget");if(!e)return;const n=document.getElementById("popup-open");if(!n)return;!function(){const e=document.createElement("style");e.type="text/css",e.innerText="\n .notification-btn {\n display: inline-block;\n width: 100%;\n padding: 12px 24px;\n background: #fff;\n border: 1px solid #111827;\n border-radius: 8px;\n color: #111827;\n font: inherit;\n text-align: center;\n text-transform: uppercase;\n cursor: pointer;\n }\n .notification-btn:hover {\n background: #111827;\n color: #fff;\n }\n #twc-nm-overlay {\n position: fixed;\n inset: 0;\n z-index: 99999;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n background: rgba(17, 17, 17, 0.55);\n opacity: 0;\n visibility: hidden;\n transition: opacity 200ms ease;\n }\n #twc-nm-overlay.is-open {\n opacity: 1;\n visibility: visible;\n }\n #twc-nm-overlay * {\n box-sizing: border-box;\n }\n #twc-nm-overlay .twc-nm-card {\n position: relative;\n width: 100%;\n max-width: 400px;\n max-height: calc(100vh - 32px);\n overflow-y: auto;\n padding: 24px;\n background: #fff;\n color: #111827;\n border-radius: 12px;\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.18);\n font: inherit;\n transform: translateY(8px);\n transition: transform 200ms ease;\n }\n #twc-nm-overlay.is-open .twc-nm-card {\n transform: translateY(0);\n }\n #twc-nm-overlay .twc-nm-close {\n position: absolute;\n top: 12px;\n right: 12px;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n background: transparent;\n border-radius: 6px;\n font-size: 24px;\n line-height: 1;\n color: #6b7280;\n cursor: pointer;\n }\n #twc-nm-overlay .twc-nm-close:hover {\n background: #f3f4f6;\n color: #111827;\n }\n #twc-nm-overlay .twc-nm-title {\n margin: 0 32px 4px 0;\n font-size: 18px;\n font-weight: 600;\n }\n #twc-nm-overlay .twc-nm-text {\n margin: 0 0 16px;\n font-size: 14px;\n line-height: 1.5;\n color: #6b7280;\n }\n #twc-nm-overlay .twc-nm-form {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n #twc-nm-overlay .twc-nm-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n #twc-nm-overlay .twc-nm-label {\n font-size: 13px;\n font-weight: 500;\n color: #374151;\n }\n #twc-nm-overlay .twc-nm-input,\n #twc-nm-overlay .twc-nm-select {\n width: 100%;\n padding: 10px 12px;\n font-size: 14px;\n font-family: inherit;\n color: #111827;\n background: #fff;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n }\n #twc-nm-overlay .twc-nm-input:focus,\n #twc-nm-overlay .twc-nm-select:focus {\n outline: none;\n border-color: #111827;\n box-shadow: 0 0 0 3px rgba(17, 24, 39, 0.08);\n }\n #twc-nm-overlay .twc-nm-select {\n appearance: none;\n -webkit-appearance: none;\n padding-right: 36px;\n cursor: pointer;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2 4l4 4 4-4' stroke='%236b7280' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 12px center;\n }\n #twc-nm-overlay .twc-nm-checks {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n #twc-nm-overlay .twc-nm-check {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #374151;\n cursor: pointer;\n }\n #twc-nm-overlay .twc-nm-check input {\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: #111827;\n }\n #twc-nm-overlay .twc-nm-status {\n font-size: 13px;\n line-height: 1.5;\n padding: 10px 12px;\n border-radius: 8px;\n }\n #twc-nm-overlay .twc-nm-status--error {\n color: #b91c1c;\n background: #fef2f2;\n }\n #twc-nm-overlay .twc-nm-status--success {\n color: #15803d;\n background: #f0fdf4;\n }\n #twc-nm-overlay .twc-nm-submit {\n width: 100%;\n padding: 12px 16px;\n font-size: 14px;\n font-weight: 600;\n font-family: inherit;\n color: #fff;\n background: #111827;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: background 150ms ease;\n }\n #twc-nm-overlay .twc-nm-submit:hover {\n background: #374151;\n }\n #twc-nm-overlay .twc-nm-submit:disabled {\n opacity: 0.6;\n cursor: default;\n }\n @media (prefers-reduced-motion: reduce) {\n #twc-nm-overlay,\n #twc-nm-overlay .twc-nm-card {\n transition: none;\n }\n #twc-nm-overlay .twc-nm-card {\n transform: none;\n }\n }\n ",document.head.appendChild(e)}();const a=JSON.parse(n.getAttribute("data-fields")||'["email"]'),o=n.getAttribute("data-type")||"notify-me",c=n.getAttribute("data-auth")||"token",i=n.getAttribute("data-tenant")||"victoria-woods",d=function(){var e,n;const a={countryCode:null,provinceCode:null,marketId:null},o=window.Shopify;if(o){"string"==typeof o.country&&(a.countryCode=o.country);const n=null===(e=o.markets)||void 0===e?void 0:e.currentMarket;if(n&&(n.countryCode&&(a.countryCode=n.countryCode),null!=n.id&&(a.marketId=String(n.id))),!a.countryCode&&"string"==typeof o.locale){const e=o.locale.split("-");e.length>1&&(a.countryCode=e[e.length-1].toUpperCase())}}if(!a.countryCode||!a.provinceCode){const e=null===(n=window.customer)||void 0===n?void 0:n.default_address;e&&(!a.countryCode&&e.country_code&&(a.countryCode=e.country_code),!a.provinceCode&&e.province_code&&(a.provinceCode=e.province_code))}if(!a.countryCode){const e=(navigator.language||"").split("-");e.length>1&&(a.countryCode=e[e.length-1].toUpperCase())}return a}(),r=n.getAttribute("data-market-id")||d.marketId;t({wrapper:e,openButton:n,config:{fields:a,type:o,authMode:c,tenant:i,marketId:r},productData:window.currentProduct,countryCtx:d})})}();
|
package/package.json
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "notify-me-wl",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Coming Soon / Notify Me wishlist widget for retailer product pages.",
|
|
5
|
+
"main": "build/notify-me-wl.min.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"build"
|
|
8
|
+
],
|
|
5
9
|
"scripts": {
|
|
10
|
+
"build": "rollup -c",
|
|
11
|
+
"dev": "rollup -c -w",
|
|
12
|
+
"typecheck": "tsc --noEmit",
|
|
6
13
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
14
|
},
|
|
8
15
|
"author": "",
|
|
9
16
|
"license": "ISC",
|
|
10
|
-
"
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
19
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
20
|
+
"@rollup/plugin-typescript": "^12.1.2",
|
|
21
|
+
"rollup": "^4.21.0",
|
|
22
|
+
"tslib": "^2.7.0",
|
|
23
|
+
"typescript": "^5.6.0"
|
|
24
|
+
}
|
|
11
25
|
}
|
package/CLAUDE.md
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md — The Wishlist Company (TWC / Wishlist.io)
|
|
2
|
-
|
|
3
|
-
This file gives Claude Code persistent context about the TWC platform so every session starts informed. Update it as the platform evolves.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## This Repository
|
|
8
|
-
|
|
9
|
-
**Repo:** `notify-me_coming-soon-wl-widget`
|
|
10
|
-
**GitHub:** https://github.com/The-Wishlist-Co/notify-me_coming-soon-wl-widget
|
|
11
|
-
|
|
12
|
-
Customer-facing widget for 'Notify Me' and 'Coming Soon' wishlist functionality. Embedded on retailer product pages.
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## Platform Overview
|
|
19
|
-
|
|
20
|
-
**Wishlist.io** is a SaaS retail platform focused on capturing and activating consumer intent data, primarily in fashion retail. It surfaces wishlist and engagement data to frontline retail staff and powers personalised outreach via messaging templates.
|
|
21
|
-
|
|
22
|
-
**GitHub org:** https://github.com/The-Wishlist-Co
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## Service Architecture
|
|
27
|
-
|
|
28
|
-
Microservices stack deployed on **AWS EKS**, service mesh via **Istio + Consul**. Netflix OSS for gateway/resilience. All services are **Spring Boot / JHipster**, Java 13.
|
|
29
|
-
|
|
30
|
-
| Service | Role |
|
|
31
|
-
|---|---|
|
|
32
|
-
| `twcgateway` | API gateway (Zuul) |
|
|
33
|
-
| `wsservice` | Wishlist core service |
|
|
34
|
-
| `customerservice` | Customer profile service |
|
|
35
|
-
| `productsvc` | Product catalogue service |
|
|
36
|
-
| `eventcollector` | Event ingestion |
|
|
37
|
-
| `inventorysvc` | Inventory service |
|
|
38
|
-
| `merchantsvc` | Merchant/retailer management |
|
|
39
|
-
| `ordersvc` | Order service |
|
|
40
|
-
|
|
41
|
-
**Observability:** OpenTelemetry + Datadog. Logs via Filebeat → Elasticsearch (`twc-ops` cluster, ECK on EKS, Elasticsearch 8.3.3, 4-node).
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Critical Infrastructure Constraints
|
|
46
|
-
|
|
47
|
-
### Java / JVM (ALL services)
|
|
48
|
-
|
|
49
|
-
All services run Java 13 in containers and **cannot auto-detect CPU limits correctly via cgroups**. Every service deployment MUST include:
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
-XX:ActiveProcessorCount=N
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
in `JAVA_OPTS`, where N matches the container's CPU allocation. Omitting this causes Undertow thread pool over-sizing → Consul health check failures → Hystrix circuit breaker trips → 500 SHORTCIRCUIT errors at the gateway.
|
|
56
|
-
|
|
57
|
-
Affected services (apply to all eight): `twcgateway`, `wsservice`, `customerservice`, `productsvc`, `eventcollector`, `inventorysvc`, `merchantsvc`, `ordersvc`.
|
|
58
|
-
|
|
59
|
-
### Elasticsearch / ECK
|
|
60
|
-
|
|
61
|
-
- Cluster: `twc-ops`, 4 nodes on EKS via ECK operator
|
|
62
|
-
- **Memory:** each node must be configured with **4Gi** (`-Xms2g -Xmx2g`). Nodes with 2Gi will OOM-kill under load.
|
|
63
|
-
- **ILM:** Filebeat data stream indices require an ILM policy with **3-day retention** to prevent disk exhaustion.
|
|
64
|
-
- Yellow cluster state will block ECK rolling restarts — resolve unassigned shards before patching the CR.
|
|
65
|
-
|
|
66
|
-
### EKS Scaling Lambda
|
|
67
|
-
|
|
68
|
-
A Lambda (`eks_node_scaleup`) has hardcoded node group values and will override manual EKS scaling changes. Do not rely on manual scaling being durable — any fix must go into the Lambda source.
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## Data Architecture
|
|
73
|
-
|
|
74
|
-
### ClickHouse (Analytics / Reporting)
|
|
75
|
-
|
|
76
|
-
Used for conversion reporting and analytics. All ETL queries follow strict conventions — see Query Conventions below.
|
|
77
|
-
|
|
78
|
-
### DynamoDB (Operational)
|
|
79
|
-
|
|
80
|
-
Key tables:
|
|
81
|
-
|
|
82
|
-
| Table | PK | SK | Notes |
|
|
83
|
-
|---|---|---|---|
|
|
84
|
-
| `TWCTEMPLATE_TOPIC` | `tenantId` | `topicId` | Soft-delete via `active` flag |
|
|
85
|
-
| `MESSAGE` | — | — | `messageTopic` stored directly at send time — single source of truth |
|
|
86
|
-
|
|
87
|
-
`messageTopic` is captured on the MESSAGE record at send time and is **not** looked up from `TWCTEMPLATE_TOPIC` at query time. This is intentional.
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## ClickHouse Query Conventions
|
|
92
|
-
|
|
93
|
-
These conventions are non-negotiable. All new queries must follow them.
|
|
94
|
-
|
|
95
|
-
### Named Queries (Conversion Reporting Dashboard)
|
|
96
|
-
|
|
97
|
-
| Query ID | Description |
|
|
98
|
-
|---|---|
|
|
99
|
-
| `CONV_KPI_SUMMARY` | Top-level KPI summary |
|
|
100
|
-
| `CONV_TREND_DAILY` | Daily trend over period |
|
|
101
|
-
| `CONV_BREAKDOWN_STORE` | Breakdown by store |
|
|
102
|
-
| `CONV_BREAKDOWN_STAFF` | Breakdown by staff |
|
|
103
|
-
| `CONV_BREAKDOWN_TOPIC` | Breakdown by message topic |
|
|
104
|
-
| `CONV_BREAKDOWN_TEMPLATE_TAG` | Breakdown by template tag |
|
|
105
|
-
| `CONV_BREAKDOWN_CUSTOMER_TAG` | Breakdown by customer tag |
|
|
106
|
-
| `CONV_BREAKDOWN_CHANNEL` | Breakdown by channel |
|
|
107
|
-
|
|
108
|
-
### API Parameter Naming Convention
|
|
109
|
-
|
|
110
|
-
| Parameter | Maps to |
|
|
111
|
-
|---|---|
|
|
112
|
-
| `value1` | channel |
|
|
113
|
-
| `value2` | topic |
|
|
114
|
-
| `value3` | templateTag |
|
|
115
|
-
| `value4` | customerTag |
|
|
116
|
-
| `param5` | storeRefs (array) |
|
|
117
|
-
| `param6` | staffRefs (array) |
|
|
118
|
-
|
|
119
|
-
### Filter Syntax Rules
|
|
120
|
-
|
|
121
|
-
**`storeRef` and `staffRef` are ALWAYS multi-select.** These are never single-value filters.
|
|
122
|
-
|
|
123
|
-
```sql
|
|
124
|
-
-- ✅ CORRECT — always use IN with empty() guard
|
|
125
|
-
AND (empty({param5: Array(String)}) OR storeRef IN {param5: Array(String)})
|
|
126
|
-
AND (empty({param6: Array(String)}) OR staffRef IN {param6: Array(String)})
|
|
127
|
-
|
|
128
|
-
-- ❌ WRONG — never use equality for store or staff
|
|
129
|
-
AND storeRef = {param5: String}
|
|
130
|
-
AND staffRef = {param6: String}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
All other filters (`value1`–`value4`) follow the same array pattern if they are multi-select dropdowns.
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
## Integrations
|
|
138
|
-
|
|
139
|
-
### Shopify
|
|
140
|
-
|
|
141
|
-
- Custom pixel integration on `twc-fashion-demo.myshopify.com` (pixel `87425273`)
|
|
142
|
-
- Pixels require `analytics.subscribe('init', ...)` capture and `Content-Type: application/json` header
|
|
143
|
-
- App updates auto-deploy to all merchants unless new OAuth permission scopes are required
|
|
144
|
-
|
|
145
|
-
### Gorgias
|
|
146
|
-
|
|
147
|
-
Backend proxy integration surfacing support ticket data on customer profile screens.
|
|
148
|
-
|
|
149
|
-
- Per-customer credentials stored encrypted (AES-256) in `gorgias_credentials` table
|
|
150
|
-
- Ticket data cached in `gorgias_ticket_cache`
|
|
151
|
-
- Cache TTLs: 15 min (summary), 2 min (full ticket list)
|
|
152
|
-
- Five API endpoints for credential management and ticket retrieval
|
|
153
|
-
|
|
154
|
-
### Emarsys
|
|
155
|
-
|
|
156
|
-
Marketing automation platform integration. Customer data synced from TWC to Emarsys for campaign targeting. Webhook updates received via `emarsys-webhook-updates` Lambda.
|
|
157
|
-
|
|
158
|
-
### Newstore
|
|
159
|
-
|
|
160
|
-
POS platform integration. TWC builds plugins/webviews for the Newstore POS environment. Webhooks received via `twc-newstore-webhook`. Proxy via `infinityAPI` for Triquestra Infinity POS.
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## Development Conventions
|
|
165
|
-
|
|
166
|
-
### General
|
|
167
|
-
|
|
168
|
-
- Full-stack ownership: data modelling, API design, backend, infra/DevOps, frontend
|
|
169
|
-
- Prefer explicit over implicit — document intent in code comments for complex query logic
|
|
170
|
-
- All schema changes should consider soft-delete patterns (see `TWCTEMPLATE_TOPIC` above)
|
|
171
|
-
- Default branch: `main`
|
|
172
|
-
- Feature branches cut from `main`, kebab-case description (e.g. `suppression-change`)
|
|
173
|
-
- PR back to `main` when complete
|
|
174
|
-
|
|
175
|
-
### Code Review Checklist (for Claude Code to apply)
|
|
176
|
-
|
|
177
|
-
Before suggesting or approving any change, verify:
|
|
178
|
-
|
|
179
|
-
- [ ] All ClickHouse queries touching store/staff use `IN` + `empty()` guard, not `=`
|
|
180
|
-
- [ ] Any new or modified Spring Boot service includes `-XX:ActiveProcessorCount` in JAVA_OPTS config
|
|
181
|
-
- [ ] DynamoDB table designs include `tenantId` as PK for all multi-tenant tables
|
|
182
|
-
- [ ] New Elasticsearch indices have an ILM policy assigned
|
|
183
|
-
- [ ] API parameter names follow the `value1`–`value4` / `param5`/`param6` convention
|
|
184
|
-
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
## Key External References
|
|
188
|
-
|
|
189
|
-
- Anthropic Claude Code docs: https://docs.claude.com/en/docs/claude-code/overview
|
|
190
|
-
- ECK operator docs: https://www.elastic.co/guide/en/cloud-on-k8s/current/index.html
|
|
191
|
-
- Shopify custom pixels: https://shopify.dev/docs/api/web-pixels-api
|
|
192
|
-
|
|
193
|
-
---
|
|
194
|
-
|
|
195
|
-
*Last updated: May 2026. Keep this file current as the platform evolves — it is the primary context source for all Claude Code sessions.*
|
|
196
|
-
|
|
197
|
-
## References
|
|
198
|
-
- **Engineering Standards:** https://github.com/The-Wishlist-Co/twc-api-specs/blob/main/standards/TWC-STANDARDS.md
|
|
199
|
-
- **API Specifications:** https://github.com/The-Wishlist-Co/twc-api-specs/blob/main/apis/
|
package/index.html
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Notify me</title>
|
|
7
|
-
<style>
|
|
8
|
-
body {
|
|
9
|
-
height: 100vh;
|
|
10
|
-
margin: 100px auto;
|
|
11
|
-
width: 300px;
|
|
12
|
-
}
|
|
13
|
-
</style>
|
|
14
|
-
</head>
|
|
15
|
-
<body>
|
|
16
|
-
<div id="notification-widget">
|
|
17
|
-
<button id="popup-open" class="notification-btn" type="button" data-type="notify-me" data-fields='["firstName", "lastName"]'>Notify Me - Join Waitlist</button>
|
|
18
|
-
</div>
|
|
19
|
-
</body>
|
|
20
|
-
<script src="/index.js"></script>
|
|
21
|
-
</html>
|