/** * HVAC AI Assist JavaScript * * Handles AI-powered event population modal interface and form integration * * @package HVAC_Community_Events * @since 3.2.0 */ jQuery(document).ready(function($) { 'use strict'; /** * AI Assist functionality object */ const HVACAIAssist = { // Properties modal: null, isProcessing: false, currentInput: '', currentInputType: 'auto', // Initialize init: function() { this.createModal(); this.bindEvents(); this.enableAIButton(); }, /** * Create the AI modal interface */ createModal: function() { const modalHTML = `
`; $('body').append(modalHTML); this.modal = $('#hvac-ai-modal'); }, /** * Bind event handlers */ bindEvents: function() { const self = this; // AI Assist button click $(document).on('click', '#ai-assist-btn', function(e) { e.preventDefault(); if (!$(this).prop('disabled')) { self.openModal(); } }); // Modal close handlers $(document).on('click', '#ai-modal-close, #ai-modal-cancel, .modal-overlay', function() { self.closeModal(); }); // Tab switching $(document).on('click', '.tab-btn', function() { const type = $(this).data('type'); self.switchTab(type); }); // Process button $(document).on('click', '#ai-process-btn', function() { self.processInput(); }); // Apply button $(document).on('click', '#ai-apply-btn', function() { self.applyToForm(); }); // Input change handlers for validation $(document).on('input', '#ai-input-auto, #ai-input-url, #ai-input-text, #ai-input-description', function() { self.validateInput(); }); // ESC key handler $(document).on('keyup', function(e) { if (e.keyCode === 27 && self.modal.is(':visible')) { self.closeModal(); } }); }, /** * Enable the AI Assist button (remove placeholder status) */ enableAIButton: function() { const $aiBtn = $('#ai-assist-btn'); $aiBtn.removeClass('placeholder-btn') .prop('disabled', false) .attr('title', 'AI-powered event creation assistant') .text('AI Assist'); }, /** * Open the AI modal */ openModal: function() { this.modal.fadeIn(300); this.resetModal(); $('#ai-input-auto').focus(); }, /** * Close the AI modal */ closeModal: function() { if (!this.isProcessing) { this.modal.fadeOut(300); this.resetModal(); } }, /** * Reset modal to initial state */ resetModal: function() { // Reset tabs $('.tab-btn').removeClass('active'); $('.tab-btn[data-type="auto"]').addClass('active'); $('.input-tab-content').removeClass('active'); $('.input-tab-content[data-type="auto"]').addClass('active'); // Clear inputs $('#ai-input-auto, #ai-input-url, #ai-input-text, #ai-input-description').val(''); // Hide sections $('#ai-processing, #ai-results').hide(); $('.ai-input-section').show(); // Reset buttons $('#ai-process-btn').show().prop('disabled', true); $('#ai-apply-btn').hide(); // Reset progress steps $('.progress-steps .step').removeClass('active'); $('.status-message').text('Analyzing your input...'); // Reset confidence indicator $('.confidence-fill').css('width', '0%'); $('.confidence-percent').text('0%'); $('.confidence-bar').removeClass('confidence-low confidence-medium confidence-high'); // Clear results content $('.result-fields').html(''); $('.warning-list').html(''); $('.result-warnings').hide(); // Clear stored data this.extractedData = null; // Reset properties this.currentInput = ''; this.currentInputType = 'auto'; this.isProcessing = false; }, /** * Switch input tabs */ switchTab: function(type) { $('.tab-btn').removeClass('active'); $(`.tab-btn[data-type="${type}"]`).addClass('active'); $('.input-tab-content').removeClass('active'); $(`.input-tab-content[data-type="${type}"]`).addClass('active'); this.currentInputType = type; // Focus on the input field $(`#ai-input-${type}`).focus(); this.validateInput(); }, /** * Validate current input */ validateInput: function() { const input = this.getCurrentInput(); const $processBtn = $('#ai-process-btn'); if (input.length >= 10) { $processBtn.prop('disabled', false); } else { $processBtn.prop('disabled', true); } }, /** * Get current input value */ getCurrentInput: function() { const activeTab = $('.input-tab-content.active'); const inputElement = activeTab.find('input, textarea'); return inputElement.val().trim(); }, /** * Process input through AI */ processInput: function() { const input = this.getCurrentInput(); if (input.length < 10) { this.showError('Please provide at least 10 characters of event information.'); return; } this.isProcessing = true; this.currentInput = input; // Show processing UI $('.ai-input-section').hide(); $('#ai-processing').show(); $('#ai-process-btn').hide(); // Start progress animation this.animateProgress(); // Make AJAX request this.makeAIRequest(input, this.currentInputType); }, /** * Animate processing steps */ animateProgress: function() { const isUrl = this.currentInputType === 'url'; const steps = isUrl ? [ { step: 1, message: 'Fetching webpage content...', delay: 500 }, { step: 2, message: 'Processing webpage data (this may take up to 40 seconds)...', delay: 3000 }, { step: 3, message: 'Extracting event details with AI...', delay: 15000 }, { step: 4, message: 'Preparing form data...', delay: 25000 } ] : [ { step: 1, message: 'Analyzing your input...', delay: 500 }, { step: 2, message: 'Extracting event details...', delay: 2000 }, { step: 3, message: 'Validating information...', delay: 4000 }, { step: 4, message: 'Preparing form data...', delay: 6000 } ]; steps.forEach(({ step, message, delay }) => { setTimeout(() => { if (this.isProcessing) { $(`.progress-steps .step[data-step="${step}"]`).addClass('active'); $('.status-message').text(message); } }, delay); }); }, /** * Make AJAX request to AI endpoint */ makeAIRequest: function(input, inputType) { const self = this; const requestData = { action: 'hvac_ai_populate_event', input: input, input_type: inputType, nonce: hvacAjaxVars.nonce // Assuming nonce is available }; $.ajax({ url: hvacAjaxVars.ajaxUrl, type: 'POST', data: requestData, timeout: inputType === 'url' ? 60000 : 50000, // 60 seconds for URLs, 50 for text success: function(response) { self.handleAISuccess(response); }, error: function(xhr, status, error) { self.handleAIError(xhr, status, error); } }); }, /** * Handle successful AI response */ handleAISuccess: function(response) { this.isProcessing = false; if (response.success && response.data && response.data.event_data) { this.displayResults(response.data.event_data); } else { const message = response.data && response.data.message ? response.data.message : 'Unexpected response format from AI service.'; this.showError(message); } }, /** * Handle AI request error */ handleAIError: function(xhr, status, error) { this.isProcessing = false; let message = 'AI service temporarily unavailable. Please try again later.'; if (status === 'timeout') { message = 'Request timed out. The AI might be processing a complex input. Please try with simpler content.'; } else if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) { message = xhr.responseJSON.data.message; } this.showError(message); }, /** * Display AI extraction results */ displayResults: function(eventData) { $('#ai-processing').hide(); $('#ai-results').show(); // Update confidence indicator const confidence = eventData.confidence && eventData.confidence.overall ? eventData.confidence.overall : 0; const confidencePercent = Math.round(confidence * 100); $('.confidence-fill').css('width', confidencePercent + '%'); $('.confidence-percent').text(confidencePercent + '%'); // Color code confidence let confidenceClass = 'confidence-low'; if (confidencePercent >= 80) confidenceClass = 'confidence-high'; else if (confidencePercent >= 60) confidenceClass = 'confidence-medium'; $('.confidence-bar').removeClass('confidence-low confidence-medium confidence-high') .addClass(confidenceClass); // Display extracted fields this.displayExtractedFields(eventData); // Check for warnings this.checkAndDisplayWarnings(eventData); // Show apply button $('#ai-apply-btn').show(); // Store data for form application this.extractedData = eventData; }, /** * Display extracted fields summary */ displayExtractedFields: function(eventData) { const fieldsHtml = []; // Title if (eventData.title) { fieldsHtml.push(`tags const formattedParagraphs = paragraphs.map(p => { if (p.match(/^<(h[1-6]|ul|\/ul|li)/)) { return p; } else { return '
' + p + '
'; } }); const result = formattedParagraphs.join('\n'); if (window.hvacDebugMarkdown) { console.log('Output:', result); } return result; }, /** * Escape HTML for safe display */ escapeHtml: function(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } }; // Initialize when document is ready HVACAIAssist.init(); // Add global test function for debugging window.testMarkdownConversion = function(testMarkdown) { window.hvacDebugMarkdown = true; console.log('=== MARKDOWN CONVERSION TEST ==='); const testInput = testMarkdown || `## Event Overview This is a **bold** text and *italic* text example. #### Key Details * First item in list * Second item in list * Third item in list ### Additional Information Here's a regular paragraph with more details.`; const result = HVACAIAssist.markdownToHtml(testInput); console.log('=== TEST COMPLETE ==='); // Also test setting it to TinyMCE if available if (typeof tinyMCE !== 'undefined' && tinyMCE.get('event_description')) { console.log('Setting test content to TinyMCE...'); tinyMCE.get('event_description').setContent(result); } else { console.log('TinyMCE not available for testing'); } window.hvacDebugMarkdown = false; return result; }; console.log('HVAC AI Assist loaded. Use testMarkdownConversion() to test markdown conversion.'); });