function Price(data){ var self = this; self.data = data; var mapping = { } ko.mapping.fromJS(data, mapping, self); }function Product(data){ var self = this; self.data = data; self.selectedPrice = ko.observable(); var mapping = { 'prices': { create: function(options) { return ko.observable(new Price(options.data)); } } } ko.mapping.fromJS(data, mapping, self); } function User(data, cart){ var self = this; self.data = data; self.hasCode = ko.observable(false); var mapping = { 'promoCode': { create: function(options) { return ko.observable(new PromoCode(options.data)); } }, 'cart': { create: function(options) { return cart } }, 'include':['contactPassword'] } self.preApproved = ko.observable(false); ko.mapping.fromJS(data, mapping, self); // self.checker = ko.computed(function(){ // console.log('Cart Update') // }) // self.check=ko.computed(function(){ // if(self.promoCode().code()){ // self.cart().promoCode(self.promoCode()) // self.hasCode(true); // } // else{ // self.hasCode(false); // } // }).extend({ deferred: true }); self.update = function(data){ ko.mapping.fromJS(JSON.parse(data), self); } self.selectedSubscription = ko.observable(false); }function PromoCode(data){ var self = this; var mapping = { } ko.mapping.fromJS(data, mapping, self); }function Option(data){ var self = this; var mapping = { } ko.mapping.fromJS(data, mapping, self); }function Cart(data) { var self = this; var mapping = { 'promoCode': { create: function(options) { return ko.observable(new PromoCode(options.data)); } }, } ko.mapping.fromJS(data, mapping, self); // self.check = ko.computed(function(){ // console.log(self.totalDiscount()); // }) self.update = function(data){ ko.mapping.fromJS(JSON.parse(data), self); } self.sendIT; self.sendDataCheck = ko.observable(); self.checkPromoCode = ko.computed(function(){ // sendUser = ko.mapping.toJS(user); async function sendData() { const response = await fetch('/_/lgc/check_code', { method: 'POST', body: JSON.stringify(ko.mapping.toJS(self.promoCode().code)) }); const responseData = await response.text(); responseSuccess = JSON.parse(responseData); if(responseSuccess.cart){ ko.mapping.fromJS(responseSuccess.cart, self); } } if(self.promoCodeCode() != self.promoCode().code()) { clearTimeout(self.sendIT); self.sendIT=setTimeout(function (){ console.log('SEND IT') sendData(); }, 1000); } }).extend({ deferred: true }); }function Question(data, user, cart){ var self = this; self.cart = cart; self.element= ko.observable(); self.error = ko.observable(); var mapping = { 'QuestionOption': { create: function(options) { return ko.observable(new Option(options.data)); } }, 'include': ["user"] } ko.mapping.fromJS(data, mapping, self); if(self.type()=='password'){ self.verifyPassword = ko.observable(); } self.user = user; if(self.type() == 'code'){ if(preSetCode!=""){ self.answer(preSetCode); self.user().code(preSetCode) self.cart().code(preSetCode) } else { self.answer(self.user().promoCode().code()); } } self.showCheck = ko.observable(false); // if(data.ajaxURL=='/_/lgc/checkcode'){ // self.answer(self.user().code()); // } self.validUrl="^(http|https)://[a-zA-Z0-9-\.]+\.[a-zA-Z]{2,5}(/[a-zA-Z0-9-._~:/?#[\]@!$&'()*+,;=]*)?$"; self.validPhone="^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$"; self.setElement=function(element){ self.element(element) }; self.valid = ko.observable(true); self.checkValidation = function(){ self.valid(true); if(self.element()){ self.element().setCustomValidity(''); if(!self.required()){ self.element().setCustomValidity(''); self.element().reportValidity(); return } if(self.type() =='select'){ if(self.answer()==''){ self.valid(false); self.element().setCustomValidity('Select an option'); self.element().reportValidity(); } else if(self.answer()==undefined){ self.valid(false); self.element().setCustomValidity('Select an option'); self.element().reportValidity(); } else if(self.answer()==null){ self.valid(false); self.element().setCustomValidity('Select an option'); self.element().reportValidity(); } return } if(self.type()=='password'){ if(self.answer() != self.verifyPassword()){ self.valid(false); e = document.getElementById('e_passwordConfirm'); e.setCustomValidity('Your passwords do not match.'); e.reportValidity(); } if(self.answer()==''){ self.valid(false); self.element().setCustomValidity('Please add a password.'); self.element().reportValidity(); } else if(self.answer()==undefined){ self.valid(false); self.element().setCustomValidity('Please add a password.'); self.element().reportValidity(); } else if(self.answer()==null){ self.valid(false); self.element().setCustomValidity('Please add a password.'); self.element().reportValidity(); } } } if(self.type()=='subscription'){ self.valid((user().selectedSubscription()==false?false:true)); if(!self.valid()) { self.error('Please select a subscription'); setTimeout(function(){ self.error('')}, 2000); } } } self.checkAnswer=ko.computed(function(){ if(self.validatorType()=='url'){ } }); self.pass=ko.computed(function(){ return self.answer == self.validator; }); } function Group(data, user, cart){ var self = this; var mapping = { 'questions': { create: function(options) { return ko.observable(new Question(options.data, user, cart)); } } } ko.mapping.fromJS(data, mapping, self); } function Step(data, currentStepCount, user, stepBack, cart){ var self = this; self.cart = cart; self.stepBack = stepBack; self.currentStepCount=currentStepCount; self.user = user; var mapping = { // 'questions': { // create: function(options) { // return ko.observable(new Question(options.data, user)); // } // }, 'groups': { create: function(options) { Object.keys(options.data)[0]; return ko.observable(new Group(options.data, user, cart)); } } } ko.mapping.fromJS(data, mapping, self); self.check=ko.computed(function(){ }); self.checkValidation = ko.computed(function(){ if(self.saveTo()=='user'){ ko.utils.arrayForEach(self.groups(), function(group) { ko.utils.arrayForEach(group().questions(), function(question) { if(self.user()[question().updateField()]){ self.user()[question().updateField()](question().answer()); } }) }); } if(self.saveTo()=='referrals'){ if(self.user().hasCode()){ if(self.currentStepCount() == self.step()){ if(self.stepBack()){ self.prevStep(); } else { self.nextStep(); } } } } if(user().id()){ if(self.saveTo()=='referrals'){ if(self.user().referrals){ i=0; ko.utils.arrayForEach(self.user().referrals(), function(referral) { if(self.groups()[i]){ ko.utils.arrayForEach(self.groups()[i]().questions(), function(question) { if(question().updateField()=='categoryID') { question().answer(referral.connect_contact_category_id()); } if(question().updateField()=='contactFirstName') { question().answer(referral.name()); } if(question().updateField()=='contactInstagram') { question().answer(referral.instagramHandle()); } }) } i++; }); } } } }, self); if(self.saveTo()=='user'){ if(user().data.id){ ko.utils.arrayForEach(self.groups(), function(group) { ko.utils.arrayForEach(group().questions(), function(question) { if(self.user()[question().updateField()]){ question().answer(user().data[question().updateField()]); } }) }); } } if(self.saveTo()=='referrals'){ var i=0; if(user().data.id){ ko.utils.arrayForEach(self.groups(), function(group) { ko.utils.arrayForEach(group().questions(), function(question) { if(self.user().referrals()[i]){ if(question().updateField()=='categoryID'){ question().answer(self.user().referrals()[i].connect_contact_category_id()); question().answerID(self.user().referrals()[i].id()); } if(question().updateField()=='contactFirstName'){ question().answer(self.user().referrals()[i].name()); question().answerID(self.user().referrals()[i].id()); } if(question().updateField()=='contactInstagram'){ question().answer(self.user().referrals()[i].instagramHandle()); question().answerID(self.user().referrals()[i].id()); } if(question().updateField()=='contactTikTok'){ question().answer(self.user().referrals()[i].tikTik()); question().answerID(self.user().referrals()[i].id()); } if(question().updateField()=='contactLinkedIn'){ question().answer(self.user().referrals()[i].linkedIn()); question().answerID(self.user().referrals()[i].id()); } } }) i++ }); } } self.errorMessage = ko.observable(); self.remoteSaved = ko.observable(); self.remoteSuccess = ko.observable(); self.saveData =function(postData){ const data = async function sendData() { const response = await fetch(self.ajaxURL(), { method: 'POST', body: JSON.stringify({ "data": postData, "currentStep":currentStepCount() }) }); const responseData = await response.json(); // console.log(responseData); if(responseData.success){ if(responseData.user){ self.user().update(JSON.stringify(responseData.user)); } if(responseData.cart){ self.cart().update(JSON.stringify(responseData.cart)); } } else { self.errorMessage(responseData.message) } if(responseData.referrals){ ko.utils.arrayForEach(responseData.referrals, function(referral) { ko.utils.arrayForEach(self.groups(), function(group) { ko.utils.arrayForEach(group().questions(), function(question) { if(question().updateField()=='categoryID'){ question().answer(referral.connect_contact_category_id); } if(question().updateField()=='contactFirstName'){ question().answer(referral.name); } if(question().updateField()=='contactInstagram'){ question().answer(referral.instagramHandle); } if(question().updateField()=='contactTikTok'){ question().answer(referral.tikTik); } if(question().updateField()=='contactLinkedIn'){ question().answer(referral.linkedIn); } question().answerID(referral.id); }) }) }); } self.remoteSuccess(responseData.success); self.remoteSaved(true); return responseData.success; } return data(); } // self.savePayment = function() { // postData = ko.mapping.toJS(self.user); // const data = async function sendData() { // const response = await fetch(self.ajaxURL(), { // method: 'POST', // body: JSON.stringify(postData) // }); // const responseData = await response.json(); // if(responseData.success){ // self.user().update(responseData.user); // } // else { // self.errorMessage(responseData.message) // } // self.remoteSuccess(responseData.success); // self.remoteSaved(true); // return responseData.success; // } // return data(); // } // self.saveReferrals = function() { // postData = ko.mapping.toJS(self.groups); // const data = async function sendData() { // const response = await fetch(self.ajaxURL(), { // method: 'POST', // body: JSON.stringify({ "data": postData, "currentStep":currentStepCount() }) // }); // const responseData = await response.json(); // ko.utils.arrayForEach(responseData.referrals, function(referral) { // ko.utils.arrayForEach(self.groups(), function(group) { // ko.utils.arrayForEach(group().questions(), function(question) { // if(question().updateField()=='categoryID'){ // question().answer(referral.connect_contact_category_id); // } // if(question().updateField()=='contactFirstName'){ // question().answer(referral.name); // } // if(question().updateField()=='contactInstagram'){ // question().answer(referral.instagramHandle); // } // if(question().updateField()=='contactTikTok'){ // question().answer(referral.tikTik); // } // if(question().updateField()=='contactLinkedIn'){ // question().answer(referral.linkedIn); // } // question().answerID(referral.id); // }) // }) // }); // if(responseData.success){ // self.user().update(responseData.user); // } // else { // self.errorMessage(responseData.message) // } // self.remoteSuccess(responseData.success); // self.remoteSaved(true); // return responseData.success; // } // return data(); // } // self.savePreAuth = function() { // postData = ko.mapping.toJS(self.groups); // const data = async function sendData() { // const response = await fetch(self.ajaxURL(), { // method: 'POST', // body: JSON.stringify({"data":postData, "currentStep":currentStepCount()}) // }); // const responseData = await response.json(); // if(responseData.success){ // self.user().update(responseData.user); // } // else { // self.errorMessage(responseData.message) // } // self.remoteSuccess(responseData.success); // self.remoteSaved(true); // return responseData.success; // } // return data(); // } self.saveStep=function(){ self.errorMessage(undefined); self.remoteSuccess(undefined); self.remoteSaved(false); if(self.saveTo()=='user'){ postData = ko.mapping.toJS(self.user); } if(self.saveTo()=='referrals'){ postData = ko.mapping.toJS(self.groups); } if(self.saveTo()=='promo'){ postData = ko.mapping.toJS(self.groups); } if(self.saveTo()=='subscription'){ postData = ko.mapping.toJS(self.cart); } if(self.saveTo()=='payment'){ postData = ko.mapping.toJS(self.user); } const getData = async () => { const data = await self.saveData(postData); return data } return getData; } self.continue = ko.observable(true) self.setVerified = ko.computed(function(){ if(currentStepCount()>=self.step()){ self.canClick(true); } }) self.nextStep = function(){ self.stepBack(false); self.continue(true); ko.utils.arrayForEach(self.groups(), function(group) { ko.utils.arrayForEach(group().questions(), function(question) { question().checkValidation(); if(!question().valid()){ self.continue(false); } }) }); async function checkNextStep() { const response = await self.saveStep()(); if(response){ self.canClick(true); currentStepCount(parseInt(currentStepCount())+1); } else { alert(self.errorMessage()); } } if(self.continue()){ checkNextStep(); gsap.to(window, {duration: 1, scrollTo: 0}); } } self.prevStep = function(){ self.stepBack(true); if(currentStepCount()==self.step()){ if(currentStepCount()-1<0){ currentStepCount(0); } else { currentStepCount(currentStepCount()-1); } } gsap.to(window, {duration: 1, scrollTo: 0}); } } async function getPrices() { prices = await fetch("/_/lgc/getprices", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ }), }).then((r) => r.json()); if(prices.data){ return prices.data; } return ; } function Onboarding(data) { var self = this; self.currentStepCount = ko.observable(); self.loadNow=ko.observable(false); self.stepBack = ko.observable(false); self.selectedPrice = ko.observable(); self.selectedSubscriptionType = ko.observable(); self.selectedProductType = ko.observable(); self.selectedAddonType = ko.observable(); self.showYearlyPricing = ko.observable(preSelectDuration); self.showPricing = ko.computed(function(){ return (self.showYearlyPricing()?'year':'month'); }); self.changePricing = function(){ self.showYearlyPricing(!self.showYearlyPricing()); return true; } var mapping = { 'cart': { create: function(options) { return ko.observable(new Cart(options.data)); }, key: function(data) { return ko.utils.unwrapObservable(data.id); } }, 'user': { create: function(options) { return ko.observable(new User(options.data, self.cart)); }, key: function(data) { return ko.utils.unwrapObservable(data.id); } }, 'steps': { create: function(options) { return new Step(options.data, self.currentStepCount, self.user, self.stepBack, self.cart); } }, 'products': { create: function(options) { return new Product(options.data); } }, 'subscriptions': { create: function(options) { return new Product(options.data); } }, 'addons': { create: function(options) { return new Product(options.data); } }, } ko.mapping.fromJS(data, mapping, self); self.currentStepCount(currentStepCount); // self.nextStep = function(){ // self.currentStepCount(self.currentStepCount()+1) // } self.prevStep = function(){ self.currentStepCount(parseInt(self.currentStepCount())-1) } self.setcurrentStepNumber = function(step){ self.currentStepCount(step.step()); } self.currentStep = ko.computed(function() { return ko.utils.arrayFilter(self.steps(), function(step) { return step.step() == self.currentStepCount(); }); }, self); self.setupCard = function(){ setupCard(); document.querySelector("#submitPayment").disabled = false; } form = document.getElementById("contact-form"); form.addEventListener('keydown', (event) => { if (event.key === 'Enter') { if(self.currentStepCount()!=(self.steps().length-1)){ self.currentStep()[0].nextStep(); } return true; } }); self.loadForm = ko.computed(function(){ if(self.user().stripe_customer_id()){ } }) self.selectPrice = function(data){ self.selectedPrice(data); self.user().selectedSubscription(data); self.cart().subscriptions([]); self.user().cart().subscriptions([]); self.cart().subscriptions().push(self.selectedPrice()); if(data.unit_amount()==0){ document.querySelector("#submitPayment").disabled = false; } // $("#nextButton").animate({ scrollTop: elementOffset }, 200); gsap.to(window, { duration: 1, scrollTo: {y:"footer", offsetY: 500} }); } ko.utils.arrayForEach(self.products(), function(product) { ko.utils.arrayForEach(product.prices(), function(price) { if(price().handle()==preSelectPrice){ self.selectPrice(price()) } }); }); ko.utils.arrayForEach(self.subscriptions(), function(product) { ko.utils.arrayForEach(product.prices(), function(price) { if(price().handle()==preSelectPrice){ self.selectPrice(price()) } }); }); // SET PRESELECTIONS self.selectedSubscriptionType = ko.observable(); self.selectedProductType = ko.observable(); self.selectedAddonType = ko.observable(); self.setType = function(p) { if(p.subscription() && !p.addon()){ self.selectedSubscriptionType(p) } else if(p.addon()){ self.selectedAddonType(p) } else { self.selectedProductType(p) } } //SUBSCRIPTIONS if(self.subscriptions().length>0){ self.selectedSubscriptionType(self.subscriptions()[0]); } ko.utils.arrayForEach(self.subscriptions(), function(subscription) { if(subscription.defaultSelect()){ self.selectedSubscriptionType(subscription); } }); // PRODUCT if(self.products().length>0){ self.selectedProductType(self.product()[0]); } ko.utils.arrayForEach(self.products(), function(product) { if(product.defaultSelect()){ self.selectedProductType(product); } }); if(self.addons().length>0){ self.selectedAddonType(self.addons()[0]); } ko.utils.arrayForEach(self.addons(), function(addon) { if(addon.defaultSelect()){ self.selectedAaddonType(addon); } }); let elements; function setupCard(){ document .querySelector("#submitPayment") .addEventListener("click", handleSubmit); async function initialize() { const { clientSecret } = await fetch("/_/lgc/stripecreate", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ }), }).then((r) => r.json()); elements = stripe.elements({ clientSecret } ); const paymentElementOptions = { style: { base: { fontSmoothing: 'antialiased', }, invalid: { iconColor: '#f7541b', color: '#f7541b', }, }, }; const cardElement = elements.create('card', paymentElementOptions); cardElement.mount("#payment-element"); } async function handleSubmit(e) { console.log('setup'); e.preventDefault(); setLoading(true); const error = await stripe .createPaymentMethod({ elements, params: { billing_details: { }, }, }) .then(function(result) { if(result.error){ console.log(result.error); showMessage(result.error.message); setLoading(false); } else { async function saveCard() { setLoading(true); result.price = ko.mapping.toJS(self.selectedPrice); const response = await fetch('/_/lgc/checkout', { method: 'POST', body: JSON.stringify(result) }); const responseData = await response.text(); data = JSON.parse(responseData) console.log(data); if(data.success){ window.location.replace(data.redirect); setLoading(false); } else { setLoading(false); showMessage(data.message); } } saveCard() } }); if (error) { showMessage(error.message); console.log(error.message); setLoading(false); } } // Fetches the payment intent status after payment submission async function checkStatus() { const clientSecret = new URLSearchParams(window.location.search).get( "payment_intent_client_secret" ); if (!clientSecret) { return; } const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret); switch (paymentIntent.status) { case "succeeded": showMessage("Payment succeeded!"); break; case "processing": showMessage("Your payment is processing."); break; case "requires_payment_method": showMessage("Your payment was not successful, please try again."); break; default: showMessage("Something went wrong."); break; } } // ------- UI helpers ------- function showMessage(messageText) { const messageContainer = document.querySelector("#payment-message"); messageContainer.classList.remove("hidden"); messageContainer.textContent = messageText; setTimeout(function () { messageContainer.classList.add("hidden"); messageContainer.textContent = ""; }, 4000); } // Show a spinner on payment submission function setLoading(isLoading) { if (isLoading) { // Disable the button and show a spinner document.querySelector("#submitPayment").disabled = true; document.querySelector("#spinner").classList.remove("hidden"); document.querySelector("#button-text").classList.add("hidden"); } else { document.querySelector("#submitPayment").disabled = false; document.querySelector("#spinner").classList.add("hidden"); document.querySelector("#button-text").classList.remove("hidden"); } } initialize(); checkStatus(); }// END SET UP CARD } // Activates knockout.js var tl = gsap.timeline(); ko.bindingHandlers.fadeVisible = { init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContent){ var value = valueAccessor(); if(ko.unwrap(value)){ gsap.to(element, { y:0, opacity:0, display:'flex'}); } else { gsap.to(element, { y:0, opacity:0, display:'none'}); } }, update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContent) { var value = valueAccessor(); if(ko.unwrap(value)){ tl.clear(true); if(viewModel.stepBack()){ tl.to('.steps', {opacity:0, y:-300, duration: 1, display:'none' }); tl.fromTo(element,{opacity:1, y:300}, { opacity: 1, y:0, duration: 1, display:'flex' }); } else { tl.to('.steps', {opacity:0, y:300, duration: 1, display:'none' }); tl.fromTo(element, {opacity:1, y:-300}, {opacity: 1, y:0, duration: 1, display:'flex' }); } // tl.to(window, {scrollTo:0, duration:1}, "<"); } } }; async function getOnbarding() { const response = await fetch('/_/lgc/getonboarding', { method: 'POST', body: {}, }); const responseData = await response.text(); ko.applyBindings(new Onboarding(JSON.parse(responseData))); } getOnbarding()