HH/templates/dashboard/department_benchmarks.html

263 lines
9.9 KiB
HTML

{% extends "layouts/base.html" %}
{% load i18n %}
{% block title %}{% trans "Department Benchmarks" %} - PX360{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Header -->
<div class="row mb-4">
<div class="col">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'dashboard:admin_evaluation' %}">{% trans "Admin Evaluation" %}</a></li>
<li class="breadcrumb-item active">{% trans "Department Benchmarks" %}</li>
</ol>
</nav>
<div class="d-flex justify-content-between align-items-center">
<div>
<h2 class="h3 mb-1">{% trans "Department Benchmarks" %}</h2>
<p class="text-muted mb-0">{{ benchmarks.department }} - {% trans "Staff Performance Comparison" %}</p>
</div>
<div>
<a href="{% url 'dashboard:admin_evaluation' %}" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Evaluation" %}
</a>
</div>
</div>
</div>
</div>
{% if benchmarks.error %}
<div class="alert alert-warning">
{{ benchmarks.error }}
</div>
{% else %}
<!-- Summary Cards -->
<div class="row g-3 mb-4">
<div class="col-md-3">
<div class="card bg-primary text-white">
<div class="card-body">
<h6 class="card-title">{% trans "Total Staff" %}</h6>
<h3 class="mb-0">{{ benchmarks.staff_count }}</h3>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-info text-white">
<div class="card-body">
<h6 class="card-title">{% trans "Average Score" %}</h6>
<h3 class="mb-0">{{ benchmarks.average_score }}</h3>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-success text-white">
<div class="card-body">
<h6 class="card-title">{% trans "Top Performer" %}</h6>
<h5 class="mb-0 text-truncate">{{ benchmarks.top_performer.name|default:"-" }}</h5>
<small>{{ benchmarks.top_performer.score|default:"0" }} pts</small>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-warning text-dark">
<div class="card-body">
<h6 class="card-title">{% trans "Avg Items/Staff" %}</h6>
<h3 class="mb-0">{{ benchmarks.average_items_per_staff }}</h3>
</div>
</div>
</div>
</div>
<!-- Charts Row -->
<div class="row g-4 mb-4">
<div class="col-lg-8">
<div class="card">
<div class="card-header">
<h5 class="mb-0">{% trans "Performance Rankings" %}</h5>
</div>
<div class="card-body">
<canvas id="rankingsChart" height="300"></canvas>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card">
<div class="card-header">
<h5 class="mb-0">{% trans "Rating Distribution" %}</h5>
</div>
<div class="card-body">
<canvas id="ratingDistributionChart" height="300"></canvas>
</div>
</div>
</div>
</div>
<!-- Needs Improvement Alert -->
{% if benchmarks.needs_improvement %}
<div class="alert alert-warning mb-4">
<h5><i class="bi bi-exclamation-triangle me-2"></i>{% trans "Staff Needing Improvement" %}</h5>
<p class="mb-2">{% trans "The following staff members have performance scores below 60:" %}</p>
<ul class="mb-0">
{% for staff in benchmarks.needs_improvement %}
<li>
<a href="{% url 'dashboard:staff_performance_detail' staff.id %}" class="fw-bold">
{{ staff.name }}
</a>
- {{ staff.score }} pts ({{ staff.total_items }} items)
</li>
{% endfor %}
</ul>
</div>
{% endif %}
<!-- Rankings Table -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">{% trans "Detailed Rankings" %}</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th class="text-center">{% trans "Rank" %}</th>
<th>{% trans "Staff Name" %}</th>
<th class="text-center">{% trans "Performance Score" %}</th>
<th class="text-center">{% trans "Rating" %}</th>
<th class="text-center">{% trans "Complaints" %}</th>
<th class="text-center">{% trans "Inquiries" %}</th>
<th class="text-center">{% trans "Total Items" %}</th>
<th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for staff in benchmarks.rankings %}
<tr class="{% if forloop.first %}table-success{% endif %}">
<td class="text-center">
{% if forloop.first %}
<i class="bi bi-trophy-fill text-warning fs-5"></i>
{% elif forloop.counter == 2 %}
<i class="bi bi-trophy-fill text-secondary fs-5"></i>
{% elif forloop.counter == 3 %}
<i class="bi bi-trophy-fill text-danger fs-5"></i>
{% else %}
{{ forloop.counter }}
{% endif %}
</td>
<td class="fw-bold">{{ staff.name }}</td>
<td class="text-center">
<span class="badge bg-{% if staff.score >= 90 %}success{% elif staff.score >= 75 %}info{% elif staff.score >= 60 %}warning{% else %}danger{% endif %} fs-6">
{{ staff.score }}
</span>
</td>
<td class="text-center">{{ staff.rating }}</td>
<td class="text-center">{{ staff.complaints }}</td>
<td class="text-center">{{ staff.inquiries }}</td>
<td class="text-center fw-bold">{{ staff.total_items }}</td>
<td>
<a href="{% url 'dashboard:staff_performance_detail' staff.id %}" class="btn btn-sm btn-outline-primary">
<i class="bi bi-eye me-1"></i>{% trans "View" %}
</a>
</td>
</tr>
{% empty %}
<tr>
<td colspan="8" class="text-center text-muted">
{% trans "No staff data available" %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}
</div>
{% endblock %}
{% block extra_js %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const rankingsData = {{ benchmarks.rankings|safe }};
document.addEventListener('DOMContentLoaded', function() {
if (rankingsData.length === 0) return;
// Rankings Bar Chart
const rankingsCtx = document.getElementById('rankingsChart').getContext('2d');
new Chart(rankingsCtx, {
type: 'bar',
data: {
labels: rankingsData.map(r => r.name),
datasets: [{
label: '{% trans "Performance Score" %}',
data: rankingsData.map(r => r.score),
backgroundColor: rankingsData.map(r => {
if (r.score >= 90) return '#10b981';
if (r.score >= 75) return '#3b82f6';
if (r.score >= 60) return '#f59e0b';
return '#ef4444';
}),
borderWidth: 0
}]
},
options: {
responsive: true,
indexAxis: 'y',
scales: {
x: {
beginAtZero: true,
max: 100
}
},
plugins: {
legend: {
display: false
}
}
}
});
// Rating Distribution Pie Chart
const ratingCounts = {
'Excellent': 0,
'Good': 0,
'Average': 0,
'Below Average': 0,
'Needs Improvement': 0
};
rankingsData.forEach(r => {
if (ratingCounts.hasOwnProperty(r.rating)) {
ratingCounts[r.rating]++;
}
});
const ratingCtx = document.getElementById('ratingDistributionChart').getContext('2d');
new Chart(ratingCtx, {
type: 'doughnut',
data: {
labels: Object.keys(ratingCounts),
datasets: [{
data: Object.values(ratingCounts),
backgroundColor: ['#10b981', '#3b82f6', '#f59e0b', '#ef4444', '#6b7280']
}]
},
options: {
responsive: true,
plugins: {
legend: {
position: 'bottom'
}
}
}
});
});
</script>
{% endblock %}