Marwan Alwali 35be20ae4c update
2025-09-06 19:07:14 +03:00

618 lines
26 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Blood Unit Details - {{ blood_unit.unit_number }}{% endblock %}
{% block css %}
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
<style>
.status-timeline {
position: relative;
padding-left: 30px;
}
.status-timeline::before {
content: '';
position: absolute;
left: 15px;
top: 0;
bottom: 0;
width: 2px;
background: #e9ecef;
}
.timeline-item {
position: relative;
margin-bottom: 20px;
}
.timeline-item::before {
content: '';
position: absolute;
left: -23px;
top: 5px;
width: 12px;
height: 12px;
border-radius: 50%;
background: #007bff;
border: 2px solid #fff;
box-shadow: 0 0 0 2px #e9ecef;
}
.timeline-item.current::before {
background: #28a745;
box-shadow: 0 0 0 2px #28a745;
}
.test-result-positive {
background-color: #f8d7da;
border-color: #f5c6cb;
}
.test-result-negative {
background-color: #d4edda;
border-color: #c3e6cb;
}
.test-result-pending {
background-color: #fff3cd;
border-color: #ffeaa7;
}
</style>
{% endblock %}
{% block content %}
<!-- BEGIN breadcrumb -->
<ol class="breadcrumb float-xl-end">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Home</a></li>
<li class="breadcrumb-item"><a href="{% url 'blood_bank:dashboard' %}">Blood Bank</a></li>
<li class="breadcrumb-item"><a href="{% url 'blood_bank:blood_unit_list' %}">Blood Units</a></li>
<li class="breadcrumb-item active">{{ blood_unit.unit_number }}</li>
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">
Blood Unit Details
<small>{{ blood_unit.unit_number }}</small>
</h1>
<!-- END page-header -->
<!-- BEGIN row -->
<div class="row">
<!-- BEGIN col-4 -->
<div class="col-xl-4">
<!-- BEGIN unit info panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Unit Information</h4>
<div class="panel-heading-btn">
<span class="badge {% if blood_unit.status == 'available' %}bg-success{% elif blood_unit.status == 'expired' %}bg-danger{% else %}bg-warning{% endif %}">
{{ blood_unit.get_status_display }}
</span>
</div>
</div>
<div class="panel-body">
<div class="text-center mb-4">
<div class="bg-light rounded p-4">
<i class="fa fa-tint fa-4x text-primary mb-2"></i>
<h4>{{ blood_unit.unit_number }}</h4>
<p class="text-muted mb-0">{{ blood_unit.component.get_name_display }}</p>
</div>
</div>
<table class="table table-borderless">
<tr>
<td class="fw-bold">Blood Group:</td>
<td>
<span class="badge bg-primary fs-6">{{ blood_unit.blood_group.display_name }}</span>
</td>
</tr>
<tr>
<td class="fw-bold">Component:</td>
<td>{{ blood_unit.component.get_name_display }}</td>
</tr>
<tr>
<td class="fw-bold">Volume:</td>
<td>{{ blood_unit.volume_ml }} ml</td>
</tr>
<tr>
<td class="fw-bold">Collection Date:</td>
<td>{{ blood_unit.collection_date|date:"M d, Y H:i" }}</td>
</tr>
<tr>
<td class="fw-bold">Expiry Date:</td>
<td>
{{ blood_unit.expiry_date|date:"M d, Y" }}
{% if blood_unit.days_to_expiry <= 3 and blood_unit.status == 'available' %}
<br><span class="badge bg-warning">{{ blood_unit.days_to_expiry }} days left</span>
{% elif blood_unit.is_expired %}
<br><span class="badge bg-danger">Expired</span>
{% endif %}
</td>
</tr>
<tr>
<td class="fw-bold">Location:</td>
<td>{{ blood_unit.location }}</td>
</tr>
<tr>
<td class="fw-bold">Bag Type:</td>
<td>{{ blood_unit.bag_type }}</td>
</tr>
<tr>
<td class="fw-bold">Anticoagulant:</td>
<td>{{ blood_unit.anticoagulant }}</td>
</tr>
<tr>
<td class="fw-bold">Collection Site:</td>
<td>{{ blood_unit.collection_site }}</td>
</tr>
<tr>
<td class="fw-bold">Collected By:</td>
<td>{{ blood_unit.collected_by.get_full_name }}</td>
</tr>
</table>
{% if blood_unit.notes %}
<hr>
<h6 class="fw-bold">Notes</h6>
<p class="text-muted">{{ blood_unit.notes }}</p>
{% endif %}
</div>
</div>
<!-- END unit info panel -->
<!-- BEGIN donor info panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Donor Information</h4>
<div class="panel-heading-btn">
<a href="{% url 'blood_bank:donor_detail' blood_unit.donor.id %}" class="btn btn-primary btn-sm">
<i class="fa fa-user"></i> View Donor
</a>
</div>
</div>
<div class="panel-body">
<table class="table table-borderless">
<tr>
<td class="fw-bold">Donor ID:</td>
<td>{{ blood_unit.donor.donor_id }}</td>
</tr>
<tr>
<td class="fw-bold">Name:</td>
<td>{{ blood_unit.donor.full_name }}</td>
</tr>
<tr>
<td class="fw-bold">Age:</td>
<td>{{ blood_unit.donor.age }} years</td>
</tr>
<tr>
<td class="fw-bold">Gender:</td>
<td>{{ blood_unit.donor.get_gender_display }}</td>
</tr>
<tr>
<td class="fw-bold">Phone:</td>
<td>{{ blood_unit.donor.phone }}</td>
</tr>
<tr>
<td class="fw-bold">Total Donations:</td>
<td>{{ blood_unit.donor.total_donations }}</td>
</tr>
</table>
</div>
</div>
<!-- END donor info panel -->
</div>
<!-- END col-4 -->
<!-- BEGIN col-8 -->
<div class="col-xl-8">
<!-- BEGIN status timeline -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Unit Status Timeline</h4>
</div>
<div class="panel-body">
<div class="status-timeline">
<div class="timeline-item {% if blood_unit.status == 'collected' %}current{% endif %}">
<div class="card">
<div class="card-body">
<h6 class="card-title">
<i class="fa fa-tint text-primary"></i> Blood Collected
</h6>
<p class="card-text">
<small class="text-muted">{{ blood_unit.collection_date|date:"M d, Y H:i" }}</small><br>
Blood unit collected from donor {{ blood_unit.donor.full_name }}
</p>
</div>
</div>
</div>
{% if tests %}
<div class="timeline-item {% if blood_unit.status == 'testing' %}current{% endif %}">
<div class="card">
<div class="card-body">
<h6 class="card-title">
<i class="fa fa-flask text-info"></i> Testing Phase
</h6>
<p class="card-text">
<small class="text-muted">{{ tests.first.test_date|date:"M d, Y H:i" }}</small><br>
Laboratory testing initiated
</p>
</div>
</div>
</div>
{% endif %}
{% if blood_unit.status == 'quarantine' %}
<div class="timeline-item current">
<div class="card">
<div class="card-body">
<h6 class="card-title">
<i class="fa fa-pause text-warning"></i> Quarantine
</h6>
<p class="card-text">
Unit placed in quarantine pending test results
</p>
</div>
</div>
</div>
{% endif %}
{% if blood_unit.status == 'available' %}
<div class="timeline-item current">
<div class="card">
<div class="card-body">
<h6 class="card-title">
<i class="fa fa-check text-success"></i> Available for Use
</h6>
<p class="card-text">
Unit cleared for transfusion and available in inventory
</p>
</div>
</div>
</div>
{% endif %}
{% if blood_unit.status == 'issued' %}
<div class="timeline-item current">
<div class="card">
<div class="card-body">
<h6 class="card-title">
<i class="fa fa-share text-primary"></i> Issued
</h6>
<p class="card-text">
Unit issued for patient transfusion
</p>
</div>
</div>
</div>
{% endif %}
{% if blood_unit.status == 'transfused' %}
<div class="timeline-item current">
<div class="card">
<div class="card-body">
<h6 class="card-title">
<i class="fa fa-heartbeat text-success"></i> Transfused
</h6>
<p class="card-text">
Unit successfully transfused to patient
</p>
</div>
</div>
</div>
{% endif %}
{% if blood_unit.status == 'expired' or blood_unit.status == 'discarded' %}
<div class="timeline-item current">
<div class="card">
<div class="card-body">
<h6 class="card-title">
<i class="fa fa-times text-danger"></i> {{ blood_unit.get_status_display }}
</h6>
<p class="card-text">
Unit removed from inventory
</p>
</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
<!-- END status timeline -->
<!-- BEGIN test results -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Test Results</h4>
<div class="panel-heading-btn">
{% if blood_unit.status in 'collected,testing,quarantine' %}
<a href="{% url 'blood_bank:blood_test_create' blood_unit.id %}" class="btn btn-success btn-sm">
<i class="fa fa-plus"></i> Add Test Result
</a>
{% endif %}
</div>
</div>
<div class="panel-body">
{% if tests %}
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Test Type</th>
<th>Result</th>
<th>Test Date</th>
<th>Tested By</th>
<th>Equipment</th>
<th>Verified</th>
</tr>
</thead>
<tbody>
{% for test in tests %}
<tr class="{% if test.result == 'positive' %}test-result-positive{% elif test.result == 'negative' %}test-result-negative{% else %}test-result-pending{% endif %}">
<td>{{ test.get_test_type_display }}</td>
<td>
{% if test.result == 'positive' %}
<span class="badge bg-danger">{{ test.get_result_display }}</span>
{% elif test.result == 'negative' %}
<span class="badge bg-success">{{ test.get_result_display }}</span>
{% elif test.result == 'indeterminate' %}
<span class="badge bg-warning">{{ test.get_result_display }}</span>
{% else %}
<span class="badge bg-secondary">{{ test.get_result_display }}</span>
{% endif %}
</td>
<td>{{ test.test_date|date:"M d, Y H:i" }}</td>
<td>{{ test.tested_by.get_full_name }}</td>
<td>{{ test.equipment_used|default:"-" }}</td>
<td>
{% if test.verified_by %}
<span class="badge bg-success">
<i class="fa fa-check"></i> {{ test.verified_by.get_full_name }}
</span>
<br><small class="text-muted">{{ test.verified_at|date:"M d, Y H:i" }}</small>
{% else %}
<span class="badge bg-warning">Pending</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4">
<i class="fa fa-flask fa-3x text-muted mb-3"></i>
<h5 class="text-muted">No Test Results</h5>
<p class="text-muted">No laboratory tests have been performed on this unit yet.</p>
{% if blood_unit.status in 'collected,testing,quarantine' %}
<a href="{% url 'blood_bank:blood_test_create' blood_unit.id %}" class="btn btn-primary">
<i class="fa fa-plus"></i> Add First Test
</a>
{% endif %}
</div>
{% endif %}
</div>
</div>
<!-- END test results -->
<!-- BEGIN crossmatch results -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Crossmatch Results</h4>
<div class="panel-heading-btn">
{% if blood_unit.status == 'available' %}
<button type="button" class="btn btn-info btn-sm" data-bs-toggle="modal" data-bs-target="#crossmatchModal">
<i class="fa fa-plus"></i> Add Crossmatch
</button>
{% endif %}
</div>
</div>
<div class="panel-body">
{% if crossmatches %}
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Patient</th>
<th>Test Type</th>
<th>Compatibility</th>
<th>Test Date</th>
<th>Tested By</th>
<th>Verified</th>
</tr>
</thead>
<tbody>
{% for crossmatch in crossmatches %}
<tr>
<td>
{{ crossmatch.recipient.full_name }}
<br><small class="text-muted">{{ crossmatch.recipient.patient_id }}</small>
</td>
<td>{{ crossmatch.get_test_type_display }}</td>
<td>
{% if crossmatch.compatibility == 'compatible' %}
<span class="badge bg-success">{{ crossmatch.get_compatibility_display }}</span>
{% elif crossmatch.compatibility == 'incompatible' %}
<span class="badge bg-danger">{{ crossmatch.get_compatibility_display }}</span>
{% else %}
<span class="badge bg-warning">{{ crossmatch.get_compatibility_display }}</span>
{% endif %}
</td>
<td>{{ crossmatch.test_date|date:"M d, Y H:i" }}</td>
<td>{{ crossmatch.tested_by.get_full_name }}</td>
<td>
{% if crossmatch.verified_by %}
<span class="badge bg-success">
<i class="fa fa-check"></i> Verified
</span>
{% else %}
<span class="badge bg-warning">Pending</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4">
<i class="fa fa-exchange-alt fa-3x text-muted mb-3"></i>
<h5 class="text-muted">No Crossmatch Results</h5>
<p class="text-muted">No crossmatch tests have been performed for this unit.</p>
</div>
{% endif %}
</div>
</div>
<!-- END crossmatch results -->
</div>
<!-- END col-8 -->
</div>
<!-- END row -->
<!-- BEGIN action buttons -->
<div class="row">
<div class="col-12">
<div class="d-flex justify-content-between">
<a href="{% url 'blood_bank:blood_unit_list' %}" class="btn btn-default">
<i class="fa fa-arrow-left"></i> Back to Units
</a>
<div>
{% if blood_unit.status in 'collected,testing,quarantine' %}
<a href="{% url 'blood_bank:blood_test_create' blood_unit.id %}" class="btn btn-success">
<i class="fa fa-flask"></i> Add Test
</a>
{% endif %}
{% if blood_unit.status == 'available' %}
<button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#moveUnitModal">
<i class="fa fa-arrows-alt"></i> Move Location
</button>
{% endif %}
<button type="button" class="btn btn-info" onclick="window.print()">
<i class="fa fa-print"></i> Print Label
</button>
</div>
</div>
</div>
</div>
<!-- Crossmatch Modal -->
<div class="modal fade" id="crossmatchModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Crossmatch Test</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="crossmatchForm">
<div class="mb-3">
<label class="form-label">Patient</label>
<select class="form-select" id="patientSelect">
<option value="">Select Patient</option>
<!-- Load patients via AJAX if needed -->
</select>
</div>
<div class="mb-3">
<label class="form-label">Test Type</label>
<select class="form-select" id="testType">
<option value="major">Major Crossmatch</option>
<option value="minor">Minor Crossmatch</option>
<option value="immediate_spin">Immediate Spin</option>
<option value="antiglobulin">Antiglobulin Test</option>
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="submitCrossmatch()">Create Crossmatch</button>
</div>
</div>
</div>
</div>
<!-- Move Unit Modal -->
<div class="modal fade" id="moveUnitModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Move Blood Unit</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="moveUnitForm">
<div class="mb-3">
<label class="form-label">New Location</label>
<select class="form-select" id="newLocation">
<option value="">Select Location</option>
<option value="Refrigerator A">Refrigerator A</option>
<option value="Refrigerator B">Refrigerator B</option>
<option value="Freezer 1">Freezer 1</option>
<option value="Platelet Agitator">Platelet Agitator</option>
<option value="Quarantine">Quarantine</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">Reason</label>
<textarea class="form-control" id="moveReason" rows="3"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-warning" onclick="submitMoveUnit()">Move Unit</button>
</div>
</div>
</div>
</div>
<!-- END action buttons -->
{% endblock %}
{% block js %}
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'plugins/sweetalert/dist/sweetalert.min.js' %}"></script>
<script>
function submitCrossmatch() {
const patient = document.getElementById("patientSelect").value;
const testType = document.getElementById("testType").value;
if (!patient) {
alert("Please select a patient");
return;
}
// Redirect to your creation URL
window.location.href = `en/blood-bank/units/{{ blood_unit.id }}/crossmatch/${patient}/?test_type=${testType}`;
}
function submitMoveUnit() {
const location = document.getElementById("newLocation").value;
const reason = document.getElementById("moveReason").value;
if (!location) {
alert("Please select a new location");
return;
}
// For now reload page, later replace with AJAX
alert(`Blood unit moved to ${location} for reason: ${reason}`);
location.reload();
}
// Auto-refresh page every 5 minutes to update status
setInterval(function() {
if (document.visibilityState === 'visible') {
location.reload();
}
}, 300000);
</script>
{% endblock %}