🚨 CRITICAL: Fixed deployment blockers by adding missing core directories: **Community System (CRITICAL)** - includes/community/ - Login_Handler and all community classes - templates/community/ - Community login forms **Certificate System (CRITICAL)** - includes/certificates/ - 8+ certificate classes and handlers - templates/certificates/ - Certificate reports and generation templates **Core Individual Classes (CRITICAL)** - includes/class-hvac-event-summary.php - includes/class-hvac-trainer-profile-manager.php - includes/class-hvac-master-dashboard-data.php - Plus 40+ other individual HVAC classes **Major Feature Systems (HIGH)** - includes/database/ - Training leads database tables - includes/find-trainer/ - Find trainer directory and MapGeo integration - includes/google-sheets/ - Google Sheets integration system - includes/zoho/ - Complete Zoho CRM integration - includes/communication/ - Communication templates system **Template Infrastructure** - templates/attendee/, templates/email-attendees/ - templates/event-summary/, templates/status/ - templates/template-parts/ - Shared template components **Impact:** - 70+ files added covering 10+ missing directories - Resolves ALL deployment blockers and feature breakdowns - Plugin activation should now work correctly - Multi-machine deployment fully supported 🔧 Generated with Claude Code Co-Authored-By: Ben Reed <ben@tealmaker.com>
		
			
				
	
	
		
			461 lines
		
	
	
		
			No EOL
		
	
	
		
			16 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			461 lines
		
	
	
		
			No EOL
		
	
	
		
			16 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Simplified Generate Certificates Template
 | |
|  *
 | |
|  * @package HVAC_Community_Events
 | |
|  * @subpackage Templates/Certificates
 | |
|  */
 | |
| 
 | |
| // Exit if accessed directly
 | |
| if (!defined('ABSPATH')) {
 | |
|     exit;
 | |
| }
 | |
| 
 | |
| // Get current user ID
 | |
| $current_user_id = get_current_user_id();
 | |
| 
 | |
| // Get event ID from URL
 | |
| $event_id = isset($_GET['event_id']) ? absint($_GET['event_id']) : 0;
 | |
| 
 | |
| // Initialize variables
 | |
| $events = array();
 | |
| $attendees = array();
 | |
| $selected_event_title = '';
 | |
| 
 | |
| try {
 | |
|     // Get user's events directly from database
 | |
|     global $wpdb;
 | |
|     
 | |
|     $events = $wpdb->get_results($wpdb->prepare(
 | |
|         "SELECT ID, post_title, post_date 
 | |
|          FROM {$wpdb->posts} 
 | |
|          WHERE post_type = 'tribe_events' 
 | |
|          AND post_author = %d 
 | |
|          AND post_status = 'publish' 
 | |
|          ORDER BY post_date DESC",
 | |
|         $current_user_id
 | |
|     ));
 | |
| 
 | |
|     // If event is selected, get attendees
 | |
|     if ($event_id > 0) {
 | |
|         // Verify the event belongs to the current user
 | |
|         $event_found = false;
 | |
|         foreach ($events as $event) {
 | |
|             if ($event->ID == $event_id) {
 | |
|                 $event_found = true;
 | |
|                 $selected_event_title = $event->post_title;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         if ($event_found) {
 | |
|             // Get attendees for the selected event
 | |
|             $attendees = $wpdb->get_results($wpdb->prepare(
 | |
|                 "SELECT p.ID as attendee_id, 
 | |
|                         pm1.meta_value as holder_name,
 | |
|                         pm2.meta_value as holder_email,
 | |
|                         pm3.meta_value as check_in
 | |
|                  FROM {$wpdb->posts} p
 | |
|                  LEFT JOIN {$wpdb->postmeta} pm1 ON p.ID = pm1.post_id AND pm1.meta_key = '_tribe_tickets_full_name'
 | |
|                  LEFT JOIN {$wpdb->postmeta} pm2 ON p.ID = pm2.post_id AND pm2.meta_key = '_tribe_tickets_email'
 | |
|                  LEFT JOIN {$wpdb->postmeta} pm3 ON p.ID = pm3.post_id AND pm3.meta_key = '_tribe_tickets_checked_in'
 | |
|                  LEFT JOIN {$wpdb->postmeta} pm4 ON p.ID = pm4.post_id AND pm4.meta_key = '_tribe_tickets_event'
 | |
|                  WHERE p.post_type = 'tribe_ticket_attendee'
 | |
|                  AND p.post_status = 'publish'
 | |
|                  AND pm4.meta_value = %d
 | |
|                  ORDER BY pm1.meta_value ASC",
 | |
|                 $event_id
 | |
|             ));
 | |
|         }
 | |
|     }
 | |
|     
 | |
| } catch (Exception $e) {
 | |
|     error_log('Generate Certificates Error: ' . $e->getMessage());
 | |
| }
 | |
| 
 | |
| // Get header
 | |
| get_header();
 | |
| ?>
 | |
| 
 | |
| <div class="hvac-container">
 | |
|     <div class="hvac-content-wrapper">
 | |
|         <!-- Navigation Header -->
 | |
|         <div class="hvac-dashboard-header">
 | |
|             <h1 class="entry-title">Generate Certificates</h1>
 | |
|             <div class="hvac-dashboard-nav">
 | |
|                 <a href="<?php echo esc_url(home_url('/hvac-dashboard/')); ?>" class="ast-button ast-button-secondary">Dashboard</a>
 | |
|                 <a href="<?php echo esc_url(home_url('/certificate-reports/')); ?>" class="ast-button ast-button-secondary">Certificate Reports</a>
 | |
|                 <a href="<?php echo esc_url(home_url('/manage-event/')); ?>" class="ast-button ast-button-primary">Create Event</a>
 | |
|             </div>
 | |
|         </div>
 | |
|         
 | |
|         <div class="hvac-page-header">
 | |
|             <p class="hvac-page-description">Generate certificates for attendees of your events.</p>
 | |
|         </div>
 | |
|         
 | |
|         <!-- Step 1: Select Event -->
 | |
|         <div class="hvac-section hvac-step-section">
 | |
|             <h2>Step 1: Select Event</h2>
 | |
|             
 | |
|             <?php if (empty($events)) : ?>
 | |
|                 <div class="hvac-no-events">
 | |
|                     <p>You don't have any events yet. Create your first event to start generating certificates.</p>
 | |
|                     <p><a href="<?php echo esc_url(home_url('/manage-event/')); ?>" class="hvac-button hvac-primary">Create Event</a></p>
 | |
|                 </div>
 | |
|             <?php else : ?>
 | |
|                 <div class="hvac-form-group">
 | |
|                     <label for="event_id">Select an event to generate certificates for:</label>
 | |
|                     <select name="event_id" id="event_id" class="hvac-select" required>
 | |
|                         <option value="">Choose an event...</option>
 | |
|                         <?php foreach ($events as $event) : ?>
 | |
|                             <option value="<?php echo esc_attr($event->ID); ?>" <?php selected($event_id, $event->ID); ?>>
 | |
|                                 <?php echo esc_html($event->post_title) . ' (' . date('M j, Y', strtotime($event->post_date)) . ')'; ?>
 | |
|                             </option>
 | |
|                         <?php endforeach; ?>
 | |
|                     </select>
 | |
|                 </div>
 | |
|             <?php endif; ?>
 | |
|         </div>
 | |
| 
 | |
|         <!-- Step 2: Select Attendees (shown when event is selected) -->
 | |
|         <?php if ($event_id > 0) : ?>
 | |
|             <div class="hvac-section hvac-step-section" id="step-select-attendees">
 | |
|                 <h2>Step 2: Select Attendees for "<?php echo esc_html($selected_event_title); ?>"</h2>
 | |
|                 
 | |
|                 <?php if (empty($attendees)) : ?>
 | |
|                     <div class="hvac-no-attendees">
 | |
|                         <p>This event has no attendees yet.</p>
 | |
|                         <p>Attendees are created when people register for your event through the ticket system.</p>
 | |
|                     </div>
 | |
|                 <?php else : ?>
 | |
|                     <form id="generate-certificates-form" method="post" action="">
 | |
|                         <?php wp_nonce_field('hvac_generate_certificates', 'hvac_certificate_nonce'); ?>
 | |
|                         <input type="hidden" name="event_id" value="<?php echo esc_attr($event_id); ?>">
 | |
|                         <input type="hidden" name="generate_certificates" value="1">
 | |
|                         
 | |
|                         <div class="hvac-form-group">
 | |
|                             <div class="hvac-table-actions">
 | |
|                                 <button type="button" class="hvac-button hvac-secondary" id="select-all-attendees">Select All</button>
 | |
|                                 <button type="button" class="hvac-button hvac-secondary" id="select-checked-in">Select Checked-In Only</button>
 | |
|                                 <button type="button" class="hvac-button hvac-secondary" id="deselect-all-attendees">Deselect All</button>
 | |
|                             </div>
 | |
|                             
 | |
|                             <div class="hvac-attendees-table-wrapper">
 | |
|                                 <table class="hvac-attendees-table">
 | |
|                                     <thead>
 | |
|                                         <tr>
 | |
|                                             <th class="hvac-checkbox-column">
 | |
|                                                 <input type="checkbox" id="select-all-checkbox">
 | |
|                                             </th>
 | |
|                                             <th>Attendee Name</th>
 | |
|                                             <th>Email</th>
 | |
|                                             <th>Check-in Status</th>
 | |
|                                         </tr>
 | |
|                                     </thead>
 | |
|                                     <tbody>
 | |
|                                         <?php foreach ($attendees as $attendee) : 
 | |
|                                             $checked_in = !empty($attendee->check_in);
 | |
|                                             $checked_in_class = $checked_in ? 'hvac-checked-in' : '';
 | |
|                                             $status_class = $checked_in ? 'hvac-status-checked-in' : 'hvac-status-not-checked-in';
 | |
|                                             $status_text = $checked_in ? 'Checked In' : 'Not Checked In';
 | |
|                                             $attendee_name = $attendee->holder_name ?: 'Unknown';
 | |
|                                             $attendee_email = $attendee->holder_email ?: 'No email';
 | |
|                                         ?>
 | |
|                                             <tr class="<?php echo esc_attr($checked_in_class); ?>">
 | |
|                                                 <td>
 | |
|                                                     <input type="checkbox" 
 | |
|                                                            name="attendee_ids[]" 
 | |
|                                                            value="<?php echo esc_attr($attendee->attendee_id); ?>" 
 | |
|                                                            class="attendee-checkbox" 
 | |
|                                                            <?php echo $checked_in ? 'checked' : ''; ?>>
 | |
|                                                 </td>
 | |
|                                                 <td><?php echo esc_html($attendee_name); ?></td>
 | |
|                                                 <td><?php echo esc_html($attendee_email); ?></td>
 | |
|                                                 <td>
 | |
|                                                     <span class="<?php echo esc_attr($status_class); ?>">
 | |
|                                                         <?php echo esc_html($status_text); ?>
 | |
|                                                     </span>
 | |
|                                                 </td>
 | |
|                                             </tr>
 | |
|                                         <?php endforeach; ?>
 | |
|                                     </tbody>
 | |
|                                 </table>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         
 | |
|                         <div class="hvac-form-group">
 | |
|                             <button type="submit" class="hvac-button hvac-primary hvac-large hvac-touch-target" id="generate-certificates-btn">
 | |
|                                 Generate Certificates for Selected Attendees
 | |
|                             </button>
 | |
|                         </div>
 | |
|                     </form>
 | |
|                 <?php endif; ?>
 | |
|             </div>
 | |
|         <?php endif; ?>
 | |
|         
 | |
|         <!-- Results Section -->
 | |
|         <div id="generation-results" class="hvac-section" style="display: none;">
 | |
|             <h2>Certificate Generation Results</h2>
 | |
|             <div id="results-content"></div>
 | |
|         </div>
 | |
|     </div>
 | |
| </div>
 | |
| 
 | |
| <style>
 | |
| .hvac-container {
 | |
|     max-width: 1200px;
 | |
|     margin: 0 auto;
 | |
|     padding: 20px;
 | |
| }
 | |
| 
 | |
| .hvac-dashboard-header {
 | |
|     display: flex;
 | |
|     justify-content: space-between;
 | |
|     align-items: center;
 | |
|     margin-bottom: 30px;
 | |
|     flex-wrap: wrap;
 | |
|     gap: 15px;
 | |
| }
 | |
| 
 | |
| .hvac-dashboard-nav {
 | |
|     display: flex;
 | |
|     gap: 10px;
 | |
|     flex-wrap: wrap;
 | |
| }
 | |
| 
 | |
| .hvac-section {
 | |
|     margin-bottom: 30px;
 | |
|     padding: 20px;
 | |
|     background: #f8f9fa;
 | |
|     border-radius: 8px;
 | |
|     border: 1px solid #e9ecef;
 | |
| }
 | |
| 
 | |
| .hvac-section h2 {
 | |
|     margin: 0 0 20px 0;
 | |
|     color: #007cba;
 | |
| }
 | |
| 
 | |
| .hvac-form-group {
 | |
|     margin-bottom: 20px;
 | |
| }
 | |
| 
 | |
| .hvac-form-group label {
 | |
|     display: block;
 | |
|     margin-bottom: 8px;
 | |
|     font-weight: bold;
 | |
| }
 | |
| 
 | |
| .hvac-select {
 | |
|     width: 100%;
 | |
|     max-width: 500px;
 | |
|     padding: 10px;
 | |
|     border: 1px solid #ddd;
 | |
|     border-radius: 4px;
 | |
|     font-size: 16px;
 | |
| }
 | |
| 
 | |
| .hvac-button {
 | |
|     padding: 10px 20px;
 | |
|     background: #007cba;
 | |
|     color: white;
 | |
|     text-decoration: none;
 | |
|     border-radius: 4px;
 | |
|     border: none;
 | |
|     cursor: pointer;
 | |
|     display: inline-block;
 | |
|     font-size: 14px;
 | |
| }
 | |
| 
 | |
| .hvac-button:hover {
 | |
|     background: #005a87;
 | |
|     color: white;
 | |
| }
 | |
| 
 | |
| .hvac-button.hvac-secondary {
 | |
|     background: #6c757d;
 | |
| }
 | |
| 
 | |
| .hvac-button.hvac-secondary:hover {
 | |
|     background: #5a6268;
 | |
| }
 | |
| 
 | |
| .hvac-button.hvac-large {
 | |
|     padding: 15px 30px;
 | |
|     font-size: 16px;
 | |
|     font-weight: bold;
 | |
| }
 | |
| 
 | |
| .hvac-touch-target {
 | |
|     min-height: 44px;
 | |
|     min-width: 44px;
 | |
| }
 | |
| 
 | |
| .hvac-table-actions {
 | |
|     margin-bottom: 15px;
 | |
|     display: flex;
 | |
|     gap: 10px;
 | |
|     flex-wrap: wrap;
 | |
| }
 | |
| 
 | |
| .hvac-attendees-table {
 | |
|     width: 100%;
 | |
|     border-collapse: collapse;
 | |
|     background: white;
 | |
|     border-radius: 4px;
 | |
|     overflow: hidden;
 | |
| }
 | |
| 
 | |
| .hvac-attendees-table th,
 | |
| .hvac-attendees-table td {
 | |
|     padding: 12px;
 | |
|     text-align: left;
 | |
|     border-bottom: 1px solid #ddd;
 | |
| }
 | |
| 
 | |
| .hvac-attendees-table th {
 | |
|     background: #007cba;
 | |
|     color: white;
 | |
|     font-weight: bold;
 | |
| }
 | |
| 
 | |
| .hvac-checkbox-column {
 | |
|     width: 50px;
 | |
|     text-align: center;
 | |
| }
 | |
| 
 | |
| .hvac-checkbox-column input {
 | |
|     margin: 0;
 | |
| }
 | |
| 
 | |
| .hvac-checked-in {
 | |
|     background-color: #d4edda;
 | |
| }
 | |
| 
 | |
| .hvac-status-checked-in {
 | |
|     color: #155724;
 | |
|     font-weight: bold;
 | |
| }
 | |
| 
 | |
| .hvac-status-not-checked-in {
 | |
|     color: #721c24;
 | |
| }
 | |
| 
 | |
| .hvac-no-events,
 | |
| .hvac-no-attendees {
 | |
|     text-align: center;
 | |
|     padding: 40px;
 | |
|     background: white;
 | |
|     border-radius: 8px;
 | |
|     border: 2px dashed #ddd;
 | |
| }
 | |
| 
 | |
| @media (max-width: 768px) {
 | |
|     .hvac-dashboard-header {
 | |
|         flex-direction: column;
 | |
|         align-items: stretch;
 | |
|     }
 | |
|     
 | |
|     .hvac-attendees-table {
 | |
|         font-size: 14px;
 | |
|     }
 | |
|     
 | |
|     .hvac-attendees-table th,
 | |
|     .hvac-attendees-table td {
 | |
|         padding: 8px;
 | |
|     }
 | |
|     
 | |
|     .hvac-table-actions {
 | |
|         flex-direction: column;
 | |
|     }
 | |
| }
 | |
| </style>
 | |
| 
 | |
| <script>
 | |
| jQuery(document).ready(function($) {
 | |
|     // Handle event selection change
 | |
|     $('#event_id').on('change', function() {
 | |
|         var eventId = $(this).val();
 | |
|         if (eventId) {
 | |
|             // Reload page with selected event
 | |
|             window.location.href = window.location.pathname + '?event_id=' + eventId;
 | |
|         }
 | |
|     });
 | |
|     
 | |
|     // Select all checkbox functionality
 | |
|     $('#select-all-checkbox').on('change', function() {
 | |
|         $('.attendee-checkbox').prop('checked', this.checked);
 | |
|     });
 | |
|     
 | |
|     // Individual checkbox change
 | |
|     $('.attendee-checkbox').on('change', function() {
 | |
|         var totalCheckboxes = $('.attendee-checkbox').length;
 | |
|         var checkedCheckboxes = $('.attendee-checkbox:checked').length;
 | |
|         $('#select-all-checkbox').prop('checked', totalCheckboxes === checkedCheckboxes);
 | |
|     });
 | |
|     
 | |
|     // Select all button
 | |
|     $('#select-all-attendees').on('click', function() {
 | |
|         $('.attendee-checkbox').prop('checked', true);
 | |
|         $('#select-all-checkbox').prop('checked', true);
 | |
|     });
 | |
|     
 | |
|     // Select checked-in only button
 | |
|     $('#select-checked-in').on('click', function() {
 | |
|         $('.attendee-checkbox').prop('checked', false);
 | |
|         $('.hvac-checked-in .attendee-checkbox').prop('checked', true);
 | |
|         
 | |
|         // Update select all checkbox
 | |
|         var totalCheckboxes = $('.attendee-checkbox').length;
 | |
|         var checkedCheckboxes = $('.attendee-checkbox:checked').length;
 | |
|         $('#select-all-checkbox').prop('checked', totalCheckboxes === checkedCheckboxes);
 | |
|     });
 | |
|     
 | |
|     // Deselect all button
 | |
|     $('#deselect-all-attendees').on('click', function() {
 | |
|         $('.attendee-checkbox').prop('checked', false);
 | |
|         $('#select-all-checkbox').prop('checked', false);
 | |
|     });
 | |
|     
 | |
|     // Form submission
 | |
|     $('#generate-certificates-form').on('submit', function(e) {
 | |
|         e.preventDefault();
 | |
|         
 | |
|         var checkedAttendees = $('.attendee-checkbox:checked').length;
 | |
|         if (checkedAttendees === 0) {
 | |
|             alert('Please select at least one attendee to generate certificates for.');
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         if (!confirm('Generate certificates for ' + checkedAttendees + ' selected attendees?')) {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         var $button = $('#generate-certificates-btn');
 | |
|         var originalText = $button.text();
 | |
|         $button.text('Generating Certificates...').prop('disabled', true);
 | |
|         
 | |
|         // Submit form via AJAX (or fall back to regular submission)
 | |
|         var formData = $(this).serialize();
 | |
|         
 | |
|         $.ajax({
 | |
|             url: ajaxurl || window.location.href,
 | |
|             type: 'POST',
 | |
|             data: formData,
 | |
|             success: function(response) {
 | |
|                 $('#generation-results').show();
 | |
|                 $('#results-content').html('<div class="hvac-success">Certificates generated successfully for ' + checkedAttendees + ' attendees!</div>');
 | |
|                 $button.text(originalText).prop('disabled', false);
 | |
|             },
 | |
|             error: function() {
 | |
|                 // Fall back to regular form submission
 | |
|                 document.getElementById('generate-certificates-form').submit();
 | |
|             }
 | |
|         });
 | |
|     });
 | |
| });
 | |
| </script>
 | |
| 
 | |
| <?php
 | |
| get_footer();
 | |
| ?>
 |