upskill-event-manager/docs/TRAINER-SYSTEM-DOCUMENTATION.md
bengizmo 705e6b563c feat: Implement Training Leads system and restructure navigation menu
- Add comprehensive Training Leads system for HVAC trainers
  * New /trainer/training-leads/ page with tabular contact submission display
  * HVAC_Training_Leads class with AJAX status updates and filtering
  * Empty state messaging and profile sharing CTA
  * Database integration with existing contact forms system

- Restructure trainer navigation menu for better UX
  * Rename "Customize" to "Profile" with logical groupings
  * Move "Logout" under "Profile" submenu
  * Change "Personal Profile" to "Trainer Profile"
  * Add "Training Leads" under Profile section
  * Update help menu to show only question mark icon positioned far right

- Enhance documentation system
  * Fix /trainer/documentation/ page styling and navigation integration
  * Update content to reflect current platform features
  * Add Training Leads documentation and navigation guide
  * Implement proper WordPress template structure

- Update user management
  * Change joe@upskillhvac.com display name to "Joe Medosch"
  * Assign Joe as author of measureQuick headquarters venue
  * Assign Joe as author of measureQuick and Upskill HVAC organizers

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

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

1035 lines
No EOL
27 KiB
Markdown

# HVAC Trainer System Documentation
This document provides comprehensive documentation for all functionality related to the HVAC Trainer custom post type and Find A Trainer page in the HVAC Community Events plugin.
## Table of Contents
1. [System Overview](#system-overview)
2. [Trainer Profile Custom Post Type](#trainer-profile-custom-post-type)
3. [Find A Trainer Page](#find-a-trainer-page)
4. [MapGeo Integration](#mapgeo-integration)
5. [User Roles & Permissions](#user-roles--permissions)
6. [API Reference](#api-reference)
7. [Frontend Components](#frontend-components)
8. [Database Schema](#database-schema)
9. [Performance Optimizations](#performance-optimizations)
10. [Troubleshooting](#troubleshooting)
## System Overview
The HVAC Trainer System is a comprehensive solution for managing trainer profiles and providing a public directory with interactive map functionality. The system consists of:
- **Custom Post Type**: `trainer_profile` for storing trainer information
- **Find A Trainer Page**: Public-facing directory with search and filtering
- **MapGeo Integration**: Interactive map with trainer markers and modals
- **Profile Management**: Complete CRUD operations for trainer profiles
- **Taxonomy System**: Categorization for business types, training formats, etc.
### Architecture Diagram
```
WordPress Users (hvac_trainer/hvac_master_trainer)
Trainer Profile Custom Post Type (trainer_profile)
Find A Trainer Page ← MapGeo Integration → Interactive Map
Search/Filter System → AJAX Handlers → Database Queries
```
## Trainer Profile Custom Post Type
### Overview
The `trainer_profile` custom post type stores comprehensive information about HVAC trainers, including personal details, certifications, business information, and location data.
### Core Files
- **Main Handler**: `includes/class-hvac-trainer-profile-manager.php`
- **Settings**: `includes/class-hvac-trainer-profile-settings.php`
- **Status Management**: `includes/class-hvac-trainer-status.php`
### Custom Fields Reference
#### Personal Information
| Field Name | Type | Description | Example |
|------------|------|-------------|---------|
| `trainer_first_name` | string | First name | "John" |
| `trainer_last_name` | string | Last name | "Smith" |
| `trainer_display_name` | string | Public display name | "John Smith" |
| `trainer_city` | string | City location | "Chicago" |
| `trainer_state` | string | State/Province | "Illinois" |
| `trainer_country` | string | Country | "USA" |
| `profile_image_url` | string | Profile photo URL | "https://..." |
| `linkedin_profile_url` | string | LinkedIn profile | "https://linkedin..." |
#### Certification Details
| Field Name | Type | Description | Values |
|------------|------|-------------|--------|
| `certification_type` | string | Certification level | "Certified measureQuick Trainer", "Certified measureQuick Champion" |
| `certification_status` | string | Current status | "Active", "Expired", "Pending", "Disabled" |
| `certification_color` | string | Hex color for MapGeo | "#5077bb", "#f19a42", "#f0f7e8" |
| `date_certified` | string | Certification date | "2024-01-15" |
| `personal_accreditation` | string | Additional certifications | Free text |
#### Business Information
| Field Name | Type | Description |
|------------|------|-------------|
| `annual_revenue_target` | string | Revenue goals |
| `application_details` | string | Registration application details |
#### System Fields
| Field Name | Type | Description |
|------------|------|-------------|
| `user_id` | integer | WordPress user ID |
| `is_public_profile` | string | Visibility flag ("1" or "0") |
| `_last_geocode_attempt` | string | Last geocoding timestamp |
| `geocoded_lat` | string | Latitude coordinate |
| `geocoded_lng` | string | Longitude coordinate |
### Taxonomies
#### Business Type (`business_type`)
- Manufacturer
- Distributor
- Contractor
- Consultant
- Educator
- Government
- Other
#### Training Audience (`training_audience`)
- Anyone (open to the public)
- Industry professionals
- Internal staff in my company
- Registered students/members of my org/institution
#### Training Formats (`training_formats`)
- In-person
- Virtual
- Hybrid
- On-demand
#### Training Locations (`training_locations`)
- Online
- Local
- Regional Travel
- National Travel
- International Travel
#### Training Resources (`training_resources`)
- 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
### Profile Creation Workflow
1. **User Registration**: User completes registration form
2. **Role Assignment**: User assigned `hvac_trainer` or `hvac_master_trainer` role
3. **Profile Creation**: System automatically creates `trainer_profile` post
4. **Data Population**: Registration data mapped to profile fields
5. **Geocoding**: System attempts to geocode trainer location
6. **Approval Process**: Admin reviews and approves profile for public display
### Profile Management
#### Creating Profiles Programmatically
```php
$profile_manager = HVAC_Trainer_Profile_Manager::get_instance();
$profile_data = [
'trainer_first_name' => 'John',
'trainer_last_name' => 'Smith',
'trainer_city' => 'Chicago',
'trainer_state' => 'Illinois',
'certification_type' => 'Certified measureQuick Trainer',
'user_id' => 123,
'is_public_profile' => '1'
];
$profile_id = $profile_manager->create_profile($profile_data);
```
#### Updating Profiles
```php
$profile_manager->update_profile($profile_id, $updated_data);
```
#### Retrieving Profiles
```php
// Get single profile
$profile = $profile_manager->get_profile($profile_id);
// Get all public profiles
$public_profiles = $profile_manager->get_public_profiles();
// Get profiles by criteria
$filtered_profiles = $profile_manager->get_profiles_by_criteria([
'state' => 'Illinois',
'certification_type' => 'Certified measureQuick Trainer'
]);
```
## Find A Trainer Page
### Overview
The Find A Trainer page (`/find-a-trainer/`) provides a public directory of approved trainer profiles with interactive search, filtering, and map functionality.
### Core Files
- **Page Handler**: `includes/find-trainer/class-hvac-find-trainer-page.php`
- **Directory Query**: `includes/find-trainer/class-hvac-trainer-directory-query.php`
- **Contact Handler**: `includes/find-trainer/class-hvac-contact-form-handler.php`
- **Template**: `templates/page-find-trainer.php`
### Features
#### Search Functionality
- **Text Search**: Search by trainer name, city, or state
- **Real-time Results**: AJAX-powered instant search results
- **Autocomplete**: Suggestions as user types
#### Filtering System
- **State/Province Filter**: Location-based filtering
- **Business Type Filter**: Filter by trainer business type
- **Training Format Filter**: Filter by available training formats
- **Training Resources Filter**: Filter by available resources
- **Multiple Filters**: Combine multiple filter criteria
#### Directory Display
- **Card Layout**: Clean trainer cards with essential information
- **Pagination**: Performance-optimized pagination system
- **Sorting**: Certified Trainers first, then Champions, then alphabetical
- **Champion Distinction**: Special styling for measureQuick Champions
#### Contact Integration
- **Contact Forms**: Direct contact forms for each trainer
- **Email Integration**: Automated email delivery to trainers
- **Lead Tracking**: Track contact form submissions
### AJAX Endpoints
| Endpoint | Purpose | Parameters |
|----------|---------|------------|
| `hvac_filter_trainers` | Filter trainers | `filters`, `page`, `per_page` |
| `hvac_search_trainers` | Search trainers | `search`, `page`, `per_page` |
| `hvac_get_filter_options` | Get filter options | None |
| `hvac_submit_contact_form` | Submit contact form | `trainer_id`, `name`, `email`, `message` |
### Frontend Implementation
#### JavaScript Integration
```javascript
// Initialize Find A Trainer functionality
jQuery(document).ready(function($) {
HVAC_FindTrainer.init({
ajax_url: hvac_find_trainer.ajax_url,
nonce: hvac_find_trainer.nonce,
filters: {
state: [],
business_type: [],
training_format: []
}
});
});
```
#### CSS Classes
| Class | Purpose |
|-------|---------|
| `.hvac-trainer-card` | Individual trainer card container |
| `.hvac-trainer-card-certified` | Certified trainer styling |
| `.hvac-champion-card` | Champion trainer styling |
| `.hvac-trainer-filters` | Filter panel container |
| `.hvac-search-box` | Search input container |
| `.hvac-trainer-modal` | Trainer profile modal |
## MapGeo Integration
### Overview
The MapGeo integration provides an interactive map showing trainer locations with clickable markers that open detailed trainer modals.
### Core Files
- **Integration Handler**: `includes/find-trainer/class-hvac-mapgeo-integration.php`
- **Map Configuration**: Integrated in Find A Trainer page template
### Features
#### Interactive Map
- **Map ID**: 5872 (configured in MapGeo plugin)
- **Marker Display**: Trainers with geocoded coordinates appear as markers
- **Color Coding**: Different colors based on certification type
- **Click Handlers**: Custom click actions for trainer markers
#### Performance Optimizations
- **Request Deduplication**: Prevents duplicate AJAX calls
- **Caching System**: Caches trainer data for instant subsequent access
- **Click Throttling**: Prevents rapid-fire clicking issues
- **Fallback Handling**: Graceful degradation when data unavailable
#### Modal System
- **Trainer Profiles**: Complete trainer information in popup modals
- **Champion Filtering**: Champions don't show modals (directory-only display)
- **Contact Integration**: Direct contact forms within modals
- **Responsive Design**: Mobile-optimized modal display
### Technical Implementation
#### MapGeo Marker Configuration
```php
public function modify_map_layout($meta, $map_id = null) {
// Only process for our specific map (5872)
if ($map_id && $map_id != $this->map_id) {
return $meta;
}
// Configure markers with trainer profile data
foreach ($meta['markers'] as &$marker) {
$trainer_profile_id = $this->find_trainer_profile_by_name($marker['title']);
if ($trainer_profile_id) {
$marker['action'] = 'hvac_show_trainer_modal';
$marker['hvac_profile_id'] = $trainer_profile_id;
$marker['id'] = 'trainer_' . $trainer_profile_id;
}
}
return $meta;
}
```
#### JavaScript Modal Handler
```javascript
window.hvac_show_trainer_modal = function(markerData) {
var profileId = markerData.hvac_profile_id;
// Check cache first for immediate response
if (window.hvacTrainerDataCache[profileId]) {
var cachedData = window.hvacTrainerDataCache[profileId];
if (typeof window.showTrainerModal === 'function') {
window.showTrainerModal(cachedData);
}
return;
}
// Fetch profile data via AJAX if not cached
// Implementation handles caching, error handling, and modal display
};
```
### Certification Color Coding
| Certification Type | Color | Usage |
|--------------------|-------|-------|
| Certified measureQuick Trainer | `#5077bb` | Primary trainer markers |
| Certified measureQuick Champion | `#f19a42` | Champion markers (no modals) |
| Default/Other | `#f0f7e8` | Fallback color |
## User Roles & Permissions
### HVAC Trainer (`hvac_trainer`)
#### Core Capabilities
- `read` - Basic WordPress read access
- `upload_files` - File upload capability
- `edit_hvac_profile` - Edit own trainer profile
- `view_hvac_dashboard` - Access trainer dashboard
- `manage_hvac_events` - Manage own events
- `manage_attendees` - Manage event attendees
- `email_attendees` - Send emails to attendees
#### Events Calendar Integration
- `publish_tribe_events` - Create and publish events
- `edit_tribe_events` - Edit events
- `delete_tribe_events` - Delete events
- `edit_published_tribe_events` - Edit published events
- `delete_published_tribe_events` - Delete published events
- `read_private_tribe_events` - View private events
### HVAC Master Trainer (`hvac_master_trainer`)
#### Extended Capabilities
- All trainer capabilities
- Access to master dashboard with analytics
- View aggregate trainer statistics
- Enhanced reporting capabilities
### Permission Checks
```php
// Check if user can edit trainer profiles
if (current_user_can('edit_hvac_profile')) {
// Allow profile editing
}
// Check for master trainer capabilities
if (current_user_can('hvac_master_trainer')) {
// Show master trainer features
}
```
## API Reference
### AJAX Handlers
#### Get Trainer Profile
**Endpoint**: `hvac_get_trainer_profile`
**Method**: POST
**Parameters**:
- `profile_id` (integer) - Trainer profile ID
- `nonce` (string) - Security nonce
**Response**:
```json
{
"success": true,
"data": {
"profile_id": 5840,
"user_id": "31",
"name": "Jeremy Begley",
"city": "Knoxville",
"state": "Tennessee",
"certification_type": "Certified measureQuick Trainer",
"profile_image": "https://...",
"business_type": "Independent Contractor",
"event_count": 5,
"training_formats": "In-Person, Virtual",
"training_locations": "On-site, Remote",
"upcoming_events": []
}
}
```
#### Filter Trainers
**Endpoint**: `hvac_filter_trainers`
**Method**: POST
**Parameters**:
- `filters` (array) - Filter criteria
- `page` (integer) - Page number
- `per_page` (integer) - Results per page
- `nonce` (string) - Security nonce
**Response**:
```json
{
"success": true,
"data": {
"html": "<div class='hvac-trainer-card'>...</div>",
"pagination": "<div class='hvac-pagination'>...</div>",
"count": 25,
"page": 1,
"max_pages": 3
}
}
```
#### Search Trainers
**Endpoint**: `hvac_search_trainers`
**Method**: POST
**Parameters**:
- `search` (string) - Search query
- `page` (integer) - Page number
- `per_page` (integer) - Results per page
- `nonce` (string) - Security nonce
**Response**: Same format as filter trainers
### PHP API Methods
#### HVAC_Trainer_Profile_Manager Methods
```php
// Get instance
$manager = HVAC_Trainer_Profile_Manager::get_instance();
// Create profile
$profile_id = $manager->create_profile($data);
// Update profile
$manager->update_profile($profile_id, $data);
// Get profile
$profile = $manager->get_profile($profile_id);
// Get public profiles
$profiles = $manager->get_public_profiles();
// Delete profile
$manager->delete_profile($profile_id);
```
#### HVAC_Find_Trainer_Page Methods
```php
// Get instance
$page = HVAC_Find_Trainer_Page::get_instance();
// Render trainer cards
$page->render_trainer_cards($trainers);
// Get filter options
$options = $page->get_filter_options();
// Build query args
$args = $page->build_query_args($filters);
```
## Frontend Components
### CSS Architecture
#### Find A Trainer Styles (`assets/css/find-trainer.css`)
```css
/* Main container */
.hvac-find-trainer-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* Search and filters */
.hvac-search-filters {
display: flex;
gap: 20px;
margin-bottom: 30px;
flex-wrap: wrap;
}
/* Trainer cards */
.hvac-trainer-cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.hvac-trainer-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: transform 0.2s, box-shadow 0.2s;
}
.hvac-trainer-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}
/* Certified trainer styling */
.hvac-trainer-card-certified {
border-color: #5077bb;
}
.hvac-trainer-card-certified::before {
content: "✓ Certified Trainer";
background: #5077bb;
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
position: absolute;
top: -8px;
right: 10px;
}
/* Champion styling */
.hvac-champion-card {
border-color: #f19a42;
background: linear-gradient(135deg, #fff 0%, #fef9f5 100%);
}
.hvac-champion-card .hvac-trainer-name {
color: #f19a42;
font-weight: bold;
}
```
#### MapGeo Integration Styles
```css
/* MapGeo modal styling */
.hvac-trainer-modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
border-radius: 8px;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
max-width: 500px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
z-index: 10000;
}
.hvac-modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 9999;
}
/* Map markers */
.hvac-trainer-marker {
cursor: pointer;
transition: all 0.2s;
}
.hvac-trainer-marker:hover {
transform: scale(1.1);
}
```
### JavaScript Components
#### Find A Trainer JavaScript (`assets/js/find-trainer.js`)
```javascript
var HVAC_FindTrainer = {
// Configuration
config: {
ajax_url: '',
nonce: '',
filters: {},
current_page: 1,
per_page: 12
},
// Initialize
init: function(options) {
this.config = Object.assign(this.config, options);
this.bindEvents();
this.loadInitialResults();
},
// Event bindings
bindEvents: function() {
// Search functionality
jQuery('#hvac-trainer-search').on('input', this.handleSearch.bind(this));
// Filter changes
jQuery('.hvac-filter-select').on('change', this.handleFilterChange.bind(this));
// Pagination
jQuery(document).on('click', '.hvac-page-link', this.handlePagination.bind(this));
// Trainer card clicks
jQuery(document).on('click', '.hvac-open-profile', this.openTrainerModal.bind(this));
},
// Handle search input
handleSearch: function(e) {
var query = jQuery(e.target).val();
this.performSearch(query);
},
// Handle filter changes
handleFilterChange: function(e) {
var $filter = jQuery(e.target);
var filterType = $filter.data('filter');
var value = $filter.val();
this.config.filters[filterType] = value;
this.applyFilters();
},
// Perform AJAX search
performSearch: function(query) {
jQuery.ajax({
url: this.config.ajax_url,
method: 'POST',
data: {
action: 'hvac_search_trainers',
search: query,
page: 1,
per_page: this.config.per_page,
nonce: this.config.nonce
},
success: this.updateResults.bind(this)
});
},
// Apply filters
applyFilters: function() {
jQuery.ajax({
url: this.config.ajax_url,
method: 'POST',
data: {
action: 'hvac_filter_trainers',
filters: this.config.filters,
page: 1,
per_page: this.config.per_page,
nonce: this.config.nonce
},
success: this.updateResults.bind(this)
});
},
// Update results display
updateResults: function(response) {
if (response.success) {
jQuery('.hvac-trainer-cards').html(response.data.html);
jQuery('.hvac-pagination').html(response.data.pagination);
this.updateResultsCount(response.data.count);
}
},
// Open trainer modal
openTrainerModal: function(e) {
e.preventDefault();
var profileId = jQuery(e.target).data('profile-id');
this.showTrainerProfile(profileId);
}
};
```
## Database Schema
### Trainer Profile Posts Table
```sql
-- wp_posts table entries for trainer_profile post type
SELECT
ID,
post_title,
post_status,
post_type,
post_date
FROM wp_posts
WHERE post_type = 'trainer_profile';
```
### Trainer Profile Meta Data
```sql
-- wp_postmeta table entries for trainer profiles
SELECT
post_id,
meta_key,
meta_value
FROM wp_postmeta
WHERE post_id IN (
SELECT ID FROM wp_posts WHERE post_type = 'trainer_profile'
)
ORDER BY post_id, meta_key;
```
### Taxonomy Relationships
```sql
-- Get trainer profiles with business type taxonomy
SELECT
p.ID,
p.post_title,
t.name as business_type
FROM wp_posts p
LEFT JOIN wp_term_relationships tr ON p.ID = tr.object_id
LEFT JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN wp_terms t ON tt.term_id = t.term_id
WHERE p.post_type = 'trainer_profile'
AND tt.taxonomy = 'business_type';
```
### Key Database Queries
#### Get Public Trainer Profiles
```php
$args = [
'post_type' => 'trainer_profile',
'post_status' => 'publish',
'posts_per_page' => -1,
'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);
```
#### Get Geocoded Trainers for Map
```php
$args = [
'post_type' => 'trainer_profile',
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => [
'relation' => 'AND',
[
'key' => 'is_public_profile',
'value' => '1',
'compare' => '='
],
[
'key' => 'geocoded_lat',
'compare' => 'EXISTS'
],
[
'key' => 'geocoded_lng',
'compare' => 'EXISTS'
]
]
];
```
## Performance Optimizations
### MapGeo Integration Optimizations
#### Request Deduplication
```javascript
// Prevent duplicate AJAX requests
window.hvacTrainerDataCache = {};
window.hvacPendingRequests = {};
function getTrainerProfile(profileId) {
// Check cache first
if (window.hvacTrainerDataCache[profileId]) {
return Promise.resolve(window.hvacTrainerDataCache[profileId]);
}
// Check if request already pending
if (window.hvacPendingRequests[profileId]) {
return window.hvacPendingRequests[profileId];
}
// Make new request and cache promise
window.hvacPendingRequests[profileId] = makeAjaxRequest(profileId)
.then(function(data) {
window.hvacTrainerDataCache[profileId] = data;
delete window.hvacPendingRequests[profileId];
return data;
});
return window.hvacPendingRequests[profileId];
}
```
#### Click Throttling
```javascript
// Prevent rapid-fire clicking
var lastClickTime = 0;
function handleMarkerClick(e) {
var now = Date.now();
if (now - lastClickTime < 500) {
return; // Throttle clicks to 500ms intervals
}
lastClickTime = now;
// Process click
processMarkerClick(e);
}
```
### Database Query Optimization
#### Efficient Trainer Queries
```php
// Use meta_query for better performance with indexes
$args = [
'post_type' => 'trainer_profile',
'posts_per_page' => 12,
'paged' => $page,
'meta_query' => [
'relation' => 'AND',
[
'key' => 'is_public_profile',
'value' => '1',
'compare' => '='
]
],
'fields' => 'ids' // Only get IDs when possible
];
// Add user status filter efficiently
$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)) {
$args['meta_query'][] = [
'key' => 'user_id',
'value' => $approved_user_ids,
'compare' => 'IN'
];
}
```
#### Caching Strategies
```php
// Cache expensive queries
$cache_key = 'hvac_public_trainers_' . md5(serialize($args));
$trainers = wp_cache_get($cache_key, 'hvac_trainers');
if (false === $trainers) {
$query = new WP_Query($args);
$trainers = $query->posts;
wp_cache_set($cache_key, $trainers, 'hvac_trainers', HOUR_IN_SECONDS);
}
```
## Troubleshooting
### Common Issues
#### Trainers Not Appearing on Map
**Symptoms**: Trainers visible in directory but not on MapGeo map
**Causes**:
1. Missing geocoding data (latitude/longitude)
2. MapGeo configuration issues
3. Profile not public
**Solutions**:
```php
// Check geocoding status
$lat = get_post_meta($profile_id, 'geocoded_lat', true);
$lng = get_post_meta($profile_id, 'geocoded_lng', true);
if (empty($lat) || empty($lng)) {
// Trigger geocoding
$geocoding_service = HVAC_Geocoding_Service::get_instance();
$geocoding_service->geocode_trainer($profile_id);
}
// Check public status
$is_public = get_post_meta($profile_id, 'is_public_profile', true);
if ($is_public !== '1') {
update_post_meta($profile_id, 'is_public_profile', '1');
}
```
#### Modal Not Opening
**Symptoms**: Clicking map markers doesn't open trainer modal
**Causes**:
1. JavaScript errors preventing modal system
2. Missing trainer data
3. Champion profiles (intentionally no modal)
**Solutions**:
```javascript
// Debug modal system
console.log('MapGeo integration loaded:', typeof window.hvac_show_trainer_modal);
console.log('Modal function available:', typeof window.showTrainerModal);
// Check if trainer is Champion (no modal should show)
if (trainerData.certification_type === 'Certified measureQuick Champion') {
console.log('Champion detected - no modal shown');
return;
}
```
#### Search/Filter Not Working
**Symptoms**: Search and filters not returning results
**Causes**:
1. AJAX endpoint errors
2. Nonce verification failures
3. Database query issues
**Solutions**:
```php
// Debug AJAX handlers
add_action('wp_ajax_hvac_filter_trainers', function() {
error_log('Filter trainers AJAX called');
error_log('POST data: ' . print_r($_POST, true));
// Verify nonce
if (!wp_verify_nonce($_POST['nonce'], 'hvac_find_trainer')) {
error_log('Nonce verification failed');
wp_send_json_error('Invalid nonce');
return;
}
// Continue with handler...
});
```
#### Performance Issues
**Symptoms**: Slow loading times, multiple AJAX requests
**Causes**:
1. Duplicate requests not prevented
2. Missing caching
3. Inefficient database queries
**Solutions**:
1. Implement request deduplication
2. Add caching layers
3. Optimize database queries with proper indexes
4. Use pagination for large datasets
### Debug Mode
Enable debug logging for troubleshooting:
```php
// Add to wp-config.php
define('HVAC_DEBUG', true);
// In plugin code
if (defined('HVAC_DEBUG') && HVAC_DEBUG) {
error_log('HVAC Debug: ' . $message);
}
```
### Performance Monitoring
Monitor system performance:
```javascript
// Track AJAX request timing
var startTime = performance.now();
jQuery.ajax({
// ... ajax config
success: function(response) {
var endTime = performance.now();
console.log('AJAX request took:', (endTime - startTime), 'milliseconds');
}
});
```
## Conclusion
The HVAC Trainer System provides a comprehensive solution for managing trainer profiles and presenting them through an interactive Find A Trainer directory. The system is designed for performance, scalability, and user experience, with extensive customization options and robust error handling.
For additional support or feature requests, refer to the main plugin documentation or contact the development team.