2025-08-12 13:33:25 +03:00

560 lines
25 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}Lab Result - {{ lab_result.test.test_name }} - {{ 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-chart-line me-2"></i>Lab Result - {{ lab_result.test.test_name }}
</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'laboratory:dashboard' %}">Laboratory</a></li>
<li class="breadcrumb-item"><a href="{% url 'laboratory:lab_result_list' %}">Results</a></li>
<li class="breadcrumb-item active">{{ lab_result.test.test_name }}</li>
</ol>
</nav>
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-secondary" onclick="printResult()">
<i class="fas fa-print me-2"></i>Print
</button>
<div class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-cog me-2"></i>Actions
</button>
<ul class="dropdown-menu">
{% if lab_result.status == 'PENDING' and perms.laboratory.change_labresult %}
<li><a class="dropdown-item" href="#" onclick="verifyResult()">
<i class="fas fa-check me-2"></i>Verify Result
</a></li>
<li><a class="dropdown-item" href="#" onclick="reviewResult()">
<i class="fas fa-eye me-2"></i>Mark as Reviewed
</a></li>
{% endif %}
<li><a class="dropdown-item" href="#" onclick="exportResult()">
<i class="fas fa-download me-2"></i>Export Result
</a></li>
<li><a class="dropdown-item" href="#" onclick="emailResult()">
<i class="fas fa-envelope me-2"></i>Email Result
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="{% url 'laboratory:lab_order_detail' lab_result.order.pk %}">
<i class="fas fa-clipboard-list me-2"></i>View Order
</a></li>
{% if lab_result.is_critical %}
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-danger" href="#" onclick="notifyCritical()">
<i class="fas fa-exclamation-triangle me-2"></i>Send Critical Alert
</a></li>
{% endif %}
</ul>
</div>
</div>
</div>
<!-- Critical Result Alert -->
{% if lab_result.is_critical %}
<div class="alert alert-danger">
<h6 class="alert-heading">
<i class="fas fa-exclamation-triangle me-2"></i>Critical Result Alert
</h6>
<p class="mb-0">
This result contains critical values that require immediate attention.
The ordering provider has been notified automatically.
</p>
</div>
{% endif %}
<!-- Abnormal Result Alert -->
{% if lab_result.is_abnormal and not lab_result.is_critical %}
<div class="alert alert-warning">
<i class="fas fa-info-circle me-2"></i>
This result is outside the normal reference range.
</div>
{% endif %}
<div class="row">
<!-- Result Information -->
<div class="col-lg-8 mb-4">
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-chart-bar me-2"></i>Result Details
</h5>
</div>
<div class="card-body">
<!-- Main Result Display -->
<div class="text-center mb-4 p-4 bg-light rounded">
<h2 class="display-4 mb-2 {% if lab_result.is_critical %}text-danger{% elif lab_result.is_abnormal %}text-warning{% else %}text-success{% endif %}">
{{ lab_result.result_value }}
{% if lab_result.unit %}
<small class="text-muted">{{ lab_result.unit }}</small>
{% endif %}
</h2>
<h5 class="text-muted">{{ lab_result.test.test_name }}</h5>
{% if lab_result.test_component %}
<p class="text-muted mb-0">{{ lab_result.test_component }}</p>
{% endif %}
</div>
<div class="row">
<div class="col-md-6">
<table class="table table-borderless">
<tr>
<td class="fw-semibold text-muted">Test:</td>
<td>
<a href="{% url 'laboratory:lab_test_detail' lab_result.test.pk %}" class="text-decoration-none">
{{ lab_result.test.test_name }}
</a>
<br><small class="text-muted">{{ lab_result.test.test_code }}</small>
</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Result Value:</td>
<td class="fw-semibold {% if lab_result.is_critical %}text-danger{% elif lab_result.is_abnormal %}text-warning{% else %}text-success{% endif %}">
{{ lab_result.result_value }} {{ lab_result.unit|default:"" }}
</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Reference Range:</td>
<td>{{ lab_result.reference_range|default:"Not specified" }}</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Status:</td>
<td>
<span class="badge bg-{% if lab_result.status == 'VERIFIED' %}success{% elif lab_result.status == 'REVIEWED' %}info{% else %}warning{% endif %} fs-6">
{{ lab_result.get_status_display }}
</span>
</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Result Date:</td>
<td>{{ lab_result.result_datetime|date:"M d, Y H:i" }}</td>
</tr>
</table>
</div>
<div class="col-md-6">
<table class="table table-borderless">
<tr>
<td class="fw-semibold text-muted">Performed By:</td>
<td>{{ lab_result.performed_by.get_full_name|default:"System" }}</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Verified By:</td>
<td>{{ lab_result.verified_by.get_full_name|default:"Pending" }}</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Method:</td>
<td>{{ lab_result.method|default:"Standard" }}</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Instrument:</td>
<td>{{ lab_result.instrument|default:"N/A" }}</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Created:</td>
<td>{{ lab_result.created_at|date:"M d, Y H:i" }}</td>
</tr>
</table>
</div>
</div>
<!-- Result Flags -->
<div class="mt-3">
<h6 class="fw-semibold text-muted mb-2">Result Flags:</h6>
<div class="d-flex flex-wrap gap-2">
{% if lab_result.is_critical %}
<span class="badge bg-danger">Critical</span>
{% endif %}
{% if lab_result.is_abnormal %}
<span class="badge bg-warning">Abnormal</span>
{% endif %}
{% if lab_result.status == 'VERIFIED' %}
<span class="badge bg-success">Verified</span>
{% endif %}
{% if not lab_result.is_abnormal and not lab_result.is_critical %}
<span class="badge bg-success">Normal</span>
{% endif %}
</div>
</div>
{% if lab_result.comments %}
<div class="mt-3">
<h6 class="fw-semibold text-muted">Comments:</h6>
<div class="alert alert-light">
{{ lab_result.comments }}
</div>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Order and Patient Information -->
<div class="col-lg-4 mb-4">
<!-- Order Information -->
<div class="card mb-3">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-clipboard-list me-2"></i>Order Information
</h5>
</div>
<div class="card-body">
<table class="table table-borderless table-sm">
<tr>
<td class="fw-semibold text-muted">Order #:</td>
<td>
<a href="{% url 'laboratory:lab_order_detail' lab_result.order.pk %}" class="text-decoration-none">
{{ lab_result.order.order_number }}
</a>
</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Priority:</td>
<td>
<span class="badge bg-{% if lab_result.order.priority == 'URGENT' %}danger{% elif lab_result.order.priority == 'STAT' %}warning{% else %}primary{% endif %}">
{{ lab_result.order.get_priority_display }}
</span>
</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Ordered:</td>
<td>{{ lab_result.order.order_datetime|date:"M d, Y H:i" }}</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Provider:</td>
<td>{{ lab_result.order.ordering_provider.get_full_name }}</td>
</tr>
</table>
</div>
</div>
<!-- Patient Information -->
<div class="card">
<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="text-center mb-3">
<div class="bg-primary bg-gradient rounded-circle d-flex align-items-center justify-content-center mx-auto mb-2" style="width: 50px; height: 50px;">
<i class="fas fa-user fa-lg text-white"></i>
</div>
<h6 class="mb-1">{{ lab_result.order.patient.get_full_name }}</h6>
<small class="text-muted">MRN: {{ lab_result.order.patient.mrn }}</small>
</div>
<table class="table table-borderless table-sm">
<tr>
<td class="fw-semibold text-muted">Age:</td>
<td>{{ lab_result.order.patient.age }} years</td>
</tr>
<tr>
<td class="fw-semibold text-muted">Gender:</td>
<td>{{ lab_result.order.patient.get_gender_display }}</td>
</tr>
<tr>
<td class="fw-semibold text-muted">DOB:</td>
<td>{{ lab_result.order.patient.date_of_birth|date:"M d, Y" }}</td>
</tr>
</table>
<div class="d-grid">
<a href="{% url 'patients:patient_detail' lab_result.order.patient.pk %}" class="btn btn-outline-primary btn-sm">
<i class="fas fa-eye me-2"></i>View Patient
</a>
</div>
</div>
</div>
</div>
</div>
<!-- Reference Range Comparison -->
{% if lab_result.reference_range %}
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-ruler me-2"></i>Reference Range Comparison
</h5>
</div>
<div class="card-body">
<div class="row align-items-center">
<div class="col-md-8">
<div class="position-relative">
<!-- Reference Range Visualization -->
<div class="bg-light rounded p-3">
<div class="d-flex justify-content-between align-items-center mb-2">
<small class="text-muted">Low</small>
<small class="text-muted">Normal Range</small>
<small class="text-muted">High</small>
</div>
<div class="progress" style="height: 20px;">
<div class="progress-bar bg-danger" style="width: 20%"></div>
<div class="progress-bar bg-success" style="width: 60%"></div>
<div class="progress-bar bg-danger" style="width: 20%"></div>
</div>
<div class="d-flex justify-content-center mt-2">
<div class="position-relative">
<i class="fas fa-caret-down fa-lg {% if lab_result.is_critical %}text-danger{% elif lab_result.is_abnormal %}text-warning{% else %}text-success{% endif %}"></i>
<small class="position-absolute top-100 start-50 translate-middle-x text-nowrap">
{{ lab_result.result_value }}
</small>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="text-center">
<h6 class="text-muted">Reference Range</h6>
<div class="h5 mb-0">{{ lab_result.reference_range }}</div>
<small class="text-muted">{{ lab_result.unit|default:"" }}</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Historical Results -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-history me-2"></i>Historical Results for {{ lab_result.test.test_name }}
</h5>
</div>
<div class="card-body">
{% if historical_results %}
<div class="table-responsive">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th>Date</th>
<th>Result</th>
<th>Reference Range</th>
<th>Status</th>
<th>Provider</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for result in historical_results %}
<tr {% if result.pk == lab_result.pk %}class="table-primary"{% endif %}>
<td>{{ result.result_datetime|date:"M d, Y" }}</td>
<td class="fw-semibold {% if result.is_critical %}text-danger{% elif result.is_abnormal %}text-warning{% else %}text-success{% endif %}">
{{ result.result_value }} {{ result.unit|default:"" }}
{% if result.pk == lab_result.pk %}
<small class="badge bg-primary ms-1">Current</small>
{% endif %}
</td>
<td>{{ result.reference_range|default:"N/A" }}</td>
<td>
<span class="badge bg-{% if result.status == 'VERIFIED' %}success{% elif result.status == 'REVIEWED' %}info{% else %}warning{% endif %}">
{{ result.get_status_display }}
</span>
</td>
<td>{{ result.order.ordering_provider.get_full_name }}</td>
<td>
{% if result.pk != lab_result.pk %}
<a href="{% url 'laboratory:lab_result_detail' result.pk %}" class="btn btn-outline-primary btn-sm">
<i class="fas fa-eye"></i>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4">
<i class="fas fa-history fa-2x text-muted mb-3"></i>
<h6 class="text-muted">No historical results</h6>
<p class="text-muted">This is the first result for this test for this patient</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<script>
function printResult() {
window.print();
}
function exportResult() {
// Export result data
const resultData = {
test: '{{ lab_result.test.test_name }}',
patient: '{{ lab_result.order.patient.get_full_name }}',
result_value: '{{ lab_result.result_value }}',
unit: '{{ lab_result.unit|default:"" }}',
reference_range: '{{ lab_result.reference_range|default:"" }}',
status: '{{ lab_result.get_status_display }}',
result_date: '{{ lab_result.result_datetime|date:"Y-m-d H:i" }}',
is_critical: {{ lab_result.is_critical|yesno:"true,false" }},
is_abnormal: {{ lab_result.is_abnormal|yesno:"true,false" }}
};
const dataStr = JSON.stringify(resultData, null, 2);
const dataBlob = new Blob([dataStr], {type: 'application/json'});
const url = URL.createObjectURL(dataBlob);
const link = document.createElement('a');
link.href = url;
link.download = 'result_{{ lab_result.pk }}.json';
link.click();
URL.revokeObjectURL(url);
}
function verifyResult() {
if (confirm('Verify this result? This action cannot be undone.')) {
fetch(`{% url 'laboratory:verify_result' lab_result.pk %}`, {
method: 'POST',
headers: {
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value,
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Error: ' + data.error);
}
});
}
}
function reviewResult() {
if (confirm('Mark this result as reviewed?')) {
fetch(`{% url 'laboratory:review_result' lab_result.pk %}`, {
method: 'POST',
headers: {
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value,
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Error: ' + data.error);
}
});
}
}
function emailResult() {
const email = prompt('Enter email address to send result:');
if (email) {
fetch(`{% url 'laboratory:email_result' lab_result.pk %}`, {
method: 'POST',
headers: {
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value,
'Content-Type': 'application/json',
},
body: JSON.stringify({email: email})
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Result sent successfully!');
} else {
alert('Error: ' + data.error);
}
});
}
}
function notifyCritical() {
if (confirm('Send critical result notification to ordering provider?')) {
fetch(`{% url 'laboratory:notify_critical' lab_result.pk %}`, {
method: 'POST',
headers: {
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value,
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Critical notification sent!');
} else {
alert('Error: ' + data.error);
}
});
}
}
</script>
<style>
.bg-gradient {
background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
}
.progress {
border-radius: 10px;
overflow: hidden;
}
.table-primary {
--bs-table-bg: rgba(13, 110, 253, 0.1);
}
@media print {
.btn, .dropdown, .breadcrumb {
display: none !important;
}
.card {
border: 1px solid #dee2e6 !important;
box-shadow: none !important;
}
.alert {
border: 1px solid #dee2e6 !important;
box-shadow: none !important;
}
}
@media (max-width: 768px) {
.d-flex.justify-content-between {
flex-direction: column;
gap: 1rem;
}
.btn-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.table-responsive {
font-size: 0.875rem;
}
.display-4 {
font-size: 2rem;
}
}
</style>
{% endblock %}