/** * Media Triage Admin UI * AI-powered media inquiry triage with human oversight */ // Auth check const token = localStorage.getItem('admin_token'); const user = JSON.parse(localStorage.getItem('admin_user') || '{}'); if (!token) { window.location.href = '/admin/login.html'; } // Display admin name document.getElementById('admin-name').textContent = user.email || 'Admin'; // Logout document.getElementById('logout-btn').addEventListener('click', () => { localStorage.removeItem('admin_token'); localStorage.removeItem('admin_user'); window.location.href = '/admin/login.html'; }); /** * API request helper with automatic auth header injection */ async function apiRequest(endpoint, options = {}) { const response = await fetch(endpoint, { ...options, headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', ...options.headers } }); if (response.status === 401) { localStorage.removeItem('admin_token'); window.location.href = '/admin/login.html'; return; } return response.json(); } // State management let inquiries = []; let currentInquiry = null; let filters = { status: 'new', urgency: '', values: '', sortBy: 'received_at' }; /** * Load and display dashboard statistics */ async function loadStatistics() { try { const response = await apiRequest('/api/media/inquiries'); if (!response.success) { console.error('Invalid stats response:', response); return; } const allInquiries = response.inquiries || []; // Calculate statistics const newInquiries = allInquiries.filter(i => !i.ai_triage); const triaged = allInquiries.filter(i => i.ai_triage && i.status === 'pending'); const responded = allInquiries.filter(i => i.status === 'responded'); const valuesInvolved = allInquiries.filter(i => i.ai_triage?.involves_values); document.getElementById('stat-total').textContent = allInquiries.length; document.getElementById('stat-new').textContent = newInquiries.length; document.getElementById('stat-triaged').textContent = triaged.length; document.getElementById('stat-values').textContent = valuesInvolved.length; document.getElementById('stat-responded').textContent = responded.length; } catch (error) { console.error('Failed to load statistics:', error); showToast('Failed to load statistics', 'error'); } } /** * Load and render inquiries based on current filters */ async function loadInquiries() { const container = document.getElementById('inquiries-container'); try { // Show loading state container.innerHTML = `
Loading media inquiries...
Try adjusting your filters.
Failed to load inquiries. Please try again.
From: ${escapeHtml(inquiry.contact.name)} (${escapeHtml(inquiry.contact.outlet)})
Received: ${receivedDate} at ${receivedTime}
${escapeHtml(inquiry.inquiry.message)}
AI Triage Analysis
⚠️ BoundaryEnforcer: ${escapeHtml(inquiry.ai_triage.boundary_enforcement)}
${escapeHtml(currentInquiry.inquiry.subject)}
${escapeHtml(currentInquiry.inquiry.message)}
${new Date(currentInquiry.inquiry.deadline).toLocaleString()}
${currentInquiry.inquiry.topic_areas.map(t => escapeHtml(t)).join(', ')}
Urgency: ${currentInquiry.ai_triage.urgency.toUpperCase()} (Score: ${currentInquiry.ai_triage.urgency_score}/100)
${escapeHtml(currentInquiry.ai_triage.urgency_reasoning)}
Topic Sensitivity: ${currentInquiry.ai_triage.topic_sensitivity.toUpperCase()}
${escapeHtml(currentInquiry.ai_triage.sensitivity_reasoning)}
${currentInquiry.ai_triage.involves_values ? '⚠️ ' : '✓ '}Values Involvement: ${currentInquiry.ai_triage.involves_values ? 'YES' : 'NO'}
${escapeHtml(currentInquiry.ai_triage.values_reasoning)}
${escapeHtml(currentInquiry.ai_triage.boundary_enforcement)}
Suggested Talking Points:
AI-Generated Draft Response (Human Review Required):
${escapeHtml(currentInquiry.ai_triage.draft_response)}
${escapeHtml(currentInquiry.ai_triage.draft_response_reasoning)}
Framework Compliance: BoundaryEnforcer: ${currentInquiry.ai_triage.framework_compliance?.boundary_enforcer_checked ? '✓' : '✗'} | Human Approval Required: ${currentInquiry.ai_triage.framework_compliance?.human_approval_required ? '✓' : '✗'} | Reasoning Transparent: ${currentInquiry.ai_triage.framework_compliance?.reasoning_transparent ? '✓' : '✗'}
AI Model: ${currentInquiry.ai_triage.ai_model} | Triaged: ${new Date(currentInquiry.ai_triage.triaged_at).toLocaleString()}
${cultural.risk_level === 'HIGH' ? '⚠️ ' : cultural.risk_level === 'MEDIUM' ? '⚡ ' : '✓ '}Risk Level: ${cultural.risk_level}
Recommended Action: ${cultural.recommended_action}
${cultural.risk_level === 'HIGH' ? `🚨 Human review recommended before sending (inst_081 pluralism)
` : ''}Cultural Concerns (${cultural.concerns.length}):
Suggested Adaptations (${cultural.suggestions.length}):
Framework: PluralisticDeliberationOrchestrator (inst_081) | Checked: ${new Date(cultural.checked_at).toLocaleString()}
Note: AI flags cultural concerns but never blocks. Human decides final approach.
To: ${escapeHtml(currentInquiry.contact.name)} (${escapeHtml(currentInquiry.contact.email)})
Outlet: ${escapeHtml(currentInquiry.contact.outlet)}
Subject: ${escapeHtml(currentInquiry.inquiry.subject)}