hospital-management/templates/emr/encounter_create.html
2025-08-12 13:33:25 +03:00

857 lines
41 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Create Encounter{% endblock %}
{% block content %}
<div id="content" class="app-content">
<div class="container">
<ul class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'emr:dashboard' %}">EMR</a></li>
<li class="breadcrumb-item active">Create Encounter</li>
</ul>
<div class="row align-items-center mb-3">
<div class="col">
<h1 class="page-header">Create New Encounter</h1>
<p class="text-muted">Document a new patient encounter or visit</p>
</div>
<div class="col-auto">
<a href="{% url 'emr:encounter_list' %}" class="btn btn-outline-secondary">
<i class="fa fa-arrow-left me-2"></i>Back to Encounters
</a>
</div>
</div>
<!-- Patient Selection -->
{% if not patient %}
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Select Patient</h4>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-8">
<div class="input-group">
<input type="text" id="patientSearch" class="form-control" placeholder="Search by name, ID, or phone number...">
<button class="btn btn-outline-secondary" type="button" onclick="searchPatients()">
<i class="fa fa-search"></i>
</button>
</div>
<div id="patientSearchResults" class="mt-2" style="display: none;">
<!-- Search results will appear here -->
</div>
</div>
<div class="col-md-4">
<a href="{% url 'patients:patient_registration' %}?return_url={% url 'emr:encounter_create' %}" class="btn btn-primary">
<i class="fa fa-plus me-2"></i>New Patient
</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Encounter Form -->
<form id="encounterForm" method="post">
{% csrf_token %}
<!-- Patient Information (if selected) -->
{% if patient %}
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Patient Information</h4>
<div class="card-tools">
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="changePatient()">
<i class="fa fa-edit me-1"></i>Change Patient
</button>
</div>
</div>
<div class="card-body">
<input type="hidden" name="patient" value="{{ patient.patient_id }}">
<div class="row">
<div class="col-md-3">
<strong>{{ patient.first_name }} {{ patient.last_name }}</strong><br>
<small class="text-muted">ID: {{ patient.patient_id }}</small>
</div>
<div class="col-md-3">
<strong>DOB:</strong> {{ patient.date_of_birth|date:"M d, Y" }}<br>
<small class="text-muted">Age: {{ patient.age }}</small>
</div>
<div class="col-md-3">
<strong>Gender:</strong> {{ patient.get_gender_display }}<br>
<small class="text-muted">{{ patient.phone_primary }}</small>
</div>
<div class="col-md-3">
<a href="{% url 'patients:patient_detail' patient.patient_id %}" class="btn btn-outline-primary btn-sm">
<i class="fa fa-eye me-1"></i>View Profile
</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Encounter Details -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Encounter Details</h4>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Encounter Type <span class="text-danger">*</span></label>
<select name="encounter_type" class="form-select" required>
<option value="">Select encounter type...</option>
<option value="office_visit">Office Visit</option>
<option value="emergency">Emergency</option>
<option value="inpatient">Inpatient</option>
<option value="outpatient">Outpatient</option>
<option value="consultation">Consultation</option>
<option value="follow_up">Follow-up</option>
<option value="preventive">Preventive Care</option>
<option value="procedure">Procedure</option>
<option value="telemedicine">Telemedicine</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Priority</label>
<select name="priority" class="form-select">
<option value="routine">Routine</option>
<option value="urgent">Urgent</option>
<option value="emergent">Emergent</option>
<option value="stat">STAT</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Encounter Date <span class="text-danger">*</span></label>
<input type="datetime-local" name="encounter_date" class="form-control" value="{{ current_datetime }}" required>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Department</label>
<select name="department" class="form-select">
<option value="">Select department...</option>
{% for dept in departments %}
<option value="{{ dept.id }}">{{ dept.name }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Provider <span class="text-danger">*</span></label>
<select name="provider" class="form-select" required>
<option value="">Select provider...</option>
{% for provider in providers %}
<option value="{{ provider.id }}" {% if provider.id == request.user.id %}selected{% endif %}>
{{ provider.get_full_name }} - {{ provider.title }}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Location</label>
<select name="location" class="form-select">
<option value="">Select location...</option>
{% for location in locations %}
<option value="{{ location.id }}">{{ location.name }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Chief Complaint & History -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Chief Complaint & History</h4>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">Chief Complaint <span class="text-danger">*</span></label>
<textarea name="chief_complaint" class="form-control" rows="3" placeholder="Describe the patient's primary concern or reason for visit..." required></textarea>
</div>
<div class="mb-3">
<label class="form-label">History of Present Illness (HPI)</label>
<textarea name="history_present_illness" class="form-control" rows="4" placeholder="Detailed description of the current illness or condition..."></textarea>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Review of Systems</label>
<textarea name="review_of_systems" class="form-control" rows="3" placeholder="Systematic review of body systems..."></textarea>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Past Medical History</label>
<textarea name="past_medical_history" class="form-control" rows="3" placeholder="Relevant past medical history..."></textarea>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Vital Signs -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Vital Signs</h4>
<div class="card-tools">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="loadPreviousVitals()">
<i class="fa fa-history me-1"></i>Load Previous
</button>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Blood Pressure</label>
<div class="input-group">
<input type="number" name="systolic_bp" class="form-control" placeholder="Systolic">
<span class="input-group-text">/</span>
<input type="number" name="diastolic_bp" class="form-control" placeholder="Diastolic">
<span class="input-group-text">mmHg</span>
</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Heart Rate</label>
<div class="input-group">
<input type="number" name="heart_rate" class="form-control" placeholder="HR">
<span class="input-group-text">bpm</span>
</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Temperature</label>
<div class="input-group">
<input type="number" name="temperature" class="form-control" step="0.1" placeholder="Temp">
<select name="temp_unit" class="form-select" style="max-width: 80px;">
<option value="F">°F</option>
<option value="C">°C</option>
</select>
</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Respiratory Rate</label>
<div class="input-group">
<input type="number" name="respiratory_rate" class="form-control" placeholder="RR">
<span class="input-group-text">rpm</span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Oxygen Saturation</label>
<div class="input-group">
<input type="number" name="oxygen_saturation" class="form-control" placeholder="O2 Sat">
<span class="input-group-text">%</span>
</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Weight</label>
<div class="input-group">
<input type="number" name="weight" class="form-control" step="0.1" placeholder="Weight">
<select name="weight_unit" class="form-select" style="max-width: 80px;">
<option value="lbs">lbs</option>
<option value="kg">kg</option>
</select>
</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Height</label>
<div class="input-group">
<input type="number" name="height" class="form-control" step="0.1" placeholder="Height">
<select name="height_unit" class="form-select" style="max-width: 80px;">
<option value="in">in</option>
<option value="cm">cm</option>
</select>
</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">BMI</label>
<div class="input-group">
<input type="number" name="bmi" class="form-control" step="0.1" placeholder="BMI" readonly>
<span class="input-group-text">kg/m²</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Physical Examination -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Physical Examination</h4>
<div class="card-tools">
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="useTemplate()">
<i class="fa fa-file-text me-1"></i>Use Template
</button>
</div>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">General Appearance</label>
<textarea name="general_appearance" class="form-control" rows="2" placeholder="Overall appearance and demeanor..."></textarea>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">HEENT (Head, Eyes, Ears, Nose, Throat)</label>
<textarea name="heent" class="form-control" rows="3" placeholder="Head, eyes, ears, nose, throat examination..."></textarea>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Cardiovascular</label>
<textarea name="cardiovascular" class="form-control" rows="3" placeholder="Heart and vascular examination..."></textarea>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Respiratory</label>
<textarea name="respiratory" class="form-control" rows="3" placeholder="Lung and breathing examination..."></textarea>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Abdomen</label>
<textarea name="abdomen" class="form-control" rows="3" placeholder="Abdominal examination..."></textarea>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Musculoskeletal</label>
<textarea name="musculoskeletal" class="form-control" rows="3" placeholder="Musculoskeletal examination..."></textarea>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Neurological</label>
<textarea name="neurological" class="form-control" rows="3" placeholder="Neurological examination..."></textarea>
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Skin</label>
<textarea name="skin" class="form-control" rows="2" placeholder="Skin examination..."></textarea>
</div>
</div>
</div>
</div>
</div>
<!-- Assessment & Plan -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Assessment & Plan</h4>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">Assessment <span class="text-danger">*</span></label>
<textarea name="assessment" class="form-control" rows="4" placeholder="Clinical assessment and impression..." required></textarea>
</div>
<div class="mb-3">
<label class="form-label">Plan</label>
<textarea name="plan" class="form-control" rows="4" placeholder="Treatment plan and next steps..."></textarea>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Follow-up Instructions</label>
<textarea name="followup_instructions" class="form-control" rows="3" placeholder="Instructions for patient follow-up..."></textarea>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Patient Education</label>
<textarea name="patient_education" class="form-control" rows="3" placeholder="Education provided to patient..."></textarea>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Additional Information -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Additional Information</h4>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Encounter Status</label>
<select name="status" class="form-select">
<option value="in_progress">In Progress</option>
<option value="completed">Completed</option>
<option value="cancelled">Cancelled</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Duration (minutes)</label>
<input type="number" name="duration" class="form-control" placeholder="Encounter duration">
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Additional Notes</label>
<textarea name="additional_notes" class="form-control" rows="3" placeholder="Any additional notes or observations..."></textarea>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="requires_followup">
<label class="form-check-label">
Requires follow-up appointment
</label>
</div>
</div>
</div>
</div>
</div>
<!-- Form Actions -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<button type="button" class="btn btn-outline-secondary" onclick="saveDraft()">
<i class="fa fa-save me-2"></i>Save as Draft
</button>
</div>
<div>
<a href="{% url 'emr:encounter_list' %}" class="btn btn-secondary me-2">
<i class="fa fa-times me-2"></i>Cancel
</a>
<button type="submit" class="btn btn-primary">
<i class="fa fa-check me-2"></i>Create Encounter
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<!-- Patient Search Modal -->
<div class="modal fade" id="patientSearchModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Select Patient</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div id="patientSearchModalContent">
<!-- Search results will be loaded here -->
</div>
</div>
</div>
</div>
</div>
<!-- Template Selection Modal -->
<div class="modal fade" id="templateModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Select Examination Template</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="list-group">
<button type="button" class="list-group-item list-group-item-action" onclick="applyTemplate('general')">
General Physical Examination
</button>
<button type="button" class="list-group-item list-group-item-action" onclick="applyTemplate('cardiac')">
Cardiac Examination
</button>
<button type="button" class="list-group-item list-group-item-action" onclick="applyTemplate('respiratory')">
Respiratory Examination
</button>
<button type="button" class="list-group-item list-group-item-action" onclick="applyTemplate('neurological')">
Neurological Examination
</button>
<button type="button" class="list-group-item list-group-item-action" onclick="applyTemplate('pediatric')">
Pediatric Examination
</button>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script>
$(document).ready(function() {
setupEventHandlers();
calculateBMI();
});
function setupEventHandlers() {
// Patient search
$('#patientSearch').on('input', function() {
var query = $(this).val();
if (query.length >= 3) {
searchPatients(query);
} else {
$('#patientSearchResults').hide();
}
});
// BMI calculation
$('input[name="weight"], input[name="height"]').on('input', function() {
calculateBMI();
});
// Form submission
$('#encounterForm').submit(function(e) {
e.preventDefault();
submitEncounter();
});
}
function searchPatients(query = null) {
if (!query) {
query = $('#patientSearch').val();
}
if (query.length < 3) {
$('#patientSearchResults').hide();
return;
}
$.get('{% url "patients:patient_search" %}', {q: query}, function(data) {
var html = '';
if (data.patients.length === 0) {
html = '<div class="alert alert-info">No patients found matching "' + query + '"</div>';
} else {
html = '<div class="list-group">';
data.patients.forEach(function(patient) {
html += '<button type="button" class="list-group-item list-group-item-action" onclick="selectPatient(\'' + patient.patient_id + '\')">' +
'<div class="d-flex w-100 justify-content-between">' +
'<h6 class="mb-1">' + patient.first_name + ' ' + patient.last_name + '</h6>' +
'<small>' + patient.patient_id + '</small>' +
'</div>' +
'<p class="mb-1">DOB: ' + patient.date_of_birth + ' | Gender: ' + patient.gender + '</p>' +
'<small>Phone: ' + (patient.phone_primary || 'Not provided') + '</small>' +
'</button>';
});
html += '</div>';
}
$('#patientSearchResults').html(html).show();
});
}
function selectPatient(patientId) {
window.location.href = '{% url "emr:encounter_create" %}?patient_id=' + patientId;
}
function changePatient() {
$('#patientSearchModal').modal('show');
searchPatients($('#patientSearch').val());
}
function calculateBMI() {
var weight = parseFloat($('input[name="weight"]').val());
var height = parseFloat($('input[name="height"]').val());
var weightUnit = $('select[name="weight_unit"]').val();
var heightUnit = $('select[name="height_unit"]').val();
if (weight && height) {
// Convert to metric if needed
var weightKg = weightUnit === 'lbs' ? weight * 0.453592 : weight;
var heightM = heightUnit === 'in' ? height * 0.0254 : height / 100;
var bmi = weightKg / (heightM * heightM);
$('input[name="bmi"]').val(bmi.toFixed(1));
}
}
function loadPreviousVitals() {
var patientId = $('input[name="patient"]').val();
if (!patientId) {
toastr.warning('Please select a patient first');
return;
}
$.get('{% url "emr:vital_signs_list" %}', {patient_id: patientId}, function(data) {
if (data.vitals) {
$('input[name="systolic_bp"]').val(data.vitals.systolic_bp);
$('input[name="diastolic_bp"]').val(data.vitals.diastolic_bp);
$('input[name="heart_rate"]').val(data.vitals.heart_rate);
$('input[name="temperature"]').val(data.vitals.temperature);
$('input[name="respiratory_rate"]').val(data.vitals.respiratory_rate);
$('input[name="oxygen_saturation"]').val(data.vitals.oxygen_saturation);
$('input[name="weight"]').val(data.vitals.weight);
$('input[name="height"]').val(data.vitals.height);
calculateBMI();
toastr.success('Previous vitals loaded');
} else {
toastr.info('No previous vitals found');
}
});
}
function useTemplate() {
$('#templateModal').modal('show');
}
function applyTemplate(templateType) {
var templates = {
'general': {
'general_appearance': 'Patient appears well-developed, well-nourished, and in no acute distress.',
'heent': 'Head: Normocephalic, atraumatic. Eyes: PERRL, EOMI, conjunctiva clear. Ears: TMs clear bilaterally. Nose: Nares patent. Throat: Oropharynx clear.',
'cardiovascular': 'Regular rate and rhythm, no murmurs, rubs, or gallops. Peripheral pulses intact.',
'respiratory': 'Clear to auscultation bilaterally, no wheezes, rales, or rhonchi.',
'abdomen': 'Soft, non-tender, non-distended, bowel sounds present.',
'musculoskeletal': 'Full range of motion, no deformities or tenderness.',
'neurological': 'Alert and oriented x3, cranial nerves II-XII intact, motor and sensory function normal.',
'skin': 'Warm, dry, intact, no rashes or lesions.'
},
'cardiac': {
'cardiovascular': 'Heart rate regular, S1 and S2 normal, no murmurs, rubs, or gallops. Point of maximal impulse not displaced. No peripheral edema. Carotid pulses 2+ bilaterally without bruits.',
'respiratory': 'Clear to auscultation bilaterally, no signs of pulmonary edema.',
'abdomen': 'No hepatomegaly or ascites.',
'musculoskeletal': 'No clubbing or cyanosis of extremities.'
},
'respiratory': {
'respiratory': 'Inspection: Symmetric chest expansion, no use of accessory muscles. Palpation: No tenderness or crepitus. Percussion: Resonant throughout. Auscultation: Clear breath sounds bilaterally.',
'cardiovascular': 'No signs of right heart strain.',
'heent': 'No cyanosis, no nasal flaring.'
},
'neurological': {
'neurological': 'Mental status: Alert, oriented x3. Cranial nerves: II-XII intact. Motor: 5/5 strength all extremities. Sensory: Intact to light touch and vibration. Reflexes: 2+ and symmetric. Coordination: Finger-to-nose and heel-to-shin intact. Gait: Normal.',
'heent': 'PERRL, EOMI, no nystagmus, facial sensation intact.'
},
'pediatric': {
'general_appearance': 'Well-appearing child, interactive, appropriate for age.',
'heent': 'Fontanelles soft and flat (if applicable), TMs clear, throat clear.',
'cardiovascular': 'Regular rate and rhythm appropriate for age, no murmurs.',
'respiratory': 'Clear breath sounds, no retractions or nasal flaring.',
'abdomen': 'Soft, non-tender, no masses.',
'skin': 'No rashes, good color and perfusion.'
}
};
var template = templates[templateType];
if (template) {
Object.keys(template).forEach(function(field) {
$('textarea[name="' + field + '"]').val(template[field]);
});
$('#templateModal').modal('hide');
toastr.success('Template applied');
}
}
function saveDraft() {
var formData = new FormData($('#encounterForm')[0]);
formData.append('save_as_draft', 'true');
$.ajax({
url: '{% url "emr:encounter_create" %}',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data) {
if (data.success) {
toastr.success('Draft saved successfully');
} else {
toastr.error('Failed to save draft: ' + data.error);
}
},
error: function() {
toastr.error('Failed to save draft');
}
});
}
function submitEncounter() {
var formData = new FormData($('#encounterForm')[0]);
$.ajax({
url: '{% url "emr:encounter_create" %}',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data) {
if (data.success) {
toastr.success('Encounter created successfully');
window.location.href = 'encounters/${data.encounter_id}/';
} else {
toastr.error('Failed to create encounter: ' + data.error);
}
},
error: function() {
toastr.error('Failed to create encounter');
}
});
}
</script>
<style>
.card-tools {
margin-left: auto;
}
.input-group-text {
background-color: #f8f9fa;
border-color: #ced4da;
}
.form-label {
font-weight: 500;
}
.text-danger {
color: #dc3545 !important;
}
#patientSearchResults {
position: absolute;
z-index: 1000;
width: 100%;
max-height: 300px;
overflow-y: auto;
background: white;
border: 1px solid #ced4da;
border-radius: 0.375rem;
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}
.list-group-item-action:hover {
background-color: #f8f9fa;
}
textarea {
resize: vertical;
}
.btn-group-sm .btn {
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
}
.card-header h4 {
margin-bottom: 0;
}
.form-check-input:checked {
background-color: #0d6efd;
border-color: #0d6efd;
}
.modal-lg {
max-width: 800px;
}
.alert {
margin-bottom: 0;
}
</style>
{% endblock %}