feat: Add Event Summary Page functionality
- Add event-summary page to required_pages array in main plugin file - Update render_event_summary() method to handle event ID from URL - Update template_include filter to load custom event summary template - Update dashboard event links to point to new event summary page - Create comprehensive event summary template with statistics and attendee info - Add E2E tests for Event Summary Page - Add documentation for Event Summary functionality 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
e59c2e5ccc
commit
1a563f3133
6 changed files with 732 additions and 5 deletions
171
wordpress-dev/tests/e2e/event-summary.spec.ts
Normal file
171
wordpress-dev/tests/e2e/event-summary.spec.ts
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
import { test, expect } from '@playwright/test';
|
||||
import { LoginPage } from './pages/LoginPage';
|
||||
import { DashboardPage } from './pages/DashboardPage';
|
||||
|
||||
test.describe('Event Summary Page', () => {
|
||||
// Define test variables
|
||||
const testTrainerUsername = 'test_trainer';
|
||||
const testTrainerPassword = 'Test123!';
|
||||
|
||||
// We'll need to figure out a test event ID during the test
|
||||
let testEventId: string;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Log in before each test
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.navigate();
|
||||
await loginPage.login(testTrainerUsername, testTrainerPassword);
|
||||
|
||||
// Navigate to dashboard to find an event to use for testing
|
||||
const dashboardPage = new DashboardPage(page);
|
||||
await dashboardPage.navigate();
|
||||
|
||||
// Find the first event in the dashboard and get its ID
|
||||
// We'll extract the event ID from the "Summary" link's href
|
||||
const summaryLink = page.locator('.column-actions a:has-text("Summary")').first();
|
||||
|
||||
// Check if there's at least one event
|
||||
const linkCount = await summaryLink.count();
|
||||
if (linkCount === 0) {
|
||||
// No events available for testing, we'll need to skip the tests
|
||||
test.skip(true, 'No events available for testing');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the href attribute from the summary link
|
||||
const summaryUrl = await summaryLink.getAttribute('href');
|
||||
|
||||
// Extract the event ID from the URL
|
||||
if (summaryUrl) {
|
||||
const match = summaryUrl.match(/event_id=(\d+)/);
|
||||
if (match && match[1]) {
|
||||
testEventId = match[1];
|
||||
} else {
|
||||
test.skip(true, 'Could not extract event ID from summary link');
|
||||
}
|
||||
} else {
|
||||
test.skip(true, 'Summary link has no href attribute');
|
||||
}
|
||||
});
|
||||
|
||||
test('should be accessible from dashboard', async ({ page }) => {
|
||||
// Navigate to dashboard
|
||||
const dashboardPage = new DashboardPage(page);
|
||||
await dashboardPage.navigate();
|
||||
|
||||
// Find and click the first summary link
|
||||
const summaryLink = page.locator('.column-actions a:has-text("Summary")').first();
|
||||
await expect(summaryLink).toBeVisible();
|
||||
await summaryLink.click();
|
||||
|
||||
// Verify we're on the event summary page
|
||||
await expect(page).toHaveURL(/.*\/event-summary\/.*event_id=.*/);
|
||||
await expect(page.locator('h1')).toContainText('Summary');
|
||||
});
|
||||
|
||||
test('should display event overview information', async ({ page }) => {
|
||||
// Navigate directly to the event summary page
|
||||
await page.goto(`/event-summary/?event_id=${testEventId}`);
|
||||
|
||||
// Check for event overview section
|
||||
await expect(page.locator('h2:has-text("Event Overview")')).toBeVisible();
|
||||
|
||||
// Check for basic event details
|
||||
const detailsTable = page.locator('.hvac-details-table');
|
||||
await expect(detailsTable).toBeVisible();
|
||||
|
||||
// Check for specific fields
|
||||
const dateRow = detailsTable.locator('tr', { hasText: 'Date & Time' });
|
||||
const statusRow = detailsTable.locator('tr', { hasText: 'Status' });
|
||||
|
||||
await expect(dateRow).toBeVisible();
|
||||
await expect(statusRow).toBeVisible();
|
||||
});
|
||||
|
||||
test('should display event statistics', async ({ page }) => {
|
||||
// Navigate directly to the event summary page
|
||||
await page.goto(`/event-summary/?event_id=${testEventId}`);
|
||||
|
||||
// Check for statistics section
|
||||
await expect(page.locator('h2:has-text("Event Statistics")')).toBeVisible();
|
||||
|
||||
// Check for statistics cards
|
||||
const statsRow = page.locator('.hvac-stats-row');
|
||||
await expect(statsRow).toBeVisible();
|
||||
|
||||
// Look for specific metric cards
|
||||
const totalTicketsCard = page.locator('.hvac-stat-card h3:has-text("Total Tickets")');
|
||||
const totalRevenueCard = page.locator('.hvac-stat-card h3:has-text("Total Revenue")');
|
||||
|
||||
await expect(totalTicketsCard).toBeVisible();
|
||||
await expect(totalRevenueCard).toBeVisible();
|
||||
});
|
||||
|
||||
test('should display ticket sales and attendees information', async ({ page }) => {
|
||||
// Navigate directly to the event summary page
|
||||
await page.goto(`/event-summary/?event_id=${testEventId}`);
|
||||
|
||||
// Check for ticket sales section
|
||||
await expect(page.locator('h2:has-text("Ticket Sales & Attendees")')).toBeVisible();
|
||||
|
||||
// The table might not be visible if there are no attendees, so check for either
|
||||
// the table or the "No ticket sales" message
|
||||
const attendeesTable = page.locator('.hvac-transactions-table');
|
||||
const noAttendeesMessage = page.locator('text=No ticket sales or attendees found');
|
||||
|
||||
const hasTable = await attendeesTable.count() > 0;
|
||||
if (hasTable) {
|
||||
// Check table headers
|
||||
const attendeeHeader = attendeesTable.locator('th', { hasText: 'Attendee' });
|
||||
const emailHeader = attendeesTable.locator('th', { hasText: 'Email' });
|
||||
const ticketTypeHeader = attendeesTable.locator('th', { hasText: 'Ticket Type' });
|
||||
|
||||
await expect(attendeeHeader).toBeVisible();
|
||||
await expect(emailHeader).toBeVisible();
|
||||
await expect(ticketTypeHeader).toBeVisible();
|
||||
} else {
|
||||
// Check for no attendees message
|
||||
await expect(noAttendeesMessage).toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
test('should display event description', async ({ page }) => {
|
||||
// Navigate directly to the event summary page
|
||||
await page.goto(`/event-summary/?event_id=${testEventId}`);
|
||||
|
||||
// Check for event description section
|
||||
await expect(page.locator('h2:has-text("Event Description")')).toBeVisible();
|
||||
|
||||
// Check for description content
|
||||
const descriptionContainer = page.locator('.hvac-event-description');
|
||||
await expect(descriptionContainer).toBeVisible();
|
||||
});
|
||||
|
||||
test('should have working navigation links', async ({ page }) => {
|
||||
// Navigate directly to the event summary page
|
||||
await page.goto(`/event-summary/?event_id=${testEventId}`);
|
||||
|
||||
// Check for dashboard navigation link
|
||||
const dashboardLink = page.locator('a[href*="/hvac-dashboard/"]');
|
||||
await expect(dashboardLink).toBeVisible();
|
||||
|
||||
// Check for edit event link (may not be visible if user doesn't have permission)
|
||||
const editEventLink = page.locator('a[href*="/manage-event/"]');
|
||||
|
||||
// Check for view public page link
|
||||
const viewPublicLink = page.locator('a[href*="/event/"]');
|
||||
await expect(viewPublicLink).toBeVisible();
|
||||
});
|
||||
|
||||
test('should redirect to login page when not logged in', async ({ page }) => {
|
||||
// Log out first
|
||||
await page.goto('/wp-login.php?action=logout');
|
||||
await page.waitForURL(/.*\/community-login.*/);
|
||||
|
||||
// Try to access event summary page directly
|
||||
await page.goto(`/event-summary/?event_id=${testEventId}`);
|
||||
|
||||
// Should redirect to login page
|
||||
await expect(page).toHaveURL(/.*\/community-login.*/);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
# Event Summary Functionality
|
||||
|
||||
## Overview
|
||||
|
||||
The Event Summary page provides trainers with detailed information about their events, including ticket sales, attendee data, and revenue tracking. This page is designed to be a central hub for monitoring event performance and managing attendees.
|
||||
|
||||
## Access & Navigation
|
||||
|
||||
- **Access Path**: The Event Summary page can be accessed from the Trainer Dashboard by clicking the "Summary" link next to any event in the events table.
|
||||
- **URL Structure**: `/event-summary/?event_id={id}` where `{id}` is the event post ID.
|
||||
- **Authentication**: Only logged-in users with appropriate permissions (event creators or administrators) can access this page.
|
||||
|
||||
## Page Components
|
||||
|
||||
### 1. Header & Navigation
|
||||
|
||||
The header section contains:
|
||||
- The event title with "Summary" suffix
|
||||
- Navigation links to:
|
||||
- Dashboard
|
||||
- Edit Event (if user has permission)
|
||||
- View Public Page (opens in new tab)
|
||||
- Email Attendees (Phase 2 feature, currently a placeholder)
|
||||
|
||||
### 2. Event Overview
|
||||
|
||||
This section provides basic event information including:
|
||||
- Date & Time (start and end)
|
||||
- Event Status (Published, Draft, etc.)
|
||||
- Cost
|
||||
- Venue information (if available)
|
||||
- Organizer details (if available)
|
||||
|
||||
### 3. Event Statistics
|
||||
|
||||
A visual representation of key metrics:
|
||||
- Total Tickets Sold
|
||||
- Total Revenue
|
||||
- Ticket Type Distribution (with count and revenue for each type)
|
||||
|
||||
Statistics are displayed in card format for easy scanning, with the same visual style as the dashboard stats.
|
||||
|
||||
### 4. Ticket Sales & Attendees
|
||||
|
||||
A comprehensive table showing all attendee information:
|
||||
- Attendee name
|
||||
- Email address
|
||||
- Ticket type
|
||||
- Price paid
|
||||
- Order ID
|
||||
- Check-in status
|
||||
|
||||
This table provides a complete overview of all registrations and can be used for attendee management.
|
||||
|
||||
### 5. Event Description
|
||||
|
||||
The full event description is displayed for reference.
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### Files & Classes
|
||||
|
||||
- **Template**: `templates/template-event-summary.php`
|
||||
- **Data Handler**: `includes/community/class-event-summary-data.php`
|
||||
- **Shortcode**: `[hvac_event_summary]` (registered in main plugin class)
|
||||
- **Styling**: Inline CSS in the template (consistent with dashboard styling)
|
||||
|
||||
### Data Flow
|
||||
|
||||
1. The `render_event_summary()` method in the main plugin class:
|
||||
- Retrieves the event ID from the URL parameter
|
||||
- Verifies user permissions
|
||||
- Includes the event summary template
|
||||
|
||||
2. The template:
|
||||
- Initializes the `HVAC_Event_Summary_Data` class with the event ID
|
||||
- Retrieves event details, venue info, organizer info, and transaction data
|
||||
- Calculates statistics from the transaction data
|
||||
- Renders the UI with the retrieved data
|
||||
|
||||
3. The `HVAC_Event_Summary_Data` class:
|
||||
- Provides methods to retrieve all necessary event data
|
||||
- Integrates with The Events Calendar API for event details
|
||||
- Integrates with Event Tickets for transaction data
|
||||
|
||||
## Testing
|
||||
|
||||
The Event Summary page is verified by E2E tests in `tests/e2e/event-summary.spec.ts`. The tests cover:
|
||||
- Page accessibility from the dashboard
|
||||
- Display of event overview information
|
||||
- Display of event statistics
|
||||
- Display of ticket sales and attendees data
|
||||
- Display of event description
|
||||
- Proper navigation links
|
||||
- Authentication requirements
|
||||
|
||||
## Future Enhancements (Planned)
|
||||
|
||||
- **Phase 2**: Integration with the Email Attendees feature
|
||||
- **Phase 2**: CSV export of attendee data
|
||||
- **Phase 3**: Enhanced visualization of event statistics
|
||||
- **Phase 3**: Integration with certificate generation
|
||||
|
|
@ -59,6 +59,10 @@ function hvac_ce_create_required_pages() {
|
|||
'title' => 'Trainer Profile',
|
||||
'content' => '<!-- wp:shortcode -->[hvac_trainer_profile]<!-- /wp:shortcode -->',
|
||||
],
|
||||
'event-summary' => [ // Add event summary page
|
||||
'title' => 'Event Summary',
|
||||
'content' => '<!-- wp:shortcode -->[hvac_event_summary]<!-- /wp:shortcode -->',
|
||||
],
|
||||
// REMOVED: 'submit-event' page creation. Will link to default TEC CE page.
|
||||
// 'submit-event' => [
|
||||
// 'title' => 'Submit Event',
|
||||
|
|
|
|||
|
|
@ -241,8 +241,34 @@ class HVAC_Community_Events {
|
|||
* Render event summary content
|
||||
*/
|
||||
public function render_event_summary() {
|
||||
// This can be used to display custom event summary content
|
||||
return '<div class="hvac-event-summary">Event Summary Content Here</div>';
|
||||
// Check if user is logged in
|
||||
if (!is_user_logged_in()) {
|
||||
return '<p>Please log in to view the event summary.</p>';
|
||||
}
|
||||
|
||||
// Get event ID from URL parameter
|
||||
$event_id = isset($_GET['event_id']) ? absint($_GET['event_id']) : 0;
|
||||
|
||||
if ($event_id <= 0) {
|
||||
return '<div class="hvac-error">No event ID provided. Please access this page from your dashboard.</div>';
|
||||
}
|
||||
|
||||
// Check if the event exists and user has permission to view it
|
||||
$event = get_post($event_id);
|
||||
if (!$event || get_post_type($event) !== Tribe__Events__Main::POSTTYPE) {
|
||||
return '<div class="hvac-error">Event not found or invalid.</div>';
|
||||
}
|
||||
|
||||
// Check if the current user has permission to view this event
|
||||
// For now, we'll check if they're the post author or have edit_posts capability
|
||||
if ($event->post_author != get_current_user_id() && !current_user_can('edit_posts')) {
|
||||
return '<div class="hvac-error">You do not have permission to view this event summary.</div>';
|
||||
}
|
||||
|
||||
// Include the event summary template
|
||||
ob_start();
|
||||
include HVAC_CE_PLUGIN_DIR . 'templates/event-summary/template-event-summary.php';
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -295,6 +321,14 @@ class HVAC_Community_Events {
|
|||
}
|
||||
}
|
||||
|
||||
// Check for event-summary page
|
||||
if (is_page('event-summary')) {
|
||||
$custom_template = HVAC_CE_PLUGIN_DIR . 'templates/template-event-summary.php';
|
||||
if (file_exists($custom_template)) {
|
||||
return $custom_template;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for single event view (temporary)
|
||||
if ( is_singular( 'tribe_events' ) ) {
|
||||
$custom_template = HVAC_CE_PLUGIN_DIR . 'templates/single-tribe_events.php';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,413 @@
|
|||
<?php
|
||||
/**
|
||||
* Template Name: HVAC Event Summary
|
||||
*
|
||||
* This template handles the display of the HVAC Event Summary page.
|
||||
* It shows detailed information about a specific event, including ticket sales,
|
||||
* attendee information, and revenue tracking.
|
||||
*
|
||||
* @package HVAC Community Events
|
||||
* @subpackage Templates
|
||||
* @author HVAC Community Events
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Get the event ID from the URL parameter
|
||||
$event_id = isset( $_GET['event_id'] ) ? absint( $_GET['event_id'] ) : 0;
|
||||
|
||||
// Ensure the data class is available
|
||||
if ( ! class_exists( 'HVAC_Event_Summary_Data' ) ) {
|
||||
// Attempt to include it if not loaded
|
||||
$class_path = plugin_dir_path( __FILE__ ) . '../includes/community/class-event-summary-data.php';
|
||||
if ( file_exists( $class_path ) ) {
|
||||
require_once $class_path;
|
||||
} else {
|
||||
// Handle error: Class not found, cannot display summary
|
||||
echo "<p>Error: Event Summary data handler not found.</p>";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the event summary data handler
|
||||
$summary_data_handler = new HVAC_Event_Summary_Data( $event_id );
|
||||
|
||||
// Check if the event is valid
|
||||
if ( ! $summary_data_handler->is_valid_event() ) {
|
||||
// Redirect to dashboard if the event doesn't exist or user doesn't have permission
|
||||
wp_safe_redirect( home_url( '/hvac-dashboard/' ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch all the required event data
|
||||
$event_details = $summary_data_handler->get_event_details();
|
||||
$venue_details = $summary_data_handler->get_event_venue_details();
|
||||
$organizer_details = $summary_data_handler->get_event_organizer_details();
|
||||
$transactions = $summary_data_handler->get_event_transactions();
|
||||
|
||||
// Calculate ticket sales summary data
|
||||
$total_tickets = 0;
|
||||
$total_revenue = 0;
|
||||
$ticket_types = array();
|
||||
|
||||
// Process transactions data
|
||||
if ( ! empty( $transactions ) ) {
|
||||
foreach ( $transactions as $txn ) {
|
||||
$total_tickets++;
|
||||
if ( isset( $txn['price'] ) ) {
|
||||
$total_revenue += floatval( $txn['price'] );
|
||||
}
|
||||
|
||||
// Count ticket types
|
||||
$ticket_type = $txn['ticket_type_name'] ?? 'Unknown';
|
||||
if ( isset( $ticket_types[$ticket_type] ) ) {
|
||||
$ticket_types[$ticket_type]['count']++;
|
||||
if ( isset( $txn['price'] ) ) {
|
||||
$ticket_types[$ticket_type]['revenue'] += floatval( $txn['price'] );
|
||||
}
|
||||
} else {
|
||||
$ticket_types[$ticket_type] = array(
|
||||
'count' => 1,
|
||||
'revenue' => isset( $txn['price'] ) ? floatval( $txn['price'] ) : 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start the template
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<div id="primary" class="content-area primary ast-container">
|
||||
<main id="main" class="site-main">
|
||||
|
||||
<!-- Event Summary Header & Navigation -->
|
||||
<div class="hvac-dashboard-header">
|
||||
<h1 class="entry-title"><?php echo esc_html( $event_details['title'] ); ?> - Summary</h1>
|
||||
<div class="hvac-dashboard-nav">
|
||||
<a href="<?php echo esc_url( home_url( '/hvac-dashboard/' ) ); ?>" class="ast-button ast-button-primary">Dashboard</a>
|
||||
<?php
|
||||
// Edit event link (if user has permission)
|
||||
if ( current_user_can( 'edit_post', $event_id ) ) {
|
||||
$edit_url = add_query_arg( 'event_id', $event_id, home_url( '/manage-event/' ) );
|
||||
echo '<a href="' . esc_url( $edit_url ) . '" class="ast-button ast-button-primary">Edit Event</a>';
|
||||
}
|
||||
|
||||
// View public event page
|
||||
echo '<a href="' . esc_url( $event_details['permalink'] ) . '" class="ast-button ast-button-secondary" target="_blank">View Public Page</a>';
|
||||
|
||||
// Email attendees link (future feature)
|
||||
if ( current_user_can( 'edit_post', $event_id ) ) {
|
||||
// TODO: Link to actual Email Attendees page when implemented (Phase 2)
|
||||
$email_url = '#'; // Placeholder for now
|
||||
echo '<a href="' . esc_url( $email_url ) . '" class="ast-button ast-button-secondary">Email Attendees</a>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event Overview Section -->
|
||||
<section class="hvac-event-summary-section">
|
||||
<h2>Event Overview</h2>
|
||||
<div class="hvac-event-summary-content">
|
||||
<!-- Event Details -->
|
||||
<div class="hvac-event-details">
|
||||
<table class="hvac-details-table">
|
||||
<tr>
|
||||
<th>Date & Time:</th>
|
||||
<td>
|
||||
<?php
|
||||
if ( function_exists( 'tribe_get_start_date' ) && function_exists( 'tribe_get_end_date' ) ) {
|
||||
echo esc_html( tribe_get_start_date( $event_id, false ) );
|
||||
if ( ! $event_details['is_all_day'] ) {
|
||||
echo ' @ ' . esc_html( tribe_get_start_date( $event_id, false, 'g:i a' ) );
|
||||
}
|
||||
// Show end date/time if different from start date
|
||||
$start_date = tribe_get_start_date( $event_id, false, 'Y-m-d' );
|
||||
$end_date = tribe_get_end_date( $event_id, false, 'Y-m-d' );
|
||||
if ( $start_date !== $end_date ) {
|
||||
echo ' - ' . esc_html( tribe_get_end_date( $event_id, false ) );
|
||||
if ( ! $event_details['is_all_day'] ) {
|
||||
echo ' @ ' . esc_html( tribe_get_end_date( $event_id, false, 'g:i a' ) );
|
||||
}
|
||||
} elseif ( ! $event_details['is_all_day'] ) {
|
||||
echo ' - ' . esc_html( tribe_get_end_date( $event_id, false, 'g:i a' ) );
|
||||
}
|
||||
} else {
|
||||
echo esc_html( $event_details['start_date'] ?? 'N/A' );
|
||||
echo ' - ';
|
||||
echo esc_html( $event_details['end_date'] ?? 'N/A' );
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Status:</th>
|
||||
<td><?php echo esc_html( ucfirst( get_post_status( $event_id ) ) ); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Cost:</th>
|
||||
<td><?php echo esc_html( $event_details['cost'] ?? 'N/A' ); ?></td>
|
||||
</tr>
|
||||
<?php if ( $venue_details && ! empty( $venue_details['name'] ) ) : ?>
|
||||
<tr>
|
||||
<th>Venue:</th>
|
||||
<td>
|
||||
<?php echo esc_html( $venue_details['name'] ); ?>
|
||||
<?php if ( ! empty( $venue_details['address'] ) ) : ?>
|
||||
<div class="hvac-detail-subtext"><?php echo esc_html( $venue_details['address'] ); ?></div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<?php if ( $organizer_details && ! empty( $organizer_details['name'] ) ) : ?>
|
||||
<tr>
|
||||
<th>Organizer:</th>
|
||||
<td>
|
||||
<?php echo esc_html( $organizer_details['name'] ); ?>
|
||||
<?php if ( ! empty( $organizer_details['email'] ) ) : ?>
|
||||
<div class="hvac-detail-subtext"><?php echo esc_html( $organizer_details['email'] ); ?></div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Event Statistics Section -->
|
||||
<section class="hvac-event-summary-section">
|
||||
<h2>Event Statistics</h2>
|
||||
<div class="hvac-stats-row">
|
||||
<!-- Total Tickets Stat Card -->
|
||||
<div class="hvac-stat-col">
|
||||
<div class="hvac-stat-card">
|
||||
<h3>Total Tickets</h3>
|
||||
<p class="metric-value"><?php echo esc_html( $total_tickets ); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Total Revenue Stat Card -->
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Ticket Types / Distribution -->
|
||||
<?php foreach ( $ticket_types as $type => $data ) : ?>
|
||||
<div class="hvac-stat-col">
|
||||
<div class="hvac-stat-card">
|
||||
<h3><?php echo esc_html( $type ); ?></h3>
|
||||
<p class="metric-value"><?php echo esc_html( $data['count'] ); ?></p>
|
||||
<small>$<?php echo esc_html( number_format( $data['revenue'], 2 ) ); ?></small>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Ticket Sales / Attendees Section -->
|
||||
<section class="hvac-event-summary-section">
|
||||
<h2>Ticket Sales & Attendees</h2>
|
||||
<?php if ( ! empty( $transactions ) ) : ?>
|
||||
<div class="hvac-event-summary-content">
|
||||
<table class="hvac-transactions-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Attendee</th>
|
||||
<th>Email</th>
|
||||
<th>Ticket Type</th>
|
||||
<th>Price</th>
|
||||
<th>Order ID</th>
|
||||
<th>Checked In</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ( $transactions as $txn ) : ?>
|
||||
<tr>
|
||||
<td><?php echo esc_html( $txn['purchaser_name'] ?? 'N/A' ); ?></td>
|
||||
<td><?php echo esc_html( $txn['purchaser_email'] ?? 'N/A' ); ?></td>
|
||||
<td><?php echo esc_html( $txn['ticket_type_name'] ?? 'N/A' ); ?></td>
|
||||
<td>$<?php echo esc_html( number_format( $txn['price'] ?? 0, 2 ) ); ?></td>
|
||||
<td><?php echo esc_html( $txn['order_id'] ?? 'N/A' ); ?></td>
|
||||
<td><?php echo $txn['checked_in'] ? 'Yes' : 'No'; ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<p>No ticket sales or attendees found for this event.</p>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<!-- Event Description Section -->
|
||||
<section class="hvac-event-summary-section">
|
||||
<h2>Event Description</h2>
|
||||
<div class="hvac-event-summary-content">
|
||||
<div class="hvac-event-description">
|
||||
<?php echo wp_kses_post( $event_details['description'] ); ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Include CSS for the Event Summary page -->
|
||||
<style>
|
||||
/* Event Summary Specific Styles */
|
||||
.hvac-event-summary-section {
|
||||
margin-bottom: 40px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
border: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.hvac-event-summary-section h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.hvac-event-summary-content {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/* Details Table */
|
||||
.hvac-details-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.hvac-details-table th,
|
||||
.hvac-details-table td {
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #eee;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.hvac-details-table th {
|
||||
width: 150px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hvac-detail-subtext {
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* Transactions Table */
|
||||
.hvac-transactions-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.hvac-transactions-table th,
|
||||
.hvac-transactions-table td {
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.hvac-transactions-table th {
|
||||
background-color: #f1f1f1;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hvac-transactions-table tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.hvac-transactions-table tr:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
/* Stats Row (reused from dashboard) */
|
||||
.hvac-stats-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
margin: -10px;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.hvac-stat-col {
|
||||
flex: 1;
|
||||
min-width: 160px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.hvac-stat-card {
|
||||
border: 1px solid #eee;
|
||||
padding: 15px;
|
||||
background: #fff;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.hvac-stat-card h3 {
|
||||
margin: 0 0 10px;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
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-dashboard-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.hvac-dashboard-nav {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.hvac-dashboard-nav a {
|
||||
margin: 5px 5px 5px 0;
|
||||
}
|
||||
|
||||
.hvac-details-table th {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.hvac-transactions-table {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
?>
|
||||
|
|
@ -186,11 +186,14 @@ get_header(); // Use theme's header
|
|||
<?php
|
||||
// Link to the new page containing the TEC CE submission form shortcode
|
||||
$edit_url = add_query_arg( 'event_id', $event['id'], home_url( '/manage-event/' ) );
|
||||
// Link to the standard WP single event view (handled by our custom template)
|
||||
$summary_url = get_permalink( $event['id'] );
|
||||
// Link to the custom event summary page
|
||||
$summary_url = add_query_arg( 'event_id', $event['id'], home_url( '/event-summary/' ) );
|
||||
// Link to the standard WP single event view
|
||||
$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( $summary_url ); ?>">Summary</a> |
|
||||
<a href="<?php echo esc_url( $view_url ); ?>" target="_blank">View</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
|||
Loading…
Reference in a new issue