Marwan Alwali 212fbb893c update
2025-12-11 10:47:50 +03:00

437 lines
20 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}Dashboard - {{ block.super }}{% endblock %}
{% block content %}
<!-- Page Header -->
<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-tachometer-alt"></i> {{ tenant.display_name }}<span class="fw-light">{{ tenant.city }}</span>
</h1>
<p class="text-muted">Manage all healthcare operations in one place</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 dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-download me-2"></i>Export
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="exportDashboard('pdf')">
<i class="fas fa-file-pdf me-2"></i>Export as PDF
</a></li>
<li><a class="dropdown-item" href="#" onclick="exportDashboard('excel')">
<i class="fas fa-file-excel me-2"></i>Export as Excel
</a></li>
</ul>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#quickActionsModal">
<i class="fas fa-plus me-2"></i>Quick Actions
</button>
</div>
</div>
</div>
<div class="container-fluid">
<!-- Dashboard Statistics -->
<div id="dashboard-stats"
hx-get="{% url 'core:dashboard_stats' %}"
hx-trigger="load, every 30s"
class="mb-4">
<div class="text-center">
<div class="spinner-border spinner-border-sm text-primary" role="status">
<span class="visually-hidden">Loading statistics...</span>
</div>
</div>
</div>
<div class="row mb-4">
<!-- Recent Activity -->
<div class="col-lg-8">
<div class="panel panel-inverse" data-sortable-id="index-1">
<div class="panel-heading">
<h4 class="panel-title"><i class="fas fa-history me-2"></i> {{ _("Recent Activity")}}</h4>
<div class="panel-heading-btn">
<a href="{% url 'core:audit_log' %}" class="btn btn-xs btn-outline-theme"><small>{{ _("View All")}}</small></a>
<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">
<div id="recent-audit-logs">
{% for log in recent_audit_logs %}
<div class="d-flex align-items-start mb-3 pb-3 {% if not forloop.last %}border-bottom{% endif %}">
<div class="avatar-sm bg-{{ log.event_type|lower|default:'primary' }} text-white rounded-circle d-flex align-items-center justify-content-center me-3">
<i class="fas fa-{% if log.event_type == 'ERROR' %}exclamation-triangle{% elif log.event_type == 'WARNING' %}exclamation{% else %}info{% endif %}"></i>
</div>
<div class="flex-grow-1">
<div class="d-flex justify-content-between align-items-start">
<div>
<h6 class="mb-1">{{ log.action }}</h6>
<p class="mb-1 text-muted">{{ log.description|truncatechars:100 }}</p>
<small class="text-muted">
<i class="fas fa-user me-1"></i>{{ log.user_email|default:"System" }}
<i class="fas fa-clock ms-2 me-1"></i>{{ log.timestamp|timesince }} ago
</small>
</div>
<span class="badge bg-{{ log.event_type|lower|default:'primary' }}">
{{ log.event_type|default:'INFO' }}
</span>
</div>
</div>
</div>
{% empty %}
<div class="text-center py-4">
<i class="fas fa-history fa-3x text-muted mb-3"></i>
<p class="text-muted">No recent activity to display.</p>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- System Health -->
<div class="panel panel-inverse mb-4" data-sortable-id="index-2">
<div class="panel-heading">
<h4 class="panel-title">
<i class="fas fa-heartbeat me-2"></i>System Health
</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="card-body p-4">
<div id="system-health"
hx-get="{% url 'core:system_health' %}"
hx-trigger="load, every 60s"
hx-swap="innerHTML">
<div class="text-center">
<div class="spinner-border spinner-border-sm text-primary" role="status">
<span class="visually-hidden">Loading system health...</span>
</div>
</div>
</div>
</div>
</div>
<!-- Tenant Information -->
{% if current_tenant %}
<div class="panel panel-inverse mb-4" data-sortable-id="index-3">
<div class="panel-heading">
<h4 class="panel-title">
<i class="fas fa-building me-2"></i>Organization Info
</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="card-body p-4">
<div id="tenant-info"
hx-get="{% url 'core:tenant_info' %}"
hx-trigger="load">
<div class="text-center">
<div class="spinner-border spinner-border-sm text-primary" role="status">
<span class="visually-hidden">Loading organization info...</span>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Quick Stats -->
<div class="panel panel-inverse mb-4" data-sortable-id="index-4">
<div class="panel-heading">
<h4 class="panel-title">
<i class="fas fa-chart-pie me-2"></i>Quick Stats
</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="card-body p-4">
<div class="row text-center">
<div class="col-6 mb-3">
<div class="border-end">
<h4 class="text-primary mb-1">{{ total_departments|default:0 }}</h4>
<small class="text-muted">Departments</small>
</div>
</div>
<div class="col-6 mb-3">
<h4 class="text-success mb-1">{{ total_configurations|default:0 }}</h4>
<small class="text-muted">Configurations</small>
</div>
<div class="col-6">
<div class="border-end">
<h4 class="text-info mb-1">{{ active_notifications|length|default:0 }}</h4>
<small class="text-muted">Active Alerts</small>
</div>
</div>
<div class="col-6">
<h4 class="text-warning mb-1">{{ recent_audit_logs|length|default:0 }}</h4>
<small class="text-muted">Recent Logs</small>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Quick Actions Grid -->
<div class="row mb-4">
<div class="col-12">
<div class="panel panel-inverse mb-4" data-sortable-id="index-5">
<div class="panel-heading">
<h4 class="panel-title">
<i class="fas fa-bolt me-2"></i>Quick Actions
</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="card-body p-4">
<div class="row">
<div class="col-xl-3 col-lg-4 col-md-6 mb-3">
<a href="{% url 'patients:patient_registration' %}" class="btn btn-outline-primary w-100 h-100 d-flex flex-column align-items-center justify-content-center py-4">
<i class="fas fa-user-plus fa-2x mb-3"></i>
<span>Register Patient</span>
</a>
</div>
<div class="col-xl-3 col-lg-4 col-md-6 mb-3">
{# <a href="{% url 'appointments:appointment_create' %}" class="btn btn-outline-success w-100 h-100 d-flex flex-column align-items-center justify-content-center py-4">#}
{# <i class="fas fa-calendar-plus fa-2x mb-3"></i>#}
{# <span>Schedule Appointment</span>#}
{# </a>#}
</div>
<div class="col-xl-3 col-lg-4 col-md-6 mb-3">
<a href="" class="btn btn-outline-info w-100 h-100 d-flex flex-column align-items-center justify-content-center py-4">
<i class="fas fa-notes-medical fa-2x mb-3"></i>
<span>Create EMR Entry</span>
</a>
</div>
<div class="col-xl-3 col-lg-4 col-md-6 mb-3">
<a href="{% url 'laboratory:lab_order_create' %}" class="btn btn-outline-warning w-100 h-100 d-flex flex-column align-items-center justify-content-center py-4">
<i class="fas fa-vial fa-2x mb-3"></i>
<span>Order Lab Test</span>
</a>
</div>
<div class="col-xl-3 col-lg-4 col-md-6 mb-3">
<a href="#" class="btn btn-outline-info w-100 h-100 d-flex flex-column align-items-center justify-content-center py-4" onclick="alert('EMR entry creation coming soon'); return false;">
<i class="fas fa-notes-medical fa-2x mb-3"></i>
<span>Create EMR Entry</span>
</a>
</div>
<div class="col-xl-3 col-lg-4 col-md-6 mb-3">
<a href="#" class="btn btn-outline-secondary w-100 h-100 d-flex flex-column align-items-center justify-content-center py-4" onclick="alert('Prescription creation coming soon'); return false;">
<i class="fas fa-prescription-bottle-alt fa-2x mb-3"></i>
<span>New Prescription</span>
</a>
</div>
<div class="col-xl-3 col-lg-4 col-md-6 mb-3">
<a href="#" class="btn btn-outline-dark w-100 h-100 d-flex flex-column align-items-center justify-content-center py-4" onclick="alert('Imaging scheduling coming soon'); return false;">
<i class="fas fa-x-ray fa-2x mb-3"></i>
<span>Schedule Imaging</span>
</a>
</div>
<div class="col-xl-3 col-lg-4 col-md-6 mb-3">
<a href="{% url 'analytics:dashboard' %}" class="btn btn-outline-primary w-100 h-100 d-flex flex-column align-items-center justify-content-center py-4">
<i class="fas fa-chart-bar fa-2x mb-3"></i>
<span>View Analytics</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Quick Actions Modal -->
<div class="modal fade" id="quickActionsModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fas fa-bolt me-2"></i>Quick Actions
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6 mb-3">
<a href="{% url 'patients:patient_registration' %}" class="btn btn-outline-primary w-100 text-start">
<i class="fas fa-user-plus me-3"></i>Register New Patient
</a>
</div>
<div class="col-md-6 mb-3">
{# <a href="{% url 'appointments:appointment_create' %}" class="btn btn-outline-success w-100 text-start">#}
{# <i class="fas fa-calendar-plus me-3"></i>Schedule Appointment#}
{# </a>#}
</div>
<div class="col-md-6 mb-3">
<a href="#" class="btn btn-outline-info w-100 text-start" onclick="alert('EMR entry creation coming soon'); return false;">
<i class="fas fa-notes-medical me-3"></i>Create Medical Record
</a>
</div>
<div class="col-md-6 mb-3">
<a href="{% url 'laboratory:lab_order_create' %}" class="btn btn-outline-warning w-100 text-start">
<i class="fas fa-vial me-3"></i>Order Laboratory Test
</a>
</div>
<div class="col-md-6 mb-3">
<a href="{% url 'billing:bill_create' %}" class="btn btn-outline-danger w-100 text-start">
<i class="fas fa-file-invoice-dollar me-3"></i>Create New Bill
</a>
</div>
<div class="col-md-6 mb-3">
<a href="#" class="btn btn-outline-secondary w-100 text-start" onclick="alert('Prescription creation coming soon'); return false;">
<i class="fas fa-prescription-bottle-alt me-3"></i>Write Prescription
</a>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<script>
// Dashboard functionality
document.addEventListener('DOMContentLoaded', function() {
// Auto-refresh indicators
setupAutoRefresh();
// Initialize tooltips
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
});
function setupAutoRefresh() {
// Add visual indicators for auto-refreshing content
const autoRefreshElements = document.querySelectorAll('[hx-trigger*="every"]');
autoRefreshElements.forEach(element => {
element.addEventListener('htmx:beforeRequest', function() {
// Add subtle loading indicator
const indicator = element.querySelector('.spinner-border');
if (indicator) {
indicator.style.display = 'inline-block';
}
});
element.addEventListener('htmx:afterRequest', function() {
// Hide loading indicator
const indicator = element.querySelector('.spinner-border');
if (indicator) {
indicator.style.display = 'none';
}
});
});
}
function exportDashboard(format) {
const params = new URLSearchParams({
format: format,
include_stats: true,
include_activity: true
});
// TODO: Implement export functionality
alert('Export functionality coming soon');
// window.open(`/core/export/dashboard/?${params.toString()}`);
}
// Keyboard shortcuts
document.addEventListener('keydown', function(e) {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') {
return;
}
switch (e.key) {
case 'q':
document.getElementById('quickActionsModal') && new bootstrap.Modal(document.getElementById('quickActionsModal')).show();
break;
case 'r':
location.reload();
break;
case 'h':
window.location.href = '{% url "core:dashboard" %}';
break;
}
});
</script>
<style>
.avatar-sm {
width: 40px;
height: 40px;
font-size: 16px;
}
.border-end {
border-right: 1px solid #dee2e6 !important;
}
.quick-action-btn {
transition: all 0.2s ease;
min-height: 120px;
}
.quick-action-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.htmx-indicator {
opacity: 0;
transition: opacity 0.3s ease;
}
.htmx-request .htmx-indicator {
opacity: 1;
}
@media (max-width: 768px) {
.border-end {
border-right: none !important;
border-bottom: 1px solid #dee2e6 !important;
padding-bottom: 1rem;
margin-bottom: 1rem;
}
.quick-action-btn {
min-height: 80px;
}
}
</style>
{% endblock %}