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

659 lines
29 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}{% if form.instance.pk %}Edit QC Record{% else %}New Quality Control Test{% endif %}{% 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;
}
.test-info {
background: #d4edda;
border-left: 4px solid #28a745;
}
.sample-info {
background: #d1ecf1;
border-left: 4px solid #17a2b8;
}
.compliance-info {
background: #fff3cd;
border-left: 4px solid #ffc107;
}
.test-parameters {
background: #e2e3e5;
border-radius: 8px;
padding: 15px;
margin-top: 15px;
}
.parameter-input {
margin-bottom: 10px;
}
.range-indicator {
font-size: 0.9em;
color: #6c757d;
}
.result-preview {
background: #f8f9fa;
border: 2px dashed #6c757d;
border-radius: 8px;
padding: 15px;
text-align: center;
margin-top: 15px;
}
.compliance-check {
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:quality_control_list' %}">Quality Control</a></li>
{% if form.instance.pk %}
<li class="breadcrumb-item"><a href="{% url 'blood_bank:quality_control_detail' form.instance.id %}">{{ form.instance.qc_id }}</a></li>
<li class="breadcrumb-item active">Edit</li>
{% else %}
<li class="breadcrumb-item active">New QC Test</li>
{% endif %}
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">
{% if form.instance.pk %}
Edit QC Record <small>{{ form.instance.qc_id }}</small>
{% else %}
New Quality Control Test <small>ensure blood safety</small>
{% endif %}
</h1>
<!-- END page-header -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">
<i class="fa fa-flask"></i> Quality Control Test Information
</h4>
<div class="panel-heading-btn">
<span class="badge bg-info">QC ID: {{ form.instance.qc_id|default:'Auto-generated' }}</span>
</div>
</div>
<div class="panel-body">
<form method="post" id="qcForm">
{% csrf_token %}
<!-- BEGIN test identification -->
<div class="form-section test-info">
<h5><i class="fa fa-vial"></i> Test Identification</h5>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label for="{{ form.test_type.id_for_label }}" class="form-label">
Test Type <span class="required-field">*</span>
</label>
<select class="form-select" name="{{ form.test_type.name }}" id="{{ form.test_type.id_for_label }}" required>
<option value="">Select test type...</option>
{% for value, label in form.test_type.field.choices %}
<option value="{{ value }}" {% if form.test_type.value == value %}selected{% endif %}>
{{ label }}
</option>
{% endfor %}
</select>
{% if form.test_type.errors %}
<div class="text-danger">{{ form.test_type.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="{{ form.test_date.id_for_label }}" class="form-label">
Test Date <span class="required-field">*</span>
</label>
<input type="datetime-local" class="form-control" name="{{ form.test_date.name }}"
id="{{ form.test_date.id_for_label }}"
value="{{ form.test_date.value|date:'Y-m-d\TH:i' }}" required>
{% if form.test_date.errors %}
<div class="text-danger">{{ form.test_date.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="{{ form.tested_by.id_for_label }}" class="form-label">
Tested By <span class="required-field">*</span>
</label>
<select class="form-select" name="{{ form.tested_by.name }}" id="{{ form.tested_by.id_for_label }}" required>
<option value="">Select staff member...</option>
{% for staff in form.tested_by.field.queryset %}
<option value="{{ staff.id }}" {% if form.tested_by.value == staff.id %}selected{% endif %}>
{{ staff.get_full_name }}
</option>
{% endfor %}
</select>
{% if form.tested_by.errors %}
<div class="text-danger">{{ form.tested_by.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- END test identification -->
<!-- BEGIN sample information -->
<div class="form-section sample-info">
<h5><i class="fa fa-eye-dropper"></i> Sample Information</h5>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="{{ form.blood_unit.id_for_label }}" class="form-label">
Blood Unit (if applicable)
</label>
<select class="form-select" name="{{ form.blood_unit.name }}" id="{{ form.blood_unit.id_for_label }}">
<option value="">Select blood unit...</option>
{% for unit in form.blood_unit.field.queryset %}
<option value="{{ unit.id }}"
data-blood-group="{{ unit.blood_group.display_name }}"
data-component="{{ unit.component.get_name_display }}"
{% if form.blood_unit.value == unit.id %}selected{% endif %}>
{{ unit.unit_number }} - {{ unit.blood_group.display_name }}
</option>
{% endfor %}
</select>
{% if form.blood_unit.errors %}
<div class="text-danger">{{ form.blood_unit.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="{{ form.sample_id.id_for_label }}" class="form-label">
Sample ID (if no blood unit)
</label>
<input type="text" class="form-control" name="{{ form.sample_id.name }}"
id="{{ form.sample_id.id_for_label }}"
value="{{ form.sample_id.value|default:'' }}"
placeholder="Enter sample identifier">
{% if form.sample_id.errors %}
<div class="text-danger">{{ form.sample_id.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div id="sampleDetails" class="alert alert-info">
<i class="fa fa-info-circle"></i> Select a blood unit or enter sample ID to proceed
</div>
</div>
</div>
</div>
<!-- END sample information -->
<!-- BEGIN test parameters -->
<div class="form-section">
<h5><i class="fa fa-cogs"></i> Test Parameters</h5>
<div id="testParameters">
<p class="text-muted">Select a test type to display relevant parameters</p>
</div>
</div>
<!-- END test parameters -->
<!-- BEGIN test results -->
<div class="form-section">
<h5><i class="fa fa-chart-line"></i> Test Results</h5>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label for="{{ form.result.id_for_label }}" class="form-label">
Result <span class="required-field">*</span>
</label>
<select class="form-select" name="{{ form.result.name }}" id="{{ form.result.id_for_label }}" required>
<option value="">Select result...</option>
{% for value, label in form.result.field.choices %}
<option value="{{ value }}" {% if form.result.value == value %}selected{% endif %}>
{{ label }}
</option>
{% endfor %}
</select>
{% if form.result.errors %}
<div class="text-danger">{{ form.result.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<label for="{{ form.notes.id_for_label }}" class="form-label">Test Notes</label>
<textarea class="form-control" name="{{ form.notes.name }}"
id="{{ form.notes.id_for_label }}" rows="3"
placeholder="Any observations, deviations, or additional notes...">{{ form.notes.value|default:'' }}</textarea>
{% if form.notes.errors %}
<div class="text-danger">{{ form.notes.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<!-- Result preview -->
<div class="result-preview" id="resultPreview">
<i class="fa fa-flask fa-2x text-muted mb-2"></i>
<p class="text-muted mb-0">Test result will be displayed here</p>
</div>
</div>
<!-- END test results -->
<!-- BEGIN compliance check -->
<div class="form-section compliance-info">
<h5><i class="fa fa-shield-alt"></i> Compliance & Standards</h5>
<div class="compliance-check">
<div class="row">
<div class="col-md-6">
<h6>Regulatory Compliance</h6>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="fdaCompliant" checked disabled>
<label class="form-check-label" for="fdaCompliant">
FDA 21 CFR Part 606 Compliant
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="aabbCompliant" checked disabled>
<label class="form-check-label" for="aabbCompliant">
AABB Standards Compliant
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="isoCompliant" checked disabled>
<label class="form-check-label" for="isoCompliant">
ISO 15189 Compliant
</label>
</div>
</div>
<div class="col-md-6">
<h6>Quality Assurance</h6>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="equipment_calibrated" id="equipmentCalibrated">
<label class="form-check-label" for="equipmentCalibrated">
Equipment calibrated and validated
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="controls_passed" id="controlsPassed">
<label class="form-check-label" for="controlsPassed">
Quality controls passed
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="procedure_followed" id="procedureFollowed">
<label class="form-check-label" for="procedureFollowed">
Standard procedure followed
</label>
</div>
</div>
</div>
</div>
</div>
<!-- END compliance check -->
<!-- BEGIN form actions -->
<div class="d-flex justify-content-between mt-4">
<a href="{% if form.instance.pk %}{% url 'blood_bank:quality_control_detail' form.instance.id %}{% else %}{% url 'blood_bank:quality_control_list' %}{% endif %}"
class="btn btn-secondary">
<i class="fa fa-arrow-left"></i> Cancel
</a>
<div>
<button type="button" class="btn btn-info" onclick="validateTest()">
<i class="fa fa-check"></i> Validate Test
</button>
<button type="submit" class="btn btn-primary">
<i class="fa fa-save"></i>
{% if form.instance.pk %}Update QC Record{% else %}Save QC Test{% endif %}
</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>
$(document).ready(function() {
// Initialize Select2
$('#{{ form.blood_unit.id_for_label }}, #{{ form.tested_by.id_for_label }}').select2({
theme: 'bootstrap-5'
});
// Set default test date to now
if (!$('#{{ form.test_date.id_for_label }}').val()) {
var now = new Date();
$('#{{ form.test_date.id_for_label }}').val(now.toISOString().slice(0, 16));
}
// Update displays when form changes
updateSampleDetails();
updateTestParameters();
updateResultPreview();
// Event listeners
$('#{{ form.blood_unit.id_for_label }}, #{{ form.sample_id.id_for_label }}').on('change', function() {
updateSampleDetails();
});
$('#{{ form.test_type.id_for_label }}').on('change', function() {
updateTestParameters();
updateResultPreview();
});
$('#{{ form.result.id_for_label }}').on('change', function() {
updateResultPreview();
});
// Form validation
$('#qcForm').on('submit', function(e) {
if (!validateTest()) {
e.preventDefault();
}
});
});
function updateSampleDetails() {
var bloodUnitId = $('#{{ form.blood_unit.id_for_label }}').val();
var sampleId = $('#{{ form.sample_id.id_for_label }}').val();
if (bloodUnitId) {
var selectedUnit = $('#{{ form.blood_unit.id_for_label }} option:selected');
var bloodGroup = selectedUnit.data('blood-group');
var component = selectedUnit.data('component');
var detailsHtml = '<strong>Blood Unit:</strong> ' + selectedUnit.text() + '<br>';
detailsHtml += '<strong>Component:</strong> ' + component + '<br>';
detailsHtml += '<strong>Blood Group:</strong> ' + bloodGroup;
$('#sampleDetails').html(detailsHtml).removeClass().addClass('alert alert-success');
// Clear sample ID if blood unit is selected
$('#{{ form.sample_id.id_for_label }}').val('');
} else if (sampleId) {
$('#sampleDetails').html('<strong>Sample ID:</strong> ' + sampleId).removeClass().addClass('alert alert-info');
} else {
$('#sampleDetails').html('<i class="fa fa-info-circle"></i> Select a blood unit or enter sample ID to proceed').removeClass().addClass('alert alert-info');
}
}
function updateTestParameters() {
var testType = $('#{{ form.test_type.id_for_label }}').val();
var parametersHtml = '';
switch(testType) {
case 'temperature':
parametersHtml = `
<div class="test-parameters">
<h6>Temperature Testing Parameters</h6>
<div class="row">
<div class="col-md-6">
<div class="parameter-input">
<label class="form-label">Temperature Reading (°C)</label>
<input type="number" step="0.1" class="form-control" name="temperature_value"
placeholder="Enter temperature" min="-10" max="10">
<div class="range-indicator">Acceptable range: 2-6°C</div>
</div>
</div>
<div class="col-md-6">
<div class="parameter-input">
<label class="form-label">Storage Location</label>
<input type="text" class="form-control" name="storage_location"
placeholder="Refrigerator/Freezer ID">
</div>
</div>
</div>
</div>
`;
break;
case 'ph':
parametersHtml = `
<div class="test-parameters">
<h6>pH Testing Parameters</h6>
<div class="row">
<div class="col-md-6">
<div class="parameter-input">
<label class="form-label">pH Value</label>
<input type="number" step="0.01" class="form-control" name="ph_value"
placeholder="Enter pH value" min="6.0" max="8.0">
<div class="range-indicator">Acceptable range: 6.5-7.5</div>
</div>
</div>
<div class="col-md-6">
<div class="parameter-input">
<label class="form-label">Buffer Solution</label>
<input type="text" class="form-control" name="buffer_solution"
placeholder="Buffer type used">
</div>
</div>
</div>
</div>
`;
break;
case 'sterility':
parametersHtml = `
<div class="test-parameters">
<h6>Sterility Testing Parameters</h6>
<div class="row">
<div class="col-md-6">
<div class="parameter-input">
<label class="form-label">Culture Medium</label>
<select class="form-select" name="culture_medium">
<option value="">Select medium...</option>
<option value="tryptic_soy">Tryptic Soy Broth</option>
<option value="thioglycollate">Thioglycollate Medium</option>
<option value="blood_agar">Blood Agar</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="parameter-input">
<label class="form-label">Incubation Period (hours)</label>
<input type="number" class="form-control" name="incubation_period"
placeholder="Hours" min="24" max="168">
<div class="range-indicator">Standard: 72-168 hours</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="parameter-input">
<label class="form-label">Growth Observation</label>
<textarea class="form-control" name="growth_observation" rows="2"
placeholder="Describe any growth observed..."></textarea>
</div>
</div>
</div>
</div>
`;
break;
case 'hemolysis':
parametersHtml = `
<div class="test-parameters">
<h6>Hemolysis Testing Parameters</h6>
<div class="row">
<div class="col-md-6">
<div class="parameter-input">
<label class="form-label">Hemolysis Percentage (%)</label>
<input type="number" step="0.01" class="form-control" name="hemolysis_percentage"
placeholder="Enter percentage" min="0" max="100">
<div class="range-indicator">Acceptable: < 0.8%</div>
</div>
</div>
<div class="col-md-6">
<div class="parameter-input">
<label class="form-label">Visual Assessment</label>
<select class="form-select" name="visual_assessment">
<option value="">Select assessment...</option>
<option value="none">No visible hemolysis</option>
<option value="slight">Slight hemolysis</option>
<option value="moderate">Moderate hemolysis</option>
<option value="severe">Severe hemolysis</option>
</select>
</div>
</div>
</div>
</div>
`;
break;
case 'bacterial_screen':
parametersHtml = `
<div class="test-parameters">
<h6>Bacterial Screening Parameters</h6>
<div class="row">
<div class="col-md-6">
<div class="parameter-input">
<label class="form-label">Screening Method</label>
<select class="form-select" name="screening_method">
<option value="">Select method...</option>
<option value="automated">Automated Detection</option>
<option value="manual">Manual Culture</option>
<option value="rapid">Rapid Test</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="parameter-input">
<label class="form-label">Detection Time (hours)</label>
<input type="number" class="form-control" name="detection_time"
placeholder="Hours to detection" min="1" max="72">
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="parameter-input">
<label class="form-label">Organisms Detected</label>
<textarea class="form-control" name="organisms_detected" rows="2"
placeholder="List any organisms detected..."></textarea>
</div>
</div>
</div>
</div>
`;
break;
default:
parametersHtml = '<p class="text-muted">Select a test type to display relevant parameters</p>';
}
$('#testParameters').html(parametersHtml);
}
function updateResultPreview() {
var testType = $('#{{ form.test_type.id_for_label }}').val();
var result = $('#{{ form.result.id_for_label }}').val();
if (!testType || !result) {
$('#resultPreview').html('<i class="fa fa-flask fa-2x text-muted mb-2"></i><p class="text-muted mb-0">Test result will be displayed here</p>');
return;
}
var resultClass = result === 'passed' ? 'text-success' : result === 'failed' ? 'text-danger' : 'text-warning';
var resultIcon = result === 'passed' ? 'fa-check-circle' : result === 'failed' ? 'fa-times-circle' : 'fa-clock';
var previewHtml = `
<i class="fa ${resultIcon} fa-2x ${resultClass} mb-2"></i>
<h5 class="${resultClass}">${result.charAt(0).toUpperCase() + result.slice(1)}</h5>
<p class="text-muted mb-0">${testType.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase())} Test</p>
`;
$('#resultPreview').html(previewHtml);
}
function validateTest() {
var errors = [];
// Check required fields
if (!$('#{{ form.test_type.id_for_label }}').val()) {
errors.push('Please select a test type');
}
if (!$('#{{ form.tested_by.id_for_label }}').val()) {
errors.push('Please select who performed the test');
}
if (!$('#{{ form.result.id_for_label }}').val()) {
errors.push('Please select test result');
}
// Check sample identification
var bloodUnit = $('#{{ form.blood_unit.id_for_label }}').val();
var sampleId = $('#{{ form.sample_id.id_for_label }}').val();
if (!bloodUnit && !sampleId) {
errors.push('Please select a blood unit or enter a sample ID');
}
// Check quality assurance checkboxes
var qaChecks = ['equipmentCalibrated', 'controlsPassed', 'procedureFollowed'];
var checkedQA = qaChecks.filter(id => document.getElementById(id).checked);
if (checkedQA.length < 2) {
errors.push('Please confirm at least 2 quality assurance requirements');
}
if (errors.length > 0) {
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: 'Quality control test is ready for submission.',
timer: 1500,
showConfirmButton: false
});
return true;
}
</script>
{% endblock %}