HH/templates/dashboard/command_center.html
Marwan Alwali 867f60fed7 update
2026-01-08 20:56:18 +03:00

340 lines
15 KiB
HTML

{% extends 'layouts/base.html' %}
{% load i18n %}
{% block title %}PX Command Center - PX360{% endblock %}
{% block page_title %}PX Command Center{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Top KPI Cards -->
{% include 'layouts/partials/stat_cards.html' with stats=stats %}
<!-- Charts Row -->
<div class="row g-3 mb-4">
<!-- Complaints Trend -->
<div class="col-lg-8">
<div class="card table-card">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-graph-up me-2"></i>{% trans "Complaints Trend (Last 30 Days)" %}</h5>
</div>
<div class="card-body">
<div id="complaintsTrendChart"></div>
</div>
</div>
</div>
<!-- Survey Satisfaction -->
<div class="col-lg-4">
<div class="card table-card">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-star me-2"></i>{% trans "Survey Satisfaction" %}</h5>
</div>
<div class="card-body text-center">
<div class="display-3 text-primary mb-2">{{ chart_data.survey_satisfaction|floatformat:1 }}</div>
<p class="text-muted">Average Score (Last 30 Days)</p>
<div class="progress" style="height: 10px;">
<div class="progress-bar bg-success" role="progressbar"
style="width: {{ chart_data.survey_satisfaction|floatformat:0 }}%"></div>
</div>
</div>
</div>
</div>
</div>
<!-- Live Feed Row -->
<div class="row g-3">
<!-- Latest High Severity Complaints -->
<div class="col-lg-6">
<div class="card table-card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0"><i class="bi bi-exclamation-triangle me-2"></i>{% trans "Latest High Severity Complaints" %}</h5>
<a href="#" class="btn btn-sm btn-primary">{% trans "View All" %}</a>
</div>
<div class="card-body p-0">
{% if latest_complaints %}
<div class="list-group list-group-flush">
{% for complaint in latest_complaints %}
<div class="list-group-item">
<div class="d-flex justify-content-between align-items-start">
<div class="flex-grow-1">
<h6 class="mb-1">{{ complaint.title }}</h6>
<p class="mb-1 text-muted small">
<i class="bi bi-person me-1"></i>{{ complaint.patient.get_full_name }}
<i class="bi bi-building ms-2 me-1"></i>{{ complaint.hospital.name }}
</p>
<small class="text-muted">{{ complaint.created_at|timesince }} ago</small>
</div>
<div>
<span class="badge bg-{{ complaint.severity }}">{{ complaint.get_severity_display }}</span>
{% if complaint.is_overdue %}
<span class="badge bg-danger ms-1">OVERDUE</span>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="p-4 text-center text-muted">
<i class="bi bi-check-circle fs-1"></i>
<p class="mt-2">No high severity complaints</p>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Latest Escalated Actions -->
<div class="col-lg-6">
<div class="card table-card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0"><i class="bi bi-arrow-up-circle me-2"></i>{% trans "Latest Escalated Actions" %}</h5>
<a href="#" class="btn btn-sm btn-primary">{% trans "View All" %}</a>
</div>
<div class="card-body p-0">
{% if latest_actions %}
<div class="list-group list-group-flush">
{% for action in latest_actions %}
<div class="list-group-item">
<div class="d-flex justify-content-between align-items-start">
<div class="flex-grow-1">
<h6 class="mb-1">{{ action.title }}</h6>
<p class="mb-1 text-muted small">
<i class="bi bi-building me-1"></i>{{ action.hospital.name }}
{% if action.assigned_to %}
<i class="bi bi-person ms-2 me-1"></i>{{ action.assigned_to.get_full_name }}
{% endif %}
</p>
<small class="text-muted">Escalated {{ action.escalated_at|timesince }} ago</small>
</div>
<div>
<span class="badge bg-danger">Level {{ action.escalation_level }}</span>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="p-4 text-center text-muted">
<i class="bi bi-check-circle fs-1"></i>
<p class="mt-2">No escalated actions</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Top Physicians This Month -->
<div class="row g-3 mt-3">
<div class="col-12">
<div class="card table-card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0"><i class="bi bi-trophy text-warning me-2"></i>{% trans "Top Physicians This Month" %}</h5>
<a href="{% url 'physicians:leaderboard' %}" class="btn btn-sm btn-primary">{% trans "View Leaderboard" %}</a>
</div>
<div class="card-body p-0">
{% if top_physicians %}
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead>
<tr>
<th style="width: 60px;">{% trans "Rank" %}</th>
<th>{% trans "Physician" %}</th>
<th>{% trans "Specialization" %}</th>
<th>{% trans "Department" %}</th>
<th>{% trans "Rating" %}</th>
<th>{% trans "Surveys" %}</th>
<th>{% trans "Sentiment" %}</th>
</tr>
</thead>
<tbody>
{% for rating in top_staff %}
<tr onclick="window.location=''" style="cursor: pointer;">
<td>
{% if forloop.counter == 1 %}
<h4 class="mb-0"><i class="bi bi-trophy-fill text-warning"></i></h4>
{% elif forloop.counter == 2 %}
<h4 class="mb-0"><i class="bi bi-trophy-fill text-secondary"></i></h4>
{% elif forloop.counter == 3 %}
<h4 class="mb-0"><i class="bi bi-trophy-fill" style="color: #cd7f32;"></i></h4>
{% else %}
<strong class="text-muted">#{{ forloop.counter }}</strong>
{% endif %}
</td>
<td>
<strong>{{ rating.staff }}</strong><br>
<small class="text-muted">{{ rating.staff.license_number }}</small>
</td>
<td>{{ rating.staff.specialization }}</td>
<td>
{% if rating.staff.department %}
{{ rating.staff.department.name }}
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
<h5 class="mb-0 text-success">{{ rating.average_rating|floatformat:2 }}</h5>
</td>
<td>
<span class="badge bg-light text-dark">{{ rating.total_surveys }}</span>
</td>
<td>
<div class="d-flex gap-1">
<span class="badge bg-success" title="{% trans 'Positive' %}">{{ rating.positive_count }}</span>
<span class="badge bg-warning" title="{% trans 'Neutral' %}">{{ rating.neutral_count }}</span>
<span class="badge bg-danger" title="{% trans 'Negative' %}">{{ rating.negative_count }}</span>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="p-4 text-center text-muted">
<i class="bi bi-trophy fs-1"></i>
<p class="mt-2">{% trans "No physician ratings available for this month" %}</p>
</div>
{% endif %}
</div>
{% if physician_stats.total_physicians %}
<div class="card-footer bg-light">
<div class="row text-center">
<div class="col-4">
<strong>{{ physician_stats.total_physicians }}</strong>
<br><small class="text-muted">{% trans "Physicians Rated" %}</small>
</div>
<div class="col-4">
<strong>{{ physician_stats.avg_rating|floatformat:2 }}</strong>
<br><small class="text-muted">{% trans "Average Rating" %}</small>
</div>
<div class="col-4">
<strong>{{ physician_stats.total_surveys }}</strong>
<br><small class="text-muted">{% trans "Total Surveys" %}</small>
</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Latest Integration Events -->
<div class="row g-3 mt-3">
<div class="col-12">
<div class="card table-card">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-activity me-2"></i>{% trans "Latest Integration Events" %}</h5>
</div>
<div class="card-body p-0">
{% if latest_events %}
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead>
<tr>
<th>{% trans "Source" %}</th>
<th>{% trans "Event Code" %}</th>
<th>{% trans "Encounter ID" %}</th>
<th>{% trans "Status" %}</th>
<th>{% trans "Processed At" %}</th>
</tr>
</thead>
<tbody>
{% for event in latest_events %}
<tr>
<td><span class="badge bg-info">{{ event.get_source_system_display }}</span></td>
<td><code>{{ event.event_code }}</code></td>
<td>{{ event.encounter_id }}</td>
<td><span class="badge bg-success">{{ event.get_status_display }}</span></td>
<td>{{ event.processed_at|timesince }} ago</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="p-4 text-center text-muted">
<i class="bi bi-inbox fs-1"></i>
<p class="mt-2">No recent events</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
// Complaints Trend Chart - ApexCharts
const chartElement = document.getElementById('complaintsTrendChart');
if (chartElement) {
const trendData = {{ chart_data.complaints_trend|safe }};
var options = {
series: [{
name: 'Complaints',
data: trendData.map(d => d.count)
}],
chart: {
type: 'area',
height: 320,
toolbar: {
show: false
}
},
stroke: {
curve: 'smooth',
width: 3
},
colors: ['#ef4444'],
fill: {
type: 'gradient',
gradient: {
shadeIntensity: 1,
opacityFrom: 0.4,
opacityTo: 0.1,
}
},
xaxis: {
categories: trendData.map(d => d.date),
labels: {
style: {
fontSize: '12px'
}
}
},
yaxis: {
min: 0,
forceNiceScale: true,
labels: {
style: {
fontSize: '12px'
}
}
},
grid: {
borderColor: '#e7e7e7',
strokeDashArray: 5
},
tooltip: {
theme: 'light',
x: {
format: 'dd MMM yyyy'
}
},
dataLabels: {
enabled: false
}
};
var chart = new ApexCharts(chartElement, options);
chart.render();
}
</script>
{% endblock %}