570 lines
27 KiB
HTML
570 lines
27 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}Vital Signs Detail - {{ block.super }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<!-- Page Header -->
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<div>
|
|
<h1 class="h3 mb-1">
|
|
<i class="fas fa-heartbeat me-2"></i>Vital Signs Detail
|
|
</h1>
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb mb-0">
|
|
<li class="breadcrumb-item"><a href="{% url 'emr:dashboard' %}">EMR</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'emr:vital_signs_list' %}">Vital Signs</a></li>
|
|
<li class="breadcrumb-item active">{{ object.measured_datetime|date:"M d, Y H:i" }}</li>
|
|
</ol>
|
|
</nav>
|
|
</div>
|
|
<div class="btn-group">
|
|
<a href="{% url 'emr:vital_signs_list' %}" class="btn btn-outline-secondary">
|
|
<i class="fas fa-arrow-left me-2"></i>Back to List
|
|
</a>
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fas fa-cog me-2"></i>Actions
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#">
|
|
<i class="fas fa-edit me-2"></i>Edit Vital Signs
|
|
</a></li>
|
|
<li><a class="dropdown-item" href="#">
|
|
<i class="fas fa-print me-2"></i>Print Report
|
|
</a></li>
|
|
<li><a class="dropdown-item" href="#">
|
|
<i class="fas fa-download me-2"></i>Export Data
|
|
</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="#">
|
|
<i class="fas fa-trash me-2"></i>Delete Record
|
|
</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Main Content -->
|
|
<div class="col-lg-8">
|
|
<!-- Patient Information -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-user me-2"></i>Patient Information
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<dl class="row">
|
|
<dt class="col-sm-4">Patient:</dt>
|
|
<dd class="col-sm-8">
|
|
<strong>{{ object.patient.get_full_name }}</strong><br>
|
|
<small class="text-muted">MRN: {{ object.patient.mrn }}</small>
|
|
</dd>
|
|
|
|
<dt class="col-sm-4">Date of Birth:</dt>
|
|
<dd class="col-sm-8">{{ object.patient.date_of_birth|date:"M d, Y" }}</dd>
|
|
|
|
<dt class="col-sm-4">Age:</dt>
|
|
<dd class="col-sm-8">{{ object.patient.age }} years</dd>
|
|
</dl>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<dl class="row">
|
|
<dt class="col-sm-4">Measured:</dt>
|
|
<dd class="col-sm-8">{{ object.measured_datetime|date:"M d, Y H:i" }}</dd>
|
|
|
|
<dt class="col-sm-4">Measured By:</dt>
|
|
<dd class="col-sm-8">{{ object.measured_by.get_full_name|default:"Not specified" }}</dd>
|
|
|
|
{% if object.encounter %}
|
|
<dt class="col-sm-4">Encounter:</dt>
|
|
<dd class="col-sm-8">
|
|
<a href="{% url 'emr:encounter_detail' object.encounter.pk %}">
|
|
{{ object.encounter.encounter_id|truncatechars:8 }}
|
|
</a>
|
|
</dd>
|
|
{% endif %}
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Vital Signs Measurements -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-chart-line me-2"></i>Measurements
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<!-- Blood Pressure -->
|
|
{% if object.systolic_bp or object.diastolic_bp %}
|
|
<div class="col-md-6 mb-4">
|
|
<div class="card border-primary">
|
|
<div class="card-header bg-primary text-white">
|
|
<h6 class="mb-0">
|
|
<i class="fas fa-heart me-2"></i>Blood Pressure
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h3 class="mb-0">
|
|
{% if object.systolic_bp and object.diastolic_bp %}
|
|
{{ object.systolic_bp }}/{{ object.diastolic_bp }}
|
|
{% elif object.systolic_bp %}
|
|
{{ object.systolic_bp }}/-
|
|
{% elif object.diastolic_bp %}
|
|
-/{{ object.diastolic_bp }}
|
|
{% endif %}
|
|
<small class="text-muted">mmHg</small>
|
|
</h3>
|
|
{% if object.bp_position %}
|
|
<small class="text-muted">Position: {{ object.get_bp_position_display }}</small><br>
|
|
{% endif %}
|
|
{% if object.bp_cuff_size %}
|
|
<small class="text-muted">Cuff: {{ object.get_bp_cuff_size_display }}</small>
|
|
{% endif %}
|
|
</div>
|
|
<div class="text-end">
|
|
{% if object.systolic_bp %}
|
|
{% if object.systolic_bp < 90 or object.systolic_bp > 140 %}
|
|
<span class="badge bg-danger">Critical</span>
|
|
{% elif object.systolic_bp > 120 %}
|
|
<span class="badge bg-warning">Elevated</span>
|
|
{% else %}
|
|
<span class="badge bg-success">Normal</span>
|
|
{% endif %}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Heart Rate -->
|
|
{% if object.heart_rate %}
|
|
<div class="col-md-6 mb-4">
|
|
<div class="card border-success">
|
|
<div class="card-header bg-success text-white">
|
|
<h6 class="mb-0">
|
|
<i class="fas fa-heartbeat me-2"></i>Heart Rate
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h3 class="mb-0">
|
|
{{ object.heart_rate }}
|
|
<small class="text-muted">bpm</small>
|
|
</h3>
|
|
</div>
|
|
<div class="text-end">
|
|
{% if object.heart_rate < 60 or object.heart_rate > 100 %}
|
|
<span class="badge bg-danger">Abnormal</span>
|
|
{% else %}
|
|
<span class="badge bg-success">Normal</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Temperature -->
|
|
{% if object.temperature %}
|
|
<div class="col-md-6 mb-4">
|
|
<div class="card border-warning">
|
|
<div class="card-header bg-warning text-dark">
|
|
<h6 class="mb-0">
|
|
<i class="fas fa-thermometer-half me-2"></i>Temperature
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h3 class="mb-0">
|
|
{{ object.temperature }}°F
|
|
</h3>
|
|
{% if object.temperature_route %}
|
|
<small class="text-muted">Route: {{ object.get_temperature_route_display }}</small>
|
|
{% endif %}
|
|
</div>
|
|
<div class="text-end">
|
|
{% if object.temperature < 97.0 or object.temperature > 100.4 %}
|
|
<span class="badge bg-danger">Abnormal</span>
|
|
{% else %}
|
|
<span class="badge bg-success">Normal</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Respiratory Rate -->
|
|
{% if object.respiratory_rate %}
|
|
<div class="col-md-6 mb-4">
|
|
<div class="card border-info">
|
|
<div class="card-header bg-info text-white">
|
|
<h6 class="mb-0">
|
|
<i class="fas fa-lungs me-2"></i>Respiratory Rate
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h3 class="mb-0">
|
|
{{ object.respiratory_rate }}
|
|
<small class="text-muted">rpm</small>
|
|
</h3>
|
|
</div>
|
|
<div class="text-end">
|
|
{% if object.respiratory_rate < 12 or object.respiratory_rate > 20 %}
|
|
<span class="badge bg-danger">Abnormal</span>
|
|
{% else %}
|
|
<span class="badge bg-success">Normal</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Oxygen Saturation -->
|
|
{% if object.oxygen_saturation %}
|
|
<div class="col-md-6 mb-4">
|
|
<div class="card border-secondary">
|
|
<div class="card-header bg-secondary text-white">
|
|
<h6 class="mb-0">
|
|
<i class="fas fa-lungs me-2"></i>Oxygen Saturation
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h3 class="mb-0">
|
|
{{ object.oxygen_saturation }}%
|
|
</h3>
|
|
</div>
|
|
<div class="text-end">
|
|
{% if object.oxygen_saturation < 95 %}
|
|
<span class="badge bg-danger">Low</span>
|
|
{% else %}
|
|
<span class="badge bg-success">Normal</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Pain Scale -->
|
|
{% if object.pain_scale is not None %}
|
|
<div class="col-md-6 mb-4">
|
|
<div class="card border-danger">
|
|
<div class="card-header bg-danger text-white">
|
|
<h6 class="mb-0">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>Pain Scale
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h3 class="mb-0">
|
|
{{ object.pain_scale }}/10
|
|
</h3>
|
|
</div>
|
|
<div class="text-end">
|
|
{% if object.pain_scale == 0 %}
|
|
<span class="badge bg-success">No Pain</span>
|
|
{% elif object.pain_scale <= 3 %}
|
|
<span class="badge bg-warning">Mild</span>
|
|
{% elif object.pain_scale <= 6 %}
|
|
<span class="badge bg-warning">Moderate</span>
|
|
{% else %}
|
|
<span class="badge bg-danger">Severe</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Physical Measurements -->
|
|
{% if object.height or object.weight %}
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<h6 class="text-primary mb-3">
|
|
<i class="fas fa-ruler me-2"></i>Physical Measurements
|
|
</h6>
|
|
</div>
|
|
|
|
{% if object.height %}
|
|
<div class="col-md-3 mb-3">
|
|
<div class="card bg-light">
|
|
<div class="card-body text-center">
|
|
<i class="fas fa-ruler-vertical fa-2x text-primary mb-2"></i>
|
|
<h5 class="mb-0">{{ object.height }} cm</h5>
|
|
<small class="text-muted">Height</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if object.weight %}
|
|
<div class="col-md-3 mb-3">
|
|
<div class="card bg-light">
|
|
<div class="card-body text-center">
|
|
<i class="fas fa-weight fa-2x text-success mb-2"></i>
|
|
<h5 class="mb-0">{{ object.weight }} kg</h5>
|
|
<small class="text-muted">Weight</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if object.height and object.weight %}
|
|
<div class="col-md-3 mb-3">
|
|
<div class="card bg-light">
|
|
<div class="card-body text-center">
|
|
<i class="fas fa-calculator fa-2x text-info mb-2"></i>
|
|
<h5 class="mb-0">{{ object.bmi|floatformat:1 }}</h5>
|
|
<small class="text-muted">BMI (kg/m²)</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if object.head_circumference %}
|
|
<div class="col-md-3 mb-3">
|
|
<div class="card bg-light">
|
|
<div class="card-body text-center">
|
|
<i class="fas fa-circle fa-2x text-warning mb-2"></i>
|
|
<h5 class="mb-0">{{ object.head_circumference }} cm</h5>
|
|
<small class="text-muted">Head Circumference</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Additional Measurements -->
|
|
{% if object.blood_glucose %}
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<h6 class="text-primary mb-3">
|
|
<i class="fas fa-tint me-2"></i>Additional Measurements
|
|
</h6>
|
|
</div>
|
|
|
|
<div class="col-md-4 mb-3">
|
|
<div class="card bg-light">
|
|
<div class="card-body text-center">
|
|
<i class="fas fa-tint fa-2x text-danger mb-2"></i>
|
|
<h5 class="mb-0">{{ object.blood_glucose }} mg/dL</h5>
|
|
<small class="text-muted">Blood Glucose</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Clinical Notes -->
|
|
{% if object.notes %}
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-notes-medical me-2"></i>Clinical Notes
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="mb-0">{{ object.notes|linebreaks }}</p>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Sidebar -->
|
|
<div class="col-lg-4">
|
|
<!-- Critical Values Alert -->
|
|
{% if object.has_critical_values %}
|
|
<div class="card mb-4 border-danger">
|
|
<div class="card-header bg-danger text-white">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>Critical Values
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-danger mb-0">
|
|
<i class="fas fa-warning me-2"></i>
|
|
<strong>Alert:</strong> This vital signs record contains values outside normal ranges that require immediate attention.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Device and Location Information -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-info-circle me-2"></i>Additional Information
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<dl class="row mb-0">
|
|
{% if object.device_used %}
|
|
<dt class="col-sm-5">Device Used:</dt>
|
|
<dd class="col-sm-7">{{ object.device_used }}</dd>
|
|
{% endif %}
|
|
|
|
{% if object.location %}
|
|
<dt class="col-sm-5">Location:</dt>
|
|
<dd class="col-sm-7">{{ object.location }}</dd>
|
|
{% endif %}
|
|
|
|
<dt class="col-sm-5">Recorded:</dt>
|
|
<dd class="col-sm-7">{{ object.created_at|date:"M d, Y H:i" }}</dd>
|
|
|
|
{% if object.updated_at != object.created_at %}
|
|
<dt class="col-sm-5">Last Updated:</dt>
|
|
<dd class="col-sm-7">{{ object.updated_at|date:"M d, Y H:i" }}</dd>
|
|
{% endif %}
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Trends Chart -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-chart-line me-2"></i>Recent Trends
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="vital-signs-chart"
|
|
hx-get="{% url 'emr:vital_signs_chart' object.patient.id %}"
|
|
hx-trigger="load">
|
|
<div class="text-center py-3">
|
|
<div class="spinner-border text-primary" role="status">
|
|
<span class="visually-hidden">Loading chart...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick Actions -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-bolt me-2"></i>Quick Actions
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-grid gap-2">
|
|
<a href="#" class="btn btn-primary">
|
|
<i class="fas fa-plus me-2"></i>Record New Vitals
|
|
</a>
|
|
<a href="#" class="btn btn-outline-success">
|
|
<i class="fas fa-edit me-2"></i>Edit This Record
|
|
</a>
|
|
<a href="{% url 'emr:vital_signs_list' %}?patient={{ object.patient.id }}" class="btn btn-outline-info">
|
|
<i class="fas fa-history me-2"></i>View Patient History
|
|
</a>
|
|
<button type="button" class="btn btn-outline-warning" onclick="printVitalSigns()">
|
|
<i class="fas fa-print me-2"></i>Print Report
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function printVitalSigns() {
|
|
window.print();
|
|
}
|
|
|
|
// Auto-refresh chart every 5 minutes
|
|
setInterval(function() {
|
|
const chartContainer = document.getElementById('vital-signs-chart');
|
|
if (chartContainer) {
|
|
htmx.trigger(chartContainer, 'refresh');
|
|
}
|
|
}, 300000);
|
|
</script>
|
|
|
|
<style>
|
|
.card.border-primary { border-color: #0d6efd !important; }
|
|
.card.border-success { border-color: #198754 !important; }
|
|
.card.border-warning { border-color: #ffc107 !important; }
|
|
.card.border-info { border-color: #0dcaf0 !important; }
|
|
.card.border-secondary { border-color: #6c757d !important; }
|
|
.card.border-danger { border-color: #dc3545 !important; }
|
|
|
|
.card-header.bg-primary { background-color: #0d6efd !important; }
|
|
.card-header.bg-success { background-color: #198754 !important; }
|
|
.card-header.bg-warning { background-color: #ffc107 !important; }
|
|
.card-header.bg-info { background-color: #0dcaf0 !important; }
|
|
.card-header.bg-secondary { background-color: #6c757d !important; }
|
|
.card-header.bg-danger { background-color: #dc3545 !important; }
|
|
|
|
.badge.bg-success { background-color: #198754 !important; }
|
|
.badge.bg-warning { background-color: #ffc107 !important; }
|
|
.badge.bg-danger { background-color: #dc3545 !important; }
|
|
|
|
dl.row dt {
|
|
font-weight: 600;
|
|
color: #495057;
|
|
}
|
|
|
|
dl.row dd {
|
|
color: #6c757d;
|
|
}
|
|
|
|
@media print {
|
|
.btn-group,
|
|
.card:last-child {
|
|
display: none !important;
|
|
}
|
|
|
|
.container-fluid {
|
|
padding: 0 !important;
|
|
}
|
|
|
|
.card {
|
|
border: 1px solid #000 !important;
|
|
break-inside: avoid;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.col-md-6.mb-4,
|
|
.col-md-3.mb-3,
|
|
.col-md-4.mb-3 {
|
|
margin-bottom: 1rem !important;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|