upskill-event-manager/templates/template-edit-profile.php
bengizmo c349428451 feat: Implement comprehensive enhanced CSV import system with taxonomy integration
COMPREHENSIVE CSV IMPORT SYSTEM REDESIGN

Problem Resolved:
- Trainer profiles missing critical information from CSV_Trainers_Import_1Aug2025.csv
- Existing import system used hardcoded data instead of reading actual CSV file
- Missing 19 fields of professional information including phone numbers, websites, certifications

Solution Implemented:
- Complete enhanced CSV import system reading actual CSV file with 43 trainer records
- Full taxonomy integration for business_type and training_audience classifications
- Comprehensive field mapping for all 19 available CSV fields
- Multi-value taxonomy handling for comma-separated fields
- Automatic venue/organizer creation based on CSV flags

Key Components Added:
- includes/enhanced-csv-import-from-file.php: Main CSV import class with comprehensive processing
- Updated includes/class-hvac-geocoding-ajax.php: Enhanced AJAX integration
- includes/taxonomy-migration.php: Safe data migration utilities
- Comprehensive error handling, progress tracking, and logging

Fields Now Imported:
- Contact: Name, Email, Phone, Website
- Professional: Company, Role, Certification details (date, type, status)
- Location: Country, State, City
- Taxonomies: Business Type, Training Audience with multi-value support
- System: Application Details, User ID, Venue/Organizer creation flags

Testing Results:
- 43 CSV rows processed successfully
- 43 trainer profiles updated with enhanced data
- Proper taxonomy assignments with comma-separated value handling
- Automatic venue/organizer creation
- Zero errors during import process
- Complete data integrity preserved

TAXONOMY SYSTEM ENHANCEMENTS

Trainer Profile Taxonomy Implementation:
- WordPress taxonomies for business_type and training_audience
- Dynamic form loading from taxonomy terms with fallback support
- Multi-value checkbox and radio interfaces
- Safe data migration from text fields to taxonomies

Template Updates:
- templates/template-edit-profile.php: Dynamic taxonomy loading
- templates/page-master-trainer-profile-edit.php: Enhanced taxonomy management
- templates/page-master-dashboard.php: Fixed critical PHP fatal error

Critical Bug Fixes:
- Fixed HVAC_Community_Events::get_instance() undefined method error
- Master dashboard template now uses correct instance() method
- Eliminated PHP fatal errors preventing master trainer access

COMPREHENSIVE TESTING & VALIDATION

E2E Testing with Playwright:
- 87.5% test pass rate (7/8 tests passing)
- Registration form taxonomy integration verified
- Profile editing with taxonomy selections confirmed
- Data persistence across sessions validated
- Comprehensive visual evidence captured

Documentation Updates:
- docs/API-REFERENCE.md: Complete CSV import AJAX endpoint documentation
- docs/DEVELOPMENT-GUIDE.md: CSV import architecture and best practices
- docs/README.md: Enhanced system overview with CSV import features
- CLAUDE.md: Comprehensive memory entry for future reference

Production Impact:
- Complete trainer profiles with professional information
- Enhanced business categorization through taxonomy system
- Automatic event management preparation with venues/organizers
- Improved master trainer dashboard functionality
- Zero data loss with comprehensive error handling

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 05:57:08 -03:00

771 lines
No EOL
41 KiB
PHP

<?php
/**
* Template Name: HVAC Edit Trainer Profile
*
* This template handles the editing of the HVAC Trainer Profile.
* It allows users to update their personal information, business details, and training preferences.
*
* @package HVAC Community Events
* @subpackage Templates
* @author HVAC Community Events
* @version 1.0.0
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// --- Security Check & Data Loading ---
// Ensure user is logged in and has the correct role
if ( ! is_user_logged_in() || ! current_user_can( 'view_hvac_dashboard' ) ) {
// Redirect to login page
wp_safe_redirect( home_url( '/community-login/' ) );
exit;
}
// Get the current user ID and data
$user_id = get_current_user_id();
$user = get_userdata($user_id);
// Load user meta data
$user_meta = array(
'personal_accreditation' => get_user_meta($user_id, 'personal_accreditation', true),
'business_name' => get_user_meta($user_id, 'business_name', true),
'business_phone' => get_user_meta($user_id, 'business_phone', true),
'business_email' => get_user_meta($user_id, 'business_email', true),
'business_website' => get_user_meta($user_id, 'business_website', true),
'business_description' => get_user_meta($user_id, 'business_description', true),
'user_country' => get_user_meta($user_id, 'user_country', true),
'user_state' => get_user_meta($user_id, 'user_state', true),
'user_city' => get_user_meta($user_id, 'user_city', true),
'user_zip' => get_user_meta($user_id, 'user_zip', true),
'user_linkedin' => get_user_meta($user_id, 'user_linkedin', true),
'business_type' => get_user_meta($user_id, 'business_type', true),
'training_audience' => get_user_meta($user_id, 'training_audience', true),
'training_formats' => get_user_meta($user_id, 'training_formats', true),
'training_locations' => get_user_meta($user_id, 'training_locations', true),
'training_resources' => get_user_meta($user_id, 'training_resources', true),
'annual_revenue_target' => get_user_meta($user_id, 'annual_revenue_target', true),
);
// Get profile image
$profile_image_id = get_user_meta($user_id, 'profile_image_id', true);
$profile_image_url = '';
if ($profile_image_id) {
$profile_image_url = wp_get_attachment_url($profile_image_id);
}
// Get messages (success, error) from query parameters if present
$message = '';
$message_type = '';
if (isset($_GET['updated']) && $_GET['updated'] === '1') {
$message = 'Your profile has been updated successfully.';
$message_type = 'success';
} elseif (isset($_GET['updated']) && $_GET['updated'] === '0') {
$message = 'There was an error updating your profile. Please try again.';
$message_type = 'error';
}
// Check if we have form errors from a previous submission via transient
$errors = [];
$transient_key = null;
if (isset($_GET['prof_error']) && $_GET['prof_error'] === '1' && isset($_GET['tid'])) {
$transient_key = 'hvac_prof_' . sanitize_key($_GET['tid']);
$transient_data = get_transient($transient_key);
if ($transient_data && is_array($transient_data)) {
$errors = $transient_data['errors'] ?? [];
// Delete the transient immediately after retrieving
delete_transient($transient_key);
}
}
// Define country, state, and province options
function get_us_states() {
return array(
'AL' => 'Alabama', 'AK' => 'Alaska', 'AZ' => 'Arizona', 'AR' => 'Arkansas', 'CA' => 'California',
'CO' => 'Colorado', 'CT' => 'Connecticut', 'DE' => 'Delaware', 'DC' => 'District of Columbia', 'FL' => 'Florida',
'GA' => 'Georgia', 'HI' => 'Hawaii', 'ID' => 'Idaho', 'IL' => 'Illinois', 'IN' => 'Indiana',
'IA' => 'Iowa', 'KS' => 'Kansas', 'KY' => 'Kentucky', 'LA' => 'Louisiana', 'ME' => 'Maine',
'MD' => 'Maryland', 'MA' => 'Massachusetts', 'MI' => 'Michigan', 'MN' => 'Minnesota', 'MS' => 'Mississippi',
'MO' => 'Missouri', 'MT' => 'Montana', 'NE' => 'Nebraska', 'NV' => 'Nevada', 'NH' => 'New Hampshire',
'NJ' => 'New Jersey', 'NM' => 'New Mexico', 'NY' => 'New York', 'NC' => 'North Carolina', 'ND' => 'North Dakota',
'OH' => 'Ohio', 'OK' => 'Oklahoma', 'OR' => 'Oregon', 'PA' => 'Pennsylvania', 'RI' => 'Rhode Island',
'SC' => 'South Carolina', 'SD' => 'South Dakota', 'TN' => 'Tennessee', 'TX' => 'Texas', 'UT' => 'Utah',
'VT' => 'Vermont', 'VA' => 'Virginia', 'WA' => 'Washington', 'WV' => 'West Virginia', 'WI' => 'Wisconsin',
'WY' => 'Wyoming'
);
}
function get_canadian_provinces() {
return array(
'AB' => 'Alberta', 'BC' => 'British Columbia', 'MB' => 'Manitoba', 'NB' => 'New Brunswick',
'NL' => 'Newfoundland and Labrador', 'NS' => 'Nova Scotia', 'ON' => 'Ontario', 'PE' => 'Prince Edward Island',
'QC' => 'Quebec', 'SK' => 'Saskatchewan', 'NT' => 'Northwest Territories', 'NU' => 'Nunavut', 'YT' => 'Yukon'
);
}
function get_country_list() {
return array(
'US' => 'United States',
'CA' => 'Canada',
'GB' => 'United Kingdom',
'AU' => 'Australia',
'NZ' => 'New Zealand',
'DE' => 'Germany',
'FR' => 'France',
'IT' => 'Italy',
'ES' => 'Spain',
'JP' => 'Japan',
'CN' => 'China',
'IN' => 'India',
'BR' => 'Brazil',
'MX' => 'Mexico',
// Add more countries as needed
);
}
// --- Template Start ---
get_header(); // Use theme's header
?>
<div id="primary" class="content-area primary ast-container">
<main id="main" class="site-main">
<!-- Profile Header & Navigation -->
<div class="hvac-dashboard-header">
<h1 class="entry-title">Edit Trainer Profile</h1>
<div class="hvac-dashboard-nav">
<a href="<?php echo esc_url(home_url('/trainer-profile/')); ?>" class="ast-button ast-button-secondary">Back to Profile</a>
<a href="<?php echo esc_url(home_url('/hvac-dashboard/')); ?>" class="ast-button ast-button-primary">Dashboard</a>
<a href="<?php echo esc_url(wp_logout_url(home_url('/community-login/'))); ?>" class="ast-button ast-button-secondary">Logout</a>
</div>
</div>
<?php if ($message) : ?>
<div class="hvac-message hvac-message-<?php echo esc_attr($message_type); ?>">
<p><?php echo esc_html($message); ?></p>
</div>
<?php endif; ?>
<div class="hvac-edit-profile-container">
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" id="hvac-edit-profile-form" enctype="multipart/form-data" novalidate>
<input type="hidden" name="action" value="hvac_update_profile">
<?php wp_nonce_field('hvac_update_profile', 'hvac_profile_nonce'); ?>
<!-- Personal Information Section -->
<div class="form-section">
<h3>Personal Information</h3>
<div class="form-row form-row-half">
<div>
<label for="first_name"><strong>First Name *</strong></label>
<input type="text" name="first_name" id="first_name" value="<?php echo esc_attr($user->first_name); ?>" required aria-describedby="first_name_error">
<?php if (isset($errors['first_name'])) echo '<p class="error-message" id="first_name_error">' . esc_html($errors['first_name']) . '</p>'; ?>
</div>
<div>
<label for="last_name"><strong>Last Name *</strong></label>
<input type="text" name="last_name" id="last_name" value="<?php echo esc_attr($user->last_name); ?>" required aria-describedby="last_name_error">
<?php if (isset($errors['last_name'])) echo '<p class="error-message" id="last_name_error">' . esc_html($errors['last_name']) . '</p>'; ?>
</div>
</div>
<div class="form-row">
<label for="display_name"><strong>Display Name *</strong></label>
<input type="text" name="display_name" id="display_name" value="<?php echo esc_attr($user->display_name); ?>" required aria-describedby="display_name_hint display_name_error">
<small id="display_name_hint">This will be the name displayed to other users on the site.</small>
<?php if (isset($errors['display_name'])) echo '<p class="error-message" id="display_name_error">' . esc_html($errors['display_name']) . '</p>'; ?>
</div>
<div class="form-row form-row-half">
<div>
<label for="user_email"><strong>Email *</strong></label>
<input type="email" name="user_email" id="user_email" value="<?php echo esc_attr($user->user_email); ?>" required aria-describedby="user_email_error">
<?php if (isset($errors['user_email'])) echo '<p class="error-message" id="user_email_error">' . esc_html($errors['user_email']) . '</p>'; ?>
</div>
<div>
<label for="user_url">Personal Website (optional)</label>
<input type="url" name="user_url" id="user_url" value="<?php echo esc_attr($user->user_url); ?>" aria-describedby="user_url_error">
<?php if (isset($errors['user_url'])) echo '<p class="error-message" id="user_url_error">' . esc_html($errors['user_url']) . '</p>'; ?>
</div>
</div>
<div class="form-row">
<label for="user_linkedin">LinkedIn Profile URL (optional)</label>
<input type="url" name="user_linkedin" id="user_linkedin" value="<?php echo esc_attr($user_meta['user_linkedin']); ?>" aria-describedby="user_linkedin_error">
<?php if (isset($errors['user_linkedin'])) echo '<p class="error-message" id="user_linkedin_error">' . esc_html($errors['user_linkedin']) . '</p>'; ?>
</div>
<div class="form-row">
<label for="personal_accreditation">Personal Accreditation (optional)</label>
<input type="text" name="personal_accreditation" id="personal_accreditation" value="<?php echo esc_attr($user_meta['personal_accreditation']); ?>" aria-describedby="personal_accreditation_hint">
<small id="personal_accreditation_hint">Enter your abbreviated accreditations separated by commas.</small>
</div>
<div class="form-row">
<label for="description"><strong>Biographical Info *</strong></label>
<textarea name="description" id="description" rows="4" required aria-describedby="description_hint description_error"><?php echo esc_textarea($user->description); ?></textarea>
<small id="description_hint">A short bio about yourself. This will be displayed on your profile page.</small>
<?php if (isset($errors['description'])) echo '<p class="error-message" id="description_error">' . esc_html($errors['description']) . '</p>'; ?>
</div>
<div class="form-row">
<label for="profile_image">Profile Image</label>
<div class="profile-image-preview">
<?php if ($profile_image_url) : ?>
<img src="<?php echo esc_url($profile_image_url); ?>" alt="<?php echo esc_attr($user->display_name); ?>" width="150" height="150">
<?php else : ?>
<div class="hvac-profile-image-placeholder">
<span><?php echo esc_html(substr($user->first_name, 0, 1) . substr($user->last_name, 0, 1)); ?></span>
</div>
<?php endif; ?>
</div>
<div class="profile-image-upload">
<input type="file" name="profile_image" id="profile_image" accept="image/jpeg,image/png,image/gif" aria-describedby="profile_image_hint profile_image_error">
<small id="profile_image_hint">To update your profile image, select a new .jpg, .png, or .gif file. Leave empty to keep your current image.</small>
<?php if (isset($errors['profile_image'])) echo '<p class="error-message" id="profile_image_error">' . esc_html($errors['profile_image']) . '</p>'; ?>
</div>
</div>
</div>
<!-- Business Information Section -->
<div class="form-section">
<h3>Business Information</h3>
<div class="form-row">
<label for="business_name"><strong>Business Name *</strong></label>
<input type="text" name="business_name" id="business_name" value="<?php echo esc_attr($user_meta['business_name']); ?>" required aria-describedby="business_name_error">
<?php if (isset($errors['business_name'])) echo '<p class="error-message" id="business_name_error">' . esc_html($errors['business_name']) . '</p>'; ?>
</div>
<div class="form-row form-row-half">
<div>
<label for="business_phone"><strong>Business Phone *</strong></label>
<input type="tel" name="business_phone" id="business_phone" value="<?php echo esc_attr($user_meta['business_phone']); ?>" required aria-describedby="business_phone_error">
<?php if (isset($errors['business_phone'])) echo '<p class="error-message" id="business_phone_error">' . esc_html($errors['business_phone']) . '</p>'; ?>
</div>
<div>
<label for="business_email"><strong>Business Email *</strong></label>
<input type="email" name="business_email" id="business_email" value="<?php echo esc_attr($user_meta['business_email']); ?>" required aria-describedby="business_email_error">
<?php if (isset($errors['business_email'])) echo '<p class="error-message" id="business_email_error">' . esc_html($errors['business_email']) . '</p>'; ?>
</div>
</div>
<div class="form-row">
<label for="business_website">Business Website (optional)</label>
<input type="url" name="business_website" id="business_website" value="<?php echo esc_attr($user_meta['business_website']); ?>" aria-describedby="business_website_error">
<?php if (isset($errors['business_website'])) echo '<p class="error-message" id="business_website_error">' . esc_html($errors['business_website']) . '</p>'; ?>
</div>
<div class="form-row">
<label for="business_description"><strong>Business Description *</strong></label>
<textarea name="business_description" id="business_description" rows="4" required aria-describedby="business_description_error"><?php echo esc_textarea($user_meta['business_description']); ?></textarea>
<?php if (isset($errors['business_description'])) echo '<p class="error-message" id="business_description_error">' . esc_html($errors['business_description']) . '</p>'; ?>
</div>
</div>
<!-- Address Information Section -->
<div class="form-section">
<h3>Address Information</h3>
<div class="form-row">
<label for="user_country"><strong>Country *</strong></label>
<select name="user_country" id="user_country" required aria-describedby="user_country_error">
<option value="">Select Country</option>
<option value="United States" <?php selected($user_meta['user_country'], 'United States'); ?>>United States</option>
<option value="Canada" <?php selected($user_meta['user_country'], 'Canada'); ?>>Canada</option>
<option value="" disabled>---</option>
<?php
$countries = get_country_list();
foreach ($countries as $code => $name) {
if ($code !== 'US' && $code !== 'CA') {
echo '<option value="' . esc_attr($name) . '" ' . selected($user_meta['user_country'], $name, false) . '>' . esc_html($name) . '</option>';
}
}
?>
</select>
<?php if (isset($errors['user_country'])) echo '<p class="error-message" id="user_country_error">' . esc_html($errors['user_country']) . '</p>'; ?>
</div>
<div class="form-row form-row-half">
<div>
<label for="user_state"><strong>State/Province *</strong></label>
<select name="user_state" id="user_state" required aria-describedby="user_state_error">
<option value="">Select State/Province</option>
<option value="Other" <?php selected($user_meta['user_state'], 'Other'); ?>>Other</option>
<?php
// Pre-populate selected state if available
$selected_state = $user_meta['user_state'];
if (!empty($selected_state) && $selected_state !== 'Other') {
$us_states = get_us_states();
$ca_provinces = get_canadian_provinces();
$is_us_state = array_key_exists($selected_state, $us_states);
$is_ca_province = array_key_exists($selected_state, $ca_provinces);
if (!$is_us_state && !$is_ca_province) {
echo '<option value="' . esc_attr($selected_state) . '" selected>' . esc_html($selected_state) . '</option>';
}
}
?>
</select>
<input type="text" name="user_state_other" id="user_state_other"
value="<?php echo esc_attr($user_meta['user_state']); ?>"
style="<?php echo (($user_meta['user_state'] === 'Other' || (($user_meta['user_country'] !== 'United States' && $user_meta['user_country'] !== 'Canada')))) ? '' : 'display:none;'; ?> margin-top: 0.5rem;"
placeholder="Enter your state/province"
aria-describedby="user_state_other_error">
<?php if (isset($errors['user_state'])) echo '<p class="error-message" id="user_state_error">' . esc_html($errors['user_state']) . '</p>'; ?>
<?php if (isset($errors['user_state_other'])) echo '<p class="error-message" id="user_state_other_error">' . esc_html($errors['user_state_other']) . '</p>'; ?>
</div>
<div>
<label for="user_city"><strong>City *</strong></label>
<input type="text" name="user_city" id="user_city" value="<?php echo esc_attr($user_meta['user_city']); ?>" required aria-describedby="user_city_error">
<?php if (isset($errors['user_city'])) echo '<p class="error-message" id="user_city_error">' . esc_html($errors['user_city']) . '</p>'; ?>
</div>
</div>
<div class="form-row">
<label for="user_zip"><strong>Zip/Postal Code *</strong></label>
<input type="text" name="user_zip" id="user_zip" value="<?php echo esc_attr($user_meta['user_zip']); ?>" required aria-describedby="user_zip_error">
<?php if (isset($errors['user_zip'])) echo '<p class="error-message" id="user_zip_error">' . esc_html($errors['user_zip']) . '</p>'; ?>
</div>
</div>
<!-- Training Information Section -->
<div class="form-section">
<h3>Training Information</h3>
<div class="form-row">
<label id="business_type_label"><strong>Business Type *</strong></label>
<small>What type of business are you?</small>
<div class="radio-group" role="radiogroup" aria-labelledby="business_type_label">
<?php
$business_terms = get_terms(['taxonomy' => 'business_type', 'hide_empty' => false]);
if (!is_wp_error($business_terms) && !empty($business_terms)) {
foreach ($business_terms as $term) {
echo '<label><input type="radio" name="business_type" value="' . esc_attr($term->name) . '" ' . checked($user_meta['business_type'], $term->name, false) . ' required> ' . esc_html($term->name) . '</label>';
}
} else {
// Fallback to hardcoded options if taxonomy not available
$business_types = ["Manufacturer", "Distributor", "Contractor", "Consultant", "Educator", "Government", "Other"];
foreach ($business_types as $type) {
echo '<label><input type="radio" name="business_type" value="' . esc_attr($type) . '" ' . checked($user_meta['business_type'], $type, false) . ' required> ' . esc_html($type) . '</label>';
}
}
?>
</div>
<?php if (isset($errors['business_type'])) echo '<p class="error-message">' . esc_html($errors['business_type']) . '</p>'; ?>
</div>
<div class="form-row">
<label id="training_audience_label"><strong>Training Audience *</strong></label>
<small>Who do you offer training to? (Select all that apply)</small>
<div class="checkbox-group" role="group" aria-labelledby="training_audience_label">
<?php
$audience_terms = get_terms(['taxonomy' => 'training_audience', 'hide_empty' => false]);
$selected_audience = $user_meta['training_audience'];
if (!is_array($selected_audience)) $selected_audience = []; // Ensure it's an array
if (!is_wp_error($audience_terms) && !empty($audience_terms)) {
foreach ($audience_terms as $term) {
echo '<label><input type="checkbox" name="training_audience[]" value="' . esc_attr($term->name) . '" ' . checked(in_array($term->name, $selected_audience), true, false) . '> ' . esc_html($term->name) . '</label>';
}
} else {
// Fallback to hardcoded options if taxonomy not available
$audience_options = [
"Anyone (open to the public)" => "Anyone (open to the public)",
"Industry professionals" => "Industry professionals",
"Internal staff in my company" => "Internal staff in my company",
"Registered students/members of my org/institution" => "Registered students/members of my org/institution"
];
foreach ($audience_options as $value => $label) {
echo '<label><input type="checkbox" name="training_audience[]" value="' . esc_attr($value) . '" ' . checked(in_array($value, $selected_audience), true, false) . '> ' . esc_html($label) . '</label>';
}
}
?>
</div>
<?php if (isset($errors['training_audience'])) echo '<p class="error-message">' . esc_html($errors['training_audience']) . '</p>'; ?>
</div>
<div class="form-row">
<label id="training_formats_label"><strong>Training Formats *</strong></label>
<small>What formats of training do you offer?</small>
<div class="checkbox-group" role="group" aria-labelledby="training_formats_label">
<?php
$format_terms = get_terms(['taxonomy' => 'training_formats', 'hide_empty' => false]);
$selected_formats = $user_meta['training_formats'];
if (!is_array($selected_formats)) $selected_formats = []; // Ensure it's an array
if (!is_wp_error($format_terms) && !empty($format_terms)) {
foreach ($format_terms as $term) {
echo '<label><input type="checkbox" name="training_formats[]" value="' . esc_attr($term->name) . '" ' . checked(in_array($term->name, $selected_formats), true, false) . '> ' . esc_html($term->name) . '</label>';
}
} else {
// Fallback to hardcoded options if taxonomy not available
$format_options = ["In-person", "Virtual", "Hybrid", "On-demand"];
foreach ($format_options as $format) {
echo '<label><input type="checkbox" name="training_formats[]" value="' . esc_attr($format) . '" ' . checked(in_array($format, $selected_formats), true, false) . '> ' . esc_html($format) . '</label>';
}
}
?>
</div>
<?php if (isset($errors['training_formats'])) echo '<p class="error-message">' . esc_html($errors['training_formats']) . '</p>'; ?>
</div>
<div class="form-row">
<label id="training_locations_label"><strong>Training Locations *</strong></label>
<small>Where are you willing to provide training? (Select all that apply)</small>
<div class="checkbox-group" role="group" aria-labelledby="training_locations_label">
<?php
$location_terms = get_terms(['taxonomy' => 'training_locations', 'hide_empty' => false]);
$selected_locations = $user_meta['training_locations'];
if (!is_array($selected_locations)) $selected_locations = []; // Ensure it's an array
if (!is_wp_error($location_terms) && !empty($location_terms)) {
foreach ($location_terms as $term) {
echo '<label><input type="checkbox" name="training_locations[]" value="' . esc_attr($term->name) . '" ' . checked(in_array($term->name, $selected_locations), true, false) . '> ' . esc_html($term->name) . '</label>';
}
} else {
// Fallback to hardcoded options if taxonomy not available
$location_options = ["Online", "Local", "Regional Travel", "National Travel", "International Travel"];
foreach ($location_options as $location) {
echo '<label><input type="checkbox" name="training_locations[]" value="' . esc_attr($location) . '" ' . checked(in_array($location, $selected_locations), true, false) . '> ' . esc_html($location) . '</label>';
}
}
?>
</div>
<?php if (isset($errors['training_locations'])) echo '<p class="error-message">' . esc_html($errors['training_locations']) . '</p>'; ?>
</div>
<div class="form-row">
<label id="training_resources_label"><strong>Training Resources *</strong></label>
<small>What training resources do you have access to? (Select all that apply)</small>
<div class="checkbox-group" role="group" aria-labelledby="training_resources_label">
<?php
$resource_terms = get_terms(['taxonomy' => 'training_resources', 'hide_empty' => false]);
$selected_resources = $user_meta['training_resources'];
if (!is_array($selected_resources)) $selected_resources = []; // Ensure it's an array
if (!is_wp_error($resource_terms) && !empty($resource_terms)) {
foreach ($resource_terms as $term) {
echo '<label><input type="checkbox" name="training_resources[]" value="' . esc_attr($term->name) . '" ' . checked(in_array($term->name, $selected_resources), true, false) . '> ' . esc_html($term->name) . '</label>';
}
} else {
// Fallback to hardcoded options if taxonomy not available
$resource_options = ["Classroom", "Training Lab", "Ducted Furnace(s)", "Ducted Air Handler(s)", "Ducted Air Conditioner(s)", "Ducted Heat Pump(s)", "Ductless Heat Pump(s)", "Training Manuals", "Presentation Slides", "LMS Platform / SCORM Files", "Custom Curriculum", "Other"];
foreach ($resource_options as $resource) {
echo '<label><input type="checkbox" name="training_resources[]" value="' . esc_attr($resource) . '" ' . checked(in_array($resource, $selected_resources), true, false) . '> ' . esc_html($resource) . '</label>';
}
}
?>
</div>
<?php if (isset($errors['training_resources'])) echo '<p class="error-message">' . esc_html($errors['training_resources']) . '</p>'; ?>
</div>
</div>
<!-- Revenue Information Section -->
<div class="form-section">
<h3>Revenue Information</h3>
<div class="form-row">
<label for="annual_revenue_target">Annual Revenue Target (optional)</label>
<small>It's our goal to help you generate revenue through your training. How much revenue are you looking to generate annually though your training on Upskill HVAC?</small>
<input type="number" name="annual_revenue_target" id="annual_revenue_target" min="0" step="1" value="<?php echo esc_attr($user_meta['annual_revenue_target']); ?>">
</div>
</div>
<!-- Password Change Section -->
<div class="form-section">
<h3>Change Password <span class="optional-section">(optional)</span></h3>
<p class="section-description">Leave these fields blank if you do not wish to change your password.</p>
<div class="form-row form-row-half">
<div>
<label for="current_password">Current Password</label>
<input type="password" name="current_password" id="current_password" aria-describedby="current_password_error">
<?php if (isset($errors['current_password'])) echo '<p class="error-message" id="current_password_error">' . esc_html($errors['current_password']) . '</p>'; ?>
</div>
<div>
<label for="new_password">New Password</label>
<input type="password" name="new_password" id="new_password" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" title="Password must be at least 8 characters long, and include at least one uppercase letter, one lowercase letter, and one number." aria-describedby="new_password_hint new_password_error">
<small id="new_password_hint">Password must be at least 8 characters long, and include at least one uppercase letter, one lowercase letter, and one number.</small>
<?php if (isset($errors['new_password'])) echo '<p class="error-message" id="new_password_error">' . esc_html($errors['new_password']) . '</p>'; ?>
</div>
</div>
<div class="form-row">
<label for="confirm_new_password">Confirm New Password</label>
<input type="password" name="confirm_new_password" id="confirm_new_password" aria-describedby="confirm_new_password_error">
<?php if (isset($errors['confirm_new_password'])) echo '<p class="error-message" id="confirm_new_password_error">' . esc_html($errors['confirm_new_password']) . '</p>'; ?>
</div>
</div>
<div class="form-submit">
<button type="submit" class="ast-button ast-button-primary" name="hvac_update_profile">Update Profile</button>
</div>
</form>
</div>
</main>
</div>
<style>
/* Edit Profile specific styles */
.hvac-edit-profile-container {
max-width: 1200px;
margin: 0 auto;
}
.hvac-message {
margin-bottom: 20px;
padding: 15px;
border-radius: 5px;
}
.hvac-message-success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.hvac-message-error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.form-section {
margin-bottom: 40px;
background: #f8f9fa;
border-radius: 8px;
padding: 20px;
border: 1px solid #e9ecef;
}
.form-section h3 {
margin-top: 0;
margin-bottom: 20px;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
.form-row {
margin-bottom: 20px;
}
.form-row label {
display: block;
margin-bottom: 5px;
}
.form-row input[type="text"],
.form-row input[type="email"],
.form-row input[type="tel"],
.form-row input[type="url"],
.form-row input[type="password"],
.form-row input[type="number"],
.form-row select,
.form-row textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
.form-row textarea {
min-height: 100px;
}
.form-row small {
display: block;
margin-top: 5px;
color: #666;
}
.form-row-half {
display: flex;
gap: 20px;
}
.form-row-half > div {
flex: 1;
}
.radio-group,
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin-top: 10px;
}
.radio-group label,
.checkbox-group label {
display: flex;
align-items: center;
margin-bottom: 0;
}
.radio-group input,
.checkbox-group input {
margin-right: 5px;
}
.profile-image-preview {
margin-bottom: 15px;
}
.profile-image-preview img {
border-radius: 50%;
object-fit: cover;
}
.hvac-profile-image-placeholder {
width: 150px;
height: 150px;
border-radius: 50%;
background-color: #0B5C7D;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
font-weight: bold;
}
.form-submit {
margin-top: 30px;
}
.form-submit button {
padding: 12px 20px;
font-size: 16px;
cursor: pointer;
}
.optional-section {
font-size: 0.8em;
font-weight: normal;
color: #666;
}
.section-description {
margin-top: -10px;
margin-bottom: 20px;
color: #666;
}
.error-message {
color: #dc3545;
margin-top: 5px;
font-size: 0.9em;
}
@media (max-width: 768px) {
.form-row-half {
flex-direction: column;
gap: 10px;
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
const countrySelect = document.getElementById('user_country');
const stateSelect = document.getElementById('user_state');
const stateOtherInput = document.getElementById('user_state_other');
// US States data
const usStates = <?php echo json_encode(get_us_states()); ?>;
// Canadian Provinces data
const caProvinces = <?php echo json_encode(get_canadian_provinces()); ?>;
// Function to populate state/province dropdown
function populateStateProvinceDropdown(country) {
// Clear current options
stateSelect.innerHTML = '';
// Add default option
const defaultOption = document.createElement('option');
defaultOption.value = '';
defaultOption.textContent = 'Select State/Province';
stateSelect.appendChild(defaultOption);
// Add 'Other' option
const otherOption = document.createElement('option');
otherOption.value = 'Other';
otherOption.textContent = 'Other';
let options = [];
if (country === 'United States') {
// Add US states
options = Object.entries(usStates).map(([code, name]) => ({code, name}));
} else if (country === 'Canada') {
// Add Canadian provinces
options = Object.entries(caProvinces).map(([code, name]) => ({code, name}));
} else {
// For other countries, select 'Other' by default
otherOption.selected = true;
stateOtherInput.style.display = '';
}
// Add options to select
options.forEach(option => {
const optionElement = document.createElement('option');
optionElement.value = option.name;
optionElement.textContent = option.name;
// Check if this option should be selected
const currentState = "<?php echo esc_js($user_meta['user_state']); ?>";
if (option.name === currentState) {
optionElement.selected = true;
}
stateSelect.appendChild(optionElement);
});
// Add 'Other' option at the end
stateSelect.appendChild(otherOption);
// Show/hide 'Other' input based on selection
toggleStateOtherInput();
}
// Function to toggle display of the 'Other' state input
function toggleStateOtherInput() {
if (stateSelect.value === 'Other') {
stateOtherInput.style.display = '';
stateOtherInput.required = true;
} else {
stateOtherInput.style.display = 'none';
stateOtherInput.required = false;
}
}
// Initialize state dropdown based on current country
populateStateProvinceDropdown(countrySelect.value);
// Handle country change event
countrySelect.addEventListener('change', function() {
populateStateProvinceDropdown(this.value);
});
// Handle state change event
stateSelect.addEventListener('change', function() {
toggleStateOtherInput();
});
// Password validation
const newPasswordInput = document.getElementById('new_password');
const confirmPasswordInput = document.getElementById('confirm_new_password');
confirmPasswordInput.addEventListener('input', function() {
if (newPasswordInput.value !== this.value) {
this.setCustomValidity('Passwords do not match');
} else {
this.setCustomValidity('');
}
});
newPasswordInput.addEventListener('input', function() {
if (confirmPasswordInput.value && confirmPasswordInput.value !== this.value) {
confirmPasswordInput.setCustomValidity('Passwords do not match');
} else {
confirmPasswordInput.setCustomValidity('');
}
});
});
</script>
<?php
get_footer(); // Use theme's footer