upskill-event-manager/assets/js/hvac-trainer-profile.js
bengizmo e4f079a89c feat: Major registration refactor and new trainer management pages
- Refactored registration form:
  * Moved Application Details to Personal Information section
  * Renamed Business Information to Training Organization Information
  * Added required Organization Logo upload with media library integration
  * Added Headquarters location fields (City, State/Province, Country)
  * Moved training-related fields into Organization section
  * Created conditional Training Venue Information section with auto-population

- Created comprehensive venue management system:
  * Training Venues List page (/trainer/venue/list) with filtering and pagination
  * Manage Venue page (/trainer/venue/manage) for create/edit operations
  * Full integration with The Events Calendar venue post type
  * AJAX-powered forms with real-time validation

- Created trainer profile system:
  * Trainer Profile view page (/trainer/profile) with stats and certifications
  * Profile Edit page (/trainer/profile/edit) with photo upload
  * Years of experience tracking and professional information
  * Integration with user meta and custom fields

- Created training organizers management:
  * Organizers List page (/trainer/organizer/list) with search functionality
  * Manage Organizer page (/trainer/organizer/manage) for CRUD operations
  * Organization logo upload and headquarters tracking
  * Full integration with The Events Calendar organizer post type

- Technical improvements:
  * Modular PHP class architecture for each feature
  * Comprehensive AJAX handlers with security nonces
  * Responsive CSS design for all new pages
  * JavaScript form validation and dynamic behavior
  * Proper WordPress and TEC API integration

All new features follow hierarchical URL structure and include breadcrumb navigation.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-30 16:29:51 -03:00

317 lines
No EOL
11 KiB
JavaScript

/**
* HVAC Trainer Profile JavaScript
*
* @package HVAC_Community_Events
* @version 2.0.0
*/
jQuery(document).ready(function($) {
// Cache DOM elements
const $profileForm = $('#hvac-profile-form');
const $uploadButton = $('#hvac-upload-photo');
const $removeButton = $('#hvac-remove-photo');
const $photoIdField = $('#profile_photo_id');
const $currentPhoto = $('.hvac-current-photo');
// Form validation
function validateProfileForm() {
let isValid = true;
const errors = [];
// Clear previous errors
$('.hvac-form-error').removeClass('hvac-form-error');
$('.hvac-error-message').remove();
// Required fields
const requiredFields = [
{ id: 'first_name', label: 'First Name' },
{ id: 'last_name', label: 'Last Name' },
{ id: 'display_name', label: 'Display Name' },
{ id: 'email', label: 'Email Address' }
];
requiredFields.forEach(field => {
const $field = $('#' + field.id);
const value = $field.val();
if (!value || value.trim() === '') {
isValid = false;
errors.push(field.label + ' is required');
$field.addClass('hvac-form-error');
$field.after('<span class="hvac-error-message">' + field.label + ' is required</span>');
}
});
// Validate email
const email = $('#email').val();
if (email && !isValidEmail(email)) {
isValid = false;
errors.push('Please enter a valid email address');
$('#email').addClass('hvac-form-error');
$('#email').after('<span class="hvac-error-message">Please enter a valid email address</span>');
}
// Validate phone format if provided
const phone = $('#phone').val();
if (phone && !isValidPhone(phone)) {
isValid = false;
errors.push('Please enter a valid phone number');
$('#phone').addClass('hvac-form-error');
$('#phone').after('<span class="hvac-error-message">Please enter a valid phone number</span>');
}
// Validate URLs if provided
const website = $('#website').val();
if (website && !isValidURL(website)) {
isValid = false;
errors.push('Please enter a valid website URL');
$('#website').addClass('hvac-form-error');
$('#website').after('<span class="hvac-error-message">Please enter a valid website URL</span>');
}
const linkedin = $('#linkedin').val();
if (linkedin && !isValidURL(linkedin)) {
isValid = false;
errors.push('Please enter a valid LinkedIn URL');
$('#linkedin').addClass('hvac-form-error');
$('#linkedin').after('<span class="hvac-error-message">Please enter a valid LinkedIn URL</span>');
}
// Validate years of experience
const years = $('#years_experience').val();
if (years && (years < 0 || years > 50)) {
isValid = false;
errors.push('Years of experience must be between 0 and 50');
$('#years_experience').addClass('hvac-form-error');
$('#years_experience').after('<span class="hvac-error-message">Must be between 0 and 50</span>');
}
return isValid;
}
// Email validation
function isValidEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}
// Phone validation
function isValidPhone(phone) {
const digits = phone.replace(/\D/g, '');
return digits.length >= 10 && digits.length <= 15;
}
// URL validation
function isValidURL(url) {
try {
new URL(url);
return true;
} catch (_) {
return false;
}
}
// Show message
function showMessage(message, type = 'success') {
const messageClass = type === 'success' ? 'hvac-message-success' : 'hvac-message-error';
const $message = $('<div class="hvac-message ' + messageClass + '">' + message + '</div>');
// Remove any existing messages
$('.hvac-message').remove();
// Add new message
$('.hvac-page-header').after($message);
// Auto-hide success messages after 5 seconds
if (type === 'success') {
setTimeout(function() {
$message.fadeOut(function() {
$(this).remove();
});
}, 5000);
}
// Scroll to top
$('html, body').animate({
scrollTop: $('.hvac-page-header').offset().top - 100
}, 300);
}
// Handle profile form submission
if ($profileForm.length) {
$profileForm.on('submit', function(e) {
e.preventDefault();
// Validate form
if (!validateProfileForm()) {
return false;
}
// Disable submit button
const $submitButton = $profileForm.find('button[type="submit"]');
const originalText = $submitButton.text();
$submitButton.prop('disabled', true).text('Saving...');
// Gather form data
const formData = {
action: 'hvac_update_profile',
nonce: hvacProfile.nonce,
first_name: $('#first_name').val(),
last_name: $('#last_name').val(),
display_name: $('#display_name').val(),
email: $('#email').val(),
phone: $('#phone').val(),
description: $('#description').val(),
city: $('#city').val(),
state: $('#state').val(),
country: $('#country').val(),
years_experience: $('#years_experience').val(),
certifications: $('#certifications').val(),
website: $('#website').val(),
linkedin: $('#linkedin').val(),
profile_photo_id: $('#profile_photo_id').val()
};
// Send AJAX request
$.ajax({
url: hvacProfile.ajax_url,
type: 'POST',
data: formData,
success: function(response) {
if (response.success) {
showMessage(response.data || 'Profile updated successfully.', 'success');
} else {
showMessage(response.data || 'An error occurred while updating your profile.', 'error');
}
},
error: function() {
showMessage('An error occurred. Please try again.', 'error');
},
complete: function() {
// Re-enable submit button
$submitButton.prop('disabled', false).text(originalText);
}
});
});
}
// Handle photo upload
if ($uploadButton.length) {
let mediaUploader;
$uploadButton.on('click', function(e) {
e.preventDefault();
// If the media uploader already exists, open it
if (mediaUploader) {
mediaUploader.open();
return;
}
// Create the media uploader
mediaUploader = wp.media({
title: 'Choose Profile Photo',
button: {
text: 'Use this photo'
},
multiple: false,
library: {
type: 'image'
}
});
// When an image is selected, run a callback
mediaUploader.on('select', function() {
const attachment = mediaUploader.state().get('selection').first().toJSON();
// Update the photo preview
$currentPhoto.html('<img src="' + attachment.sizes.thumbnail.url + '" alt="Profile photo" />');
// Update the hidden field
$photoIdField.val(attachment.id);
// Update button text
$uploadButton.text('Change Photo');
// Show remove button if not already visible
if (!$removeButton.length) {
const removeBtn = '<button type="button" id="hvac-remove-photo" class="hvac-button hvac-button-danger-outline">Remove Photo</button>';
$uploadButton.after(removeBtn);
}
});
// Open the media uploader
mediaUploader.open();
});
}
// Handle photo removal
$(document).on('click', '#hvac-remove-photo', function(e) {
e.preventDefault();
// Clear the photo preview
$currentPhoto.html('<div class="hvac-photo-placeholder">No photo uploaded</div>');
// Clear the hidden field
$photoIdField.val('');
// Update button text
$uploadButton.text('Upload Photo');
// Remove the remove button
$(this).remove();
});
// Real-time validation
$('#email').on('blur', function() {
const email = $(this).val();
$('.hvac-error-message', $(this).parent()).remove();
$(this).removeClass('hvac-form-error');
if (email && !isValidEmail(email)) {
$(this).addClass('hvac-form-error');
$(this).after('<span class="hvac-error-message">Please enter a valid email address</span>');
}
});
$('#phone').on('blur', function() {
const phone = $(this).val();
$('.hvac-error-message', $(this).parent()).remove();
$(this).removeClass('hvac-form-error');
if (phone && !isValidPhone(phone)) {
$(this).addClass('hvac-form-error');
$(this).after('<span class="hvac-error-message">Please enter a valid phone number</span>');
}
});
$('#website, #linkedin').on('blur', function() {
const url = $(this).val();
$('.hvac-error-message', $(this).parent()).remove();
$(this).removeClass('hvac-form-error');
if (url && !isValidURL(url)) {
$(this).addClass('hvac-form-error');
$(this).after('<span class="hvac-error-message">Please enter a valid URL</span>');
}
});
// Auto-format phone number
$('#phone').on('input', function() {
let value = $(this).val().replace(/\D/g, '');
if (value.length > 0) {
if (value.length <= 3) {
value = value;
} else if (value.length <= 6) {
value = value.slice(0, 3) + '-' + value.slice(3);
} else if (value.length <= 10) {
value = value.slice(0, 3) + '-' + value.slice(3, 6) + '-' + value.slice(6);
} else {
value = value.slice(0, 3) + '-' + value.slice(3, 6) + '-' + value.slice(6, 10);
}
}
$(this).val(value);
});
});