PluginProbe
AI Builder – Generate pages, blocks, images & translate with AI / 2.1.2
AI Builder – Generate pages, blocks, images & translate with AI v2.1.2
2.7.10 2.7.9 2.7.8 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.3.10 All 122 releases
ai-builder / assets / js / account.js

account.js in AI Builder – Generate pages, blocks, images & translate with AI 2.1.2, at assets/js/account.js

488 lines 15.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 let currentForm = "";
2
3 function showMessage(message, type = "info") {
4 let container = document.getElementById("message-container");
5
6 // Si le container n'existe pas, le créer
7 if (!container) {
8 container = document.createElement("div");
9 container.id = "message-container";
10 const authContainer = document.querySelector(".ai-auth-container");
11 if (authContainer) {
12 authContainer.appendChild(container);
13 }
14 }
15
16 container.innerHTML = `<div class="ai-message ${type}">${message}</div>`;
17 container.scrollIntoView({ behavior: "smooth" });
18 }
19
20 function setLoading(buttonId, isLoading) {
21 const button = document.getElementById(buttonId);
22
23 if (!button) {
24 console.error(`Button with id '${buttonId}' not found`);
25 return;
26 }
27
28 let loading = button.querySelector(".ai-loading");
29
30 // Si l'élément loading n'existe pas, le créer
31 if (!loading) {
32 loading = document.createElement("span");
33 loading.className = "ai-loading";
34 loading.style.display = "none";
35 button.appendChild(loading);
36 }
37
38 // Stocker le texte original dans un attribut data si pas déjà fait
39 if (!button.dataset.originalText) {
40 button.dataset.originalText = button.textContent.trim();
41 }
42
43 if (isLoading) {
44 loading.style.display = "inline-block";
45 button.disabled = true;
46 button.textContent = "";
47 button.appendChild(loading);
48 button.appendChild(document.createTextNode(button.dataset.originalText));
49 } else {
50 loading.style.display = "none";
51 button.disabled = false;
52 button.textContent = button.dataset.originalText;
53 }
54 }
55
56 function toggleForm(formType) {
57 const container = document.querySelector(".ai-auth-container");
58 const hiddenSignup = document.getElementById("hidden-signup-form");
59 const hiddenSignin = document.getElementById("hidden-signin-form");
60
61 if (formType === "signup") {
62 container.innerHTML = hiddenSignup.innerHTML;
63 currentForm = "signup";
64 setupFormListeners();
65 } else {
66 container.innerHTML = hiddenSignin.innerHTML;
67 currentForm = "signin";
68 setupFormListeners();
69 }
70
71 // Ajouter l'animation
72 container.classList.remove("ai-fade-in");
73 void container.offsetWidth; // Trigger reflow
74 container.classList.add("ai-fade-in");
75 }
76
77 function setupFormListeners() {
78 const signupForm =
79 document.getElementById("signup-form") ||
80 document.getElementById("hidden-signup-form-element");
81 const signinForm =
82 document.getElementById("signin-form") ||
83 document.getElementById("hidden-signin-form-element");
84
85 if (signupForm) {
86 signupForm.addEventListener("submit", handleSignup);
87
88 // Ajouter un listener pour la checkbox des conditions d'utilisation
89 const termsCheckbox = signupForm.querySelector("#terms-checkbox");
90 if (termsCheckbox) {
91 termsCheckbox.addEventListener("change", function () {
92 const checkboxLabel = this.closest(".ai-checkbox-label");
93 if (checkboxLabel) {
94 if (this.checked) {
95 checkboxLabel.classList.remove("error");
96 }
97 }
98 });
99 }
100 }
101
102 if (signinForm) {
103 signinForm.addEventListener("submit", handleSignin);
104 }
105 }
106
107 async function handleSignup(e) {
108 e.preventDefault();
109 const form = e.target;
110 const email = form.email.value;
111 const password = form.password.value;
112 const confirmPassword = form.confirm_password.value;
113 const termsAccepted = form.terms_accepted && form.terms_accepted.checked;
114
115 // Récupérer le token Turnstile selon le formulaire
116 let captcha_token = "";
117 // if (currentForm === 'signup') {
118 // captcha_token = window.turnstile && turnstile.getResponse('cf-turnstile-signup');
119 // } else {
120 // captcha_token = window.turnstile && turnstile.getResponse('cf-turnstile-hidden-signup');
121 // }
122 // if (!captcha_token) {
123 // showMessage('Please complete the captcha.', 'error');
124 // return;
125 // }
126
127 if (password !== confirmPassword) {
128 showMessage("Passwords do not match", "error");
129 return;
130 }
131
132 if (password.length < 8) {
133 showMessage("Password must be at least 8 characters long", "error");
134 return;
135 }
136
137 if (!termsAccepted) {
138 showMessage(
139 "You must accept the Terms of Service and Privacy Policy to create an account",
140 "error"
141 );
142 // Ajouter une classe d'erreur visuelle à la checkbox
143 const checkboxLabel = document.querySelector(".ai-checkbox-label");
144 if (checkboxLabel) {
145 checkboxLabel.classList.add("error");
146 // Retirer la classe d'erreur après 3 secondes
147 setTimeout(() => {
148 checkboxLabel.classList.remove("error");
149 }, 3000);
150 }
151 return;
152 }
153
154 // Déterminer l'ID du bouton selon le formulaire actuel
155 const buttonId =
156 currentForm === "signup" ? "signup-btn" : "hidden-signup-btn";
157 setLoading(buttonId, true);
158
159 // Récupérer le nom de domaine du site
160 const siteDomain = (typeof aiBuilderVars !== 'undefined' && aiBuilderVars.siteDomain)
161 ? aiBuilderVars.siteDomain
162 : window.location.hostname;
163
164 try {
165 const response = await fetch(`${window.config.apiUrl}/auth/signup`, {
166 method: "POST",
167 headers: { "Content-Type": "application/json" },
168 body: JSON.stringify({ email, password, captcha_token, domain: siteDomain }),
169 });
170
171 console.log(response);
172 const data = await response.json();
173
174 if (response.ok) {
175 // Marquer l'inscription comme réussie
176 await fetch(ajaxurl, {
177 method: "POST",
178 headers: { "Content-Type": "application/x-www-form-urlencoded" },
179 body:
180 "action=aibui_set_signup_success&nonce=" + aiBuilderVars.nonce,
181 });
182
183 showMessage(
184 "Account created successfully! Please check your email to verify your account.",
185 "success"
186 );
187
188 // Basculer vers le formulaire de connexion après 3 secondes
189 setTimeout(() => {
190 toggleForm("signin");
191 showMessage(
192 "Before signing in, please check your email and click the verification link to activate your account.",
193 "info"
194 );
195 }, 3000);
196 } else {
197 showMessage(data.message || "Signup failed. Please try again.", "error");
198 }
199 } catch (error) {
200 console.log(error);
201 showMessage("Network error. Please check your connection.", "error");
202 } finally {
203 setLoading(buttonId, false);
204 // Réinitialiser le widget Turnstile
205 // if (currentForm === 'signup') {
206 // window.turnstile && turnstile.reset('cf-turnstile-signup');
207 // } else {
208 // window.turnstile && turnstile.reset('cf-turnstile-hidden-signup');
209 // }
210 }
211 }
212
213 async function handleSignin(e) {
214 e.preventDefault();
215 const form = e.target;
216 const email = form.email.value;
217 const password = form.password.value;
218
219 // Récupérer le token Turnstile selon le formulaire
220 let captcha_token = "";
221 // if (currentForm === 'signin') {
222 // captcha_token = window.turnstile && turnstile.getResponse('cf-turnstile-signin');
223 // } else {
224 // captcha_token = window.turnstile && turnstile.getResponse('cf-turnstile-hidden-signin');
225 // }
226 // if (!captcha_token) {
227 // showMessage('Please complete the captcha.', 'error');
228 // return;
229 // }
230
231 // Déterminer l'ID du bouton selon le formulaire actuel
232 const buttonId =
233 currentForm === "signin" ? "signin-btn" : "hidden-signin-btn";
234 setLoading(buttonId, true);
235
236 console.log("🔐 Attempting signin for:", email);
237
238 try {
239 const response = await fetch(`${window.config.apiUrl}/auth/signin`, {
240 method: "POST",
241 headers: { "Content-Type": "application/json" },
242 body: JSON.stringify({ email, password, captcha_token }),
243 });
244
245 const data = await response.json();
246 console.log("🔐 Signin response:", { status: response.status, data });
247
248 if (response.ok && data.token) {
249 console.log("�
250 Token received:", data.token.substring(0, 20) + "...");
251 console.log("�
252 Token length:", data.token.length);
253 console.log(
254 "�
255 Token format check:",
256 data.token.split(".").length === 3
257 ? "Valid JWT format"
258 : "Invalid JWT format"
259 );
260
261 // Vérifier le format du token reçu
262 if (data.token.split(".").length !== 3) {
263 console.error("❌ Invalid JWT format received from signin API");
264 showMessage("Invalid token received from server", "error");
265 return;
266 }
267
268 // Sauvegarder le token JWT
269 const saveResponse = await fetch(ajaxurl, {
270 method: "POST",
271 headers: { "Content-Type": "application/x-www-form-urlencoded" },
272 body: `action=aibui_save_token&token=${encodeURIComponent(
273 data.token
274 )}&nonce=${aiBuilderVars.nonce}`,
275 });
276
277 const saveData = await saveResponse.json();
278 console.log("💾 Token save response:", saveData);
279
280 showMessage("Sign in successful! Redirecting...", "success");
281
282 // Recharger la page pour afficher le dashboard
283 location.reload();
284 } else {
285 console.error("❌ Signin failed:", data);
286 showMessage(
287 data.message || "Sign in failed. Please check your credentials.",
288 "error"
289 );
290 }
291 } catch (error) {
292 console.error("❌ Signin network error:", error);
293 showMessage("Network error. Please check your connection.", "error");
294 } finally {
295 setLoading(buttonId, false);
296 // Réinitialiser le widget Turnstile
297 // if (currentForm === 'signin') {
298 // window.turnstile && turnstile.reset('cf-turnstile-signin');
299 // } else {
300 // window.turnstile && turnstile.reset('cf-turnstile-hidden-signin');
301 // }
302 }
303 }
304
305 async function signOut() {
306 try {
307 await fetch(ajaxurl, {
308 method: "POST",
309 headers: { "Content-Type": "application/x-www-form-urlencoded" },
310 body: "action=aibui_signout&nonce=" + aiBuilderVars.nonce,
311 });
312
313 showMessage("Signed out successfully", "success");
314
315 setTimeout(() => {
316 location.reload();
317 }, 1500);
318 } catch (error) {
319 showMessage("Error signing out", "error");
320 }
321 }
322
323 // Initialiser les listeners
324 document.addEventListener("DOMContentLoaded", function () {
325 // Déterminer le formulaire actuel basé sur le contenu de la page
326 const signupForm = document.getElementById("signup-form");
327 const signinForm = document.getElementById("signin-form");
328 const dashboardContent = document.querySelector(".ai-dashboard-content");
329
330 if (signupForm) {
331 currentForm = "signup";
332 } else if (signinForm) {
333 currentForm = "signin";
334 } else if (dashboardContent) {
335 currentForm = "dashboard";
336 }
337
338 setupFormListeners();
339
340 // Si on est sur le dashboard, charger les informations du compte
341 if (currentForm === "dashboard") {
342 loadUserAccountInfo();
343 }
344 });
345
346 // Fonction pour charger les informations du compte utilisateur
347 async function loadUserAccountInfo() {
348 // Éviter les appels multiples
349 if (window.isLoadingUserInfo) {
350 return;
351 }
352 window.isLoadingUserInfo = true;
353
354 console.log("🔍 Loading user account info...");
355
356 // Récupérer le token depuis les options WordPress via AJAX
357 try {
358 const tokenResponse = await fetch(ajaxurl, {
359 method: "POST",
360 headers: { "Content-Type": "application/x-www-form-urlencoded" },
361 body: "action=aibui_get_token&nonce=" + aiBuilderVars.nonce,
362 });
363
364 const tokenData = await tokenResponse.json();
365 console.log("📡 Token response:", tokenData);
366
367 if (!tokenData.success || !tokenData.data.token) {
368 console.error("❌ No token found:", tokenData);
369 showMessage("No authentication token found", "error");
370 // Supprimer le token invalide et rediriger vers la connexion
371 await fetch(ajaxurl, {
372 method: "POST",
373 headers: { "Content-Type": "application/x-www-form-urlencoded" },
374 body: "action=aibui_signout&nonce=" + aiBuilderVars.nonce,
375 });
376 setTimeout(() => {
377 location.reload();
378 }, 2000);
379 return;
380 }
381
382 const jwtToken = tokenData.data.token;
383 // Vérifier le format du token
384 if (jwtToken.split(".").length !== 3) {
385 console.error(
386 "❌ Invalid JWT format - token should have 3 parts separated by dots"
387 );
388 showMessage("Invalid token format", "error");
389 return;
390 }
391 const response = await fetch(`${window.config.apiUrl}/user/profile`, {
392 method: "GET",
393 headers: {
394 Authorization: `Bearer ${jwtToken}`,
395 "Content-Type": "application/json",
396 },
397 });
398
399 console.log("🌐 API Response status:", response.status);
400 console.log(
401 "🌐 API Response headers:",
402 Object.fromEntries(response.headers.entries())
403 );
404
405 if (response.ok) {
406 const userData = await response.json();
407 console.log("�
408 User data received:", userData);
409 displayUserInfo(userData?.user);
410 } else if (response.status === 401) {
411 console.error("❌ 401 Unauthorized - Token might be invalid");
412
413 // Essayer de récupérer plus d'informations sur l'erreur
414 try {
415 const errorData = await response.text();
416 console.error("❌ Error response body:", errorData);
417 } catch (e) {
418 console.error("❌ Could not read error response");
419 }
420
421 showMessage("Authentication failed. Please sign in again.", "error");
422 // Supprimer le token invalide
423 await fetch(ajaxurl, {
424 method: "POST",
425 headers: { "Content-Type": "application/x-www-form-urlencoded" },
426 body: "action=aibui_signout&nonce=" + aiBuilderVars.nonce,
427 });
428 // Rediriger vers la connexion sans recharger en boucle
429 setTimeout(() => {
430 window.location.href = aiBuilderVars.accountUrl;
431 }, 2000);
432 } else {
433 console.error("❌ API Error:", response.status, response.statusText);
434 showMessage("Failed to load account information", "error");
435 }
436 } catch (error) {
437 console.error("❌ Network error:", error);
438 showMessage("Network error while loading account information", "error");
439 } finally {
440 window.isLoadingUserInfo = false;
441 }
442 }
443
444 // Fonction pour afficher les informations utilisateur
445 function displayUserInfo(userData) {
446 console.log("🔍 User data:", userData);
447 // Afficher le plan
448 const planBadge = document.getElementById("plan-badge");
449 if (planBadge) {
450 const plan = userData.plan || "basic";
451 planBadge.textContent = plan.charAt(0).toUpperCase() + plan.slice(1);
452 console.log("🔍 Plan:", planBadge.textContent);
453 planBadge.className = `ai-plan-badge ${plan}`;
454 }
455
456 // Afficher les crédits
457 const creditsDisplay = document.getElementById("credits-display");
458 const creditsBreakdown = userData.aiCredits || {
459 onAccountCreation: 0,
460 monthlySubscription: 0,
461 paid: 0,
462 };
463
464 // Calculer le total des crédits
465 const totalCredits =
466 creditsBreakdown.onAccountCreation +
467 creditsBreakdown.monthlySubscription +
468 creditsBreakdown.paid;
469
470 if (creditsDisplay) {
471 creditsDisplay.innerHTML = `
472 <span>${totalCredits}</span>
473 <span style="font-size: 14px; color: #666;">credits</span>
474 `;
475 }
476
477 // Afficher le détail des crédits
478 const creationCredits = document.getElementById("creation-credits");
479 const monthlyCredits = document.getElementById("monthly-credits");
480 const paidCredits = document.getElementById("paid-credits");
481
482 if (creationCredits)
483 creationCredits.textContent = creditsBreakdown.onAccountCreation;
484 if (monthlyCredits)
485 monthlyCredits.textContent = creditsBreakdown.monthlySubscription;
486 if (paidCredits) paidCredits.textContent = creditsBreakdown.paid;
487 }
488