252 lines
13 KiB
HTML
252 lines
13 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Appointment Statistics{% endblock %}
|
|
|
|
{% block css %}
|
|
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
<div class="container">
|
|
<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">Statistics</li>
|
|
</ul>
|
|
|
|
<h1 class="page-header">Appointment Statistics</h1>
|
|
|
|
<!-- Summary Cards -->
|
|
<div class="row mb-4">
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="card bg-primary text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-grow-1">
|
|
<div class="fs-3 fw-bold">{{ stats.total_appointments|default:0 }}</div>
|
|
<div>Total Appointments</div>
|
|
</div>
|
|
<div class="w-50px h-50px bg-white bg-opacity-20 rounded-circle d-flex align-items-center justify-content-center">
|
|
<i class="fa fa-calendar fa-lg"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="card bg-success text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-grow-1">
|
|
<div class="fs-3 fw-bold">{{ stats.completed_appointments|default:0 }}</div>
|
|
<div>Completed</div>
|
|
</div>
|
|
<div class="w-50px h-50px bg-white bg-opacity-20 rounded-circle d-flex align-items-center justify-content-center">
|
|
<i class="fa fa-check fa-lg"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="card bg-warning text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-grow-1">
|
|
<div class="fs-3 fw-bold">{{ stats.cancelled_appointments|default:0 }}</div>
|
|
<div>Cancelled</div>
|
|
</div>
|
|
<div class="w-50px h-50px bg-white bg-opacity-20 rounded-circle d-flex align-items-center justify-content-center">
|
|
<i class="fa fa-times fa-lg"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="card bg-danger text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-grow-1">
|
|
<div class="fs-3 fw-bold">{{ stats.no_show_appointments|default:0 }}</div>
|
|
<div>No Shows</div>
|
|
</div>
|
|
<div class="w-50px h-50px bg-white bg-opacity-20 rounded-circle d-flex align-items-center justify-content-center">
|
|
<i class="fa fa-user-times fa-lg"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-xl-8">
|
|
<!-- Appointments by Status -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Appointments by Status</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Status</th>
|
|
<th>Count</th>
|
|
<th>Percentage</th>
|
|
<th>Visual</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for status in stats.by_status %}
|
|
<tr>
|
|
<td>{{ status.status|title }}</td>
|
|
<td>{{ status.count }}</td>
|
|
<td>{{ status.percentage|floatformat:1 }}%</td>
|
|
<td>
|
|
<div class="progress" style="height: 20px;">
|
|
<div class="progress-bar" role="progressbar" style="width: {{ status.percentage }}%"></div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Appointments by Department -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Appointments by Department</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Department</th>
|
|
<th>Total</th>
|
|
<th>Completed</th>
|
|
<th>Cancelled</th>
|
|
<th>No Shows</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for dept in stats.by_department %}
|
|
<tr>
|
|
<td>{{ dept.department_name }}</td>
|
|
<td>{{ dept.total }}</td>
|
|
<td>{{ dept.completed }}</td>
|
|
<td>{{ dept.cancelled }}</td>
|
|
<td>{{ dept.no_shows }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-4">
|
|
<!-- Key Metrics -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Key Metrics</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row mb-3">
|
|
<div class="col-8">Show Rate:</div>
|
|
<div class="col-4 text-end">
|
|
<span class="badge bg-success">{{ stats.show_rate|floatformat:1 }}%</span>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-8">Completion Rate:</div>
|
|
<div class="col-4 text-end">
|
|
<span class="badge bg-primary">{{ stats.completion_rate|floatformat:1 }}%</span>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-8">Cancellation Rate:</div>
|
|
<div class="col-4 text-end">
|
|
<span class="badge bg-warning">{{ stats.cancellation_rate|floatformat:1 }}%</span>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-8">Average Duration:</div>
|
|
<div class="col-4 text-end">{{ stats.avg_duration|default:"N/A" }} min</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-8">Peak Hour:</div>
|
|
<div class="col-4 text-end">{{ stats.peak_hour|default:"N/A" }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Top Providers -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Top Providers</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
{% for provider in stats.top_providers %}
|
|
<div class="d-flex align-items-center mb-3">
|
|
<div class="flex-grow-1">
|
|
<div class="fw-bold">{{ provider.provider_name }}</div>
|
|
<small class="text-muted">{{ provider.department }}</small>
|
|
</div>
|
|
<div class="text-end">
|
|
<div class="fw-bold">{{ provider.appointment_count }}</div>
|
|
<small class="text-muted">appointments</small>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Recent Trends -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Recent Trends</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row mb-2">
|
|
<div class="col-8">This Week:</div>
|
|
<div class="col-4 text-end">{{ stats.this_week|default:0 }}</div>
|
|
</div>
|
|
<div class="row mb-2">
|
|
<div class="col-8">Last Week:</div>
|
|
<div class="col-4 text-end">{{ stats.last_week|default:0 }}</div>
|
|
</div>
|
|
<div class="row mb-2">
|
|
<div class="col-8">This Month:</div>
|
|
<div class="col-4 text-end">{{ stats.this_month|default:0 }}</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-8">Last Month:</div>
|
|
<div class="col-4 text-end">{{ stats.last_month|default:0 }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</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>
|
|
{% endblock %}
|
|
|