upskill-event-manager/assets/js/hvac-registration.js
Ben bb3441c0e6 feat: Complete TEC integration with mobile fixes and comprehensive testing
- Added mobile navigation fix CSS to resolve overlapping elements
- Created TEC integration pages (create, edit, my events)
- Implemented comprehensive Playwright E2E test suites
- Fixed mobile navigation conflicts with z-index management
- Added test runners with detailed reporting
- Achieved 70% test success rate (100% on core features)
- Page load performance optimized to 3.8 seconds
- Cross-browser compatibility verified

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-18 07:07:06 -03:00

445 lines
No EOL
18 KiB
JavaScript

jQuery(document).ready(function($) {
const $countrySelect = $('#user_country');
const $stateSelect = $('#user_state');
const $stateOtherInput = $('#user_state_other');
const $registrationForm = $('#hvac-registration-form');
// Headquarters fields
const $hqCountrySelect = $('#org_headquarters_country');
const $hqStateSelect = $('#org_headquarters_state');
const $hqStateOtherInput = $('#org_headquarters_state_other');
// Venue fields
const $createVenue = $('input[name="create_venue"]');
const $venueDetails = $('#venue-details');
const $venueName = $('#venue_name');
const $businessName = $('#business_name');
const $userCity = $('#user_city');
const $venuePhone = $('#venue_phone');
const $venueWebsite = $('#venue_website');
const $businessPhone = $('#business_phone');
const $businessWebsite = $('#business_website');
// Form validation helpers
function showFieldError(fieldId, message) {
const $field = $('#' + fieldId);
const $existingError = $field.siblings('.error-message');
if ($existingError.length) {
$existingError.text(message);
} else {
$field.after('<p class="error-message" id="' + fieldId + '_error">' + message + '</p>');
}
$field.addClass('error');
}
function clearFieldError(fieldId) {
const $field = $('#' + fieldId);
$field.siblings('.error-message').remove();
// Use jQuery compatibility fix
if (typeof window.HVACjQuery !== 'undefined') {
window.HVACjQuery.safeRemoveClass($field, 'error');
} else {
try {
$field.removeClass('error');
} catch (error) {
// Fallback to vanilla JavaScript
if ($field[0] && $field[0].classList) {
$field[0].classList.remove('error');
}
}
}
}
// Real-time email validation
$('#user_email').on('blur', function() {
const email = $(this).val();
if (email && !isValidEmail(email)) {
showFieldError('user_email', 'Please enter a valid email address.');
} else {
clearFieldError('user_email');
}
});
$('#business_email').on('blur', function() {
const email = $(this).val();
if (email && !isValidEmail(email)) {
showFieldError('business_email', 'Please enter a valid business email address.');
} else {
clearFieldError('business_email');
}
});
function isValidEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}
// Real-time password validation
$('#user_pass').on('input blur', function() {
const password = $(this).val();
if (password) {
const errors = [];
if (password.length < 8) {
errors.push('at least 8 characters');
}
if (!/[A-Z]/.test(password)) {
errors.push('one uppercase letter');
}
if (!/[a-z]/.test(password)) {
errors.push('one lowercase letter');
}
if (!/[0-9]/.test(password)) {
errors.push('one number');
}
if (errors.length > 0) {
showFieldError('user_pass', 'Password must contain ' + errors.join(', ') + '.');
} else {
clearFieldError('user_pass');
// Check confirm password if it has a value
const confirmPass = $('#confirm_password').val();
if (confirmPass) {
$('#confirm_password').trigger('blur');
}
}
}
});
// Confirm password validation
$('#confirm_password').on('blur', function() {
const password = $('#user_pass').val();
const confirmPassword = $(this).val();
if (confirmPassword && password !== confirmPassword) {
showFieldError('confirm_password', 'Passwords do not match.');
} else {
clearFieldError('confirm_password');
}
});
// URL validation for optional fields
function isValidURL(url) {
try {
new URL(url);
return true;
} catch (_) {
return false;
}
}
$('#user_url, #user_linkedin, #business_website, #venue_website').on('blur', function() {
const url = $(this).val();
const fieldId = $(this).attr('id');
if (url && !isValidURL(url)) {
const fieldName = fieldId === 'user_url' ? 'personal website' :
fieldId === 'user_linkedin' ? 'LinkedIn profile' :
fieldId === 'business_website' ? 'organization website' :
'venue website';
showFieldError(fieldId, 'Please enter a valid URL for your ' + fieldName + '.');
} else {
clearFieldError(fieldId);
}
});
// Handle venue creation toggle
$createVenue.on('change', function() {
if ($(this).val() === 'Yes') {
$venueDetails.slideDown();
// Auto-populate venue name if empty
updateVenueName();
// Auto-populate venue phone and website
if (!$venuePhone.val() && $businessPhone.val()) {
$venuePhone.val($businessPhone.val());
}
if (!$venueWebsite.val() && $businessWebsite.val()) {
$venueWebsite.val($businessWebsite.val());
}
} else {
$venueDetails.slideUp();
}
});
// Auto-populate venue name
function updateVenueName() {
if (!$venueName.val()) {
const businessName = $businessName.val();
const city = $userCity.val();
if (businessName && city) {
$venueName.val(businessName + ' of ' + city);
} else if (businessName) {
$venueName.val(businessName + ' Training Venue');
}
}
}
// Update venue name when business name or city changes
$businessName.on('blur', updateVenueName);
$userCity.on('blur', updateVenueName);
// Copy organization info to venue fields
$businessPhone.on('blur', function() {
if (!$venuePhone.val() && $(this).val()) {
$venuePhone.val($(this).val());
}
});
$businessWebsite.on('blur', function() {
if (!$venueWebsite.val() && $(this).val()) {
$venueWebsite.val($(this).val());
}
});
// Form submission validation
$registrationForm.on('submit', function(e) {
let hasErrors = false;
const errors = [];
// Check required fields
const requiredFields = [
{ id: 'user_email', name: 'Email' },
{ id: 'user_pass', name: 'Password' },
{ id: 'confirm_password', name: 'Confirm Password' },
{ id: 'first_name', name: 'First Name' },
{ id: 'last_name', name: 'Last Name' },
{ id: 'display_name', name: 'Display Name' },
{ id: 'description', name: 'Biographical Info' },
{ id: 'business_name', name: 'Organization Name' },
{ id: 'business_phone', name: 'Organization Phone' },
{ id: 'business_email', name: 'Organization Email' },
{ id: 'business_description', name: 'Organization Description' },
{ id: 'application_details', name: 'Application Details' }
];
// Check venue fields if creating venue
if ($('input[name="create_venue"]:checked').val() === 'Yes') {
requiredFields.push(
{ id: 'venue_name', name: 'Venue Name' },
{ id: 'venue_address', name: 'Street Address' },
{ id: 'user_country', name: 'Country' },
{ id: 'user_city', name: 'City' },
{ id: 'user_zip', name: 'Zip/Postal Code' }
);
}
requiredFields.forEach(field => {
const $field = $('#' + field.id);
if (!$field.val() || $field.val().trim() === '') {
hasErrors = true;
errors.push(field.name + ' is required.');
showFieldError(field.id, field.name + ' is required.');
}
});
// Check org logo
const $orgLogo = $('#org_logo');
if ($orgLogo.length && !$orgLogo[0].files.length) {
hasErrors = true;
errors.push('Organization Logo is required.');
showFieldError('org_logo', 'Organization Logo is required.');
}
// Check state/province for venue
if ($('input[name="create_venue"]:checked').val() === 'Yes') {
const country = $('#user_country').val();
if (country) {
if (country === 'United States' || country === 'Canada') {
const state = $('#user_state').val();
if (!state || state === '') {
hasErrors = true;
errors.push('State/Province is required.');
showFieldError('user_state', 'State/Province is required.');
}
} else {
const otherState = $('#user_state_other').val();
if (!otherState || otherState.trim() === '') {
hasErrors = true;
errors.push('State/Province is required.');
showFieldError('user_state_other', 'State/Province is required.');
}
}
}
}
// Check radio buttons
if (!$('input[name="create_venue"]:checked').length) {
hasErrors = true;
errors.push('Please select whether to create a training venue profile.');
}
// Check business type dropdown
const businessType = $('#business_type').val();
if (!businessType || businessType === '') {
hasErrors = true;
errors.push('Business Type is required.');
showFieldError('business_type', 'Business Type is required.');
}
// Check checkbox groups
const checkboxGroups = [
{ name: 'training_audience[]', label: 'Training Audience' },
{ name: 'training_formats[]', label: 'Training Formats' },
{ name: 'training_locations[]', label: 'Training Locations' },
{ name: 'training_resources[]', label: 'Training Resources' }
];
checkboxGroups.forEach(group => {
if (!$('input[name="' + group.name + '"]:checked').length) {
hasErrors = true;
errors.push('Please select at least one option for ' + group.label + '.');
}
});
if (hasErrors) {
e.preventDefault();
// Show error summary at the top
let $errorSummary = $('.hvac-form-errors');
if (!$errorSummary.length) {
$errorSummary = $('<div class="hvac-form-errors" role="alert"><h3>Please correct the following errors:</h3><ul></ul></div>');
$registrationForm.prepend($errorSummary);
}
const $errorList = $errorSummary.find('ul');
$errorList.empty();
errors.forEach(error => {
$errorList.append('<li>' + error + '</li>');
});
// Scroll to top of form
$('html, body').animate({
scrollTop: $('.hvac-registration-form').offset().top - 100
}, 500);
}
});
// Function to populate states/provinces
function loadStates(country) {
console.log(`Loading states/provinces for ${country}`); // Keep log for debugging
$stateSelect.find('option').not('[value=""],[value="Other"]').remove(); // Clear existing options except defaults
let options = {};
if (country === 'United States' && typeof hvacRegistrationData !== 'undefined' && hvacRegistrationData.states) {
options = hvacRegistrationData.states;
} else if (country === 'Canada' && typeof hvacRegistrationData !== 'undefined' && hvacRegistrationData.provinces) {
options = hvacRegistrationData.provinces;
} else {
// If country is not US/CA or data is missing, ensure 'Other' is selected and input shown
$stateSelect.val('Other').trigger('change'); // Trigger change to show 'Other' input if needed
return;
}
// Append new options
$.each(options, function(value, label) {
// Append before the 'Other' option if it exists, otherwise just append
const $otherOption = $stateSelect.find('option[value="Other"]');
const $newOption = $('<option></option>').val(value).text(label);
if ($otherOption.length > 0) {
$newOption.insertBefore($otherOption);
} else {
$stateSelect.append($newOption);
}
});
// Ensure the 'Other' input is hidden initially when states/provinces are loaded
$stateOtherInput.hide().val('');
// Reset state selection to default prompt
$stateSelect.val('');
}
// Handle state/province field visibility based on 'Other' selection
$stateSelect.change(function() {
if ($(this).val() === 'Other') {
$stateOtherInput.show().prop('required', true); // Make required if Other is selected
} else {
$stateOtherInput.hide().val('').prop('required', false); // Hide and make not required
}
}).trigger('change'); // Trigger on load to set initial visibility
// Handle country change to show/hide/populate state field
$countrySelect.change(function() {
const country = $(this).val();
if (country === 'United States' || country === 'Canada') {
loadStates(country);
$stateSelect.show().prop('required', true); // Show and require state select
$stateOtherInput.prop('required', false); // Ensure 'Other' input is not required initially
} else if (country) {
// For other countries, hide state select, select 'Other', show/require 'Other' input
$stateSelect.hide().val('Other').prop('required', false); // Hide and make not required
$stateOtherInput.show().prop('required', true); // Show and require 'Other' input
} else {
// No country selected
$stateSelect.hide().val('').prop('required', false); // Hide and make not required
$stateOtherInput.hide().val('').prop('required', false); // Hide and make not required
}
}).trigger('change'); // Trigger on load to set initial state based on pre-selected country (if any)
// Function to populate headquarters states/provinces
function loadHqStates(country) {
console.log(`Loading HQ states/provinces for ${country}`);
$hqStateSelect.find('option').not('[value=""],[value="Other"]').remove();
let options = {};
if (country === 'United States' && typeof hvacRegistrationData !== 'undefined' && hvacRegistrationData.states) {
options = hvacRegistrationData.states;
} else if (country === 'Canada' && typeof hvacRegistrationData !== 'undefined' && hvacRegistrationData.provinces) {
options = hvacRegistrationData.provinces;
} else {
// For other countries, just select 'Other' without triggering
$hqStateSelect.val('Other');
$hqStateOtherInput.show().prop('required', false);
return;
}
// Append new options
$.each(options, function(value, label) {
const $otherOption = $hqStateSelect.find('option[value="Other"]');
const $newOption = $('<option></option>').val(value).text(label);
if ($otherOption.length > 0) {
$newOption.insertBefore($otherOption);
} else {
$hqStateSelect.append($newOption);
}
});
// Hide the 'Other' input and reset state selection
$hqStateOtherInput.hide().val('');
$hqStateSelect.val('');
}
// Handle headquarters state/province field visibility based on 'Other' selection
$hqStateSelect.change(function() {
if ($(this).val() === 'Other') {
$hqStateOtherInput.show().prop('required', false);
} else {
$hqStateOtherInput.hide().val('').prop('required', false);
}
}).trigger('change');
// Handle headquarters country change to show/hide/populate state field
$hqCountrySelect.change(function() {
const country = $(this).val();
if (country === 'United States' || country === 'Canada') {
loadHqStates(country);
$hqStateSelect.show().prop('required', false);
$hqStateOtherInput.prop('required', false);
} else if (country) {
// For other countries, hide state select, select 'Other', show 'Other' input
$hqStateSelect.hide().val('Other').prop('required', false);
$hqStateOtherInput.show().prop('required', false);
} else {
// No country selected
$hqStateSelect.hide().val('').prop('required', false);
$hqStateOtherInput.hide().val('').prop('required', false);
}
}).trigger('change');
// Initialize venue visibility on load
$createVenue.filter(':checked').trigger('change');
});