// -------------- AUTH FORMS — multi-instance version ------------- const CLIENT_ID = "pgnfidgwuKhlfrh4jRuIirRpvteChDGnga9I4hmj"; window.dataLayer = window.dataLayer || []; // ------------------------ GLOBAL HELPERS ------------------------ // NB: DOMAIN, isMobileDevice, getCookie and setCookie are provided by the page's // inline auth script and are intentionally NOT redefined here to avoid // duplicated logic. This file relies on that inline script being loaded first. let recaptchaLoaded = false; function loadRecaptcha() { if (recaptchaLoaded) return; recaptchaLoaded = true; const script = document.createElement("script"); script.src = "https://www.google.com/recaptcha/api.js"; script.async = true; script.defer = true; document.body.appendChild(script); } // Function to validate email function isValidEmail(email) { const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailPattern.test(email); } // Function to handle form errors function handleFormError(inputWrap, errorText, message) { if (!inputWrap) return; inputWrap.classList.add("is-error"); if (!errorText) return; if (message === "Incorrect credentials") { errorText.textContent = "Invalid email address or password. Try again"; } else { errorText.textContent = message; } } // Function to clear form errors function clearFormError(inputWrap, errorText) { if (inputWrap) inputWrap.classList.remove("is-error"); if (errorText) errorText.textContent = ""; } // Function to validate form input function validateForm( email, password, emailInputWrap, emailErrorText, passwordInputWrap, passErrorText, ) { let isValid = true; if (emailInputWrap && emailErrorText) { clearFormError(emailInputWrap, emailErrorText); if (!email) { handleFormError(emailInputWrap, emailErrorText, "Email is required"); isValid = false; } else if (!isValidEmail(email)) { handleFormError(emailInputWrap, emailErrorText, "Invalid email address"); isValid = false; } } if (passwordInputWrap && passErrorText) { clearFormError(passwordInputWrap, passErrorText); if (!password) { handleFormError(passwordInputWrap, passErrorText, "Password is required"); isValid = false; } else if (password.length < 6) { handleFormError( passwordInputWrap, passErrorText, "Password must be at least 6 characters long", ); isValid = false; } } return isValid; } // show/hide loader on btn function toggleLoader(button, isLoading) { if (!button) return; button.classList.toggle("is-loading", isLoading); } // get initial user data function fetchUserData() { const accessToken = getCookie("accessToken"); return fetch(`https://app.${DOMAIN}/api/auth/user/`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}`, }, credentials: "include", }) .then((response) => response.json()) .then((data) => { if (data.error_map) { localStorage.removeItem("currentUser"); } else { localStorage.setItem("currentUser", JSON.stringify(data)); } return data; }) .catch((error) => { console.error("Error:", error); }); } // Get country params function getCountryInfoByTimezone(timezone) { for (const country of countries) { if (country.timezones.includes(timezone)) { return { country_code: country.country_code, name: country.name, }; } } return null; } // ------------------------ ANALYTICS ------------------------ function userLoginEvent(userId, method) { window.dataLayer.push({ user_id: userId, method: method, color_theme: "system", event: "user_login", }); } function userSignUpEvent(userId, method) { const currentDate = new Date(); const formattedDate = currentDate.getDate() + "." + (currentDate.getMonth() + 1) + "." + currentDate.getFullYear(); window.dataLayer.push({ userId: userId, eventCategory: "SignUp", eventAction: "Completed", registration_date: formattedDate, method: method, color_theme: "system", event: "CompleteRegistration", }); } // Active tab text within a specific form root function userMethodRegisterEvent(root, eventName) { const activeTab = root.querySelector('[data-auth="tab-link"].w--current'); const clickText = activeTab ? activeTab.textContent.trim() : ""; window.dataLayer.push({ event: eventName, click_text: clickText, type: "Auth modal", }); } // ------------------------ GLOBAL SDK INIT ------------------------ // Apple if (typeof AppleID !== "undefined") { AppleID.auth.init({ clientId: "com.epro.web", scope: "name email", redirectURI: `https://${DOMAIN}/apple-callback`, state: "init", nonce: "9b1deb4d-3b7d-4bad-9baw-2b0d7b3dcb6d", usePopup: true, }); } // Facebook window.fbAsyncInit = function () { FB.init({ appId: "1377613392528854", cookie: true, xfbml: true, version: "v14.0", }); FB.AppEvents.logPageView(); }; (function (d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) { return; } js = d.createElement(s); js.id = id; js.src = "https://connect.facebook.net/en_US/sdk.js"; fjs.parentNode.insertBefore(js, fjs); })(document, "script", "facebook-jssdk"); // Google One Tap is initialized and prompted by the page's inline script // ===================================================================== // PER-FORM INITIALIZATION // Returns a small API: { name, root, open(tabIndex) } // ===================================================================== function initAuthForm(root) { const name = root.dataset.authForm || "default"; // --- scoped selector helpers --- // NB: root itself can carry a data-auth role (e.g. the modal container is // also the [data-auth-form] root), so match the root before its descendants. const el = (role) => { const selector = `[data-auth="${role}"]`; return root.matches(selector) ? root : root.querySelector(selector); }; const els = (role) => root.querySelectorAll(`[data-auth="${role}"]`); const elIndexed = (role, index) => root.querySelector(`[data-auth="${role}"][data-index="${index}"]`); const on = (role, event, handler) => { const node = el(role); if (node) node.addEventListener(event, handler); }; const onAll = (role, event, handler) => { els(role).forEach((node) => node.addEventListener(event, handler)); }; // Toggle 'is-active' on a scoped element const toggleState = (role, add = true) => { const node = el(role); if (node) node.classList.toggle("is-active", add); }; // --- per-form state --- let loginToken = ""; let accessTokenApple; let accessTokenFb; let recaptchaResponse; let googleBtnWidth; const tabLinks = els("tab-link"); // ------------------------ STATE / RESPONSE HELPERS ------------------------ function showTwoFactorStep() { toggleState("initial-state", false); toggleState("auth-form-social", false); toggleState("code-state", true); } function showConfirmEmailStep(email) { const confirmEmail = el("confirm-email"); if (confirmEmail) confirmEmail.textContent = email; toggleState("initial-state", false); toggleState("auth-form-social", false); toggleState("confirm-state", true); } function showCodeErrorStep(codeStatus, authType) { if (codeStatus === "DEACTIVATED_USER_ERROR") { if (authType === "facebook") { toggleState("reactivate-yes", false); toggleState("reactivate-yes-fb", true); } else if (authType === "apple") { toggleState("reactivate-yes", false); toggleState("reactivate-yes-apple", true); } toggleState("reactivate-popup", true); } else if (codeStatus === "LOCKED_USER_ERROR") { toggleState("locked-popup", true); } } // Universal function to handle API response function handleApiResponse( data, emailInputWrap, passwordInputWrap, passErrorText, emailErrorText, ) { if (data.is_sms_otp_allow) { showTwoFactorStep(); loginToken = data.token; } else if (!data.error_map) { if (!data.allow_unverified_user && data.state === "unverified") { showConfirmEmailStep(data.email); } else { window.location.href = `https://app.${DOMAIN}/`; } } else { let message = ""; if (typeof data.message === "object" && data.message !== null) { message = data.message.email || ""; } else { message = data.message; } if (message[0].includes("Email")) { handleFormError(emailInputWrap, emailErrorText, message); handleFormError(passwordInputWrap, passErrorText, ""); } else if (message.includes("WriterPro")) { const modalError = el("auth-modal-error"); if (modalError) { modalError.style.display = "block"; modalError.textContent = message; setTimeout(() => { modalError.style.display = "none"; }, 5000); } } else { handleFormError(emailInputWrap, emailErrorText, ""); handleFormError(passwordInputWrap, passErrorText, message); } showCodeErrorStep(data.code, "email"); } } // ------------------------ TABS / GOOGLE BUTTON ------------------------ function renderGoogleButton(index) { if (typeof google === "undefined" || !google.accounts) return; const buttonElement = elIndexed("google-btn-render", index); const buttonWrap = elIndexed("google-btn-wrap", index); if (!buttonElement) return; googleBtnWidth = buttonWrap?.offsetWidth || googleBtnWidth; google.accounts.id.renderButton(buttonElement, { theme: "outline", size: "large", width: googleBtnWidth, click_listener: () => userMethodRegisterEvent(root, "click_google_icon"), }); } function switchTab(tabIndex) { const link = tabLinks[tabIndex]; if (link) link.click(); setTimeout(() => { renderGoogleButton(tabIndex); }, 100); } tabLinks.forEach((tabLink, index) => { tabLink.addEventListener("click", () => { renderGoogleButton(index); }); }); // Tab analytics (0 = Log in, 1 = Sign up) if (tabLinks[0]) { tabLinks[0].addEventListener("click", () => { window.dataLayer.push({ event: "click_login_tab", click_text: "Log in", type: "Auth modal", }); }); } if (tabLinks[1]) { tabLinks[1].addEventListener("click", () => { window.dataLayer.push({ event: "click_sign_up_tab", click_text: "Sign up", type: "Auth modal", }); }); } // ------------------------ APPLE ------------------------ function sendAppleRequest(token, activateValue) { fetch(`https://app.${DOMAIN}/api/social/auth/signin/apple-id/`, { method: "POST", body: JSON.stringify({ access_token: token, client_id: CLIENT_ID, role: "customer", activate: activateValue, is_premium_blog_user: true, }), headers: { "Content-Type": "application/json", }, credentials: "include", }) .then((response) => response.json()) .then((data) => { if (data.is_sms_otp_allow) { showTwoFactorStep(); loginToken = data.token; } else if (!data.error_map) { setCookie({ name: "accessToken", value: data.access_token, domain: `.${DOMAIN}`, }); setCookie({ name: "refreshToken", value: data.refresh_token, domain: `.${DOMAIN}`, }); if (data.is_new) { setCookie({ name: "new_user", value: "true", domain: `.${DOMAIN}`, }); } fetchUserData().then((userData) => { if (userData.new_user) { userSignUpEvent(userData.id, "apple-id"); } else { userLoginEvent(userData.id, "apple-id"); } if ( !userData.allow_unverified_user && userData.state === "unverified" ) { showConfirmEmailStep(userData.email); } else { window.location.href = `https://app.${DOMAIN}/`; } }); } else { showCodeErrorStep(data.code, "apple"); } }) .catch((error) => { console.error("Error during login", error); }); } function signInWithApple() { AppleID.auth .signIn() .then((response) => { accessTokenApple = response.authorization.id_token; sendAppleRequest(accessTokenApple, false); }) .catch((error) => { console.error("Sign in with Apple failed:", error); }); userMethodRegisterEvent(root, "click_apple_icon"); } onAll("apple", "click", signInWithApple); // ------------------------ FACEBOOK ------------------------ function sendFbRequest(activateValue) { fetch(`https://app.${DOMAIN}/api/social/auth/signin/facebook/`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ access_token: accessTokenFb, activate: activateValue, client_id: CLIENT_ID, is_test: false, role: "customer", site: `app.${DOMAIN}`, is_premium_blog_user: true, }), credentials: "include", }) .then((response) => response.json()) .then((data) => { if (data.is_sms_otp_allow) { showTwoFactorStep(); loginToken = data.token; } else if (!data.error_map) { setCookie({ name: "accessToken", value: data.access_token, domain: `.${DOMAIN}`, }); setCookie({ name: "refreshToken", value: data.refresh_token, domain: `.${DOMAIN}`, }); if (data.is_new) { setCookie({ name: "new_user", value: "true", domain: `.${DOMAIN}`, }); } fetchUserData().then((userData) => { if (userData.new_user) { userSignUpEvent(userData.id, "facebook"); } else { userLoginEvent(userData.id, "facebook"); } if ( !userData.allow_unverified_user && userData.state === "unverified" ) { showConfirmEmailStep(userData.email); } else { window.location.href = `https://app.${DOMAIN}/`; } }); } else { showCodeErrorStep(data.code, "facebook"); } }) .catch((error) => console.error("Error:", error)); } onAll("facebook", "click", function () { FB.login( function (response) { if (response.status === "connected") { accessTokenFb = response.authResponse.accessToken; sendFbRequest(false); } else { console.log("User cancelled login or did not fully authorize."); } }, { scope: "public_profile,email" }, ); userMethodRegisterEvent(root, "click_facebook_icon"); }); // ------------------------ TOGGLE PASSWORD ------------------------ onAll("toggle-password", "click", function () { const parent = this.closest('[data-auth="password-field"]'); if (!parent) return; const passwordInput = parent.querySelector("input"); const passwordHideIcon = parent.querySelector('[data-auth="pass-hide"]'); const passwordShowIcon = parent.querySelector('[data-auth="pass-show"]'); const isPassword = passwordInput.type === "password"; passwordInput.type = isPassword ? "text" : "password"; passwordHideIcon?.classList.toggle("hide", !isPassword); passwordShowIcon?.classList.toggle("hide", isPassword); }); // ------------------------ FORGOT PASSWORD NAV ------------------------ on("forgot-password-btn", "click", function () { toggleState("initial-state", false); toggleState("auth-form-social", false); toggleState("forgot-state", true); }); onAll("forgot-back", "click", function () { toggleState("forgot-state", false); toggleState("initial-state", true); toggleState("auth-form-social", true); toggleState("forgot-success-block", false); el("forgot-form")?.classList.remove("is-hide"); const resetTarget = el("forgot-email-target"); if (resetTarget) resetTarget.textContent = ""; const forgotEmail = el("forgot-email"); if (forgotEmail) forgotEmail.value = ""; }); // ------------------------ START EMAIL STATE ------------------------ onAll("start-email-btn", "click", () => { els("auth-email-step").forEach((step) => step.classList.remove("is-hide")); els("google-icon").forEach((btn) => btn.classList.remove("is-hide")); els("auth-start-state").forEach((state) => state.classList.add("is-hide")); userMethodRegisterEvent(root, "click_with_email_icon"); }); // Back from the email step to the initial start state (inverse of above). onAll("start-back", "click", () => { els("auth-email-step").forEach((step) => step.classList.add("is-hide")); els("google-icon").forEach((btn) => btn.classList.add("is-hide")); els("auth-start-state").forEach((state) => state.classList.remove("is-hide"), ); }); // ------------------------ REACTIVATE / LOCKED ------------------------ on("reactivate-no", "click", () => toggleState("reactivate-popup", false)); on("contact-help-btn", "click", () => { Intercom("show"); toggleState("locked-popup", false); }); on("reactivate-yes", "click", function () { const email = el("signin-email")?.value; const password = el("signin-password")?.value; const emailInputWrap = el("signin-email-wrap"); const emailErrorText = el("signin-email-error"); const passwordInputWrap = el("signin-pass-wrap"); const passErrorText = el("signin-pass-error"); fetch(`https://app.${DOMAIN}/api/auth/signin/`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ activate: true, remember_me: true, email: email, password: password, client_id: CLIENT_ID, site: `app.${DOMAIN}`, is_premium_blog_user: true, }), credentials: "include", }) .then((response) => response.json()) .then((data) => { setCookie({ name: "accessToken", value: data.access_token, domain: `.${DOMAIN}`, }); setCookie({ name: "refreshToken", value: data.refresh_token, domain: `.${DOMAIN}`, }); handleApiResponse( data, emailInputWrap, passwordInputWrap, passErrorText, emailErrorText, ); }) .catch((error) => console.error("Error:", error)); toggleState("reactivate-popup", false); }); on("reactivate-yes-google", "click", function () { const accessToken = getCookie("accessToken"); const authForm = el("auth-form"); const isPremiumUser = authForm && authForm.classList.contains("is-active"); fetch(`https://app.${DOMAIN}/api/social/auth/signin/google-oauth2/`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ activate: true, access_token: accessToken, client_id: CLIENT_ID, is_test: false, role: "customer", site: `app.${DOMAIN}`, ...(isPremiumUser && { is_premium_blog_user: true }), }), credentials: "include", }) .then((response) => response.json()) .then((data) => { if (data.is_sms_otp_allow) { showTwoFactorStep(); loginToken = data.token; } else if (!data.error_map) { setCookie({ name: "accessToken", value: data.access_token, domain: `.${DOMAIN}`, }); setCookie({ name: "refreshToken", value: data.refresh_token, domain: `.${DOMAIN}`, }); if (!data.allow_unverified_user && data.state === "unverified") { showConfirmEmailStep(data.email); } else { window.location.href = `https://app.${DOMAIN}/`; } } }) .catch((error) => console.error("Error:", error)); toggleState("reactivate-popup", false); }); on("reactivate-yes-fb", "click", function () { sendFbRequest(true); toggleState("reactivate-popup", false); }); on("reactivate-yes-apple", "click", function () { sendAppleRequest(accessTokenApple, true); toggleState("reactivate-popup", false); }); // ------------------------ LOGIN (EMAIL) ------------------------ function getLoginEmailValidationElements() { return { emailInputWrap: el("signin-email-wrap"), emailErrorText: el("signin-email-error"), email: el("signin-email")?.value ?? "", }; } function getLoginPasswordValidationElements() { return { passwordInputWrap: el("signin-pass-wrap"), passErrorText: el("signin-pass-error"), password: el("signin-password")?.value ?? "", }; } function validateLoginEmail() { const { email, emailInputWrap, emailErrorText } = getLoginEmailValidationElements(); validateForm(email, "", emailInputWrap, emailErrorText, null, null); } function validateLoginPassword() { const { password, passwordInputWrap, passErrorText } = getLoginPasswordValidationElements(); validateForm("", password, null, null, passwordInputWrap, passErrorText); } on("login-button", "click", function (event) { const currentBtn = event.currentTarget; const { email, emailInputWrap, emailErrorText } = getLoginEmailValidationElements(); const { password, passwordInputWrap, passErrorText } = getLoginPasswordValidationElements(); const isEmailValid = validateForm( email, "", emailInputWrap, emailErrorText, null, null, ); const isPasswordValid = validateForm( "", password, null, null, passwordInputWrap, passErrorText, ); if (!isEmailValid || !isPasswordValid) return; toggleLoader(currentBtn, true); fetch(`https://app.${DOMAIN}/api/auth/signin/`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ activate: null, remember_me: true, email: email, password: password, client_id: CLIENT_ID, site: `app.${DOMAIN}`, is_premium_blog_user: true, }), credentials: "include", }) .then((response) => response.json()) .then((data) => { const userId = getCookie("extra_metadata"); setCookie({ name: "accessToken", value: data.access_token, domain: `.${DOMAIN}`, }); setCookie({ name: "refreshToken", value: data.refresh_token, domain: `.${DOMAIN}`, }); localStorage.setItem("currentUser", JSON.stringify(data)); if (!data.error_map) { userLoginEvent(userId, "email"); } handleApiResponse( data, emailInputWrap, passwordInputWrap, passErrorText, emailErrorText, ); }) .catch((error) => console.error("Error:", error)) .finally(() => { toggleLoader(currentBtn, false); }); }); on("signin-email", "input", validateLoginEmail); on("signin-password", "input", validateLoginPassword); // ------------------------ SIGN UP ------------------------ function getSignEmailValidationElements() { return { emailInputWrap: el("signup-email-wrap"), emailErrorText: el("signup-email-error"), email: el("signup-email")?.value ?? "", }; } function getSignPasswordValidationElements() { return { passwordInputWrap: el("signup-pass-wrap"), passErrorText: el("signup-pass-error"), password: el("signup-password")?.value ?? "", }; } function validateSignEmail() { const { email, emailInputWrap, emailErrorText } = getSignEmailValidationElements(); validateForm(email, "", emailInputWrap, emailErrorText, null, null); } function validateSignPassword() { const { password, passwordInputWrap, passErrorText } = getSignPasswordValidationElements(); validateForm("", password, null, null, passwordInputWrap, passErrorText); } function handleSignUpSubmission() { if (!recaptchaResponse) { return; } const { email, emailInputWrap, emailErrorText } = getSignEmailValidationElements(); const { password, passwordInputWrap, passErrorText } = getSignPasswordValidationElements(); const isEmailValid = validateForm( email, "", emailInputWrap, emailErrorText, null, null, ); const isPasswordValid = validateForm( "", password, null, null, passwordInputWrap, passErrorText, ); if (!isEmailValid) { window.dataLayer.push({ event: "auth_error_email", order_error_type: emailErrorText?.innerText, }); } if (!isPasswordValid) { window.dataLayer.push({ event: "auth_error_password", order_error_type: passErrorText?.innerText, }); } if (!isEmailValid || !isPasswordValid) return; const signUpButton = el("signup-button"); toggleLoader(signUpButton, true); let responseData = {}; fetch(`https://app.${DOMAIN}/api/auth/signup/`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ email, password, role: "customer", client_id: CLIENT_ID, g_recaptcha_response: recaptchaResponse, site: `app.${DOMAIN}`, is_premium_blog_user: true, }), credentials: "include", }) .then((response) => response.json()) .then((data) => { responseData = data; setCookie({ name: "accessToken", value: data.access_token, domain: `.${DOMAIN}`, }); setCookie({ name: "refreshToken", value: data.refresh_token, domain: `.${DOMAIN}`, }); if (!data.error_map) { return fetchUserData(); } if (typeof data.message === "object" && data.message !== null) { window.dataLayer.push({ event: "auth_error_email", order_error_type: data.message.email[0] || "", }); } else { window.dataLayer.push({ event: "auth_error_password", order_error_type: data.message, }); } }) .then((userData) => { const combinedData = { ...responseData, ...userData, }; if (combinedData.new_user) { setCookie({ name: "new_user", value: "true", domain: `.${DOMAIN}` }); userSignUpEvent(combinedData.id, "email"); } else { userLoginEvent(combinedData.id, "email"); } handleApiResponse( combinedData, emailInputWrap, passwordInputWrap, passErrorText, emailErrorText, ); }) .catch((error) => console.error("Error:", error)) .finally(() => { toggleLoader(signUpButton, false); }); } // reCAPTCHA callback: the signup button declares its own global callback // name via data-recaptcha-callback="" so multiple forms don't // collide. Fallback: submit on plain click if no reCAPTCHA is wired up. const signUpButton = el("signup-button"); if (signUpButton) { // Prefer an explicit data-recaptcha-callback, but fall back to the // Webflow invisible-reCAPTCHA data-callback so existing markup works. const recaptchaCbName = signUpButton.dataset.recaptchaCallback || signUpButton.dataset.callback; if (recaptchaCbName) { window[recaptchaCbName] = (token) => { recaptchaResponse = token; handleSignUpSubmission(); }; } signUpButton.addEventListener("click", function (event) { event.preventDefault(); handleSignUpSubmission(); }); } on("signup-email", "input", validateSignEmail); on("signup-password", "input", validateSignPassword); // ------------------------ FORGOT PASSWORD SUBMIT ------------------------ function getForgotEmailValidationElements() { return { emailInputWrap: el("forgot-email-wrap"), emailErrorText: el("forgot-email-error"), email: el("forgot-email")?.value ?? "", }; } function validateForgotEmail() { const { email, emailInputWrap, emailErrorText } = getForgotEmailValidationElements(); validateForm(email, "", emailInputWrap, emailErrorText, null, null); } on("forgot-button", "click", function () { const { email, emailInputWrap, emailErrorText } = getForgotEmailValidationElements(); const isEmailValid = validateForm( email, "", emailInputWrap, emailErrorText, null, null, ); if (!isEmailValid) return; fetch( `https://app.${DOMAIN}/api/auth/forgot-password?email=${encodeURIComponent(email)}`, { method: "GET", }, ) .then((response) => response) .then((data) => { if (data.status === 200) { toggleState("forgot-success-block", true); el("forgot-form")?.classList.add("is-hide"); const resetTarget = el("forgot-email-target"); if (resetTarget) resetTarget.textContent = email; } else { handleFormError( emailInputWrap, emailErrorText, "Email not registered", ); } }) .catch((error) => console.error("Error:", error)); }); on("forgot-email", "input", validateForgotEmail); // ------------------------ OPEN / CLOSE POPUP ------------------------ function handleAuthPopupClick(tabIndex) { const countryInfo = getCountryInfoByTimezone( Intl.DateTimeFormat().resolvedOptions().timeZone, ); const allowedCountries = ["GB", "AU", "NZ", "IE", "AT"]; if (countryInfo && allowedCountries.includes(countryInfo.country_code)) { const countryName = el("country-name"); if (countryName) countryName.textContent = countryInfo.name; const countryNameS = el("country-name-s"); if (countryNameS) countryNameS.textContent = `${countryInfo.name}'s`; toggleState("country-popup", true); } switchTab(tabIndex); toggleState("auth-form", true); document.body.classList.add("popup-open"); } on("close-popup", "click", () => { toggleState("auth-form", false); document.body.classList.remove("popup-open"); window.dataLayer.push({ event: "auth_modal_click_close", click_text: "Close popup", }); }); // Close modal when clicking outside of it const authModal = el("auth-form"); if (authModal) { authModal.addEventListener("click", (event) => { if ( authModal.classList.contains("is-active") && event.target === authModal ) { toggleState("auth-form", false); document.body.classList.remove("popup-open"); window.dataLayer.push({ event: "auth_modal_click_close", click_text: "Click backdrop", }); } }); } // ------------------------ CONFIRM EMAIL ------------------------ on("back-to-signup", "click", function () { const accessToken = getCookie("accessToken"); switchTab(1); toggleState("confirm-state", false); toggleState("initial-state", true); toggleState("auth-form-social", true); fetch(`https://app.${DOMAIN}/api/auth/signout/`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}`, }, credentials: "include", }) .then((response) => response.json()) .then((data) => { if (data.status) { localStorage.removeItem("currentUser"); } }) .catch((error) => { console.error("Error:", error); }); }); on("confirm-resend-btn", "click", function () { const confirmEmail = el("confirm-email")?.textContent; const accessToken = getCookie("accessToken"); fetch(`https://app.${DOMAIN}/api/auth/verify-email/resend/`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}`, }, body: JSON.stringify({ email: confirmEmail, }), credentials: "include", }) .then((response) => response) .then((data) => { if (data.ok) { el("confirm-btn-wrap")?.classList.add("is-hide"); toggleState("confirm-done", true); } }) .catch((error) => console.error("Error:", error)); }); on("confirm-resend-again", "click", function () { el("confirm-resend-btn")?.click(); }); // ------------------------ TWO-FACTOR ------------------------ const codeInputs = els("code-input"); const twoFactorSubmitBtn = el("two-factor-button"); let code = ""; function checkInputs() { code = Array.from(codeInputs) .map((input) => input.value) .join(""); if (code.length === codeInputs.length && codeInputs.length > 0) { twoFactorSubmitBtn?.classList.remove("not-active"); twoFactorSubmitBtn?.click(); } else { twoFactorSubmitBtn?.classList.add("not-active"); } } function clearCodeInputs() { codeInputs.forEach((input) => { input.value = ""; }); code = ""; twoFactorSubmitBtn?.classList.add("not-active"); if (codeInputs.length > 0) { codeInputs[0].focus(); } } codeInputs.forEach((input, index) => { input.addEventListener("input", (e) => { let { value } = e.target; if (value.length > 1) { value = value.charAt(0); e.target.value = value; } if (value.length === 1 && index < codeInputs.length - 1) { codeInputs[index + 1].focus(); } checkInputs(); }); input.addEventListener("keydown", (e) => { if (e.key === "Backspace" && index > 0 && input.value === "") { codeInputs[index - 1].focus(); } }); input.addEventListener("paste", (e) => { e.preventDefault(); const pasteData = e.clipboardData.getData("text"); if (pasteData.length === codeInputs.length) { codeInputs.forEach((codeInput, i) => { codeInput.value = pasteData[i] || ""; }); checkInputs(); codeInputs[codeInputs.length - 1].focus(); } }); }); if (twoFactorSubmitBtn) { twoFactorSubmitBtn.addEventListener("click", function (event) { const currentBtn = event.currentTarget; const codeInputWrap = el("code-input-wrap"); const codeInputError = el("code-input-error"); if (!code) { handleFormError( codeInputWrap, codeInputError, "Verification code is required", ); return; } toggleLoader(currentBtn, true); fetch(`https://app.${DOMAIN}/api/auth/signin/two-factor/`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ otp: code, token: loginToken, client_id: CLIENT_ID, }), credentials: "include", }) .then((response) => response.json()) .then((data) => { if (!data.error_map) { setCookie({ name: "accessToken", value: data.access_token, domain: `.${DOMAIN}`, }); setCookie({ name: "refreshToken", value: data.refresh_token, domain: `.${DOMAIN}`, }); window.location.href = `https://app.${DOMAIN}/`; } else { clearCodeInputs(); handleFormError( codeInputWrap, codeInputError, data.message?.otp?.[0] || "", ); toggleState("two-factor-sms", true); } }) .catch((error) => console.error("Error:", error)) .finally(() => { toggleLoader(currentBtn, false); }); }); } on("two-factor-sms", "click", function () { fetch(`https://app.${DOMAIN}/api/auth/signin/two-factor/sms/`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ token: loginToken, client_id: CLIENT_ID, }), credentials: "include", }) .then((response) => response.json()) .then((data) => { if (!data.error_map) { console.log("SMS resent successfully"); } else { console.error("Error resending SMS:", data.error_map); } }) .catch((error) => console.error("Error:", error)); }); // ------------------------ COUNTRY POPUP ------------------------ on("country-close", "click", function () { toggleState("country-popup", false); }); on("country-close-all", "click", function () { toggleState("country-popup", false); toggleState("auth-form", false); document.body.classList.remove("popup-open"); }); // ---------------------------- FORM ----------------------------- // If already signed in but unverified — show confirm state for this form if (getCookie("accessToken")) { fetchUserData().then(() => { const storedData = localStorage.getItem("currentUser"); if (storedData) { const user = JSON.parse(storedData); if (user.state === "unverified") { toggleState("auth-form", true); toggleState("initial-state", false); toggleState("auth-form-social", false); toggleState("confirm-state", true); const confirmEmail = el("confirm-email"); if (confirmEmail) confirmEmail.textContent = user.email; } } }); } return { name, root, open: handleAuthPopupClick, }; } // ---------------------------- CREATE ORDER ----------------------------- let orderParams = {}; async function sendOrder(data) { if (Object.keys(data).length < 1) return false; const orderId = crypto.randomUUID(); const orderData = { front_id: orderId, ...data }; try { const response = await fetch( `https://app.${DOMAIN}/api/order/order-form/`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(orderData), }, ); if (!response.ok) { const errorText = await response.text(); throw new Error(`HTTP ${response.status}: ${errorText}`); } const encodedCookie = encodeURIComponent( JSON.stringify({ context: "order-form", payload: { front_id: orderId }, }), ); document.cookie = `landing_context=${encodedCookie}; domain=.${DOMAIN}; path=/;`; return true; } catch (error) { console.error("Error", error.message); return false; } }