275 lines
15 KiB
HTML
275 lines
15 KiB
HTML
{% extends "layouts/base.html" %}
|
|
{% load i18n %}
|
|
|
|
{% block title %}{% trans "Onboarding & Acknowledgements Dashboard" %}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="p-6 md:p-8 bg-gradient-to-br from-light to-blue-50 min-h-screen">
|
|
<!-- Header -->
|
|
<div class="mb-8">
|
|
<div class="flex items-center gap-3 mb-4">
|
|
<div class="flex items-center justify-center w-14 h-14 bg-gradient-to-br from-blue to-navy rounded-2xl shadow-lg shadow-blue-200">
|
|
<i data-lucide="clipboard-check" class="w-8 h-8 text-white"></i>
|
|
</div>
|
|
<div>
|
|
<h1 class="text-3xl font-bold text-navy mb-1">
|
|
{% trans "Onboarding & Acknowledgements" %}
|
|
</h1>
|
|
<p class="text-slate">
|
|
{% trans "Manage staff onboarding progress and acknowledgements" %}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Stats Cards -->
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
|
|
<div class="bg-white p-6 rounded-2xl shadow-sm border border-blue-100 hover:shadow-md transition">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<div class="flex items-center gap-3">
|
|
<div class="bg-gradient-to-br from-blue to-blue-100 p-2.5 rounded-xl">
|
|
<i data-lucide="users" class="text-blue w-5 h-5"></i>
|
|
</div>
|
|
<span class="text-slate text-sm font-semibold">{% trans "Total Invited" %}</span>
|
|
</div>
|
|
</div>
|
|
<div class="text-4xl font-bold text-navy">{{ stats.total_invited }}</div>
|
|
<div class="mt-2 text-xs text-slate">{% trans "staff members invited" %}</div>
|
|
</div>
|
|
|
|
<div class="bg-white p-6 rounded-2xl shadow-sm border border-emerald-100 hover:shadow-md transition">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<div class="flex items-center gap-3">
|
|
<div class="bg-gradient-to-br from-emerald-500 to-emerald-600 p-2.5 rounded-xl">
|
|
<i data-lucide="check-circle" class="text-white w-5 h-5"></i>
|
|
</div>
|
|
<span class="text-slate text-sm font-semibold">{% trans "Completed" %}</span>
|
|
</div>
|
|
</div>
|
|
<div class="text-4xl font-bold text-navy">{{ stats.completed }}</div>
|
|
<div class="mt-2 text-xs text-slate">{% trans "completed onboarding" %}</div>
|
|
</div>
|
|
|
|
<div class="bg-white p-6 rounded-2xl shadow-sm border border-orange-100 hover:shadow-md transition">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<div class="flex items-center gap-3">
|
|
<div class="bg-gradient-to-br from-orange-400 to-orange-500 p-2.5 rounded-xl">
|
|
<i data-lucide="clock" class="text-white w-5 h-5"></i>
|
|
</div>
|
|
<span class="text-slate text-sm font-semibold">{% trans "In Progress" %}</span>
|
|
</div>
|
|
</div>
|
|
<div class="text-4xl font-bold text-navy">{{ stats.in_progress }}</div>
|
|
<div class="mt-2 text-xs text-slate">{% trans "currently in progress" %}</div>
|
|
</div>
|
|
|
|
<div class="bg-white p-6 rounded-2xl shadow-sm border border-red-100 hover:shadow-md transition">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<div class="flex items-center gap-3">
|
|
<div class="bg-gradient-to-br from-red-500 to-red-600 p-2.5 rounded-xl">
|
|
<i data-lucide="circle-x" class="text-white w-5 h-5"></i>
|
|
</div>
|
|
<span class="text-slate text-sm font-semibold">{% trans "Not Started" %}</span>
|
|
</div>
|
|
</div>
|
|
<div class="text-4xl font-bold text-navy">{{ stats.not_started }}</div>
|
|
<div class="mt-2 text-xs text-slate">{% trans "haven't started" %}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick Actions -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
|
<a href="{% url 'accounts:bulk-invite-users' %}" class="group">
|
|
<div class="bg-white p-6 rounded-2xl shadow-sm border-2 border-blue-100 hover:border-blue hover:shadow-lg hover:-translate-y-1 transition-all duration-200">
|
|
<div class="flex items-center gap-4 mb-3">
|
|
<div class="bg-gradient-to-br from-blue to-navy p-3 rounded-xl group-hover:shadow-lg transition">
|
|
<i data-lucide="mail-plus" class="text-white w-6 h-6"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Bulk Invite" %}</h3>
|
|
</div>
|
|
<p class="text-sm text-slate">{% trans "Invite multiple staff via CSV" %}</p>
|
|
</div>
|
|
</a>
|
|
|
|
<a href="{% url 'accounts:acknowledgement-checklist-list' %}" class="group">
|
|
<div class="bg-white p-6 rounded-2xl shadow-sm border-2 border-blue-100 hover:border-blue hover:shadow-lg hover:-translate-y-1 transition-all duration-200">
|
|
<div class="flex items-center gap-4 mb-3">
|
|
<div class="bg-gradient-to-br from-blue to-cyan-500 p-3 rounded-xl group-hover:shadow-lg transition">
|
|
<i data-lucide="list-checks" class="text-white w-6 h-6"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Checklist" %}</h3>
|
|
</div>
|
|
<p class="text-sm text-slate">{% trans "Manage checklist items" %}</p>
|
|
</div>
|
|
</a>
|
|
|
|
<a href="{% url 'accounts:acknowledgement-content-list' %}" class="group">
|
|
<div class="bg-white p-6 rounded-2xl shadow-sm border-2 border-blue-100 hover:border-blue hover:shadow-lg hover:-translate-y-1 transition-all duration-200">
|
|
<div class="flex items-center gap-4 mb-3">
|
|
<div class="bg-gradient-to-br from-blue to-indigo-500 p-3 rounded-xl group-hover:shadow-lg transition">
|
|
<i data-lucide="file-text" class="text-white w-6 h-6"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Content" %}</h3>
|
|
</div>
|
|
<p class="text-sm text-slate">{% trans "Manage onboarding content" %}</p>
|
|
</div>
|
|
</a>
|
|
|
|
<a href="{% url 'accounts:provisional-user-list' %}" class="group">
|
|
<div class="bg-white p-6 rounded-2xl shadow-sm border-2 border-blue-100 hover:border-blue hover:shadow-lg hover:-translate-y-1 transition-all duration-200">
|
|
<div class="flex items-center gap-4 mb-3">
|
|
<div class="bg-gradient-to-br from-blue to-purple-500 p-3 rounded-xl group-hover:shadow-lg transition">
|
|
<i data-lucide="user-plus" class="text-white w-6 h-6"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Accounts" %}</h3>
|
|
</div>
|
|
<p class="text-sm text-slate">{% trans "View provisional accounts" %}</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
<!-- Recent Activity -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-blue-100 overflow-hidden">
|
|
<div class="px-6 py-5 border-b border-blue-100 bg-gradient-to-r from-blue-50 to-transparent">
|
|
<h2 class="text-lg font-bold text-navy flex items-center gap-2">
|
|
<i data-lucide="activity" class="w-5 h-5 text-blue"></i>
|
|
{% trans "Recent Activity" %}
|
|
</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
<div class="space-y-4">
|
|
{% for activity in recent_activations %}
|
|
<div class="flex items-center gap-4 p-4 bg-gradient-to-r from-blue-50/50 to-transparent rounded-xl border border-blue-50">
|
|
<div class="flex items-center justify-center w-12 h-12 bg-white rounded-full shadow-sm border border-blue-100">
|
|
<i data-lucide="check-circle" class="w-6 h-6 text-emerald-500"></i>
|
|
</div>
|
|
<div class="flex-1">
|
|
<p class="font-bold text-navy">{{ activity.get_full_name|default:activity.email }}</p>
|
|
<p class="text-sm text-slate">{% trans "Completed onboarding" %} • {{ activity.acknowledgement_completed_at|timesince }}</p>
|
|
</div>
|
|
</div>
|
|
{% empty %}
|
|
<div class="text-center py-8">
|
|
<i data-lucide="inbox" class="w-12 h-12 text-blue-200 mx-auto mb-3"></i>
|
|
<p class="text-slate">{% trans "No recent activity" %}</p>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Completion by Role -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-blue-100 overflow-hidden">
|
|
<div class="px-6 py-5 border-b border-blue-100 bg-gradient-to-r from-blue-50 to-transparent">
|
|
<h2 class="text-lg font-bold text-navy flex items-center gap-2">
|
|
<i data-lucide="circle-help" class="w-5 h-5 text-blue"></i>
|
|
{% trans "Completion by Role" %}
|
|
</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
<div class="space-y-4">
|
|
{% for role_data in completion_by_role %}
|
|
<div>
|
|
<div class="flex items-center justify-between mb-2">
|
|
<span class="text-sm font-semibold text-navy">{{ role_data.role }}</span>
|
|
<span class="text-sm font-bold text-blue">{{ role_data.rate }}%</span>
|
|
</div>
|
|
<div class="w-full bg-blue-100 h-2.5 rounded-full overflow-hidden">
|
|
<div class="bg-gradient-to-r from-blue to-navy h-full rounded-full" style="width: {{ role_data.rate }}%"></div>
|
|
</div>
|
|
<div class="flex items-center gap-3 mt-1">
|
|
<span class="text-xs text-emerald-600 font-medium">{{ role_data.completed }} completed</span>
|
|
<span class="text-xs text-slate">{{ role_data.pending }} pending</span>
|
|
</div>
|
|
</div>
|
|
{% empty %}
|
|
<div class="text-center py-8">
|
|
<i data-lucide="circle-help" class="w-12 h-12 text-blue-200 mx-auto mb-3"></i>
|
|
<p class="text-slate">{% trans "No data available" %}</p>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Pending Users -->
|
|
<div class="mt-6 bg-white rounded-2xl shadow-sm border border-blue-100 overflow-hidden">
|
|
<div class="px-6 py-5 border-b border-blue-100 bg-gradient-to-r from-blue-50 to-transparent">
|
|
<h2 class="text-lg font-bold text-navy flex items-center gap-2">
|
|
<i data-lucide="clock" class="w-5 h-5 text-blue"></i>
|
|
{% trans "Pending Activations" %}
|
|
</h2>
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead class="bg-blue-50">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "User" %}</th>
|
|
<th class="px-6 py-3 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "Email" %}</th>
|
|
<th class="px-6 py-3 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "Role" %}</th>
|
|
<th class="px-6 py-3 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "Expires" %}</th>
|
|
<th class="px-6 py-3 text-left text-xs font-bold text-blue-800 uppercase tracking-wider">{% trans "Status" %}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-blue-50">
|
|
{% for user in pending_users %}
|
|
<tr class="hover:bg-blue-50/50 transition">
|
|
<td class="px-6 py-4">
|
|
<div class="flex items-center gap-3">
|
|
<div class="flex items-center justify-center w-10 h-10 bg-gradient-to-br from-blue to-navy rounded-full">
|
|
<span class="text-white font-bold text-sm">{{ user.first_name|first|default:"U" }}{{ user.last_name|first|default:"" }}</span>
|
|
</div>
|
|
<span class="font-semibold text-navy">{{ user.get_full_name|default:user.email }}</span>
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4 text-slate">{{ user.email }}</td>
|
|
<td class="px-6 py-4">
|
|
{% if user.groups.first %}
|
|
<span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-bold bg-blue-100 text-blue-700">
|
|
{{ user.groups.first.name }}
|
|
</span>
|
|
{% endif %}
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span class="text-sm {% if user.is_expiring_soon %}text-red-600 font-bold{% else %}text-slate{% endif %}">
|
|
{% if user.days_remaining %}
|
|
{{ user.days_remaining }} {% trans "days" %}
|
|
{% else %}-{% endif %}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
{% if user.is_expiring_soon %}
|
|
<span class="inline-flex items-center gap-1 px-3 py-1 rounded-full text-xs font-bold bg-red-100 text-red-700">
|
|
<i data-lucide="alert-circle" class="w-3 h-3"></i>
|
|
{% trans "Expiring Soon" %}
|
|
</span>
|
|
{% else %}
|
|
<span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-bold bg-orange-100 text-orange-700">
|
|
{% trans "Pending" %}
|
|
</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="5" class="px-6 py-12 text-center">
|
|
<i data-lucide="check-circle" class="w-12 h-12 text-emerald-500 mx-auto mb-3"></i>
|
|
<p class="text-slate">{% trans "All users have activated their accounts" %}</p>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
lucide.createIcons();
|
|
});
|
|
</script>
|
|
{% endblock %}
|