344 lines
16 KiB
HTML
344 lines
16 KiB
HTML
{% extends "base.html" %}
|
|
{% load i18n static patient_tags %}
|
|
|
|
{% block title %}{% trans "Dashboard" %} - {{ block.super }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<!-- Page Header -->
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<div>
|
|
<h1 class="h3 mb-0">
|
|
<i class="fa fa-dashboard me-2"></i>{% trans "Dashboard" %}
|
|
</h1>
|
|
<p class="text-muted mb-0">{% trans "Welcome back" %}, {{ request.user.get_full_name }}</p>
|
|
</div>
|
|
<div class="text-end">
|
|
<small class="text-muted">
|
|
<i class="fa fa-building me-1"></i>{% if LANGUAGE_CODE == 'ar' %}{{ request.tenant.name_ar }}{% else %}{{ request.tenant.name }}{% endif %}
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- Statistics Cards -->
|
|
<div class="row mb-4">
|
|
<!-- Total Patients -->
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="card border-left-primary shadow h-100 py-2">
|
|
<div class="card-body">
|
|
<div class="row no-gutters align-items-center">
|
|
<div class="col mr-2">
|
|
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
|
|
{% trans "Total Patients" %}
|
|
</div>
|
|
<div class="h5 mb-0 font-weight-bold text-gray-800">
|
|
{{ stats.total_patients|default:0 }}
|
|
</div>
|
|
</div>
|
|
<div class="col-auto">
|
|
<i class="fa fa-users fa-2x text-gray-300"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Today's Appointments -->
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="card border-left-success shadow h-100 py-2">
|
|
<div class="card-body">
|
|
<div class="row no-gutters align-items-center">
|
|
<div class="col mr-2">
|
|
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
|
|
{% trans "Today's Appointments" %}
|
|
</div>
|
|
<div class="h5 mb-0 font-weight-bold text-gray-800">
|
|
{{ stats.today_appointments|default:0 }}
|
|
</div>
|
|
</div>
|
|
<div class="col-auto">
|
|
<i class="fa fa-calendar-check fa-2x text-gray-300"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Active Queue -->
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="card border-left-warning shadow h-100 py-2">
|
|
<div class="card-body">
|
|
<div class="row no-gutters align-items-center">
|
|
<div class="col mr-2">
|
|
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
|
|
{% trans "Patients in Queue" %}
|
|
</div>
|
|
<div class="h5 mb-0 font-weight-bold text-gray-800">
|
|
{{ stats.queue_count|default:0 }}
|
|
</div>
|
|
</div>
|
|
<div class="col-auto">
|
|
<i class="fa fa-list-ol fa-2x text-gray-300"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Active Employees -->
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="card border-left-info shadow h-100 py-2">
|
|
<div class="card-body">
|
|
<div class="row no-gutters align-items-center">
|
|
<div class="col mr-2">
|
|
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">
|
|
{% trans "Active Employees" %}
|
|
</div>
|
|
<div class="h5 mb-0 font-weight-bold text-gray-800">
|
|
{{ stats.active_employees|default:0 }}
|
|
</div>
|
|
</div>
|
|
<div class="col-auto">
|
|
<i class="fa fa-user-md fa-2x text-gray-300"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Left Column -->
|
|
<div class="col-lg-8">
|
|
<!-- Today's Schedule -->
|
|
<div class="card shadow mb-4">
|
|
<div class="card-header py-3 d-flex justify-content-between align-items-center">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="fa fa-calendar-day me-2"></i>{% trans "Today's Schedule" %}
|
|
</h6>
|
|
<a href="{% url 'appointments:appointment_calendar' %}" class="btn btn-sm btn-primary">
|
|
{% trans "View Calendar" %}
|
|
</a>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if today_appointments %}
|
|
<div class="table-responsive">
|
|
<table class="table table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>{% trans "Time" %}</th>
|
|
<th>{% trans "Patient" %}</th>
|
|
<th>{% trans "Service" %}</th>
|
|
<th>{% trans "Provider" %}</th>
|
|
<th>{% trans "Status" %}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for apt in today_appointments|slice:":10" %}
|
|
<tr>
|
|
<td>{{ apt.start_time|time:"H:i" }}</td>
|
|
<td>
|
|
<a href="{% url 'core:patient-detail' apt.patient.pk %}">
|
|
{% patient_name apt.patient %}
|
|
</a>
|
|
</td>
|
|
<td>{{ apt.service.name }}</td>
|
|
<td>{{ apt.provider.first_name }} {{ apt.provider.last_name }}</td>
|
|
<td>
|
|
<span class="badge bg-{% if apt.status == 'SCHEDULED' %}primary{% elif apt.status == 'CONFIRMED' %}success{% elif apt.status == 'CHECKED_IN' %}warning{% elif apt.status == 'COMPLETED' %}secondary{% else %}danger{% endif %}">
|
|
{{ apt.get_status_display }}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<p class="text-muted text-center py-4 mb-0">
|
|
{% trans "No appointments scheduled for today." %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Recent Encounters -->
|
|
<div class="card shadow mb-4">
|
|
<div class="card-header py-3 d-flex justify-content-between align-items-center">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="fa fa-stethoscope me-2"></i>{% trans "Recent Encounters" %}
|
|
</h6>
|
|
<a href="" class="btn btn-sm btn-primary">
|
|
{% trans "View All" %}
|
|
</a>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if recent_encounters %}
|
|
<div class="list-group list-group-flush">
|
|
{% for encounter in recent_encounters|slice:":5" %}
|
|
<a href="{% url 'clinic:encounter-detail' encounter.pk %}" class="list-group-item list-group-item-action">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div>
|
|
<h6 class="mb-1">{% patient_name encounter.patient %}</h6>
|
|
<p class="mb-1 text-muted">
|
|
<small>
|
|
<i class="fa fa-calendar me-1"></i>{{ encounter.encounter_date|date:"Y-m-d" }}
|
|
<i class="fa fa-user-md ms-2 me-1"></i>{{ encounter.provider.first_name }} {{ encounter.provider.last_name }}
|
|
</small>
|
|
</p>
|
|
</div>
|
|
<span class="badge bg-{% if encounter.status == 'COMPLETED' %}success{% elif encounter.status == 'IN_PROGRESS' %}warning{% else %}secondary{% endif %}">
|
|
{{ encounter.get_status_display }}
|
|
</span>
|
|
</div>
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<p class="text-muted text-center py-4 mb-0">
|
|
{% trans "No recent encounters." %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Column -->
|
|
<div class="col-lg-4">
|
|
<!-- Quick Actions -->
|
|
<div class="card shadow mb-4">
|
|
<div class="card-header py-3">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="fa fa-bolt me-2"></i>{% trans "Quick Actions" %}
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-grid gap-2">
|
|
<a href="{% url 'core:patient_create' %}" class="btn btn-primary">
|
|
<i class="fa fa-user-plus me-2"></i>{% trans "Add New Patient" %}
|
|
</a>
|
|
<a href="{% url 'appointments:appointment_create' %}" class="btn btn-success">
|
|
<i class="fa fa-calendar-plus me-2"></i>{% trans "Schedule Appointment" %}
|
|
</a>
|
|
<a href="" class="btn btn-info">
|
|
<i class="fa fa-stethoscope me-2"></i>{% trans "New Encounter" %}
|
|
</a>
|
|
<a href="" class="btn btn-warning">
|
|
<i class="fa fa-list-ol me-2"></i>{% trans "Queue Board" %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Service Statistics -->
|
|
<div class="card shadow mb-4">
|
|
<div class="card-header py-3">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="fa fa-chart-pie me-2"></i>{% trans "Services Overview" %}
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if service_stats %}
|
|
{% for service in service_stats %}
|
|
<div class="mb-3">
|
|
<div class="d-flex justify-content-between align-items-center mb-1">
|
|
<small class="font-weight-bold">{{ service.name }}</small>
|
|
<small class="text-muted">{{ service.count }} {% trans "patients" %}</small>
|
|
</div>
|
|
<div class="progress" style="height: 10px;">
|
|
<div class="progress-bar bg-primary" role="progressbar"
|
|
style="width: {{ service.percentage }}%"
|
|
aria-valuenow="{{ service.percentage }}"
|
|
aria-valuemin="0"
|
|
aria-valuemax="100">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
{% else %}
|
|
<p class="text-muted text-center mb-0">{% trans "No service data available." %}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Pending Tasks -->
|
|
<div class="card shadow mb-4">
|
|
<div class="card-header py-3">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="fa fa-tasks me-2"></i>{% trans "Pending Tasks" %}
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="list-group list-group-flush">
|
|
{% if pending_referrals %}
|
|
<div class="list-group-item px-0">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<span>
|
|
<i class="fa fa-exchange-alt text-warning me-2"></i>
|
|
{% trans "Pending Referrals" %}
|
|
</span>
|
|
<span class="badge bg-warning">{{ pending_referrals }}</span>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if unsigned_notes %}
|
|
<div class="list-group-item px-0">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<span>
|
|
<i class="fa fa-file-signature text-danger me-2"></i>
|
|
{% trans "Unsigned Notes" %}
|
|
</span>
|
|
<span class="badge bg-danger">{{ unsigned_notes }}</span>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if pending_consents %}
|
|
<div class="list-group-item px-0">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<span>
|
|
<i class="fa fa-file-contract text-info me-2"></i>
|
|
{% trans "Pending Consents" %}
|
|
</span>
|
|
<span class="badge bg-info">{{ pending_consents }}</span>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if not pending_referrals and not unsigned_notes and not pending_consents %}
|
|
<p class="text-muted text-center py-3 mb-0">
|
|
<i class="fa fa-check-circle text-success fa-2x mb-2"></i><br>
|
|
{% trans "All tasks completed!" %}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block css %}
|
|
<style>
|
|
.border-left-primary {
|
|
border-left: 0.25rem solid #4e73df !important;
|
|
}
|
|
.border-left-success {
|
|
border-left: 0.25rem solid #1cc88a !important;
|
|
}
|
|
.border-left-warning {
|
|
border-left: 0.25rem solid #f6c23e !important;
|
|
}
|
|
.border-left-info {
|
|
border-left: 0.25rem solid #36b9cc !important;
|
|
}
|
|
.text-xs {
|
|
font-size: 0.7rem;
|
|
}
|
|
</style>
|
|
{% endblock %}
|