feat: Add Trainer Profile page and functionality

- Add trainer-profile page to required_pages array in main plugin file
- Create template-trainer-profile.php with comprehensive profile display
- Implement render_trainer_profile() function in main class
- Add template loading for trainer-profile page
- Create helper script to ensure trainer-profile page exists in WordPress
- Fix shortcode registration in Login_Handler to prevent duplicates
- Add dashboard verification script for testing

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
bengizmo 2025-05-20 07:43:39 -03:00
parent 461304e9f6
commit e59c2e5ccc
6 changed files with 585 additions and 9 deletions

View file

@ -0,0 +1,24 @@
#!/bin/bash
# Verify dashboard changes by running Playwright script
# Usage: ./verify-dashboard.sh
cd "$(dirname "$0")/.."
# Check if Node.js is installed
if ! command -v node &> /dev/null; then
echo "Node.js is required to run this script"
exit 1
fi
# Check if Playwright is installed
if ! npm list -g playwright &> /dev/null; then
echo "Installing Playwright..."
npm install -g playwright
fi
# Run the verification script
echo "Running dashboard verification script..."
node bin/verify-dashboard-changes.js
echo "Verification complete. Check the generated screenshots for visual confirmation."

View file

@ -0,0 +1,69 @@
<?php
/**
* Helper script to create or refresh the trainer-profile page
*
* This can be run using wp-cli with:
* wp --path=/path/to/wordpress eval-file create-trainer-profile-page.php
*/
// Bootstrap WordPress
if (!defined('ABSPATH')) {
// Load WordPress core if not loaded
require_once(dirname(dirname(dirname(dirname(__FILE__)))) . '/wp-load.php');
}
// Check if the trainer-profile page exists
$existing_page = get_page_by_path('trainer-profile', OBJECT, 'page');
// Page data
$page_data = [
'post_title' => 'Trainer Profile',
'post_name' => 'trainer-profile',
'post_content' => '<!-- wp:shortcode -->[hvac_trainer_profile]<!-- /wp:shortcode -->',
'post_status' => 'publish',
'post_type' => 'page',
'comment_status' => 'closed',
'ping_status' => 'closed',
];
if (!$existing_page) {
// Create new page
$page_id = wp_insert_post($page_data);
if (is_wp_error($page_id)) {
echo "Error creating trainer-profile page: " . $page_id->get_error_message() . "\n";
} else {
echo "Successfully created trainer-profile page with ID: $page_id\n";
// Update the HVAC community pages option
$created_pages_option = 'hvac_community_pages';
$created_pages = get_option($created_pages_option, []);
$created_pages['trainer_profile'] = $page_id;
update_option($created_pages_option, $created_pages);
echo "Updated hvac_community_pages option with the new page ID\n";
}
} else {
// Update existing page
$page_data['ID'] = $existing_page->ID;
$page_id = wp_update_post($page_data);
if (is_wp_error($page_id)) {
echo "Error updating trainer-profile page: " . $page_id->get_error_message() . "\n";
} else {
echo "Successfully updated trainer-profile page with ID: $page_id\n";
// Ensure the page is in the HVAC community pages option
$created_pages_option = 'hvac_community_pages';
$created_pages = get_option($created_pages_option, []);
if (!isset($created_pages['trainer_profile']) || $created_pages['trainer_profile'] != $page_id) {
$created_pages['trainer_profile'] = $page_id;
update_option($created_pages_option, $created_pages);
echo "Updated hvac_community_pages option with the page ID\n";
}
}
}
// Flush rewrite rules to ensure the page is accessible
flush_rewrite_rules();
echo "Flushed rewrite rules\n";
echo "Done!\n";

View file

@ -55,6 +55,10 @@ function hvac_ce_create_required_pages() {
'title' => 'My Events', 'title' => 'My Events',
'content' => '<!-- wp:shortcode -->[tribe_community_events view="my_events"]<!-- /wp:shortcode -->', 'content' => '<!-- wp:shortcode -->[tribe_community_events view="my_events"]<!-- /wp:shortcode -->',
], ],
'trainer-profile' => [ // Add trainer profile page
'title' => 'Trainer Profile',
'content' => '<!-- wp:shortcode -->[hvac_trainer_profile]<!-- /wp:shortcode -->',
],
// REMOVED: 'submit-event' page creation. Will link to default TEC CE page. // REMOVED: 'submit-event' page creation. Will link to default TEC CE page.
// 'submit-event' => [ // 'submit-event' => [
// 'title' => 'Submit Event', // 'title' => 'Submit Event',

View file

@ -205,8 +205,8 @@ class HVAC_Community_Events {
// Registration form shortcode // Registration form shortcode
add_shortcode('hvac_trainer_registration', array('HVAC_Registration', 'render_registration_form')); add_shortcode('hvac_trainer_registration', array('HVAC_Registration', 'render_registration_form'));
// Community login shortcode // Community login shortcode - initialize Login_Handler to register the shortcode
add_shortcode('hvac_community_login', array('\\HVAC_Community_Events\\Community\\Login_Handler', 'render_login_form')); new \HVAC_Community_Events\Community\Login_Handler();
// Dashboard shortcode // Dashboard shortcode
add_shortcode('hvac_dashboard', array($this, 'render_dashboard')); add_shortcode('hvac_dashboard', array($this, 'render_dashboard'));
@ -214,6 +214,9 @@ class HVAC_Community_Events {
// Add the event summary shortcode // Add the event summary shortcode
add_shortcode('hvac_event_summary', array($this, 'render_event_summary')); add_shortcode('hvac_event_summary', array($this, 'render_event_summary'));
// Add trainer profile shortcode
add_shortcode('hvac_trainer_profile', array($this, 'render_trainer_profile'));
// Remove the event form shortcode as we're using TEC's shortcode instead // Remove the event form shortcode as we're using TEC's shortcode instead
// add_shortcode('hvac_event_form', array('HVAC_Community_Event_Handler', 'render_event_form')); // add_shortcode('hvac_event_form', array('HVAC_Community_Event_Handler', 'render_event_form'));
@ -242,6 +245,20 @@ class HVAC_Community_Events {
return '<div class="hvac-event-summary">Event Summary Content Here</div>'; return '<div class="hvac-event-summary">Event Summary Content Here</div>';
} }
/**
* Render trainer profile content
*/
public function render_trainer_profile() {
if (!is_user_logged_in()) {
return '<p>Please log in to view your profile.</p>';
}
// Include the trainer profile template
ob_start();
include HVAC_CE_PLUGIN_DIR . 'templates/template-trainer-profile.php';
return ob_get_clean();
}
/** /**
* Include custom templates for plugin pages * Include custom templates for plugin pages
*/ */
@ -270,6 +287,14 @@ class HVAC_Community_Events {
} }
} }
// Check for trainer-profile page
if (is_page('trainer-profile')) {
$custom_template = HVAC_CE_PLUGIN_DIR . 'templates/template-trainer-profile.php';
if (file_exists($custom_template)) {
return $custom_template;
}
}
// Check for single event view (temporary) // Check for single event view (temporary)
if ( is_singular( 'tribe_events' ) ) { if ( is_singular( 'tribe_events' ) ) {
$custom_template = HVAC_CE_PLUGIN_DIR . 'templates/single-tribe_events.php'; $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/single-tribe_events.php';

View file

@ -23,18 +23,22 @@ class Login_Handler {
* Hooks into WordPress. * Hooks into WordPress.
*/ */
public function __construct() { public function __construct() {
add_shortcode( 'hvac_community_login', array( $this, 'render_login_form' ) ); // Register our shortcode only if it doesn't exist already
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); // Enqueue scripts/styles if (!shortcode_exists('hvac_community_login')) {
add_shortcode('hvac_community_login', array($this, 'render_login_form'));
}
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts')); // Enqueue scripts/styles
// Add action hooks for authentication and redirection (Task 2.2 & 2.5) // Add action hooks for authentication and redirection (Task 2.2 & 2.5)
add_action( 'wp_authenticate', array( $this, 'handle_authentication' ), 30, 2 ); // Allow custom auth checks add_action('wp_authenticate', array($this, 'handle_authentication'), 30, 2); // Allow custom auth checks
// REMOVED: add_action( 'login_form_login', array( $this, 'redirect_on_login_failure' ) ); // This was causing premature redirects // REMOVED: add_action('login_form_login', array($this, 'redirect_on_login_failure')); // This was causing premature redirects
add_action( 'wp_login_failed', array( $this, 'handle_login_failure' ) ); // Handle failed login redirect add_action('wp_login_failed', array($this, 'handle_login_failure')); // Handle failed login redirect
add_filter( 'login_redirect', array( $this, 'custom_login_redirect' ), 10, 3 ); // Handle success redirect add_filter('login_redirect', array($this, 'custom_login_redirect'), 10, 3); // Handle success redirect
// Redirect logged-in users away from the login page // Redirect logged-in users away from the login page
add_action( 'template_redirect', array( $this, 'redirect_logged_in_user' ) ); add_action('template_redirect', array($this, 'redirect_logged_in_user'));
} }
/** /**

View file

@ -0,0 +1,450 @@
<?php
/**
* Template Name: HVAC Trainer Profile
*
* This template handles the display of the HVAC Trainer Profile.
* It displays user information, business details, and training stats.
*
* @package HVAC Community Events
* @subpackage Templates
* @author HVAC Community Events
* @version 1.0.0
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// --- Security Check & Data Loading ---
// Ensure user is logged in and has the correct role
if ( ! is_user_logged_in() || ! current_user_can( 'view_hvac_dashboard' ) ) {
// Redirect to login page
wp_safe_redirect( home_url( '/community-login/' ) );
exit;
}
// Get the current user ID and data
$user_id = get_current_user_id();
$user = get_userdata($user_id);
// Get profile image
$profile_image_id = get_user_meta($user_id, 'profile_image_id', true);
$profile_image_url = '';
if ($profile_image_id) {
$profile_image_url = wp_get_attachment_url($profile_image_id);
}
// Load user meta data
$user_meta = array(
'personal_accreditation' => get_user_meta($user_id, 'personal_accreditation', true),
'business_name' => get_user_meta($user_id, 'business_name', true),
'business_phone' => get_user_meta($user_id, 'business_phone', true),
'business_email' => get_user_meta($user_id, 'business_email', true),
'business_website' => get_user_meta($user_id, 'business_website', true),
'business_description' => get_user_meta($user_id, 'business_description', true),
'user_country' => get_user_meta($user_id, 'user_country', true),
'user_state' => get_user_meta($user_id, 'user_state', true),
'user_city' => get_user_meta($user_id, 'user_city', true),
'user_zip' => get_user_meta($user_id, 'user_zip', true),
'linkedin' => get_user_meta($user_id, 'user_linkedin', true),
'business_type' => get_user_meta($user_id, 'business_type', true),
'training_audience' => get_user_meta($user_id, 'training_audience', true),
'training_formats' => get_user_meta($user_id, 'training_formats', true),
'training_locations' => get_user_meta($user_id, 'training_locations', true),
'training_resources' => get_user_meta($user_id, 'training_resources', true),
'annual_revenue_target' => get_user_meta($user_id, 'annual_revenue_target', true),
);
// Get organizer ID if available
$organizer_id = get_user_meta($user_id, 'hvac_organizer_id', true);
// Get venue ID if available
$venue_id = get_user_meta($user_id, 'hvac_venue_id', true);
// Get training stats
include_once HVAC_CE_PLUGIN_DIR . 'includes/class-hvac-dashboard-data.php';
$dashboard_data = new HVAC_Dashboard_Data($user_id);
$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();
// --- Template Start ---
get_header(); // Use theme's header
?>
<div id="primary" class="content-area primary ast-container">
<main id="main" class="site-main">
<!-- Profile Header & Navigation -->
<div class="hvac-dashboard-header">
<h1 class="entry-title">Trainer Profile</h1>
<div class="hvac-dashboard-nav">
<a href="<?php echo esc_url(home_url('/hvac-dashboard/')); ?>" class="ast-button ast-button-primary">Dashboard</a>
<a href="<?php echo esc_url(home_url('/manage-event/')); ?>" class="ast-button ast-button-primary">Create Event</a>
<a href="<?php echo esc_url(home_url('/my-events/')); ?>" class="ast-button ast-button-primary">My Events</a>
<a href="<?php echo esc_url(wp_logout_url(home_url('/community-login/'))); ?>" class="ast-button ast-button-secondary">Logout</a>
</div>
</div>
<div class="hvac-profile-container">
<!-- Personal Information -->
<section class="hvac-profile-section">
<div class="hvac-profile-header">
<h2>Personal Information</h2>
<div class="hvac-profile-actions">
<a href="<?php echo esc_url(get_edit_profile_url($user_id)); ?>" class="ast-button ast-button-secondary">Edit Profile</a>
</div>
</div>
<div class="hvac-profile-content">
<div class="hvac-profile-image">
<?php if ($profile_image_url) : ?>
<img src="<?php echo esc_url($profile_image_url); ?>" alt="<?php echo esc_attr($user->display_name); ?>" width="150" height="150">
<?php else : ?>
<div class="hvac-profile-image-placeholder">
<span><?php echo esc_html(substr($user->first_name, 0, 1) . substr($user->last_name, 0, 1)); ?></span>
</div>
<?php endif; ?>
</div>
<div class="hvac-profile-details">
<h3><?php echo esc_html($user->display_name); ?>
<?php if (!empty($user_meta['personal_accreditation'])) : ?>
<span class="hvac-accreditation"><?php echo esc_html($user_meta['personal_accreditation']); ?></span>
<?php endif; ?>
</h3>
<p class="hvac-profile-bio"><?php echo wp_kses_post($user->description); ?></p>
<div class="hvac-profile-contact">
<p><strong>Email:</strong> <?php echo esc_html($user->user_email); ?></p>
<?php if (!empty($user->user_url)) : ?>
<p><strong>Website:</strong> <a href="<?php echo esc_url($user->user_url); ?>" target="_blank"><?php echo esc_html($user->user_url); ?></a></p>
<?php endif; ?>
<?php if (!empty($user_meta['linkedin'])) : ?>
<p><strong>LinkedIn:</strong> <a href="<?php echo esc_url($user_meta['linkedin']); ?>" target="_blank">LinkedIn Profile</a></p>
<?php endif; ?>
</div>
</div>
</div>
</section>
<!-- Business Information -->
<section class="hvac-profile-section">
<h2>Business Information</h2>
<div class="hvac-profile-content">
<div class="hvac-business-details">
<h3><?php echo esc_html($user_meta['business_name']); ?></h3>
<p><strong>Type:</strong> <?php echo esc_html($user_meta['business_type']); ?></p>
<p><strong>Phone:</strong> <?php echo esc_html($user_meta['business_phone']); ?></p>
<p><strong>Email:</strong> <?php echo esc_html($user_meta['business_email']); ?></p>
<?php if (!empty($user_meta['business_website'])) : ?>
<p><strong>Website:</strong> <a href="<?php echo esc_url($user_meta['business_website']); ?>" target="_blank"><?php echo esc_html($user_meta['business_website']); ?></a></p>
<?php endif; ?>
<div class="hvac-business-address">
<h4>Address</h4>
<p>
<?php echo esc_html($user_meta['user_city']); ?>,
<?php echo esc_html($user_meta['user_state']); ?>
<?php echo esc_html($user_meta['user_zip']); ?><br>
<?php echo esc_html($user_meta['user_country']); ?>
</p>
</div>
<div class="hvac-business-description">
<h4>Description</h4>
<p><?php echo wp_kses_post($user_meta['business_description']); ?></p>
</div>
</div>
</div>
</section>
<!-- Training Information -->
<section class="hvac-profile-section">
<h2>Training Information</h2>
<div class="hvac-profile-content">
<div class="hvac-training-details">
<!-- Training Audience -->
<div class="hvac-training-item">
<h4>Training Audience</h4>
<?php if (is_array($user_meta['training_audience']) && !empty($user_meta['training_audience'])) : ?>
<ul>
<?php foreach ($user_meta['training_audience'] as $audience) : ?>
<li><?php echo esc_html($audience); ?></li>
<?php endforeach; ?>
</ul>
<?php else : ?>
<p>No training audience specified</p>
<?php endif; ?>
</div>
<!-- Training Formats -->
<div class="hvac-training-item">
<h4>Training Formats</h4>
<?php if (is_array($user_meta['training_formats']) && !empty($user_meta['training_formats'])) : ?>
<ul>
<?php foreach ($user_meta['training_formats'] as $format) : ?>
<li><?php echo esc_html($format); ?></li>
<?php endforeach; ?>
</ul>
<?php else : ?>
<p>No training formats specified</p>
<?php endif; ?>
</div>
<!-- Training Locations -->
<div class="hvac-training-item">
<h4>Training Locations</h4>
<?php if (is_array($user_meta['training_locations']) && !empty($user_meta['training_locations'])) : ?>
<ul>
<?php foreach ($user_meta['training_locations'] as $location) : ?>
<li><?php echo esc_html($location); ?></li>
<?php endforeach; ?>
</ul>
<?php else : ?>
<p>No training locations specified</p>
<?php endif; ?>
</div>
<!-- Training Resources -->
<div class="hvac-training-item">
<h4>Training Resources</h4>
<?php if (is_array($user_meta['training_resources']) && !empty($user_meta['training_resources'])) : ?>
<ul>
<?php foreach ($user_meta['training_resources'] as $resource) : ?>
<li><?php echo esc_html($resource); ?></li>
<?php endforeach; ?>
</ul>
<?php else : ?>
<p>No training resources specified</p>
<?php endif; ?>
</div>
</div>
</div>
</section>
<!-- Training Stats -->
<section class="hvac-profile-section">
<h2>Training Statistics</h2>
<div class="hvac-profile-content">
<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($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($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($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($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($total_revenue, 2)); ?></p>
<?php if (!empty($user_meta['annual_revenue_target'])) : ?>
<small>Target: $<?php echo esc_html(number_format($user_meta['annual_revenue_target'], 2)); ?></small>
<?php endif; ?>
</div>
</div>
</div>
</div>
</section>
</div>
</main>
</div>
<style>
/* Profile Page Specific Styles */
.hvac-profile-container {
max-width: 1200px;
margin: 0 auto;
}
.hvac-profile-section {
margin-bottom: 40px;
background: #f8f9fa;
border-radius: 8px;
padding: 20px;
border: 1px solid #e9ecef;
}
.hvac-profile-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.hvac-profile-header h2 {
margin: 0;
}
.hvac-profile-content {
display: flex;
flex-wrap: wrap;
}
.hvac-profile-image {
margin-right: 30px;
margin-bottom: 20px;
}
.hvac-profile-image img {
border-radius: 50%;
object-fit: cover;
}
.hvac-profile-image-placeholder {
width: 150px;
height: 150px;
border-radius: 50%;
background-color: #0B5C7D;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
font-weight: bold;
}
.hvac-profile-details {
flex: 1;
min-width: 300px;
}
.hvac-accreditation {
font-size: 16px;
color: #666;
margin-left: 8px;
}
.hvac-profile-bio {
margin-bottom: 20px;
}
.hvac-business-details,
.hvac-training-details {
width: 100%;
}
.hvac-business-address,
.hvac-business-description {
margin-top: 20px;
}
.hvac-training-details {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.hvac-training-item {
flex: 1;
min-width: 200px;
}
.hvac-training-item ul {
margin: 0;
padding-left: 20px;
}
.hvac-stats-row {
display: flex;
flex-wrap: wrap;
margin: -10px;
justify-content: space-between;
}
.hvac-stat-col {
flex: 1;
min-width: 160px;
padding: 10px;
}
.hvac-stat-card {
padding: 20px;
text-align: center;
background: white;
border: 1px solid #e9ecef;
border-radius: 8px;
}
.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;
}
@media (max-width: 768px) {
.hvac-profile-header {
flex-direction: column;
align-items: flex-start;
}
.hvac-profile-actions {
margin-top: 10px;
}
.hvac-profile-content {
flex-direction: column;
}
.hvac-profile-image {
margin-right: 0;
}
.hvac-training-item {
min-width: 100%;
}
}
</style>
<?php
get_footer(); // Use theme's footer