/** * Comment & Feedback Analysis * Framework-guided analysis of social media comments and article feedback */ // Get auth token function getAuthToken() { return localStorage.getItem('admin_token'); } // Analyze feedback async function analyzeFeedback() { const source = document.getElementById('feedback-source').value; const relatedPost = document.getElementById('related-post').value.trim(); const content = document.getElementById('feedback-content').value.trim(); const notes = document.getElementById('your-notes').value.trim(); if (!content) { alert('Please enter feedback content'); return; } if (!source) { alert('Please select a source platform'); return; } // Show loading state const analyzeBtn = document.getElementById('analyze-feedback-btn'); analyzeBtn.disabled = true; analyzeBtn.innerHTML = ' Analyzing...'; try { const response = await fetch('/api/admin/feedback/analyze', { method: 'POST', headers: { 'Authorization': `Bearer ${getAuthToken()}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ source, relatedPost, content, notes }) }); const data = await response.json(); if (data.success) { displayResults(data.analysis); } else { alert('Analysis failed: ' + (data.error || 'Unknown error')); } } catch (error) { console.error('Analysis error:', error); alert('Failed to analyze feedback. Please try again.'); } finally { analyzeBtn.disabled = false; analyzeBtn.innerHTML = 'Analyze with Framework'; } } // Display analysis results function displayResults(analysis) { const resultsSection = document.getElementById('results-section'); resultsSection.classList.remove('hidden'); // Sentiment analysis const sentimentEl = document.getElementById('sentiment-result'); sentimentEl.innerHTML = renderSentiment(analysis.sentiment); // Values & concerns const valuesEl = document.getElementById('values-result'); valuesEl.innerHTML = renderValues(analysis.values); // Risk assessment const riskEl = document.getElementById('risk-result'); riskEl.innerHTML = renderRisk(analysis.risk); // Recommended responses const responseEl = document.getElementById('response-options'); responseEl.innerHTML = renderResponses(analysis.responses); // Framework guidance const guidanceEl = document.getElementById('framework-guidance'); guidanceEl.innerHTML = renderGuidance(analysis.guidance); // Setup copy handlers for responses setupResponseCopyHandlers(); // Scroll to results resultsSection.scrollIntoView({ behavior: 'smooth', block: 'start' }); } // Render sentiment analysis function renderSentiment(sentiment) { const sentimentColors = { positive: { bg: 'bg-green-100', text: 'text-green-700', icon: '😊' }, neutral: { bg: 'bg-gray-100', text: 'text-gray-700', icon: '😐' }, negative: { bg: 'bg-red-100', text: 'text-red-700', icon: '😟' }, mixed: { bg: 'bg-yellow-100', text: 'text-yellow-700', icon: '🤔' } }; const colors = sentimentColors[sentiment.overall] || sentimentColors.neutral; let html = `
${risk.summary}
No response recommendations generated
'; } return responses.map((response, index) => { const priorityColors = { high: 'border-red-300 bg-red-50', medium: 'border-yellow-300 bg-yellow-50', low: 'border-gray-300 bg-gray-50' }; const borderColor = priorityColors[response.priority] || priorityColors.low; return `No framework guidance available
'; } // Setup copy handlers for responses (CSP-compliant) function setupResponseCopyHandlers() { document.querySelectorAll('.copy-response-btn').forEach(btn => { btn.addEventListener('click', function(e) { e.stopPropagation(); const card = this.closest('.response-card'); const text = card.querySelector('.response-text').textContent; navigator.clipboard.writeText(text).then(() => { const originalText = this.textContent; this.textContent = 'Copied!'; this.classList.add('text-green-600'); setTimeout(() => { this.textContent = originalText; this.classList.remove('text-green-600'); }, 2000); }); }); }); } // Apply dynamic styles using data attributes (CSP-compliant) function applyDynamicStyles() { document.querySelectorAll('[data-width]').forEach(el => { const width = el.getAttribute('data-width'); el.style.width = width + '%'; }); } // Save analysis async function saveAnalysis() { const source = document.getElementById('feedback-source').value; const relatedPost = document.getElementById('related-post').value.trim(); const content = document.getElementById('feedback-content').value.trim(); const notes = document.getElementById('your-notes').value.trim(); if (!content) { alert('Please enter feedback content before saving'); return; } try { const response = await fetch('/api/admin/feedback/save', { method: 'POST', headers: { 'Authorization': `Bearer ${getAuthToken()}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ source, relatedPost, content, notes }) }); const data = await response.json(); if (data.success) { alert('Analysis saved successfully!'); } else { alert('Failed to save analysis: ' + (data.error || 'Unknown error')); } } catch (error) { console.error('Save error:', error); alert('Failed to save analysis. Please try again.'); } } // Export report async function exportReport() { const source = document.getElementById('feedback-source').value; const relatedPost = document.getElementById('related-post').value.trim(); const content = document.getElementById('feedback-content').value.trim(); if (!content) { alert('Please analyze feedback before exporting'); return; } try { const response = await fetch('/api/admin/feedback/export', { method: 'POST', headers: { 'Authorization': `Bearer ${getAuthToken()}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ source, relatedPost, content }) }); if (response.ok) { const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `feedback-analysis-${Date.now()}.pdf`; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); } else { alert('Failed to export report'); } } catch (error) { console.error('Export error:', error); alert('Failed to export report. Please try again.'); } } // Event listeners document.addEventListener('DOMContentLoaded', () => { document.getElementById('analyze-feedback-btn').addEventListener('click', analyzeFeedback); document.getElementById('save-analysis-btn')?.addEventListener('click', saveAnalysis); document.getElementById('export-report-btn')?.addEventListener('click', exportReport); });