upskill-event-manager/templates/page-find-trainer.php
Ben c3e7fe9140 feat: comprehensive HVAC plugin development framework and modernization
## Major Enhancements

### 🏗️ Architecture & Infrastructure
- Implement comprehensive Docker testing infrastructure with hermetic environment
- Add Forgejo Actions CI/CD pipeline for automated deployments
- Create Page Object Model (POM) testing architecture reducing test duplication by 90%
- Establish security-first development patterns with input validation and output escaping

### 🧪 Testing Framework Modernization
- Migrate 146+ tests from 80 duplicate files to centralized architecture
- Add comprehensive E2E test suites for all user roles and workflows
- Implement WordPress error detection with automatic site health monitoring
- Create robust browser lifecycle management with proper cleanup

### 📚 Documentation & Guides
- Add comprehensive development best practices guide
- Create detailed administrator setup documentation
- Establish user guides for trainers and master trainers
- Document security incident reports and migration guides

### 🔧 Core Plugin Features
- Enhance trainer profile management with certification system
- Improve find trainer functionality with advanced filtering
- Strengthen master trainer area with content management
- Add comprehensive venue and organizer management

### 🛡️ Security & Reliability
- Implement security-first patterns throughout codebase
- Add comprehensive input validation and output escaping
- Create secure credential management system
- Establish proper WordPress role-based access control

### 🎯 WordPress Integration
- Strengthen singleton pattern implementation across all classes
- Enhance template hierarchy with proper WordPress integration
- Improve page manager with hierarchical URL structure
- Add comprehensive shortcode and menu system

### 🔍 Developer Experience
- Add extensive debugging and troubleshooting tools
- Create comprehensive test data seeding scripts
- Implement proper error handling and logging
- Establish consistent code patterns and standards

### 📊 Performance & Optimization
- Optimize database queries and caching strategies
- Improve asset loading and script management
- Enhance template rendering performance
- Streamline user experience across all interfaces

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-29 11:26:10 -03:00

702 lines
No EOL
34 KiB
PHP

<?php
/**
* Template Name: Find a Trainer
* Template for displaying the Find a Trainer page
*
* @package HVAC_Plugin
* @since 1.0.0
*/
// Define constant to identify we're in a page template
define('HVAC_IN_PAGE_TEMPLATE', true);
// Get header
get_header();
// Initialize required classes
if (class_exists('HVAC_Find_Trainer_Page')) {
$find_trainer = HVAC_Find_Trainer_Page::get_instance();
}
if (class_exists('HVAC_Trainer_Directory_Query')) {
$directory_query = HVAC_Trainer_Directory_Query::get_instance();
}
// Check if we have a direct profile URL pattern
$qr_generator = HVAC_QR_Generator::instance();
$direct_profile_id = $qr_generator->parse_profile_id_from_url();
$show_direct_profile = false;
$direct_profile_data = null;
if ($direct_profile_id) {
// Get the specific profile data
$direct_profile_data = $qr_generator->get_trainer_share_data($direct_profile_id);
if ($direct_profile_data) {
$show_direct_profile = true;
// Get additional profile data for full display
$profile_post = get_post($direct_profile_id);
$user_id = get_post_meta($direct_profile_id, 'user_id', true);
$user = get_userdata($user_id);
// Get profile metadata
$profile_meta = [];
if ($profile_post) {
$all_meta = get_post_meta($direct_profile_id);
foreach ($all_meta as $key => $value) {
$profile_meta[$key] = is_array($value) ? $value[0] : $value;
}
}
// Get cached event count with timestamp validation
$cached_timestamp = get_post_meta($direct_profile_id, 'cached_event_count_timestamp', true);
$cache_expiry = 3600; // 1 hour cache
$cache_valid = $cached_timestamp && (time() - $cached_timestamp < $cache_expiry);
$event_count = get_post_meta($direct_profile_id, 'cached_event_count', true);
if (empty($event_count) || !$cache_valid) {
// Defer expensive database queries to prevent Safari hanging
// Use AJAX to load event data after page load
$event_count = get_post_meta($direct_profile_id, 'cached_event_count', true) ?: 0;
}
// Upcoming events loaded via AJAX to prevent template query cascades
$upcoming_events = [];
// Add additional data to the profile data array
$direct_profile_data['profile_meta'] = $profile_meta;
$direct_profile_data['user'] = $user;
$direct_profile_data['event_count'] = $event_count;
$direct_profile_data['upcoming_events'] = $upcoming_events;
$direct_profile_data['profile_content'] = $profile_post ? $profile_post->post_content : '';
}
}
// Get trainers for initial display with user status filtering
$trainers = [];
$total_pages = 1;
// Get approved user IDs first
$user_query = new WP_User_Query([
'meta_query' => [
[
'key' => 'account_status',
'value' => ['approved', 'active', 'inactive'],
'compare' => 'IN'
]
],
'fields' => 'ID'
]);
$approved_user_ids = $user_query->get_results();
if (!empty($approved_user_ids)) {
// Query trainer profiles for approved users only
$args = [
'post_type' => 'trainer_profile',
'posts_per_page' => 12,
'post_status' => 'publish',
'meta_query' => [
'relation' => 'AND',
[
'key' => 'is_public_profile',
'value' => '1',
'compare' => '='
],
[
'key' => 'user_id',
'value' => $approved_user_ids,
'compare' => 'IN'
]
]
];
$query = new WP_Query($args);
$total_pages = $query->max_num_pages;
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$profile_id = get_the_ID();
$user_id = get_post_meta($profile_id, 'user_id', true);
// Get event count from cached meta (much faster)
$event_count = get_post_meta($profile_id, 'cached_event_count', true);
if (empty($event_count)) {
// Fallback: quick count query if cache not available
if ($user_id && function_exists('tribe_get_events')) {
$count_query = new WP_Query([
'post_type' => 'tribe_events',
'author' => $user_id,
'post_status' => 'publish',
'fields' => 'ids',
'posts_per_page' => 1,
'no_found_rows' => false
]);
$event_count = $count_query->found_posts;
wp_reset_postdata();
// Cache the result for 1 hour
update_post_meta($profile_id, 'cached_event_count', $event_count);
update_post_meta($profile_id, 'cached_event_count_timestamp', time());
} else {
$event_count = 0;
}
}
// Get certifications from new system (with fallback to legacy)
$certifications = [];
$legacy_certification = get_post_meta($profile_id, 'certification_type', true);
if (class_exists('HVAC_Trainer_Certification_Manager')) {
$cert_manager = HVAC_Trainer_Certification_Manager::instance();
$trainer_certifications = $cert_manager->get_trainer_certifications($user_id);
foreach ($trainer_certifications as $cert) {
$cert_type = get_post_meta($cert->ID, 'certification_type', true);
$status = get_post_meta($cert->ID, 'status', true) ?: 'active';
$expiration_date = get_post_meta($cert->ID, 'expiration_date', true);
// Calculate if expired
$is_expired = false;
if ($expiration_date) {
$is_expired = strtotime($expiration_date) < time();
}
// Only include active, non-expired certifications
if ($status === 'active' && !$is_expired) {
$certifications[] = [
'type' => $cert_type,
'status' => $status,
'expiration_date' => $expiration_date,
'is_expired' => $is_expired
];
}
}
}
// Fallback to legacy certification if no new certifications found
if (empty($certifications) && !empty($legacy_certification)) {
$certifications[] = [
'type' => $legacy_certification,
'status' => 'legacy',
'expiration_date' => '',
'is_expired' => false
];
}
$trainers[] = [
'profile_id' => $profile_id,
'user_id' => $user_id,
'name' => get_post_meta($profile_id, 'trainer_display_name', true),
'city' => get_post_meta($profile_id, 'trainer_city', true),
'state' => get_post_meta($profile_id, 'trainer_state', true),
'certification' => $legacy_certification, // Keep for backward compatibility
'certifications' => $certifications, // New multiple certifications array
'profile_image' => get_post_meta($profile_id, 'profile_image_url', true),
'event_count' => $event_count
];
}
}
wp_reset_postdata();
// Sort trainers: Certified measureQuick Trainers first, Champions last
usort($trainers, function($a, $b) {
$a_cert = $a['certification'];
$b_cert = $b['certification'];
// Define sort order: Trainers = 1, Champions = 2, Others = 3
$a_priority = 3; // Default for others
$b_priority = 3; // Default for others
if ($a_cert === 'Certified measureQuick Trainer') {
$a_priority = 1;
} elseif ($a_cert === 'Certified measureQuick Champion') {
$a_priority = 2;
}
if ($b_cert === 'Certified measureQuick Trainer') {
$b_priority = 1;
} elseif ($b_cert === 'Certified measureQuick Champion') {
$b_priority = 2;
}
// Primary sort by certification priority
if ($a_priority !== $b_priority) {
return $a_priority - $b_priority;
}
// Secondary sort by name (alphabetical)
return strcasecmp($a['name'], $b['name']);
});
}
// Assets are now handled by HVAC_Find_Trainer_Assets class via wp_enqueue_scripts hook
// This ensures proper timing and Safari compatibility
// Profile sharing assets are now handled by HVAC_Find_Trainer_Assets class
// Script localization is now handled by HVAC_Find_Trainer_Assets class
?>
<div class="hvac-find-trainer-page">
<div class="ast-container">
<!-- Page Title -->
<h1 class="hvac-page-title"><?php echo $show_direct_profile ? 'Trainer Profile' : 'Find a Trainer'; ?></h1>
<!-- Direct Profile Display -->
<?php if ($show_direct_profile && $direct_profile_data): ?>
<div class="hvac-direct-profile-container">
<div class="hvac-direct-profile-header">
<a href="<?php echo esc_url(remove_query_arg('', get_permalink())); ?>" class="hvac-back-to-directory">
<span class="dashicons dashicons-arrow-left-alt2"></span> Back to Trainer Directory
</a>
</div>
<!-- Full Trainer Profile Display -->
<div class="hvac-trainer-profile-full">
<!-- Profile Header Section -->
<div class="hvac-trainer-profile-header">
<div class="hvac-trainer-image-section">
<?php if (!empty($direct_profile_data['profile_image'])): ?>
<img src="<?php echo esc_url($direct_profile_data['profile_image']); ?>" alt="<?php echo esc_attr($direct_profile_data['trainer_name']); ?>" class="hvac-trainer-main-image">
<?php else: ?>
<div class="hvac-trainer-avatar-large">
<span class="dashicons dashicons-businessperson"></span>
</div>
<?php endif; ?>
<!-- mQ Certified Badge -->
<?php if ($direct_profile_data['certification_type'] === 'Certified measureQuick Trainer'): ?>
<div class="hvac-mq-badge-overlay">
<img src="/wp-content/uploads/2025/08/mQ-Certified-trainer.png" alt="measureQuick Certified Trainer" class="hvac-mq-badge" width="35" height="35">
</div>
<?php endif; ?>
</div>
<div class="hvac-trainer-header-info">
<h2 class="hvac-trainer-name"><?php echo esc_html($direct_profile_data['trainer_name']); ?></h2>
<p class="hvac-trainer-location">
<?php echo esc_html($direct_profile_data['trainer_city'] . ', ' . $direct_profile_data['trainer_state']); ?>
</p>
<p class="hvac-trainer-certification"><?php echo esc_html($direct_profile_data['certification_type'] ?: 'HVAC Trainer'); ?></p>
<?php if (!empty($direct_profile_data['business_name'])): ?>
<p class="hvac-trainer-business"><?php echo esc_html($direct_profile_data['business_name']); ?></p>
<?php endif; ?>
<p class="hvac-trainer-events-stat">Total Training Events: <strong><?php echo esc_html($direct_profile_data['event_count']); ?></strong></p>
</div>
</div>
<!-- Training Details Section -->
<div class="hvac-trainer-details-section">
<h3>Training Information</h3>
<div class="hvac-training-details-grid">
<?php
$profile_meta = $direct_profile_data['profile_meta'] ?? [];
$training_formats = $profile_meta['training_formats'] ?? 'In-Person, Virtual';
$training_locations = $profile_meta['training_locations'] ?? 'On-site, Remote';
?>
<div class="hvac-training-detail">
<strong>Training Formats:</strong>
<span><?php echo esc_html($training_formats); ?></span>
</div>
<div class="hvac-training-detail">
<strong>Training Locations:</strong>
<span><?php echo esc_html($training_locations); ?></span>
</div>
<?php if (!empty($profile_meta['training_audience'])): ?>
<div class="hvac-training-detail">
<strong>Training Audience:</strong>
<span><?php echo esc_html($profile_meta['training_audience']); ?></span>
</div>
<?php endif; ?>
<?php if (!empty($profile_meta['years_experience'])): ?>
<div class="hvac-training-detail">
<strong>Years Experience:</strong>
<span><?php echo esc_html($profile_meta['years_experience']); ?> years</span>
</div>
<?php endif; ?>
</div>
</div>
<!-- Upcoming Events Section -->
<div class="hvac-upcoming-events-section">
<h3>Upcoming Events</h3>
<?php if (!empty($direct_profile_data['upcoming_events'])): ?>
<ul class="hvac-events-list">
<?php foreach ($direct_profile_data['upcoming_events'] as $event): ?>
<li>
<a href="<?php echo esc_url($event['url']); ?>" target="_blank">
<?php echo esc_html($event['title']); ?>
</a>
- <?php echo esc_html($event['date']); ?>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>No upcoming events scheduled</p>
<?php endif; ?>
</div>
<!-- About Section -->
<?php if (!empty($direct_profile_data['profile_content'])): ?>
<div class="hvac-trainer-about-section">
<h3>About</h3>
<div class="hvac-trainer-bio">
<?php echo wp_kses_post(wpautop($direct_profile_data['profile_content'])); ?>
</div>
</div>
<?php endif; ?>
<!-- Contact Section -->
<div class="hvac-contact-section">
<h3>Contact</h3>
<form id="hvac-direct-contact-form" class="hvac-contact-form">
<div class="hvac-form-row">
<input type="text" name="first_name" placeholder="First Name" required>
<input type="text" name="last_name" placeholder="Last Name" required>
</div>
<div class="hvac-form-row">
<input type="email" name="email" placeholder="Email" required>
<input type="tel" name="phone" placeholder="Phone Number">
</div>
<div class="hvac-form-row">
<input type="text" name="city" placeholder="City">
<input type="text" name="state_province" placeholder="State/Province">
</div>
<div class="hvac-form-full">
<input type="text" name="company" placeholder="Company">
</div>
<div class="hvac-form-full">
<textarea name="message" placeholder="Message" rows="4"></textarea>
</div>
<input type="hidden" name="trainer_id" value="<?php echo esc_attr($direct_profile_data['user_id']); ?>">
<input type="hidden" name="trainer_profile_id" value="<?php echo esc_attr($direct_profile_id); ?>">
<button type="submit" class="hvac-form-submit">Send Message</button>
</form>
<!-- Success/Error Messages -->
<div class="hvac-form-message hvac-form-success" style="display: none;">
Your message has been sent! Check your inbox for more details.
</div>
<div class="hvac-form-message hvac-form-error" style="display: none;">
There was an error sending your message. Please try again.
</div>
</div>
</div>
</div>
<?php endif; ?>
<!-- Container 1: Summary (hidden for direct profiles) -->
<?php if (!$show_direct_profile): ?>
<div class="hvac-summary-container">
<p>Upskill HVAC is proud to be the only training body offering Certified measureQuick training.</p>
<p><strong>Certified measureQuick Trainers</strong> have demonstrated their skills and mastery of HVAC science and the measureQuick app, and are authorized to provide measureQuick training to the industry.</p>
<p><strong>measureQuick Certified Champions</strong> have also demonstrated mastery of HVAC science and the measureQuick app, but they do not offer public training.</p>
<p>Use the interactive map and filters below to discover trainers who match your specific needs. Click on any <strong>Certified measureQuick Trainer</strong> to view their profile and contact them directly about training opportunities.</p>
</div>
<?php endif; ?>
<!-- Container 2: Map & Filters (hidden for direct profiles) -->
<?php if (!$show_direct_profile): ?>
<div class="hvac-map-filters-container">
<!-- Container 3: Map (2/3 width) -->
<div class="hvac-map-section">
<?php
// Display MapGeo map
if (shortcode_exists('display-map')) {
echo do_shortcode('[display-map id="5872"]');
} else {
// Fallback if MapGeo is not installed
?>
<div class="hvac-map-placeholder" style="height: 450px; background: #f5f5f5; display: flex; align-items: center; justify-content: center; color: #666;">
<p>Map plugin not installed</p>
</div>
<?php
}
?>
</div>
<!-- Container 4: Filters (1/3 width) -->
<div class="hvac-filters-section">
<!-- Search Box -->
<div class="hvac-search-box">
<input type="text" id="hvac-trainer-search" class="hvac-search-input" placeholder="Search..." aria-label="Search trainers">
<span class="dashicons dashicons-search"></span>
</div>
<!-- Filter Label with Clear Button -->
<div class="hvac-filters-header">
<span class="hvac-filters-label">Filters:</span>
<button class="hvac-clear-filters" type="button" style="display: none;">
Clear All
</button>
</div>
<!-- Filter Buttons -->
<button class="hvac-filter-btn" data-filter="state" type="button">
State / Province
<span class="dashicons dashicons-arrow-down-alt2"></span>
</button>
<button class="hvac-filter-btn" data-filter="business_type" type="button">
Business Type
<span class="dashicons dashicons-arrow-down-alt2"></span>
</button>
<button class="hvac-filter-btn" data-filter="training_format" type="button">
Training Format
<span class="dashicons dashicons-arrow-down-alt2"></span>
</button>
<button class="hvac-filter-btn" data-filter="training_resources" type="button">
Training Resources
<span class="dashicons dashicons-arrow-down-alt2"></span>
</button>
<!-- Active Filters Display -->
<div class="hvac-active-filters"></div>
</div>
</div>
<?php endif; ?>
<!-- Container 5: Trainer Directory (hidden for direct profiles) -->
<?php if (!$show_direct_profile): ?>
<div class="hvac-trainer-directory-container">
<div class="hvac-trainer-grid">
<?php if (!empty($trainers)) : ?>
<?php foreach ($trainers as $trainer) :
// Get featured image or use default avatar
$featured_image = !empty($trainer['profile_image']) ? $trainer['profile_image'] : false;
?>
<div class="hvac-trainer-card hvac-open-profile<?php
// Check for multiple certifications
$has_trainer_cert = false;
$has_champion_cert = false;
if (!empty($trainer['certifications'])) {
foreach ($trainer['certifications'] as $cert) {
if ($cert['type'] === 'measureQuick Certified Trainer') {
$has_trainer_cert = true;
} elseif ($cert['type'] === 'measureQuick Certified Champion') {
$has_champion_cert = true;
}
}
}
// Fallback to legacy certification
if ($trainer['certification'] === 'Certified measureQuick Champion') {
$has_champion_cert = true;
} elseif ($trainer['certification'] === 'Certified measureQuick Trainer') {
$has_trainer_cert = true;
}
// Priority: Trainer cert shows trainer styling, Champion only if no trainer cert
if ($has_trainer_cert) {
echo ' hvac-trainer-card-certified';
} elseif ($has_champion_cert) {
echo ' hvac-champion-card';
}
?>" data-profile-id="<?php echo esc_attr($trainer['profile_id']); ?>" data-event-count="<?php echo esc_attr($trainer['event_count']); ?>">
<div class="hvac-trainer-card-content">
<!-- Featured Image -->
<div class="hvac-trainer-image">
<?php if ($featured_image) : ?>
<img src="<?php echo esc_url($featured_image); ?>" alt="<?php echo esc_attr($trainer['name']); ?>">
<?php else : ?>
<div class="hvac-trainer-avatar">
<span class="dashicons dashicons-businessperson"></span>
</div>
<?php endif; ?>
<!-- mQ Certified Trainer Badge Overlay -->
<?php if ($has_trainer_cert) : ?>
<div class="hvac-mq-badge-overlay">
<img src="/wp-content/uploads/2025/08/mQ-Certified-trainer.png" alt="measureQuick Certified Trainer" class="hvac-mq-badge" width="35" height="35">
</div>
<?php endif; ?>
</div>
<!-- Trainer Info -->
<div class="hvac-trainer-details">
<!-- Name (conditional clickable) -->
<h3 class="hvac-trainer-name">
<?php if ($has_trainer_cert || (!$has_trainer_cert && !$has_champion_cert)) : ?>
<!-- Trainers and non-champions - name only -->
<span class="hvac-trainer-name-text"><?php echo esc_html($trainer['name']); ?></span>
<?php else : ?>
<!-- Champions only (without trainer cert) are not clickable -->
<span class="hvac-champion-name"><?php echo esc_html($trainer['name']); ?></span>
<?php endif; ?>
</h3>
<!-- Location -->
<p class="hvac-trainer-location">
<?php echo esc_html($trainer['city']); ?>, <?php echo esc_html($trainer['state']); ?>
</p>
<!-- Multiple Certifications -->
<div class="hvac-trainer-certifications">
<?php if (!empty($trainer['certifications'])): ?>
<?php foreach ($trainer['certifications'] as $cert): ?>
<span class="hvac-trainer-cert-badge hvac-cert-<?php
echo esc_attr(strtolower(str_replace(['measureQuick Certified ', ' '], ['', '-'], $cert['type'])));
?><?php echo $cert['status'] === 'legacy' ? ' hvac-cert-legacy' : ''; ?>">
<?php echo esc_html($cert['type']); ?>
</span>
<?php endforeach; ?>
<?php else: ?>
<span class="hvac-trainer-cert-badge hvac-cert-default">HVAC Trainer</span>
<?php endif; ?>
</div>
<!-- See Events (hidden for v1) -->
<!--
<a href="#" class="hvac-see-events" data-trainer-id="<?php echo esc_attr($trainer['user_id']); ?>">
<span class="dashicons dashicons-calendar-alt"></span> See Events
</a>
-->
</div>
</div>
</div>
<?php endforeach; ?>
<?php else : ?>
<div class="hvac-no-trainers">
<p>No trainers found. Please try adjusting your search or filters.</p>
</div>
<?php endif; ?>
</div>
<!-- Pagination -->
<?php if ($total_pages > 1) : ?>
<div class="hvac-pagination">
<?php
echo paginate_links([
'total' => $total_pages,
'current' => 1,
'prev_text' => '&laquo;',
'next_text' => '&raquo;',
'type' => 'plain'
]);
?>
</div>
<?php endif; ?>
</div>
<!-- Container 6: CTA Section (hidden for direct profiles) -->
<?php endif; ?>
<?php if (!$show_direct_profile): ?>
<div class="hvac-cta-container">
<p class="hvac-cta-text">Are you an HVAC Trainer that wants to be listed in our directory?</p>
<a href="/trainer/registration/" class="hvac-cta-button">Become A Trainer</a>
</div>
<?php endif; ?>
</div>
</div>
<!-- Filter Modal Template -->
<div id="hvac-filter-modal" class="hvac-filter-modal" style="display: none !important; visibility: hidden !important; opacity: 0 !important;">
<div class="hvac-filter-modal-content">
<h3 class="hvac-filter-modal-title"></h3>
<div class="hvac-filter-options"></div>
<button class="hvac-filter-apply">Apply</button>
</div>
</div>
<!-- Trainer Profile Modal Template -->
<div id="hvac-trainer-modal" class="hvac-trainer-modal" style="display: none;">
<div class="hvac-trainer-modal-content">
<!-- Close Button -->
<button class="hvac-modal-close" aria-label="Close">
<span class="dashicons dashicons-no"></span>
</button>
<!-- Modal Title -->
<h2 class="hvac-modal-title">[Trainer Name]</h2>
<!-- Container 1: Profile Info -->
<div class="hvac-modal-profile">
<div class="hvac-modal-image">
<!-- Trainer profile image will be loaded dynamically via JavaScript -->
</div>
<div class="hvac-modal-info">
<p class="hvac-modal-location">[trainer_city], [trainer_state]</p>
<div class="hvac-modal-certifications">
<!-- Multiple certifications will be populated by JavaScript -->
<div class="hvac-modal-certification-badges">
<!-- Certification badges populated dynamically -->
</div>
</div>
<p class="hvac-modal-business">[business_type]</p>
<p class="hvac-modal-events">Total Training Events: <span>[#]</span></p>
</div>
</div>
<!-- Container 2: Training Details -->
<div class="hvac-modal-training">
<div class="hvac-training-row">
<strong>Training Formats:</strong> <span class="hvac-training-formats">[training_formats]</span>
</div>
<div class="hvac-training-row">
<strong>Training Locations:</strong> <span class="hvac-training-locations">[training_locations]</span>
</div>
<div class="hvac-training-events">
<strong>Upcoming Events:</strong>
<ul class="hvac-events-list">
<!-- Events populated via JS -->
</ul>
</div>
</div>
<!-- Container 3: Contact Form -->
<div class="hvac-modal-contact">
<h3>Contact</h3>
<form id="hvac-contact-form" class="hvac-contact-form">
<div class="hvac-form-row">
<input type="text" name="first_name" placeholder="First Name" required>
<input type="text" name="last_name" placeholder="Last Name" required>
</div>
<div class="hvac-form-row">
<input type="email" name="email" placeholder="Email" required>
<input type="tel" name="phone" placeholder="Phone Number">
</div>
<div class="hvac-form-row">
<input type="text" name="city" placeholder="City">
<input type="text" name="state_province" placeholder="State/Province">
</div>
<div class="hvac-form-full">
<input type="text" name="company" placeholder="Company">
</div>
<div class="hvac-form-full">
<textarea name="message" placeholder="Message" rows="4"></textarea>
</div>
<input type="hidden" name="trainer_id" value="">
<input type="hidden" name="trainer_profile_id" value="">
<button type="submit" class="hvac-form-submit">Submit</button>
</form>
<!-- Success/Error Messages -->
<div class="hvac-form-message hvac-form-success" style="display: none;">
Your message has been sent! Check your inbox for more details.
</div>
<div class="hvac-form-message hvac-form-error" style="display: none;">
There was an error sending your message. Please try again.
</div>
</div>
</div>
</div>
<?php
// Get footer
get_footer();
?>