upskill-event-manager/includes/class-hvac-dashboard.php
bengizmo 2cb37d0285 fix: Ensure trainer registration page is publicly accessible
- Added explicit checks to prevent authentication redirects on registration page
- Added ensure_registration_page_public() method with priority 1 to run before other auth checks
- Included registration-pending and training-login pages in public pages list
- Added fallback function in main plugin file to remove auth hooks on registration page

This ensures that users can access /trainer/registration/ without being logged in, as intended for new trainer signups.
2025-07-28 10:30:54 -03:00

644 lines
No EOL
29 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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_CE_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_CE_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_CE_PLUGIN_URL . 'assets/css/hvac-ux-enhancements.css',
array(),
HVAC_CE_VERSION
);
wp_enqueue_script(
'hvac-ux-enhancements-js',
HVAC_CE_PLUGIN_URL . 'assets/js/hvac-ux-enhancements.js',
array('jquery'),
HVAC_CE_VERSION,
true
);
// Enqueue enhanced dashboard CSS
wp_enqueue_style(
'hvac-dashboard-enhanced-css',
HVAC_CE_PLUGIN_URL . 'assets/css/hvac-dashboard-enhanced.css',
array('hvac-ux-enhancements-css'),
HVAC_CE_VERSION
);
// Enqueue enhanced dashboard JavaScript
wp_enqueue_script(
'hvac-dashboard-enhanced-js',
HVAC_CE_PLUGIN_URL . 'assets/js/hvac-dashboard-enhanced.js',
array('jquery', 'hvac-ux-enhancements-js'),
HVAC_CE_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();