diff --git a/assets/css/hvac-tec-tickets.css b/assets/css/hvac-tec-tickets.css new file mode 100644 index 00000000..2a66b4b3 --- /dev/null +++ b/assets/css/hvac-tec-tickets.css @@ -0,0 +1,186 @@ +/* + * HVAC TEC Tickets CSS + * Styling for event ticketing and registration forms + */ + +/* ===== RESPONSIVE FIELD GROUPING ===== */ +.form-row-group { + display: flex; + gap: 20px; + width: 100%; + margin-bottom: 15px; +} + +.form-row-half { + flex: 1; + min-width: 0; +} + +.datetime-group .form-row-half, +.price-capacity-group .form-row-half, +.sales-dates-group .form-row-half { + display: flex; + flex-direction: column; +} + +@media (max-width: 768px) { + .form-row-group { + flex-direction: column; + gap: 15px; + } + .form-row-half { + width: 100%; + } +} + +/* ===== TOGGLE SWITCHES ===== */ +.toggle-field-wrapper { + display: flex; + align-items: flex-start; + gap: 12px; + margin-bottom: 20px; + padding: 15px; + background: #f8f9fa; + border-radius: 6px; + border: 1px solid #e9ecef; +} + +.toggle-switch { + position: relative; + display: inline-block; + width: 50px; + height: 24px; + flex-shrink: 0; +} + +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; +} + +.toggle-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + transition: 0.3s; + border-radius: 24px; +} + +.toggle-slider:before { + position: absolute; + content: ""; + height: 18px; + width: 18px; + left: 3px; + bottom: 3px; + background-color: white; + transition: 0.3s; + border-radius: 50%; +} + +.toggle-switch input:checked + .toggle-slider { + background-color: #007cba; +} + +.toggle-switch input:checked + .toggle-slider:before { + transform: translateX(26px); +} + +.toggle-label { + flex: 1; +} + +.toggle-label strong { + display: block; + margin-bottom: 4px; + color: #333; +} + +.toggle-description { + margin: 0; + color: #666; + font-size: 14px; + line-height: 1.4; +} + +/* ===== FORM SECTIONS ===== */ +.form-section { + border: 1px solid #e0e0e0; + padding: 20px; + margin-top: 20px; + background: #f8f8f8; + border-radius: 4px; +} + +.registration-type-selection { + background: white; + padding: 15px; + border: 1px solid #ddd; + border-radius: 4px; + margin-bottom: 20px; +} + +.rsvp-container { + background: white; + padding: 15px; + border: 1px solid #ddd; + border-radius: 4px; + margin-top: 15px; +} + +.tickets-container { + border: 1px solid #ddd; + padding: 20px; + margin-top: 20px; + background: #f9f9f9; +} + +.tickets-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +} + +.ticket-subform { + background: white; + border: 1px solid #ddd; + padding: 15px; + margin-bottom: 15px; + border-radius: 4px; +} + +.ticket-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; + border-bottom: 1px solid #eee; + padding-bottom: 10px; +} + +.attendee-fields-config { + display: flex; + gap: 30px; + margin-top: 15px; +} + +.field-checkbox { + display: block; + margin-bottom: 8px; +} + +.advanced-ticket-options { + margin-top: 15px; +} + +.advanced-ticket-options summary { + cursor: pointer; + font-weight: 600; + margin-bottom: 15px; +} \ No newline at end of file diff --git a/assets/js/hvac-community-events.js b/assets/js/hvac-community-events.js index dad0763e..64503121 100644 --- a/assets/js/hvac-community-events.js +++ b/assets/js/hvac-community-events.js @@ -7,6 +7,11 @@ (function($) { 'use strict'; + // WORDPRESS COMPATIBILITY: Ensure jQuery is available in noConflict mode + if (typeof $ === 'undefined' && typeof jQuery !== 'undefined') { + $ = jQuery; + } + // Wait for DOM ready $(document).ready(function() { @@ -59,7 +64,33 @@ } }); }); - + + // Initialize advanced fields as hidden + $('.advanced-field').hide(); + }); + // Global functions for form functionality + window.hvacToggleAdvancedOptions = function() { + // WORDPRESS COMPATIBILITY: Use jQuery instead of $ due to noConflict mode + const button = jQuery('.toggle-advanced-options'); + const icon = button.find('.toggle-icon'); + const text = button.find('.toggle-text'); + const advancedFields = jQuery('.advanced-field'); + + // Toggle visibility of advanced fields + advancedFields.slideToggle(300); + + // Toggle button state + if (advancedFields.is(':visible')) { + icon.removeClass('dashicons-arrow-down-alt2').addClass('dashicons-arrow-up-alt2'); + text.text('Hide Advanced Options'); + button.addClass('expanded'); + } else { + icon.removeClass('dashicons-arrow-up-alt2').addClass('dashicons-arrow-down-alt2'); + text.text('Show Advanced Options'); + button.removeClass('expanded'); + } + }; + })(jQuery); \ No newline at end of file diff --git a/includes/class-hvac-event-form-builder.php b/includes/class-hvac-event-form-builder.php index dac85c36..2e5b51f7 100644 --- a/includes/class-hvac-event-form-builder.php +++ b/includes/class-hvac-event-form-builder.php @@ -196,6 +196,9 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { $this->add_organizer_fields(); } + // Add categories field - new feature for enhanced categorization + $this->add_categories_fields(); + if ($config['include_capacity_fields']) { $this->add_capacity_field(); } @@ -304,8 +307,49 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { 'required' => true, ]); - // Event description - $description_field = array_merge($this->event_field_defaults['event-description'], [ + // Event description with rich text editor + $description_field = [ + 'type' => 'custom', + 'name' => 'event_description', + 'custom_html' => '
+ +
+
+
+ + + +
+
+ + +
+
+ + +
+
+
+ +
+ Use the toolbar above to format your event description. Character limit: 5000 +
', + 'wrapper_class' => 'form-row event-description-field' + ]; + + // Original description field for fallback + $description_field_fallback = array_merge($this->event_field_defaults['event-description'], [ 'name' => 'event_description', 'label' => 'Event Description', 'placeholder' => 'Describe your event...', @@ -322,12 +366,20 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { * Add datetime fields for event scheduling */ public function add_datetime_fields(): self { + // DateTime section grouping - same row on desktop, columns on mobile + $this->add_field([ + 'type' => 'custom', + 'name' => 'datetime_row_group', + 'custom_html' => '
', + 'wrapper_class' => '' + ]); + // Start date/time $start_datetime_field = array_merge($this->event_field_defaults['datetime-local'], [ 'name' => 'event_start_datetime', 'label' => 'Start Date & Time', 'required' => true, - 'wrapper_class' => 'form-row datetime-row start-datetime', + 'wrapper_class' => 'form-row-half datetime-field start-datetime', ]); // End date/time @@ -335,7 +387,7 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { 'name' => 'event_end_datetime', 'label' => 'End Date & Time', 'required' => true, - 'wrapper_class' => 'form-row datetime-row end-datetime', + 'wrapper_class' => 'form-row-half datetime-field end-datetime', ]); // Timezone @@ -351,6 +403,15 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { $this->add_field($start_datetime_field); $this->add_field($end_datetime_field); + + // Close the datetime row group + $this->add_field([ + 'type' => 'custom', + 'name' => 'datetime_row_group_end', + 'custom_html' => '
', + 'wrapper_class' => '' + ]); + $this->add_field($timezone_field); return $this; @@ -360,15 +421,13 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { * Add venue selection and management fields */ public function add_venue_fields(): self { - // Get venue options with caching - $venue_options = $this->get_venue_options(); - + // Simplified venue selector using regular select field $venue_field = array_merge($this->event_field_defaults['venue-select'], [ 'name' => 'event_venue', 'label' => 'Venue', - 'options' => $venue_options, - 'description' => 'Select an existing venue or create a new one', - 'wrapper_class' => 'form-row venue-row', + 'options' => $this->get_venue_options(), + 'wrapper_class' => 'form-row venue-field', + 'description' => 'Select an existing venue or create a new one' ]); $this->add_field($venue_field); @@ -383,15 +442,13 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { * Add organizer selection and management fields */ public function add_organizer_fields(): self { - // Get organizer options with caching - $organizer_options = $this->get_organizer_options(); - + // Simplified organizer selector using regular select field $organizer_field = array_merge($this->event_field_defaults['organizer-select'], [ 'name' => 'event_organizer', 'label' => 'Organizer', - 'options' => $organizer_options, - 'description' => 'Select an existing organizer or create a new one', - 'wrapper_class' => 'form-row organizer-row', + 'options' => $this->get_organizer_options(), + 'wrapper_class' => 'form-row organizer-field', + 'description' => 'Select an existing organizer or create a new one' ]); $this->add_field($organizer_field); @@ -402,6 +459,53 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { return $this; } + /** + * Add categories field with multi-select search functionality + */ + public function add_categories_fields(): self { + // Get event categories from TEC taxonomy + $category_options = ['0' => '-- Select Category --']; + + // Get TEC event categories + $categories = get_terms([ + 'taxonomy' => 'tribe_events_cat', + 'hide_empty' => false, + 'orderby' => 'name', + 'order' => 'ASC' + ]); + + if (!is_wp_error($categories) && !empty($categories)) { + foreach ($categories as $category) { + $category_options[$category->term_id] = $category->name; + } + } + + // Add default categories if none exist + if (count($category_options) === 1) { + $category_options['general'] = 'General'; + $category_options['training'] = 'Training'; + $category_options['workshop'] = 'Workshop'; + $category_options['certification'] = 'Certification'; + } + + // Simplified categories selector using regular select field + $categories_field = [ + 'type' => 'select', + 'name' => 'event_categories', + 'label' => 'Category', + 'options' => $category_options, + 'wrapper_class' => 'form-row categories-field', + 'description' => 'Select an event category', + 'class' => 'hvac-categories-select', + 'validate' => [], + 'sanitize' => 'int', + ]; + + $this->add_field($categories_field); + + return $this; + } + /** * Add capacity field */ @@ -458,16 +562,6 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { $this->add_field($save_template_field); - // Add save template dialog - $save_dialog_field = [ - 'type' => 'custom', - 'name' => 'save_template_dialog', - 'custom_html' => $this->render_save_template_dialog(), - 'wrapper_class' => 'form-row template-dialog-row', - ]; - - $this->add_field($save_dialog_field); - return $this; } @@ -1010,44 +1104,6 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { - template_mode_enabled): ?> - - - render_button($field); } + // Handle custom HTML fields (venue, organizer, categories, etc.) + if ($field['type'] === 'custom') { + return $this->render_custom_field($field); + } + // Use parent implementation for standard fields return parent::render_field($field); } @@ -1155,6 +1216,32 @@ class HVAC_Event_Form_Builder extends HVAC_Form_Builder { return $output; } + /** + * Render custom HTML field + * + * @param array $field Field configuration + * @return string Rendered field HTML + */ + private function render_custom_field($field): string { + // Custom fields already contain their own wrapper div and labels + // Just return the custom HTML directly + if (isset($field['custom_html'])) { + return $field['custom_html']; + } + + // Fallback for custom fields without custom_html + $output = sprintf('
', esc_attr($field['wrapper_class'] ?? 'form-row')); + + if (isset($field['label'])) { + $output .= sprintf('', esc_html($field['label'])); + } + + $output .= sprintf('

Custom field "%s" missing custom_html

', esc_html($field['name'])); + $output .= '
'; + + return $output; + } + /** * Enqueue template-related assets */ diff --git a/includes/class-hvac-plugin.php b/includes/class-hvac-plugin.php index c545f69c..11d054b9 100644 --- a/includes/class-hvac-plugin.php +++ b/includes/class-hvac-plugin.php @@ -112,7 +112,7 @@ final class HVAC_Plugin { */ private function defineConstants(): void { if (!defined('HVAC_PLUGIN_VERSION')) { - define('HVAC_PLUGIN_VERSION', '2.0.0'); + define('HVAC_PLUGIN_VERSION', '2.0.1'); } if (!defined('HVAC_VERSION')) { define('HVAC_VERSION', '2.0.0'); @@ -216,6 +216,8 @@ final class HVAC_Plugin { // AJAX optimization system (Phase 1D - Performance Optimization) require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-ajax-optimizer.php'; + // AI Event Population System (Phase 3.2 - AI-Assisted Form Population) + require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-ai-event-populator.php'; // Unified Event Management System (replaces 8+ fragmented implementations) require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-event-manager.php'; diff --git a/includes/class-hvac-scripts-styles.php b/includes/class-hvac-scripts-styles.php index c5927c37..50e6c8c3 100644 --- a/includes/class-hvac-scripts-styles.php +++ b/includes/class-hvac-scripts-styles.php @@ -77,27 +77,34 @@ class HVAC_Scripts_Styles { if (defined('HVAC_FORCE_LEGACY_SCRIPTS') && HVAC_FORCE_LEGACY_SCRIPTS) { return true; } - + // Use legacy in development by default if (defined('WP_DEBUG') && WP_DEBUG && (!defined('HVAC_USE_BUNDLES') || !HVAC_USE_BUNDLES)) { return true; } - + + // CROSS-BROWSER FIX: Always use legacy scripts for consistent JavaScript loading + // This ensures hvacToggleAdvancedOptions and other functions work in all browsers + // Previously only loaded for Safari, causing function undefined errors in Chrome/Firefox + return true; + + // DISABLED: Safari-only loading restriction // Use legacy for Safari browsers for compatibility - if (class_exists('HVAC_Browser_Detection')) { - $browser_detection = HVAC_Browser_Detection::instance(); - if ($browser_detection->is_safari_browser()) { - return true; - } - } - + // if (class_exists('HVAC_Browser_Detection')) { + // $browser_detection = HVAC_Browser_Detection::instance(); + // if ($browser_detection->is_safari_browser()) { + // return true; + // } + // } + + // DISABLED: Bundled assets fallback // Check if bundled assets class is using legacy fallback - if (class_exists('HVAC_Bundled_Assets')) { - // If bundled assets are not being used, use legacy - return true; - } - - return false; + // if (class_exists('HVAC_Bundled_Assets')) { + // // If bundled assets are not being used, use legacy + // return true; + // } + + // DISABLED: return false; } /**