function validateEmailSendOTP() { var emailInput = $('#email'); var btnSendOTP = $('#sendOTP'); var otpInput = $('#Otp'); var modal = $('#sendOTPModal'); const emailInputed = document.getElementById('email'); emailInputed.addEventListener('input', removeErrorClass); function removeErrorClass() { if (this.value.trim() !== '') { this.classList.remove('error-input'); } } const email = emailInputed.value; if (!email) { showToast('warning', 'Please fill the required field!', 'failed!', 4000); emailInputed.classList.add('error-input'); return; } else if (!/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(email)) { showToast('warning', 'Invalid email address, please double-check!', 'failed!', 4000); return; } // Create the overlay div element var overlay = $('
'); // Create the loader spinner element var loader = $(''); // Append the overlay and loader to the modal modal.append(overlay); modal.append(loader); $.ajax({ url: endpoint.SendOTPByEmail, type: 'POST', data: { email }, beforeSend: function () { overlay.show(); loader.show(); }, complete: function () { overlay.hide(); loader.hide(); }, success: function (response) { if (response.success) { $('#btnSendOTP').prop('disabled', false); emailInput.prop('readonly', true); otpInput.prop('readonly', false); $('#sendOTP').prop('disabled', true); // Set the countdown duration in seconds (3 minutes = 180 seconds) var countdownDuration = 180; var countdownInterval = setInterval(function () { btnSendOTP.text('Resend OTP (' + countdownDuration + 's)'); countdownDuration--; if (countdownDuration < 0) { $('#sendOTP').prop('disabled', false); btnSendOTP.text('Resend OTP'); clearInterval(countdownInterval); } }, 1000); showToast('success', "Success!: Please check your email to get the OTP code", 'success!', 4000); } else { showToast('warning', 'Email is not valid, please double-check!', 'failed!', 4000); } }, error: function (xhr, error, thrown) { console.log('Error:', error); console.log('Details:', thrown); console.log('xhr Details:', xhr); showToast('warning', 'Email is not valid, please double-check!', 'failed!', 4000); // Hide the overlay and loader manually in case of an error overlay.hide(); loader.hide(); } }); } function clearElements() { document.getElementById("NewPassword").value = ""; document.getElementById("emailForgotPassword").value = ""; document.getElementById("ConfirmPassword").value = ""; document.getElementById("sendOTP").value = ""; document.getElementById("email").value = ""; } function validateOTP() { var loader = $('#overlay, #loader'); const email = document.getElementById('email').value; var emailInput = document.getElementById("emailForgotPassword"); const otpInput = document.getElementById('Otp'); otpInput.addEventListener('input', function () { if (otpInput.value.trim() !== '') { otpInput.classList.remove('error-input'); } }); const otp = otpInput.value; if (!otp) { showToast('warning', 'Please fill the required field!', 'failed!', 4000); otpInput.classList.add('error-input'); return; } else if (otp.length !== 8) { showToast('warning', 'OTP is invalid, please double-check!', 'OTP failed!', 4000); return; } $.ajax({ url: endpoint.ValidateOTP, type: 'POST', data: { email, otp }, beforeSend: function () { loader.show(); }, complete: function () { loader.hide(); }, success: function (response) { if (response.success) { $('#sendOTPModal').modal('hide'); $('#forgotPasswordModal').modal('show'); emailInput.value = email; } else { showToast('error', 'Email or OTP is invalid, please double-check!', 'OTP failed!', 4000); } }, error: function (xhr, error, thrown) { console.log('Error:', error); console.log('Details:', thrown); console.log('xhr Details:', xhr); showToast('error', 'Email or OTP is invalid, please double-check!', 'OTP failed!', 4000); } }); } function refreshCaptcha() { const captchaImage = document.getElementById('captchaImage'); captchaImage.src = `/Home/GetCaptcha?ts=${new Date().getTime()}`; // Cache-busting query } // Password visibility toggle function togglePasswordVisibility() { const input = document.getElementById('PasswordLogin'); const icon = document.getElementById('togglePassword'); const isHidden = input.type === 'password'; input.type = isHidden ? 'text' : 'password'; icon.classList.toggle('fa-eye', !isHidden); icon.classList.toggle('fa-eye-slash', isHidden); icon.style.color = isHidden ? '#00897b' : '#9ca3af'; } // Call this at the START of your login() function function setLoginLoading(loading) { const btn = document.getElementById('BtnLogin'); const icon = document.getElementById('btnIcon'); const text = document.getElementById('btnText'); if (loading) { btn.disabled = true; icon.className = ''; // remove fa classes icon.innerHTML = ''; text.textContent = 'Signing in...'; } else { btn.disabled = false; icon.innerHTML = ''; icon.className = 'fas fa-sign-in-alt'; icon.style.marginRight = '8px'; text.textContent = 'Sign In'; } } function validateCaptCha(captchaCode) { return new Promise((resolve, reject) => { var loader = $('#overlay, #loader'); $.ajax({ url: endpoint.ValidateCaptcha, type: 'POST', data: { captchaCode }, beforeSend: function () { loader.show(); }, complete: function () { loader.hide(); }, success: function (response) { if (response.success) { resolve(true); } else { showToast('error', 'Invalid CAPTCHA. Please try again!','Login failed!',4000); reject(false); setLoginLoading(false); } }, error: errorHandler }); }); } // Function to remove error styling function removeErrClass(event) { const input = event.target; const wrapper = input.closest('.login-input-wrapper'); // Remove error class from input input.classList.remove('error-input'); // Remove error class from wrapper (for icon styling) if (wrapper) { wrapper.classList.remove('error'); } // Remove any error messages (optional) const errorMessage = wrapper?.nextElementSibling; if (errorMessage && errorMessage.classList.contains('login-error-message')) { errorMessage.remove(); } } // Function to add error styling function addErrorClass(input, message = '') { const wrapper = input.closest('.login-input-wrapper'); // Add error class to input input.classList.add('error-input'); // Add error class to wrapper (for icon styling) if (wrapper) { wrapper.classList.add('error'); } // Optional: Add error message if (message && wrapper) { // Remove existing error message first const existingError = wrapper.nextElementSibling; if (existingError && existingError.classList.contains('login-error-message')) { existingError.remove(); } // Create and insert new error message const errorDiv = document.createElement('div'); errorDiv.className = 'login-error-message'; errorDiv.innerHTML = ` ${message}`; wrapper.parentNode.insertBefore(errorDiv, wrapper.nextSibling); } } function login() { var loader = $('#overlay, #loader').css('z-index', 1090); setLoginLoading(true); const userNameInput = document.getElementById('UserNameLogin'); const passwordInput = document.getElementById('PasswordLogin'); const captchaCodeInput = document.getElementById('captchaCode'); // Clear any existing errors first removeErrClass({ target: userNameInput }); removeErrClass({ target: passwordInput }); removeErrClass({ target: captchaCodeInput }); // Add event listeners for real-time error removal userNameInput.addEventListener('input', removeErrClass); passwordInput.addEventListener('input', removeErrClass); captchaCodeInput.addEventListener('input', removeErrClass); const captchaCode = captchaCodeInput.value.trim(); const UserName = userNameInput.value.trim(); const Password = passwordInput.value.trim(); let hasErrors = false; // Validate each field and add appropriate error styling if (!UserName) { addErrorClass(userNameInput, 'Username is required'); hasErrors = true; setLoginLoading(false); } if (!Password) { addErrorClass(passwordInput, 'Password is required'); hasErrors = true; setLoginLoading(false); } if (!captchaCode) { addErrorClass(captchaCodeInput, 'Security verification is required'); hasErrors = true; setLoginLoading(false); } // If there are validation errors, show toast and return if (hasErrors) { showToast('warning', 'Please fill all required fields!', 'Login failed!', 4000); setLoginLoading(false); // Focus on the first error field if (!UserName) { userNameInput.focus(); } else if (!Password) { passwordInput.focus(); } else if (!captchaCode) { captchaCodeInput.focus(); } return; } // Proceed with validation and login validateCaptCha(captchaCode) .then(() => { $.ajax({ url: endpoint.Login, type: 'POST', data: { UserName, Password }, beforeSend: function () { loader.show(); }, complete: function () { loader.hide(); }, success: function (response) { let parsedMessage = null; if (response && response.responseMessage) { try { parsedMessage = JSON.parse(response.responseMessage); } catch (e) { console.error("Failed to parse responseMessage", e); } } if (response && response.success === true) { window.location.href = '/' + response.responseController + '/' + response.responseAction; } else if (response && response.success === false) { const errorMessage = parsedMessage?.message || "Login failed."; showToast('error', errorMessage, 'Login failed!', 4000); // Highlight inputs if credential-related error if (errorMessage.toLowerCase().includes('username') || errorMessage.toLowerCase().includes('credential')) { addErrorClass(userNameInput); addErrorClass(passwordInput); } } setLoginLoading(false); }, error: function (xhr, status, error) { errorHandler(xhr, status, error); addErrorClass(userNameInput); addErrorClass(passwordInput); setLoginLoading(false); } }); }) .catch(() => { showToast('error', 'Login aborted due to invalid CAPTCHA.', 'Login failed!', 4000); addErrorClass(captchaCodeInput, 'Invalid security code'); captchaCodeInput.focus(); }); } document.addEventListener('keydown', function (event) { if (event.key === 'Enter') { event.preventDefault(); login(); } }); function showForgotPasswordModal() { $('#forgotPasswordModal').modal('show'); } function changePassword() { var loader = $('#overlay, #loader'); const email = document.getElementById('email').value; const newPasswordInput = document.getElementById('NewPassword'); const confirmPasswordInput = document.getElementById("ConfirmPassword"); const oTP = document.getElementById("Otp").value; // Add an event listener for the input event newPasswordInput.addEventListener('input', removeErrorClass); confirmPasswordInput.addEventListener('input', removeErrorClass); // Function to remove the 'error-input' class when the input is not empty function removeErrorClass() { if (this.value.trim() !== '') { this.classList.remove('error-input'); } } // Check if UserName or Password is empty or null const newPassword = newPasswordInput.value; const confirmPassword = confirmPasswordInput.value; if (newPassword !== confirmPassword) { alert('New password and Confirm password not match!'); // Make the input fields red by adding a CSS class if (!newPassword) { newPasswordInput.classList.add('error-input'); } if (!confirmPassword) { confirmPasswordInput.classList.add('error-input'); } return; } // Check if UserName or Password is empty or null if (!newPassword || !confirmPassword) { alert('Please fill the required fields!'); // Make the input fields red by adding a CSS class if (!newPassword) { newPasswordInput.classList.add('error-input'); } if (!confirmPassword) { confirmPasswordInput.classList.add('error-input'); } return; } //console.log('OTP Value: ' + oTP); $.ajax({ url: '/Account/ChangePassword', type: 'PUT', data: { email, newPassword, oTP }, beforeSend: function () { loader.show(); }, complete: function () { loader.hide(); }, success: function (response) { // console.log('Response from api: ' + response.success) if (response.success) { alert("Your password reset successfully!"); $('#forgotPasswordModal').modal('hide'); loader.hide(); clearElements(); } else { // console.log('response message: ' + response.responseMessage); // If email is not valid, show an alert alert("Error: " + response.responseMessage); } }, error: function (xhr, error, thrown) { console.log('Error:', error); console.log('Details:', thrown); console.log('xhr Details:', xhr); // If email is not valid, show an alert alert("Email or OTP is invalid, please double-check!"); } }); } async function forGotPassword() { const email = document.getElementById('email').value; try { const response = await fetch('https://lloydwebapi.lloydlab.com:2021/api/account/RequestResetPassword', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email: email, }), }); if (response.ok) { const result = await response.json(); alert(result.message); // Show a success message // Optionally close the modal or do other actions } else { const errorResult = await response.json(); alert(`Error: ${errorResult.message}`); } } catch (error) { console.error('Error:', error); } }