Files
arrr-erp/app/modules/employees/templates/employees/progress_dashboard.html
T
2026-06-20 15:01:44 +05:30

106 lines
9.3 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "ui/templates/base/layout.html" %}
{% block content %}
{% include "modules/managers/templates/managers/_manager_tabs.html" %}
<div class="space-y-6">
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<h1 class="text-2xl font-semibold text-slate-900">Engagement Progress</h1>
<p class="mt-1 text-sm text-slate-500">Client-wise and engagement-wise progress based on existing service task instances.</p>
</div>
</div>
<div class="grid gap-4 md:grid-cols-4 xl:grid-cols-8">
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Clients</div><div class="mt-1 text-2xl font-semibold">{{ progress_payload.summary.clients }}</div></div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Engagements</div><div class="mt-1 text-2xl font-semibold">{{ progress_payload.summary.engagements }}</div></div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Tasks</div><div class="mt-1 text-2xl font-semibold">{{ progress_payload.summary.tasks }}</div></div>
<div class="rounded-2xl border border-blue-200 bg-blue-50 p-4 shadow-soft"><div class="text-xs font-semibold uppercase text-blue-600">Avg Progress</div><div class="mt-1 text-2xl font-semibold text-blue-700">{{ progress_payload.summary.average_progress }}%</div></div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Open</div><div class="mt-1 text-2xl font-semibold">{{ progress_payload.summary.open }}</div></div>
<div class="rounded-2xl border border-red-200 bg-red-50 p-4 shadow-soft"><div class="text-xs font-semibold uppercase text-red-600">Overdue</div><div class="mt-1 text-2xl font-semibold text-red-700">{{ progress_payload.summary.overdue }}</div></div>
<div class="rounded-2xl border border-amber-200 bg-amber-50 p-4 shadow-soft"><div class="text-xs font-semibold uppercase text-amber-600">Due Today</div><div class="mt-1 text-2xl font-semibold text-amber-700">{{ progress_payload.summary.due_today }}</div></div>
<div class="rounded-2xl border border-emerald-200 bg-emerald-50 p-4 shadow-soft"><div class="text-xs font-semibold uppercase text-emerald-600">Completed</div><div class="mt-1 text-2xl font-semibold text-emerald-700">{{ progress_payload.summary.completed }}</div></div>
</div>
<form method="get" action="/employees/progress" class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft">
<div class="grid gap-3 md:grid-cols-[1fr_180px_240px_auto]">
<input type="search" name="q" value="{{ q or '' }}" placeholder="Search client, engagement or task" class="rounded-xl border border-slate-300 px-3 py-2 text-sm focus:border-brand-500 focus:outline-none focus:ring-2 focus:ring-brand-100">
<select name="status" class="rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="open" {% if status == 'open' %}selected{% endif %}>Open engagements</option>
<option value="all" {% if status == 'all' %}selected{% endif %}>All tasks</option>
<option value="overdue" {% if status == 'overdue' %}selected{% endif %}>Overdue only</option>
<option value="due_today" {% if status == 'due_today' %}selected{% endif %}>Due today</option>
<option value="closed" {% if status == 'closed' %}selected{% endif %}>Closed tasks</option>
<option value="pending" {% if status == 'pending' %}selected{% endif %}>Pending</option>
<option value="in_progress" {% if status == 'in_progress' %}selected{% endif %}>In Progress</option>
<option value="blocked" {% if status == 'blocked' %}selected{% endif %}>Blocked</option>
<option value="completed" {% if status == 'completed' %}selected{% endif %}>Completed</option>
</select>
<select name="assigned_to_user_id" class="rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="0">All assignees</option>
{% for user in assignable_users %}
<option value="{{ user.id }}" {% if selected_assigned_to_user_id == user.id %}selected{% endif %}>{{ user.full_name or user.email }}</option>
{% endfor %}
</select>
<button type="submit" class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white hover:bg-brand-700">Filter</button>
</div>
</form>
<div class="space-y-4">
{% for client_group in progress_payload.clients %}
<details class="group rounded-2xl border border-slate-200 bg-white shadow-soft" {% if loop.first %}open{% endif %}>
<summary class="flex cursor-pointer list-none flex-wrap items-center justify-between gap-4 rounded-2xl px-5 py-4 hover:bg-slate-50">
<div>
<div class="text-lg font-semibold text-slate-900">{{ client_group.client_name }}</div>
<div class="text-xs text-slate-500">{{ client_group.client_code or 'No client code' }} · {{ client_group.engagements|length }} engagement{{ '' if client_group.engagements|length == 1 else 's' }} · {{ client_group.task_count }} task{{ '' if client_group.task_count == 1 else 's' }}</div>
</div>
<div class="min-w-[240px]">
<div class="flex justify-between text-xs font-semibold text-slate-500"><span>Client progress</span><span>{{ client_group.progress_percent }}%</span></div>
<div class="mt-1 h-2 rounded-full bg-slate-100"><div class="h-2 rounded-full bg-brand-600" style="width: {{ client_group.progress_percent }}%"></div></div>
<div class="mt-1 text-xs text-slate-500">Open {{ client_group.open_count }} · Completed {{ client_group.completed_count }} · Overdue {{ client_group.overdue_count }}</div>
</div>
<span class="text-lg text-slate-400 transition group-open:rotate-90"></span>
</summary>
<div class="space-y-3 border-t border-slate-100 p-4">
{% for engagement_group in client_group.engagements %}
<details class="group/eng rounded-xl border border-slate-200 bg-slate-50" {% if engagement_group.overdue_count > 0 or loop.first %}open{% endif %}>
<summary class="flex cursor-pointer list-none flex-wrap items-center justify-between gap-4 px-4 py-3 hover:bg-slate-100">
<div>
<div class="font-semibold text-slate-900">{{ engagement_group.label }}</div>
<div class="text-xs text-slate-500">Status: {{ engagement_group.status.replace('_',' ').title() }} · Due: {{ engagement_group.due_date or '-' }}</div>
</div>
<div class="min-w-[260px]">
<div class="flex justify-between text-xs font-semibold text-slate-500"><span>{{ engagement_group.progress_status.replace('_',' ').title() }}</span><span>{{ engagement_group.progress_percent }}%</span></div>
<div class="mt-1 h-2 rounded-full bg-slate-200"><div class="h-2 rounded-full {% if engagement_group.progress_status == 'completed' %}bg-emerald-600{% elif engagement_group.progress_status == 'overdue' %}bg-red-600{% else %}bg-brand-600{% endif %}" style="width: {{ engagement_group.progress_percent }}%"></div></div>
<div class="mt-1 text-xs text-slate-500">Open {{ engagement_group.open_count }} · Completed {{ engagement_group.completed_count }} · Unassigned {{ engagement_group.unassigned_count }}</div>
</div>
<span class="text-slate-400 transition group-open/eng:rotate-90"></span>
</summary>
<div class="overflow-x-auto border-t border-slate-200">
<table class="min-w-full divide-y divide-slate-200 text-sm">
<thead class="bg-slate-100 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">
<tr><th class="px-4 py-3">Task</th><th class="px-4 py-3">Assignee</th><th class="px-4 py-3">Status</th><th class="px-4 py-3">Priority</th><th class="px-4 py-3">Target</th></tr>
</thead>
<tbody class="divide-y divide-slate-100 bg-white">
{% for task in engagement_group.tasks %}
<tr class="{% if task.is_overdue %}bg-red-50{% elif task.is_due_today %}bg-amber-50{% endif %}">
<td class="px-4 py-3"><div class="font-medium text-slate-900">{{ task.task_name }}</div>{% if task.description %}<div class="mt-1 text-xs text-slate-500">{{ task.description }}</div>{% endif %}</td>
<td class="px-4 py-3">{{ task.assigned_to.full_name if task.assigned_to else 'Unassigned' }}</td>
<td class="px-4 py-3"><span class="rounded-full bg-slate-100 px-2.5 py-1 text-xs font-semibold text-slate-700">{{ task.status_label }}</span></td>
<td class="px-4 py-3">{{ task.priority_label }}</td>
<td class="px-4 py-3">{{ task.internal_target_date or '-' }}<div class="text-xs text-slate-500">{{ task.date_bucket }}</div></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</details>
{% endfor %}
</div>
</details>
{% else %}
<div class="rounded-2xl border border-slate-200 bg-white p-8 text-center shadow-soft"><h3 class="font-semibold text-slate-900">No progress data found</h3><p class="mt-1 text-sm text-slate-500">No engagement task matches the selected filter.</p></div>
{% endfor %}
</div>
</div>
{% endblock %}