"use strict"; // Class definition var KTSignupGeneral = function () { // Elements var form; var submitButton; var validator; var passwordMeter; // Handle form var handleForm = function (e) { // Init form validation rules. For more info check the FormValidation plugin's official documentation:https://formvalidation.io/ validator = FormValidation.formValidation( form, { fields: { 'firstname': { validators: { notEmpty: { message: 'First Name is required' } } }, 'lastname': { validators: { notEmpty: { message: 'Last Name is required' } } }, 'email': { validators: { notEmpty: { message: 'Email address is required' }, regexp: { regexp: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Please enter a valid email address', } } }, 'password': { validators: { notEmpty: { message: 'Password is required' }, callback: { message: 'Password must be at least 8 characters with a mix of letters, numbers & symbols', callback: function (input) { if (input.value.length > 0) { return validatePassword(); } } } } }, 'confirm-password': { validators: { notEmpty: { message: 'Password confirmation is required' }, identical: { compare: function () { return form.querySelector('[name="password"]').value; }, message: 'Passwords do not match' } } }, 'toc': { validators: { notEmpty: { message: 'You must accept the terms and conditions' } } } }, plugins: { trigger: new FormValidation.plugins.Trigger({ event: { password: false } }), bootstrap: new FormValidation.plugins.Bootstrap5({ rowSelector: '.fv-row', eleInvalidClass: '', // comment to enable invalid state icons eleValidClass: '' // comment to enable valid state icons }) } } ); // Handle form submit submitButton.addEventListener('click', function (e) { e.preventDefault(); console.log('Form submit clicked - regular form handler'); // Validate all fields including password confirmation validator.revalidateField('password'); validator.revalidateField('confirm-password'); validator.revalidateField('email'); validator.revalidateField('firstname'); validator.revalidateField('lastname'); validator.revalidateField('toc'); // Debug: Check form values before validation console.log('Form values before validation:'); console.log('- First name:', form.querySelector('[name="firstname"]').value); console.log('- Last name:', form.querySelector('[name="lastname"]').value); console.log('- Email:', form.querySelector('[name="email"]').value); console.log('- Password:', form.querySelector('[name="password"]').value); console.log('- Confirm password:', form.querySelector('[name="confirm-password"]').value); console.log('- Terms accepted:', form.querySelector('[name="toc"]').checked); validator.validate().then(function (status) { console.log('Validation status:', status); if (status == 'Valid') { console.log('Form is valid, submitting...'); // Show loading indication submitButton.setAttribute('data-kt-indicator', 'on'); // Disable button to avoid multiple click submitButton.disabled = true; // Submit the form to the server form.submit(); } else { console.log('Form validation failed'); // Show error popup. For more info check the plugin's official documentation: https://sweetalert2.github.io/ Swal.fire({ text: "Please fill in all required fields correctly.", icon: "error", buttonsStyling: false, confirmButtonText: "Ok, got it!", customClass: { confirmButton: "btn btn-primary" } }); } }); }); // Handle password input form.querySelector('input[name="password"]').addEventListener('input', function () { console.log('Password field changed:', this.value.length); if (this.value.length > 0) { validator.updateFieldStatus('password', 'NotValidated'); } // Also revalidate confirm password when password changes var confirmPassword = form.querySelector('input[name="confirm-password"]'); if (confirmPassword && confirmPassword.value.length > 0) { console.log('Revalidating confirm password because password changed'); validator.revalidateField('confirm-password'); } }); // Handle confirm password input var confirmPasswordField = form.querySelector('input[name="confirm-password"]'); if (confirmPasswordField) { confirmPasswordField.addEventListener('input', function () { console.log('Confirm password field changed:', this.value.length); if (this.value.length > 0) { validator.revalidateField('confirm-password'); } }); confirmPasswordField.addEventListener('blur', function () { console.log('Confirm password field lost focus, validating...'); validator.revalidateField('confirm-password'); }); } } // Handle form ajax var handleFormAjax = function (e) { // Init form validation rules. For more info check the FormValidation plugin's official documentation:https://formvalidation.io/ validator = FormValidation.formValidation( form, { fields: { 'name': { validators: { notEmpty: { message: 'Name is required' } } }, 'email': { validators: { notEmpty: { message: 'Email address is required' }, regexp: { regexp: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Please enter a valid email address', } } }, 'password': { validators: { notEmpty: { message: 'Password is required' }, callback: { message: 'Password must be at least 8 characters with a mix of letters, numbers & symbols', callback: function (input) { if (input.value.length > 0) { return validatePassword(); } } } } }, 'password_confirmation': { validators: { notEmpty: { message: 'The password confirmation is required' }, identical: { compare: function () { return form.querySelector('[name="password"]').value; }, message: 'The password and its confirm are not the same' } } }, 'toc': { validators: { notEmpty: { message: 'You must accept the terms and conditions' } } } }, plugins: { trigger: new FormValidation.plugins.Trigger({ event: { password: false } }), bootstrap: new FormValidation.plugins.Bootstrap5({ rowSelector: '.fv-row', eleInvalidClass: '', // comment to enable invalid state icons eleValidClass: '' // comment to enable valid state icons }) } } ); // Handle form submit submitButton.addEventListener('click', function (e) { e.preventDefault(); console.log('Form submit clicked - AJAX form handler'); // Validate all fields including password confirmation validator.revalidateField('password'); validator.revalidateField('confirm-password'); validator.revalidateField('email'); validator.revalidateField('firstname'); validator.revalidateField('lastname'); validator.revalidateField('toc'); // Debug: Check form values before validation console.log('AJAX Form values before validation:'); console.log('- First name:', form.querySelector('[name="firstname"]').value); console.log('- Last name:', form.querySelector('[name="lastname"]').value); console.log('- Email:', form.querySelector('[name="email"]').value); console.log('- Password:', form.querySelector('[name="password"]').value); console.log('- Confirm password:', form.querySelector('[name="confirm-password"]').value); console.log('- Terms accepted:', form.querySelector('[name="toc"]').checked); validator.validate().then(function (status) { console.log('AJAX Validation status:', status); if (status == 'Valid') { console.log('AJAX Form is valid, submitting...'); // Show loading indication submitButton.setAttribute('data-kt-indicator', 'on'); // Disable button to avoid multiple click submitButton.disabled = true; // Check axios library docs: https://axios-http.com/docs/intro axios.post(submitButton.closest('form').getAttribute('action'), new FormData(form)).then(function (response) { if (response) { form.reset(); const redirectUrl = form.getAttribute('data-kt-redirect-url'); if (redirectUrl) { location.href = redirectUrl; } } else { // Show error popup. For more info check the plugin's official documentation: https://sweetalert2.github.io/ Swal.fire({ text: "Sorry, looks like there are some errors detected, please try again.", icon: "error", buttonsStyling: false, confirmButtonText: "Ok, got it!", customClass: { confirmButton: "btn btn-primary" } }); } }).catch(function (error) { Swal.fire({ text: "Sorry, looks like there are some errors detected, please try again.", icon: "error", buttonsStyling: false, confirmButtonText: "Ok, got it!", customClass: { confirmButton: "btn btn-primary" } }); }).then(() => { // Hide loading indication submitButton.removeAttribute('data-kt-indicator'); // Enable button submitButton.disabled = false; }); } else { console.log('AJAX Form validation failed'); // Show error popup. For more info check the plugin's official documentation: https://sweetalert2.github.io/ Swal.fire({ text: "Please fill in all required fields correctly.", icon: "error", buttonsStyling: false, confirmButtonText: "Ok, got it!", customClass: { confirmButton: "btn btn-primary" } }); } }); }); // Handle password input form.querySelector('input[name="password"]').addEventListener('input', function () { console.log('AJAX Password field changed:', this.value.length); if (this.value.length > 0) { validator.updateFieldStatus('password', 'NotValidated'); } // Also revalidate confirm password when password changes var confirmPassword = form.querySelector('input[name="confirm-password"]'); if (confirmPassword && confirmPassword.value.length > 0) { console.log('AJAX Revalidating confirm password because password changed'); validator.revalidateField('confirm-password'); } }); // Handle confirm password input var confirmPasswordField = form.querySelector('input[name="confirm-password"]'); if (confirmPasswordField) { confirmPasswordField.addEventListener('input', function () { console.log('AJAX Confirm password field changed:', this.value.length); if (this.value.length > 0) { validator.revalidateField('confirm-password'); } }); confirmPasswordField.addEventListener('blur', function () { console.log('AJAX Confirm password field lost focus, validating...'); validator.revalidateField('confirm-password'); }); } } // Password input validation var validatePassword = function () { // Check if password meter exists and is properly initialized if (!passwordMeter) { console.warn('Password meter not initialized, falling back to basic validation'); var password = form.querySelector('input[name="password"]').value; // Basic password validation as fallback var hasMinLength = password.length >= 8; var hasUppercase = /[A-Z]/.test(password); var hasLowercase = /[a-z]/.test(password); var hasDigit = /[0-9]/.test(password); var hasSpecialChar = /[~`!#@$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/.test(password); // Require at least 3 out of 4 criteria plus minimum length var criteriaCount = [hasUppercase, hasLowercase, hasDigit, hasSpecialChar].filter(Boolean).length; return hasMinLength && criteriaCount >= 3; } try { var score = passwordMeter.getScore(); console.log('Password meter score:', score); return score > 50; } catch (error) { console.error('Error getting password meter score:', error); // Fallback to basic validation var password = form.querySelector('input[name="password"]').value; var hasMinLength = password.length >= 8; var hasUppercase = /[A-Z]/.test(password); var hasLowercase = /[a-z]/.test(password); var hasDigit = /[0-9]/.test(password); var hasSpecialChar = /[~`!#@$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/.test(password); var criteriaCount = [hasUppercase, hasLowercase, hasDigit, hasSpecialChar].filter(Boolean).length; return hasMinLength && criteriaCount >= 3; } } var isValidUrl = function(url) { try { // If URL is empty or null, return false if (!url || url.trim() === '') { return false; } // Check if it's a relative URL (starts with /) if (url.startsWith('/')) { return true; } // Check if it's a full URL new URL(url); return true; } catch (e) { return false; } } // Public functions return { // Initialization init: function () { // Elements form = document.querySelector('#kt_sign_up_form'); submitButton = document.querySelector('#kt_sign_up_submit'); console.log('Form found:', form); console.log('Submit button found:', submitButton); // Debug: Check form elements if (form) { console.log('Form elements found:'); console.log('- First name:', form.querySelector('[name="firstname"]')); console.log('- Last name:', form.querySelector('[name="lastname"]')); console.log('- Email:', form.querySelector('[name="email"]')); console.log('- Password:', form.querySelector('[name="password"]')); console.log('- Confirm password:', form.querySelector('[name="confirm-password"]')); console.log('- Terms checkbox:', form.querySelector('[name="toc"]')); } if (form && submitButton) { // Initialize password meter var passwordMeterElement = form.querySelector('[data-kt-password-meter="true"]'); console.log('Password meter element found:', passwordMeterElement); if (passwordMeterElement) { // Wait a bit for other scripts to load setTimeout(function() { try { passwordMeter = KTPasswordMeter.getInstance(passwordMeterElement); if (!passwordMeter) { console.log('Password meter not found, creating new instance...'); passwordMeter = new KTPasswordMeter(passwordMeterElement); } console.log('Password meter initialized:', passwordMeter); // Ensure password meter responds to input var passwordInput = form.querySelector('input[name="password"]'); if (passwordInput && passwordMeter) { passwordInput.addEventListener('input', function() { // Trigger password meter check if (passwordMeter.check) { passwordMeter.check(); } }); } } catch (error) { console.error('Error initializing password meter:', error); passwordMeter = null; } // Initialize form handlers after password meter is set up var formAction = form.getAttribute('action'); console.log('Form action:', formAction); console.log('Is valid URL:', isValidUrl(formAction)); // For signup, always use regular form submission to allow backend redirect if (formAction && formAction.includes('signup')) { console.log('Using regular form handler for signup'); handleForm(); } else if (formAction && isValidUrl(formAction)) { console.log('Using AJAX form handler'); handleFormAjax(); } else { console.log('Using regular form handler'); handleForm(); } }, 100); } else { console.warn('Password meter element not found, proceeding without it'); passwordMeter = null; var formAction = form.getAttribute('action'); console.log('Form action (no meter):', formAction); console.log('Is valid URL (no meter):', isValidUrl(formAction)); if (formAction && formAction.includes('signup')) { console.log('Using regular form handler for signup'); handleForm(); } else if (formAction && isValidUrl(formAction)) { console.log('Using AJAX form handler'); handleFormAjax(); } else { console.log('Using regular form handler'); handleForm(); } } } else { console.error('Form or submit button not found!'); } } }; }(); // Live email availability checking (independent of form validation) function initEmailCheck() { console.log('Initializing email check...'); var emailField = document.getElementById('signup_email'); var emailMessageDiv = document.getElementById('email-check-message'); var emailCheckTimeout; console.log('Email field found:', emailField); console.log('Message div found:', emailMessageDiv); if (emailField && emailMessageDiv) { console.log('Adding event listener to email field'); emailField.addEventListener('input', function() { console.log('Email input event triggered, value:', this.value); var email = this.value.trim(); // Clear previous timeout if (emailCheckTimeout) { clearTimeout(emailCheckTimeout); } // Hide message if email is empty if (!email) { emailMessageDiv.style.display = 'none'; return; } // Basic email format check var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { emailMessageDiv.style.display = 'none'; return; } // Debounce the API call (wait 500ms after user stops typing) emailCheckTimeout = setTimeout(function() { checkEmailAvailability(email); }, 500); }); } else { console.error('Email field or message div not found!'); console.error('Email field:', emailField); console.error('Message div:', emailMessageDiv); } function checkEmailAvailability(email) { console.log('Checking email availability for:', email); fetch('http://localhost:5000/check-email', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email: email }) }) .then(response => { console.log('Response status:', response.status); return response.json(); }) .then(data => { console.log('Response data:', data); if (data.available) { emailMessageDiv.innerHTML = '