// EMR Page JavaScript
// static/js/emr.js
class EMRPage {
constructor() {
this.currentPatientId = null;
this.currentPatient = null;
this.emrEntries = [];
this.filteredEntries = [];
this.currentPage = 1;
this.entriesPerPage = 20;
this.init();
}
async init() {
this.setupEventListeners();
await this.loadPatientFromURL();
if (this.currentPatientId) {
await this.loadEMRData();
await this.loadPatientStats();
} else {
this.showEmptyState();
}
}
setupEventListeners() {
// Refresh button
document.getElementById('refreshBtn').addEventListener('click', () => {
this.loadEMRData();
});
// Search button
document.getElementById('searchBtn').addEventListener('click', () => {
this.openSearchModal();
});
// Search input
document.getElementById('searchInput').addEventListener('input', (e) => {
this.filterEntries(e.target.value);
});
// Filter selects
document.getElementById('dateFilter').addEventListener('change', () => {
this.applyFilters();
});
document.getElementById('typeFilter').addEventListener('change', () => {
this.applyFilters();
});
// Tab buttons
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
this.switchTab(e.target.dataset.tab);
});
});
// Modal handlers
this.setupModalHandlers();
// File upload handlers
this.setupFileUploadHandlers();
}
setupModalHandlers() {
// EMR Detail Modal
const emrDetailModal = document.getElementById('emrDetailModal');
const emrDetailModalClose = document.getElementById('emrDetailModalClose');
const emrDetailModalCancel = document.getElementById('emrDetailModalCancel');
if (emrDetailModalClose) {
emrDetailModalClose.addEventListener('click', () => {
emrDetailModal.classList.remove('show');
});
}
if (emrDetailModalCancel) {
emrDetailModalCancel.addEventListener('click', () => {
emrDetailModal.classList.remove('show');
});
}
// Search Modal
const searchModal = document.getElementById('searchModal');
const searchModalClose = document.getElementById('searchModalClose');
const searchModalCancel = document.getElementById('searchModalCancel');
const performSearchBtn = document.getElementById('performSearchBtn');
if (searchModalClose) {
searchModalClose.addEventListener('click', () => {
searchModal.classList.remove('show');
});
}
if (searchModalCancel) {
searchModalCancel.addEventListener('click', () => {
searchModal.classList.remove('show');
});
}
if (performSearchBtn) {
performSearchBtn.addEventListener('click', () => {
this.performAdvancedSearch();
searchModal.classList.remove('show');
});
}
// Document Preview Modal
const documentPreviewModal = document.getElementById('documentPreviewModal');
const documentPreviewModalClose = document.getElementById('documentPreviewModalClose');
const documentPreviewCancel = document.getElementById('documentPreviewCancel');
const saveDocumentAnalysis = document.getElementById('saveDocumentAnalysis');
if (documentPreviewModalClose) {
documentPreviewModalClose.addEventListener('click', () => {
documentPreviewModal.classList.remove('show');
});
}
if (documentPreviewCancel) {
documentPreviewCancel.addEventListener('click', () => {
documentPreviewModal.classList.remove('show');
});
}
if (saveDocumentAnalysis) {
saveDocumentAnalysis.addEventListener('click', () => {
this.saveDocumentAnalysis();
});
}
}
setupFileUploadHandlers() {
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
const uploadBtn = document.getElementById('uploadBtn');
const uploadProgress = document.getElementById('uploadProgress');
// Click to upload
if (uploadBtn) {
uploadBtn.addEventListener('click', () => {
fileInput.click();
});
}
if (uploadArea) {
uploadArea.addEventListener('click', () => {
fileInput.click();
});
}
// File input change
if (fileInput) {
fileInput.addEventListener('change', (e) => {
if (e.target.files.length > 0) {
this.handleFileUpload(e.target.files);
}
});
}
// Drag and drop
if (uploadArea) {
uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
uploadArea.classList.add('dragover');
});
uploadArea.addEventListener('dragleave', (e) => {
e.preventDefault();
uploadArea.classList.remove('dragover');
});
uploadArea.addEventListener('drop', (e) => {
e.preventDefault();
uploadArea.classList.remove('dragover');
if (e.dataTransfer.files.length > 0) {
this.handleFileUpload(e.dataTransfer.files);
}
});
}
}
async loadPatientFromURL() {
const urlParams = new URLSearchParams(window.location.search);
const patientId = urlParams.get('patient_id');
// Check if patientId is valid (not undefined, null, or empty)
if (patientId && patientId !== 'undefined' && patientId !== 'null' && patientId.trim() !== '') {
this.currentPatientId = patientId;
await this.loadPatientInfo();
} else {
// Try to get from localStorage
const savedPatientId = localStorage.getItem('medicalChatbotPatientId');
if (savedPatientId && savedPatientId !== 'undefined' && savedPatientId !== 'null' && savedPatientId.trim() !== '') {
this.currentPatientId = savedPatientId;
await this.loadPatientInfo();
} else {
console.warn('No valid patient ID found in URL or localStorage');
this.showEmptyState();
}
}
}
async loadPatientInfo() {
try {
const response = await fetch(`/patient/${this.currentPatientId}`);
if (response.ok) {
this.currentPatient = await response.json();
this.updatePatientInfoBar();
} else {
console.error('Failed to load patient info');
this.showEmptyState();
}
} catch (error) {
console.error('Error loading patient info:', error);
this.showEmptyState();
}
}
updatePatientInfoBar() {
if (!this.currentPatient) return;
const patientInfoBar = document.getElementById('patientInfoBar');
const patientName = document.getElementById('patientName');
const patientDetails = document.getElementById('patientDetails');
patientName.textContent = this.currentPatient.name;
patientDetails.textContent = `Age: ${this.currentPatient.age} | Sex: ${this.currentPatient.sex} | ID: ${this.currentPatient._id}`;
patientInfoBar.style.display = 'block';
}
async loadPatientStats() {
try {
const response = await fetch(`/emr/statistics/${this.currentPatientId}`);
if (response.ok) {
const stats = await response.json();
this.updatePatientStats(stats);
}
} catch (error) {
console.error('Error loading patient stats:', error);
}
}
updatePatientStats(stats) {
const patientStats = document.getElementById('patientStats');
patientStats.innerHTML = `
${stats.total_entries || 0}
Total Entries
${Math.round((stats.avg_confidence || 0) * 100)}%
Avg Confidence
${stats.diagnosis_count || 0}
Diagnoses
${stats.medication_count || 0}
Medications
`;
}
async loadEMRData() {
if (!this.currentPatientId) return;
this.showLoading(true);
try {
const response = await fetch(`/emr/patient/${this.currentPatientId}?limit=100`);
if (response.ok) {
this.emrEntries = await response.json();
this.filteredEntries = [...this.emrEntries];
this.renderEMRTable();
} else {
console.error('Failed to load EMR data');
this.showEmptyState();
}
} catch (error) {
console.error('Error loading EMR data:', error);
this.showErrorState('Failed to load EMR data. Please try again.');
} finally {
this.showLoading(false);
}
}
renderEMRTable() {
const tableBody = document.getElementById('emrTableBody');
if (this.filteredEntries.length === 0) {
this.showEmptyState();
return;
}
tableBody.innerHTML = this.filteredEntries.map(entry => {
const date = new Date(entry.created_at).toLocaleString();
const type = this.getEMRType(entry.extracted_data);
const diagnosis = entry.extracted_data.diagnosis?.slice(0, 2).join(', ') || '-';
const medications = entry.extracted_data.medications?.slice(0, 2).map(m => m.name).join(', ') || '-';
const vitals = this.formatVitalSigns(entry.extracted_data.vital_signs);
const confidence = this.formatConfidence(entry.confidence_score);
return `
| ${date} |
${type} |
${diagnosis} |
${medications} |
${vitals} |
${confidence} |
|
`;
}).join('');
}
getEMRType(extractedData) {
if (extractedData.diagnosis?.length > 0) return 'diagnosis';
if (extractedData.medications?.length > 0) return 'medication';
if (extractedData.vital_signs && Object.values(extractedData.vital_signs).some(v => v)) return 'vitals';
if (extractedData.lab_results?.length > 0) return 'lab';
return 'general';
}
formatVitalSigns(vitalSigns) {
if (!vitalSigns) return '-';
const vitals = [];
if (vitalSigns.blood_pressure) vitals.push(`BP: ${vitalSigns.blood_pressure}`);
if (vitalSigns.heart_rate) vitals.push(`HR: ${vitalSigns.heart_rate}`);
if (vitalSigns.temperature) vitals.push(`Temp: ${vitalSigns.temperature}`);
return vitals.length > 0 ? vitals.join(', ') : '-';
}
formatConfidence(score) {
const percentage = Math.round(score * 100);
const level = score >= 0.8 ? 'high' : score >= 0.6 ? 'medium' : 'low';
return `
`;
}
async viewEMRDetail(emrId) {
try {
const response = await fetch(`/emr/${emrId}`);
if (response.ok) {
const entry = await response.json();
this.showEMRDetailModal(entry);
} else {
alert('Failed to load EMR details');
}
} catch (error) {
console.error('Error loading EMR detail:', error);
alert('Error loading EMR details');
}
}
showEMRDetailModal(entry) {
const modal = document.getElementById('emrDetailModal');
const content = document.getElementById('emrDetailContent');
const date = new Date(entry.created_at).toLocaleString();
content.innerHTML = `
Basic Information
Date: ${date}
Confidence: ${Math.round(entry.confidence_score * 100)}%
Original Message:
${entry.original_message}
${entry.extracted_data.diagnosis?.length > 0 ? `
Diagnoses
${entry.extracted_data.diagnosis.map(d => `- ${d}
`).join('')}
` : ''}
${entry.extracted_data.symptoms?.length > 0 ? `
Symptoms
${entry.extracted_data.symptoms.map(s => `- ${s}
`).join('')}
` : ''}
${entry.extracted_data.medications?.length > 0 ? `
Medications
${entry.extracted_data.medications.map(med => `
${med.name}
${med.dosage ? `Dosage: ${med.dosage}` : ''}
${med.frequency ? ` | Frequency: ${med.frequency}` : ''}
${med.duration ? ` | Duration: ${med.duration}` : ''}
`).join('')}
` : ''}
${entry.extracted_data.vital_signs && Object.values(entry.extracted_data.vital_signs).some(v => v) ? `
Vital Signs
${Object.entries(entry.extracted_data.vital_signs).map(([key, value]) =>
value ? `
${key.replace('_', ' ').toUpperCase()}
${value}
` : ''
).join('')}
` : ''}
${entry.extracted_data.lab_results?.length > 0 ? `
Lab Results
${entry.extracted_data.lab_results.map(lab => `
-
${lab.test_name}: ${lab.value} ${lab.unit || ''}
${lab.reference_range ? ` (Normal: ${lab.reference_range})` : ''}
`).join('')}
` : ''}
${entry.extracted_data.procedures?.length > 0 ? `
Procedures
${entry.extracted_data.procedures.map(p => `- ${p}
`).join('')}
` : ''}
${entry.extracted_data.notes ? `
Notes
${entry.extracted_data.notes}
` : ''}
`;
modal.classList.add('show');
}
async deleteEMREntry(emrId) {
if (!confirm('Are you sure you want to delete this EMR entry?')) {
return;
}
try {
const response = await fetch(`/emr/${emrId}`, {
method: 'DELETE'
});
if (response.ok) {
this.loadEMRData(); // Refresh the data
this.loadPatientStats(); // Refresh stats
} else {
alert('Failed to delete EMR entry');
}
} catch (error) {
console.error('Error deleting EMR entry:', error);
alert('Error deleting EMR entry');
}
}
filterEntries(query) {
if (!query.trim()) {
this.filteredEntries = [...this.emrEntries];
} else {
this.filteredEntries = this.emrEntries.filter(entry => {
const searchText = query.toLowerCase();
return (
entry.original_message.toLowerCase().includes(searchText) ||
entry.extracted_data.diagnosis?.some(d => d.toLowerCase().includes(searchText)) ||
entry.extracted_data.symptoms?.some(s => s.toLowerCase().includes(searchText)) ||
entry.extracted_data.medications?.some(m => m.name.toLowerCase().includes(searchText)) ||
entry.extracted_data.notes?.toLowerCase().includes(searchText)
);
});
}
this.renderEMRTable();
}
applyFilters() {
const dateFilter = document.getElementById('dateFilter').value;
const typeFilter = document.getElementById('typeFilter').value;
this.filteredEntries = this.emrEntries.filter(entry => {
// Date filter
if (dateFilter !== 'all') {
const entryDate = new Date(entry.created_at);
const now = new Date();
switch (dateFilter) {
case 'today':
if (entryDate.toDateString() !== now.toDateString()) return false;
break;
case 'week':
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
if (entryDate < weekAgo) return false;
break;
case 'month':
const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
if (entryDate < monthAgo) return false;
break;
}
}
// Type filter
if (typeFilter !== 'all') {
const entryType = this.getEMRType(entry.extracted_data);
if (entryType !== typeFilter) return false;
}
return true;
});
this.renderEMRTable();
}
openSearchModal() {
document.getElementById('searchModal').classList.add('show');
}
async performAdvancedSearch() {
const semanticQuery = document.getElementById('semanticSearchInput').value.trim();
const exactQuery = document.getElementById('exactSearchInput').value.trim();
if (!semanticQuery && !exactQuery) {
alert('Please enter a search query');
return;
}
this.showLoading(true);
try {
let searchResults = [];
if (semanticQuery) {
const response = await fetch(`/emr/search/${this.currentPatientId}?query=${encodeURIComponent(semanticQuery)}&limit=50`);
if (response.ok) {
searchResults = await response.json();
}
}
if (exactQuery) {
const exactResults = this.emrEntries.filter(entry => {
const searchText = exactQuery.toLowerCase();
return (
entry.original_message.toLowerCase().includes(searchText) ||
entry.extracted_data.diagnosis?.some(d => d.toLowerCase().includes(searchText)) ||
entry.extracted_data.symptoms?.some(s => s.toLowerCase().includes(searchText)) ||
entry.extracted_data.medications?.some(m => m.name.toLowerCase().includes(searchText)) ||
entry.extracted_data.notes?.toLowerCase().includes(searchText)
);
});
// Merge results if both searches were performed
if (semanticQuery) {
const exactIds = new Set(exactResults.map(r => r.emr_id));
searchResults = searchResults.concat(exactResults.filter(r => !exactIds.has(r.emr_id)));
} else {
searchResults = exactResults;
}
}
this.filteredEntries = searchResults;
this.renderEMRTable();
} catch (error) {
console.error('Error performing search:', error);
alert('Error performing search');
} finally {
this.showLoading(false);
}
}
showLoading(show) {
const loadingState = document.getElementById('loadingState');
const tableContainer = document.querySelector('.emr-table-container');
if (show) {
loadingState.style.display = 'block';
tableContainer.style.display = 'none';
} else {
loadingState.style.display = 'none';
tableContainer.style.display = 'block';
}
}
showEmptyState() {
const emptyState = document.getElementById('emptyState');
const tableContainer = document.querySelector('.emr-table-container');
emptyState.style.display = 'block';
tableContainer.style.display = 'none';
}
showErrorState(message) {
const emptyState = document.getElementById('emptyState');
const tableContainer = document.querySelector('.emr-table-container');
// Update the empty state to show error message
emptyState.querySelector('h3').textContent = 'Error Loading EMR Data';
emptyState.querySelector('p').textContent = message;
emptyState.querySelector('.btn').style.display = 'none';
emptyState.style.display = 'block';
tableContainer.style.display = 'none';
}
switchTab(tabName) {
// Update tab buttons
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.classList.remove('active');
});
document.querySelector(`[data-tab="${tabName}"]`).classList.add('active');
// Update tab content
document.querySelectorAll('.tab-content').forEach(content => {
content.classList.remove('active');
});
document.getElementById(`${tabName}-tab`).classList.add('active');
// Load specific tab data
switch (tabName) {
case 'diagnosis':
this.renderDiagnosisTab();
break;
case 'medications':
this.renderMedicationsTab();
break;
case 'vitals':
this.renderVitalsTab();
break;
case 'lab':
this.renderLabTab();
break;
case 'procedures':
this.renderProceduresTab();
break;
}
}
renderDiagnosisTab() {
const timeline = document.getElementById('diagnosisTimeline');
const diagnoses = [];
this.emrEntries.forEach(entry => {
if (entry.extracted_data.diagnosis && entry.extracted_data.diagnosis.length > 0) {
entry.extracted_data.diagnosis.forEach(diagnosis => {
diagnoses.push({
name: diagnosis,
date: new Date(entry.created_at).toLocaleDateString(),
confidence: Math.round(entry.confidence_score * 100)
});
});
}
});
if (diagnoses.length === 0) {
timeline.innerHTML = 'No diagnoses found in EMR entries.
';
return;
}
timeline.innerHTML = diagnoses.map(diagnosis => `
${diagnosis.date}
${diagnosis.name}
${diagnosis.confidence}%
`).join('');
}
renderMedicationsTab() {
const grid = document.getElementById('medicationsGrid');
const medications = [];
this.emrEntries.forEach(entry => {
if (entry.extracted_data.medications && entry.extracted_data.medications.length > 0) {
entry.extracted_data.medications.forEach(med => {
medications.push({
name: med.name,
dosage: med.dosage || 'Not specified',
frequency: med.frequency || 'Not specified',
duration: med.duration || 'Not specified',
date: new Date(entry.created_at).toLocaleDateString()
});
});
}
});
if (medications.length === 0) {
grid.innerHTML = 'No medications found in EMR entries.
';
return;
}
grid.innerHTML = medications.map(med => `
${med.name}
Dosage: ${med.dosage}
Frequency: ${med.frequency}
Duration: ${med.duration}
Date: ${med.date}
`).join('');
}
renderVitalsTab() {
const tableBody = document.getElementById('vitalsTableBody');
const vitalsData = [];
this.emrEntries.forEach(entry => {
if (entry.extracted_data.vital_signs) {
const vitals = entry.extracted_data.vital_signs;
if (Object.values(vitals).some(v => v)) {
vitalsData.push({
date: new Date(entry.created_at).toLocaleDateString(),
blood_pressure: vitals.blood_pressure || '-',
heart_rate: vitals.heart_rate || '-',
temperature: vitals.temperature || '-',
respiratory_rate: vitals.respiratory_rate || '-',
oxygen_saturation: vitals.oxygen_saturation || '-'
});
}
}
});
if (vitalsData.length === 0) {
tableBody.innerHTML = '| No vital signs found in EMR entries. |
';
return;
}
tableBody.innerHTML = vitalsData.map(vitals => `
| ${vitals.date} |
${vitals.blood_pressure} |
${vitals.heart_rate} |
${vitals.temperature} |
${vitals.respiratory_rate} |
${vitals.oxygen_saturation} |
`).join('');
}
renderLabTab() {
const container = document.getElementById('labResultsContainer');
const labResults = [];
this.emrEntries.forEach(entry => {
if (entry.extracted_data.lab_results && entry.extracted_data.lab_results.length > 0) {
entry.extracted_data.lab_results.forEach(lab => {
labResults.push({
test_name: lab.test_name,
value: lab.value,
unit: lab.unit || '',
reference_range: lab.reference_range || 'Not specified',
date: new Date(entry.created_at).toLocaleDateString()
});
});
}
});
if (labResults.length === 0) {
container.innerHTML = 'No lab results found in EMR entries.
';
return;
}
container.innerHTML = labResults.map(lab => `
Date: ${lab.date}
Reference Range: ${lab.reference_range}
`).join('');
}
renderProceduresTab() {
const timeline = document.getElementById('proceduresTimeline');
const procedures = [];
this.emrEntries.forEach(entry => {
if (entry.extracted_data.procedures && entry.extracted_data.procedures.length > 0) {
entry.extracted_data.procedures.forEach(procedure => {
procedures.push({
name: procedure,
date: new Date(entry.created_at).toLocaleDateString(),
confidence: Math.round(entry.confidence_score * 100)
});
});
}
});
if (procedures.length === 0) {
timeline.innerHTML = 'No procedures found in EMR entries.
';
return;
}
timeline.innerHTML = procedures.map(procedure => `
${procedure.date}
${procedure.name}
${procedure.confidence}%
`).join('');
}
async handleFileUpload(files) {
if (!this.currentPatientId) {
alert('Please select a patient first');
return;
}
const file = files[0]; // Handle only the first file for now
// Validate file type
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'image/jpeg', 'image/jpg', 'image/png', 'image/tiff'];
if (!allowedTypes.includes(file.type)) {
alert('Unsupported file type. Please upload PDF, DOC, DOCX, JPG, PNG, or TIFF files.');
return;
}
// Validate file size (10MB limit)
if (file.size > 10 * 1024 * 1024) {
alert('File size exceeds 10MB limit.');
return;
}
this.showUploadProgress(true);
try {
// Create FormData
const formData = new FormData();
formData.append('patient_id', this.currentPatientId);
formData.append('file', file);
// Upload and analyze document
const response = await fetch('/emr/preview-document', {
method: 'POST',
body: formData
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || 'Failed to analyze document');
}
const result = await response.json();
this.showDocumentPreview(result);
} catch (error) {
console.error('Error uploading file:', error);
alert(`Error analyzing document: ${error.message}`);
} finally {
this.showUploadProgress(false);
}
}
showUploadProgress(show) {
const uploadProgress = document.getElementById('uploadProgress');
const uploadArea = document.getElementById('uploadArea');
if (show) {
uploadProgress.style.display = 'block';
uploadArea.style.display = 'none';
} else {
uploadProgress.style.display = 'none';
uploadArea.style.display = 'block';
}
}
showDocumentPreview(analysisResult) {
const modal = document.getElementById('documentPreviewModal');
const content = document.getElementById('documentPreviewContent');
// Store the analysis result for saving
this.currentDocumentAnalysis = analysisResult;
content.innerHTML = this.renderDocumentPreview(analysisResult);
modal.classList.add('show');
}
renderDocumentPreview(data) {
const { filename, confidence_score, extracted_data } = data;
return `
Document Information
Filename: ${filename}
Confidence Score: ${Math.round(confidence_score * 100)}%
${extracted_data.overview ? `
Overview
` : ''}
Medications
${(extracted_data.medications || []).map((med, index) => `
Medication ${index + 1}
`).join('')}
${extracted_data.vital_signs ? `
` : ''}
Lab Results
${(extracted_data.lab_results || []).map((lab, index) => `
Lab Test ${index + 1}
`).join('')}
Notes
`;
}
addDiagnosis() {
const list = document.getElementById('diagnosisList');
const li = document.createElement('li');
li.innerHTML = `
`;
list.appendChild(li);
}
addSymptom() {
const list = document.getElementById('symptomsList');
const li = document.createElement('li');
li.innerHTML = `
`;
list.appendChild(li);
}
addMedication() {
const list = document.getElementById('medicationsList');
const index = list.children.length;
const div = document.createElement('div');
div.className = 'medication-preview-item';
div.innerHTML = `
Medication ${index + 1}
`;
list.appendChild(div);
}
addLabResult() {
const list = document.getElementById('labResultsList');
const index = list.children.length;
const div = document.createElement('div');
div.className = 'lab-result-preview-item';
div.innerHTML = `
Lab Test ${index + 1}
`;
list.appendChild(div);
}
addProcedure() {
const list = document.getElementById('proceduresList');
const li = document.createElement('li');
li.innerHTML = `
`;
list.appendChild(li);
}
removeListItem(button) {
button.parentElement.remove();
}
removeMedication(button) {
button.parentElement.remove();
}
removeLabResult(button) {
button.parentElement.remove();
}
async saveDocumentAnalysis() {
if (!this.currentDocumentAnalysis) {
alert('No document analysis to save');
return;
}
try {
// Collect all the edited data
const extractedData = this.collectEditedData();
const formData = new FormData();
formData.append('patient_id', this.currentPatientId);
formData.append('filename', this.currentDocumentAnalysis.filename);
formData.append('extracted_data', JSON.stringify(extractedData));
formData.append('confidence_score', this.currentDocumentAnalysis.confidence_score);
const response = await fetch('/emr/save-document-analysis', {
method: 'POST',
body: formData
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || 'Failed to save document analysis');
}
const result = await response.json();
// Close modal and refresh EMR data
document.getElementById('documentPreviewModal').classList.remove('show');
this.loadEMRData();
this.loadPatientStats();
alert('Document analysis saved successfully!');
} catch (error) {
console.error('Error saving document analysis:', error);
alert(`Error saving document analysis: ${error.message}`);
}
}
collectEditedData() {
const data = {
overview: document.getElementById('overviewField')?.value || '',
diagnosis: Array.from(document.querySelectorAll('.diagnosis-input')).map(input => input.value).filter(val => val.trim()),
symptoms: Array.from(document.querySelectorAll('.symptom-input')).map(input => input.value).filter(val => val.trim()),
medications: Array.from(document.querySelectorAll('.medication-preview-item')).map(item => ({
name: item.querySelector('.med-name-input')?.value || '',
dosage: item.querySelector('.med-dosage-input')?.value || '',
frequency: item.querySelector('.med-frequency-input')?.value || '',
duration: item.querySelector('.med-duration-input')?.value || ''
})).filter(med => med.name.trim()),
vital_signs: {
blood_pressure: document.getElementById('bpInput')?.value || null,
heart_rate: document.getElementById('hrInput')?.value || null,
temperature: document.getElementById('tempInput')?.value || null,
respiratory_rate: document.getElementById('rrInput')?.value || null,
oxygen_saturation: document.getElementById('o2Input')?.value || null
},
lab_results: Array.from(document.querySelectorAll('.lab-result-preview-item')).map(item => ({
test_name: item.querySelector('.lab-name-input')?.value || '',
value: item.querySelector('.lab-value-input')?.value || '',
unit: item.querySelector('.lab-unit-input')?.value || '',
reference_range: item.querySelector('.lab-range-input')?.value || ''
})).filter(lab => lab.test_name.trim()),
procedures: Array.from(document.querySelectorAll('.procedure-input')).map(input => input.value).filter(val => val.trim()),
notes: document.getElementById('notesField')?.value || ''
};
// Clean up empty vital signs
if (Object.values(data.vital_signs).every(val => !val)) {
data.vital_signs = null;
}
return data;
}
}
// Initialize the EMR page when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
window.emrPage = new EMRPage();
});