452 lines
18 KiB
HTML
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 %}
|