566 lines
24 KiB
HTML
566 lines
24 KiB
HTML
{% extends "base.html" %}
|
||
{% load static %}
|
||
|
||
{% block title %}{% if object %}Edit{% else %}Create{% endif %} Surgical Case - Operating Theatre{% endblock %}
|
||
|
||
{% block css %}
|
||
<link href="{% static 'plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css' %}" rel="stylesheet" />
|
||
<link href="{% static 'plugins/bootstrap-timepicker/css/bootstrap-timepicker.min.css' %}" rel="stylesheet" />
|
||
<link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<!-- Breadcrumb -->
|
||
<ol class="breadcrumb float-xl-end">
|
||
<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:surgical_case_list' %}">Surgical Cases</a></li>
|
||
<li class="breadcrumb-item active">{% if object %}Edit{% else %}Create{% endif %} Case</li>
|
||
</ol>
|
||
|
||
<h1 class="page-header">
|
||
{% if object %}Edit Surgical Case{% else %}Create Surgical Case{% endif %}
|
||
<small>{% if object %}{{ object.case_number }}{% else %}New Surgery Scheduling{% endif %}</small>
|
||
</h1>
|
||
|
||
<div class="row">
|
||
<div class="col-xl-8">
|
||
<!-- Main panel -->
|
||
<div class="panel panel-inverse">
|
||
<div class="panel-heading">
|
||
<h4 class="panel-title">Case Information</h4>
|
||
<div class="panel-heading-btn">
|
||
<button type="button" class="btn btn-xs btn-secondary me-2" onclick="saveDraft()">
|
||
<i class="fa fa-save"></i> Save Draft
|
||
</button>
|
||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||
</div>
|
||
</div>
|
||
<div class="panel-body">
|
||
<form method="post" id="case-form" novalidate>
|
||
{% csrf_token %}
|
||
|
||
<!-- Patient -->
|
||
<h6 class="border-bottom pb-2 mb-3">Patient Information</h6>
|
||
<div class="row mb-3">
|
||
<div class="col-md-6">
|
||
<div class="form-floating">
|
||
{{ form.patient }}
|
||
<label for="{{ form.patient.id_for_label }}">Patient <span class="text-danger">*</span></label>
|
||
{% if form.patient.errors %}<div class="invalid-feedback d-block">{{ form.patient.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<div id="patient-info" class="mt-2" style="display:none;">
|
||
<div class="alert alert-info"><div id="patient-details"></div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Surgery -->
|
||
<h6 class="border-bottom pb-2 mb-3">Surgery Information</h6>
|
||
<div class="row mb-3">
|
||
<div class="col-md-6">
|
||
<div class="form-floating">
|
||
{{ form.procedure_name }}
|
||
<label for="{{ form.procedure_name.id_for_label }}">Procedure Name <span class="text-danger">*</span></label>
|
||
{% if form.procedure_name.errors %}<div class="invalid-feedback d-block">{{ form.procedure_name.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<div class="form-floating">
|
||
{{ form.procedure_code }}
|
||
<label for="{{ form.procedure_code.id_for_label }}">Procedure Code</label>
|
||
{% if form.procedure_code.errors %}<div class="invalid-feedback d-block">{{ form.procedure_code.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row mb-3">
|
||
<div class="col-md-4">
|
||
<div class="form-floating">
|
||
{{ form.surgery_type }}
|
||
<label for="{{ form.surgery_type.id_for_label }}">Surgery Type <span class="text-danger">*</span></label>
|
||
{% if form.surgery_type.errors %}<div class="invalid-feedback d-block">{{ form.surgery_type.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<div class="form-floating">
|
||
{{ form.priority }}
|
||
<label for="{{ form.priority.id_for_label }}">Priority <span class="text-danger">*</span></label>
|
||
{% if form.priority.errors %}<div class="invalid-feedback d-block">{{ form.priority.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<div class="form-floating">
|
||
{{ form.estimated_duration }}
|
||
<label for="{{ form.estimated_duration.id_for_label }}">Estimated Duration (minutes) <span class="text-danger">*</span></label>
|
||
{% if form.estimated_duration.errors %}<div class="invalid-feedback d-block">{{ form.estimated_duration.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Scheduling -->
|
||
<h6 class="border-bottom pb-2 mb-3">Scheduling Information</h6>
|
||
<div class="row mb-3">
|
||
<div class="col-md-4">
|
||
<div class="form-floating">
|
||
{{ form.operating_room }}
|
||
<label for="{{ form.operating_room.id_for_label }}">Operating Room <span class="text-danger">*</span></label>
|
||
{% if form.operating_room.errors %}<div class="invalid-feedback d-block">{{ form.operating_room.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
{# Prefer unified DateTimeField if available #}
|
||
{% if form.scheduled_start %}
|
||
<div class="col-md-8">
|
||
<div class="form-floating">
|
||
{{ form.scheduled_start }}
|
||
<label for="{{ form.scheduled_start.id_for_label }}">Scheduled Start <span class="text-danger">*</span></label>
|
||
{% if form.scheduled_start.errors %}<div class="invalid-feedback d-block">{{ form.scheduled_start.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
{% else %}
|
||
<div class="col-md-4">
|
||
<div class="form-floating">
|
||
{{ form.scheduled_date }}
|
||
<label for="{{ form.scheduled_date.id_for_label }}">Scheduled Date <span class="text-danger">*</span></label>
|
||
{% if form.scheduled_date.errors %}<div class="invalid-feedback d-block">{{ form.scheduled_date.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<div class="form-floating">
|
||
{{ form.scheduled_start_time }}
|
||
<label for="{{ form.scheduled_start_time.id_for_label }}">Start Time <span class="text-danger">*</span></label>
|
||
{% if form.scheduled_start_time.errors %}<div class="invalid-feedback d-block">{{ form.scheduled_start_time.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<!-- Availability banner -->
|
||
<div class="row mb-3">
|
||
<div class="col-md-12">
|
||
<div id="room-availability" class="alert alert-info" style="display:none;">
|
||
<i class="fa fa-info-circle me-2"></i><span id="availability-message"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Team -->
|
||
<h6 class="border-bottom pb-2 mb-3">Surgical Team</h6>
|
||
<div class="row mb-3">
|
||
<div class="col-md-6">
|
||
<div class="form-floating">
|
||
{{ form.primary_surgeon }}
|
||
<label for="{{ form.primary_surgeon.id_for_label }}">Primary Surgeon <span class="text-danger">*</span></label>
|
||
{% if form.primary_surgeon.errors %}<div class="invalid-feedback d-block">{{ form.primary_surgeon.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<div class="form-floating">
|
||
{{ form.anesthesiologist }}
|
||
<label for="{{ form.anesthesiologist.id_for_label }}">Anesthesiologist</label>
|
||
{% if form.anesthesiologist.errors %}<div class="invalid-feedback d-block">{{ form.anesthesiologist.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mb-3">
|
||
<label class="form-label">Additional Team Members</label>
|
||
<div id="team-members">
|
||
{% if object %}
|
||
{% for team_member in object.surgical_team.all %}
|
||
<div class="team-member-row mb-2">
|
||
<div class="row">
|
||
<div class="col-md-5">
|
||
<select class="form-select" name="team_member_staff">
|
||
<option value="{{ team_member.staff_member.id }}" selected>{{ team_member.staff_member.get_full_name }}</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-5">
|
||
<input type="text" class="form-control" name="team_member_role" value="{{ team_member.role }}" placeholder="Role">
|
||
</div>
|
||
<div class="col-md-2">
|
||
<button type="button" class="btn btn-outline-danger" onclick="removeTeamMember(this)"><i class="fa fa-times"></i></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
{% endif %}
|
||
</div>
|
||
<button type="button" class="btn btn-outline-primary btn-sm" onclick="addTeamMember()">
|
||
<i class="fa fa-plus me-2"></i>Add Team Member
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Equipment & Supplies -->
|
||
<h6 class="border-bottom pb-2 mb-3">Equipment & Supplies</h6>
|
||
<div class="row mb-3">
|
||
<div class="col-md-6">
|
||
<label class="form-label">Required Equipment</label>
|
||
<div id="equipment-list">
|
||
{% if object %}
|
||
{% for equipment in object.equipment_required.all %}
|
||
<div class="equipment-item mb-2">
|
||
<div class="input-group">
|
||
<select class="form-select" name="equipment">
|
||
<option value="{{ equipment.id }}" selected>{{ equipment.name }}</option>
|
||
</select>
|
||
<button type="button" class="btn btn-outline-danger" onclick="removeEquipment(this)"><i class="fa fa-times"></i></button>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
{% endif %}
|
||
</div>
|
||
<button type="button" class="btn btn-outline-primary btn-sm" onclick="addEquipment()">
|
||
<i class="fa fa-plus me-2"></i>Add Equipment
|
||
</button>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label class="form-label">Required Supplies</label>
|
||
<div id="supplies-list">
|
||
{% if object %}
|
||
{% for supply in object.supplies_required.all %}
|
||
<div class="supply-item mb-2">
|
||
<div class="row">
|
||
<div class="col-8">
|
||
<select class="form-select" name="supply">
|
||
<option value="{{ supply.item.id }}" selected>{{ supply.item.name }}</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-3">
|
||
<input type="number" class="form-control" name="supply_quantity" value="{{ supply.quantity }}" placeholder="Qty" min="1">
|
||
</div>
|
||
<div class="col-1">
|
||
<button type="button" class="btn btn-outline-danger btn-sm" onclick="removeSupply(this)"><i class="fa fa-times"></i></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
{% endif %}
|
||
</div>
|
||
<button type="button" class="btn btn-outline-primary btn-sm" onclick="addSupply()">
|
||
<i class="fa fa-plus me-2"></i>Add Supply
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Notes -->
|
||
<h6 class="border-bottom pb-2 mb-3">Clinical Notes</h6>
|
||
<div class="mb-3">
|
||
<label class="form-label">Pre-operative Notes</label>
|
||
{{ form.pre_operative_notes }}
|
||
{% if form.pre_operative_notes.help_text %}<div class="form-text">{{ form.pre_operative_notes.help_text }}</div>{% endif %}
|
||
{% if form.pre_operative_notes.errors %}<div class="invalid-feedback d-block">{{ form.pre_operative_notes.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label">Special Instructions</label>
|
||
{{ form.special_instructions }}
|
||
{% if form.special_instructions.help_text %}<div class="form-text">{{ form.special_instructions.help_text }}</div>{% endif %}
|
||
{% if form.special_instructions.errors %}<div class="invalid-feedback d-block">{{ form.special_instructions.errors.0 }}</div>{% endif %}
|
||
</div>
|
||
|
||
<!-- Actions -->
|
||
<div class="d-flex justify-content-between mt-4">
|
||
<a href="{% url 'operating_theatre:surgical_case_list' %}" class="btn btn-secondary">
|
||
<i class="fa fa-arrow-left me-2"></i>Cancel
|
||
</a>
|
||
<div>
|
||
<button type="button" class="btn btn-info me-2" onclick="saveDraft()">
|
||
<i class="fa fa-save me-2"></i>Save Draft
|
||
</button>
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="fa fa-check me-2"></i>{% if object %}Update{% else %}Schedule{% endif %} Surgery
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<!-- /Main panel -->
|
||
</div>
|
||
|
||
<div class="col-xl-4">
|
||
<!-- Guidelines -->
|
||
<div class="panel panel-inverse">
|
||
<div class="panel-heading"><h4 class="panel-title">Scheduling Guidelines</h4></div>
|
||
<div class="panel-body">
|
||
<div class="alert alert-info">
|
||
<h6 class="alert-heading">Surgery Scheduling Tips</h6>
|
||
<ul class="mb-0 small">
|
||
<li>Check room availability before scheduling</li>
|
||
<li>Ensure all team members are available</li>
|
||
<li>Verify equipment and supplies are in stock</li>
|
||
<li>Consider patient preparation time</li>
|
||
<li>Allow buffer time between surgeries</li>
|
||
</ul>
|
||
</div>
|
||
<div class="alert alert-warning">
|
||
<h6 class="alert-heading">Priority Guidelines</h6>
|
||
<ul class="mb-0 small">
|
||
<li><strong>Emergency:</strong> Life-threatening conditions</li>
|
||
<li><strong>Urgent:</strong> Within 24–48 hours</li>
|
||
<li><strong>Elective:</strong> Scheduled in advance</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Room schedule -->
|
||
<div class="panel panel-inverse">
|
||
<div class="panel-heading"><h4 class="panel-title">Room Schedule</h4></div>
|
||
<div class="panel-body">
|
||
<div id="room-schedule">
|
||
<p class="text-muted mb-0">Select a room and date to view schedule</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{% if object %}
|
||
<!-- Case status -->
|
||
<div class="panel panel-inverse">
|
||
<div class="panel-heading"><h4 class="panel-title">Case Status</h4></div>
|
||
<div class="panel-body">
|
||
<table class="table table-borderless table-sm">
|
||
<tr>
|
||
<td class="fw-bold" width="110">Status:</td>
|
||
<td>
|
||
<span class="badge bg-{% if object.status == 'SCHEDULED' %}info{% elif object.status == 'IN_PROGRESS' %}warning{% elif object.status == 'COMPLETED' %}success{% else %}secondary{% endif %}">
|
||
{{ object.get_status_display }}
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="fw-bold">Created:</td>
|
||
<td>{{ object.created_at|date:"M d, Y H:i" }}</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="fw-bold">Case #:</td>
|
||
<td><code>{{ object.case_number }}</code></td>
|
||
</tr>
|
||
{% if object.scheduled_start %}
|
||
<tr>
|
||
<td class="fw-bold">Scheduled:</td>
|
||
<td>{{ object.scheduled_start|date:"M d, Y H:i" }}</td>
|
||
</tr>
|
||
{% endif %}
|
||
</table>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block js %}
|
||
<script src="{% static 'plugins/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js' %}"></script>
|
||
<script src="{% static 'plugins/bootstrap-timepicker/js/bootstrap-timepicker.min.js' %}"></script>
|
||
<script src="{% static 'plugins/select2/dist/js/select2.min.js' %}"></script>
|
||
<script>
|
||
// --- CSRF via cookie (consistent across app) ---
|
||
function getCookie(name) {
|
||
const value = `; ${document.cookie}`;
|
||
const parts = value.split(`; ${name}=`);
|
||
if (parts.length === 2) return parts.pop().split(';').shift();
|
||
}
|
||
|
||
// --- Init widgets (fallbacks for split date/time fields) ---
|
||
$(function() {
|
||
// Select2 theme
|
||
$('select').select2({ theme: 'bootstrap-5', width: '100%' });
|
||
|
||
// Only init if the inputs exist (supports unified scheduled_start alternative)
|
||
if ($('#id_scheduled_date').length) {
|
||
$('#id_scheduled_date').datepicker({ format: 'yyyy-mm-dd', startDate: 'today', autoclose: true });
|
||
}
|
||
if ($('#id_scheduled_start_time').length) {
|
||
$('#id_scheduled_start_time').timepicker({ showMeridian: false, defaultTime: '08:00' });
|
||
}
|
||
|
||
// Patient info
|
||
$('#id_patient').on('change', function() {
|
||
const id = $(this).val();
|
||
if (!id) return $('#patient-info').hide();
|
||
loadPatientInfo(id);
|
||
});
|
||
|
||
// Room/date/time changes -> availability & schedule
|
||
$('#id_operating_room, #id_scheduled_date, #id_scheduled_start_time, #id_scheduled_start, #id_estimated_duration').on('change', function() {
|
||
checkRoomAvailability();
|
||
loadRoomSchedule();
|
||
});
|
||
});
|
||
|
||
// --- Patient details ---
|
||
function loadPatientInfo(patientId) {
|
||
fetch('{% url "patients:get_patient_info" 0 %}'.replace('0', patientId), { credentials: 'same-origin' })
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
if (!data.success) return;
|
||
const p = data.patient;
|
||
const html = `
|
||
<strong>${p.name}</strong><br>
|
||
<small>ID: ${p.patient_id} | DOB: ${p.date_of_birth} | Age: ${p.age}</small><br>
|
||
<small>Blood Type: ${p.blood_type || 'Unknown'} | Allergies: ${p.allergies || 'None known'}</small>
|
||
`;
|
||
$('#patient-details').html(html);
|
||
$('#patient-info').show();
|
||
})
|
||
.catch(() => toastr.error('Failed to load patient information'));
|
||
}
|
||
|
||
// --- Availability check (supports both unified and split datetime inputs) ---
|
||
function checkRoomAvailability() {
|
||
const roomId = $('#id_operating_room').val();
|
||
const duration = $('#id_estimated_duration').val();
|
||
|
||
// Unified DateTimeField
|
||
const scheduledStart = $('#id_scheduled_start').val();
|
||
|
||
// Split date & time fields
|
||
const date = $('#id_scheduled_date').val();
|
||
const time = $('#id_scheduled_start_time').val();
|
||
|
||
let payload = { room_id: roomId, duration, case_id: '{{ object.id|default:"" }}' };
|
||
|
||
if (scheduledStart) {
|
||
payload.scheduled_start = scheduledStart; // ISO or input value as provided by widget
|
||
} else if (date && time) {
|
||
payload.date = date;
|
||
payload.start_time = time;
|
||
} else {
|
||
$('#room-availability').hide();
|
||
return;
|
||
}
|
||
|
||
if (!roomId || !duration) {
|
||
$('#room-availability').hide();
|
||
return;
|
||
}
|
||
|
||
fetch('{% url "operating_theatre:check_room_availability" %}', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
|
||
body: JSON.stringify(payload),
|
||
credentials: 'same-origin'
|
||
})
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
const $banner = $('#room-availability');
|
||
if (data.available) {
|
||
$('#availability-message').html('Room is available for the selected time slot');
|
||
$banner.removeClass('alert-warning alert-danger').addClass('alert-success').show();
|
||
} else {
|
||
$('#availability-message').html('Room conflict: ' + (data.conflict_reason || 'Unavailable'));
|
||
$banner.removeClass('alert-success alert-info').addClass('alert-danger').show();
|
||
}
|
||
})
|
||
.catch(() => {
|
||
$('#availability-message').html('Unable to check room availability');
|
||
$('#room-availability').removeClass('alert-success alert-info').addClass('alert-warning').show();
|
||
});
|
||
}
|
||
|
||
// --- Room schedule preview (server returns HTML snippet) ---
|
||
{#function loadRoomSchedule() {#}
|
||
{# const roomId = $('#id_operating_room').val();#}
|
||
{# const scheduledStart = $('#id_scheduled_start').val();#}
|
||
{# const date = $('#id_scheduled_date').val();#}
|
||
{##}
|
||
{# const query = new URLSearchParams();#}
|
||
{# if (roomId) query.set('room_id', roomId);#}
|
||
{# if (scheduledStart) query.set('date', scheduledStart.substring(0, 10));#}
|
||
{# else if (date) query.set('date', date);#}
|
||
{# else { $('#room-schedule').html('<p class="text-muted mb-0">Select a room and date to view schedule</p>'); return; }#}
|
||
{##}
|
||
{# fetch('{% url "operating_theatre:room_schedule" %}?'+query.toString(), { credentials: 'same-origin' })#}
|
||
{# .then(r => r.json())#}
|
||
{# .then(data => { $('#room-schedule').html(data.html || '<p class="text-muted mb-0">No schedule found.</p>'); })#}
|
||
{# .catch(() => { $('#room-schedule').html('<p class="text-danger mb-0">Unable to load room schedule</p>'); });#}
|
||
{# }#}
|
||
|
||
// --- Dynamic add/remove helpers ---
|
||
function addTeamMember() {
|
||
const html = `
|
||
<div class="team-member-row mb-2">
|
||
<div class="row">
|
||
<div class="col-md-5">
|
||
<select class="form-select" name="team_member_staff">
|
||
<option value="">Select staff member...</option>
|
||
{% for staff in available_staff %}
|
||
<option value="{{ staff.id }}">{{ staff.get_full_name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
<div class="col-md-5">
|
||
<input type="text" class="form-control" name="team_member_role" placeholder="Role (e.g., Scrub Nurse, Resident)">
|
||
</div>
|
||
<div class="col-md-2">
|
||
<button type="button" class="btn btn-outline-danger" onclick="removeTeamMember(this)"><i class="fa fa-times"></i></button>
|
||
</div>
|
||
</div>
|
||
</div>`;
|
||
$('#team-members').append(html);
|
||
}
|
||
function removeTeamMember(btn){ $(btn).closest('.team-member-row').remove(); }
|
||
|
||
function addEquipment() {
|
||
const html = `
|
||
<div class="equipment-item mb-2">
|
||
<div class="input-group">
|
||
<select class="form-select" name="equipment">
|
||
<option value="">Select equipment...</option>
|
||
{% for equipment in available_equipment %}
|
||
<option value="{{ equipment.id }}">{{ equipment.name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<button type="button" class="btn btn-outline-danger" onclick="removeEquipment(this)"><i class="fa fa-times"></i></button>
|
||
</div>
|
||
</div>`;
|
||
$('#equipment-list').append(html);
|
||
}
|
||
function removeEquipment(btn){ $(btn).closest('.equipment-item').remove(); }
|
||
|
||
function addSupply() {
|
||
const html = `
|
||
<div class="supply-item mb-2">
|
||
<div class="row">
|
||
<div class="col-8">
|
||
<select class="form-select" name="supply">
|
||
<option value="">Select supply...</option>
|
||
{% for supply in available_supplies %}
|
||
<option value="{{ supply.id }}">{{ supply.name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
<div class="col-3">
|
||
<input type="number" class="form-control" name="supply_quantity" placeholder="Qty" min="1">
|
||
</div>
|
||
<div class="col-1">
|
||
<button type="button" class="btn btn-outline-danger btn-sm" onclick="removeSupply(this)"><i class="fa fa-times"></i></button>
|
||
</div>
|
||
</div>
|
||
</div>`;
|
||
$('#supplies-list').append(html);
|
||
}
|
||
function removeSupply(btn){ $(btn).closest('.supply-item').remove(); }
|
||
|
||
// --- Save draft (FormData + cookie CSRF) ---
|
||
function saveDraft() {
|
||
const form = document.getElementById('case-form');
|
||
const fd = new FormData(form);
|
||
fd.append('save_draft', 'true');
|
||
|
||
fetch(window.location.href, {
|
||
method: 'POST',
|
||
body: fd,
|
||
headers: { 'X-CSRFToken': getCookie('csrftoken') },
|
||
credentials: 'same-origin'
|
||
})
|
||
.then(r => r.json())
|
||
.then(data => data && data.success ? toastr.success('Draft saved successfully') : toastr.error('Error saving draft'))
|
||
.catch(() => toastr.error('Failed to save draft'));
|
||
}
|
||
</script>
|
||
{% endblock %} |