let userData = null; let hasSubscription = false; let currentPlan = null; // Charger les informations utilisateur au chargement document.addEventListener("DOMContentLoaded", function () { // Vérifier les paramètres de succès dans l'URL checkSuccessParameters(); // Attacher les événements aux boutons de plan (une seule fois au chargement) attachPlanButtonEvents(); // Charger les informations utilisateur loadUserInfo(); }); // Fonction pour vérifier les paramètres de succès dans l'URL function checkSuccessParameters() { const urlParams = new URLSearchParams(window.location.search); const type = urlParams.get("type"); const sessionId = urlParams.get("session_id"); if (type && sessionId) { if (type === "credits_success") { showMessage( "Credit purchase completed successfully! Your credits will be updated shortly.", "success" ); // Recharger les données après un délai pour s'assurer que les crédits sont mis à jour setTimeout(() => { loadUserInfo(); }, 3000); // Nettoyer l'URL après affichage du message setTimeout(() => { const newUrl = window.location.pathname + window.location.search .replace(/[?&]type=[^&]*&session_id=[^&]*/, "") .replace(/^&/, "?"); window.history.replaceState({}, document.title, newUrl); }, 5000); } else if (type === "subscription_success") { showMessage( "Subscription activated successfully! Your subscription is now active.", "success" ); // Recharger les données après un délai pour s'assurer que l'abonnement est mis à jour setTimeout(() => { loadUserInfo(); }, 3000); // Nettoyer l'URL après affichage du message setTimeout(() => { const newUrl = window.location.pathname + window.location.search .replace(/[?&]type=[^&]*&session_id=[^&]*/, "") .replace(/^&/, "?"); window.history.replaceState({}, document.title, newUrl); }, 5000); } } } // Fonction pour charger les informations utilisateur async function loadUserInfo() { try { const tokenResponse = await fetch(ajaxurl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "action=aibui_get_token&nonce=" + aiBuilderVars.nonce, }); const tokenData = await tokenResponse.json(); if (!tokenData.success || !tokenData.data.token) { showMessage("Authentication failed", "error"); return; } const jwtToken = tokenData.data.token; const response = await fetch(window.config.apiUrl + "/user/profile", { method: "GET", headers: { Authorization: `Bearer ${jwtToken}`, "Content-Type": "application/json", }, }); if (response.ok) { userData = await response.json(); displayUserInfo(userData?.user); // updateSubscriptionButton() n'est plus nécessaire car updatePlansDisplay() gère tout } else { showMessage("Failed to load user information", "error"); } } catch (error) { console.error("Error loading user info:", error); showMessage("Network error while loading user information", "error"); } } // Afficher les informations utilisateur function displayUserInfo(data) { // Afficher les crédits const creditsDisplay = document.getElementById("current-credits"); const creditsBreakdown = data.aiCredits || { onAccountCreation: 0, monthlySubscription: 0, paid: 0, }; const totalCredits = creditsBreakdown.onAccountCreation + creditsBreakdown.monthlySubscription + creditsBreakdown.paid; if (creditsDisplay) { creditsDisplay.innerHTML = ` ${totalCredits} credits `; } // Afficher le plan const planDisplay = document.getElementById("current-plan"); if (planDisplay) { const plan = data.plan || "basic"; let resiliateText = ""; if (data.resiliateAt) { const resiliateDate = new Date(data.resiliateAt); const now = new Date(); const isEnded = resiliateDate < now.setHours(0, 0, 0, 0); if (isEnded) { resiliateText = `Subscription has ended on ${resiliateDate.toLocaleDateString()}`; } else { resiliateText = `Subscription will end on ${resiliateDate.toLocaleDateString()}`; } } planDisplay.innerHTML = ` ${plan.charAt(0).toUpperCase() + plan.slice(1) } ${resiliateText} `; } // Afficher le message dans la carte Subscription (section management) const subscriptionCard = document.querySelector( ".ai-subscription-actions .ai-action-content" ); if (subscriptionCard) { let resiliateMsg = subscriptionCard.querySelector(".resiliate-badge"); if (data.resiliateAt) { if (!resiliateMsg) { resiliateMsg = document.createElement("div"); resiliateMsg.className = "resiliate-badge"; resiliateMsg.innerHTML = `Subscription will end on ${new Date( data.resiliateAt ).toLocaleDateString()}`; subscriptionCard.appendChild(resiliateMsg); } else { resiliateMsg.innerHTML = `Subscription will end on ${new Date( data.resiliateAt ).toLocaleDateString()}`; } } else if (resiliateMsg) { resiliateMsg.remove(); } } // Vérifier si l'utilisateur a un abonnement hasSubscription = data.plan && data.plan !== "basic"; currentPlan = data.plan || "basic"; window.hasResiliate = !!data.resiliateAt; // Mettre à jour l'affichage de la section Buy Credits updateCreditPurchaseSection(); // Mettre à jour l'affichage des plans updatePlansDisplay(); } // Attacher les événements aux boutons de plan function attachPlanButtonEvents() { // Utiliser la délégation d'événements pour éviter les problèmes de duplication const plansContainer = document.getElementById("subscription-plans-container"); if (plansContainer) { // Retirer l'ancien listener s'il existe plansContainer.removeEventListener("click", handlePlanButtonClick); // Ajouter le nouveau listener plansContainer.addEventListener("click", handlePlanButtonClick); } // Bouton d'annulation const cancelBtn = document.getElementById("subscription-btn"); if (cancelBtn) { cancelBtn.onclick = showCancelModal; } } // Gestionnaire de clic pour les boutons de plan (délégation d'événements) function handlePlanButtonClick(event) { const button = event.target.closest(".ai-plan-btn"); if (!button || button.disabled) return; const subscriptionType = button.getAttribute("data-subscription-type"); if (subscriptionType) { // Vérifier dynamiquement l'état de l'abonnement if (hasSubscription && !window.hasResiliate) { // Utilisateur avec abonnement actif -> changer de plan handleChangeSubscription(subscriptionType, button); } else { // Utilisateur sans abonnement ou abonnement annulé -> nouveau checkout handleSubscription(subscriptionType, button); } } } // Mettre à jour l'affichage des plans function updatePlansDisplay() { const planWrappers = document.querySelectorAll(".ai-plan-card-wrapper"); const cancelCard = document.getElementById("cancel-subscription-card"); if (!planWrappers || planWrappers.length === 0) { return; // Les plans ne sont pas encore chargés } planWrappers.forEach((wrapper) => { const planType = wrapper.getAttribute("data-plan"); const button = wrapper.querySelector(".ai-plan-btn"); if (!button) return; const btnText = button.querySelector(".btn-text"); if (!btnText) return; // Réinitialiser l'état wrapper.setAttribute("data-current-plan", "false"); button.classList.remove("current-plan"); button.disabled = false; if (hasSubscription && !window.hasResiliate) { // Utilisateur avec abonnement actif if (planType === currentPlan) { // Plan actuel wrapper.setAttribute("data-current-plan", "true"); button.classList.add("current-plan"); btnText.textContent = "Current Plan"; button.disabled = true; } else { // Autre plan -> option de changement btnText.textContent = `Switch to ${planType.charAt(0).toUpperCase() + planType.slice(1)}`; button.disabled = false; } } else if (hasSubscription && window.hasResiliate) { // Abonnement annulé mais pas encore terminé btnText.textContent = `Choose ${planType.charAt(0).toUpperCase() + planType.slice(1)}`; button.disabled = false; } else { // Pas d'abonnement btnText.textContent = `Choose ${planType.charAt(0).toUpperCase() + planType.slice(1)}`; button.disabled = false; } }); // Afficher/masquer la carte d'annulation if (cancelCard) { if (hasSubscription && !window.hasResiliate) { cancelCard.style.display = "block"; } else { cancelCard.style.display = "none"; } } } // Mettre à jour le bouton d'abonnement (fonction conservée pour compatibilité mais non utilisée) // L'affichage des plans est maintenant géré par updatePlansDisplay() // Cette fonction peut être utilisée pour le bouton d'annulation si nécessaire function updateSubscriptionButton() { const btn = document.getElementById("subscription-btn"); if (!btn) return; // Sécurité : le bouton n'existe pas // Reconstruit le HTML interne du bouton à chaque fois btn.innerHTML = ` `; const btnText = btn.querySelector(".btn-text"); const loading = btn.querySelector(".ai-loading"); if (!btnText || !loading) return; // Sécurité : structure inattendue if (hasSubscription && window.hasResiliate) { btnText.textContent = "Reactivate Subscription"; btn.className = "ai-primary-btn ai-reactivate-btn"; btn.onclick = handleReactivateSubscription; } else if (hasSubscription) { btnText.textContent = "Cancel Subscription"; btn.className = "ai-danger-btn"; btn.onclick = showCancelModal; } else { // Ce cas ne devrait plus se produire car nous avons maintenant les boutons de plan individuels btnText.textContent = "Get Subscription"; btn.className = "ai-primary-btn"; btn.onclick = null; // Ne pas assigner handleSubscription sans paramètre } } // Fonction pour réactiver l'abonnement async function handleReactivateSubscription() { setLoading("subscription-btn", true); try { const tokenResponse = await fetch(ajaxurl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "action=aibui_get_token&nonce=" + aiBuilderVars.nonce, }); const tokenData = await tokenResponse.json(); const jwtToken = tokenData.data.token; const response = await fetch( window.config.apiUrl + "/payments/resume-subscription", { method: "POST", headers: { Authorization: `Bearer ${jwtToken}`, "Content-Type": "application/json", }, } ); const data = await response.json(); if (response.ok) { showMessage("Subscription reactivated successfully!", "success"); setTimeout(() => { loadUserInfo(); }, 1000); } else { showMessage(data.message || "Failed to reactivate subscription", "error"); } } catch (error) { console.error("Error reactivating subscription:", error); showMessage("Network error while reactivating subscription", "error"); } finally { setLoading("subscription-btn", false); } } // Mettre à jour l'affichage de la section Buy Credits function updateCreditPurchaseSection() { const creditCard = document.getElementById("credit-purchase-card"); const buyCreditsBtn = document.getElementById("buy-credits-btn"); const subscriptionMessage = document.getElementById( "subscription-required-message" ); const sectionHeader = document.querySelector( "#credit-purchase-section .ai-section-header p" ); if (hasSubscription) { // Utilisateur avec abonnement - afficher normalement creditCard.classList.remove("ai-disabled"); buyCreditsBtn.disabled = false; buyCreditsBtn.onclick = handleCreditPurchase; subscriptionMessage.style.display = "none"; sectionHeader.textContent = "Purchase additional credits when you need them"; } else { // Utilisateur sans abonnement - griser et afficher message creditCard.classList.add("ai-disabled"); buyCreditsBtn.disabled = true; buyCreditsBtn.onclick = null; subscriptionMessage.style.display = "flex"; // sectionHeader.textContent = // "Active subscription required to purchase credits"; } } // Gérer l'abonnement (nouveau checkout) async function handleSubscription(subscriptionType, buttonElement) { if (!subscriptionType) { showMessage("Please select a subscription plan", "error"); return; } // Désactiver tous les boutons pendant le traitement const planButtons = document.querySelectorAll(".ai-plan-btn"); planButtons.forEach((btn) => { btn.disabled = true; }); // Afficher le loading sur le bouton cliqué if (buttonElement) { const loading = buttonElement.querySelector(".ai-loading"); const btnText = buttonElement.querySelector(".btn-text"); if (loading) loading.style.display = "inline-block"; if (btnText) { const originalText = btnText.textContent; btnText.textContent = "Processing..."; } } try { const tokenResponse = await fetch(ajaxurl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "action=aibui_get_token&nonce=" + aiBuilderVars.nonce, }); const tokenData = await tokenResponse.json(); if (!tokenData.success || !tokenData.data.token) { showMessage("Authentication failed", "error"); return; } const jwtToken = tokenData.data.token; const response = await fetch( window.config.apiUrl + "/payments/create-checkout-session-abo", { method: "POST", headers: { Authorization: `Bearer ${jwtToken}`, "Content-Type": "application/json", }, body: JSON.stringify({ subscriptionType: subscriptionType, urlFrom: window.location.href, }), } ); const data = await response.json(); if (response.ok && data.url) { window.location.href = data.url; } else { showMessage( data.message || "Failed to create subscription checkout", "error" ); // Réactiver les boutons en cas d'erreur planButtons.forEach((btn) => { btn.disabled = false; }); if (buttonElement) { const loading = buttonElement.querySelector(".ai-loading"); const btnText = buttonElement.querySelector(".btn-text"); if (loading) loading.style.display = "none"; if (btnText) { btnText.textContent = buttonElement.getAttribute("data-subscription-type") ? `Choose ${buttonElement.getAttribute("data-subscription-type").charAt(0).toUpperCase() + buttonElement.getAttribute("data-subscription-type").slice(1)}` : "Choose Plan"; } } } } catch (error) { console.error("Error creating subscription:", error); showMessage("Network error while creating subscription", "error"); // Réactiver les boutons en cas d'erreur const planButtons = document.querySelectorAll(".ai-plan-btn"); planButtons.forEach((btn) => { btn.disabled = false; }); if (buttonElement) { const loading = buttonElement.querySelector(".ai-loading"); const btnText = buttonElement.querySelector(".btn-text"); if (loading) loading.style.display = "none"; if (btnText) { btnText.textContent = buttonElement.getAttribute("data-subscription-type") ? `Choose ${buttonElement.getAttribute("data-subscription-type").charAt(0).toUpperCase() + buttonElement.getAttribute("data-subscription-type").slice(1)}` : "Choose Plan"; } } } } // Gérer le changement d'abonnement async function handleChangeSubscription(subscriptionType, buttonElement) { if (!subscriptionType) { showMessage("Please select a subscription plan", "error"); return; } // Vérifier si c'est le même plan if (subscriptionType === currentPlan) { showMessage("You are already on this plan", "info"); return; } // Désactiver tous les boutons pendant le traitement const planButtons = document.querySelectorAll(".ai-plan-btn"); planButtons.forEach((btn) => { btn.disabled = true; }); // Afficher le loading sur le bouton cliqué if (buttonElement) { const loading = buttonElement.querySelector(".ai-loading"); const btnText = buttonElement.querySelector(".btn-text"); if (loading) loading.style.display = "inline-block"; if (btnText) { const originalText = btnText.textContent; btnText.textContent = "Switching..."; } } try { const tokenResponse = await fetch(ajaxurl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "action=aibui_get_token&nonce=" + aiBuilderVars.nonce, }); const tokenData = await tokenResponse.json(); if (!tokenData.success || !tokenData.data.token) { showMessage("Authentication failed", "error"); return; } const jwtToken = tokenData.data.token; const response = await fetch( window.config.apiUrl + "/payments/change-subscription", { method: "POST", headers: { Authorization: `Bearer ${jwtToken}`, "Content-Type": "application/json", }, body: JSON.stringify({ subscriptionType: subscriptionType, }), } ); const data = await response.json(); if (response.ok) { showMessage("Subscription changed successfully!", "success"); // Recharger les informations utilisateur setTimeout(() => { loadUserInfo(); }, 1000); } else { showMessage( data.message || "Failed to change subscription", "error" ); // Réactiver les boutons en cas d'erreur planButtons.forEach((btn) => { btn.disabled = false; }); if (buttonElement) { const loading = buttonElement.querySelector(".ai-loading"); const btnText = buttonElement.querySelector(".btn-text"); if (loading) loading.style.display = "none"; if (btnText) { btnText.textContent = `Switch to ${subscriptionType.charAt(0).toUpperCase() + subscriptionType.slice(1)}`; } } } } catch (error) { console.error("Error changing subscription:", error); showMessage("Network error while changing subscription", "error"); // Réactiver les boutons en cas d'erreur const planButtons = document.querySelectorAll(".ai-plan-btn"); planButtons.forEach((btn) => { btn.disabled = false; }); if (buttonElement) { const loading = buttonElement.querySelector(".ai-loading"); const btnText = buttonElement.querySelector(".btn-text"); if (loading) loading.style.display = "none"; if (btnText) { btnText.textContent = `Switch to ${subscriptionType.charAt(0).toUpperCase() + subscriptionType.slice(1)}`; } } } } // Acheter des crédits async function handleCreditPurchase() { try { const tokenResponse = await fetch(ajaxurl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "action=aibui_get_token&nonce=" + aiBuilderVars.nonce, }); const tokenData = await tokenResponse.json(); const jwtToken = tokenData.data.token; const urlFrom = window.location.href; const response = await fetch( window.config.apiUrl + "/payments/create-checkout-session-credits", { method: "POST", headers: { Authorization: `Bearer ${jwtToken}`, "Content-Type": "application/json", }, body: JSON.stringify({ urlFrom, }), } ); const data = await response.json(); if (response.ok && data.url) { window.location.href = data.url; } else { showMessage(data.message || "Failed to create credit checkout", "error"); } } catch (error) { console.error("Error creating credit checkout:", error); showMessage("Network error while creating credit checkout", "error"); } } // Accéder au compte Stripe async function handleStripeAccount() { try { const tokenResponse = await fetch(ajaxurl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "action=aibui_get_token&nonce=" + aiBuilderVars.nonce, }); const tokenData = await tokenResponse.json(); const jwtToken = tokenData.data.token; const urlFrom = window.location.href; const response = await fetch( window.config.apiUrl + "/payments/stripe-customer-portal", { method: "POST", headers: { Authorization: `Bearer ${jwtToken}`, "Content-Type": "application/json", }, body: JSON.stringify({ urlFrom, }), } ); const data = await response.json(); if (response.ok && data.url) { window.open(data.url, "_blank"); } else { showMessage(data.message || "Failed to access Stripe account", "error"); } } catch (error) { console.error("Error accessing Stripe account:", error); showMessage("Network error while accessing Stripe account", "error"); } } // Afficher la modal de confirmation function showCancelModal() { document.getElementById("confirmation-modal").style.display = "flex"; } // Fermer la modal function closeModal() { document.getElementById("confirmation-modal").style.display = "none"; } // Confirmer l'annulation de l'abonnement async function confirmCancelSubscription() { const btn = document.querySelector(".ai-danger-btn"); const loading = btn.querySelector(".ai-loading"); const text = btn.textContent; loading.style.display = "inline-block"; btn.textContent = ""; btn.appendChild(loading); btn.appendChild(document.createTextNode(text)); btn.disabled = true; try { const tokenResponse = await fetch(ajaxurl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "action=aibui_get_token&nonce=" + aiBuilderVars.nonce, }); const tokenData = await tokenResponse.json(); const jwtToken = tokenData.data.token; const response = await fetch( window.config.apiUrl + "/payments/cancel-subscription", { method: "POST", headers: { Authorization: `Bearer ${jwtToken}`, "Content-Type": "application/json", }, } ); const data = await response.json(); if (response.ok) { showMessage("Subscription cancelled successfully", "success"); closeModal(); // Forcer l'état local pour l'UI window.hasResiliate = true; hasSubscription = false; // Mettre à jour l'état local // Recharger les informations utilisateur (qui va mettre à jour l'affichage via updatePlansDisplay) setTimeout(() => { loadUserInfo(); }, 1000); } else { showMessage(data.message || "Failed to cancel subscription", "error"); } } catch (error) { console.error("Error cancelling subscription:", error); showMessage("Network error while cancelling subscription", "error"); } finally { loading.style.display = "none"; btn.textContent = text; btn.disabled = false; } } // Fonctions utilitaires function showMessage(message, type = "info") { const container = document.getElementById("message-container"); container.innerHTML = `
${message}
`; container.scrollIntoView({ behavior: "smooth" }); } function setLoading(buttonId, isLoading) { const button = document.getElementById(buttonId); const loading = button.querySelector(".ai-loading"); const text = button.querySelector(".btn-text"); if (isLoading) { loading.style.display = "inline-block"; button.disabled = true; } else { loading.style.display = "none"; button.disabled = false; } }