2025-08-12 13:33:25 +03:00

422 lines
15 KiB
HTML

{% load static %}
<!-- Surgery Calendar Partial -->
<div id="surgery-calendar-container">
<!-- Calendar Controls -->
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-primary btn-sm" id="prev-month">
<i class="fa fa-chevron-left"></i>
</button>
<button type="button" class="btn btn-outline-primary btn-sm" id="today">Today</button>
<button type="button" class="btn btn-outline-primary btn-sm" id="next-month">
<i class="fa fa-chevron-right"></i>
</button>
</div>
<h5 class="mb-0" id="calendar-title">Surgery Schedule</h5>
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-secondary btn-sm" data-view="month">Month</button>
<button type="button" class="btn btn-outline-secondary btn-sm" data-view="agendaWeek">Week</button>
<button type="button" class="btn btn-outline-secondary btn-sm" data-view="agendaDay">Day</button>
</div>
</div>
<!-- Calendar Legend -->
<div class="row mb-3">
<div class="col-12">
<div class="d-flex flex-wrap gap-3">
<div class="d-flex align-items-center">
<div class="me-2" style="width: 12px; height: 12px; background-color: #007bff; border-radius: 2px;"></div>
<small>Scheduled</small>
</div>
<div class="d-flex align-items-center">
<div class="me-2" style="width: 12px; height: 12px; background-color: #28a745; border-radius: 2px;"></div>
<small>In Progress</small>
</div>
<div class="d-flex align-items-center">
<div class="me-2" style="width: 12px; height: 12px; background-color: #ffc107; border-radius: 2px;"></div>
<small>Completed</small>
</div>
<div class="d-flex align-items-center">
<div class="me-2" style="width: 12px; height: 12px; background-color: #dc3545; border-radius: 2px;"></div>
<small>Cancelled</small>
</div>
<div class="d-flex align-items-center">
<div class="me-2" style="width: 12px; height: 12px; background-color: #fd7e14; border-radius: 2px;"></div>
<small>Emergency</small>
</div>
</div>
</div>
</div>
<!-- Calendar -->
<div id="surgery-calendar" style="min-height: 600px;"></div>
</div>
<!-- Surgery Quick View Modal -->
<div class="modal fade" id="surgeryQuickViewModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Surgery Details</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" id="surgery-quick-view-content">
<!-- Content will be loaded dynamically -->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<a href="#" class="btn btn-primary" id="view-full-surgery">View Full Details</a>
</div>
</div>
</div>
</div>
<!-- Add Surgery Modal -->
<div class="modal fade" id="addSurgeryModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Schedule New Surgery</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="quick-surgery-form">
{% csrf_token %}
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Patient <span class="text-danger">*</span></label>
<select class="form-select select2" name="patient" required>
<option value="">Select Patient</option>
<!-- Options will be loaded dynamically -->
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Surgeon <span class="text-danger">*</span></label>
<select class="form-select select2" name="surgeon" required>
<option value="">Select Surgeon</option>
<!-- Options will be loaded dynamically -->
</select>
</div>
</div>
<div class="row">
<div class="col-md-12 mb-3">
<label class="form-label">Procedure Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="procedure_name" required>
</div>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label class="form-label">Date <span class="text-danger">*</span></label>
<input type="date" class="form-control" name="scheduled_date" required>
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Start Time <span class="text-danger">*</span></label>
<input type="time" class="form-control" name="scheduled_start_time" required>
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Duration (minutes)</label>
<input type="number" class="form-control" name="estimated_duration" min="15" step="15">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Operating Room</label>
<select class="form-select" name="operating_room">
<option value="">Select OR</option>
<!-- Options will be loaded dynamically -->
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Urgency Level</label>
<select class="form-select" name="urgency_level">
<option value="elective">Elective</option>
<option value="urgent">Urgent</option>
<option value="emergency">Emergency</option>
</select>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="save-quick-surgery">Schedule Surgery</button>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
var calendar;
// Initialize FullCalendar
calendar = $('#surgery-calendar').fullCalendar({
header: false, // We're using custom header
defaultView: 'month',
height: 'auto',
editable: false,
eventLimit: true,
eventLimitText: 'more',
// Event sources
events: function(start, end, timezone, callback) {
$.ajax({
url: '{% url "inpatients:surgery_calendar_data" %}',
data: {
start: start.format(),
end: end.format()
},
success: function(data) {
callback(data.events);
},
error: function() {
toastr.error('Failed to load surgery calendar data');
callback([]);
}
});
},
// Event rendering
eventRender: function(event, element) {
// Add tooltip
element.attr('title', event.title + '\n' +
'Surgeon: ' + event.surgeon + '\n' +
'Room: ' + (event.room || 'TBD') + '\n' +
'Status: ' + event.status);
// Add status class
element.addClass('surgery-event-' + event.status);
// Add urgency indicator for emergency surgeries
if (event.urgency === 'emergency') {
element.prepend('<i class="fa fa-exclamation-triangle text-warning me-1"></i>');
}
},
// Event click handler
eventClick: function(event, jsEvent, view) {
loadSurgeryQuickView(event.id);
},
// Day click handler for adding new surgeries
dayClick: function(date, jsEvent, view) {
if (date.isSameOrAfter(moment(), 'day')) {
$('#addSurgeryModal input[name="scheduled_date"]').val(date.format('YYYY-MM-DD'));
$('#addSurgeryModal').modal('show');
}
},
// View render callback
viewRender: function(view, element) {
$('#calendar-title').text(view.title);
}
});
// Custom navigation buttons
$('#prev-month').click(function() {
calendar.fullCalendar('prev');
});
$('#next-month').click(function() {
calendar.fullCalendar('next');
});
$('#today').click(function() {
calendar.fullCalendar('today');
});
// View change buttons
$('[data-view]').click(function() {
var view = $(this).data('view');
calendar.fullCalendar('changeView', view);
$('[data-view]').removeClass('active');
$(this).addClass('active');
});
// Set default active view
$('[data-view="month"]').addClass('active');
// Load surgery quick view
function loadSurgeryQuickView(surgeryId) {
$.ajax({
url: '{% url "inpatients:surgery_quick_view" 0 %}'.replace('0', surgeryId),
success: function(data) {
$('#surgery-quick-view-content').html(data.html);
$('#view-full-surgery').attr('href', data.detail_url);
$('#surgeryQuickViewModal').modal('show');
},
error: function() {
toastr.error('Failed to load surgery details');
}
});
}
// Initialize Select2 for modals
$('#addSurgeryModal').on('shown.bs.modal', function() {
$('.select2').select2({
theme: 'bootstrap-5',
dropdownParent: $('#addSurgeryModal')
});
// Load patients and surgeons
loadSelectOptions();
});
// Load select options
function loadSelectOptions() {
// Load patients
$.ajax({
url: '{% url "patients:patient_list_api" %}',
success: function(data) {
var patientSelect = $('select[name="patient"]');
patientSelect.empty().append('<option value="">Select Patient</option>');
data.forEach(function(patient) {
patientSelect.append('<option value="' + patient.id + '">' +
patient.name + ' (' + patient.mrn + ')</option>');
});
}
});
// Load surgeons
$.ajax({
url: '{% url "users:surgeon_list_api" %}',
success: function(data) {
var surgeonSelect = $('select[name="surgeon"]');
surgeonSelect.empty().append('<option value="">Select Surgeon</option>');
data.forEach(function(surgeon) {
surgeonSelect.append('<option value="' + surgeon.id + '">Dr. ' +
surgeon.name + '</option>');
});
}
});
// Load operating rooms
$.ajax({
url: '{% url "inpatients:operating_room_list_api" %}',
success: function(data) {
var roomSelect = $('select[name="operating_room"]');
roomSelect.empty().append('<option value="">Select OR</option>');
data.forEach(function(room) {
roomSelect.append('<option value="' + room.id + '">' + room.name + '</option>');
});
}
});
}
// Save quick surgery
$('#save-quick-surgery').click(function() {
var formData = $('#quick-surgery-form').serialize();
$.ajax({
url: '{% url "inpatients:surgery_create_quick" %}',
method: 'POST',
data: formData,
success: function(response) {
if (response.success) {
toastr.success('Surgery scheduled successfully');
$('#addSurgeryModal').modal('hide');
calendar.fullCalendar('refetchEvents');
} else {
toastr.error('Failed to schedule surgery: ' + response.error);
}
},
error: function() {
toastr.error('An error occurred while scheduling the surgery');
}
});
});
// Auto-refresh calendar every 5 minutes
setInterval(function() {
calendar.fullCalendar('refetchEvents');
}, 300000);
});
</script>
<style>
/* Custom calendar styles */
.surgery-event-scheduled {
background-color: #007bff !important;
border-color: #007bff !important;
}
.surgery-event-in_progress {
background-color: #28a745 !important;
border-color: #28a745 !important;
}
.surgery-event-completed {
background-color: #ffc107 !important;
border-color: #ffc107 !important;
color: #000 !important;
}
.surgery-event-cancelled {
background-color: #dc3545 !important;
border-color: #dc3545 !important;
}
.fc-event {
cursor: pointer;
font-size: 12px;
}
.fc-event:hover {
opacity: 0.8;
}
.fc-day-grid-event {
margin: 1px 2px;
}
.fc-time-grid-event {
border-radius: 3px;
}
/* Emergency surgery styling */
.surgery-event-emergency {
border-left: 4px solid #fd7e14 !important;
}
/* Calendar header styling */
.fc-toolbar {
margin-bottom: 1rem;
}
.fc-toolbar h2 {
font-size: 1.25rem;
font-weight: 600;
}
/* Modal styling */
.modal-lg {
max-width: 800px;
}
#surgery-quick-view-content {
max-height: 400px;
overflow-y: auto;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.fc-toolbar .fc-left,
.fc-toolbar .fc-right,
.fc-toolbar .fc-center {
float: none;
display: block;
clear: both;
margin: 10px 0;
}
.fc-toolbar > * > * {
float: none;
margin: 0 5px;
}
}
</style>