288 lines
17 KiB
HTML
288 lines
17 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}Lab Results - {{ block.super }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title mb-0">
|
|
<i class="fas fa-chart-line me-2"></i>Laboratory Results
|
|
</h4>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<!-- Filters -->
|
|
<form method="get" class="mb-3">
|
|
<div class="row">
|
|
<div class="col-md-2">
|
|
<select name="status" class="form-select">
|
|
<option value="">All Status</option>
|
|
<option value="PENDING" {% if status == 'PENDING' %}selected{% endif %}>Pending</option>
|
|
<option value="IN_PROGRESS" {% if status == 'IN_PROGRESS' %}selected{% endif %}>In Progress</option>
|
|
<option value="COMPLETED" {% if status == 'COMPLETED' %}selected{% endif %}>Completed</option>
|
|
<option value="VERIFIED" {% if status == 'VERIFIED' %}selected{% endif %}>Verified</option>
|
|
<option value="CANCELLED" {% if status == 'CANCELLED' %}selected{% endif %}>Cancelled</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<select name="abnormal_flag" class="form-select">
|
|
<option value="">All Results</option>
|
|
<option value="NORMAL" {% if abnormal_flag == 'NORMAL' %}selected{% endif %}>Normal</option>
|
|
<option value="HIGH" {% if abnormal_flag == 'HIGH' %}selected{% endif %}>High</option>
|
|
<option value="LOW" {% if abnormal_flag == 'LOW' %}selected{% endif %}>Low</option>
|
|
<option value="CRITICAL_HIGH" {% if abnormal_flag == 'CRITICAL_HIGH' %}selected{% endif %}>Critical High</option>
|
|
<option value="CRITICAL_LOW" {% if abnormal_flag == 'CRITICAL_LOW' %}selected{% endif %}>Critical Low</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-1">
|
|
<select name="is_critical" class="form-select">
|
|
<option value="">All</option>
|
|
<option value="true" {% if is_critical == 'true' %}selected{% endif %}>Critical</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-1">
|
|
<select name="verified" class="form-select">
|
|
<option value="">All</option>
|
|
<option value="false" {% if verified == 'false' %}selected{% endif %}>Unverified</option>
|
|
<option value="true" {% if verified == 'true' %}selected{% endif %}>Verified</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<input type="date" name="date_from" class="form-control"
|
|
value="{{ date_from }}" placeholder="From Date">
|
|
</div>
|
|
<div class="col-md-3">
|
|
<input type="text" name="search" class="form-control"
|
|
value="{{ search }}" placeholder="Search patients, tests...">
|
|
</div>
|
|
<div class="col-md-1">
|
|
<button type="submit" class="btn btn-primary w-100">
|
|
<i class="fas fa-search"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- Results Table -->
|
|
<div class="table-responsive">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>Patient</th>
|
|
<th>Test</th>
|
|
<th>Result</th>
|
|
<th>Reference Range</th>
|
|
<th>Flag</th>
|
|
<th>Analyzed</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for result in page_obj %}
|
|
<tr {% if result.is_critical %}class="table-danger"{% elif result.abnormal_flag in 'HIGH,LOW' %}class="table-warning"{% endif %}>
|
|
<td>
|
|
<strong>{{ result.order.patient.get_full_name }}</strong><br>
|
|
<small class="text-muted">
|
|
MRN: {{ result.order.patient.mrn }} •
|
|
Order: {{ result.order.order_number }}
|
|
</small>
|
|
</td>
|
|
<td>
|
|
<strong>{{ result.test.test_name }}</strong>
|
|
{% if result.test.test_code %}
|
|
<br><small class="text-muted">{{ result.test.test_code }}</small>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if result.numeric_result %}
|
|
<strong>{{ result.numeric_result }}</strong> {{ result.test.unit }}
|
|
{% elif result.text_result %}
|
|
{{ result.text_result }}
|
|
{% else %}
|
|
<span class="text-muted">Pending</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if result.reference_range %}
|
|
{{ result.reference_range }}
|
|
{% else %}
|
|
<span class="text-muted">-</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if result.abnormal_flag == 'NORMAL' %}
|
|
<span class="badge bg-success">Normal</span>
|
|
{% elif result.abnormal_flag == 'HIGH' %}
|
|
<span class="badge bg-warning">High</span>
|
|
{% elif result.abnormal_flag == 'LOW' %}
|
|
<span class="badge bg-warning">Low</span>
|
|
{% elif result.abnormal_flag == 'CRITICAL_HIGH' %}
|
|
<span class="badge bg-danger">Critical High</span>
|
|
{% elif result.abnormal_flag == 'CRITICAL_LOW' %}
|
|
<span class="badge bg-danger">Critical Low</span>
|
|
{% endif %}
|
|
{% if result.is_critical %}
|
|
<br><i class="fas fa-exclamation-triangle text-danger" title="Critical Result"></i>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{{ result.analyzed_datetime|date:"M d, Y H:i" }}
|
|
{% if result.analyzed_by %}
|
|
<br><small class="text-muted">By: {{ result.analyzed_by.get_full_name }}</small>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if result.status == 'PENDING' %}
|
|
<span class="badge bg-secondary">Pending</span>
|
|
{% elif result.status == 'IN_PROGRESS' %}
|
|
<span class="badge bg-warning">In Progress</span>
|
|
{% elif result.status == 'COMPLETED' %}
|
|
{% if result.verified %}
|
|
<span class="badge bg-success">Verified</span>
|
|
{% else %}
|
|
<span class="badge bg-info">Completed</span>
|
|
{% endif %}
|
|
{% elif result.status == 'VERIFIED' %}
|
|
<span class="badge bg-success">Verified</span>
|
|
{% elif result.status == 'CANCELLED' %}
|
|
<span class="badge bg-danger">Cancelled</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<div class="btn-group btn-group-sm">
|
|
<button class="btn btn-outline-primary" title="View Details">
|
|
<i class="fas fa-eye"></i>
|
|
</button>
|
|
{% if result.status == 'COMPLETED' and not result.verified %}
|
|
<button class="btn btn-outline-success"
|
|
title="Verify Result"
|
|
hx-post="{% url 'laboratory:verify_result' result.result_id %}"
|
|
hx-confirm="Verify this result?"
|
|
hx-swap="none">
|
|
<i class="fas fa-check"></i>
|
|
</button>
|
|
{% endif %}
|
|
{% if result.is_critical and not result.critical_called %}
|
|
<button class="btn btn-outline-danger"
|
|
title="Call Critical Result"
|
|
data-bs-toggle="modal"
|
|
data-bs-target="#critical-modal-{{ result.result_id }}">
|
|
<i class="fas fa-phone"></i>
|
|
</button>
|
|
{% endif %}
|
|
<button class="btn btn-outline-info" title="Trend Chart">
|
|
<i class="fas fa-chart-line"></i>
|
|
</button>
|
|
<button class="btn btn-outline-secondary" title="Print">
|
|
<i class="fas fa-print"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="8" class="text-center py-4">
|
|
<i class="fas fa-chart-line fa-3x text-muted mb-3"></i>
|
|
<h5 class="text-muted">No lab results found</h5>
|
|
<p class="text-muted">No lab results match your current filters.</p>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
{% if page_obj.has_other_pages %}
|
|
<nav aria-label="Lab results pagination">
|
|
<ul class="pagination justify-content-center">
|
|
{% if page_obj.has_previous %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page=1{% if search %}&search={{ search }}{% endif %}{% if status %}&status={{ status }}{% endif %}">First</a>
|
|
</li>
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if search %}&search={{ search }}{% endif %}{% if status %}&status={{ status }}{% endif %}">Previous</a>
|
|
</li>
|
|
{% endif %}
|
|
|
|
<li class="page-item active">
|
|
<span class="page-link">
|
|
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
|
|
</span>
|
|
</li>
|
|
|
|
{% if page_obj.has_next %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if search %}&search={{ search }}{% endif %}{% if status %}&status={{ status }}{% endif %}">Next</a>
|
|
</li>
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if search %}&search={{ search }}{% endif %}{% if status %}&status={{ status }}{% endif %}">Last</a>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
</nav>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Critical Result Call Modals -->
|
|
{% for result in page_obj %}
|
|
{% if result.is_critical and not result.critical_called %}
|
|
<div class="modal fade" id="critical-modal-{{ result.result_id }}" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Call Critical Result</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<form hx-post="{% url 'laboratory:call_critical_result' result.result_id %}">
|
|
<div class="modal-body">
|
|
<div class="alert alert-danger">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
<strong>Critical Result Alert</strong>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Patient</label>
|
|
<p class="form-control-plaintext">{{ result.order.patient.get_full_name }}</p>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Test</label>
|
|
<p class="form-control-plaintext">{{ result.test.test_name }}</p>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Result</label>
|
|
<p class="form-control-plaintext">
|
|
{% if result.numeric_result %}
|
|
{{ result.numeric_result }} {{ result.test.unit }}
|
|
{% else %}
|
|
{{ result.text_result }}
|
|
{% endif %}
|
|
</p>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="called_to" class="form-label">Called To</label>
|
|
<input type="text" class="form-control" name="called_to"
|
|
placeholder="Provider name or contact" required>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" class="btn btn-danger">Confirm Call</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endblock %}
|
|
|