| | |
| | | (()=>{class e{constructor(){this.container=document.querySelector(".jvb-referral"),this.container&&(this.a11y=window.jvbA11y,this.toggle=document.querySelector('button[data-action="toggle-referral"]'),this.initElements(),this.initListeners(),this.checkForReferral())}initElements(){this.selectors={copy:"button.copy",login:".login",submit:"[type=submit]"},this.forms=this.container.querySelectorAll("form"),console.log(this.forms),this.popup=new window.jvbPopup({toggle:this.toggle,popup:this.container,name:"Referral Box",onOpen:()=>{this.forms.forEach((e=>{e.addEventListener("submit",this.submitHandler)})),this.container.addEventListener("click",this.clickHandler),this.container.addEventListener("input",this.inputHandler)},onClose:()=>{this.forms.forEach((e=>{e.removeEventListener("submit",this.submitHandler)})),this.container.removeEventListener("click",this.clickHandler),this.container.removeEventListener("input",this.inputHandler)}}),this.tabs=null,this.container.querySelector("nav.tabs")&&(this.tabs=new window.jvbTabs(this.container,{updateURL:!1})),this.ui=window.uiFromSelectors(this.selectors,this.container)}initListeners(){this.clickHandler=this.handleClick.bind(this),this.inputHandler=this.handleInput.bind(this),this.submitHandler=this.handleFormSubmit.bind(this),this.changeHandler=this.handleChange.bind(this)}handleClick(e){if(e.target.classList.contains(".copy")){let t=e.target.dataset.target,r=this.container.querySelector(`#${t}`);r=!!r&&r.textContent,r&&this.handleCopy(e.target,r)}}handleChange(e){"referral-code"===e.target.id&&window.debouncer.schedule("check-referral",(()=>this.makeRequest("referrals/check-code",{code:e.target.value})))}handleInput(e){"referral-code"===e.target.id&&(e.target.value=e.target.value.toUpperCase())}initShareWidget(){this.initCopyButton(),this.loadStats()}async checkForReferral(){const e=this.getUrlParameter("seeReferral"),t=this.getUrlParameter("ref");if(!e&&!t)return;if(!t)return void this.popup.openPopup();const r=this.container.querySelector("#referral-code-input");if(!r)return;const n=t.toUpperCase();r.value=n,r.readOnly=!0,this.popup.togglePopup();try{const e=await this.validateCodeOnly(n);if(e.success){this.showReferrerBanner(e.referrer_name,n);const t=this.container.querySelector("#referral-name");t&&t.focus()}else r.readOnly=!1,this.showMessage("This referral link is invalid. Please enter a valid code.","error")}catch(e){console.error("Error validating code:",e),r.readOnly=!1}this.removeUrlParameter("ref")}getUrlParameter(e){return new URLSearchParams(window.location.search).get(e)}removeUrlParameter(e){const t=new URL(window.location);t.searchParams.delete(e),window.history.replaceState({},document.title,t.toString())}async validateCodeOnly(e){const t=await fetch(`${jvbSettings.api}/referrals/check-code`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:e})});return await t.json()}showReferrerBanner(e,t){const r=this.container.querySelector(".referral-header");if(!r)return;const n=document.createElement("div");n.className="referrer-banner",n.innerHTML=`\n <div class="banner-icon">🎉</div>\n <div class="banner-content">\n <strong>${window.escapeHtml(e)}</strong> referred you!\n <div class="banner-code">Code: <code>${window.escapeHtml(t)}</code></div>\n </div>\n `,r.parentNode.insertBefore(n,r.nextSibling);const a=r.querySelector("h3");a&&(a.textContent="Complete Your Registration");const o=r.querySelector("p");o&&(o.textContent="Enter your details below to claim your welcome reward!")}handleCopy(e,t=""){if(""===t||"string"!=typeof t)return;let r=e.textContent;(navigator.clipboard||navigator.clipboard.writeText)&&navigator.clipboard.writeText(t).then((()=>{e.textContent="Copied!",e.style.background="#00a32a",setTimeout((()=>{e.textContent=r,e.style.background=""}),2e3)}))}async loadStats(){if(this.container.querySelector(".referral-stats"))try{const e=await fetch(`${jvbSettings.api}/referrals/stats`,{headers:{"X-WP-Nonce":jvbSettings.nonce}}),t=await e.json();t.success&&t.stats&&this.updateStats(t.stats)}catch(e){console.error("Error loading stats:",e)}}updateStats(e){const t={total:this.container.querySelector('[data-stat="total"]'),treated:this.container.querySelector('[data-stat="treated"]'),pending:this.container.querySelector('[data-stat="pending"]'),rewards:this.container.querySelector('[data-stat="rewards"]')};t.total&&(t.total.textContent=e.total_referrals||0),t.treated&&(t.treated.textContent=e.treated_count||0),t.pending&&(t.pending.textContent=e.pending_count||0),t.rewards&&(t.rewards.textContent="$"+parseFloat(e.available_rewards||0).toFixed(2))}async handleFormSubmit(e){console.log("Form Submission!"),window.debouncer.cancel("check-referral"),e.preventDefault(),console.log("Still working?");const t=e.target,r=new FormData(t);let n={};this.setFormLoading(!0,t);try{let e={success:!1,message:""};console.log(t),console.log(t.id),"referral-code-form"===t.id?(r.get("name")||(e.message+="We need your name to know who you are."),r.get("email")||(e.message+="We need your email to confirm you have access to it."),r.get("referral_code")||(e.message+="We need the referral code to know who sent you."),r.get("name")&&r.get("email")&&r.get("referral_code")&&(n.name=r.get("name"),n.email=r.get("email"),n.code=r.get("referral_code"),e=await this.makeRequest("referrals/register",n))):"login-form"===t.id&&r.get("login-email")&&(n.type="login",n.email=r.get("login-email"),n.context={},n.context.redirect_to=window.location.href+"?seeReferral=1",console.log("Making Request with: ",n),e=await this.makeRequest("magic",n)),e.success?this.handleSuccess(e):(this.showMessage(e.message||"Something went wrong. Please try again.","error"),this.setFormLoading(!1,t))}catch(e){console.error("Error registering:",e),this.showMessage("Something went wrong. Please try again.","error"),this.setFormLoading(!1,t)}finally{this.setFormLoading(!1,t)}}async makeRequest(e,t){if(!["magic","referrals/register","referrals/check-code"].includes(e))return{success:!1,message:"Something went wrong (Invalid endpoint)."};console.log("Endpoint: ",e),console.log("Data: ",t);const r=await fetch(`${jvbSettings.api}${e}`,{method:"POST",headers:{"Content-Type":"application/json","X-WP-Nonce":jvbSettings.nonce},body:JSON.stringify(t)});return await r.json()}handleSuccess(e){this.container.querySelectorAll("form").forEach((e=>{window.fade(e,!1)}));const t=this.container.querySelector(".success-message");t&&(t.hidden=!1,t.scrollIntoView({behavior:"smooth",block:"center"}),this.dispatchEvent("emailSent",{email:e.email}))}setFormLoading(e,t){t.querySelectorAll("input").forEach((t=>t.disabled=e));let r=t.querySelector(".status"),n=r.querySelector(".message");r.hidden=e,r.classList.toggle("loading",e),n.textContent=e?"Checking with server...":""}showMessage(e,t="success"){const r=this.container.querySelector("#referral-message");r&&(r.textContent=e,r.className="message "+t,r.style.display="block","error"===t&&setTimeout((()=>{r.style.display="none"}),5e3))}dispatchEvent(e,t){const r=new CustomEvent("referralWidget:"+e,{detail:t,bubbles:!0});this.container.dispatchEvent(r)}}document.addEventListener("DOMContentLoaded",(()=>{window.jvbReferral=new e}))})(); |
| | | (()=>{class e{constructor(){this.container=document.querySelector(".jvb-referral"),this.container&&(this.a11y=window.jvbA11y,this.toggle=document.querySelector('button[data-action="toggle-referral"]'),this.initElements(),this.initListeners(),this.checkForReferral(),this.isLoggedIn()&&(this.loadStats(),this.loadRecentReferrals()))}initElements(){this.selectors={copyBtn:".copy-btn",checkCode:".check-code-btn",submit:"[type=submit]"},this.forms=this.container.querySelectorAll("form"),this.popup=new window.jvbPopup({toggle:this.toggle,popup:this.container,name:"Referral Box",onOpen:()=>{this.bindEventListeners(!0)},onClose:()=>{this.bindEventListeners(!1)}}),this.tabs=null,this.container.querySelector("nav.tabs")&&(this.tabs=new window.jvbTabs(this.container,{updateURL:!1})),this.ui=window.uiFromSelectors(this.selectors,this.container)}initListeners(){this.clickHandler=this.handleClick.bind(this),this.inputHandler=this.handleInput.bind(this),this.submitHandler=this.handleFormSubmit.bind(this)}bindEventListeners(e){const t=e?"addEventListener":"removeEventListener";this.forms.forEach((e=>{e[t]("submit",this.submitHandler)})),this.container[t]("click",this.clickHandler),this.container[t]("input",this.inputHandler)}isLoggedIn(){return Boolean(jvbSettings.currentUser)}handleClick(e){const t=e.target.closest(".copy-btn, .check-code-btn, .attn");t&&(t.classList.contains("copy-btn")?this.handleCopyClick(t):t.classList.contains("check-code-btn")?this.handleCheckCode(e):t.classList.contains("attn")&&t.classList.remove("attn"))}handleCopyClick(e){const t=e.dataset.target,s=this.container.querySelector(`#${t}`);if(!s)return;const r=s.textContent.trim();navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(r).then((()=>{this.showCopySuccess(e)})).catch((()=>{this.selectText(s),this.showCopyFallback(e)})):(this.selectText(s),this.showCopyFallback(e))}selectText(e){if(window.getSelection&&document.createRange){const t=window.getSelection(),s=document.createRange();s.selectNodeContents(e),t.removeAllRanges(),t.addRange(s)}else if(document.body.createTextRange){const t=document.body.createTextRange();t.moveToElementText(e),t.select()}}showCopySuccess(e){const t=e.innerHTML;e.innerHTML=window.jvbIcon("check",{size:16})+" Copied!",e.classList.add("success"),setTimeout((()=>{e.innerHTML=t,e.classList.remove("success")}),2e3)}showCopyFallback(e){const t=e.innerHTML;e.innerHTML="✓ Selected - Press Ctrl+C",e.classList.add("selected"),setTimeout((()=>{e.innerHTML=t,e.classList.remove("selected")}),3e3)}handleInput(e){"referral_code"!==e.target.id&&"referral_code"!==e.target.name||(e.target.value=e.target.value.toUpperCase())}async handleCheckCode(e){e.preventDefault();const t=e.target.closest("form"),s=t.querySelector('[name="referral_code"]'),r=t.querySelector(".code-status");if(!s||!r)return;const n=s.value.trim();if(n){r.hidden=!1,r.className="code-status loading",r.innerHTML='<span class="spinner"></span> Checking...';try{const e=await this.validateCodeOnly(n);e.success?this.showCodeStatus(r,`✓ Valid! Referred by ${e.referrer_name}`,"success"):this.showCodeStatus(r,e.message||"Invalid code","error")}catch(e){console.error("Error checking code:",e),this.showCodeStatus(r,"Error checking code","error")}}else this.showCodeStatus(r,"Please enter a code","error")}showCodeStatus(e,t,s){e.hidden=!1,e.className=`code-status ${s}`,e.textContent=t,"error"===s&&setTimeout((()=>{e.hidden=!0}),5e3)}async checkForReferral(){const e=this.getUrlParameter("seeReferral"),t=this.getUrlParameter("ref");if(!e&&!t)return;if(!t)return void this.popup.openPopup();const s=this.container.querySelector('[name="referral_code"]');if(!s)return;const r=t.toUpperCase();s.value=r,s.readOnly=!0,this.popup.togglePopup();try{const e=await this.validateCodeOnly(r);if(e.success){const t=s.closest("form").querySelector(".code-status");t&&this.showCodeStatus(t,`✓ ${e.referrer_name} invited you!`,"success");const r=this.container.querySelector('[name="referral_name"]');r&&r.focus()}else s.readOnly=!1,this.showMessage("This referral link is invalid. Please enter a valid code.","error")}catch(e){console.error("Error validating code:",e),s.readOnly=!1}this.removeUrlParameter("ref")}getUrlParameter(e){return new URLSearchParams(window.location.search).get(e)}removeUrlParameter(e){const t=new URL(window.location);t.searchParams.delete(e),window.history.replaceState({},document.title,t.toString())}async validateCodeOnly(e){const t=await fetch(`${jvbSettings.api}referrals/check-code`,{method:"POST",headers:{"Content-Type":"application/json","X-WP-Nonce":jvbSettings.nonce},body:JSON.stringify({code:e})});return await t.json()}async loadStats(){if(this.container.querySelector(".stats-summary"))try{const e=await fetch(`${jvbSettings.api}referrals/my-stats?user=${jvbSettings.currentUser}`,{headers:{"X-WP-Nonce":jvbSettings.nonce}}),t=await e.json();t.success&&t.stats&&this.updateStats(t.stats)}catch(e){console.error("Error loading stats:",e)}}updateStats(e){const t={total:this.container.querySelector('[data-stat="total"]'),treated:this.container.querySelector('[data-stat="treated"]'),pending:this.container.querySelector('[data-stat="pending"]'),rewards:this.container.querySelector('[data-stat="rewards"]')};t.total&&(t.total.textContent=e.total_referrals||0),t.treated&&(t.treated.textContent=e.treated_count||0),t.pending&&(t.pending.textContent=e.pending_count||0),t.rewards&&(t.rewards.textContent="$"+parseFloat(e.available_rewards||0).toFixed(2))}async loadRecentReferrals(){const e=this.container.querySelector(".recent-referrals-list");if(e)try{const t=await fetch(`${jvbSettings.api}referrals/my-referrals?limit=5&user=${jvbSettings.currentUser}`,{headers:{"X-WP-Nonce":jvbSettings.nonce}}),s=await t.json();s.success&&s.referrals?this.renderRecentReferrals(e,s.referrals):e.innerHTML='<p class="no-referrals">No referrals yet</p>'}catch(t){console.error("Error loading referrals:",t),e.innerHTML='<p class="error">Failed to load referrals</p>'}}renderRecentReferrals(e,t){if(!t||0===t.length)return void(e.innerHTML='<p class="no-referrals">Share your code to get started!</p>');const s=t.map((e=>`\n\t\t\t<div class="referral-item">\n\t\t\t\t<div class="referral-info">\n\t\t\t\t\t<strong>${window.escapeHtml(e.referee_name)}</strong>\n\t\t\t\t\t<span class="status-badge ${e.status}">${e.status}</span>\n\t\t\t\t</div>\n\t\t\t\t<div class="referral-date">${this.formatDate(e.referred_at)}</div>\n\t\t\t</div>\n\t\t`)).join("");e.innerHTML=s}formatDate(e){const t=new Date(e),s=new Date,r=Math.abs(s-t),n=Math.floor(r/864e5);return 0===n?"Today":1===n?"Yesterday":n<7?`${n} days ago`:t.toLocaleDateString("en-US",{month:"short",day:"numeric"})}async handleFormSubmit(e){e.preventDefault();const t=e.target,s=new FormData(t);this.setFormLoading(!0,t);try{let e={success:!1,message:""};if("referral-code-form"===t.id){const t={name:s.get("referral_name"),email:s.get("referral_email"),code:s.get("referral_code")};t.name&&t.email&&t.code?e=await this.makeRequest("referrals/register",t):e.message="Please fill in all fields"}else if("login-form"===t.id){const t={type:"login",email:s.get("login_email"),context:{redirect_to:window.location.href+"?seeReferral=1"}};e=await this.makeRequest("magic",t)}e.success?this.handleSuccess(t,e):this.showFormMessage(t,e.message||"Something went wrong. Please try again.","error")}catch(e){console.error("Error submitting form:",e),this.showFormMessage(t,"Something went wrong. Please try again.","error")}finally{this.setFormLoading(!1,t)}}async makeRequest(e,t){if(!["magic","referrals/register","referrals/check-code"].includes(e))return{success:!1,message:"Invalid endpoint"};const s=await fetch(`${jvbSettings.api}${e}`,{method:"POST",headers:{"Content-Type":"application/json","X-WP-Nonce":jvbSettings.nonce},body:JSON.stringify(t)});return await s.json()}handleSuccess(e,t){e.style.display="none";const s=e.nextElementSibling;s&&s.classList.contains("success-content")&&(s.hidden=!1,s.scrollIntoView({behavior:"smooth",block:"center"})),this.dispatchEvent("emailSent",{email:t.email})}showFormMessage(e,t,s="error"){const r=e.querySelector(".status");if(!r)return;const n=r.querySelector(".message");n&&(n.textContent=t),r.hidden=!1,r.className=`status ${s}`,"error"===s&&setTimeout((()=>{r.hidden=!0}),5e3)}setFormLoading(e,t){t.querySelectorAll("input, button").forEach((t=>t.disabled=e));const s=t.querySelector(".status");if(s&&(s.classList.toggle("loading",e),e)){s.hidden=!1;const e=s.querySelector(".message");e&&(e.textContent="Sending...")}}dispatchEvent(e,t){const s=new CustomEvent("referralWidget:"+e,{detail:t,bubbles:!0});this.container.dispatchEvent(s)}}document.addEventListener("DOMContentLoaded",(()=>{window.jvbReferral=new e}))})(); |