Admin Console Rev 14

RNI Admin Console - Rev 14

Admin Console

System Operations Queue

Azure: Healthy
AI Council: 6/6 Online
GCP: Healthy
Next Maintenance 2:00am
Data Integrity Alerts (2)
Epic HL7 Feed Disconnected
ADT Interface • Down 47 minutes
NOW
C Dr. Chen compliance alert: Patient data sync interrupted, manual reconciliation may be required
HL7 ADT feed from Epic lost connection. 23 admission records pending sync. Risk of duplicate MRNs if not resolved quickly.
Coding Backlog Exceeds SLA
127 Charts • 48-hour turnaround at risk
6h
T Dr. Taylor analytics: Backlog 34% above normal, recommend temporary coder assignment
ICD-10 coding queue backed up due to holiday staffing. Billing cycle at risk. 4 coders currently active, need 6.
Data Quality Tasks (4)
Release of Information Requests
14 Pending • HIPAA 30-day deadline
12 days
Patient records requests from attorneys, insurers, and transfer facilities. Verify authorization forms complete.
Chart Completeness Audit
Q4 Review • 847 records sampled
5 days
Quarterly documentation audit for Joint Commission readiness. Focus: treatment plans, progress notes, discharge summaries.
FHIR Mapping — Wearable Data
Biometric Integration • 45M daily points
Ongoing
Map incoming HRV, sleep, and activity data to FHIR Observation resources. Ensure proper LOINC codes assigned.
ICD-10 2025 Code Update
Annual Update • Effective 10/1/2025
9 months
Review new behavioral health codes for SUD, anxiety, and depression. Update encoder and train coding staff.
Resolved Today (2)
Duplicate MRN Merged
PT-4521 + PT-4523 • Same patient
Resolved
Cerner Query Optimized
Report runtime 45s → 8s
Resolved
HIPAA Privacy Alerts (1)
Unusual PHI Access Pattern
After-hours access • Nurse J. Smith • 23 records
4h
C Dr. Chen anomaly detection: Access volume 340% above baseline for this user
Nurse accessed 23 patient records between 2am-4am. Only 3 were assigned patients. May be legitimate (covering shift) or potential breach. Requires investigation per §164.308(a)(1)(ii)(D).
Compliance Tasks (3)
Annual HIPAA Training Compliance
23 staff overdue • Deadline: Dec 31
17 days
Staff must complete annual HIPAA privacy and security training. 23 employees have not completed. Auto-reminders sent.
BAA Review — Wearable Vendor
FitSync Inc. • New data sharing agreement
5 days
Business Associate Agreement for new wearable integration. Review data handling, breach notification terms, and subcontractor provisions.
Annual Risk Assessment
Q4 Security Risk Analysis • §164.308(a)(1)(ii)(A)
17 days
Annual assessment of potential risks and vulnerabilities to ePHI. Document administrative, physical, and technical safeguards.
Compliance Cleared (2)
OCR Inquiry — Case Closed
No violation found
Cleared
42 CFR Part 2 Audit
SUD records compliant
Passed
Clinical Decision Support Alerts (1)
Alert Fatigue Risk — Dr. Olivia
47 unread alerts • Clinician burnout indicator
Review
O Dr. Olivia self-assessment: Alert override rate 34% — threshold tuning recommended
Dr. Martinez has 47 unacknowledged behavioral health alerts. High override rate suggests alert thresholds may be too sensitive. Risk of missing genuine crisis.
Informatics Tasks (3)
AI Model Validation — Crisis Prediction
48-96hr Window • Monthly Review
5 days
Monthly accuracy review of 6-doctor AI Council predictions. Current: 94% sensitivity, 87% specificity. Compare against clinician outcomes.
Workflow Integration — Discharge
Epic → RNI handoff automation
Ongoing
Map discharge workflow to trigger post-acute monitoring. Auto-enroll patients in wearable tracking with proper consent documentation.
CDS Rule Update — MAT Protocol
Buprenorphine dosing decision support
7 days
Update clinical decision support rules for MAT per ASAM 2024 guidelines. Add naloxone co-prescribing reminder.
Validated This Week (2)
HRV Algorithm Update
Accuracy improved to 94%
Validated
PHQ-9 Auto-Scoring
100% accuracy vs manual
Live
Infrastructure Alerts (1)
Dr. Taylor Node — High Latency
Predictive AI • Response: 340ms (SLA: 200ms)
15m
T Dr. Taylor self-diagnostic: Memory pressure detected, recommend scale-up
Gemini endpoint experiencing increased load. 45M daily biometric points causing queue backup. Auto-scaling triggered but not sufficient.
IT Infrastructure Tasks (3)
SSL Certificate Renewal
*.recoverynetwork.ai • Expires in 14 days
14 days
Auto-renewal configured via Let's Encrypt. Verify DNS challenge ready for all subdomains including Epic interface.
Quarterly DR Test
Azure → GCP Failover • Dec 20
6 days
HIPAA requires documented DR testing. Schedule off-peak failover drill. RTO target: 4 minutes. RPO: 1 hour.
API Gateway Rate Limit Tuning
Pilot traffic increase expected
3 days
New pilot site launching Monday. Increase rate limits on biometric ingestion endpoints. Current: 1000/min, need: 2500/min.
System Health (2)
Platform Uptime
99.97% • 30 days
SLA Met
Backup Verification
4:00am • Restore test passed
Verified
Quality Alerts (1)
30-Day Readmission Rate Spike
Current: 18% (Target: 12%)
Analyze
T Dr. Taylor root cause analysis: 67% of readmits had <3 days post-discharge monitoring
Readmission rate up 6 points from last quarter. Pattern shows correlation with patients who declined wearable monitoring. SAMHSA reporting threshold at risk.
Quality Improvement Tasks (3)
CARF Accreditation Survey Prep
Scheduled: January 15-17, 2025
32 days
Prepare documentation for CARF Behavioral Health accreditation. Focus areas: treatment planning, patient rights, outcomes measurement.
PHQ-9 Completion Rate
Current: 87% (Target: 95%)
Ongoing
Depression screening completion below SAMHSA CCBHC standard. Gap analysis shows intake workflow issue. Recommend EHR prompt enhancement.
Patient Satisfaction Survey — Q4
CAHPS-BH • 234 responses pending
10 days
Q4 patient experience survey in progress. Current NPS: 72. Response rate: 43%. Send reminder to non-responders.
Quality Targets Met (2)
Program Completion Rate
76% (+4% vs Q3)
Target Met
MAT Adherence
94% • SAMHSA benchmark
Exceeds
` : ''; // Show gate triggers if any const triggerDisplay = gateTriggers.length > 0 ? `
🟡 ${gateTriggers.join(' + ')}
` : ''; return ` `; } // ============================================ // RENDER MAIN PANEL CARDS - From liveDataset ONLY // ============================================ function renderMainPanel() { const container = document.getElementById("live-pcode-feed"); if (!container) return; // Clear and rebuild from backend truth container.innerHTML = ''; liveDataset.forEach(p => { const card = renderTaskCard(p); container.appendChild(card); }); } function renderTaskCard(p) { const statusUI = mapStatusToUI(p.status); const clockDisplay = formatClockDisplay(p); const progress = p.percent_complete || 0; const isAwaiting = p.status === 'awaiting'; const isBlocked = p.status === 'blocked'; // Domain classification const primaryDomain = p.primaryDomain || p.domain || 'Operations'; const secondaryDomains = p.secondaryDomains || []; const gateTriggers = p.gateTriggers || []; // Only show P-code if it's clean format (P-XXX), otherwise hide completely const isCleanPcode = p.pcode && /^P-\d+/.test(p.pcode); const displayCode = isCleanPcode ? p.pcode : ''; // Build domain tags HTML const domainTagsHtml = `
${primaryDomain} ${secondaryDomains.map(domain => ` ${domain} `).join('')}
${gateTriggers.length > 0 ? `
🟡 ${gateTriggers.join(' + ')}
` : ''} ${isBlocked && p.error ? `
✗ EXECUTION ERROR: ${p.error}
` : ''} `; const card = document.createElement("div"); card.className = `task-card ${statusUI.color} ${isAwaiting ? 'awaiting' : ''} ${isBlocked ? 'blocked' : ''}`; card.id = p.pcode; card.dataset.pcode = p.pcode; card.innerHTML = ` ${isAwaiting ? '' : ''} ${isBlocked ? '' : ''} ${statusUI.label}
${primaryDomain}
${displayCode ? `
${displayCode}
` : ''}
${domainTagsHtml}
${p.assigned_doctor || 'Unassigned'}
${clockDisplay}
${p.origin_request || ''}
`; // Click handler for selection card.style.cursor = 'pointer'; card.addEventListener('click', (e) => { if (!e.target.closest('button')) { selectPcode(p.pcode); if (isAwaiting) { showGovernanceModalFromData(p); } } }); return card; } // ============================================ // SELECTION - Cross-view highlighting // ============================================ function selectPcode(pcodeId) { // Clear all selections document.querySelectorAll('.sidebar-item').forEach(el => el.classList.remove('active')); document.querySelectorAll('.task-card').forEach(el => { el.classList.remove('selected'); el.classList.remove('dimmed'); }); // Highlight sidebar const sidebarItem = document.querySelector(`.sidebar-item[data-pcode="${pcodeId}"]`); if (sidebarItem) { sidebarItem.classList.add('active'); sidebarItem.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } // Highlight card, dim others document.querySelectorAll('.task-card').forEach(card => { if (card.id === pcodeId || card.dataset.pcode === pcodeId) { card.classList.add('selected'); card.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } else { card.classList.add('dimmed'); } }); } // ============================================ // GOVERNANCE MODAL - With real authorization // Only shows for Compliance, Risk, Security, Strategic/IP, Phoenix // NOT for 404s or execution errors // ============================================ function showGovernanceModalFromData(pcode) { const modal = document.getElementById('governance-modal'); const container = document.getElementById('modal-content'); if (!modal || !container) return; // Domain classification const primaryDomain = pcode.primaryDomain || pcode.domain || 'Operations'; const secondaryDomains = pcode.secondaryDomains || []; const gateTriggers = pcode.gateTriggers || []; const impact = pcode.impact || 'Standard'; // Build explicit trigger reason - shows WHY this needs approval let triggerReason = ''; if (gateTriggers.length > 0) { triggerReason = `Paused due to ${impact} impact + ${gateTriggers.join(' + ')} trigger`; } else if (impact === 'Strategic' || impact === 'Critical') { triggerReason = `Paused due to ${impact} impact classification`; } else { triggerReason = `Paused for Executive Authorization`; } // Build domain routing display const domainRoutingHtml = `
Domain Routing
PRIMARY: ${primaryDomain} ${secondaryDomains.map(domain => ` + ${domain} `).join('')}
${gateTriggers.length > 0 ? `
⚠ GATE TRIGGERS: ${gateTriggers.join(' + ')}
These domains require executive authorization before execution
` : ''}
`; // Build engines locked display (if gate triggers) const enginesLockedHtml = gateTriggers.length > 0 ? `
🔒 ENGINES LOCKED
AI Council, Phoenix, and Worker execution paused pending authorization
` : ''; container.innerHTML = ` ${domainRoutingHtml} ${enginesLockedHtml} `; modal.className = 'governance-modal active'; modal.onclick = (e) => { if (e.target === modal) { leavePaused(); } }; } // ============================================ // AUTHORIZATION - POST to /pcode/issue (VERIFIED LIVE) // "Authorize & Start Execution" button handler // No simulated execution. Server truth only. // ============================================ async function authorizeFromBackend(pcodeId) { console.log('🔐 Authorizing P-code:', pcodeId); // Show loading state const btn = document.querySelector('.btn-primary-action'); if (btn) { btn.disabled = true; btn.textContent = 'Authorizing...'; } // Find the P-code to get its details const pcode = liveDataset.find(p => p.pcode === pcodeId); if (!pcode) { showErrorInModal('P-code not found', 'Could not locate task in dataset.', 'Refresh and retry.'); return; } // VERIFIED PAYLOAD STRUCTURE - matches working /pcode/issue endpoint const payload = { source: "executive-console-authorize", requested_by: "jb", domain_class: pcode.primaryDomain || pcode.domain || 'Operations', urgency_class: "Priority", impact_class: pcode.impact || "Strategic", authorization_class: "Executive", tenant_id: "rni-default-tenant", origin_request: `[AUTHORIZED] ${pcode.origin_request || pcodeId}` }; console.log('📤 POST /pcode/issue (authorize):', payload); try { const response = await fetch(PCODE_ISSUE_ENDPOINT, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const result = await response.json().catch(() => ({})); // RESPONSE HANDLING: if (result.pcode) { // Success - authorized and new P-code issued console.log('✓ Authorization successful:', result.pcode); showSuccessToast(`Authorized. New P-code: ${result.pcode}`); closeGovernanceModal(); clearSelectionStates(); // Update local state pcode.status = 'active'; pcode.percent_complete = 1; renderSidebar(); renderMainPanel(); // Start polling for progress updates startStatusPolling(result.pcode); } else if (response.status === 404) { // 404 → "Execution service not reachable" (NOT approval) console.error('✗ Execution service not reachable (404)'); showErrorInModal('Execution service not reachable', 'The execution service is not responding. This is a system error, not a governance hold.', 'Fallback mode activated. Manual control enabled.'); activateFallbackMode({ domain: pcode.domain }, 'Authorization service unreachable (404)'); } else if (response.status === 500) { // 500 → Blocked (red) + Fallback console.error('✗ Server error (500):', result); showErrorInModal('Server Error', result.error || 'The server encountered an error processing this request.', 'Fallback mode activated. Manual control enabled.'); pcode.status = 'blocked'; pcode.error = result.error || 'Server error'; renderSidebar(); renderMainPanel(); closeGovernanceModal(); activateFallbackMode({ domain: pcode.domain }, 'Server error (500)'); } else { console.error('✗ ISSUER ERROR:', response.status, result); showErrorInModal('Issuer Error', result.error || 'The issuer returned an error.', 'Manual control available.'); } } catch (error) { // Network failure = service unreachable - ACTIVATE FALLBACK console.error('✗ Network error:', error); showErrorInModal('Network Error', `Could not reach execution service: ${error.message}`, 'Fallback mode activated. Manual control enabled.'); activateFallbackMode({ domain: pcode.domain }, `Authorization network error: ${error.message}`); } finally { // Reset button state if (btn) { btn.disabled = false; btn.textContent = 'Authorize & Start Execution'; } } } // Show error IN the modal (not as separate alert) function showErrorInModal(title, reason, action) { const container = document.getElementById('modal-content'); if (!container) return; // Find or create error display area let errorDiv = container.querySelector('.modal-error'); if (!errorDiv) { errorDiv = document.createElement('div'); errorDiv.className = 'modal-error'; errorDiv.style.cssText = 'margin: 16px 0; padding: 12px; background: #fef2f2; border-radius: 8px; border-left: 4px solid #dc2626;'; container.querySelector('.modal-body').after(errorDiv); } errorDiv.innerHTML = `
✗ ${title}
Reason: ${reason}
Action: ${action}
`; } // ============================================ // MASTER REFRESH - Backend truth overwrites all // Single source of truth. Left column and center mirror SAME record. // ============================================ // ============================================ // REV 65 — PHASE 5 & 6: LIVE BACKEND POLLING // /pcode/recent for activity panel and Phoenix check // ============================================ async function refreshFromBackend() { try { console.log('🔄 Fetching /pcode/recent...'); const response = await fetch(PCODE_RECENT_ENDPOINT); if (response.status === 404) { console.warn('⚠️ /pcode/recent not available (404)'); updatePhoenixStatus('unknown'); return; } if (!response.ok) { console.warn('⚠️ Backend fetch failed:', response.status); updatePhoenixStatus('unknown'); return; } const data = await response.json(); console.log('ISSUER → UI /pcode/recent:', data); // Extract pcodes array from response let rawPcodes = []; if (data && Array.isArray(data.pcodes)) { rawPcodes = data.pcodes; } else if (data && Array.isArray(data)) { rawPcodes = data; } else { console.warn('Unexpected response format:', data); return; } // Take last 5 P-codes for activity panel liveDataset = rawPcodes.slice(0, 5).map(normalizeBackendPcode); console.log(`✅ Loaded ${liveDataset.length} P-codes from backend`); // PHASE 5: Check Phoenix escalation status checkPhoenixEscalationStatus(liveDataset); // Re-render both views renderSidebar(); renderMainPanel(); } catch (error) { console.error('❌ Backend refresh error:', error); updatePhoenixStatus('unknown'); } } // ============================================ // PHASE 5: PHOENIX ESCALATION CHECK // If newest P-code has no orchestrator status after 10s → ESCALATION ACTIVE // ============================================ function checkPhoenixEscalationStatus(pcodes) { if (!pcodes || pcodes.length === 0) { updatePhoenixStatus('idle'); return; } const newest = pcodes[0]; const now = new Date(); const issuedAt = new Date(newest.started_at || newest.created_at || now); const ageMs = now - issuedAt; // If newest P-code is less than 10s old and has no orchestrator status if (ageMs < PHOENIX_CHECK_DELAY && !newest.orchestrator_status) { // Still waiting - check again later console.log('⏳ Phoenix check: P-code too new, waiting...'); updatePhoenixStatus('watching'); return; } // If older than 10s and still no orchestrator status → ESCALATION if (ageMs >= PHOENIX_CHECK_DELAY && !newest.orchestrator_status) { console.warn('🔄 AUTOMATED RECOVERY ACTIVE - No orchestrator status'); updatePhoenixStatus('escalation'); return; } // Has orchestrator status → healthy console.log('✅ Phoenix check: Orchestrator healthy'); updatePhoenixStatus('healthy'); } // ============================================ // PHOENIX STATUS UI UPDATE // ============================================ function updatePhoenixStatus(status) { phoenixStatus = status; console.log('PHOENIX STATUS:', phoenixStatus); const phoenixNode = document.querySelector('.pipeline-node.node-blue'); if (!phoenixNode) return; const statusEl = phoenixNode.querySelector('.pipeline-node-status'); if (!statusEl) return; // Executive-grade status labels with color chips switch(status) { case 'escalation': // Recovering - amber, brief state statusEl.innerHTML = '🔄 Fully Self-Healing...'; statusEl.style.color = '#f59e0b'; phoenixNode.style.animation = 'subtle-pulse 2s ease-in-out infinite'; showRecoveryBanner(); break; case 'watching': statusEl.innerHTML = '🔄 Fully Self-Healing...'; statusEl.style.color = '#f59e0b'; phoenixNode.style.animation = ''; break; case 'healthy': statusEl.innerHTML = ' Fully Self-Healed'; statusEl.style.color = '#10b981'; phoenixNode.style.animation = ''; hideRecoveryBanner(); break; case 'idle': statusEl.innerHTML = ' Stable'; statusEl.style.color = '#10b981'; phoenixNode.style.animation = ''; hideRecoveryBanner(); break; default: statusEl.innerHTML = ' Stable'; statusEl.style.color = '#10b981'; phoenixNode.style.animation = ''; } } // ============================================ // AUTOMATED RECOVERY BANNER // Executive-grade messaging, Phoenix lives in tooltip only // ============================================ function showRecoveryBanner() { // Remove existing banner if any hideRecoveryBanner(); const banner = document.createElement('div'); banner.id = 'recovery-banner'; banner.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; background: linear-gradient(90deg, #f59e0b, #d97706); color: white; padding: 12px 20px; text-align: center; z-index: 10001; box-shadow: 0 2px 8px rgba(0,0,0,0.2); `; banner.innerHTML = `
🔄 Fully Self-Healing
System handling automatically. No action required.
`; document.body.prepend(banner); } function hideRecoveryBanner() { const existing = document.getElementById('recovery-banner'); if (existing) existing.remove(); } // Start periodic refresh setInterval(refreshFromBackend, RECENT_REFRESH_INTERVAL); // ============================================ // REV 62 — STATUS POLLING REMOVED // No orchestrator calls. No /pcode/status polling. // P-codes display from successful issue responses only. // ============================================ function startStatusPolling(pcodeId) { // REMOVED: No status polling console.log(`📋 P-code ${pcodeId} added to local session`); } function stopStatusPolling(pcodeId) { // REMOVED: No status polling } // ============================================ // FILE UPLOAD HANDLER // ============================================ let uploadedFiles = []; function handleFileUpload(files) { if (!files || files.length === 0) return; const maxFiles = 5; const maxSizeMB = 10; Array.from(files).forEach(file => { if (uploadedFiles.length >= maxFiles) { showErrorToast(`Maximum ${maxFiles} files allowed`); return; } if (file.size > maxSizeMB * 1024 * 1024) { showErrorToast(`${file.name} exceeds ${maxSizeMB}MB limit`); return; } uploadedFiles.push(file); console.log('📎 File attached:', file.name); }); updateAttachedFilesDisplay(); showSuccessToast(`${files.length} file(s) attached`); document.getElementById('file-upload-input').value = ''; } function updateAttachedFilesDisplay() { let container = document.getElementById('attached-files-display'); const requestBox = document.querySelector('.request-box'); const actionsDiv = requestBox.querySelector('.request-actions'); if (!container && uploadedFiles.length > 0) { container = document.createElement('div'); container.id = 'attached-files-display'; container.style.cssText = 'margin-bottom: 12px; display: flex; flex-wrap: wrap; gap: 6px;'; requestBox.insertBefore(container, actionsDiv); } if (container) { if (uploadedFiles.length === 0) { container.remove(); return; } container.innerHTML = uploadedFiles.map((file, i) => `
${file.name}
`).join(''); } } function removeUploadedFile(index) { uploadedFiles.splice(index, 1); updateAttachedFilesDisplay(); } function clearUploadedFiles() { uploadedFiles = []; const container = document.getElementById('attached-files-display'); if (container) container.remove(); } // ============================================ // DOWNLOAD OPERATIONS REPORT (PDF) // ============================================ function downloadOperationsReport() { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const now = new Date(); const timestamp = now.toISOString().slice(0, 10); // Colors const rniGreen = [67, 219, 163]; const darkGray = [31, 41, 55]; const mutedGray = [107, 114, 128]; // Header doc.setFillColor(...rniGreen); doc.rect(0, 0, 210, 35, 'F'); doc.setTextColor(255, 255, 255); doc.setFontSize(24); doc.setFont('helvetica', 'bold'); doc.text('RNI Admin Console', 20, 20); doc.setFontSize(11); doc.setFont('helvetica', 'normal'); doc.text('Operations Report', 20, 28); doc.setFontSize(10); doc.text(now.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }), 140, 20); // System Status let y = 50; doc.setTextColor(...darkGray); doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.text('System Status', 20, y); y += 10; doc.setFontSize(11); doc.setFont('helvetica', 'normal'); const statusData = [ ['Operations', '24 / 160'], ['Uptime', '99.94%'], ['Council', '6 doctors online'], ['Workers', '10/10 healthy'], ['Phoenix', 'Stable'] ]; statusData.forEach(([label, value]) => { doc.setTextColor(...mutedGray); doc.text(label + ':', 20, y); doc.setTextColor(...darkGray); doc.setFont('helvetica', 'bold'); doc.text(value, 60, y); doc.setFont('helvetica', 'normal'); y += 7; }); // Active P-Codes y += 10; doc.setTextColor(...darkGray); doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.text('Active P-Codes', 20, y); y += 10; doc.setFontSize(10); if (liveDataset && liveDataset.length > 0) { liveDataset.forEach((p, i) => { if (y > 260) { doc.addPage(); y = 20; } doc.setFont('helvetica', 'bold'); doc.setTextColor(...rniGreen); doc.text(`${i + 1}. ${p.pcode || 'P-XXX'}`, 20, y); y += 6; doc.setFont('helvetica', 'normal'); doc.setTextColor(...mutedGray); doc.text(`Domain: ${p.domain || 'Unclassified'} | Status: ${p.status || 'Unknown'}`, 25, y); y += 8; }); } else { doc.setTextColor(...mutedGray); doc.text('No active P-codes in current session.', 20, y); } // Footer const pageHeight = doc.internal.pageSize.height; doc.setFillColor(...rniGreen); doc.rect(0, pageHeight - 15, 210, 15, 'F'); doc.setTextColor(255, 255, 255); doc.setFontSize(9); doc.text('Recovery Network Inc. — data that heals™', 20, pageHeight - 6); doc.text('CONFIDENTIAL', 170, pageHeight - 6); doc.save(`RNI-Operations-Report-${timestamp}.pdf`); showSuccessToast('PDF downloaded'); } // ============================================ // ERROR TOAST - Service unreachable messages // ============================================ function showErrorToast(message) { const existing = document.querySelector('.error-toast'); if (existing) existing.remove(); const toast = document.createElement('div'); toast.className = 'error-toast'; toast.style.cssText = ` position: fixed; bottom: 20px; right: 20px; background: #fef2f2; color: #991b1b; padding: 12px 20px; border-radius: 8px; box-shadow: 0 4px 12px rgba(220, 38, 38, 0.2); border-left: 4px solid #dc2626; z-index: 9999; font-size: 14px; font-weight: 500; animation: toastSlideIn 300ms ease-out; `; toast.innerHTML = `${message}`; document.body.appendChild(toast); setTimeout(() => { toast.style.animation = 'toastSlideIn 300ms ease-out reverse'; setTimeout(() => toast.remove(), 300); }, 6000); } // ============================================ // CARD ACTION HANDLER // ============================================ function handleCardAction(pcodeId) { const pcode = liveDataset.find(p => p.pcode === pcodeId); if (!pcode) return; if (pcode.status === 'awaiting') { showGovernanceModalFromData(pcode); } else { // Show detail view for non-awaiting P-codes showSimpleDetail(pcode); } } // ============================================ // INITIALIZATION - Wire to backend // No client-side execution paths // UI is a control panel only, not a simulator // ============================================ document.addEventListener('DOMContentLoaded', () => { // Create live feed container if not exists const mainScroll = document.querySelector('.main-scroll'); if (mainScroll && !document.getElementById('live-pcode-feed')) { const feedContainer = document.createElement('div'); feedContainer.id = 'live-pcode-feed'; feedContainer.className = 'task-section'; // Insert after the request box const requestBox = document.querySelector('.request-box'); if (requestBox) { requestBox.after(feedContainer); } else { mainScroll.appendChild(feedContainer); } } // Initial render renderSidebar(); renderMainPanel(); // PHASE 6: Load recent P-codes from backend console.log('🚀 Loading recent P-codes from backend...'); refreshFromBackend(); console.log('✓ Rev 141 initialized - FULL HANDSHAKE WIRING'); }); // ============================================ // REV 65 — PHASE 7: CONSOLE LOGGING // Full visibility into UI ↔ Backend handshake // ============================================ console.log('========================================'); console.log('🏥 RNI Admin Console Rev 15'); console.log('========================================'); console.log('📡 POST /pcode/issue — Submit new P-code'); console.log('📡 GET /pcode/recent — Load activity panel'); console.log('📡 GET /health — Service health check'); console.log('🔥 Phoenix escalation: Data-driven'); console.log('========================================'); // P-code drill-down modal function openPcodeDetail(pcode, title, doctor, status, description) { const modal = document.createElement('div'); modal.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.6); display: flex; align-items: center; justify-content: center; z-index: 10000; animation: fadeIn 0.2s; `; modal.innerHTML = `

${title}

${pcode}
Assigned Doctor
${doctor}
Status
${status}
Description
${description}
Timeline
Started: Nov 18, 2025
⦿
In Progress: 2 days elapsed
Due: Nov 22, 2025 (2 days remaining)
Council Recommendations
Dr. Olivia: Prioritize user feedback integration before final testing.

Dr. Williams: Ensure API response time stays under 200ms threshold.

Dr. Taylor: Add Phoenix monitoring hooks for real-time error detection.
`; document.body.appendChild(modal); // Close on background click modal.addEventListener('click', (e) => { if (e.target === modal) modal.remove(); }); } // Add click handlers to all task cards document.querySelectorAll('.task-card').forEach(card => { card.style.cursor = 'pointer'; card.addEventListener('click', function(e) { // Don't trigger if clicking a button if (e.target.closest('button')) return; const title = this.querySelector('.task-title').textContent; const pcode = this.querySelector('.task-code').textContent; const doctor = this.querySelector('.task-meta-item:first-child span').textContent; const status = this.querySelector('.task-meta-item:nth-child(2) span').textContent; const description = this.querySelector('.task-description, .task-list')?.textContent || 'No description available'; openPcodeDetail(pcode, title, doctor, status, description); }); }); // Add CSS animations const style = document.createElement('style'); style.textContent = ` @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } `; document.head.appendChild(style); /* ================================ REV 52 - Legacy functions kept for compatibility All real logic now in telemetry system above ================================ */ /* Show Governance Modal - delegates to new system */function showGovernanceModal(pcode) { // Convert old format to new format and delegate const normalizedPcode = { pcode: pcode.pcode || pcode.id, status: 'awaiting', domain: pcode.domain_class || pcode.domain || 'System', impact: pcode.impact_class || 'Standard', origin_request: pcode.origin_request || '', assigned_doctor: pcode.requested_by || 'Executive' }; showGovernanceModalFromData(normalizedPcode); } /* Legacy authorize function - delegates to new backend call */function authorizeAndStart(pcodeId) { authorizeFromBackend(pcodeId); } /* Handle awaiting click - delegates to new system */function handleAwaitingClick(pcodeId, pcodeData) { selectPcode(pcodeId); showGovernanceModal(pcodeData); } /* Success Toast */function showSuccessToast(message) { const toast = document.createElement('div'); toast.className = 'success-toast'; toast.innerHTML = `
Success
${message}
`; document.body.appendChild(toast); setTimeout(() => { toast.style.animation = 'toastSlideIn 300ms ease-out reverse'; setTimeout(() => toast.remove(), 300); }, 4000); } // ============================================ // NOTES - Governance Artifacts (NOT social chatter) // "Add Comment / Modify" only appends a note // It does NOT resubmit or reroute // ============================================ function addNoteModify(id) { console.log("📝 Adding note to:", id); const noteText = prompt(`Add note for P-Code ${id}:\n\nThis appends a governance note to the audit trail.\nIt does NOT resubmit or reroute the task.`); if (noteText && noteText.trim()) { // Just log the note - no resubmission, no rerouting console.log(`✏️ Note appended to ${id}:`, noteText); showSuccessToast(`Note added to P-Code ${id}. Audit trail updated.`); closeGovernanceModal(); } } // Legacy alias function addCommentModify(id) { addNoteModify(id); } function leavePaused() { console.log("⏸ Left paused - no action taken"); closeGovernanceModal(); clearSelectionStates(); } function closeGovernanceModal() { const modal = document.getElementById('governance-modal'); if (modal) { modal.className = 'governance-modal'; } } function clearSelectionStates() { document.querySelectorAll('.sidebar-item').forEach(item => { item.classList.remove('selected', 'active'); }); document.querySelectorAll('.task-card').forEach(card => { card.classList.remove('selected', 'dimmed'); }); } /* Simple detail pane for non-awaiting P-codes */function showSimpleDetail(pcode) { const pane = document.getElementById("pcode-detail-pane"); if (!pane) return; const statusUI = mapStatusToUI(pcode.status || 'active'); // Use request snippet as title (first 60 chars), P-code as subtitle const requestSnippet = pcode.origin_request ? (pcode.origin_request.length > 60 ? pcode.origin_request.substring(0, 60) + '...' : pcode.origin_request) : 'Request Details'; const shortPcode = pcode.pcode ? `P-${pcode.pcode.substring(0, 8)}...` : ''; pane.className = "active"; pane.innerHTML = `

${requestSnippet}

${shortPcode} • ${statusUI.label}
Domain: ${pcode.domain || "—"} Impact: ${pcode.impact || "—"} Assigned: ${pcode.assigned_doctor || "—"} Progress: ${pcode.percent_complete || 0}%
Full Request:
${pcode.origin_request || "—"}
`; pane.scrollIntoView({ behavior: 'smooth', block: 'start' }); } /* Legacy show detail - delegates to new system */function showPcodeDetail(pcode) { const normalizedPcode = { pcode: pcode.pcode || pcode.id, status: pcode.status || 'active', domain: pcode.domain_class || pcode.domain || 'System', impact: pcode.impact_class || pcode.impact || 'Standard', origin_request: pcode.origin_request || '', assigned_doctor: pcode.requested_by || pcode.assigned_doctor || 'Unassigned', percent_complete: pcode.percent_complete || 0 }; if (normalizedPcode.status === 'awaiting' || pcode.impact_class === 'Strategic' || pcode.impact_class === 'Critical') { normalizedPcode.status = 'awaiting'; showGovernanceModalFromData(normalizedPcode); } else { showSimpleDetail(normalizedPcode); } } function closeDetail() { const pane = document.getElementById("pcode-detail-pane"); if (pane) pane.className = ""; } // ============================================ // ADMIN CONSOLE - ROLE SWITCHING // ============================================ const roleNames = { him: 'HIM Director', compliance: 'Compliance Officer', informatics: 'Clinical Informatics', itdir: 'IT Director', quality: 'Quality Director' }; function switchRole(role) { console.log('🔄 Switching to role:', roleNames[role] || role); // Hide all role views (main content) document.querySelectorAll('.role-view').forEach(view => { view.classList.remove('active'); view.style.display = 'none'; }); // Show selected role view const selectedView = document.getElementById(`view-${role}`); if (selectedView) { selectedView.style.display = 'block'; selectedView.classList.add('active'); } // Hide all sidebar role views document.querySelectorAll('.sidebar-role-view').forEach(view => { view.classList.remove('active'); view.style.display = 'none'; }); // Show selected sidebar role view const selectedSidebar = document.getElementById(`sidebar-${role}`); if (selectedSidebar) { selectedSidebar.style.display = 'block'; selectedSidebar.classList.add('active'); } // Update role chip in Ask Council const roleChip = document.getElementById('pill-role'); if (roleChip) { roleChip.textContent = roleNames[role] || role; } // Count tasks in the active view const activeView = document.querySelector('.role-view.active'); const urgentTasks = activeView ? activeView.querySelectorAll('.task-card.red, .task-card.yellow').length : 0; // Update Active count in sidebar const activeCountEl = document.querySelector('.sidebar-stat-value.red'); if (activeCountEl) { activeCountEl.textContent = urgentTasks; } // Show toast showToast(`Switched to ${roleNames[role]} view`, 'success'); } // Shift Clock Countdown function updateShiftClock() { const clock = document.getElementById('shiftClock'); if (!clock) return; let [h, m, s] = clock.textContent.split(':').map(Number); if (s > 0) s--; else if (m > 0) { m--; s = 59; } else if (h > 0) { h--; m = 59; s = 59; } clock.textContent = `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`; } setInterval(updateShiftClock, 1000); // Toast notification function showToast(message, type = 'info') { // Remove existing toasts document.querySelectorAll('.rni-toast').forEach(t => t.remove()); const toast = document.createElement('div'); toast.className = `rni-toast ${type}`; // Elegant center notification for role switches if (message.includes('Switched to')) { const roleName = message.replace('Switched to ', '').replace(' view', ''); toast.innerHTML = `
Now viewing as
${roleName}
`; toast.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.9); padding: 32px 48px; background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-radius: 16px; box-shadow: 0 24px 80px rgba(0, 0, 0, 0.12), 0 0 1px rgba(0, 0, 0, 0.1); z-index: 10000; text-align: center; opacity: 0; transition: opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1), transform 0.6s cubic-bezier(0.16, 1, 0.3, 1); `; // Add inner styles const style = document.createElement('style'); style.textContent = ` .role-toast-label { font-size: 11px; text-transform: uppercase; letter-spacing: 2px; color: #9CA3AF; margin-bottom: 8px; font-weight: 500; } .role-toast-name { font-size: 24px; font-weight: 600; color: #111827; margin-bottom: 16px; } .role-toast-bar { width: 0%; height: 3px; background: linear-gradient(90deg, #DC2626, #EF4444); border-radius: 2px; margin: 0 auto; animation: roleBarFill 2s cubic-bezier(0.16, 1, 0.3, 1) forwards; animation-delay: 0.3s; } @keyframes roleBarFill { 0% { width: 0%; opacity: 0; } 10% { opacity: 1; } 100% { width: 100%; opacity: 1; } } `; document.head.appendChild(style); document.body.appendChild(toast); // Animate in requestAnimationFrame(() => { toast.style.opacity = '1'; toast.style.transform = 'translate(-50%, -50%) scale(1)'; }); // Animate out setTimeout(() => { toast.style.opacity = '0'; toast.style.transform = 'translate(-50%, -50%) scale(0.95)'; setTimeout(() => { toast.remove(); style.remove(); }, 600); }, 2200); } else { // Standard toast for other messages toast.innerHTML = ` ${message}`; toast.style.cssText = ` position: fixed; bottom: 24px; right: 24px; padding: 14px 20px; background: ${type === 'success' ? '#DC2626' : '#3B82F6'}; color: white; border-radius: 8px; font-size: 14px; font-weight: 500; z-index: 10000; display: flex; align-items: center; gap: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); opacity: 0; transform: translateY(10px); transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1), transform 0.4s cubic-bezier(0.16, 1, 0.3, 1); `; document.body.appendChild(toast); requestAnimationFrame(() => { toast.style.opacity = '1'; toast.style.transform = 'translateY(0)'; }); setTimeout(() => { toast.style.opacity = '0'; toast.style.transform = 'translateY(10px)'; setTimeout(() => toast.remove(), 400); }, 3000); } } // Quick Ask presets function quickAsk(type) { const input = document.getElementById('request-input'); const box = document.getElementById('askCouncilBox'); const presets = { 'attention': 'Which patients need immediate attention right now?', 'hrv': 'What is the current HRV status across all monitored patients?', 'discharge': 'Which patients are ready for discharge or step-down?', 'handoffs': 'What are the pending handoffs for this shift?' }; // Expand the Ask Council box if collapsed if (box && box.classList.contains('collapsed')) { box.classList.remove('collapsed'); } if (input && presets[type]) { input.value = presets[type]; input.focus(); } } // Dark Mode Toggle // Toggle Ask Council Box function toggleAskCouncil() { const box = document.getElementById('askCouncilBox'); const icon = document.getElementById('askToggleIcon'); box.classList.toggle('collapsed'); } function toggleDarkMode() { document.body.classList.toggle('dark-mode'); const icon = document.getElementById('darkModeIcon'); if (document.body.classList.contains('dark-mode')) { icon.classList.remove('fa-moon'); icon.classList.add('fa-sun'); showToast('Dark mode enabled', 'success'); } else { icon.classList.remove('fa-sun'); icon.classList.add('fa-moon'); showToast('Light mode enabled', 'success'); } } // S.O.A.P. Auto-Draft Viewer function viewSOAPDraft(patientId) { const drafts = { 'james-wilson': { patient: 'James Wilson', date: new Date().toLocaleDateString(), subjective: 'Patient reports improved mood, sleeping 7 hours/night, appetite returned. Denies SI/HI. States "feeling more like myself." Engaged in group therapy.', objective: 'Alert, oriented x4. Affect euthymic, congruent. Speech normal rate/rhythm. No psychomotor changes. VS: HR 72, BP 118/76, SpO2 99%.', assessment: 'Generalized Anxiety Disorder, improving. PHQ-9: 8 (↓4 from admission). GAD-7: 6 (↓5). Sleep improved. Medication adherence 100%.', plan: '1. Continue current medication regimen\n2. Continue group therapy daily\n3. Family session scheduled Thursday\n4. Target discharge Day 7 pending stability' } }; const draft = drafts[patientId]; if (!draft) { showToast('Draft not found', 'error'); return; } // Create modal with S.O.A.P. content const modal = document.createElement('div'); modal.className = 'soap-modal'; modal.innerHTML = `

S.O.A.P. Auto-Draft

${draft.patient} • ${draft.date} • Generated by Dr. Williams

S Subjective
${draft.subjective}
O Objective
${draft.objective}
A Assessment
${draft.assessment}
P Plan
${draft.plan}
`; document.body.appendChild(modal); } console.log('🏥 RNI Admin Console Rev 23 - Role-Specific Views'); console.log('═══════════════════════════════════════════════════'); console.log('+ 17/17 Clinical Grievances Addressed'); console.log('+ EHR Sync Badge (Epic: Connected)'); console.log('+ S.O.A.P. Auto-Draft Viewer'); console.log('+ Shift Handoff Summary Card'); console.log('+ Med Reconciliation Task'); console.log('+ Dark Mode Toggle'); console.log('+ 5 Role Views with Task Filtering'); console.log('═══════════════════════════════════════════════════');