Files
BagExchange/static/js/i18n.js
2026-02-15 17:09:19 +01:00

573 lines
26 KiB
JavaScript

(function () {
var supported = ["en", "it", "fr", "de", "es"];
var fallback = "en";
var aliases = {
"en-us": "en",
"de-ch": "de",
"fr-ch": "fr"
};
var translations = {
en: {
pageTitle: "Bag Exchange | Swap bags and handbags",
languageLabel: "Language",
badge: "community beta",
heroTitle: "Give your bags a new life.",
heroDesc: "Swap bags and handbags in a simple, safe, and sustainable way. Upload your item, find real matches, and refresh your style without buying new every time.",
ctaPrimary: "Start swapping",
ctaLogin: "Login",
ctaLogout: "Logout",
ctaSecondary: "See how it works",
ctaRegister: "Create account",
howTitle: "How it works in 3 steps",
step1: "1. List your bag with photos and condition",
step2: "2. Receive offers from people with similar taste",
step3: "3. Confirm the swap through chat and tracked shipping",
card1Title: "Verified profiles only",
card1Desc: "We reduce risk with account verification, feedback, and transparent swap history.",
card2Title: "Save and add value",
card2Desc: "A smart way to renew your wardrobe while avoiding waste and unnecessary spending.",
card3Title: "Circular style",
card3Desc: "From daily bags to elegant clutches: every piece can find a new owner.",
communityTitle: "Videochat and grow your profile",
communityDesc: "You can videochat with people interested in your items or simply exchange opinions and advice. You can aspire to become a fashion bag influencer.",
footer: "© 2026 Bag Exchange · Bag and handbag exchange between individuals",
modalTitle: "How to prepare your exchange",
modalStep1: "Create a photo gallery of your bag.",
modalStep2: "Describe the product.",
modalStep3: "Add your exchange conditions.",
subscribeTitle: "We are building Bag Exchange.",
subscribeDesc: "Enter your email to stay updated.",
subscribePlaceholder: "Your email",
subscribeCta: "Keep me updated",
subscribeThanks: "Thank you. We will keep you updated.",
subscribeInvalidEmail: "Please enter a valid email address.",
subscribeError: "Something went wrong. Please try again.",
registerTitle: "Create your account",
registerDesc: "Register to start exchanging bags and join the community.",
registerEmailPlaceholder: "Your email",
registerPasswordPlaceholder: "Password",
registerConfirmPlaceholder: "Confirm password",
registerCta: "Create account",
registerThanks: "Registration completed. You can now log in when the auth area is live.",
registerInvalidEmail: "Please enter a valid email address.",
registerPasswordMismatch: "Passwords do not match.",
registerWeakPassword: "Use at least 8 characters with letters and numbers.",
registerEmailExists: "This email is already registered.",
registerError: "Unable to complete registration. Please try again.",
loginTitle: "Access your account",
loginDesc: "Log in to continue your exchange journey.",
loginEmailPlaceholder: "Your email",
loginPasswordPlaceholder: "Password",
loginCta: "Log in",
loginForgotLink: "Forgot your password?",
loginSuccess: "Login successful.",
loginInvalid: "Invalid email or password.",
loginNotVerified: "Email not verified. Check your inbox for the verification link.",
loginError: "Unable to log in. Please try again.",
authStatusGuest: "Not logged in.",
authStatusUserPrefix: "Logged in as:"
},
it: {
pageTitle: "Bag Exchange | Scambia borse e borsette",
languageLabel: "Lingua",
badge: "community beta",
heroTitle: "Dai nuova vita alle tue borse.",
heroDesc: "Scambia borse e borsette in modo semplice, sicuro e sostenibile. Carica il tuo articolo, trova match reali e rinnova il tuo stile senza comprare ogni volta da zero.",
ctaPrimary: "Inizia a scambiare",
ctaLogin: "Login",
ctaLogout: "Logout",
ctaSecondary: "Guarda come funziona",
ctaRegister: "Crea account",
howTitle: "Come funziona in 3 step",
step1: "1. Pubblica la tua borsa con foto e condizioni",
step2: "2. Ricevi proposte da persone con gusti simili",
step3: "3. Conferma lo scambio con chat e spedizione tracciata",
card1Title: "Solo profili verificati",
card1Desc: "Riduciamo i rischi grazie a verifica account, feedback e storico scambi trasparente.",
card2Title: "Risparmia e valorizza",
card2Desc: "Un modo intelligente per rinnovare il guardaroba evitando sprechi e spese inutili.",
card3Title: "Stile circolare",
card3Desc: "Dalle borse da giorno alle pochette eleganti: ogni pezzo trova una nuova proprietaria.",
communityTitle: "Videochat e crescita del tuo profilo",
communityDesc: "Hai la possibilita di videochattare con gli interessati ai tuoi prodotti o semplicemente per scambiarsi opinioni e consigli. Puoi aspirare a diventare una fashion bag influencer.",
footer: "© 2026 Bag Exchange · Scambio borse e borsette tra privati",
modalTitle: "Come preparare il tuo scambio",
modalStep1: "Crea una galleria di foto della tua borsa.",
modalStep2: "Descrivi il prodotto.",
modalStep3: "Inserisci le condizioni di scambio.",
subscribeTitle: "Stiamo sviluppando Bag Exchange.",
subscribeDesc: "Inserisci la tua email per rimanere aggiornato.",
subscribePlaceholder: "La tua email",
subscribeCta: "Tienimi aggiornato",
subscribeThanks: "Grazie. Ti terremo aggiornato.",
subscribeInvalidEmail: "Inserisci un indirizzo email valido.",
subscribeError: "Si e verificato un errore. Riprova.",
registerTitle: "Crea il tuo account",
registerDesc: "Registrati per iniziare a scambiare borse ed entrare nella community.",
registerEmailPlaceholder: "La tua email",
registerPasswordPlaceholder: "Password",
registerConfirmPlaceholder: "Conferma password",
registerCta: "Crea account",
registerThanks: "Registrazione completata. Potrai fare login quando l'area auth sara disponibile.",
registerInvalidEmail: "Inserisci un indirizzo email valido.",
registerPasswordMismatch: "Le password non coincidono.",
registerWeakPassword: "Usa almeno 8 caratteri con lettere e numeri.",
registerEmailExists: "Questa email e gia registrata.",
registerError: "Impossibile completare la registrazione. Riprova.",
loginTitle: "Accedi al tuo account",
loginDesc: "Effettua il login per continuare il tuo percorso di scambio.",
loginEmailPlaceholder: "La tua email",
loginPasswordPlaceholder: "Password",
loginCta: "Accedi",
loginForgotLink: "Hai dimenticato la password?",
loginSuccess: "Login effettuato con successo.",
loginInvalid: "Email o password non validi.",
loginNotVerified: "Email non verificata. Controlla la tua casella per il link di verifica.",
loginError: "Impossibile effettuare il login. Riprova.",
authStatusGuest: "Non autenticato.",
authStatusUserPrefix: "Connesso come:"
},
fr: {
pageTitle: "Bag Exchange | Echange de sacs et pochettes",
languageLabel: "Langue",
badge: "communaute beta",
heroTitle: "Donnez une nouvelle vie a vos sacs.",
heroDesc: "Echangez sacs et pochettes de facon simple, sure et durable. Publiez votre article, trouvez de vrais matchs et renouvelez votre style sans acheter neuf a chaque fois.",
ctaPrimary: "Commencer l'echange",
ctaLogin: "Connexion",
ctaLogout: "Deconnexion",
ctaSecondary: "Voir comment ca marche",
ctaRegister: "Creer un compte",
howTitle: "Comment ca marche en 3 etapes",
step1: "1. Publiez votre sac avec photos et etat",
step2: "2. Recevez des propositions de personnes au style proche",
step3: "3. Confirmez l'echange via chat et livraison suivie",
card1Title: "Profils verifies uniquement",
card1Desc: "Nous reduisons les risques avec verification des comptes, avis et historique d'echange transparent.",
card2Title: "Economisez et valorisez",
card2Desc: "Une facon intelligente de renouveler votre dressing en evitant le gaspillage et les depenses inutiles.",
card3Title: "Style circulaire",
card3Desc: "Du sac quotidien a la pochette elegante: chaque piece peut trouver une nouvelle proprietaire.",
communityTitle: "Videochat et visibilite mode",
communityDesc: "Vous pouvez faire une videochat avec les personnes interessees par vos articles ou simplement echanger des avis et des conseils. Vous pouvez aspirer a devenir une influenceuse mode des sacs.",
footer: "© 2026 Bag Exchange · Echange de sacs et pochettes entre particuliers",
modalTitle: "Comment preparer votre echange",
modalStep1: "Creez une galerie photo de votre sac.",
modalStep2: "Decrivez le produit.",
modalStep3: "Ajoutez vos conditions d'echange.",
subscribeTitle: "Nous developpons Bag Exchange.",
subscribeDesc: "Entrez votre email pour rester informe.",
subscribePlaceholder: "Votre email",
subscribeCta: "Me tenir informe",
subscribeThanks: "Merci. Nous vous tiendrons informe.",
subscribeInvalidEmail: "Veuillez entrer une adresse email valide.",
subscribeError: "Une erreur est survenue. Veuillez reessayer.",
registerTitle: "Creez votre compte",
registerDesc: "Inscrivez-vous pour commencer les echanges et rejoindre la communaute.",
registerEmailPlaceholder: "Votre email",
registerPasswordPlaceholder: "Mot de passe",
registerConfirmPlaceholder: "Confirmer le mot de passe",
registerCta: "Creer un compte",
registerThanks: "Inscription terminee. Vous pourrez vous connecter quand l'espace auth sera disponible.",
registerInvalidEmail: "Veuillez entrer une adresse email valide.",
registerPasswordMismatch: "Les mots de passe ne correspondent pas.",
registerWeakPassword: "Utilisez au moins 8 caracteres avec lettres et chiffres.",
registerEmailExists: "Cet email est deja enregistre.",
registerError: "Impossible de finaliser l'inscription. Veuillez reessayer.",
loginTitle: "Accedez a votre compte",
loginDesc: "Connectez-vous pour poursuivre votre parcours d'echange.",
loginEmailPlaceholder: "Votre email",
loginPasswordPlaceholder: "Mot de passe",
loginCta: "Connexion",
loginForgotLink: "Mot de passe oublie ?",
loginSuccess: "Connexion reussie.",
loginInvalid: "Email ou mot de passe invalide.",
loginNotVerified: "Email non verifiee. Verifiez votre boite de reception pour le lien de verification.",
loginError: "Impossible de se connecter. Veuillez reessayer.",
authStatusGuest: "Non connecte.",
authStatusUserPrefix: "Connecte en tant que :"
},
de: {
pageTitle: "Bag Exchange | Tausche Taschen und Handtaschen",
languageLabel: "Sprache",
badge: "community beta",
heroTitle: "Gib deinen Taschen ein neues Leben.",
heroDesc: "Tausche Taschen und Handtaschen einfach, sicher und nachhaltig. Lade dein Teil hoch, finde echte Matches und erneuere deinen Stil ohne standig neu zu kaufen.",
ctaPrimary: "Jetzt tauschen",
ctaLogin: "Login",
ctaLogout: "Logout",
ctaSecondary: "So funktioniert es",
ctaRegister: "Konto erstellen",
howTitle: "So funktioniert es in 3 Schritten",
step1: "1. Stelle deine Tasche mit Fotos und Zustand ein",
step2: "2. Erhalte Angebote von Menschen mit ahnlichem Geschmack",
step3: "3. Bestatige den Tausch per Chat und Sendungsverfolgung",
card1Title: "Nur verifizierte Profile",
card1Desc: "Wir reduzieren Risiken durch Kontoverifizierung, Bewertungen und transparente Tauschhistorie.",
card2Title: "Spare und schaffe Wert",
card2Desc: "Eine smarte Art, deine Garderobe zu erneuern und gleichzeitig Verschwendung und unnotige Ausgaben zu vermeiden.",
card3Title: "Kreislauf-Stil",
card3Desc: "Von Alltagstaschen bis zur eleganten Clutch: Jedes Stuck kann eine neue Besitzerin finden.",
communityTitle: "Videochat und Profilaufbau",
communityDesc: "Du kannst per Videochat mit Interessierten an deinen Produkten sprechen oder einfach Meinungen und Tipps austauschen. Du kannst darauf hinarbeiten, Fashion-Bag-Influencerin zu werden.",
footer: "© 2026 Bag Exchange · Taschen- und Handtaschentausch zwischen Privatpersonen",
modalTitle: "So bereitest du deinen Tausch vor",
modalStep1: "Erstelle eine Fotogalerie deiner Tasche.",
modalStep2: "Beschreibe das Produkt.",
modalStep3: "Hinterlege die Tauschbedingungen.",
subscribeTitle: "Wir entwickeln Bag Exchange.",
subscribeDesc: "Gib deine E-Mail ein, um auf dem Laufenden zu bleiben.",
subscribePlaceholder: "Deine E-Mail",
subscribeCta: "Auf dem Laufenden halten",
subscribeThanks: "Danke. Wir halten dich auf dem Laufenden.",
subscribeInvalidEmail: "Bitte gib eine gueltige E-Mail-Adresse ein.",
subscribeError: "Etwas ist schiefgelaufen. Bitte versuche es erneut.",
registerTitle: "Erstelle dein Konto",
registerDesc: "Registriere dich, um mit dem Tauschen zu starten und der Community beizutreten.",
registerEmailPlaceholder: "Deine E-Mail",
registerPasswordPlaceholder: "Passwort",
registerConfirmPlaceholder: "Passwort bestaetigen",
registerCta: "Konto erstellen",
registerThanks: "Registrierung abgeschlossen. Du kannst dich einloggen, sobald der Auth-Bereich live ist.",
registerInvalidEmail: "Bitte gib eine gueltige E-Mail-Adresse ein.",
registerPasswordMismatch: "Die Passwoerter stimmen nicht ueberein.",
registerWeakPassword: "Mindestens 8 Zeichen mit Buchstaben und Zahlen verwenden.",
registerEmailExists: "Diese E-Mail ist bereits registriert.",
registerError: "Registrierung konnte nicht abgeschlossen werden. Bitte erneut versuchen.",
loginTitle: "Zugang zu deinem Konto",
loginDesc: "Melde dich an, um deine Austauschreise fortzusetzen.",
loginEmailPlaceholder: "Deine E-Mail",
loginPasswordPlaceholder: "Passwort",
loginCta: "Anmelden",
loginForgotLink: "Passwort vergessen?",
loginSuccess: "Login erfolgreich.",
loginInvalid: "Ungueltige E-Mail oder Passwort.",
loginNotVerified: "E-Mail nicht verifiziert. Bitte pruefe dein Postfach auf den Verifizierungslink.",
loginError: "Anmeldung nicht moeglich. Bitte erneut versuchen.",
authStatusGuest: "Nicht angemeldet.",
authStatusUserPrefix: "Angemeldet als:"
},
es: {
pageTitle: "Bag Exchange | Intercambio de bolsos y carteras",
languageLabel: "Idioma",
badge: "comunidad beta",
heroTitle: "Dale nueva vida a tus bolsos.",
heroDesc: "Intercambia bolsos y carteras de forma simple, segura y sostenible. Sube tu articulo, encuentra matches reales y renueva tu estilo sin comprar nuevo cada vez.",
ctaPrimary: "Empezar a intercambiar",
ctaLogin: "Iniciar sesion",
ctaLogout: "Cerrar sesion",
ctaSecondary: "Ver como funciona",
ctaRegister: "Crear cuenta",
howTitle: "Como funciona en 3 pasos",
step1: "1. Publica tu bolso con fotos y estado",
step2: "2. Recibe propuestas de personas con gustos similares",
step3: "3. Confirma el intercambio con chat y envio con seguimiento",
card1Title: "Solo perfiles verificados",
card1Desc: "Reducimos riesgos con verificacion de cuenta, valoraciones e historial de intercambios transparente.",
card2Title: "Ahorra y revaloriza",
card2Desc: "Una forma inteligente de renovar tu armario evitando desperdicios y gastos innecesarios.",
card3Title: "Estilo circular",
card3Desc: "Desde bolsos de diario hasta clutch elegante: cada pieza puede encontrar nueva duena.",
communityTitle: "Videochat y crecimiento de perfil",
communityDesc: "Puedes hacer videochat con personas interesadas en tus productos o simplemente intercambiar opiniones y consejos. Puedes aspirar a convertirte en una influencer de bolsos de moda.",
footer: "© 2026 Bag Exchange · Intercambio de bolsos y carteras entre particulares",
modalTitle: "Como preparar tu intercambio",
modalStep1: "Crea una galeria de fotos de tu bolso.",
modalStep2: "Describe el producto.",
modalStep3: "Indica las condiciones de intercambio.",
subscribeTitle: "Estamos desarrollando Bag Exchange.",
subscribeDesc: "Ingresa tu email para mantenerte al dia.",
subscribePlaceholder: "Tu email",
subscribeCta: "Mantenerme informado",
subscribeThanks: "Gracias. Te mantendremos informado.",
subscribeInvalidEmail: "Introduce un correo electronico valido.",
subscribeError: "Algo salio mal. Intentalo de nuevo.",
registerTitle: "Crea tu cuenta",
registerDesc: "Registrate para empezar a intercambiar y unirte a la comunidad.",
registerEmailPlaceholder: "Tu email",
registerPasswordPlaceholder: "Contrasena",
registerConfirmPlaceholder: "Confirmar contrasena",
registerCta: "Crear cuenta",
registerThanks: "Registro completado. Podras iniciar sesion cuando el area auth este disponible.",
registerInvalidEmail: "Introduce un correo electronico valido.",
registerPasswordMismatch: "Las contrasenas no coinciden.",
registerWeakPassword: "Usa al menos 8 caracteres con letras y numeros.",
registerEmailExists: "Este email ya esta registrado.",
registerError: "No se pudo completar el registro. Intentalo de nuevo.",
loginTitle: "Accede a tu cuenta",
loginDesc: "Inicia sesion para continuar tu recorrido de intercambio.",
loginEmailPlaceholder: "Tu email",
loginPasswordPlaceholder: "Contrasena",
loginCta: "Iniciar sesion",
loginForgotLink: "Has olvidado tu contrasena?",
loginSuccess: "Sesion iniciada correctamente.",
loginInvalid: "Email o contrasena no validos.",
loginNotVerified: "Email no verificado. Revisa tu bandeja de entrada para el enlace de verificacion.",
loginError: "No se pudo iniciar sesion. Intentalo de nuevo.",
authStatusGuest: "No autenticado.",
authStatusUserPrefix: "Conectado como:"
}
};
var currentLanguage = fallback;
var currentAuthEmail = "";
function normalizeLanguage(lang) {
if (!lang) return fallback;
var normalized = String(lang).toLowerCase().replace("_", "-");
if (aliases[normalized]) return aliases[normalized];
var base = normalized.split("-")[0];
if (supported.indexOf(base) !== -1) return base;
return fallback;
}
function getInitialLanguage() {
var params = new URLSearchParams(window.location.search);
var queryLang = params.get("lang");
if (queryLang) return normalizeLanguage(queryLang);
var saved = window.localStorage.getItem("preferredLang");
if (saved) return normalizeLanguage(saved);
var browserLang = navigator.language || (navigator.languages && navigator.languages[0]) || fallback;
return normalizeLanguage(browserLang);
}
function applyLanguage(lang) {
var active = translations[lang] || translations[fallback];
currentLanguage = lang;
document.documentElement.lang = lang;
document.title = active.pageTitle;
var nodes = document.querySelectorAll("[data-i18n]");
for (var i = 0; i < nodes.length; i++) {
var key = nodes[i].getAttribute("data-i18n");
if (active[key]) nodes[i].textContent = active[key];
}
var placeholders = document.querySelectorAll("[data-i18n-placeholder]");
for (var j = 0; j < placeholders.length; j++) {
var placeholderKey = placeholders[j].getAttribute("data-i18n-placeholder");
if (active[placeholderKey]) placeholders[j].setAttribute("placeholder", active[placeholderKey]);
}
var selector = document.getElementById("language-select");
if (selector) selector.value = lang;
var authStatusNode = document.getElementById("auth-status");
if (authStatusNode) {
if (currentAuthEmail) {
authStatusNode.textContent = currentAuthEmail;
authStatusNode.classList.remove("is-hidden");
} else {
authStatusNode.textContent = "";
authStatusNode.classList.add("is-hidden");
}
}
var url = new URL(window.location.href);
url.searchParams.set("lang", lang);
window.history.replaceState({}, "", url.toString());
}
var initialLanguage = getInitialLanguage();
applyLanguage(initialLanguage);
var select = document.getElementById("language-select");
if (select) {
select.addEventListener("change", function (event) {
var chosen = normalizeLanguage(event.target.value);
window.localStorage.setItem("preferredLang", chosen);
applyLanguage(chosen);
});
}
function closeModal(modal) {
if (!modal) return;
modal.classList.remove("is-open");
modal.setAttribute("aria-hidden", "true");
}
function openModal(modal) {
if (!modal) return;
modal.classList.add("is-open");
modal.setAttribute("aria-hidden", "false");
}
function bindModal(openButtonId, modalId, closeButtonId) {
var modal = document.getElementById(modalId);
var openButton = document.getElementById(openButtonId);
var closeButton = document.getElementById(closeButtonId);
if (!modal || !openButton || !closeButton) return null;
openButton.addEventListener("click", function () {
openModal(modal);
});
closeButton.addEventListener("click", function () {
closeModal(modal);
});
modal.addEventListener("click", function (event) {
if (event.target === modal) {
closeModal(modal);
}
});
return modal;
}
var modals = [];
var subscribeModal = bindModal("start-swapping-btn", "subscribe-modal", "subscribe-close-btn");
if (subscribeModal) modals.push(subscribeModal);
var subscribeForm = document.getElementById("subscribe-form");
var subscribeEmailInput = document.getElementById("subscribe-email");
var subscribeSubmitButton = document.getElementById("subscribe-submit-btn");
var subscribeFeedback = document.getElementById("subscribe-feedback");
var subscribeError = document.getElementById("subscribe-error");
var loginButton = document.getElementById("login-btn");
var registerButton = document.getElementById("register-btn");
var logoutButton = document.getElementById("logout-btn");
function getActiveTranslation(key) {
var active = translations[currentLanguage] || translations[fallback];
return active[key] || "";
}
function setSubscribeState(subscribed) {
if (!subscribeForm || !subscribeFeedback) return;
subscribeForm.classList.toggle("is-hidden", subscribed);
subscribeFeedback.classList.toggle("is-hidden", !subscribed);
if (subscribed && subscribeError) {
subscribeError.classList.add("is-hidden");
subscribeError.textContent = "";
}
}
function setSubscribeError(message) {
if (!subscribeError) return;
subscribeError.textContent = message;
subscribeError.classList.remove("is-hidden");
}
function setAuthStatus(email) {
currentAuthEmail = email || "";
var authStatusNode = document.getElementById("auth-status");
if (!authStatusNode) return;
if (currentAuthEmail) {
authStatusNode.textContent = currentAuthEmail;
authStatusNode.classList.remove("is-hidden");
if (loginButton) loginButton.classList.add("is-hidden");
if (registerButton) registerButton.classList.add("is-hidden");
if (logoutButton) logoutButton.classList.remove("is-hidden");
} else {
authStatusNode.textContent = "";
authStatusNode.classList.add("is-hidden");
if (loginButton) loginButton.classList.remove("is-hidden");
if (registerButton) registerButton.classList.remove("is-hidden");
if (logoutButton) logoutButton.classList.add("is-hidden");
}
}
async function refreshAuthStatus() {
try {
var response = await fetch("/api/auth/me", { method: "GET" });
if (!response.ok) {
setAuthStatus("");
return;
}
var payload = await response.json();
if (payload && payload.authenticated && payload.email) {
setAuthStatus(payload.email);
} else {
setAuthStatus("");
}
} catch (error) {
setAuthStatus("");
}
}
function collectBrowserData() {
return {
userAgent: navigator.userAgent || "",
language: navigator.language || "",
languages: navigator.languages || [],
platform: navigator.platform || "",
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || "",
screen: {
width: window.screen && window.screen.width ? window.screen.width : 0,
height: window.screen && window.screen.height ? window.screen.height : 0
}
};
}
if (subscribeForm) {
subscribeForm.addEventListener("submit", async function (event) {
event.preventDefault();
if (!subscribeEmailInput) return;
var email = subscribeEmailInput.value.trim();
if (!email || !subscribeEmailInput.checkValidity()) {
setSubscribeError(getActiveTranslation("subscribeInvalidEmail"));
return;
}
if (subscribeError) {
subscribeError.classList.add("is-hidden");
subscribeError.textContent = "";
}
if (subscribeSubmitButton) subscribeSubmitButton.disabled = true;
try {
var response = await fetch("/api/subscribe", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email: email,
browserData: collectBrowserData()
})
});
if (response.ok || response.status === 409) {
setSubscribeState(true);
subscribeForm.reset();
if (subscribeFeedback) {
subscribeFeedback.textContent = getActiveTranslation("subscribeThanks");
}
} else if (response.status === 400) {
setSubscribeError(getActiveTranslation("subscribeInvalidEmail"));
} else {
setSubscribeError(getActiveTranslation("subscribeError"));
}
} catch (error) {
setSubscribeError(getActiveTranslation("subscribeError"));
} finally {
if (subscribeSubmitButton) subscribeSubmitButton.disabled = false;
}
});
}
if (logoutButton) {
logoutButton.addEventListener("click", async function () {
try {
await fetch("/api/auth/logout", { method: "POST" });
} catch (error) {
}
setAuthStatus("");
});
}
refreshAuthStatus();
document.addEventListener("keydown", function (event) {
if (event.key === "Escape") {
for (var i = 0; i < modals.length; i++) {
closeModal(modals[i]);
}
}
});
})();