817 lines
31 KiB
HTML
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 %}
|
|
|