Add staff dashboard and work wizards v1

This commit is contained in:
A R R R Associates
2026-07-05 20:15:21 +05:30
parent 21c71c7172
commit bbf71599b8
14 changed files with 503 additions and 0 deletions
@@ -0,0 +1,70 @@
{% extends "ui/templates/base/layout.html" %}
{% block content %}
<div class="space-y-6">
<section class="rounded-3xl bg-gradient-to-r from-slate-900 via-brand-700 to-brand-600 p-6 text-white shadow-soft">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<p class="text-xs font-semibold uppercase tracking-[0.24em] text-brand-100">Staff Work Execution</p>
<h1 class="mt-2 text-2xl font-bold">Staff Dashboard V1</h1>
<p class="mt-2 max-w-3xl text-sm text-brand-100">Your assigned tasks, due work, client-pending items, documents, returned work and staff work wizards in one place.</p>
<p class="mt-3 text-xs text-brand-100">FY: {{ overview.financial_year or 'All' }}{% if overview.employee %} · {{ overview.employee.full_name }}{% endif %}</p>
</div>
<div class="flex flex-wrap gap-2">
<a href="/employees/work" class="rounded-xl bg-white px-4 py-2 text-sm font-semibold text-brand-700 hover:bg-brand-50">Open My Work</a>
<a href="/documents" class="rounded-xl border border-white/40 px-4 py-2 text-sm font-semibold text-white hover:bg-white/10">Documents</a>
</div>
</div>
</section>
{% set tabs = [
('my-tasks','My Tasks'),
('due-today','Due Today'),
('overdue','Overdue'),
('client-pending','Client Pending'),
('documents','Documents'),
('returned-work','Returned Work'),
('reports','Reports'),
('wizards','Wizards')
] %}
<section class="rounded-3xl border border-slate-200 bg-white p-3 shadow-soft">
<div class="flex gap-2 overflow-x-auto" id="staff-tabs">
{% for code, label in tabs %}
<button type="button" data-tab="{{ code }}" class="staff-tab whitespace-nowrap rounded-2xl px-4 py-2 text-sm font-semibold transition {% if active_tab == code %}bg-brand-600 text-white{% else %}text-slate-600 hover:bg-slate-100{% endif %}">{{ label }}</button>
{% endfor %}
</div>
</section>
<section id="staff-dashboard-panel">
{% include 'modules/staff_dashboard/templates/staff_dashboard/partials/' ~ (active_tab|replace('-', '_')) ~ '.html' ignore missing %}
</section>
</div>
<script>
(function(){
const tabs = document.querySelectorAll('.staff-tab');
const panel = document.getElementById('staff-dashboard-panel');
async function loadTab(tab) {
tabs.forEach(btn => {
const active = btn.dataset.tab === tab;
btn.classList.toggle('bg-brand-600', active);
btn.classList.toggle('text-white', active);
btn.classList.toggle('text-slate-600', !active);
btn.classList.toggle('hover:bg-slate-100', !active);
});
panel.innerHTML = '<div class="rounded-3xl border border-slate-200 bg-white p-8 text-center text-sm text-slate-500 shadow-soft">Loading...</div>';
try {
const res = await fetch('/staff/dashboard/tab/' + encodeURIComponent(tab), {headers: {'X-Requested-With':'fetch'}});
if (!res.ok) throw new Error('HTTP ' + res.status);
panel.innerHTML = await res.text();
const url = new URL(window.location.href);
url.searchParams.set('tab', tab);
window.history.replaceState({}, '', url);
} catch (err) {
panel.innerHTML = '<div class="rounded-3xl border border-red-200 bg-red-50 p-8 text-center text-sm font-semibold text-red-700 shadow-soft">Unable to load tab. Please refresh the page.</div>';
}
}
tabs.forEach(btn => btn.addEventListener('click', () => loadTab(btn.dataset.tab)));
})();
</script>
{% endblock %}
@@ -0,0 +1,46 @@
<div class="overflow-hidden rounded-3xl border border-slate-200 bg-white shadow-soft">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-slate-200 text-sm">
<thead class="bg-slate-50 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">
<tr>
<th class="px-4 py-3">Client</th>
<th class="px-4 py-3">Service / Task</th>
<th class="px-4 py-3">Due</th>
<th class="px-4 py-3">Status</th>
<th class="px-4 py-3">Priority</th>
<th class="px-4 py-3">Docs / Notes</th>
<th class="px-4 py-3 text-right">Action</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100">
{% for row in rows %}
<tr class="hover:bg-slate-50">
<td class="px-4 py-3">
<div class="font-semibold text-slate-900">{{ row.client_name }}</div>
<div class="text-xs text-slate-500">{{ row.client_code or '-' }}</div>
</td>
<td class="px-4 py-3">
<div class="text-xs font-semibold uppercase tracking-wide text-brand-600">{{ row.service_name }}</div>
<div class="font-medium text-slate-900">{{ row.task_name }}</div>
<div class="text-xs text-slate-500">Period: {{ row.period }}</div>
</td>
<td class="px-4 py-3">
{% if row.due_date %}
<div class="font-medium {% if row.is_overdue %}text-red-700{% elif row.is_due_today %}text-amber-700{% else %}text-slate-700{% endif %}">{{ row.due_date.strftime('%d-%b-%Y') }}</div>
{% if row.is_overdue %}<div class="text-xs text-red-600">{{ row.days_overdue }} day(s) overdue</div>{% endif %}
{% else %}
<span class="text-slate-400">No due date</span>
{% endif %}
</td>
<td class="px-4 py-3"><span class="rounded-full bg-slate-100 px-3 py-1 text-xs font-semibold text-slate-700">{{ row.status_label }}</span></td>
<td class="px-4 py-3"><span class="rounded-full bg-brand-50 px-3 py-1 text-xs font-semibold text-brand-700">{{ row.priority|title }}</span></td>
<td class="px-4 py-3 text-xs text-slate-500">Docs: {{ row.document_count }}<br>Notes: {{ row.comment_count }}</td>
<td class="px-4 py-3 text-right"><a href="{{ row.href }}" class="rounded-xl bg-brand-600 px-3 py-2 text-xs font-semibold text-white hover:bg-brand-700">Open</a></td>
</tr>
{% else %}
<tr><td colspan="7" class="px-4 py-10 text-center text-sm text-slate-500">No tasks found for this view.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
@@ -0,0 +1,5 @@
<div class="space-y-4">
<div class="rounded-3xl border border-orange-200 bg-orange-50 p-5 shadow-soft"><h2 class="text-lg font-bold text-orange-900">Client Pending</h2><p class="mt-1 text-sm text-orange-700">Work blocked due to client data, document or clarification pending.</p></div>
{% set rows = client_pending %}
{% include 'modules/staff_dashboard/templates/staff_dashboard/partials/_task_table.html' %}
</div>
@@ -0,0 +1,8 @@
<div class="space-y-4">
<div class="flex flex-col gap-3 rounded-3xl border border-slate-200 bg-white p-5 shadow-soft md:flex-row md:items-center md:justify-between">
<div><h2 class="text-lg font-bold text-slate-900">Documents</h2><p class="mt-1 text-sm text-slate-500">Document-linked or document-pending tasks assigned to you.</p></div>
<a href="/documents" class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white hover:bg-brand-700">Open Documents</a>
</div>
{% set rows = documents_pending %}
{% include 'modules/staff_dashboard/templates/staff_dashboard/partials/_task_table.html' %}
</div>
@@ -0,0 +1,5 @@
<div class="space-y-4">
<div class="rounded-3xl border border-amber-200 bg-amber-50 p-5 shadow-soft"><h2 class="text-lg font-bold text-amber-900">Due Today</h2><p class="mt-1 text-sm text-amber-700">Tasks assigned to you with internal target date today.</p></div>
{% set rows = due_today %}
{% include 'modules/staff_dashboard/templates/staff_dashboard/partials/_task_table.html' %}
</div>
@@ -0,0 +1,10 @@
<div class="space-y-6">
<div class="grid gap-4 md:grid-cols-4">
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><p class="text-xs font-semibold uppercase text-slate-500">Open Tasks</p><p class="mt-2 text-3xl font-bold text-slate-900">{{ overview.open_count }}</p></div>
<div class="rounded-3xl border border-amber-200 bg-amber-50 p-5 shadow-soft"><p class="text-xs font-semibold uppercase text-amber-700">Due Today</p><p class="mt-2 text-3xl font-bold text-amber-800">{{ overview.due_today_count }}</p></div>
<div class="rounded-3xl border border-red-200 bg-red-50 p-5 shadow-soft"><p class="text-xs font-semibold uppercase text-red-700">Overdue</p><p class="mt-2 text-3xl font-bold text-red-800">{{ overview.overdue_count }}</p></div>
<div class="rounded-3xl border border-brand-200 bg-brand-50 p-5 shadow-soft"><p class="text-xs font-semibold uppercase text-brand-700">In Progress</p><p class="mt-2 text-3xl font-bold text-brand-800">{{ overview.in_progress_count }}</p></div>
</div>
{% set rows = my_tasks %}
{% include 'modules/staff_dashboard/templates/staff_dashboard/partials/_task_table.html' %}
</div>
@@ -0,0 +1,5 @@
<div class="space-y-4">
<div class="rounded-3xl border border-red-200 bg-red-50 p-5 shadow-soft"><h2 class="text-lg font-bold text-red-900">Overdue Tasks</h2><p class="mt-1 text-sm text-red-700">Assigned open tasks past internal target date.</p></div>
{% set rows = overdue %}
{% include 'modules/staff_dashboard/templates/staff_dashboard/partials/_task_table.html' %}
</div>
@@ -0,0 +1,13 @@
<div class="space-y-5">
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><h2 class="text-lg font-bold text-slate-900">Staff Reports</h2><p class="mt-1 text-sm text-slate-500">Quick report cards based on your assigned work.</p></div>
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
{% for card in reports %}
<a href="{{ card.href }}" class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft transition hover:-translate-y-0.5 hover:shadow-lg">
<p class="text-xs font-semibold uppercase tracking-wide text-brand-600">{{ card.group }}</p>
<h3 class="mt-2 text-base font-bold text-slate-900">{{ card.title }}</h3>
<p class="mt-2 text-sm text-slate-500">{{ card.desc }}</p>
<p class="mt-4 text-sm font-semibold text-brand-700">View report →</p>
</a>
{% endfor %}
</div>
</div>
@@ -0,0 +1,5 @@
<div class="space-y-4">
<div class="rounded-3xl border border-purple-200 bg-purple-50 p-5 shadow-soft"><h2 class="text-lg font-bold text-purple-900">Returned / Correction Work</h2><p class="mt-1 text-sm text-purple-700">Tasks returned for correction, rework or resubmission.</p></div>
{% set rows = returned_work %}
{% include 'modules/staff_dashboard/templates/staff_dashboard/partials/_task_table.html' %}
</div>
@@ -0,0 +1,12 @@
<div class="space-y-5">
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><h2 class="text-lg font-bold text-slate-900">Staff Work Wizards</h2><p class="mt-1 text-sm text-slate-500">Action shortcuts for task execution using existing ERP screens.</p></div>
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
{% for card in wizards %}
<a href="{{ card.href }}" class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft transition hover:-translate-y-0.5 hover:shadow-lg">
<h3 class="text-base font-bold text-slate-900">{{ card.title }}</h3>
<p class="mt-2 text-sm text-slate-500">{{ card.desc }}</p>
<p class="mt-4 text-sm font-semibold text-brand-700">Open →</p>
</a>
{% endfor %}
</div>
</div>