hospital-management/templates_for_deletion/calendar_appointments.html
Marwan Alwali 263292f6be update
2025-11-04 00:50:06 +03:00

323 lines
15 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Appointment Calendar{% endblock %}
{% block css %}
{% endblock %}
{% block content %}
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-xl-12">
<ul class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'appointments:appointment_list' %}">Appointments</a></li>
<li class="breadcrumb-item active">Calendar</li>
</ul>
<div class="d-flex align-items-center justify-content-between mb-3">
<h1 class="page-header mb-0">Appointment Calendar</h1>
<div>
<a href="#" class="btn btn-success">
<i class="fa fa-plus me-2"></i>New Appointment
</a>
</div>
</div>
<div class="row">
<div class="col-xl-9">
<div class="card">
<div class="card-body">
<div id="calendar"></div>
</div>
</div>
</div>
<div class="col-xl-3">
<!-- Filters -->
<div class="card mb-4">
<div class="card-header">
<h4 class="card-title">Filters</h4>
</div>
<div class="card-body">
<form id="filterForm">
<div class="mb-3">
<label class="form-label">Provider</label>
<select name="provider" class="form-select" id="providerFilter">
<option value="">All Providers</option>
{% for provider in appointments.provider.all %}
<option value="{{ provider.id }}">{{ provider.first_name }} {{ provider.last_name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">Department</label>
<select name="department" class="form-select" id="departmentFilter">
<option value="">All Departments</option>
{% for dept in departments %}
<option value="{{ dept.id }}">{{ dept.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">Status</label>
<select name="status" class="form-select" id="statusFilter">
<option value="">All Statuses</option>
<option value="scheduled">Scheduled</option>
<option value="confirmed">Confirmed</option>
<option value="checked_in">Checked In</option>
<option value="in_progress">In Progress</option>
<option value="completed">Completed</option>
<option value="cancelled">Cancelled</option>
<option value="no_show">No Show</option>
</select>
</div>
<button type="button" class="btn btn-primary" onclick="applyFilters()">
<i class="fa fa-filter me-2"></i>Apply Filters
</button>
</form>
</div>
</div>
<!-- Legend -->
<div class="card mb-4">
<div class="card-header">
<h4 class="card-title">Status Legend</h4>
</div>
<div class="card-body">
<div class="d-flex align-items-center mb-2">
<div class="w-20px h-20px bg-info rounded me-2"></div>
<span>Scheduled</span>
</div>
<div class="d-flex align-items-center mb-2">
<div class="w-20px h-20px bg-success rounded me-2"></div>
<span>Confirmed</span>
</div>
<div class="d-flex align-items-center mb-2">
<div class="w-20px h-20px bg-primary rounded me-2"></div>
<span>Checked In</span>
</div>
<div class="d-flex align-items-center mb-2">
<div class="w-20px h-20px bg-warning rounded me-2"></div>
<span>In Progress</span>
</div>
<div class="d-flex align-items-center mb-2">
<div class="w-20px h-20px bg-dark rounded me-2"></div>
<span>Completed</span>
</div>
<div class="d-flex align-items-center mb-2">
<div class="w-20px h-20px bg-danger rounded me-2"></div>
<span>Cancelled</span>
</div>
<div class="d-flex align-items-center">
<div class="w-20px h-20px bg-secondary rounded me-2"></div>
<span>No Show</span>
</div>
</div>
</div>
<!-- Today's Appointments -->
<div class="card">
<div class="card-header">
<h4 class="card-title">Today's Appointments</h4>
</div>
<div class="card-body">
{% for appointment in appointments %}
<div class="d-flex align-items-center mb-3 p-2 border rounded">
<div class="flex-grow-1">
<div class="fw-bold">{{ appointment.appointment_time|time:"g:i A" }}</div>
<div class="small">{{ appointment.patient.first_name }} {{ appointment.patient.last_name }}</div>
<div class="small text-muted">{{ appointment.provider.first_name }} {{ appointment.provider.last_name }}</div>
</div>
<div>
{% if appointment.status == 'SCHEDULED' %}
<span class="badge bg-info">Scheduled</span>
{% elif appointment.status == 'CONFIRMED' %}
<span class="badge bg-success">Confirmed</span>
{% elif appointment.status == 'CHECKED_IN' %}
<span class="badge bg-primary">Checked In</span>
{% elif appointment.status == 'IN_PROGRESS' %}
<span class="badge bg-warning">In Progress</span>
{% elif appointment.status == 'COMPLETED' %}
<span class="badge bg-dark">Completed</span>
{% elif appointment.status == 'CANCELLED' %}
<span class="badge bg-danger">Cancelled</span>
{% elif appointment.status == 'NO_SHOW' %}
<span class="badge bg-secondary">No Show</span>
{% endif %}
</div>
</div>
{% empty %}
<p class="text-muted text-center">No appointments today</p>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Appointment Detail Modal -->
<div class="modal fade" id="appointmentModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Appointment Details</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" id="appointmentModalBody">
<!-- 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="editAppointmentBtn">Edit</a>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script src="{% static 'plugins/@fullcalendar/core/index.global.js' %}"></script>
<script src="{% static 'plugins/@fullcalendar/bootstrap/index.global.js' %}"></script>
<script src="{% static 'plugins/@fullcalendar/daygrid/index.global.js' %}"></script>
<script src="{% static 'plugins/@fullcalendar/timegrid/index.global.js' %}"></script>
<script src="{% static 'plugins/@fullcalendar/interaction/index.global.js' %}"></script>
<script src="{% static 'plugins/@fullcalendar/list/index.global.js' %}"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: function(fetchInfo, successCallback, failureCallback) {
// Get filter values
var provider = document.getElementById('providerFilter').value;
var department = document.getElementById('departmentFilter').value;
var status = document.getElementById('statusFilter').value;
// Build URL with filters
var url = '{% url "appointments:calendar_appointments" %}?format=json';
if (provider) url += '&provider=' + provider;
if (department) url += '&department=' + department;
if (status) url += '&status=' + status;
url += '&start=' + fetchInfo.startStr + '&end=' + fetchInfo.endStr;
fetch(url)
.then(response => response.json())
.then(data => {
var events = data.map(function(appointment) {
var color = getStatusColor(appointment.status);
return {
id: appointment.id,
title: appointment.patient_name + ' - ' + appointment.provider_name,
start: appointment.appointment_datetime,
backgroundColor: color,
borderColor: color,
extendedProps: appointment
};
});
successCallback(events);
})
.catch(error => {
console.error('Error loading appointments:', error);
failureCallback(error);
});
},
eventClick: function(info) {
showAppointmentDetails(info.event.extendedProps);
}
});
calendar.render();
// Store calendar reference for filter updates
window.appointmentCalendar = calendar;
});
function getStatusColor(status) {
var colors = {
'scheduled': '#17a2b8',
'confirmed': '#28a745',
'checked_in': '#007bff',
'in_progress': '#ffc107',
'completed': '#343a40',
'cancelled': '#dc3545',
'no_show': '#6c757d'
};
return colors[status] || '#17a2b8';
}
function applyFilters() {
if (window.appointmentCalendar) {
window.appointmentCalendar.refetchEvents();
}
}
function showAppointmentDetails(appointment) {
var modalBody = document.getElementById('appointmentModalBody');
var editBtn = document.getElementById('editAppointmentBtn');
modalBody.innerHTML = `
<div class="row mb-2">
<div class="col-4"><strong>Patient:</strong></div>
<div class="col-8">${appointment.patient_name}</div>
</div>
<div class="row mb-2">
<div class="col-4"><strong>Provider:</strong></div>
<div class="col-8">${appointment.provider_name}</div>
</div>
<div class="row mb-2">
<div class="col-4"><strong>Department:</strong></div>
<div class="col-8">${appointment.department_name}</div>
</div>
<div class="row mb-2">
<div class="col-4"><strong>Date/Time:</strong></div>
<div class="col-8">${new Date(appointment.appointment_datetime).toLocaleString()}</div>
</div>
<div class="row mb-2">
<div class="col-4"><strong>Type:</strong></div>
<div class="col-8">${appointment.appointment_type}</div>
</div>
<div class="row mb-2">
<div class="col-4"><strong>Status:</strong></div>
<div class="col-8"><span class="badge bg-${getStatusBadgeClass(appointment.status)}">${appointment.status}</span></div>
</div>
${appointment.notes ? `
<div class="row">
<div class="col-4"><strong>Notes:</strong></div>
<div class="col-8">${appointment.notes}</div>
</div>
` : ''}
`;
editBtn.href = `/appointments/${appointment.id}/update/`;
var modal = new bootstrap.Modal(document.getElementById('appointmentModal'));
modal.show();
}
function getStatusBadgeClass(status) {
var classes = {
'scheduled': 'info',
'confirmed': 'success',
'checked_in': 'primary',
'in_progress': 'warning',
'completed': 'dark',
'cancelled': 'danger',
'no_show': 'secondary'
};
return classes[status] || 'info';
}
</script>
{% endblock %}