import { __ } from "@wordpress/i18n"; jQuery(document).ready(function($) { function getScoreColorClass(score) { if (score >= 80) return 'green'; if (score >= 50) return 'yellow'; if (score >= 30) return 'orange'; return 'red'; } function getScoreStatusText(score) { if (score >= 80) return __('Excellent', 'betterdocs'); if (score >= 60) return __('Good', 'betterdocs'); if (score >= 40) return __('Needs Improvement', 'betterdocs'); return __('Poor', 'betterdocs'); } function showResults(container, data) { const $container = $(container); const $results = $container.find('.quality-results'); const $empty = $container.find('.quality-empty'); // Hide empty state, show results $empty.hide(); $results.show(); // Handle nested data structure (response.data.data) const analysisData = data.data || data; // Build results HTML const score = analysisData.overall_score || 0; const scores = analysisData.scores || {}; const feedback = analysisData.feedback || {}; const strengths = feedback.strengths || []; const improvements = feedback.improvements || []; const suggestions = feedback.suggestions || []; let resultsHTML = ''; // Results header with regenerate button resultsHTML += '
'; resultsHTML += '

' + __('Docs quality analysis results', 'betterdocs') + '

'; resultsHTML += ''; resultsHTML += '
'; // Calculate circular progress const scoreColor = getScoreColorClass(score); const circumference = 2 * Math.PI * 54; // radius = 54 const offset = circumference - (score / 100) * circumference; // Start two-column layout resultsHTML += '
'; // Left Column: Circular Progress Score resultsHTML += '
'; resultsHTML += '

' + __('Overall Score', 'betterdocs') + '

'; resultsHTML += '
'; resultsHTML += ''; resultsHTML += ''; resultsHTML += ''; resultsHTML += ''; resultsHTML += '
'; resultsHTML += '' + score + ''; resultsHTML += '' + __('out of 100', 'betterdocs') + ''; resultsHTML += '
'; resultsHTML += '
'; resultsHTML += '
' + getScoreStatusText(score) + '
'; resultsHTML += '

' + __('This score is a weighted average of clarity, relevance, structure, and other quality factors.', 'betterdocs') + '

'; resultsHTML += '
'; // Right Column: Details (Score Breakdown) resultsHTML += '
'; if (Object.keys(scores).length > 0) { resultsHTML += '
'; resultsHTML += '

' + __('Score Breakdown', 'betterdocs') + '

'; resultsHTML += '
'; Object.keys(scores).forEach(function(criterion) { const criterionScore = scores[criterion]; resultsHTML += '
'; resultsHTML += '
'; resultsHTML += '' + criterion.charAt(0).toUpperCase() + criterion.slice(1) + ''; resultsHTML += '' + criterionScore + '%'; resultsHTML += '
'; resultsHTML += '
'; resultsHTML += '
'; resultsHTML += '
'; resultsHTML += '
'; resultsHTML += '
'; resultsHTML += '
'; }); resultsHTML += '
'; resultsHTML += '
'; } resultsHTML += '
'; // Close details-column resultsHTML += '
'; // Close quality-results-body // Gather all suggestions for "Actionable Insights" section const allSuggestions = []; if (strengths.length > 0) allSuggestions.push(...strengths); if (improvements.length > 0) allSuggestions.push(...improvements); if (suggestions.length > 0) allSuggestions.push(...suggestions); if (allSuggestions.length > 0) { resultsHTML += '
'; resultsHTML += '

' + __('Actionable Insights', 'betterdocs') + '

'; resultsHTML += '
'; allSuggestions.forEach(function(suggestion) { resultsHTML += '
'; resultsHTML += '
'; resultsHTML += ''; resultsHTML += ''; resultsHTML += ''; resultsHTML += ''; resultsHTML += '
'; resultsHTML += '' + suggestion + ''; resultsHTML += '
'; }); resultsHTML += '
'; resultsHTML += '
'; } $results.html(resultsHTML); } function showLoading(container) { const $container = $(container); $container.find('.quality-empty').hide(); $container.find('.quality-results').hide(); $container.find('.quality-error').hide(); $container.find('.quality-loading').show(); } function hideLoading(container) { const $container = $(container); $container.find('.quality-loading').hide(); } function showError(container, errorData) { const $container = $(container); hideLoading(container); // Extract error message from various response formats let message = ''; let isConfigError = false; if (typeof errorData === 'string') { message = errorData; } else if (errorData && typeof errorData === 'object') { // Handle WP_Error format or standard error response if (errorData.message) { message = errorData.message; } else if (errorData.data && errorData.data.message) { message = errorData.data.message; } else { message = __('An unexpected error occurred. Please try again.', 'betterdocs'); } } else { message = __('Analysis failed. Please try again.', 'betterdocs'); } // Check if this is an API key configuration error if (message.toLowerCase().includes('api key') || message.toLowerCase().includes('not configured')) { isConfigError = true; message = __('AI API key is not configured. Please configure your API key in the settings to use this feature.', 'betterdocs'); // Hide the analyze button and show error in empty state $container.find('.betterdocs-analyze-btn').hide(); $container.find('.quality-empty').show(); // Show configuration error UI elements $container.find('.quality-error').find('.error-icon').show(); $container.find('.quality-error').find('strong').show(); $container.find('.quality-error').find('.error-action-button').show(); // Add configuration error class, remove content error class $container.find('.quality-error').removeClass('error-content-validation').addClass('error-config'); } else { // For content errors (empty, too short, etc.) // Hide configuration-specific UI elements $container.find('.quality-error').find('.error-icon').hide(); $container.find('.quality-error').find('strong').hide(); $container.find('.quality-error').find('.error-action-button').hide(); // Keep the analyze button visible for content errors $container.find('.betterdocs-analyze-btn').show(); $container.find('.quality-empty').show(); // Add content error class, remove configuration error class $container.find('.quality-error').removeClass('error-config').addClass('error-content-validation'); } $container.find('.quality-error').find('.error-message').text(message); $container.find('.quality-error').show(); } // Analyze button click handler $(document).on('click', '#betterdocs-analyze-quality', function(e) { e.preventDefault(); const $button = $(this); const $container = $button.closest('.betterdocs-quality-analysis-content'); const postId = $container.data('post-id'); if (!postId) { alert(__('Please save the post first.', 'betterdocs')); return; } // Get current editor content (handles both Classic and Gutenberg editors) let currentContent = ''; let currentTitle = ''; // Try to get Gutenberg editor content if (typeof wp !== 'undefined' && wp.data && wp.data.select('core/editor')) { const editor = wp.data.select('core/editor'); currentContent = editor.getEditedPostContent(); currentTitle = editor.getEditedPostAttribute('title'); } // Fallback to Classic Editor else if (typeof tinymce !== 'undefined' && tinymce.get('content')) { currentContent = tinymce.get('content').getContent(); currentTitle = $('#title').val() || ''; } // Fallback to textarea (if visual editor is disabled) else if ($('#content').length) { currentContent = $('#content').val(); currentTitle = $('#title').val() || ''; } // Show loading state $button.prop('disabled', true); showLoading($container); // Prepare AJAX data const ajaxData = { action: 'betterdocs_analyze_quality', post_id: postId, nonce: betterdocsQualityScore.nonce }; // Add current content if available if (currentContent) { ajaxData.current_content = currentContent; ajaxData.current_title = currentTitle; } // Run analysis $.ajax({ url: betterdocsQualityScore.ajax_url, type: 'POST', data: ajaxData, success: function(response) { if (response.success) { hideLoading($container); showResults($container, response.data); } else { showError($container, response.data || response); } }, error: function() { showError($container, __('Network error. Please try again.', 'betterdocs')); }, complete: function() { $button.prop('disabled', false); } }); }); // Regenerate button click handler $(document).on('click', '#betterdocs-regenerate-quality', function(e) { e.preventDefault(); const $button = $(this); const $container = $button.closest('.betterdocs-quality-analysis-content'); const postId = $container.data('post-id'); if (!postId) { alert(__('Please save the post first.', 'betterdocs')); return; } // Get current editor content (handles both Classic and Gutenberg editors) let currentContent = ''; let currentTitle = ''; // Try to get Gutenberg editor content if (typeof wp !== 'undefined' && wp.data && wp.data.select('core/editor')) { const editor = wp.data.select('core/editor'); currentContent = editor.getEditedPostContent(); currentTitle = editor.getEditedPostAttribute('title'); } // Fallback to Classic Editor else if (typeof tinymce !== 'undefined' && tinymce.get('content')) { currentContent = tinymce.get('content').getContent(); currentTitle = $('#title').val() || ''; } // Fallback to textarea (if visual editor is disabled) else if ($('#content').length) { currentContent = $('#content').val(); currentTitle = $('#title').val() || ''; } // Show loading state $button.prop('disabled', true); showLoading($container); // Prepare AJAX data const ajaxData = { action: 'betterdocs_analyze_quality', post_id: postId, nonce: betterdocsQualityScore.nonce }; // Add current content if available if (currentContent) { ajaxData.current_content = currentContent; ajaxData.current_title = currentTitle; } // Run analysis $.ajax({ url: betterdocsQualityScore.ajax_url, type: 'POST', data: ajaxData, success: function(response) { if (response.success) { hideLoading($container); showResults($container, response.data); } else { showError($container, response.data || response); } }, error: function() { showError($container, __('Network error. Please try again.', 'betterdocs')); }, complete: function() { $button.prop('disabled', false); } }); }); });