744 lines
32 KiB
HTML
744 lines
32 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Issue Blood Unit - Request #{{ blood_request.request_number }}{% endblock %}
|
|
|
|
{% block css %}
|
|
<link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
|
|
<style>
|
|
.form-section {
|
|
background: #f8f9fa;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
border-left: 4px solid #007bff;
|
|
}
|
|
|
|
.form-section h5 {
|
|
color: #007bff;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.required-field {
|
|
color: #dc3545;
|
|
}
|
|
|
|
.request-info {
|
|
background: #d4edda;
|
|
border-left: 4px solid #28a745;
|
|
}
|
|
|
|
.unit-selection {
|
|
background: #d1ecf1;
|
|
border-left: 4px solid #17a2b8;
|
|
}
|
|
|
|
.safety-checks {
|
|
background: #fff3cd;
|
|
border-left: 4px solid #ffc107;
|
|
}
|
|
|
|
.emergency-section {
|
|
background: #f8d7da;
|
|
border-left: 4px solid #dc3545;
|
|
animation: pulse 2s infinite;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0% { opacity: 1; }
|
|
50% { opacity: 0.8; }
|
|
100% { opacity: 1; }
|
|
}
|
|
|
|
.unit-card {
|
|
background: white;
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
margin-bottom: 15px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.unit-card:hover {
|
|
border-color: #007bff;
|
|
box-shadow: 0 2px 8px rgba(0,123,255,0.2);
|
|
}
|
|
|
|
.unit-card.selected {
|
|
border-color: #28a745;
|
|
background-color: #d4edda;
|
|
}
|
|
|
|
.unit-card.incompatible {
|
|
border-color: #dc3545;
|
|
background-color: #f8d7da;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.compatibility-badge {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
}
|
|
|
|
.issue-preview {
|
|
background: #e2e3e5;
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
margin-top: 15px;
|
|
}
|
|
|
|
.verification-checklist {
|
|
background: #f8f9fa;
|
|
border: 2px solid #28a745;
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
margin-top: 15px;
|
|
}
|
|
|
|
.transport-info {
|
|
background: #e9ecef;
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
margin-top: 15px;
|
|
}
|
|
</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_request_list' %}">Blood Requests</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'blood_bank:blood_request_detail' blood_request.id %}">{{ blood_request.request_number }}</a></li>
|
|
<li class="breadcrumb-item active">Issue Blood</li>
|
|
</ol>
|
|
<!-- END breadcrumb -->
|
|
|
|
<!-- BEGIN page-header -->
|
|
<h1 class="page-header">
|
|
Issue Blood Unit
|
|
<small>Request #{{ blood_request.request_number }}</small>
|
|
{% if blood_request.urgency == 'emergency' %}
|
|
<span class="badge bg-danger ms-2">EMERGENCY</span>
|
|
{% endif %}
|
|
</h1>
|
|
<!-- END page-header -->
|
|
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">
|
|
<i class="fa fa-shipping-fast"></i> Blood Unit Issue
|
|
</h4>
|
|
<div class="panel-heading-btn">
|
|
<span class="badge bg-info">Request: {{ blood_request.request_number }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="panel-body">
|
|
<form method="post" id="bloodIssueForm">
|
|
{% csrf_token %}
|
|
|
|
<!-- BEGIN request information -->
|
|
<div class="form-section {% if blood_request.urgency == 'emergency' %}emergency-section{% else %}request-info{% endif %}">
|
|
<h5><i class="fa fa-file-medical"></i> Blood Request Information</h5>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<table class="table table-borderless mb-0">
|
|
<tr>
|
|
<td class="fw-bold">Request Number:</td>
|
|
<td>{{ blood_request.request_number }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Patient:</td>
|
|
<td>{{ blood_request.patient.full_name }} ({{ blood_request.patient.patient_id }})</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Blood Group:</td>
|
|
<td><span class="badge bg-primary">{{ blood_request.patient.blood_group.display_name }}</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Component Requested:</td>
|
|
<td>{{ blood_request.component.get_name_display }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<table class="table table-borderless mb-0">
|
|
<tr>
|
|
<td class="fw-bold">Quantity:</td>
|
|
<td>{{ blood_request.quantity_requested }} units</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Urgency:</td>
|
|
<td>
|
|
<span class="badge bg-{% if blood_request.urgency == 'emergency' %}danger{% elif blood_request.urgency == 'urgent' %}warning{% else %}info{% endif %}">
|
|
{{ blood_request.get_urgency_display }}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Requested By:</td>
|
|
<td>{{ blood_request.requested_by.get_full_name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Department:</td>
|
|
<td>{{ blood_request.department.name }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{% if blood_request.special_requirements %}
|
|
<div class="mt-3">
|
|
<h6>Special Requirements:</h6>
|
|
<div class="alert alert-info">{{ blood_request.special_requirements }}</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<!-- END request information -->
|
|
|
|
<!-- BEGIN unit selection -->
|
|
<div class="form-section unit-selection">
|
|
<h5><i class="fa fa-tint"></i> Available Blood Units</h5>
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<p class="text-muted">Select compatible blood units for this request. Units are filtered by blood group compatibility and availability.</p>
|
|
|
|
<div id="availableUnits">
|
|
{% for unit in available_units %}
|
|
<div class="unit-card position-relative" data-unit-id="{{ unit.id }}" onclick="selectUnit(this)">
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<h6>{{ unit.unit_number }}</h6>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<small class="text-muted">Blood Group:</small><br>
|
|
<span class="badge bg-primary">{{ unit.blood_group.display_name }}</span>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<small class="text-muted">Component:</small><br>
|
|
{{ unit.component.get_name_display }}
|
|
</div>
|
|
</div>
|
|
<div class="row mt-2">
|
|
<div class="col-md-6">
|
|
<small class="text-muted">Volume:</small><br>
|
|
{{ unit.volume_ml }} ml
|
|
</div>
|
|
<div class="col-md-6">
|
|
<small class="text-muted">Expiry:</small><br>
|
|
{{ unit.expiry_date|date:"M d, Y" }}
|
|
{% if unit.days_to_expiry <= 3 %}
|
|
<span class="badge bg-warning">Expires Soon</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="text-end">
|
|
<small class="text-muted">Donor:</small><br>
|
|
{{ unit.donor.full_name }}<br>
|
|
<small class="text-muted">Collection:</small><br>
|
|
{{ unit.collection_date|date:"M d, Y" }}<br>
|
|
<small class="text-muted">Location:</small><br>
|
|
{{ unit.location.name }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Compatibility badge -->
|
|
<div class="compatibility-badge">
|
|
{% if unit.is_compatible %}
|
|
<span class="badge bg-success">Compatible</span>
|
|
{% else %}
|
|
<span class="badge bg-danger">Check Required</span>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Crossmatch status -->
|
|
{% if unit.crossmatch_status %}
|
|
<div class="mt-2">
|
|
<small class="text-muted">Crossmatch:</small>
|
|
<span class="badge bg-{% if unit.crossmatch_status == 'compatible' %}success{% elif unit.crossmatch_status == 'incompatible' %}danger{% else %}warning{% endif %}">
|
|
{{ unit.crossmatch_status|title }}
|
|
</span>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% empty %}
|
|
<div class="alert alert-warning">
|
|
<i class="fa fa-exclamation-triangle"></i> No compatible blood units available for this request.
|
|
<br>Please check inventory or contact blood bank supervisor.
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<input type="hidden" name="selected_units" id="selectedUnits" value="">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END unit selection -->
|
|
|
|
<!-- BEGIN issue details -->
|
|
<div class="form-section">
|
|
<h5><i class="fa fa-info-circle"></i> Issue Details</h5>
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<div class="form-group">
|
|
<label for="issueDate" class="form-label">
|
|
Issue Date & Time <span class="required-field">*</span>
|
|
</label>
|
|
<input type="datetime-local" class="form-control" id="issueDate" name="issue_date" required>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-group">
|
|
<label for="issuedBy" class="form-label">
|
|
Issued By <span class="required-field">*</span>
|
|
</label>
|
|
<select class="form-select" id="issuedBy" name="issued_by" required>
|
|
<option value="">Select staff member...</option>
|
|
{% for staff in blood_bank_staff %}
|
|
<option value="{{ staff.id }}">{{ staff.get_full_name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-group">
|
|
<label for="receivedBy" class="form-label">
|
|
Received By <span class="required-field">*</span>
|
|
</label>
|
|
<select class="form-select" id="receivedBy" name="received_by" required>
|
|
<option value="">Select receiving staff...</option>
|
|
{% for staff in clinical_staff %}
|
|
<option value="{{ staff.id }}">{{ staff.get_full_name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END issue details -->
|
|
|
|
<!-- BEGIN transport information -->
|
|
<div class="form-section">
|
|
<h5><i class="fa fa-truck"></i> Transport Information</h5>
|
|
<div class="transport-info">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="transportMethod" class="form-label">
|
|
Transport Method <span class="required-field">*</span>
|
|
</label>
|
|
<select class="form-select" id="transportMethod" name="transport_method" required>
|
|
<option value="">Select method...</option>
|
|
<option value="hand_carry">Hand Carry</option>
|
|
<option value="pneumatic_tube">Pneumatic Tube</option>
|
|
<option value="courier">Courier Service</option>
|
|
<option value="emergency_transport">Emergency Transport</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="transportContainer" class="form-label">
|
|
Transport Container <span class="required-field">*</span>
|
|
</label>
|
|
<select class="form-select" id="transportContainer" name="transport_container" required>
|
|
<option value="">Select container...</option>
|
|
<option value="insulated_bag">Insulated Transport Bag</option>
|
|
<option value="cooler_box">Cooler Box</option>
|
|
<option value="temperature_controlled">Temperature Controlled Container</option>
|
|
<option value="emergency_kit">Emergency Transport Kit</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="transportTemperature" class="form-label">
|
|
Transport Temperature (°C)
|
|
</label>
|
|
<input type="number" step="0.1" class="form-control" id="transportTemperature"
|
|
name="transport_temperature" placeholder="2-6°C" min="1" max="10">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="estimatedDelivery" class="form-label">
|
|
Estimated Delivery Time
|
|
</label>
|
|
<input type="datetime-local" class="form-control" id="estimatedDelivery" name="estimated_delivery">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END transport information -->
|
|
|
|
<!-- BEGIN verification checklist -->
|
|
<div class="form-section safety-checks">
|
|
<h5><i class="fa fa-shield-alt"></i> Pre-Issue Verification Checklist</h5>
|
|
<div class="verification-checklist">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6>Unit Verification</h6>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="unitNumberVerified" required>
|
|
<label class="form-check-label" for="unitNumberVerified">
|
|
Blood unit number verified against request
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="bloodGroupVerified" required>
|
|
<label class="form-check-label" for="bloodGroupVerified">
|
|
Blood group compatibility verified
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="expiryDateChecked" required>
|
|
<label class="form-check-label" for="expiryDateChecked">
|
|
Expiry date checked and valid
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="visualInspection" required>
|
|
<label class="form-check-label" for="visualInspection">
|
|
Visual inspection completed (no clots, discoloration)
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6>Documentation & Testing</h6>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="crossmatchCompleted" required>
|
|
<label class="form-check-label" for="crossmatchCompleted">
|
|
Crossmatch completed and compatible
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="testingCompleted" required>
|
|
<label class="form-check-label" for="testingCompleted">
|
|
All required testing completed and negative
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="patientIdentityVerified" required>
|
|
<label class="form-check-label" for="patientIdentityVerified">
|
|
Patient identity verified (2 identifiers)
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="requestAuthorized" required>
|
|
<label class="form-check-label" for="requestAuthorized">
|
|
Request properly authorized by physician
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mt-3">
|
|
<div class="col-md-12">
|
|
<h6>Emergency Procedures (if applicable)</h6>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="emergencyProtocol">
|
|
<label class="form-check-label" for="emergencyProtocol">
|
|
Emergency release protocol followed (if applicable)
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="emergencyConsent">
|
|
<label class="form-check-label" for="emergencyConsent">
|
|
Emergency consent documented (if applicable)
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END verification checklist -->
|
|
|
|
<!-- BEGIN special instructions -->
|
|
<div class="form-section">
|
|
<h5><i class="fa fa-clipboard-list"></i> Special Instructions & Notes</h5>
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="form-group">
|
|
<label for="issueNotes" class="form-label">Issue Notes</label>
|
|
<textarea class="form-control" id="issueNotes" name="issue_notes" rows="3"
|
|
placeholder="Any special handling instructions, observations, or notes..."></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="handlingInstructions" class="form-label">Handling Instructions</label>
|
|
<select class="form-select" id="handlingInstructions" name="handling_instructions">
|
|
<option value="">Select if applicable...</option>
|
|
<option value="keep_refrigerated">Keep Refrigerated (2-6°C)</option>
|
|
<option value="room_temperature">Room Temperature (20-24°C)</option>
|
|
<option value="immediate_use">For Immediate Use</option>
|
|
<option value="irradiated">Irradiated Product</option>
|
|
<option value="cmv_negative">CMV Negative</option>
|
|
<option value="leukoreduced">Leukoreduced</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="returnTime" class="form-label">Return Time Limit</label>
|
|
<input type="datetime-local" class="form-control" id="returnTime" name="return_time_limit"
|
|
placeholder="If not used, return by...">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END special instructions -->
|
|
|
|
<!-- BEGIN issue preview -->
|
|
<div class="issue-preview">
|
|
<h6><i class="fa fa-eye"></i> Issue Summary</h6>
|
|
<div id="issueSummary">
|
|
<p class="text-muted">Select blood units and complete the form to preview issue details</p>
|
|
</div>
|
|
</div>
|
|
<!-- END issue preview -->
|
|
|
|
<!-- BEGIN form actions -->
|
|
<div class="d-flex justify-content-between mt-4">
|
|
<a href="{% url 'blood_bank:blood_request_detail' blood_request.id %}" class="btn btn-secondary">
|
|
<i class="fa fa-arrow-left"></i> Cancel
|
|
</a>
|
|
<div>
|
|
<button type="button" class="btn btn-info" onclick="validateIssue()">
|
|
<i class="fa fa-check"></i> Validate Issue
|
|
</button>
|
|
<button type="submit" class="btn btn-primary" id="submitBtn" disabled>
|
|
<i class="fa fa-shipping-fast"></i> Issue Blood Units
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<!-- END form actions -->
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script src="{% static 'plugins/select2/dist/js/select2.min.js' %}"></script>
|
|
|
|
<script>
|
|
var selectedUnits = [];
|
|
|
|
$(document).ready(function() {
|
|
// Initialize Select2
|
|
$('#issuedBy, #receivedBy, #transportMethod, #transportContainer, #handlingInstructions').select2({
|
|
theme: 'bootstrap-5'
|
|
});
|
|
|
|
// Set default issue date to now
|
|
var now = new Date();
|
|
$('#issueDate').val(now.toISOString().slice(0, 16));
|
|
|
|
// Set estimated delivery time (30 minutes from now)
|
|
var deliveryTime = new Date(now.getTime() + 30 * 60000);
|
|
$('#estimatedDelivery').val(deliveryTime.toISOString().slice(0, 16));
|
|
|
|
// Set return time limit (4 hours from now for RBC, 6 hours for platelets)
|
|
var returnTime = new Date(now.getTime() + 4 * 60 * 60000);
|
|
$('#returnTime').val(returnTime.toISOString().slice(0, 16));
|
|
|
|
// Update displays when form changes
|
|
updateIssueSummary();
|
|
|
|
// Event listeners
|
|
$('.verification-checklist input[type="checkbox"]').on('change', function() {
|
|
validateVerificationChecklist();
|
|
});
|
|
|
|
$('#transportMethod, #transportContainer').on('change', function() {
|
|
updateIssueSummary();
|
|
});
|
|
|
|
// Form validation
|
|
$('#bloodIssueForm').on('submit', function(e) {
|
|
if (!validateIssue()) {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
});
|
|
|
|
function selectUnit(unitCard) {
|
|
var unitId = $(unitCard).data('unit-id');
|
|
|
|
if ($(unitCard).hasClass('incompatible')) {
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Incompatible Unit',
|
|
text: 'This unit may not be compatible. Please verify crossmatch results.',
|
|
confirmButtonText: 'OK'
|
|
});
|
|
return;
|
|
}
|
|
|
|
if ($(unitCard).hasClass('selected')) {
|
|
// Deselect unit
|
|
$(unitCard).removeClass('selected');
|
|
selectedUnits = selectedUnits.filter(id => id !== unitId);
|
|
} else {
|
|
// Select unit
|
|
$(unitCard).addClass('selected');
|
|
selectedUnits.push(unitId);
|
|
}
|
|
|
|
$('#selectedUnits').val(selectedUnits.join(','));
|
|
updateIssueSummary();
|
|
validateIssue();
|
|
}
|
|
|
|
function updateIssueSummary() {
|
|
if (selectedUnits.length === 0) {
|
|
$('#issueSummary').html('<p class="text-muted">Select blood units and complete the form to preview issue details</p>');
|
|
return;
|
|
}
|
|
|
|
var summaryHtml = '<div class="row">';
|
|
summaryHtml += '<div class="col-md-6">';
|
|
summaryHtml += '<h6>Selected Units (' + selectedUnits.length + ')</h6>';
|
|
|
|
selectedUnits.forEach(function(unitId) {
|
|
var unitCard = $('.unit-card[data-unit-id="' + unitId + '"]');
|
|
var unitNumber = unitCard.find('h6').text();
|
|
summaryHtml += '<div class="badge bg-success me-1 mb-1">' + unitNumber + '</div>';
|
|
});
|
|
|
|
summaryHtml += '</div>';
|
|
summaryHtml += '<div class="col-md-6">';
|
|
summaryHtml += '<h6>Issue Details</h6>';
|
|
|
|
var issuedBy = $('#issuedBy option:selected').text();
|
|
var receivedBy = $('#receivedBy option:selected').text();
|
|
var transportMethod = $('#transportMethod option:selected').text();
|
|
var issueDate = $('#issueDate').val();
|
|
|
|
if (issuedBy && issuedBy !== 'Select staff member...') {
|
|
summaryHtml += '<p><strong>Issued By:</strong> ' + issuedBy + '</p>';
|
|
}
|
|
if (receivedBy && receivedBy !== 'Select receiving staff...') {
|
|
summaryHtml += '<p><strong>Received By:</strong> ' + receivedBy + '</p>';
|
|
}
|
|
if (transportMethod && transportMethod !== 'Select method...') {
|
|
summaryHtml += '<p><strong>Transport:</strong> ' + transportMethod + '</p>';
|
|
}
|
|
if (issueDate) {
|
|
summaryHtml += '<p><strong>Issue Time:</strong> ' + new Date(issueDate).toLocaleString() + '</p>';
|
|
}
|
|
|
|
summaryHtml += '</div>';
|
|
summaryHtml += '</div>';
|
|
|
|
// Add emergency warning if applicable
|
|
{% if blood_request.urgency == 'emergency' %}
|
|
summaryHtml += '<div class="alert alert-danger mt-2">';
|
|
summaryHtml += '<strong>⚠️ EMERGENCY ISSUE:</strong> Expedited processing and transport required.';
|
|
summaryHtml += '</div>';
|
|
{% endif %}
|
|
|
|
$('#issueSummary').html(summaryHtml);
|
|
}
|
|
|
|
function validateVerificationChecklist() {
|
|
var checkboxes = $('.verification-checklist input[type="checkbox"]:not(#emergencyProtocol):not(#emergencyConsent)');
|
|
var checkedCount = checkboxes.filter(':checked').length;
|
|
var totalCount = checkboxes.length;
|
|
|
|
$('#submitBtn').prop('disabled', checkedCount < totalCount || selectedUnits.length === 0);
|
|
|
|
if (checkedCount === totalCount) {
|
|
$('.verification-checklist').removeClass('border-warning').addClass('border-success');
|
|
} else {
|
|
$('.verification-checklist').removeClass('border-success').addClass('border-warning');
|
|
}
|
|
}
|
|
|
|
function validateIssue() {
|
|
var errors = [];
|
|
|
|
// Check selected units
|
|
if (selectedUnits.length === 0) {
|
|
errors.push('Please select at least one blood unit');
|
|
}
|
|
|
|
// Check required fields
|
|
if (!$('#issueDate').val()) {
|
|
errors.push('Please enter issue date and time');
|
|
}
|
|
|
|
if (!$('#issuedBy').val()) {
|
|
errors.push('Please select who is issuing the blood');
|
|
}
|
|
|
|
if (!$('#receivedBy').val()) {
|
|
errors.push('Please select who is receiving the blood');
|
|
}
|
|
|
|
if (!$('#transportMethod').val()) {
|
|
errors.push('Please select transport method');
|
|
}
|
|
|
|
if (!$('#transportContainer').val()) {
|
|
errors.push('Please select transport container');
|
|
}
|
|
|
|
// Check verification checklist
|
|
var requiredCheckboxes = $('.verification-checklist input[type="checkbox"]:not(#emergencyProtocol):not(#emergencyConsent)');
|
|
var checkedCount = requiredCheckboxes.filter(':checked').length;
|
|
|
|
if (checkedCount < requiredCheckboxes.length) {
|
|
errors.push('Please complete all verification checklist items');
|
|
}
|
|
|
|
// Check quantity match
|
|
var requestedQuantity = {{ blood_request.units_requested }};
|
|
if (selectedUnits.length !== requestedQuantity) {
|
|
errors.push('Selected units (' + selectedUnits.length + ') do not match requested quantity (' + requestedQuantity + ')');
|
|
}
|
|
|
|
// Enable/disable submit button
|
|
$('#submitBtn').prop('disabled', errors.length > 0);
|
|
|
|
if (errors.length > 0) {
|
|
if (errors.length < 8) { // Only show errors if validation was explicitly requested
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Validation Errors',
|
|
html: '<ul class="text-start"><li>' + errors.join('</li><li>') + '</li></ul>',
|
|
confirmButtonText: 'OK'
|
|
});
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Validation Passed',
|
|
text: 'All requirements met. Ready to issue blood units.',
|
|
timer: 1500,
|
|
showConfirmButton: false
|
|
});
|
|
|
|
return true;
|
|
}
|
|
</script>
|
|
{% endblock %}
|
|
|