- Implement singleton pattern for HVAC_Enhanced_Settings to prevent duplicate initialization - Fix jQuery selector error by checking for valid hash selectors before using $(href) - Add default email templates with professional copy for trainer notifications - Update plugin version to 1.0.1 for cache busting - Remove duplicate Enhanced Settings initialization from HVAC_Community_Events - Add force cache refresh suffix to admin scripts This resolves the duplicate content issue on email templates page and fixes JavaScript errors in the admin interface. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			644 lines
		
	
	
		
			No EOL
		
	
	
		
			29 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			644 lines
		
	
	
		
			No EOL
		
	
	
		
			29 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | ||
| /**
 | ||
|  * HVAC Dashboard Handler
 | ||
|  * 
 | ||
|  * Handles dashboard page rendering and functionality
 | ||
|  * 
 | ||
|  * @package HVAC_Community_Events
 | ||
|  * @since 1.0.0
 | ||
|  */
 | ||
| 
 | ||
| if (!defined('ABSPATH')) {
 | ||
|     exit;
 | ||
| }
 | ||
| 
 | ||
| class HVAC_Dashboard {
 | ||
|     
 | ||
|     /**
 | ||
|      * Constructor
 | ||
|      */
 | ||
|     public function __construct() {
 | ||
|         add_action('init', array($this, 'register_shortcode'));
 | ||
|         // Use higher priority to run after shortcode processing
 | ||
|         add_filter('the_content', array($this, 'render_dashboard_content'), 99);
 | ||
|         add_action('wp_enqueue_scripts', array($this, 'enqueue_dashboard_assets'));
 | ||
|         
 | ||
|         // AJAX handler for events filtering
 | ||
|         add_action('wp_ajax_hvac_filter_events', array($this, 'ajax_filter_events'));
 | ||
|     }
 | ||
|     
 | ||
|     /**
 | ||
|      * Register dashboard shortcode
 | ||
|      */
 | ||
|     public function register_shortcode() {
 | ||
|         add_shortcode('hvac_trainer_dashboard', array($this, 'render_dashboard_shortcode'));
 | ||
|     }
 | ||
|     
 | ||
|     /**
 | ||
|      * Render dashboard via shortcode
 | ||
|      */
 | ||
|     public function render_dashboard_shortcode($atts) {
 | ||
|         // Check if user is logged in and has proper permissions
 | ||
|         if (!is_user_logged_in()) {
 | ||
|             return '<div class="hvac-login-notice">
 | ||
|                 <p>Please log in to view the dashboard.</p>
 | ||
|                 <p><a href="' . esc_url(home_url('/community-login/')) . '" class="button">Login</a></p>
 | ||
|             </div>';
 | ||
|         }
 | ||
|         
 | ||
|         if (!current_user_can('view_hvac_dashboard')) {
 | ||
|             return '<div class="hvac-access-denied">
 | ||
|                 <p>You do not have permission to view this dashboard.</p>
 | ||
|             </div>';
 | ||
|         }
 | ||
|         
 | ||
|         return $this->get_dashboard_content();
 | ||
|     }
 | ||
|     
 | ||
|     /**
 | ||
|      * Render dashboard content for the page
 | ||
|      */
 | ||
|     public function render_dashboard_content($content) {
 | ||
|         // Only process if content contains our shortcode
 | ||
|         if (has_shortcode($content, 'hvac_trainer_dashboard')) {
 | ||
|             return do_shortcode($content);
 | ||
|         }
 | ||
|         
 | ||
|         return $content;
 | ||
|     }
 | ||
|     
 | ||
|     /**
 | ||
|      * Get dashboard content
 | ||
|      */
 | ||
|     private function get_dashboard_content() {
 | ||
|         $user_id = get_current_user_id();
 | ||
|         
 | ||
|         // Include dashboard data class
 | ||
|         require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-dashboard-data.php';
 | ||
|         $dashboard_data = new HVAC_Dashboard_Data($user_id);
 | ||
|         
 | ||
|         // Get data
 | ||
|         $data = array(
 | ||
|             'total_events' => $dashboard_data->get_total_events_count(),
 | ||
|             'upcoming_events' => $dashboard_data->get_upcoming_events_count(),
 | ||
|             'past_events' => $dashboard_data->get_past_events_count(),
 | ||
|             'total_sold' => $dashboard_data->get_total_tickets_sold(),
 | ||
|             'total_revenue' => $dashboard_data->get_total_revenue(),
 | ||
|             'revenue_target' => $dashboard_data->get_annual_revenue_target(),
 | ||
|             'events_table' => $dashboard_data->get_events_table_data(isset($_GET['event_status']) ? sanitize_key($_GET['event_status']) : 'all'),
 | ||
|             'current_filter' => isset($_GET['event_status']) ? sanitize_key($_GET['event_status']) : 'all'
 | ||
|         );
 | ||
|         
 | ||
|         // Get dashboard HTML
 | ||
|         ob_start();
 | ||
|         ?>
 | ||
|         <div class="hvac-dashboard-wrapper">
 | ||
|             <!-- Dashboard Header & Navigation -->
 | ||
|             <div class="hvac-dashboard-header">
 | ||
|                 <h1>Trainer Dashboard</h1>
 | ||
|                 <div class="hvac-dashboard-nav">
 | ||
|                     <a href="<?php echo esc_url(home_url('/manage-event/')); ?>" class="button hvac-button hvac-button-primary">Create Event</a>
 | ||
|                     <a href="<?php echo esc_url(home_url('/certificate-reports/')); ?>" class="button hvac-button hvac-button-primary">Certificate Reports</a>
 | ||
|                     <a href="<?php echo esc_url(home_url('/trainer-profile/')); ?>" class="button hvac-button hvac-button-secondary">View Profile</a>
 | ||
|                     <a href="<?php echo esc_url(wp_logout_url(home_url('/community-login/'))); ?>" class="button hvac-button hvac-button-secondary">Logout</a>
 | ||
|                 </div>
 | ||
|             </div>
 | ||
| 
 | ||
|             <!-- Statistics Section -->
 | ||
|             <section class="hvac-dashboard-stats">
 | ||
|                 <h2>Your Stats</h2>
 | ||
|                 <div class="hvac-stats-row">
 | ||
|                     <!-- Total Events -->
 | ||
|                     <div class="hvac-stat-col"><div class="hvac-stat-card">
 | ||
|                         <h3>Total Events</h3>
 | ||
|                         <p class="metric-value"><?php echo esc_html($data['total_events']); ?></p>
 | ||
|                     </div></div>
 | ||
| 
 | ||
|                     <!-- Upcoming Events -->
 | ||
|                     <div class="hvac-stat-col"><div class="hvac-stat-card">
 | ||
|                         <h3>Upcoming Events</h3>
 | ||
|                         <p class="metric-value"><?php echo esc_html($data['upcoming_events']); ?></p>
 | ||
|                     </div></div>
 | ||
| 
 | ||
|                     <!-- Past Events -->
 | ||
|                     <div class="hvac-stat-col"><div class="hvac-stat-card">
 | ||
|                         <h3>Past Events</h3>
 | ||
|                         <p class="metric-value"><?php echo esc_html($data['past_events']); ?></p>
 | ||
|                     </div></div>
 | ||
| 
 | ||
|                     <!-- Total Tickets Sold -->
 | ||
|                     <div class="hvac-stat-col"><div class="hvac-stat-card">
 | ||
|                         <h3>Tickets Sold</h3>
 | ||
|                         <p class="metric-value"><?php echo esc_html($data['total_sold']); ?></p>
 | ||
|                     </div></div>
 | ||
| 
 | ||
|                     <!-- Total Revenue -->
 | ||
|                     <div class="hvac-stat-col"><div class="hvac-stat-card">
 | ||
|                         <h3>Total Revenue</h3>
 | ||
|                         <p class="metric-value">$<?php echo esc_html(number_format($data['total_revenue'], 2)); ?></p>
 | ||
|                         <?php if ($data['revenue_target']) : ?>
 | ||
|                             <small>Target: $<?php echo esc_html(number_format($data['revenue_target'], 2)); ?></small>
 | ||
|                         <?php endif; ?>
 | ||
|                     </div></div>
 | ||
|                 </div>
 | ||
|             </section>
 | ||
| 
 | ||
|             <!-- Events Table Section -->
 | ||
|             <section class="hvac-dashboard-events">
 | ||
|                 <h2>Your Events</h2>
 | ||
| 
 | ||
|                 <!-- Tab Filters -->
 | ||
|                 <div class="hvac-event-filters">
 | ||
|                     <span>Filter: </span>
 | ||
|                     <?php 
 | ||
|                     $dashboard_url = get_permalink();
 | ||
|                     $filter_statuses = array('all', 'publish', 'draft', 'pending', 'private');
 | ||
|                     foreach ($filter_statuses as $status) :
 | ||
|                         $url = ($status === 'all') ? remove_query_arg('event_status', $dashboard_url) : add_query_arg('event_status', $status, $dashboard_url);
 | ||
|                         $class = ($status === $data['current_filter']) ? 'hvac-filter hvac-filter-active ast-button-primary' : 'hvac-filter ast-button-secondary';
 | ||
|                     ?>
 | ||
|                         <a href="<?php echo esc_url($url); ?>" class="ast-button <?php echo esc_attr($class); ?>" data-status="<?php echo esc_attr($status); ?>"><?php echo esc_html(ucfirst($status)); ?></a>
 | ||
|                     <?php endforeach; ?>
 | ||
|                 </div>
 | ||
| 
 | ||
|                 <!-- Events Table -->
 | ||
|                 <div class="hvac-events-table-wrapper">
 | ||
|                     <?php if (!empty($data['events_table'])) : ?>
 | ||
|                         <table class="hvac-events-table">
 | ||
|                             <thead>
 | ||
|                                 <tr>
 | ||
|                                     <th>Status</th>
 | ||
|                                     <th>Event Name</th>
 | ||
|                                     <th>Date</th>
 | ||
|                                     <th>Organizer</th>
 | ||
|                                     <th>Capacity</th>
 | ||
|                                     <th>Sold</th>
 | ||
|                                     <th>Revenue</th>
 | ||
|                                     <th>Actions</th>
 | ||
|                                 </tr>
 | ||
|                             </thead>
 | ||
|                             <tbody>
 | ||
|                                 <?php foreach ($data['events_table'] as $event) : ?>
 | ||
|                                     <tr>
 | ||
|                                         <td><?php echo esc_html(ucfirst($event['status'])); ?></td>
 | ||
|                                         <td>
 | ||
|                                             <strong><a href="<?php echo esc_url($event['link']); ?>" target="_blank"><?php echo esc_html($event['name']); ?></a></strong>
 | ||
|                                         </td>
 | ||
|                                         <td><?php echo esc_html(date('Y-m-d H:i', $event['start_date_ts'])); ?></td>
 | ||
|                                         <td><?php 
 | ||
|                                             if (function_exists('tribe_get_organizer')) {
 | ||
|                                                 echo esc_html(tribe_get_organizer($event['organizer_id']));
 | ||
|                                             } else {
 | ||
|                                                 echo 'Organizer ID: ' . esc_html($event['organizer_id']);
 | ||
|                                             }
 | ||
|                                         ?></td>
 | ||
|                                         <td><?php echo esc_html($event['capacity']); ?></td>
 | ||
|                                         <td><?php echo esc_html($event['sold']); ?></td>
 | ||
|                                         <td>$<?php echo esc_html(number_format($event['revenue'], 2)); ?></td>
 | ||
|                                         <td>
 | ||
|                                             <?php
 | ||
|                                             $edit_url = add_query_arg('event_id', $event['id'], home_url('/manage-event/'));
 | ||
|                                             $summary_url = get_permalink($event['id']);
 | ||
|                                             ?>
 | ||
|                                             <a href="<?php echo esc_url($edit_url); ?>">Edit</a> |
 | ||
|                                             <a href="<?php echo esc_url($summary_url); ?>">Summary</a>
 | ||
|                                         </td>
 | ||
|                                     </tr>
 | ||
|                                 <?php endforeach; ?>
 | ||
|                             </tbody>
 | ||
|                         </table>
 | ||
|                     <?php else : ?>
 | ||
|                         <p>No events found.</p>
 | ||
|                     <?php endif; ?>
 | ||
|                 </div>
 | ||
|             </section>
 | ||
|         </div>
 | ||
|         <?php
 | ||
|         return ob_get_clean();
 | ||
|     }
 | ||
|     
 | ||
|     /**
 | ||
|      * Handle AJAX request for filtered events table
 | ||
|      */
 | ||
|     public function ajax_filter_events() {
 | ||
|         // Check nonce
 | ||
|         if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hvac_dashboard_nonce')) {
 | ||
|             wp_send_json_error(array('message' => 'Security check failed.'));
 | ||
|             return;
 | ||
|         }
 | ||
|         
 | ||
|         // Get current user ID
 | ||
|         $user_id = get_current_user_id();
 | ||
|         if (!$user_id || !current_user_can('view_hvac_dashboard')) {
 | ||
|             wp_send_json_error(array('message' => 'Access denied.'));
 | ||
|             return;
 | ||
|         }
 | ||
|         
 | ||
|         // Get all filters and parameters
 | ||
|         $args = array(
 | ||
|             'status' => isset($_POST['status']) ? sanitize_key($_POST['status']) : 'all',
 | ||
|             'search' => isset($_POST['search']) ? sanitize_text_field($_POST['search']) : '',
 | ||
|             'orderby' => isset($_POST['orderby']) ? sanitize_key($_POST['orderby']) : 'date',
 | ||
|             'order' => isset($_POST['order']) ? sanitize_key($_POST['order']) : 'DESC',
 | ||
|             'page' => isset($_POST['page']) ? absint($_POST['page']) : 1,
 | ||
|             'per_page' => isset($_POST['per_page']) ? absint($_POST['per_page']) : 10,
 | ||
|             'date_from' => isset($_POST['date_from']) ? sanitize_text_field($_POST['date_from']) : '',
 | ||
|             'date_to' => isset($_POST['date_to']) ? sanitize_text_field($_POST['date_to']) : '',
 | ||
|         );
 | ||
|         
 | ||
|         // Include dashboard data class
 | ||
|         require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-dashboard-data.php';
 | ||
|         $dashboard_data = new HVAC_Dashboard_Data($user_id);
 | ||
|         
 | ||
|         // Get filtered events data
 | ||
|         $result = $dashboard_data->get_events_table_data($args);
 | ||
|         $events = $result['events'];
 | ||
|         $pagination = $result['pagination'];
 | ||
|         
 | ||
|         // Build HTML for events table
 | ||
|         ob_start();
 | ||
|         
 | ||
|         ?>
 | ||
|         <table class="hvac-events-table wp-list-table widefat fixed striped">
 | ||
|             <thead>
 | ||
|                 <tr>
 | ||
|                     <th scope="col" class="manage-column column-status sortable <?php echo ($args['orderby'] === 'status') ? 'sorted ' . strtolower($args['order']) : ''; ?>">
 | ||
|                         <a href="#" data-orderby="status" data-order="<?php echo ($args['orderby'] === 'status' && $args['order'] === 'ASC') ? 'DESC' : 'ASC'; ?>">
 | ||
|                             <span>Status</span>
 | ||
|                             <span class="sorting-indicators">
 | ||
|                                 <span class="sorting-indicator asc" aria-hidden="true"></span>
 | ||
|                                 <span class="sorting-indicator desc" aria-hidden="true"></span>
 | ||
|                             </span>
 | ||
|                         </a>
 | ||
|                     </th>
 | ||
|                     <th scope="col" class="manage-column column-title sortable <?php echo ($args['orderby'] === 'name') ? 'sorted ' . strtolower($args['order']) : ''; ?>">
 | ||
|                         <a href="#" data-orderby="name" data-order="<?php echo ($args['orderby'] === 'name' && $args['order'] === 'ASC') ? 'DESC' : 'ASC'; ?>">
 | ||
|                             <span>Event Name</span>
 | ||
|                             <span class="sorting-indicators">
 | ||
|                                 <span class="sorting-indicator asc" aria-hidden="true"></span>
 | ||
|                                 <span class="sorting-indicator desc" aria-hidden="true"></span>
 | ||
|                             </span>
 | ||
|                         </a>
 | ||
|                     </th>
 | ||
|                     <th scope="col" class="manage-column column-date sortable <?php echo ($args['orderby'] === 'date') ? 'sorted ' . strtolower($args['order']) : ''; ?>">
 | ||
|                         <a href="#" data-orderby="date" data-order="<?php echo ($args['orderby'] === 'date' && $args['order'] === 'ASC') ? 'DESC' : 'ASC'; ?>">
 | ||
|                             <span>Date</span>
 | ||
|                             <span class="sorting-indicators">
 | ||
|                                 <span class="sorting-indicator asc" aria-hidden="true"></span>
 | ||
|                                 <span class="sorting-indicator desc" aria-hidden="true"></span>
 | ||
|                             </span>
 | ||
|                         </a>
 | ||
|                     </th>
 | ||
|                     <th scope="col" class="manage-column column-organizer">Organizer</th>
 | ||
|                     <th scope="col" class="manage-column column-capacity sortable <?php echo ($args['orderby'] === 'capacity') ? 'sorted ' . strtolower($args['order']) : ''; ?>">
 | ||
|                         <a href="#" data-orderby="capacity" data-order="<?php echo ($args['orderby'] === 'capacity' && $args['order'] === 'ASC') ? 'DESC' : 'ASC'; ?>">
 | ||
|                             <span>Capacity</span>
 | ||
|                             <span class="sorting-indicators">
 | ||
|                                 <span class="sorting-indicator asc" aria-hidden="true"></span>
 | ||
|                                 <span class="sorting-indicator desc" aria-hidden="true"></span>
 | ||
|                             </span>
 | ||
|                         </a>
 | ||
|                     </th>
 | ||
|                     <th scope="col" class="manage-column column-sold sortable <?php echo ($args['orderby'] === 'sold') ? 'sorted ' . strtolower($args['order']) : ''; ?>">
 | ||
|                         <a href="#" data-orderby="sold" data-order="<?php echo ($args['orderby'] === 'sold' && $args['order'] === 'ASC') ? 'DESC' : 'ASC'; ?>">
 | ||
|                             <span>Sold</span>
 | ||
|                             <span class="sorting-indicators">
 | ||
|                                 <span class="sorting-indicator asc" aria-hidden="true"></span>
 | ||
|                                 <span class="sorting-indicator desc" aria-hidden="true"></span>
 | ||
|                             </span>
 | ||
|                         </a>
 | ||
|                     </th>
 | ||
|                     <th scope="col" class="manage-column column-revenue sortable <?php echo ($args['orderby'] === 'revenue') ? 'sorted ' . strtolower($args['order']) : ''; ?>">
 | ||
|                         <a href="#" data-orderby="revenue" data-order="<?php echo ($args['orderby'] === 'revenue' && $args['order'] === 'ASC') ? 'DESC' : 'ASC'; ?>">
 | ||
|                             <span>Revenue</span>
 | ||
|                             <span class="sorting-indicators">
 | ||
|                                 <span class="sorting-indicator asc" aria-hidden="true"></span>
 | ||
|                                 <span class="sorting-indicator desc" aria-hidden="true"></span>
 | ||
|                             </span>
 | ||
|                         </a>
 | ||
|                     </th>
 | ||
|                     <th scope="col" class="manage-column column-actions">Actions</th>
 | ||
|                 </tr>
 | ||
|             </thead>
 | ||
|             <tbody id="the-list">
 | ||
|                 <?php if (!empty($events)) : ?>
 | ||
|                     <?php foreach ($events as $event) : ?>
 | ||
|                         <tr>
 | ||
|                             <td class="column-status"><?php echo esc_html(ucfirst($event['status'])); ?></td>
 | ||
|                             <td class="column-title">
 | ||
|                                 <strong><a href="<?php echo esc_url($event['link']); ?>" target="_blank"><?php echo esc_html($event['name']); ?></a></strong>
 | ||
|                             </td>
 | ||
|                             <td class="column-date"><?php echo esc_html(date('Y-m-d H:i', $event['start_date_ts'])); ?></td>
 | ||
|                             <td class="column-organizer"><?php 
 | ||
|                                 if (function_exists('tribe_get_organizer')) {
 | ||
|                                     echo esc_html(tribe_get_organizer($event['organizer_id']));
 | ||
|                                 } else {
 | ||
|                                     echo 'Organizer ID: ' . esc_html($event['organizer_id']);
 | ||
|                                 }
 | ||
|                             ?></td>
 | ||
|                             <td class="column-capacity"><?php echo esc_html($event['capacity']); ?></td>
 | ||
|                             <td class="column-sold"><?php echo esc_html($event['sold']); ?></td>
 | ||
|                             <td class="column-revenue">$<?php echo esc_html(number_format($event['revenue'], 2)); ?></td>
 | ||
|                             <td class="column-actions">
 | ||
|                                 <?php
 | ||
|                                 $edit_url = add_query_arg('event_id', $event['id'], home_url('/manage-event/'));
 | ||
|                                 $summary_url = add_query_arg('event_id', $event['id'], home_url('/event-summary/'));
 | ||
|                                 $view_url = get_permalink($event['id']);
 | ||
|                                 ?>
 | ||
|                                 <a href="<?php echo esc_url($edit_url); ?>">Edit</a> |
 | ||
|                                 <a href="<?php echo esc_url($summary_url); ?>">Summary</a> |
 | ||
|                                 <a href="<?php echo esc_url($view_url); ?>" target="_blank">View</a>
 | ||
|                             </td>
 | ||
|                         </tr>
 | ||
|                     <?php endforeach; ?>
 | ||
|                 <?php else : ?>
 | ||
|                     <tr>
 | ||
|                         <td colspan="8">No events found.</td>
 | ||
|                     </tr>
 | ||
|                 <?php endif; ?>
 | ||
|             </tbody>
 | ||
|         </table>
 | ||
|         
 | ||
|         <div class="tablenav bottom">
 | ||
|             <div class="tablenav-pages">
 | ||
|                 <span class="displaying-num"><?php echo esc_html($pagination['total_items']); ?> items</span>
 | ||
|                 <?php if ($pagination['total_pages'] > 1) : ?>
 | ||
|                     <span class="pagination-links">
 | ||
|                         <?php if ($pagination['has_prev']) : ?>
 | ||
|                             <a class="first-page button" href="#" data-page="1">
 | ||
|                                 <span class="screen-reader-text">First page</span>
 | ||
|                                 <span aria-hidden="true">«</span>
 | ||
|                             </a>
 | ||
|                             <a class="prev-page button" href="#" data-page="<?php echo esc_attr($pagination['current_page'] - 1); ?>">
 | ||
|                                 <span class="screen-reader-text">Previous page</span>
 | ||
|                                 <span aria-hidden="true">‹</span>
 | ||
|                             </a>
 | ||
|                         <?php else : ?>
 | ||
|                             <span class="tablenav-pages-navspan button disabled" aria-hidden="true">«</span>
 | ||
|                             <span class="tablenav-pages-navspan button disabled" aria-hidden="true">‹</span>
 | ||
|                         <?php endif; ?>
 | ||
|                         
 | ||
|                         <span class="paging-input">
 | ||
|                             <label for="current-page-selector" class="screen-reader-text">Current Page</label>
 | ||
|                             <input class="current-page" id="current-page-selector" type="text" name="paged" value="<?php echo esc_attr($pagination['current_page']); ?>" size="1" aria-describedby="table-paging">
 | ||
|                             <span class="tablenav-paging-text"> of <span class="total-pages"><?php echo esc_html($pagination['total_pages']); ?></span></span>
 | ||
|                         </span>
 | ||
|                         
 | ||
|                         <?php if ($pagination['has_next']) : ?>
 | ||
|                             <a class="next-page button" href="#" data-page="<?php echo esc_attr($pagination['current_page'] + 1); ?>">
 | ||
|                                 <span class="screen-reader-text">Next page</span>
 | ||
|                                 <span aria-hidden="true">›</span>
 | ||
|                             </a>
 | ||
|                             <a class="last-page button" href="#" data-page="<?php echo esc_attr($pagination['total_pages']); ?>">
 | ||
|                                 <span class="screen-reader-text">Last page</span>
 | ||
|                                 <span aria-hidden="true">»</span>
 | ||
|                             </a>
 | ||
|                         <?php else : ?>
 | ||
|                             <span class="tablenav-pages-navspan button disabled" aria-hidden="true">›</span>
 | ||
|                             <span class="tablenav-pages-navspan button disabled" aria-hidden="true">»</span>
 | ||
|                         <?php endif; ?>
 | ||
|                     </span>
 | ||
|                 <?php endif; ?>
 | ||
|             </div>
 | ||
|         </div>
 | ||
|         <?php
 | ||
|         
 | ||
|         $html = ob_get_clean();
 | ||
|         
 | ||
|         // Send JSON response
 | ||
|         wp_send_json_success(array(
 | ||
|             'html' => $html,
 | ||
|             'count' => count($events),
 | ||
|             'pagination' => $pagination,
 | ||
|             'args' => $args
 | ||
|         ));
 | ||
|     }
 | ||
|     
 | ||
|     /**
 | ||
|      * Enqueue dashboard assets (CSS and JavaScript)
 | ||
|      */
 | ||
|     public function enqueue_dashboard_assets() {
 | ||
|         // Check if we're on the dashboard page
 | ||
|         global $post;
 | ||
|         if (!is_a($post, 'WP_Post') || !has_shortcode($post->post_content, 'hvac_trainer_dashboard')) {
 | ||
|             return;
 | ||
|         }
 | ||
|         
 | ||
|         // Enqueue UX enhancements (CSS and JS)
 | ||
|         wp_enqueue_style(
 | ||
|             'hvac-ux-enhancements-css',
 | ||
|             HVAC_PLUGIN_URL . 'assets/css/hvac-ux-enhancements.css',
 | ||
|             array(),
 | ||
|             HVAC_PLUGIN_VERSION
 | ||
|         );
 | ||
|         
 | ||
|         wp_enqueue_script(
 | ||
|             'hvac-ux-enhancements-js',
 | ||
|             HVAC_PLUGIN_URL . 'assets/js/hvac-ux-enhancements.js',
 | ||
|             array('jquery'),
 | ||
|             HVAC_PLUGIN_VERSION,
 | ||
|             true
 | ||
|         );
 | ||
|         
 | ||
|         // Enqueue enhanced dashboard CSS
 | ||
|         wp_enqueue_style(
 | ||
|             'hvac-dashboard-enhanced-css',
 | ||
|             HVAC_PLUGIN_URL . 'assets/css/hvac-dashboard-enhanced.css',
 | ||
|             array('hvac-ux-enhancements-css'),
 | ||
|             HVAC_PLUGIN_VERSION
 | ||
|         );
 | ||
|         
 | ||
|         // Enqueue enhanced dashboard JavaScript
 | ||
|         wp_enqueue_script(
 | ||
|             'hvac-dashboard-enhanced-js',
 | ||
|             HVAC_PLUGIN_URL . 'assets/js/hvac-dashboard-enhanced.js',
 | ||
|             array('jquery', 'hvac-ux-enhancements-js'),
 | ||
|             HVAC_PLUGIN_VERSION,
 | ||
|             true
 | ||
|         );
 | ||
|         
 | ||
|         // Localize script with AJAX URL and nonce
 | ||
|         wp_localize_script('hvac-dashboard-enhanced-js', 'hvac_dashboard', array(
 | ||
|             'ajax_url' => admin_url('admin-ajax.php'),
 | ||
|             'nonce' => wp_create_nonce('hvac_dashboard_nonce')
 | ||
|         ));
 | ||
|         
 | ||
|         // Inline CSS for now - can be moved to external file later
 | ||
|         $css = '
 | ||
|             .hvac-dashboard-wrapper {
 | ||
|                 max-width: 1200px;
 | ||
|                 margin: 0 auto;
 | ||
|                 padding: 20px;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-dashboard-header {
 | ||
|                 margin-bottom: 30px;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-dashboard-header h1 {
 | ||
|                 margin-bottom: 20px;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-dashboard-nav {
 | ||
|                 display: flex;
 | ||
|                 gap: 10px;
 | ||
|                 flex-wrap: wrap;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-button {
 | ||
|                 display: inline-block;
 | ||
|                 padding: 10px 20px;
 | ||
|                 text-decoration: none;
 | ||
|                 border-radius: 4px;
 | ||
|                 transition: all 0.3s ease;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-button-primary {
 | ||
|                 background-color: #E9AF28;
 | ||
|                 color: #000;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-button-primary:hover {
 | ||
|                 background-color: #d49b20;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-button-secondary {
 | ||
|                 background-color: #0B5C7D;
 | ||
|                 color: #fff;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-button-secondary:hover {
 | ||
|                 background-color: #084562;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-dashboard-stats {
 | ||
|                 margin-bottom: 40px;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-stats-row {
 | ||
|                 display: flex;
 | ||
|                 flex-direction: row;
 | ||
|                 flex-wrap: wrap;
 | ||
|                 margin: -10px; /* Counteract the padding on columns */
 | ||
|                 justify-content: space-between;
 | ||
|                 align-items: stretch;
 | ||
|                 margin-top: 20px;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-stat-col {
 | ||
|                 flex: 1;
 | ||
|                 min-width: 160px; /* Ensure minimum width for readability */
 | ||
|                 padding: 10px;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-stat-card {
 | ||
|                 background: #f8f9fa;
 | ||
|                 border: 1px solid #e9ecef;
 | ||
|                 border-radius: 8px;
 | ||
|                 padding: 20px;
 | ||
|                 text-align: center;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-stat-card h3 {
 | ||
|                 margin: 0 0 10px;
 | ||
|                 font-size: 16px;
 | ||
|                 color: #666;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-stat-card .metric-value {
 | ||
|                 font-size: 32px;
 | ||
|                 font-weight: bold;
 | ||
|                 color: #E9AF28;
 | ||
|                 margin: 0;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-stat-card small {
 | ||
|                 display: block;
 | ||
|                 margin-top: 5px;
 | ||
|                 color: #666;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-dashboard-events {
 | ||
|                 margin-top: 40px;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-event-filters {
 | ||
|                 margin: 20px 0;
 | ||
|                 display: flex;
 | ||
|                 gap: 10px;
 | ||
|                 align-items: center;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-filter {
 | ||
|                 padding: 5px 15px;
 | ||
|                 border: 1px solid #ddd;
 | ||
|                 border-radius: 4px;
 | ||
|                 text-decoration: none;
 | ||
|                 color: #333;
 | ||
|                 transition: all 0.3s ease;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-filter:hover,
 | ||
|             .hvac-filter-active {
 | ||
|                 background-color: #E9AF28;
 | ||
|                 color: #000;
 | ||
|                 border-color: #E9AF28;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-events-table-wrapper {
 | ||
|                 overflow-x: auto;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-events-table {
 | ||
|                 width: 100%;
 | ||
|                 border-collapse: collapse;
 | ||
|                 margin-top: 20px;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-events-table th,
 | ||
|             .hvac-events-table td {
 | ||
|                 padding: 12px;
 | ||
|                 text-align: left;
 | ||
|                 border-bottom: 1px solid #ddd;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-events-table th {
 | ||
|                 background-color: #f8f9fa;
 | ||
|                 font-weight: bold;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-events-table tr:hover {
 | ||
|                 background-color: #f8f9fa;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-events-table a {
 | ||
|                 color: #0B5C7D;
 | ||
|                 text-decoration: none;
 | ||
|             }
 | ||
|             
 | ||
|             .hvac-events-table a:hover {
 | ||
|                 text-decoration: underline;
 | ||
|             }
 | ||
|             
 | ||
|             @media (max-width: 768px) {
 | ||
|                 .hvac-stats-grid {
 | ||
|                     grid-template-columns: 1fr;
 | ||
|                 }
 | ||
|                 
 | ||
|                 .hvac-events-table {
 | ||
|                     font-size: 14px;
 | ||
|                 }
 | ||
|                 
 | ||
|                 .hvac-events-table th,
 | ||
|                 .hvac-events-table td {
 | ||
|                     padding: 8px;
 | ||
|                 }
 | ||
|             }
 | ||
|         ';
 | ||
|         
 | ||
|         wp_add_inline_style('astra-theme-css', $css);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| // Initialize the dashboard
 | ||
| new HVAC_Dashboard();
 |