Marwan Alwali b9b8c69129 update
2025-08-31 10:47:23 +03:00

817 lines
31 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}
{% if template.pk %}Edit Template - {{ template.name }}{% else %}Create Surgical Template{% endif %}
{% endblock %}
{% block css %}
<style>
.form-section {
background: white;
border: 1px solid #dee2e6;
border-radius: 0.375rem;
margin-bottom: 1.5rem;
}
.section-header {
background: #f8f9fa;
border-bottom: 1px solid #dee2e6;
padding: 1rem 1.5rem;
font-weight: 600;
color: #495057;
display: flex;
align-items: center;
justify-content: between;
}
.section-content {
padding: 1.5rem;
}
.step-builder {
border: 1px solid #dee2e6;
border-radius: 0.375rem;
margin-bottom: 1rem;
}
.step-header {
background: #f8f9fa;
padding: 1rem;
border-bottom: 1px solid #dee2e6;
display: flex;
align-items: center;
justify-content: between;
}
.step-number {
background: #007bff;
color: white;
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 0.875rem;
}
.step-content {
padding: 1rem;
}
.equipment-item {
border: 1px solid #dee2e6;
border-radius: 0.25rem;
padding: 1rem;
margin-bottom: 1rem;
background: #f8f9fa;
}
.team-member-item {
border: 1px solid #dee2e6;
border-radius: 0.25rem;
padding: 1rem;
margin-bottom: 1rem;
background: white;
}
.duration-calculator {
background: #e7f3ff;
border: 1px solid #b3d9ff;
border-radius: 0.375rem;
padding: 1rem;
margin-bottom: 1rem;
}
.preview-section {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 0.375rem;
padding: 1.5rem;
margin-bottom: 1.5rem;
}
.form-actions {
background: white;
border-top: 1px solid #dee2e6;
padding: 1.5rem;
position: sticky;
bottom: 0;
z-index: 100;
}
.complexity-indicator {
display: inline-block;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
font-size: 0.75rem;
font-weight: 600;
}
.complexity-simple { background: #d4edda; color: #155724; }
.complexity-moderate { background: #fff3cd; color: #856404; }
.complexity-complex { background: #f8d7da; color: #721c24; }
.complexity-highly-complex { background: #d1ecf1; color: #0c5460; }
.drag-handle {
cursor: move;
color: #6c757d;
}
.drag-handle:hover {
color: #495057;
}
@media (max-width: 768px) {
.section-content {
padding: 1rem;
}
.step-header {
flex-direction: column;
align-items: flex-start;
}
.form-actions {
position: static;
}
}
</style>
{% endblock %}
{% block content %}
<div id="content" class="app-content">
<!-- Page Header -->
<div class="d-flex align-items-center mb-3">
<div>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'operating_theatre:dashboard' %}">Operating Theatre</a></li>
<li class="breadcrumb-item"><a href="{% url 'operating_theatre:template_list' %}">Templates</a></li>
<li class="breadcrumb-item active">
{% if template.pk %}Edit Template{% else %}Create Template{% endif %}
</li>
</ol>
<h1 class="page-header mb-0">
<i class="fas fa-file-medical me-2"></i>
{% if template.pk %}Edit Template{% else %}Create Surgical Template{% endif %}
</h1>
</div>
<div class="ms-auto">
<button type="button" class="btn btn-outline-secondary me-2" onclick="previewTemplate()">
<i class="fas fa-eye me-1"></i>Preview
</button>
<a href="{% url 'operating_theatre:template_list' %}" class="btn btn-outline-secondary">
<i class="fas fa-arrow-left me-1"></i>Back to List
</a>
</div>
</div>
<form method="post" id="templateForm">
{% csrf_token %}
<!-- Basic Information -->
<div class="form-section">
<div class="section-header">
<div>
<i class="fas fa-info-circle me-2"></i>Basic Information
</div>
</div>
<div class="section-content">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Template Name *</label>
{{ form.name }}
{% if form.name.errors %}
<div class="text-danger small">{{ form.name.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Specialty *</label>
{{ form.specialty }}
{% if form.specialty.errors %}
<div class="text-danger small">{{ form.specialty.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Description</label>
{{ form.description }}
{% if form.description.errors %}
<div class="text-danger small">{{ form.description.errors.0 }}</div>
{% endif %}
</div>
<div class="row">
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Procedure Type</label>
{{ form.procedure_type }}
{% if form.procedure_type.errors %}
<div class="text-danger small">{{ form.procedure_type.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Complexity</label>
{{ form.complexity }}
{% if form.complexity.errors %}
<div class="text-danger small">{{ form.complexity.errors.0 }}</div>
{% endif %}
<div id="complexityIndicator" class="mt-1"></div>
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Status</label>
{{ form.status }}
{% if form.status.errors %}
<div class="text-danger small">{{ form.status.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<!-- Duration and Requirements -->
<div class="form-section">
<div class="section-header">
<div>
<i class="fas fa-clock me-2"></i>Duration and Requirements
</div>
</div>
<div class="section-content">
<div class="duration-calculator">
<h6 class="mb-3">
<i class="fas fa-calculator me-2"></i>Duration Calculator
</h6>
<div class="row">
<div class="col-md-3">
<label class="form-label">Estimated Duration (minutes)</label>
{{ form.estimated_duration }}
{% if form.estimated_duration.errors %}
<div class="text-danger small">{{ form.estimated_duration.errors.0 }}</div>
{% endif %}
</div>
<div class="col-md-3">
<label class="form-label">Setup Time (minutes)</label>
<input type="number" class="form-control" id="setupTime" value="15" min="0">
</div>
<div class="col-md-3">
<label class="form-label">Cleanup Time (minutes)</label>
<input type="number" class="form-control" id="cleanupTime" value="10" min="0">
</div>
<div class="col-md-3">
<label class="form-label">Total Time</label>
<input type="text" class="form-control" id="totalTime" readonly>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Required Team Size</label>
{{ form.required_team_size }}
{% if form.required_team_size.errors %}
<div class="text-danger small">{{ form.required_team_size.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Anesthesia Type</label>
{{ form.anesthesia_type }}
{% if form.anesthesia_type.errors %}
<div class="text-danger small">{{ form.anesthesia_type.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Patient Position</label>
{{ form.patient_position }}
{% if form.patient_position.errors %}
<div class="text-danger small">{{ form.patient_position.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-check">
{{ form.requires_anesthesia }}
<label class="form-check-label" for="{{ form.requires_anesthesia.id_for_label }}">
Requires Anesthesia
</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
{{ form.is_emergency_procedure }}
<label class="form-check-label" for="{{ form.is_emergency_procedure.id_for_label }}">
Emergency Procedure
</label>
</div>
</div>
</div>
</div>
</div>
<!-- Procedure Steps -->
<div class="form-section">
<div class="section-header">
<div>
<i class="fas fa-list-ol me-2"></i>Procedure Steps
</div>
<button type="button" class="btn btn-sm btn-primary" onclick="addStep()">
<i class="fas fa-plus me-1"></i>Add Step
</button>
</div>
<div class="section-content">
<div id="stepsContainer">
<!-- Steps will be dynamically added here -->
</div>
<div class="text-center py-3" id="noStepsMessage">
<i class="fas fa-list-ol fa-2x text-muted mb-2"></i>
<p class="text-muted">No procedure steps added yet</p>
<button type="button" class="btn btn-outline-primary" onclick="addStep()">
<i class="fas fa-plus me-1"></i>Add First Step
</button>
</div>
</div>
</div>
<!-- Required Equipment -->
<div class="form-section">
<div class="section-header">
<div>
<i class="fas fa-tools me-2"></i>Required Equipment
</div>
<button type="button" class="btn btn-sm btn-primary" onclick="addEquipment()">
<i class="fas fa-plus me-1"></i>Add Equipment
</button>
</div>
<div class="section-content">
<div id="equipmentContainer">
<!-- Equipment will be dynamically added here -->
</div>
<div class="text-center py-3" id="noEquipmentMessage">
<i class="fas fa-tools fa-2x text-muted mb-2"></i>
<p class="text-muted">No equipment requirements added yet</p>
<button type="button" class="btn btn-outline-primary" onclick="addEquipment()">
<i class="fas fa-plus me-1"></i>Add Equipment
</button>
</div>
</div>
</div>
<!-- Required Team -->
<div class="form-section">
<div class="section-header">
<div>
<i class="fas fa-users me-2"></i>Required Team
</div>
<button type="button" class="btn btn-sm btn-primary" onclick="addTeamMember()">
<i class="fas fa-plus me-1"></i>Add Team Member
</button>
</div>
<div class="section-content">
<div id="teamContainer">
<!-- Team members will be dynamically added here -->
</div>
<div class="text-center py-3" id="noTeamMessage">
<i class="fas fa-users fa-2x text-muted mb-2"></i>
<p class="text-muted">No team requirements added yet</p>
<button type="button" class="btn btn-outline-primary" onclick="addTeamMember()">
<i class="fas fa-plus me-1"></i>Add Team Member
</button>
</div>
</div>
</div>
<!-- Additional Information -->
<div class="form-section">
<div class="section-header">
<div>
<i class="fas fa-sticky-note me-2"></i>Additional Information
</div>
</div>
<div class="section-content">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Room Requirements</label>
{{ form.room_requirements }}
{% if form.room_requirements.errors %}
<div class="text-danger small">{{ form.room_requirements.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Usage Frequency</label>
{{ form.usage_frequency }}
{% if form.usage_frequency.errors %}
<div class="text-danger small">{{ form.usage_frequency.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Notes</label>
{{ form.notes }}
{% if form.notes.errors %}
<div class="text-danger small">{{ form.notes.errors.0 }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label">Warnings</label>
{{ form.warnings }}
{% if form.warnings.errors %}
<div class="text-danger small">{{ form.warnings.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
</form>
<!-- Form Actions -->
<div class="form-actions">
<div class="d-flex justify-content-between align-items-center">
<div>
<button type="button" class="btn btn-outline-secondary" onclick="saveDraft()">
<i class="fas fa-save me-1"></i>Save as Draft
</button>
</div>
<div>
<a href="{% url 'operating_theatre:template_list' %}" class="btn btn-outline-secondary me-2">
<i class="fas fa-times me-1"></i>Cancel
</a>
<button type="submit" form="templateForm" class="btn btn-primary">
<i class="fas fa-check me-1"></i>
{% if template.pk %}Update Template{% else %}Create Template{% endif %}
</button>
</div>
</div>
</div>
</div>
<!-- Preview Modal -->
<div class="modal fade" id="previewModal" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fas fa-eye me-2"></i>Template Preview
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" id="previewContent">
<!-- Preview content will be loaded here -->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script>
let stepCounter = 0;
let equipmentCounter = 0;
let teamCounter = 0;
$(document).ready(function() {
// Initialize duration calculator
updateTotalTime();
$('#setupTime, #cleanupTime').on('input', updateTotalTime);
$('#id_estimated_duration').on('input', updateTotalTime);
// Initialize complexity indicator
updateComplexityIndicator();
$('#id_complexity').on('change', updateComplexityIndicator);
// Load existing data if editing
{% if template.pk %}
loadExistingData();
{% endif %}
});
function updateTotalTime() {
const procedureTime = parseInt($('#id_estimated_duration').val()) || 0;
const setupTime = parseInt($('#setupTime').val()) || 0;
const cleanupTime = parseInt($('#cleanupTime').val()) || 0;
const total = procedureTime + setupTime + cleanupTime;
$('#totalTime').val(total + ' minutes');
}
function updateComplexityIndicator() {
const complexity = $('#id_complexity').val();
const indicator = $('#complexityIndicator');
indicator.removeClass('complexity-simple complexity-moderate complexity-complex complexity-highly-complex');
if (complexity) {
indicator.addClass('complexity-' + complexity.replace('_', '-'));
indicator.text(complexity.replace('_', ' ').toUpperCase());
indicator.show();
} else {
indicator.hide();
}
}
function addStep() {
stepCounter++;
const stepHtml = `
<div class="step-builder" data-step="${stepCounter}">
<div class="step-header">
<div class="d-flex align-items-center">
<div class="step-number">${stepCounter}</div>
<span class="ms-2 fw-bold">Step ${stepCounter}</span>
</div>
<div>
<button type="button" class="btn btn-sm btn-outline-secondary me-1 drag-handle">
<i class="fas fa-grip-vertical"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-danger" onclick="removeStep(${stepCounter})">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<div class="step-content">
<div class="row">
<div class="col-md-8">
<div class="mb-3">
<label class="form-label">Step Title</label>
<input type="text" class="form-control" name="step_${stepCounter}_title" required>
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Duration (minutes)</label>
<input type="number" class="form-control" name="step_${stepCounter}_duration" min="1">
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Description</label>
<textarea class="form-control" name="step_${stepCounter}_description" rows="3"></textarea>
</div>
<div class="mb-3">
<label class="form-label">Critical Points</label>
<textarea class="form-control" name="step_${stepCounter}_critical_points" rows="2"
placeholder="Important safety considerations or critical steps..."></textarea>
</div>
</div>
</div>
`;
$('#stepsContainer').append(stepHtml);
$('#noStepsMessage').hide();
}
function removeStep(stepId) {
if (confirm('Remove this step?')) {
$(`.step-builder[data-step="${stepId}"]`).remove();
if ($('#stepsContainer .step-builder').length === 0) {
$('#noStepsMessage').show();
}
// Renumber steps
renumberSteps();
}
}
function renumberSteps() {
$('#stepsContainer .step-builder').each(function(index) {
const newNumber = index + 1;
$(this).find('.step-number').text(newNumber);
$(this).find('.step-header span').text(`Step ${newNumber}`);
});
}
function addEquipment() {
equipmentCounter++;
const equipmentHtml = `
<div class="equipment-item" data-equipment="${equipmentCounter}">
<div class="d-flex justify-content-between align-items-start mb-3">
<h6 class="mb-0">Equipment ${equipmentCounter}</h6>
<button type="button" class="btn btn-sm btn-outline-danger" onclick="removeEquipment(${equipmentCounter})">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Equipment Name</label>
<input type="text" class="form-control" name="equipment_${equipmentCounter}_name" required>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Category</label>
<select class="form-select" name="equipment_${equipmentCounter}_category">
<option value="">Select Category</option>
<option value="surgical_instruments">Surgical Instruments</option>
<option value="monitoring">Monitoring Equipment</option>
<option value="anesthesia">Anesthesia Equipment</option>
<option value="imaging">Imaging Equipment</option>
<option value="electrosurgical">Electrosurgical</option>
<option value="positioning">Positioning Equipment</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Quantity</label>
<input type="number" class="form-control" name="equipment_${equipmentCounter}_quantity" value="1" min="1">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Alternatives</label>
<input type="text" class="form-control" name="equipment_${equipmentCounter}_alternatives"
placeholder="Alternative equipment options...">
</div>
</div>
<div class="col-md-6">
<div class="form-check mt-4">
<input type="checkbox" class="form-check-input" name="equipment_${equipmentCounter}_critical" value="1">
<label class="form-check-label">Critical Equipment</label>
</div>
</div>
</div>
</div>
`;
$('#equipmentContainer').append(equipmentHtml);
$('#noEquipmentMessage').hide();
}
function removeEquipment(equipmentId) {
if (confirm('Remove this equipment requirement?')) {
$(`.equipment-item[data-equipment="${equipmentId}"]`).remove();
if ($('#equipmentContainer .equipment-item').length === 0) {
$('#noEquipmentMessage').show();
}
}
}
function addTeamMember() {
teamCounter++;
const teamHtml = `
<div class="team-member-item" data-team="${teamCounter}">
<div class="d-flex justify-content-between align-items-start mb-3">
<h6 class="mb-0">Team Member ${teamCounter}</h6>
<button type="button" class="btn btn-sm btn-outline-danger" onclick="removeTeamMember(${teamCounter})">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="row">
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Role</label>
<select class="form-select" name="team_${teamCounter}_role" required>
<option value="">Select Role</option>
<option value="surgeon">Surgeon</option>
<option value="assistant_surgeon">Assistant Surgeon</option>
<option value="anesthesiologist">Anesthesiologist</option>
<option value="nurse_anesthetist">Nurse Anesthetist</option>
<option value="scrub_nurse">Scrub Nurse</option>
<option value="circulating_nurse">Circulating Nurse</option>
<option value="surgical_technologist">Surgical Technologist</option>
<option value="perfusionist">Perfusionist</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Specialization</label>
<input type="text" class="form-control" name="team_${teamCounter}_specialization"
placeholder="Required specialization...">
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Count</label>
<input type="number" class="form-control" name="team_${teamCounter}_count" value="1" min="1">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Min Experience (years)</label>
<input type="number" class="form-control" name="team_${teamCounter}_experience" min="0">
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Required Certifications</label>
<input type="text" class="form-control" name="team_${teamCounter}_certifications"
placeholder="Required certifications...">
</div>
</div>
</div>
</div>
`;
$('#teamContainer').append(teamHtml);
$('#noTeamMessage').hide();
}
function removeTeamMember(teamId) {
if (confirm('Remove this team member requirement?')) {
$(`.team-member-item[data-team="${teamId}"]`).remove();
if ($('#teamContainer .team-member-item').length === 0) {
$('#noTeamMessage').show();
}
}
}
function previewTemplate() {
// Collect form data and show preview
const formData = new FormData($('#templateForm')[0]);
$.ajax({
url: '{% url "operating_theatre:template_preview" %}',
method: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
$('#previewContent').html(response.html);
$('#previewModal').modal('show');
},
error: function() {
alert('Error generating preview');
}
});
}
function saveDraft() {
$('#id_status').val('draft');
$('#templateForm').submit();
}
function loadExistingData() {
// Load existing steps, equipment, and team data
// This would be populated from the backend
}
// Form validation
$('#templateForm').on('submit', function(e) {
let isValid = true;
// Validate required fields
$(this).find('[required]').each(function() {
if (!$(this).val()) {
isValid = false;
$(this).addClass('is-invalid');
} else {
$(this).removeClass('is-invalid');
}
});
if (!isValid) {
e.preventDefault();
alert('Please fill in all required fields');
}
});
// Auto-save functionality
let autoSaveTimer;
$('#templateForm input, #templateForm textarea, #templateForm select').on('input change', function() {
clearTimeout(autoSaveTimer);
autoSaveTimer = setTimeout(function() {
// Auto-save logic here
console.log('Auto-saving...');
}, 30000); // Auto-save every 30 seconds
});
</script>
{% endblock %}