HH/templates/complaints/sla_management.html
2026-03-28 14:03:56 +03:00

452 lines
18 KiB
HTML

{% extends 'layouts/base.html' %}
{% load static %}
{% load i18n %}
{% block title %}{% trans "Complaint SLA Management" %} | {{ hospital.name }}{% endblock %}
{% block extra_css %}
<style>
:root {
--hh-navy: #005696;
--hh-blue: #007bbd;
--hh-light: #eef6fb;
--hh-slate: #64748b;
}
.page-header-gradient {
background: linear-gradient(135deg, #005696 0%, #0069a8 50%, #007bbd 100%);
color: white;
padding: 1.5rem 2rem;
border-radius: 1rem;
margin-bottom: 1.5rem;
box-shadow: 0 10px 15px -3px rgba(0, 86, 150, 0.2);
}
.section-card {
background: white;
border-radius: 1rem;
border: 2px solid #e2e8f0;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: all 0.3s ease;
margin-bottom: 1.5rem;
}
.section-card:hover {
border-color: #005696;
box-shadow: 0 10px 25px -5px rgba(0, 86, 150, 0.15);
}
.section-header {
padding: 1rem 1.5rem;
border-bottom: 2px solid #e2e8f0;
background: linear-gradient(to right, #f8fafc, #f1f5f9);
display: flex;
align-items: center;
gap: 0.75rem;
}
.table-container {
overflow-x: auto;
}
.table-container table {
width: 100%;
border-collapse: collapse;
}
.table-container thead {
background: linear-gradient(135deg, var(--hh-light), #e0f2fe);
}
.table-container th {
padding: 0.875rem 1rem;
text-align: left;
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--hh-navy);
border-bottom: 2px solid #bae6fd;
}
.table-container td {
padding: 1rem;
border-bottom: 1px solid #f1f5f9;
color: #475569;
font-size: 0.875rem;
}
.table-container tbody tr {
transition: background-color 0.2s ease;
}
.table-container tbody tr:hover {
background-color: var(--hh-light);
}
.stat-card {
background: white;
border-radius: 1rem;
border: 2px solid #e2e8f0;
padding: 1.5rem;
transition: all 0.3s ease;
}
.stat-card:hover {
border-color: #005696;
box-shadow: 0 10px 25px -5px rgba(0, 86, 150, 0.15);
}
.badge {
display: inline-flex;
align-items: center;
gap: 0.375rem;
padding: 0.375rem 0.75rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 700;
}
.text-navy {
color: #005696;
}
.text-blue {
color: #007bbd;
}
.text-slate {
color: #64748b;
}
.bg-navy {
background-color: #005696;
}
.bg-blue {
background-color: #007bbd;
}
.bg-light {
background-color: #eef6fb;
}
.bg-slate {
background-color: #64748b;
}
.hover\:bg-blue-50:hover {
background-color: #eff6ff;
}
.hover\:bg-green-50:hover {
background-color: #f0fdf4;
}
.hover\:bg-slate-100:hover {
background-color: #f1f5f9;
}
</style>
{% endblock %}
{% block content %}
<!-- Page Header -->
<div class="page-header-gradient">
<div class="flex justify-between items-center">
<div>
<h1 class="text-2xl font-bold mb-1">
<i data-lucide="file-clock" class="w-6 h-6 inline-block mr-2"></i>
{% trans "Complaint SLA Management" %}
</h1>
<p class="text-blue-100 text-sm">{% trans "Configure Service Level Agreements for complaint resolution" %}</p>
</div>
<a href="{% url 'complaints:sla_management_create' %}"
class="inline-flex items-center px-4 py-2.5 bg-white text-navy font-medium rounded-xl hover:bg-blue-50 transition">
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
{% trans "Add SLA Configuration" %}
</a>
</div>
<!-- Hospital Badge -->
<div class="mt-4 bg-white/10 backdrop-blur-sm border border-white/20 rounded-xl p-4">
<div class="flex items-center">
<i data-lucide="building-2" class="w-5 h-5 text-white/90 mr-3"></i>
<div>
<p class="text-xs text-white/80 font-medium">{% trans "Current Hospital" %}</p>
<p class="text-sm font-bold text-white">{{ hospital.name }}</p>
</div>
</div>
</div>
</div>
<!-- Main Content -->
<div class="section-card p-6">
<!-- Stats Cards -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
<div class="stat-card bg-white rounded-2xl border-2 border-slate-200 p-6 flex items-center gap-4">
<div class="flex-shrink-0">
<div class="w-14 h-14 bg-navy/10 rounded-xl flex items-center justify-center">
<i data-lucide="file-text" class="w-7 h-7 text-navy"></i>
</div>
</div>
<div>
<h6 class="text-slate-500 text-sm font-medium mb-1">{% trans "Total Configurations" %}</h6>
<h2 class="text-3xl font-bold text-gray-800">{{ total_configs }}</h2>
</div>
</div>
<div class="stat-card bg-white rounded-2xl border-2 border-slate-200 p-6 flex items-center gap-4">
<div class="flex-shrink-0">
<div class="w-14 h-14 bg-blue-500/10 rounded-xl flex items-center justify-center">
<i data-lucide="layers" class="w-7 h-7 text-blue-600"></i>
</div>
</div>
<div>
<h6 class="text-slate-500 text-sm font-medium mb-1">{% trans "Source-Based SLAs" %}</h6>
<h2 class="text-3xl font-bold text-gray-800">{{ source_based_configs.count }}</h2>
</div>
</div>
<div class="stat-card bg-white rounded-2xl border-2 border-slate-200 p-6 flex items-center gap-4">
<div class="flex-shrink-0">
<div class="w-14 h-14 bg-purple-500/10 rounded-xl flex items-center justify-center">
<i data-lucide="tag" class="w-7 h-7 text-purple-600"></i>
</div>
</div>
<div>
<h6 class="text-slate-500 text-sm font-medium mb-1">{% trans "Severity-Based SLAs" %}</h6>
<h2 class="text-3xl font-bold text-gray-800">{{ severity_based_configs.count }}</h2>
</div>
</div>
</div>
<!-- Info Panel -->
<div class="bg-blue-50 border-2 border-blue-200 rounded-xl p-4 mb-6">
<div class="flex">
<div class="flex-shrink-0">
<i data-lucide="info" class="h-5 w-5 text-blue-600"></i>
</div>
<div class="ml-3">
<h3 class="text-sm font-bold text-blue-800">{% trans "SLA Configuration Priority" %}</h3>
<div class="mt-2 text-sm text-blue-700">
<ol class="list-decimal list-inside space-y-1">
<li><strong>{% trans "Source-based configs" %}</strong> ({% trans "MOH, CCHI, Patient, etc." %}) {% trans "take precedence" %}</li>
<li><strong>{% trans "Severity/Priority-based configs" %}</strong> {% trans "apply when no source-based config exists" %}</li>
<li><strong>{% trans "System defaults" %}</strong> {% trans "are used as fallback" %}</li>
</ol>
</div>
</div>
</div>
</div>
</div>
<!-- Source-Based Configurations -->
<div class="section-card">
<div class="section-header flex items-center justify-between p-6">
<div class="flex items-center gap-3">
<div class="w-10 h-10 bg-blue-500/10 rounded-xl flex items-center justify-center">
<i data-lucide="layers" class="w-5 h-5 text-blue-600"></i>
</div>
<div>
<h2 class="text-lg font-bold text-navy m-0">{% trans "Source-Based SLA Configurations" %}</h2>
<p class="text-sm text-slate mt-0.5">{% trans "SLAs based on complaint source (MOH, CCHI, Patient, etc.)" %}</p>
</div>
</div>
</div>
{% if source_based_configs %}
<div class="table-container px-6 pb-6">
<table class="w-full">
<thead>
<tr>
<th class="text-left">{% trans "Source" %}</th>
<th class="text-center">{% trans "SLA (Hours)" %}</th>
<th class="text-center">{% trans "1st Reminder" %}</th>
<th class="text-center">{% trans "2nd Reminder" %}</th>
<th class="text-center">{% trans "Escalation" %}</th>
<th class="text-right">{% trans "Actions" %}</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-slate-100">
{% for config in source_based_configs %}
<tr class="hover:bg-slate-50/50 transition">
<td class="px-5 py-4">
<div class="flex items-center gap-3">
<div class="w-10 h-10 bg-blue-50 rounded-lg flex items-center justify-center flex-shrink-0">
<i data-lucide="building-2" class="w-5 h-5 text-blue-600"></i>
</div>
<div>
<div class="text-sm font-bold text-navy">{{ config.source.name_en }}</div>
<div class="text-xs text-slate">{{ config.source.name_ar }}</div>
</div>
</div>
</td>
<td class="px-5 py-4 text-center">
<span class="inline-flex items-center px-3 py-1 rounded-lg text-sm font-bold bg-blue-100 text-blue-800">
{{ config.sla_hours }}h
</span>
</td>
<td class="px-5 py-4 text-center text-sm text-slate">
{% if config.first_reminder_hours_after > 0 %}
+{{ config.first_reminder_hours_after }}h
{% else %}
-{{ config.reminder_hours_before }}h
{% endif %}
</td>
<td class="px-5 py-4 text-center text-sm text-slate">
{% if config.second_reminder_hours_after > 0 %}
+{{ config.second_reminder_hours_after }}h
{% elif config.second_reminder_enabled %}
-{{ config.second_reminder_hours_before }}h
{% else %}
<span class="text-slate-400"></span>
{% endif %}
</td>
<td class="px-5 py-4 text-center text-sm text-slate">
{% if config.escalation_hours_after > 0 %}
+{{ config.escalation_hours_after }}h
{% else %}
<span class="text-slate-400">{% trans "On overdue" %}</span>
{% endif %}
</td>
<td class="px-5 py-4 text-right">
<div class="flex items-center justify-end gap-2">
<a href="{% url 'complaints:sla_management_edit' config.pk %}"
class="p-2 text-blue hover:bg-blue-50 rounded-lg transition"
title="{% trans 'Edit' %}">
<i data-lucide="edit-2" class="w-4 h-4"></i>
</a>
<form action="{% url 'complaints:sla_management_toggle' config.pk %}" method="POST" class="inline">
{% csrf_token %}
<button type="submit"
class="p-2 {% if config.is_active %}text-green hover:bg-green-50{% else %}text-slate-400 hover:bg-slate-100{% endif %} rounded-lg transition"
title="{% if config.is_active %}{% trans 'Deactivate' %}{% else %}{% trans 'Activate' %}{% endif %}">
<i data-lucide="{% if config.is_active %}check-circle{% else %}circle{% endif %}" class="w-4 h-4"></i>
</button>
</form>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-12 px-6">
<div class="w-16 h-16 bg-slate-100 rounded-full flex items-center justify-center mx-auto mb-4">
<i data-lucide="file-text" class="w-8 h-8 text-slate-400"></i>
</div>
<h3 class="text-lg font-bold text-navy mb-2">{% trans "No source-based configurations" %}</h3>
<p class="text-slate mb-6">{% trans "Get started by creating a new SLA configuration." %}</p>
<a href="{% url 'complaints:sla_management_create' %}"
class="inline-flex items-center px-5 py-2.5 bg-navy text-white font-medium rounded-xl hover:bg-blue transition">
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
{% trans "Add Source-Based SLA" %}
</a>
</div>
{% endif %}
</div>
<!-- Severity-Based Configurations -->
<div class="section-card">
<div class="section-header flex items-center justify-between p-6">
<div class="flex items-center gap-3">
<div class="w-10 h-10 bg-purple-500/10 rounded-xl flex items-center justify-center">
<i data-lucide="tag" class="w-5 h-5 text-purple-600"></i>
</div>
<div>
<h2 class="text-lg font-bold text-navy m-0">{% trans "Severity/Priority-Based SLA Configurations" %}</h2>
<p class="text-sm text-slate mt-0.5">{% trans "SLAs based on complaint severity and priority levels" %}</p>
</div>
</div>
</div>
{% if severity_based_configs %}
<div class="table-container px-6 pb-6">
<table class="w-full">
<thead>
<tr>
<th class="text-left">{% trans "Severity" %}</th>
<th class="text-left">{% trans "Priority" %}</th>
<th class="text-center">{% trans "SLA (Hours)" %}</th>
<th class="text-center">{% trans "1st Reminder" %}</th>
<th class="text-center">{% trans "2nd Reminder" %}</th>
<th class="text-right">{% trans "Actions" %}</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-slate-100">
{% for config in severity_based_configs %}
<tr class="hover:bg-slate-50/50 transition">
<td class="px-5 py-4">
{% include 'complaints/partials/severity_badge.html' with severity=config.severity %}
</td>
<td class="px-5 py-4">
{% include 'complaints/partials/priority_badge.html' with priority=config.priority %}
</td>
<td class="px-5 py-4 text-center">
<span class="inline-flex items-center px-3 py-1 rounded-lg text-sm font-bold bg-purple-100 text-purple-800">
{{ config.sla_hours }}h
</span>
</td>
<td class="px-5 py-4 text-center text-sm text-slate">
{% if config.first_reminder_hours_after > 0 %}
+{{ config.first_reminder_hours_after }}h
{% else %}
-{{ config.reminder_hours_before }}h
{% endif %}
</td>
<td class="px-5 py-4 text-center text-sm text-slate">
{% if config.second_reminder_hours_after > 0 %}
+{{ config.second_reminder_hours_after }}h
{% elif config.second_reminder_enabled %}
-{{ config.second_reminder_hours_before }}h
{% else %}
<span class="text-slate-400"></span>
{% endif %}
</td>
<td class="px-5 py-4 text-right">
<div class="flex items-center justify-end gap-2">
<a href="{% url 'complaints:sla_management_edit' config.pk %}"
class="p-2 text-blue hover:bg-blue-50 rounded-lg transition"
title="{% trans 'Edit' %}">
<i data-lucide="edit-2" class="w-4 h-4"></i>
</a>
<form action="{% url 'complaints:sla_management_toggle' config.pk %}" method="POST" class="inline">
{% csrf_token %}
<button type="submit"
class="p-2 {% if config.is_active %}text-green hover:bg-green-50{% else %}text-slate-400 hover:bg-slate-100{% endif %} rounded-lg transition"
title="{% if config.is_active %}{% trans 'Deactivate' %}{% else %}{% trans 'Activate' %}{% endif %}">
<i data-lucide="{% if config.is_active %}check-circle{% else %}circle{% endif %}" class="w-4 h-4"></i>
</button>
</form>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-12 px-6">
<div class="w-16 h-16 bg-slate-100 rounded-full flex items-center justify-center mx-auto mb-4">
<i data-lucide="tag" class="w-8 h-8 text-slate-400"></i>
</div>
<h3 class="text-lg font-bold text-navy mb-2">{% trans "No severity-based configurations" %}</h3>
<p class="text-slate mb-6">{% trans "Get started by creating a new SLA configuration." %}</p>
<a href="{% url 'complaints:sla_management_create' %}"
class="inline-flex items-center px-5 py-2.5 bg-navy text-white font-medium rounded-xl hover:bg-blue transition">
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
{% trans "Add Severity-Based SLA" %}
</a>
</div>
{% endif %}
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
});
</script>
{% endblock %}