165 lines
7.4 KiB
HTML
165 lines
7.4 KiB
HTML
{% extends "base.html" %}
|
|
{% load i18n static %}
|
|
|
|
{% block title %}{% trans "Appointments" %} - Tenhal{% endblock %}
|
|
|
|
{% block css %}
|
|
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
|
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<!-- Page Header -->
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<h1 class="page-header mb-0">
|
|
<i class="fas fa-calendar-check me-2"></i>{% trans "Appointments" %}
|
|
</h1>
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">{% trans "Dashboard" %}</a></li>
|
|
<li class="breadcrumb-item active">{% trans "Appointments" %}</li>
|
|
</ol>
|
|
</nav>
|
|
</div>
|
|
<div>
|
|
{% if user.role in 'ADMIN,FRONT_DESK' %}
|
|
<a href="{% url 'appointments:appointment_create' %}" class="btn btn-primary">
|
|
<i class="fas fa-plus me-1"></i>{% trans "New Appointment" %}
|
|
</a>
|
|
{% endif %}
|
|
<a href="{% url 'appointments:appointment_calendar' %}" class="btn btn-outline-secondary">
|
|
<i class="fas fa-calendar-alt me-1"></i>{% trans "Calendar View" %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters Card -->
|
|
<div class="card mb-3">
|
|
<div class="card-body">
|
|
<form method="get" id="filterForm" hx-get="{% url 'appointments:appointment_list' %}"
|
|
hx-target="#appointmentListContainer" hx-trigger="change, submit" hx-swap="innerHTML">
|
|
<div class="row g-3">
|
|
<!-- Search -->
|
|
<div class="col-md-3">
|
|
<label class="form-label">{% trans "Search" %}</label>
|
|
<input type="text" name="search" class="form-control"
|
|
placeholder="{% trans 'Patient name, MRN, or appointment #' %}"
|
|
value="{{ current_filters.search }}"
|
|
hx-get="{% url 'appointments:appointment_list' %}"
|
|
hx-target="#appointmentListContainer"
|
|
hx-trigger="keyup changed delay:500ms"
|
|
hx-include="[name='status'], [name='clinic'], [name='provider'], [name='date_from'], [name='date_to']">
|
|
</div>
|
|
|
|
<!-- Status Filter -->
|
|
<div class="col-md-2">
|
|
<label class="form-label">{% trans "Status" %}</label>
|
|
<select name="status" class="form-select">
|
|
<option value="">{% trans "All Statuses" %}</option>
|
|
{% for value, label in status_choices %}
|
|
<option value="{{ value }}" {% if current_filters.status == value %}selected{% endif %}>
|
|
{{ label }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Clinic Filter -->
|
|
<div class="col-md-2">
|
|
<label class="form-label">{% trans "Clinic" %}</label>
|
|
<select name="clinic" class="form-select">
|
|
<option value="">{% trans "All Clinics" %}</option>
|
|
{% for clinic in clinics %}
|
|
<option value="{{ clinic.id }}" {% if current_filters.clinic == clinic.id|stringformat:"s" %}selected{% endif %}>
|
|
{{ clinic.name }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Provider Filter -->
|
|
<div class="col-md-2">
|
|
<label class="form-label">{% trans "Provider" %}</label>
|
|
<select name="provider" class="form-select">
|
|
<option value="">{% trans "All Providers" %}</option>
|
|
{% for provider in providers %}
|
|
<option value="{{ provider.id }}" {% if current_filters.provider == provider.id|stringformat:"s" %}selected{% endif %}>
|
|
{{ provider.user.get_full_name }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Date From -->
|
|
<div class="col-md-1.5">
|
|
<label class="form-label">{% trans "From" %}</label>
|
|
<input type="date" name="date_from" class="form-control"
|
|
value="{{ current_filters.date_from }}">
|
|
</div>
|
|
|
|
<!-- Date To -->
|
|
<div class="col-md-1.5">
|
|
<label class="form-label">{% trans "To" %}</label>
|
|
<input type="date" name="date_to" class="form-control"
|
|
value="{{ current_filters.date_to }}">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mt-3">
|
|
<div class="col-12">
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fas fa-filter me-1"></i>{% trans "Apply Filters" %}
|
|
</button>
|
|
<a href="{% url 'appointments:appointment_list' %}" class="btn btn-outline-secondary">
|
|
<i class="fas fa-times me-1"></i>{% trans "Clear Filters" %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Appointments List -->
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div id="appointmentListContainer">
|
|
{% include 'appointments/partials/appointment_list_partial.html' %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
|
|
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
|
<script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
|
<script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
|
<script>
|
|
// Status badge colors
|
|
const statusColors = {
|
|
'BOOKED': 'info',
|
|
'CONFIRMED': 'primary',
|
|
'RESCHEDULED': 'warning',
|
|
'CANCELLED': 'danger',
|
|
'NO_SHOW': 'dark',
|
|
'ARRIVED': 'success',
|
|
'IN_PROGRESS': 'warning',
|
|
'COMPLETED': 'success'
|
|
};
|
|
|
|
// HTMX event listeners
|
|
document.body.addEventListener('htmx:afterSwap', function(event) {
|
|
if (event.detail.target.id === 'appointmentListContainer') {
|
|
// Reinitialize tooltips after HTMX swap
|
|
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
|
tooltipTriggerList.map(function (tooltipTriggerEl) {
|
|
return new bootstrap.Tooltip(tooltipTriggerEl);
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|