File: /mnt/data/dreamssalon-wp-market/wp-content/themes/dreamsalon/assets/js/dreamsalon-registration.js
/**
* Dream Salon Registration OTP System
* This file handles OTP verification for user registration
*/
(function($) {
'use strict';
/**
* Registration OTP Manager
* @param {Object} config - Configuration object
*/
class RegistrationOTPManager {
constructor(config) {
this.config = config;
this.otpTimer = null;
this.resendTimer = null;
this.otpTimeLeft = config.otpExpirySeconds || 300;
this.resendTimeLeft = config.otpResendSeconds || 60;
this.isOtpVerified = !config.otpEnabled;
this.canResend = false;
this.form = $('#dreamsalon-register-form');
this.init();
}
/**
* Initialize all event handlers
*/
init() {
// Email availability check
this.bindEmailCheck();
// Clear errors on input
this.bindInputEvents();
// OTP related functionality (only if enabled)
if (this.config.otpEnabled) {
this.bindOTPEvents();
}
// Form submission
this.bindFormSubmission();
}
/**
* Show error message
* @param {string} fieldId - Field ID
* @param {string} message - Error message
*/
showError(fieldId, message) {
$('#' + fieldId).html(message).show();
$('#' + fieldId.replace('-error', '')).addClass('field-error');
}
/**
* Clear error message
* @param {string} fieldId - Field ID
*/
clearError(fieldId) {
$('#' + fieldId).html('').hide();
$('#' + fieldId.replace('-error', '')).removeClass('field-error');
}
/**
* Bind input events to clear errors
*/
bindInputEvents() {
$('input').on('input', (e) => {
const fieldName = $(e.target).attr('id');
if (fieldName) {
this.clearError(fieldName + '-error');
}
});
}
/**
* Bind email availability check
*/
bindEmailCheck() {
$('#email').on('blur', (e) => {
const email = $(e.target).val().trim();
const emailCheckMessage = $('#email-check-message');
// Clear previous messages
emailCheckMessage.html('').removeClass('email-available email-taken email-checking');
this.clearError('email-error');
if (!email) return;
// Basic email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) return;
// Show checking message
emailCheckMessage.html('Checking email availability...').addClass('email-checking');
$.ajax({
url: this.config.ajaxUrl,
type: 'POST',
data: {
action: 'check_email_availability',
email: email,
security: this.config.emailCheckNonce
},
success: (response) => {
if (response.success) {
if (response.data.available) {
emailCheckMessage.html('✓ Email is available').addClass('email-available').removeClass('email-taken email-checking');
} else {
emailCheckMessage.html('').addClass('email-taken').removeClass('email-available email-checking');
this.showError('email-error', 'This email is already registered. Please login instead.');
}
} else {
emailCheckMessage.html('Error checking email').addClass('email-taken').removeClass('email-checking');
}
},
error: () => {
emailCheckMessage.html('Error checking email availability').addClass('email-taken').removeClass('email-checking');
}
});
});
// Clear email error specifically
$('#email').on('input', (e) => {
this.clearError('email-error');
this.clearError('otp-status');
$('#email-check-message').html('').removeClass('email-available email-taken email-checking');
});
// Firefox-specific email validation fixes
this.fixFirefoxEmailValidation();
}
/**
* Fix Firefox email validation issues
*/
fixFirefoxEmailValidation() {
// Detect Firefox
const isFirefox = typeof InstallTrigger !== 'undefined' ||
navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if (isFirefox) {
// Fix all form fields for Firefox
this.fixFirefoxFormFields();
}
}
/**
* Fix Firefox validation for all form fields
*/
fixFirefoxFormFields() {
// Firefox-specific styling fixes for all form controls
$('.form-control').css({
'-moz-appearance': 'none',
'appearance': 'none'
});
$('.form-check-input').css({
'-moz-appearance': 'none',
'appearance': 'none'
});
$('.btn').css({
'-moz-appearance': 'none',
'appearance': 'none'
});
// NAME FIELD VALIDATION
$('#name').on('blur', (e) => {
const name = $(e.target).val().trim();
if (!name) {
this.showError('name-error', 'Name is required.');
$(e.target).addClass('field-error');
} else if (name.length < 0) {
this.showError('name-error', 'Fill This Field.');
$(e.target).addClass('field-error');
} else {
this.clearError('name-error');
$(e.target).removeClass('field-error');
}
});
$('#name').on('input', (e) => {
const name = $(e.target).val().trim();
if (name && name.length >= 2) {
this.clearError('name-error');
$(e.target).removeClass('field-error');
}
});
// EMAIL FIELD VALIDATION
$('#email').on('blur', (e) => {
const email = $(e.target).val().trim();
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (email && !emailRegex.test(email)) {
this.showError('email-error', 'Please enter a valid email address.');
$(e.target).addClass('field-error');
} else {
this.clearError('email-error');
$(e.target).removeClass('field-error');
}
});
$('#email').on('input', (e) => {
const email = $(e.target).val().trim();
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (email && emailRegex.test(email)) {
this.clearError('email-error');
$(e.target).removeClass('field-error');
}
});
// PASSWORD FIELD VALIDATION
$('#password').on('blur', (e) => {
const password = $(e.target).val();
if (!password) {
this.showError('password-error', 'Password is required.');
$(e.target).addClass('field-error');
} else if (password.length < 6) {
this.showError('password-error', 'Password must be at least 6 characters long.');
$(e.target).addClass('field-error');
} else {
this.clearError('password-error');
$(e.target).removeClass('field-error');
}
});
$('#password').on('input', (e) => {
const password = $(e.target).val();
if (password && password.length >= 6) {
this.clearError('password-error');
$(e.target).removeClass('field-error');
}
});
// CHECKBOX VALIDATION
$('#agree_terms').on('change', (e) => {
const isChecked = $(e.target).is(':checked');
if (!isChecked) {
this.showError('terms-error', 'You must agree to Terms & Service.');
$(e.target).addClass('field-error');
} else {
this.clearError('terms-error');
$(e.target).removeClass('field-error');
}
});
// FOCUS/BLUR STYLING FOR ALL FIELDS
$('.form-control').on('focus', (e) => {
if (!$(e.target).hasClass('field-error')) {
$(e.target).css({
'border-color': '#86b7fe',
'box-shadow': '0 0 0 0.25rem rgba(13, 110, 253, 0.25)',
'outline': 'none'
});
}
});
$('.form-control').on('blur', (e) => {
if (!$(e.target).hasClass('field-error')) {
$(e.target).css({
'border-color': '#ced4da',
'box-shadow': 'none'
});
}
});
// ENSURE VALIDATION MESSAGES ARE VISIBLE IN FIREFOX
const ensureVisibility = () => {
$('.error-message').each((index, element) => {
const $element = $(element);
if ($element.html()) {
$element.css({
'display': 'block',
'visibility': 'visible',
'opacity': '1'
});
}
});
$('.email-check-message').each((index, element) => {
const $element = $(element);
if ($element.html()) {
$element.css({
'display': 'block',
'visibility': 'visible',
'opacity': '1'
});
}
});
};
// Force visibility check every 100ms
setInterval(ensureVisibility, 100);
// ENHANCED ERROR STATE HANDLING
const originalShowError = this.showError;
this.showError = (fieldId, message) => {
originalShowError.call(this, fieldId, message);
const $field = $('#' + fieldId.replace('-error', ''));
if ($field.length) {
$field.css({
'border-color': '#dc3545',
'box-shadow': '0 0 0 0.25rem rgba(220, 53, 69, 0.25)'
}).addClass('field-error');
}
};
const originalClearError = this.clearError;
this.clearError = (fieldId) => {
originalClearError.call(this, fieldId);
const $field = $('#' + fieldId.replace('-error', ''));
if ($field.length) {
$field.css({
'border-color': '#ced4da',
'box-shadow': 'none'
}).removeClass('field-error');
}
};
}
/**
* Bind OTP related events
*/
bindOTPEvents() {
// Send OTP
$('#send_otp').on('click', (e) => {
this.handleSendOTP(e);
});
// Resend OTP
$('#resend_otp_link').on('click', (e) => {
this.handleResendOTP(e);
});
// Verify OTP
$('#verify-otp').on('click', (e) => {
this.handleVerifyOTP(e);
});
// Auto-verify when 6 digits entered
$('#otp').on('input', (e) => {
const otp = $(e.target).val().trim();
if (otp.length === 6 && /^\d+$/.test(otp) && !this.isOtpVerified) {
$('#verify-otp').click();
}
});
// Email change handler
$('#email').on('change', (e) => {
this.handleEmailChange(e);
});
}
/**
* Handle send OTP button click
*/
/**
* Handle resend OTP
*/
/**
* Handle OTP verification
*/
/**
* Handle email change
*/
handleEmailChange(e) {
// Reset OTP verification if email changes
if (this.isOtpVerified) {
this.isOtpVerified = false;
$('#register-btn').prop('disabled', true);
$('#verify-status').html('');
$('#otp').val('').prop('readonly', false);
$('#verify-otp').text('Verify').prop('disabled', false);
$('#send_otp').prop('disabled', false);
$('#resend_otp_link').show().prop('disabled', false).css('pointer-events', 'auto');
$('#otp-section').slideUp(300, () => {
$('#registration-fields').slideDown(300);
});
$('#auto-submit-message').hide();
$('#submit-section').show();
$('#resend-timer').hide();
clearInterval(this.otpTimer);
clearInterval(this.resendTimer);
}
}
/**
* Validate registration fields
*/
validateRegistrationFields(name, email, password, agreeTerms) {
let hasErrors = false;
// Validate name
if (!name) {
this.showError('name-error', 'Name is required.');
hasErrors = true;
}
// Validate email
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!email) {
this.showError('email-error', 'Email is required.');
hasErrors = true;
} else if (!emailRegex.test(email)) {
this.showError('email-error', 'Please enter a valid email address.');
hasErrors = true;
}
// Check if email is already registered
const emailCheckMessage = $('#email-check-message');
if (emailCheckMessage.hasClass('email-taken')) {
this.showError('email-error', 'This email is already registered. Please login instead.');
hasErrors = true;
}
// Validate password
if (!password) {
this.showError('password-error', 'Password is required.');
hasErrors = true;
} else if (password.length < 6) {
this.showError('password-error', 'Password must be at least 6 characters long.');
hasErrors = true;
}
// Validate terms
if (!agreeTerms) {
this.showError('terms-error', 'You must agree to the Terms & Service.');
hasErrors = true;
}
if (hasErrors) {
// Scroll to first error
$('html, body').animate({
scrollTop: $('.error-message:visible').first().offset().top - 100
}, 500);
return false;
}
return true;
}
/**
* Start OTP expiration timer
*/
/**
* Start resend timer
*/
/**
* Update resend timer display
*/
/**
* Bind form submission
*/
/**
* Validate form before submission
*/
validateFormSubmission(e) {
let hasErrors = false;
// Clear all errors first
this.clearError('name-error');
this.clearError('email-error');
this.clearError('password-error');
this.clearError('terms-error');
if (this.config.otpEnabled) {
this.clearError('otp-error');
}
// Get field values
const name = $('#name').val().trim();
const email = $('#email').val().trim();
const password = $('#password').val();
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const emailCheckMessage = $('#email-check-message');
// Validate name
if (!name) {
this.showError('name-error', 'Name is required.');
hasErrors = true;
}
// Validate email
if (!email) {
this.showError('email-error', 'Email is required.');
hasErrors = true;
} else if (!emailRegex.test(email)) {
this.showError('email-error', 'Please enter a valid email address.');
hasErrors = true;
}
// Check if email is already registered
if (emailCheckMessage.hasClass('email-taken')) {
this.showError('email-error', 'This email is already registered. Please login instead.');
hasErrors = true;
}
// Validate password
if (!password) {
this.showError('password-error', 'Password is required.');
hasErrors = true;
} else if (password.length < 6) {
this.showError('password-error', 'Password must be at least 6 characters long.');
hasErrors = true;
}
// Validate terms
if (!$('#agree_terms').is(':checked')) {
this.showError('terms-error', 'You must agree to the Terms & Service.');
hasErrors = true;
}
// Validate OTP only if enabled
if (this.config.otpEnabled && !this.isOtpVerified) {
this.showError('otp-error', 'Please verify your OTP before submitting.');
hasErrors = true;
}
if (hasErrors) {
e.preventDefault();
// Scroll to first error
$('html, body').animate({
scrollTop: $('.error-message:visible').first().offset().top - 100
}, 500);
return false;
}
// Show loading state
const submitBtn = $('#register-btn');
const originalText = submitBtn.text();
submitBtn.prop('disabled', true).text('Creating Account...');
// Re-enable after 3 seconds if still on page (fallback)
setTimeout(() => {
if ($('#register-btn').text() === 'Creating Account...') {
submitBtn.prop('disabled', false).text(originalText);
}
}, 3000);
return true;
}
/**
* Show success message
*/
showSuccessMessage(message) {
// Remove any existing success messages
$('.success-alert').remove();
// Create success alert
const successAlert = $('<div class="alert alert-success success-alert text-center mb-4">' + message + '</div>');
successAlert.hide().insertBefore('#dreamsalon-register-form').fadeIn(300);
// Auto-hide after 5 seconds
setTimeout(() => {
successAlert.fadeOut(300, () => {
$(this).remove();
});
}, 5000);
}
}
/**
* Initialize Registration OTP Manager when DOM is ready
*/
$(document).ready(() => {
// Check if registration form exists on the page
if ($('#dreamsalon-register-form').length) {
// Get configuration from PHP variables (these should be set in your PHP template)
const config = {
ajaxUrl: dreamsalonRegistration.ajaxUrl || '/wp-admin/admin-ajax.php',
otpEnabled: dreamsalonRegistration.otpEnabled || false,
otpExpirySeconds: parseInt(dreamsalonRegistration.otpExpirySeconds) || 300,
otpResendSeconds: parseInt(dreamsalonRegistration.otpResendSeconds) || 60,
otpNonce: dreamsalonRegistration.otpNonce || '',
emailCheckNonce: dreamsalonRegistration.emailCheckNonce || ''
};
// Initialize the OTP manager
new RegistrationOTPManager(config);
}
});
})(jQuery);