From 91873c6a9c18d32f95b47c64712ef755e7c4ff85 Mon Sep 17 00:00:00 2001 From: ben Date: Fri, 26 Sep 2025 20:24:31 -0300 Subject: [PATCH] feat: implement comprehensive featured image system for events, organizers, and venues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add featured image field to main event creation form with WordPress media uploader - Implement featured image upload in organizer and venue creation modals - Update AJAX handlers to process and validate featured image attachments - Add comprehensive media upload UI with preview and removal functionality - Include proper permission validation for administrator, trainer, and master trainer roles - Create authoritative documentation for complete event creation page functionality 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- assets/js/hvac-modal-forms.js | 106 ++- docs/EVENT-CREATION-PAGE-DOCUMENTATION.md | 739 +++++++++++++++++++++ includes/class-hvac-ajax-handlers.php | 28 +- includes/class-hvac-event-form-builder.php | 135 +++- 4 files changed, 1002 insertions(+), 6 deletions(-) create mode 100644 docs/EVENT-CREATION-PAGE-DOCUMENTATION.md diff --git a/assets/js/hvac-modal-forms.js b/assets/js/hvac-modal-forms.js index 99b1ec77..abba4310 100644 --- a/assets/js/hvac-modal-forms.js +++ b/assets/js/hvac-modal-forms.js @@ -47,6 +47,17 @@ this.closeModal(); } }); + + // Media upload handlers + $(document).on('click', '.hvac-modal .select-image-btn', (e) => { + e.preventDefault(); + this.openMediaUploader(e.target); + }); + + $(document).on('click', '.hvac-modal .remove-image', (e) => { + e.preventDefault(); + this.removeImage(e.target); + }); } createModalContainer() { @@ -104,7 +115,8 @@ { name: 'organizer_name', label: 'Organizer Name', type: 'text', required: true }, { name: 'organizer_email', label: 'Email', type: 'email', required: false }, { name: 'organizer_website', label: 'Website', type: 'url', required: false }, - { name: 'organizer_phone', label: 'Phone', type: 'tel', required: false } + { name: 'organizer_phone', label: 'Phone', type: 'tel', required: false }, + { name: 'organizer_featured_image', label: 'Featured Image', type: 'media', required: false } ], action: 'hvac_create_organizer' }, @@ -127,7 +139,8 @@ { name: 'venue_zip', label: 'Zip/Postal Code', type: 'text', required: false }, { name: 'venue_country', label: 'Country', type: 'text', required: false }, { name: 'venue_website', label: 'Website', type: 'url', required: false }, - { name: 'venue_phone', label: 'Phone', type: 'tel', required: false } + { name: 'venue_phone', label: 'Phone', type: 'tel', required: false }, + { name: 'venue_featured_image', label: 'Featured Image', type: 'media', required: false } ], action: 'hvac_create_venue' } @@ -184,6 +197,33 @@ `; } + if (field.type === 'media') { + return ` +
+ +
+
+ +
+
+ + + +
+

+ Recommended: 300x300 pixels or larger +

+
+
+ `; + } + return `
@@ -284,6 +324,68 @@ }, 5000); } + openMediaUploader(button) { + const $button = $(button); + const $fieldContainer = $button.closest('.hvac-media-field'); + const $imagePreview = $fieldContainer.find('.image-preview'); + const $previewImg = $fieldContainer.find('.image-preview img'); + const $imageIdInput = $fieldContainer.find('.image-id-input'); + const $imageUrlInput = $fieldContainer.find('.image-url-input'); + + // Create WordPress media frame + const mediaUploader = wp.media({ + title: 'Select Image', + button: { + text: 'Select Image' + }, + multiple: false, + library: { + type: 'image' + } + }); + + // When an image is selected + mediaUploader.on('select', () => { + const attachment = mediaUploader.state().get('selection').first().toJSON(); + + // Update hidden inputs + $imageIdInput.val(attachment.id); + $imageUrlInput.val(attachment.url); + + // Update preview + $previewImg.attr('src', attachment.url); + $previewImg.attr('alt', attachment.alt || attachment.title || 'Selected image'); + $imagePreview.show(); + + // Update button text + $button.html('Change Image'); + }); + + // Open the media modal + mediaUploader.open(); + } + + removeImage(button) { + const $button = $(button); + const $fieldContainer = $button.closest('.hvac-media-field'); + const $imagePreview = $fieldContainer.find('.image-preview'); + const $previewImg = $fieldContainer.find('.image-preview img'); + const $imageIdInput = $fieldContainer.find('.image-id-input'); + const $imageUrlInput = $fieldContainer.find('.image-url-input'); + const $selectBtn = $fieldContainer.find('.select-image-btn'); + + // Clear inputs + $imageIdInput.val(''); + $imageUrlInput.val(''); + + // Hide preview + $imagePreview.hide(); + $previewImg.attr('src', ''); + + // Reset button text + $selectBtn.html('Select Image'); + } + capitalizeFirst(str) { return str.charAt(0).toUpperCase() + str.slice(1); } diff --git a/docs/EVENT-CREATION-PAGE-DOCUMENTATION.md b/docs/EVENT-CREATION-PAGE-DOCUMENTATION.md new file mode 100644 index 00000000..8446fa71 --- /dev/null +++ b/docs/EVENT-CREATION-PAGE-DOCUMENTATION.md @@ -0,0 +1,739 @@ +# HVAC Community Events - Event Creation Page Documentation + +**Version:** 3.2.0 +**Last Updated:** January 2025 +**Status:** Production Ready + +## Overview + +The HVAC Community Events plugin provides a comprehensive event creation system designed specifically for HVAC training organizations. This document serves as the authoritative reference for the event creation page functionality, architecture, and implementation details. + +## Table of Contents + +1. [System Architecture](#system-architecture) +2. [User Interface Components](#user-interface-components) +3. [Form Fields Reference](#form-fields-reference) +4. [Dynamic Features](#dynamic-features) +5. [Role-Based Access Control](#role-based-access-control) +6. [API Endpoints](#api-endpoints) +7. [Security Implementation](#security-implementation) +8. [Template System](#template-system) +9. [Integration Points](#integration-points) +10. [Performance Considerations](#performance-considerations) +11. [Troubleshooting Guide](#troubleshooting-guide) + +--- + +## System Architecture + +### Core Components + +The event creation system is built on a modular architecture with the following primary components: + +#### 1. **HVAC_Event_Form_Builder** +- **File:** `includes/class-hvac-event-form-builder.php` +- **Purpose:** Central form generation and validation engine +- **Pattern:** Singleton with fluent interface +- **Responsibilities:** + - Form field rendering and validation + - Progressive disclosure management + - Template integration + - Media upload handling + - Security implementation + +#### 2. **HVAC_Ajax_Handlers** +- **File:** `includes/class-hvac-ajax-handlers.php` +- **Purpose:** Server-side AJAX request processing +- **Pattern:** Singleton with dependency injection +- **Responsibilities:** + - AI-powered event population + - Dynamic search functionality + - Entity creation (venues, organizers, categories) + - Security validation and nonce verification + +#### 3. **Frontend JavaScript Components** +- **AI Assistant:** `assets/js/hvac-ai-assist.js` +- **Searchable Selectors:** `assets/js/hvac-searchable-selectors.js` +- **Modal Forms:** `assets/js/hvac-modal-forms.js` +- **Purpose:** Rich user interface interactions +- **Pattern:** ES6 classes with event delegation + +#### 4. **Template System** +- **File:** `templates/page-tec-create-event.php` +- **Purpose:** WordPress-native page template +- **Integration:** The Events Calendar compatibility +- **Features:** Responsive design, accessibility compliance + +--- + +## User Interface Components + +### Layout Structure + +``` +Event Creation Page +├── Header Section +│ ├── Page Title +│ ├── Breadcrumb Navigation +│ └── User Context Information +├── Main Form Container +│ ├── Basic Event Fields +│ ├── Featured Image Upload +│ ├── DateTime Management +│ ├── Venue Selection +│ ├── Organizer Management +│ ├── Category Assignment +│ └── Advanced Options (Collapsible) +├── AI Assistant Panel +│ ├── Input Methods (URL, Text, Manual) +│ ├── Processing Indicators +│ └── Confidence Metrics +└── Footer Actions + ├── Save Draft + ├── Preview + └── Publish Event +``` + +### Progressive Disclosure + +The interface implements progressive disclosure to reduce cognitive load: + +- **Basic Fields:** Always visible, essential information +- **Advanced Options:** Collapsible section for power users +- **Modal Forms:** Overlay interfaces for entity creation +- **AI Assistant:** Contextual panel that appears when needed + +--- + +## Form Fields Reference + +### Basic Event Information + +#### Event Title +- **Type:** Text input +- **Validation:** 3-200 characters, required +- **Sanitization:** `sanitize_text_field()` +- **Purpose:** Primary event identifier + +#### Event Description +- **Type:** WordPress TinyMCE rich text editor +- **Features:** + - Custom toolbar: Format, Bold, Italic, Lists, Links, Alignment + - Markdown-to-HTML conversion support + - Paste cleanup for external content +- **Validation:** HTML content filtering with `wp_kses` +- **Purpose:** Detailed event information + +#### Featured Image +- **Type:** WordPress Media Uploader +- **Constraints:** Image files only +- **Recommended:** 1200x630 pixels +- **Storage:** WordPress attachment with post thumbnail relationship +- **Purpose:** Visual representation for event listings + +### Date and Time Management + +#### Start Date & Time +- **Type:** HTML5 `datetime-local` input +- **Validation:** Must be future date +- **Format:** WordPress-compatible datetime +- **Integration:** The Events Calendar meta fields + +#### End Date & Time +- **Type:** HTML5 `datetime-local` input +- **Validation:** Must be after start date +- **Default:** 2 hours after start time +- **Integration:** TEC `_EventEndDate` meta field + +#### Timezone +- **Type:** Dropdown select +- **Options:** WordPress timezone list +- **Default:** Site timezone setting +- **Storage:** `_EventTimezone` meta field +- **Advanced:** Hidden by default, revealed in advanced options + +### Venue Management + +#### Venue Selection +- **Type:** Searchable single-select +- **Search:** Real-time AJAX with 2+ character minimum +- **Features:** + - Autocomplete with venue address display + - "Add New" modal for inline venue creation + - Address validation and formatting +- **Integration:** TEC `_EventVenueID` relationship + +#### Venue Creation Modal +- **Fields:** + - Venue Name (required) + - Address, City, State, Zip, Country + - Website, Phone + - Featured Image +- **Permissions:** Trainers, Master Trainers, Administrators +- **Validation:** Address normalization, phone formatting + +### Organizer Management + +#### Organizer Selection +- **Type:** Searchable multi-select +- **Limit:** Maximum 3 organizers per event +- **Search:** Real-time AJAX with contact information display +- **Features:** + - Selected item display with removal + - "Add New" modal for inline organizer creation + - Email and phone display in search results +- **Integration:** TEC `_EventOrganizerID` array + +#### Organizer Creation Modal +- **Fields:** + - Organizer Name (required) + - Email, Website, Phone + - Featured Image +- **Permissions:** Trainers, Master Trainers, Administrators +- **Validation:** Email format, URL validation + +### Category Assignment + +#### Category Selection +- **Type:** Searchable multi-select +- **Limit:** Maximum 3 categories per event +- **Source:** WordPress `tribe_events_cat` taxonomy +- **Features:** + - Hierarchical category display + - Description tooltips + - Role-based creation permissions +- **Integration:** WordPress taxonomy relationship + +#### Category Creation Modal +- **Fields:** + - Category Name (required) + - Description +- **Permissions:** Master Trainers only +- **Validation:** Taxonomy name sanitization + +### Advanced Fields + +#### Event Capacity +- **Type:** Number input +- **Range:** 1-10,000 attendees +- **Purpose:** Registration limit setting +- **Integration:** TEC capacity management +- **Advanced:** Hidden by default + +#### Event Cost +- **Type:** Number input with decimal support +- **Format:** Currency display +- **Purpose:** Event pricing information +- **Integration:** TEC cost meta fields +- **Advanced:** Hidden by default + +--- + +## Dynamic Features + +### AI Assistant System + +#### Input Methods + +**1. URL Processing** +- **Supported Platforms:** EventBrite, Facebook Events, Meetup, General URLs +- **Process:** + 1. URL validation and platform detection + 2. Content extraction with timeout handling (60 seconds) + 3. Data parsing and confidence scoring + 4. Form field population with validation +- **Rate Limiting:** 10 requests per hour per user + +**2. Text Extraction** +- **Purpose:** Process existing event descriptions or marketing copy +- **Features:** + - Smart field detection (title, date, location extraction) + - Markdown processing with list formatting + - Content cleanup and normalization +- **Validation:** 10+ character minimum + +**3. Manual Description** +- **Purpose:** AI-generated content from user prompts +- **Features:** + - Context-aware content generation + - Professional formatting + - Industry-specific terminology +- **Output:** Structured markdown converted to HTML + +#### Processing Flow + +```mermaid +graph TD + A[User Input] --> B[Input Validation] + B --> C[AI Processing Request] + C --> D[Progress Indication] + D --> E[Response Processing] + E --> F[Confidence Analysis] + F --> G[Form Population] + G --> H[User Validation] +``` + +#### Confidence Scoring + +The AI system provides confidence levels for each populated field: + +- **High (90-100%):** Green indicator, auto-accept +- **Medium (70-89%):** Yellow indicator, user review recommended +- **Low (50-69%):** Orange indicator, manual verification required +- **Very Low (<50%):** Red indicator, suggests manual entry + +### Searchable Selectors + +#### Real-time Search Implementation + +**Debounced AJAX Requests:** +- **Trigger:** 2+ characters entered +- **Delay:** 300ms debounce +- **Caching:** Client-side result caching for 5 minutes +- **Error Handling:** Graceful degradation with fallback options + +**Search Results Display:** +- **Venue Results:** Name, full address, phone +- **Organizer Results:** Name, email, organization +- **Category Results:** Name, description, event count + +#### Selection Management + +**Multi-select Behavior (Organizers, Categories):** +- Visual selected item display with removal buttons +- Duplicate prevention +- Maximum selection enforcement +- Keyboard navigation support + +**Single-select Behavior (Venues):** +- Replacement selection model +- Clear selection option +- Visual state management + +### Modal Creation Forms + +#### WordPress Media Integration + +**Featured Image Upload:** +- **Interface:** Native WordPress Media Library +- **Features:** + - Image preview with removal option + - File type validation + - Size recommendations + - Alt text management +- **Storage:** WordPress attachment system + +#### Form Validation + +**Client-side Validation:** +- Real-time field validation +- Visual error indicators +- Progressive enhancement + +**Server-side Validation:** +- Comprehensive input sanitization +- Business rule enforcement +- Security validation + +--- + +## Role-Based Access Control + +### Permission Levels + +#### Unauthenticated Users +- **Access:** Redirected to login page +- **Message:** Clear authentication requirement + +#### Standard WordPress Users +- **Access:** Denied with capability check +- **Requirement:** Must have HVAC-specific roles + +#### HVAC Trainers +- **Permissions:** + - Create and edit events + - Create organizers and venues + - Use AI assistant features + - Access basic template system +- **Restrictions:** + - Cannot create categories + - Limited template management + +#### HVAC Master Trainers +- **Permissions:** + - All trainer permissions + - Create and manage categories + - Full template system access + - Advanced configuration options + - User management capabilities + +#### Administrators +- **Permissions:** + - Complete system access + - Plugin configuration + - Role management + - System maintenance + +### Security Implementation + +#### Nonce Verification +```php +// Example nonce verification +$security_check = HVAC_Ajax_Security::verify_ajax_request( + 'create_event', + HVAC_Ajax_Security::NONCE_GENERAL, + array('hvac_trainer', 'hvac_master_trainer'), + false +); +``` + +#### Input Sanitization +- **Text Fields:** `sanitize_text_field()` +- **Email Fields:** `sanitize_email()` +- **URL Fields:** `esc_url_raw()` +- **HTML Content:** `wp_kses()` with allowed tags +- **Number Fields:** `absint()` or `floatval()` + +--- + +## API Endpoints + +### Core AJAX Handlers + +#### Event Population +- **Endpoint:** `hvac_ai_populate_event` +- **Method:** POST +- **Purpose:** AI-powered event data extraction +- **Parameters:** + - `input_text` (string): URL or text content + - `input_type` (enum): 'url', 'text', 'description' + - `nonce` (string): Security token +- **Response:** JSON with populated field data and confidence scores + +#### Search Endpoints + +**Organizer Search:** +- **Endpoint:** `hvac_search_organizers` +- **Parameters:** `search` (string, 2+ chars) +- **Response:** Array of organizer objects with contact info + +**Venue Search:** +- **Endpoint:** `hvac_search_venues` +- **Parameters:** `search` (string, 2+ chars) +- **Response:** Array of venue objects with address info + +**Category Search:** +- **Endpoint:** `hvac_search_categories` +- **Parameters:** `search` (string, 2+ chars) +- **Response:** Array of category objects with descriptions + +#### Entity Creation + +**Create Organizer:** +- **Endpoint:** `hvac_create_organizer` +- **Required:** `organizer_name` +- **Optional:** `organizer_email`, `organizer_website`, `organizer_phone`, `organizer_featured_image` +- **Response:** Created organizer object + +**Create Venue:** +- **Endpoint:** `hvac_create_venue` +- **Required:** `venue_name` +- **Optional:** Address fields, contact info, featured image +- **Response:** Created venue object + +**Create Category:** +- **Endpoint:** `hvac_create_category` +- **Required:** `category_name` +- **Optional:** `category_description` +- **Permissions:** Master Trainers only +- **Response:** Created category object + +### Response Format + +#### Success Response +```json +{ + "success": true, + "data": { + "id": 123, + "title": "Created Item Name", + "subtitle": "Additional information", + "confidence": 85 + } +} +``` + +#### Error Response +```json +{ + "success": false, + "data": { + "message": "Error description", + "code": "error_type", + "field_errors": { + "field_name": "Specific field error" + } + } +} +``` + +--- + +## Security Implementation + +### Authentication & Authorization + +#### WordPress Integration +- **User Authentication:** WordPress session management +- **Capability Checking:** Custom capabilities with role mapping +- **Nonce System:** Action-specific tokens with expiration + +#### HVAC_Ajax_Security Class +```php +class HVAC_Ajax_Security { + const NONCE_GENERAL = 'hvac_general'; + const NONCE_AI = 'hvac_ai'; + + public static function verify_ajax_request($action, $nonce_action, $required_roles, $check_capabilities) { + // Comprehensive security validation + } +} +``` + +### Input Validation + +#### Validation Rules +```php +$input_rules = array( + 'event_title' => array( + 'type' => 'text', + 'required' => true, + 'min_length' => 3, + 'max_length' => 200 + ), + 'event_description' => array( + 'type' => 'html', + 'required' => false, + 'allowed_tags' => 'p,br,strong,em,ul,ol,li,h2,h3,h4,h5,h6' + ) +); +``` + +#### XSS Prevention +- **Output Escaping:** All user content escaped with appropriate functions +- **HTML Filtering:** Allowed tag whitelist with attribute sanitization +- **JavaScript Safety:** JSON data properly escaped for client consumption + +### Rate Limiting + +#### AI Endpoint Protection +- **Rate:** 10 requests per hour per user +- **Storage:** WordPress transients +- **Reset:** Hourly cleanup with WP Cron +- **Error Handling:** Clear rate limit messages + +--- + +## Template System + +### Template Architecture + +#### Template Storage +- **Format:** JSON with metadata +- **Location:** WordPress options table +- **Versioning:** Timestamp-based versioning +- **Backup:** Automatic backup on modification + +#### Template Categories +- **General:** Basic event templates +- **Training:** Technical training sessions +- **Workshop:** Hands-on workshops +- **Certification:** Certification programs +- **Conference:** Large-scale events + +### Template Management + +#### Template Creation +```javascript +// Save current form as template +const templateData = { + name: 'Template Name', + category: 'training', + fields: { + event_title: 'Template Title', + event_description: 'Template Description', + // ... other fields + }, + metadata: { + created_by: userId, + created_date: timestamp, + usage_count: 0 + } +}; +``` + +#### Template Application +- **Field Mapping:** Intelligent field matching +- **Conflict Resolution:** User confirmation for overrides +- **Partial Application:** Selective field application +- **Confidence Scoring:** Template fit analysis + +--- + +## Integration Points + +### The Events Calendar (TEC) + +#### Post Type Integration +- **Events:** `tribe_events` post type +- **Venues:** `tribe_venue` post type +- **Organizers:** `tribe_organizer` post type +- **Categories:** `tribe_events_cat` taxonomy + +#### Meta Field Mapping +```php +// TEC meta field integration +$tec_meta = array( + '_EventStartDate' => $start_datetime, + '_EventEndDate' => $end_datetime, + '_EventTimezone' => $timezone, + '_EventVenueID' => $venue_id, + '_EventOrganizerID' => $organizer_ids, + '_EventCost' => $event_cost, + '_EventCapacity' => $event_capacity +); +``` + +### WordPress Core + +#### Media Library +- **Featured Images:** Post thumbnail system +- **File Handling:** WordPress upload system +- **Security:** File type validation + +#### User Management +- **Roles:** Custom HVAC roles +- **Capabilities:** Fine-grained permissions +- **Session Handling:** WordPress authentication + +#### Taxonomy System +- **Categories:** Native WordPress taxonomy +- **Hierarchical:** Support for nested categories +- **Meta:** Additional category metadata + +--- + +## Performance Considerations + +### Frontend Optimization + +#### JavaScript Loading +- **Conditional Loading:** Scripts only on event creation page +- **Dependency Management:** Proper WordPress enqueueing +- **Minification:** Production asset minification +- **Caching:** Browser caching headers + +#### AJAX Optimization +- **Request Debouncing:** Reduced server requests +- **Response Caching:** Client-side result caching +- **Pagination:** Large result set pagination +- **Compression:** Gzip response compression + +### Backend Optimization + +#### Database Queries +- **Prepared Statements:** SQL injection prevention +- **Query Optimization:** Efficient database queries +- **Indexing:** Proper database indexing +- **Caching:** WordPress object caching + +#### Memory Management +- **Object Lifecycle:** Proper object destruction +- **Image Processing:** Optimized image handling +- **Garbage Collection:** PHP memory management + +--- + +## Troubleshooting Guide + +### Common Issues + +#### AI Assistant Not Working +**Symptoms:** AI requests fail or timeout +**Causes:** +- API rate limiting exceeded +- Network connectivity issues +- Invalid input format +**Solutions:** +1. Check rate limit status +2. Verify network connectivity +3. Validate input format +4. Check error logs + +#### Search Not Returning Results +**Symptoms:** Empty search results despite existing data +**Causes:** +- Insufficient search term length +- Database connectivity issues +- Permission problems +**Solutions:** +1. Ensure 2+ character search terms +2. Verify database connection +3. Check user permissions +4. Clear search cache + +#### Modal Forms Not Opening +**Symptoms:** "Add New" buttons not working +**Causes:** +- JavaScript errors +- Permission restrictions +- Missing dependencies +**Solutions:** +1. Check browser console for errors +2. Verify user role permissions +3. Ensure WordPress media scripts loaded +4. Clear browser cache + +### Error Logging + +#### WordPress Debug Integration +```php +// Enable debug logging +define('WP_DEBUG', true); +define('WP_DEBUG_LOG', true); + +// Log custom events +error_log('HVAC Event Creation: ' . $message); +``` + +#### Custom Error Tracking +- **Error Categorization:** System, user, validation errors +- **Context Capture:** User, action, environment data +- **Notification System:** Admin notifications for critical errors + +### Performance Monitoring + +#### Key Metrics +- **Page Load Time:** Target < 2 seconds +- **AJAX Response Time:** Target < 500ms +- **Database Queries:** Monitor N+1 queries +- **Memory Usage:** Monitor PHP memory consumption + +#### Monitoring Tools +- **WordPress Debug Bar:** Development debugging +- **Query Monitor:** Database query analysis +- **Server Monitoring:** Application performance monitoring + +--- + +## Conclusion + +The HVAC Community Events plugin provides a comprehensive, secure, and user-friendly event creation system. This documentation serves as the authoritative reference for developers, administrators, and users working with the system. + +For additional support or feature requests, please refer to the project repository or contact the development team. + +--- + +**Document Version:** 1.0 +**Next Review:** July 2025 +**Maintained By:** HVAC Development Team \ No newline at end of file diff --git a/includes/class-hvac-ajax-handlers.php b/includes/class-hvac-ajax-handlers.php index fa3caa2d..2e4f76e9 100644 --- a/includes/class-hvac-ajax-handlers.php +++ b/includes/class-hvac-ajax-handlers.php @@ -1287,7 +1287,7 @@ class HVAC_Ajax_Handlers { $security_check = HVAC_Ajax_Security::verify_ajax_request( 'create_organizer', HVAC_Ajax_Security::NONCE_GENERAL, - array('hvac_trainer', 'hvac_master_trainer'), + array('administrator', 'hvac_trainer', 'hvac_master_trainer'), false ); @@ -1319,6 +1319,10 @@ class HVAC_Ajax_Handlers { 'type' => 'text', 'required' => false, 'max_length' => 20 + ), + 'organizer_featured_image' => array( + 'type' => 'text', + 'required' => false ) ); @@ -1361,6 +1365,14 @@ class HVAC_Ajax_Handlers { update_post_meta($organizer_id, '_OrganizerPhone', $params['organizer_phone']); } + // Set featured image if provided + if (!empty($params['organizer_featured_image'])) { + $image_id = absint($params['organizer_featured_image']); + if ($image_id && wp_attachment_is_image($image_id)) { + set_post_thumbnail($organizer_id, $image_id); + } + } + // Return created organizer data wp_send_json_success(array( 'id' => $organizer_id, @@ -1456,7 +1468,7 @@ class HVAC_Ajax_Handlers { $security_check = HVAC_Ajax_Security::verify_ajax_request( 'create_venue', HVAC_Ajax_Security::NONCE_GENERAL, - array('hvac_trainer', 'hvac_master_trainer'), + array('administrator', 'hvac_trainer', 'hvac_master_trainer'), false ); @@ -1509,6 +1521,10 @@ class HVAC_Ajax_Handlers { 'type' => 'text', 'required' => false, 'max_length' => 20 + ), + 'venue_featured_image' => array( + 'type' => 'text', + 'required' => false ) ); @@ -1557,6 +1573,14 @@ class HVAC_Ajax_Handlers { } } + // Set featured image if provided + if (!empty($params['venue_featured_image'])) { + $image_id = absint($params['venue_featured_image']); + if ($image_id && wp_attachment_is_image($image_id)) { + set_post_thumbnail($venue_id, $image_id); + } + } + // Build subtitle for display $subtitle_parts = array_filter(array( $params['venue_address'], diff --git a/includes/class-hvac-event-form-builder.php b/includes/class-hvac-event-form-builder.php index 2ce851cb..a6ad93ba 100644 --- a/includes/class-hvac-event-form-builder.php +++ b/includes/class-hvac-event-form-builder.php @@ -172,6 +172,9 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { // Basic event fields $this->add_basic_event_fields(); + // Featured image field + $this->add_featured_image_field(); + /** * Action hook for TEC ticketing integration * @@ -323,6 +326,23 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { return $this; } + /** + * Add featured image field for event + */ + public function add_featured_image_field(): self { + $featured_image_field = [ + 'type' => 'custom', + 'name' => 'event_featured_image', + 'label' => 'Featured Image', + 'custom_html' => $this->render_media_upload_field('event_featured_image', 'Select Event Image'), + 'wrapper_class' => 'form-row featured-image-field' + ]; + + $this->add_field($featured_image_field); + + return $this; + } + /** * Add datetime fields for event scheduling */ @@ -1475,7 +1495,9 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { */ private function render_searchable_organizer_selector(): string { $current_user = wp_get_current_user(); - $can_create = in_array('hvac_trainer', $current_user->roles) || in_array('hvac_master_trainer', $current_user->roles); + $can_create = in_array('administrator', $current_user->roles) || + in_array('hvac_trainer', $current_user->roles) || + in_array('hvac_master_trainer', $current_user->roles); return << @@ -1569,7 +1591,9 @@ HTML; */ private function render_searchable_venue_selector(): string { $current_user = wp_get_current_user(); - $can_create = in_array('hvac_trainer', $current_user->roles) || in_array('hvac_master_trainer', $current_user->roles); + $can_create = in_array('administrator', $current_user->roles) || + in_array('hvac_trainer', $current_user->roles) || + in_array('hvac_master_trainer', $current_user->roles); return << @@ -1710,4 +1734,111 @@ HTML; +
+
+ +
+
+ + + +
+

+ Recommended size: 1200x630 pixels for optimal display across devices. +

+
+ + +