300 lines
19 KiB
HTML
300 lines
19 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
{% block title %}Appointments - Hospital Management System{% endblock %}
|
|
|
|
|
|
{% block css %}
|
|
{% endblock %}
|
|
{% block content %}
|
|
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
|
<div>
|
|
<h1 class="h2">
|
|
<i class="fas fa-calendar-alt"></i> Appointments<span class="fw-light">Requests</span>
|
|
</h1>
|
|
<p class="text-muted">Manage your appointments and view their details.</p>
|
|
</div>
|
|
<div class="btn-toolbar mb-2 mb-md-0">
|
|
<div class="btn-group me-2">
|
|
<button type="button" class="btn btn-outline-secondary"><i class="fas fa-download"></i> Export</button>
|
|
<button type="button" class="btn btn-outline-secondary"><i class="fas fa-print"></i> Print</button>
|
|
<button type="button" class="btn btn-outline-primary"><i class="fas fa-calendar-plus"></i> Schedule New</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="container-fluid">
|
|
<!-- Appointment List -->
|
|
<div class="panel panel-inverse mb-4" data-sortable-id="index-1" id="appointment-list">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">
|
|
<i class="fas fa-calendar-alt"></i> Appointments
|
|
</h4>
|
|
<div class="panel-heading-btn">
|
|
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
|
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
|
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
|
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
|
|
</div>
|
|
</div>
|
|
<div class="panel-body">
|
|
<!-- Search and Filters -->
|
|
<div class="card mb-4">
|
|
<div class="card-body">
|
|
<form method="get" class="row g-3">
|
|
<div class="col-md-3">
|
|
<label for="search" class="form-label">Search</label>
|
|
<input type="text"
|
|
class="form-control"
|
|
id="search"
|
|
name="search"
|
|
value="{{ request.GET.search }}"
|
|
placeholder="Patient name, MRN, provider..."
|
|
hx-get="{% url 'appointments:appointment_search' %}"
|
|
hx-target="#appointment-list"
|
|
hx-trigger="keyup changed delay:500ms">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="status" class="form-label">Status</label>
|
|
<select class="form-select" id="status" name="status">
|
|
<option value="">All Statuses</option>
|
|
<option value="PENDING" {% if request.GET.status == 'PENDING' %}selected{% endif %}>Pending</option>
|
|
<option value="SCHEDULED" {% if request.GET.status == 'SCHEDULED' %}selected{% endif %}>Scheduled</option>
|
|
<option value="CONFIRMED" {% if request.GET.status == 'CONFIRMED' %}selected{% endif %}>Confirmed</option>
|
|
<option value="CHECKED_IN" {% if request.GET.status == 'CHECKED_IN' %}selected{% endif %}>Checked In</option>
|
|
<option value="IN_PROGRESS" {% if request.GET.status == 'IN_PROGRESS' %}selected{% endif %}>In Progress</option>
|
|
<option value="COMPLETED" {% if request.GET.status == 'COMPLETED' %}selected{% endif %}>Completed</option>
|
|
<option value="CANCELLED" {% if request.GET.status == 'CANCELLED' %}selected{% endif %}>Cancelled</option>
|
|
<option value="NO_SHOW" {% if request.GET.status == 'NO_SHOW' %}selected{% endif %}>No Show</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="appointment_type" class="form-label">Type</label>
|
|
<select class="form-select" id="appointment_type" name="appointment_type">
|
|
<option value="">All Types</option>
|
|
<option value="CONSULTATION" {% if request.GET.appointment_type == 'CONSULTATION' %}selected{% endif %}>Consultation</option>
|
|
<option value="FOLLOW_UP" {% if request.GET.appointment_type == 'FOLLOW_UP' %}selected{% endif %}>Follow-up</option>
|
|
<option value="PROCEDURE" {% if request.GET.appointment_type == 'PROCEDURE' %}selected{% endif %}>Procedure</option>
|
|
<option value="SURGERY" {% if request.GET.appointment_type == 'SURGERY' %}selected{% endif %}>Surgery</option>
|
|
<option value="DIAGNOSTIC" {% if request.GET.appointment_type == 'DIAGNOSTIC' %}selected{% endif %}>Diagnostic</option>
|
|
<option value="TELEMEDICINE" {% if request.GET.appointment_type == 'TELEMEDICINE' %}selected{% endif %}>Telemedicine</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="specialty" class="form-label">Specialty</label>
|
|
<select class="form-select" id="specialty" name="specialty">
|
|
<option value="">All Specialties</option>
|
|
{% for specialty in specialties %}
|
|
<option value="{{ specialty }}" {% if request.GET.specialty == specialty %}selected{% endif %}>
|
|
{{ specialty|title }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="date_filter" class="form-label">Date</label>
|
|
<select class="form-select" id="date_filter" name="date_filter">
|
|
<option value="">All Dates</option>
|
|
<option value="today" {% if request.GET.date_filter == 'today' %}selected{% endif %}>Today</option>
|
|
<option value="tomorrow" {% if request.GET.date_filter == 'tomorrow' %}selected{% endif %}>Tomorrow</option>
|
|
<option value="this_week" {% if request.GET.date_filter == 'this_week' %}selected{% endif %}>This Week</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-1">
|
|
<label class="form-label"> </label>
|
|
<div class="d-grid">
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fas fa-search"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Date & Time</th>
|
|
<th>Patient</th>
|
|
<th>Provider</th>
|
|
<th>Type & Specialty</th>
|
|
<th>Status</th>
|
|
<th>Priority</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for appointment in appointments %}
|
|
<tr>
|
|
<td>
|
|
{% if appointment.scheduled_datetime %}
|
|
<div class="fw-bold">{{ appointment.scheduled_datetime|date:"M d, Y" }}</div>
|
|
<div class="text-muted">{{ appointment.scheduled_datetime|time:"g:i A" }}</div>
|
|
{% else %}
|
|
<div class="text-muted">Not scheduled</div>
|
|
{% endif %}
|
|
{% if appointment.is_telemedicine %}
|
|
<span class="badge bg-info mt-1">
|
|
<i class="fas fa-video"></i> Telemedicine
|
|
</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<div class="fw-bold">{{ appointment.patient.get_full_name }}</div>
|
|
<div class="text-muted small">MRN: {{ appointment.patient.mrn }}</div>
|
|
{% if appointment.patient.date_of_birth %}
|
|
<div class="text-muted small">Age: {{ appointment.patient.age }}</div>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<div>{{ appointment.provider.get_full_name }}</div>
|
|
<div class="text-muted small">{{ appointment.provider.get_role_display }}</div>
|
|
</td>
|
|
<td>
|
|
<div>{{ appointment.get_appointment_type_display }}</div>
|
|
<div class="text-muted small">{{ appointment.get_specialty_display }}</div>
|
|
<div class="text-muted small">{{ appointment.duration_minutes }} min</div>
|
|
</td>
|
|
<td>
|
|
{% if appointment.status == 'PENDING' %}
|
|
<span class="badge bg-secondary">{{ appointment.get_status_display }}</span>
|
|
{% elif appointment.status == 'SCHEDULED' %}
|
|
<span class="badge bg-primary">{{ appointment.get_status_display }}</span>
|
|
{% elif appointment.status == 'CONFIRMED' %}
|
|
<span class="badge bg-success">{{ appointment.get_status_display }}</span>
|
|
{% elif appointment.status == 'CHECKED_IN' %}
|
|
<span class="badge bg-warning">{{ appointment.get_status_display }}</span>
|
|
{% elif appointment.status == 'IN_PROGRESS' %}
|
|
<span class="badge bg-info">{{ appointment.get_status_display }}</span>
|
|
{% elif appointment.status == 'COMPLETED' %}
|
|
<span class="badge bg-success">{{ appointment.get_status_display }}</span>
|
|
{% elif appointment.status == 'CANCELLED' %}
|
|
<span class="badge bg-danger">{{ appointment.get_status_display }}</span>
|
|
{% elif appointment.status == 'NO_SHOW' %}
|
|
<span class="badge bg-dark">{{ appointment.get_status_display }}</span>
|
|
{% elif appointment.status == 'RESCHEDULED' %}
|
|
<span class="badge bg-warning">{{ appointment.get_status_display }}</span>
|
|
{% else %}
|
|
<span class="badge bg-light text-dark">{{ appointment.get_status_display }}</span>
|
|
{% endif %}
|
|
{% if appointment.is_overdue %}
|
|
<br><span class="badge bg-danger mt-1">Overdue</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if appointment.priority == 'ROUTINE' %}
|
|
<span class="badge bg-light text-dark">{{ appointment.get_priority_display }}</span>
|
|
{% elif appointment.priority == 'URGENT' %}
|
|
<span class="badge bg-warning">{{ appointment.get_priority_display }}</span>
|
|
{% elif appointment.priority == 'STAT' %}
|
|
<span class="badge bg-danger">{{ appointment.get_priority_display }}</span>
|
|
{% elif appointment.priority == 'EMERGENCY' %}
|
|
<span class="badge bg-danger">{{ appointment.get_priority_display }}</span>
|
|
{% endif %}
|
|
|
|
{% if appointment.urgency_score > 5 %}
|
|
<br><small class="text-danger">Score: {{ appointment.urgency_score }}/10</small>
|
|
{% else %}
|
|
<br><small class="text-muted">Score: {{ appointment.urgency_score }}/10</small>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<div class="btn-group btn-group-sm" role="group">
|
|
<!-- Check In Button -->
|
|
{% if appointment.status == 'SCHEDULED' or appointment.status == 'CONFIRMED' %}
|
|
<button type="button"
|
|
class="btn btn-outline-success"
|
|
title="Check In Patient"
|
|
hx-post="{% url 'appointments:check_in_patient' appointment.id %}"
|
|
hx-target="#appointment-list"
|
|
hx-swap="innerHTML"
|
|
hx-confirm="Are you sure you want to check-in this patient?"
|
|
hx-headers='{"X-CSRFToken":"{{ csrf_token }}"}'>
|
|
<i class="fas fa-check"></i>
|
|
</button>
|
|
{% endif %}
|
|
|
|
<!-- Telemedicine Join Button -->
|
|
{% if appointment.is_telemedicine and appointment.status in 'CHECKED_IN,IN_PROGRESS' and appointment.meeting_url %}
|
|
<button type="button"
|
|
class="btn btn-outline-primary"
|
|
title="Join Telemedicine Session"
|
|
onclick="window.open('{{ appointment.meeting_url }}', '_blank')">
|
|
<i class="fas fa-video"></i>
|
|
</button>
|
|
{% endif %}
|
|
|
|
<!-- Complete Button -->
|
|
{% if appointment.status == 'IN_PROGRESS' %}
|
|
<button type="button"
|
|
class="btn btn-outline-success"
|
|
title="Complete Appointment"
|
|
hx-post="{% url 'appointments:complete_appointment' appointment.id %}"
|
|
hx-target="#appointment-list"
|
|
hx-swap="innerHTML"
|
|
hx-confirm="Are you sure you want to complete this appointment?"
|
|
hx-headers='{"X-CSRFToken":"{{ csrf_token }}"}'>
|
|
<i class="fas fa-check-circle"></i>
|
|
</button>
|
|
{% endif %}
|
|
|
|
<!-- Reschedule Button -->
|
|
{% if appointment.status in 'PENDING,SCHEDULED,CONFIRMED' %}
|
|
<a class="btn btn-outline-warning"
|
|
href="{% url 'appointments:reschedule_appointment' appointment.id %}">
|
|
<i class="fas fa-calendar-alt"></i>
|
|
</a>
|
|
{% endif %}
|
|
<!-- View Details Button -->
|
|
<a href="{% url 'appointments:appointment_detail' appointment.pk %}"
|
|
class="btn btn-outline-info"
|
|
title="View Details">
|
|
<i class="fas fa-eye"></i>
|
|
</a>
|
|
<!-- More Actions Dropdown -->
|
|
<div class="btn-group btn-group-sm" role="group">
|
|
<button type="button"
|
|
class="btn btn-outline-secondary dropdown-toggle"
|
|
data-bs-toggle="dropdown"
|
|
aria-expanded="false">
|
|
<i class="fas fa-ellipsis-v"></i>
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#"><i class="fas fa-edit"></i> Edit</a></li>
|
|
<li><a class="dropdown-item" href="#"><i class="fas fa-copy"></i> Duplicate</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item text-danger" href="#"><i class="fas fa-times"></i> Cancel</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="7" class="text-center text-muted py-5">
|
|
<i class="fas fa-calendar fa-3x mb-3"></i>
|
|
<h5>No appointments found</h5>
|
|
<p>Try adjusting your search criteria or schedule a new appointment.</p>
|
|
<button type="button" class="btn btn-primary">
|
|
<i class="fas fa-calendar-plus"></i> Schedule New Appointment
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
<!-- Pagination -->
|
|
{% if is_paginated %}
|
|
{% include 'partial/pagination.html' %}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script src="{% static 'plugins/sweetalert/dist/sweetalert.min.js' %}"></script>
|
|
<script>
|
|
|
|
</script>
|
|
{% endblock %} |