724 lines
34 KiB
HTML
724 lines
34 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Report Generation - Radiology{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="content">
|
|
<div class="container-fluid">
|
|
<!-- Page Header -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="page-header">
|
|
<div class="page-title">
|
|
<h4>Radiology Report Generation</h4>
|
|
<h6>Create, edit, and manage radiology reports with AI assistance</h6>
|
|
</div>
|
|
<div class="page-btn">
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-primary" onclick="createNewReport()">
|
|
<i class="fa fa-plus"></i> New Report
|
|
</button>
|
|
<button type="button" class="btn btn-info" onclick="loadTemplates()">
|
|
<i class="fa fa-clipboard-list"></i> Templates
|
|
</button>
|
|
<button type="button" class="btn btn-success" onclick="aiAssist()">
|
|
<i class="fa fa-robot"></i> AI Assist
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Study Information -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Study Information</h5>
|
|
<div class="card-tools">
|
|
<button type="button" class="btn btn-sm btn-outline-primary" onclick="viewImages()">
|
|
<i class="fa fa-images"></i> View Images
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-outline-info" onclick="viewPriorStudies()">
|
|
<i class="fa fa-history"></i> Prior Studies
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-3">
|
|
<h6>Patient Information</h6>
|
|
<p><strong>Name:</strong> {{ study.patient_name|default:"John Smith" }}</p>
|
|
<p><strong>MRN:</strong> {{ study.patient_mrn|default:"123456" }}</p>
|
|
<p><strong>DOB:</strong> {{ study.patient_dob|default:"1980-05-15"|date:"M d, Y" }}</p>
|
|
<p><strong>Age:</strong> {{ study.patient_age|default:"43" }} years</p>
|
|
<p><strong>Sex:</strong> {{ study.patient_sex|default:"Male" }}</p>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<h6>Study Details</h6>
|
|
<p><strong>Study Date:</strong> {{ study.study_date|default:"Jan 15, 2024"|date:"M d, Y" }}</p>
|
|
<p><strong>Study Time:</strong> {{ study.study_time|default:"14:30" }}</p>
|
|
<p><strong>Modality:</strong> {{ study.modality|default:"CT" }}</p>
|
|
<p><strong>Body Part:</strong> {{ study.body_part|default:"Chest" }}</p>
|
|
<p><strong>Protocol:</strong> {{ study.protocol|default:"Chest CT with Contrast" }}</p>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<h6>Order Information</h6>
|
|
<p><strong>Accession #:</strong> {{ study.accession_number|default:"ACC123456" }}</p>
|
|
<p><strong>Order ID:</strong> {{ study.order_id|default:"RAD-2024-001" }}</p>
|
|
<p><strong>Referring Physician:</strong> {{ study.referring_physician|default:"Dr. Johnson" }}</p>
|
|
<p><strong>Priority:</strong> <span class="badge bg-warning">{{ study.priority|default:"Urgent" }}</span></p>
|
|
<p><strong>Clinical Indication:</strong> {{ study.clinical_indication|default:"Chest pain, rule out PE" }}</p>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<h6>Report Status</h6>
|
|
<p><strong>Status:</strong> <span class="badge bg-warning">{{ report.status|default:"In Progress" }}</span></p>
|
|
<p><strong>Radiologist:</strong> {{ report.radiologist|default:"Dr. Smith" }}</p>
|
|
<p><strong>Started:</strong> {{ report.started_at|default:"Jan 15, 2024 15:00" }}</p>
|
|
<p><strong>Last Modified:</strong> {{ report.modified_at|default:"Jan 15, 2024 15:30" }}</p>
|
|
<p><strong>Report ID:</strong> {{ report.report_id|default:"RPT-2024-001" }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Report Editor -->
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Report Editor</h5>
|
|
<div class="card-tools">
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-sm btn-outline-primary" onclick="insertTemplate('technique')">
|
|
<i class="fa fa-cog"></i> Technique
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" onclick="insertTemplate('findings')">
|
|
<i class="fa fa-search"></i> Findings
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" onclick="insertTemplate('impression')">
|
|
<i class="fa fa-lightbulb"></i> Impression
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-outline-success" onclick="spellCheck()">
|
|
<i class="fa fa-spell-check"></i> Spell Check
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<form id="reportForm">
|
|
<div class="mb-3">
|
|
<label class="form-label"><strong>TECHNIQUE:</strong></label>
|
|
<textarea name="technique" class="form-control" rows="3" placeholder="Describe the imaging technique used...">{{ report.technique|default:"Axial CT images of the chest were obtained following the administration of intravenous contrast material." }}</textarea>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label"><strong>COMPARISON:</strong></label>
|
|
<textarea name="comparison" class="form-control" rows="2" placeholder="Compare with prior studies if available...">{{ report.comparison|default:"No prior chest CT available for comparison." }}</textarea>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label"><strong>FINDINGS:</strong></label>
|
|
<textarea name="findings" class="form-control" rows="8" placeholder="Describe detailed findings...">{{ report.findings|default:"LUNGS: The lungs are clear bilaterally without evidence of consolidation, pleural effusion, or pneumothorax. No pulmonary nodules or masses are identified.\n\nHEART: The heart is normal in size and configuration. No pericardial effusion.\n\nMEDIASTINUM: The mediastinal structures appear normal. No lymphadenopathy.\n\nBONES: No acute osseous abnormalities." }}</textarea>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label"><strong>IMPRESSION:</strong></label>
|
|
<textarea name="impression" class="form-control" rows="4" placeholder="Provide clinical impression and recommendations...">{{ report.impression|default:"1. Normal chest CT.\n2. No evidence of pulmonary embolism.\n3. No acute cardiopulmonary abnormalities." }}</textarea>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Report Status</label>
|
|
<select name="report_status" class="form-select">
|
|
<option value="draft">Draft</option>
|
|
<option value="preliminary" selected>Preliminary</option>
|
|
<option value="final">Final</option>
|
|
<option value="amended">Amended</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Urgency</label>
|
|
<select name="urgency" class="form-select">
|
|
<option value="routine">Routine</option>
|
|
<option value="urgent" selected>Urgent</option>
|
|
<option value="stat">STAT</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="critical_result" id="criticalResult">
|
|
<label class="form-check-label" for="criticalResult">
|
|
This is a critical result requiring immediate notification
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3" id="criticalNotificationPanel" style="display: none;">
|
|
<label class="form-label">Critical Result Notification</label>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<input type="text" name="notification_recipient" class="form-control" placeholder="Physician to notify">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<input type="tel" name="notification_phone" class="form-control" placeholder="Phone number">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tools and Templates -->
|
|
<div class="col-md-4">
|
|
<!-- AI Assistant -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h6 class="card-title">AI Assistant</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="ai-suggestions mb-3">
|
|
<h6>Suggested Findings</h6>
|
|
<div class="suggestion-item mb-2">
|
|
<small class="text-muted">Based on image analysis:</small>
|
|
<p class="mb-1">"No acute cardiopulmonary abnormalities"</p>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="insertSuggestion(1)">
|
|
<i class="fa fa-plus"></i> Insert
|
|
</button>
|
|
</div>
|
|
<div class="suggestion-item mb-2">
|
|
<small class="text-muted">Common for this study type:</small>
|
|
<p class="mb-1">"Lungs are clear bilaterally"</p>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="insertSuggestion(2)">
|
|
<i class="fa fa-plus"></i> Insert
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ai-actions">
|
|
<button class="btn btn-sm btn-outline-success w-100 mb-2" onclick="generateDraft()">
|
|
<i class="fa fa-magic"></i> Generate Draft Report
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-info w-100 mb-2" onclick="improveLanguage()">
|
|
<i class="fa fa-language"></i> Improve Language
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-warning w-100" onclick="checkConsistency()">
|
|
<i class="fa fa-check-double"></i> Check Consistency
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick Templates -->
|
|
<div class="card mt-3">
|
|
<div class="card-header">
|
|
<h6 class="card-title">Quick Templates</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="template-buttons">
|
|
<button class="btn btn-sm btn-outline-secondary w-100 mb-2" onclick="loadTemplate('normal_chest_ct')">
|
|
Normal Chest CT
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-secondary w-100 mb-2" onclick="loadTemplate('pe_protocol')">
|
|
PE Protocol
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-secondary w-100 mb-2" onclick="loadTemplate('trauma_chest')">
|
|
Trauma Chest
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-secondary w-100 mb-2" onclick="loadTemplate('lung_nodule')">
|
|
Lung Nodule Follow-up
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-secondary w-100 mb-2" onclick="loadTemplate('pneumonia')">
|
|
Pneumonia
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-primary w-100" onclick="manageTemplates()">
|
|
<i class="fa fa-cog"></i> Manage Templates
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Measurements -->
|
|
<div class="card mt-3">
|
|
<div class="card-header">
|
|
<h6 class="card-title">Measurements</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="measurements-list">
|
|
<div class="measurement-item mb-2">
|
|
<small class="text-muted">Nodule diameter:</small>
|
|
<p class="mb-1"><strong>8.5 mm</strong></p>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="insertMeasurement(1)">
|
|
<i class="fa fa-plus"></i> Insert
|
|
</button>
|
|
</div>
|
|
<div class="measurement-item mb-2">
|
|
<small class="text-muted">Cardiac width:</small>
|
|
<p class="mb-1"><strong>12.3 cm</strong></p>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="insertMeasurement(2)">
|
|
<i class="fa fa-plus"></i> Insert
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<button class="btn btn-sm btn-outline-info w-100" onclick="viewAllMeasurements()">
|
|
<i class="fa fa-ruler"></i> View All Measurements
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Voice Recognition -->
|
|
<div class="card mt-3">
|
|
<div class="card-header">
|
|
<h6 class="card-title">Voice Dictation</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="voice-controls text-center">
|
|
<button class="btn btn-outline-danger mb-2" id="voiceBtn" onclick="toggleVoiceRecognition()">
|
|
<i class="fa fa-microphone"></i> Start Dictation
|
|
</button>
|
|
<div class="voice-status">
|
|
<small class="text-muted">Click to start voice dictation</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Report Actions -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div class="report-actions">
|
|
<button type="button" class="btn btn-outline-secondary" onclick="saveDraft()">
|
|
<i class="fa fa-save"></i> Save Draft
|
|
</button>
|
|
<button type="button" class="btn btn-outline-info" onclick="previewReport()">
|
|
<i class="fa fa-eye"></i> Preview
|
|
</button>
|
|
<button type="button" class="btn btn-outline-warning" onclick="sendForReview()">
|
|
<i class="fa fa-user-check"></i> Send for Review
|
|
</button>
|
|
</div>
|
|
<div class="final-actions">
|
|
<button type="button" class="btn btn-success" onclick="signReport()">
|
|
<i class="fa fa-signature"></i> Sign & Finalize
|
|
</button>
|
|
<button type="button" class="btn btn-primary" onclick="sendReport()">
|
|
<i class="fa fa-paper-plane"></i> Send Report
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Report History -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Report History & Versions</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Version</th>
|
|
<th>Status</th>
|
|
<th>Modified By</th>
|
|
<th>Date/Time</th>
|
|
<th>Changes</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>v1.2</strong></td>
|
|
<td><span class="badge bg-warning">Current</span></td>
|
|
<td>Dr. Smith</td>
|
|
<td>Jan 15, 2024 15:30</td>
|
|
<td>Updated impression section</td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewVersion('1.2')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>v1.1</td>
|
|
<td><span class="badge bg-secondary">Previous</span></td>
|
|
<td>Dr. Smith</td>
|
|
<td>Jan 15, 2024 15:15</td>
|
|
<td>Added measurements</td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewVersion('1.1')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-warning" onclick="restoreVersion('1.1')">
|
|
<i class="fa fa-undo"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>v1.0</td>
|
|
<td><span class="badge bg-secondary">Previous</span></td>
|
|
<td>Dr. Smith</td>
|
|
<td>Jan 15, 2024 15:00</td>
|
|
<td>Initial draft</td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewVersion('1.0')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-warning" onclick="restoreVersion('1.0')">
|
|
<i class="fa fa-undo"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let isVoiceRecognitionActive = false;
|
|
let recognition;
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Initialize voice recognition if available
|
|
if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) {
|
|
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
recognition = new SpeechRecognition();
|
|
recognition.continuous = true;
|
|
recognition.interimResults = true;
|
|
|
|
recognition.onresult = function(event) {
|
|
let finalTranscript = '';
|
|
for (let i = event.resultIndex; i < event.results.length; i++) {
|
|
if (event.results[i].isFinal) {
|
|
finalTranscript += event.results[i][0].transcript;
|
|
}
|
|
}
|
|
|
|
if (finalTranscript) {
|
|
insertTextAtCursor(finalTranscript);
|
|
}
|
|
};
|
|
}
|
|
|
|
// Critical result checkbox handler
|
|
document.getElementById('criticalResult').addEventListener('change', function() {
|
|
const panel = document.getElementById('criticalNotificationPanel');
|
|
panel.style.display = this.checked ? 'block' : 'none';
|
|
});
|
|
|
|
// Auto-save functionality
|
|
setInterval(autoSave, 30000); // Auto-save every 30 seconds
|
|
});
|
|
|
|
function createNewReport() {
|
|
if (confirm('Create a new report? Any unsaved changes will be lost.')) {
|
|
document.getElementById('reportForm').reset();
|
|
console.log('New report created');
|
|
alert('New report created. You can now start dictating or typing.');
|
|
}
|
|
}
|
|
|
|
function loadTemplates() {
|
|
console.log('Loading report templates...');
|
|
alert('Report template library would be displayed here.');
|
|
}
|
|
|
|
function aiAssist() {
|
|
console.log('Opening AI assistant...');
|
|
alert('AI assistant panel is now active. It will provide suggestions as you type.');
|
|
}
|
|
|
|
function viewImages() {
|
|
console.log('Opening image viewer...');
|
|
alert('DICOM image viewer would open here.');
|
|
}
|
|
|
|
function viewPriorStudies() {
|
|
console.log('Loading prior studies...');
|
|
alert('Prior studies comparison would be displayed here.');
|
|
}
|
|
|
|
function insertTemplate(section) {
|
|
const templates = {
|
|
'technique': 'Axial CT images of the chest were obtained following the administration of intravenous contrast material.',
|
|
'findings': 'LUNGS: The lungs are clear bilaterally without evidence of consolidation, pleural effusion, or pneumothorax.\n\nHEART: The heart is normal in size and configuration.\n\nMEDIASTINUM: The mediastinal structures appear normal.',
|
|
'impression': '1. Normal chest CT.\n2. No acute cardiopulmonary abnormalities.'
|
|
};
|
|
|
|
const template = templates[section];
|
|
if (template) {
|
|
const textarea = document.querySelector(`textarea[name="${section}"]`);
|
|
if (textarea) {
|
|
textarea.value = template;
|
|
console.log(`Inserted ${section} template`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function spellCheck() {
|
|
console.log('Running spell check...');
|
|
alert('Spell check completed. No errors found.');
|
|
}
|
|
|
|
function insertSuggestion(suggestionId) {
|
|
const suggestions = {
|
|
1: 'No acute cardiopulmonary abnormalities.',
|
|
2: 'Lungs are clear bilaterally.'
|
|
};
|
|
|
|
const suggestion = suggestions[suggestionId];
|
|
if (suggestion) {
|
|
insertTextAtCursor(suggestion);
|
|
console.log(`Inserted suggestion: ${suggestion}`);
|
|
}
|
|
}
|
|
|
|
function generateDraft() {
|
|
console.log('Generating AI draft report...');
|
|
alert('AI is generating a draft report based on the images and clinical indication. This may take a few moments.');
|
|
}
|
|
|
|
function improveLanguage() {
|
|
console.log('Improving report language...');
|
|
alert('AI has reviewed and improved the language and clarity of your report.');
|
|
}
|
|
|
|
function checkConsistency() {
|
|
console.log('Checking report consistency...');
|
|
alert('Report consistency check completed. All sections are consistent.');
|
|
}
|
|
|
|
function loadTemplate(templateName) {
|
|
const templates = {
|
|
'normal_chest_ct': {
|
|
technique: 'Axial CT images of the chest were obtained following the administration of intravenous contrast material.',
|
|
findings: 'LUNGS: The lungs are clear bilaterally without evidence of consolidation, pleural effusion, or pneumothorax. No pulmonary nodules or masses are identified.\n\nHEART: The heart is normal in size and configuration. No pericardial effusion.\n\nMEDIASTINUM: The mediastinal structures appear normal. No lymphadenopathy.',
|
|
impression: '1. Normal chest CT.\n2. No acute cardiopulmonary abnormalities.'
|
|
}
|
|
};
|
|
|
|
const template = templates[templateName];
|
|
if (template) {
|
|
Object.keys(template).forEach(field => {
|
|
const textarea = document.querySelector(`textarea[name="${field}"]`);
|
|
if (textarea) {
|
|
textarea.value = template[field];
|
|
}
|
|
});
|
|
console.log(`Loaded template: ${templateName}`);
|
|
alert(`Template "${templateName}" loaded successfully.`);
|
|
}
|
|
}
|
|
|
|
function manageTemplates() {
|
|
console.log('Opening template manager...');
|
|
alert('Template management interface would open here.');
|
|
}
|
|
|
|
function insertMeasurement(measurementId) {
|
|
const measurements = {
|
|
1: 'There is a 8.5 mm nodule in the right upper lobe.',
|
|
2: 'The cardiac silhouette measures 12.3 cm in width.'
|
|
};
|
|
|
|
const measurement = measurements[measurementId];
|
|
if (measurement) {
|
|
insertTextAtCursor(measurement);
|
|
console.log(`Inserted measurement: ${measurement}`);
|
|
}
|
|
}
|
|
|
|
function viewAllMeasurements() {
|
|
console.log('Viewing all measurements...');
|
|
alert('Complete measurements list would be displayed here.');
|
|
}
|
|
|
|
function toggleVoiceRecognition() {
|
|
const voiceBtn = document.getElementById('voiceBtn');
|
|
|
|
if (!recognition) {
|
|
alert('Voice recognition is not supported in this browser.');
|
|
return;
|
|
}
|
|
|
|
if (isVoiceRecognitionActive) {
|
|
recognition.stop();
|
|
voiceBtn.innerHTML = '<i class="fa fa-microphone"></i> Start Dictation';
|
|
voiceBtn.classList.remove('btn-danger');
|
|
voiceBtn.classList.add('btn-outline-danger');
|
|
isVoiceRecognitionActive = false;
|
|
console.log('Voice recognition stopped');
|
|
} else {
|
|
recognition.start();
|
|
voiceBtn.innerHTML = '<i class="fa fa-stop"></i> Stop Dictation';
|
|
voiceBtn.classList.remove('btn-outline-danger');
|
|
voiceBtn.classList.add('btn-danger');
|
|
isVoiceRecognitionActive = true;
|
|
console.log('Voice recognition started');
|
|
}
|
|
}
|
|
|
|
function insertTextAtCursor(text) {
|
|
const activeElement = document.activeElement;
|
|
if (activeElement && activeElement.tagName === 'TEXTAREA') {
|
|
const start = activeElement.selectionStart;
|
|
const end = activeElement.selectionEnd;
|
|
const value = activeElement.value;
|
|
|
|
activeElement.value = value.substring(0, start) + text + value.substring(end);
|
|
activeElement.selectionStart = activeElement.selectionEnd = start + text.length;
|
|
activeElement.focus();
|
|
}
|
|
}
|
|
|
|
function saveDraft() {
|
|
console.log('Saving draft report...');
|
|
alert('Report draft saved successfully.');
|
|
autoSave();
|
|
}
|
|
|
|
function autoSave() {
|
|
const formData = new FormData(document.getElementById('reportForm'));
|
|
console.log('Auto-saving report...', Object.fromEntries(formData));
|
|
// In real implementation, this would save to the server
|
|
}
|
|
|
|
function previewReport() {
|
|
console.log('Generating report preview...');
|
|
alert('Report preview would be displayed in a new window.');
|
|
}
|
|
|
|
function sendForReview() {
|
|
const reviewer = prompt('Send report for review to:\n1. Senior Radiologist\n2. Department Head\n3. Attending Physician\n\nEnter number:');
|
|
|
|
if (reviewer && ['1', '2', '3'].includes(reviewer)) {
|
|
const reviewers = {
|
|
'1': 'Senior Radiologist',
|
|
'2': 'Department Head',
|
|
'3': 'Attending Physician'
|
|
};
|
|
|
|
console.log(`Sending report for review to: ${reviewers[reviewer]}`);
|
|
alert(`Report sent for review to: ${reviewers[reviewer]}`);
|
|
}
|
|
}
|
|
|
|
function signReport() {
|
|
if (confirm('Sign and finalize this report? This action cannot be undone.')) {
|
|
console.log('Signing and finalizing report...');
|
|
alert('Report has been signed and finalized. It will be sent to the referring physician.');
|
|
}
|
|
}
|
|
|
|
function sendReport() {
|
|
const method = prompt('Send report via:\n1. Electronic delivery\n2. Fax\n3. Print and mail\n4. Secure email\n\nEnter number:');
|
|
|
|
if (method && ['1', '2', '3', '4'].includes(method)) {
|
|
const methods = {
|
|
'1': 'Electronic delivery',
|
|
'2': 'Fax',
|
|
'3': 'Print and mail',
|
|
'4': 'Secure email'
|
|
};
|
|
|
|
console.log(`Sending report via: ${methods[method]}`);
|
|
alert(`Report sent via ${methods[method]} to the referring physician.`);
|
|
}
|
|
}
|
|
|
|
function viewVersion(version) {
|
|
console.log(`Viewing report version: ${version}`);
|
|
alert(`Report version ${version} would be displayed here.`);
|
|
}
|
|
|
|
function restoreVersion(version) {
|
|
if (confirm(`Restore to version ${version}? Current changes will be lost.`)) {
|
|
console.log(`Restoring to version: ${version}`);
|
|
alert(`Report restored to version ${version}.`);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.suggestion-item, .measurement-item {
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 4px;
|
|
padding: 8px;
|
|
background-color: #f8f9fa;
|
|
}
|
|
|
|
.template-buttons .btn {
|
|
text-align: left;
|
|
}
|
|
|
|
.voice-controls {
|
|
padding: 1rem 0;
|
|
}
|
|
|
|
.voice-status {
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
.report-actions .btn {
|
|
margin-right: 0.5rem;
|
|
}
|
|
|
|
.final-actions .btn {
|
|
margin-left: 0.5rem;
|
|
}
|
|
|
|
textarea {
|
|
font-family: 'Courier New', monospace;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.card-tools {
|
|
margin-left: auto;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.report-actions, .final-actions {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.report-actions .btn, .final-actions .btn {
|
|
margin: 0;
|
|
}
|
|
|
|
.d-flex.justify-content-between {
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|