151 lines
11 KiB
HTML
151 lines
11 KiB
HTML
{% if employee %}
|
||
<section class="grid gap-4 md:grid-cols-2 xl:grid-cols-6">
|
||
<button type="button" data-tab="attendance" class="employee-portal-tab af-metric-card text-left hover:border-brand-200">
|
||
<div class="text-xs font-semibold uppercase text-slate-500">Attendance</div>
|
||
<div class="mt-2 text-lg font-semibold text-slate-900">{% if today_attendance %}{% if today_attendance.punch_out_utc %}Completed{% elif today_attendance.punch_in_utc %}Punched In{% else %}Marked{% endif %}{% else %}Not Marked{% endif %}</div>
|
||
<div class="mt-1 text-xs text-slate-500">Today</div>
|
||
</button>
|
||
<button type="button" data-tab="due-today" class="employee-portal-tab af-metric-card text-left hover:border-brand-200">
|
||
<div class="text-xs font-semibold uppercase text-slate-500">Due Today</div>
|
||
<div class="mt-2 text-3xl font-semibold text-brand-700">{{ work_payload.summary.due_today if work_payload else 0 }}</div>
|
||
<div class="mt-1 text-xs text-slate-500">Need action today</div>
|
||
</button>
|
||
<button type="button" data-tab="overdue" class="employee-portal-tab af-metric-card border-red-200 bg-red-50 text-left hover:border-red-300">
|
||
<div class="text-xs font-semibold uppercase text-red-700">Overdue</div>
|
||
<div class="mt-2 text-3xl font-semibold text-red-700">{{ work_payload.summary.overdue if work_payload else 0 }}</div>
|
||
<div class="mt-1 text-xs text-red-700">Immediate attention</div>
|
||
</button>
|
||
<button type="button" data-tab="client-pending" class="employee-portal-tab af-metric-card border-amber-200 bg-amber-50 text-left hover:border-amber-300">
|
||
<div class="text-xs font-semibold uppercase text-amber-700">Client Pending</div>
|
||
<div class="mt-2 text-3xl font-semibold text-amber-700">{{ work_payload.summary.blocked if work_payload else 0 }}</div>
|
||
<div class="mt-1 text-xs text-amber-700">Blocked / clarification</div>
|
||
</button>
|
||
<button type="button" data-tab="work" class="employee-portal-tab af-metric-card text-left hover:border-brand-200">
|
||
<div class="text-xs font-semibold uppercase text-slate-500">Open Work</div>
|
||
<div class="mt-2 text-3xl font-semibold text-slate-900">{{ work_payload.summary.open if work_payload else 0 }}</div>
|
||
<div class="mt-1 text-xs text-slate-500">Assigned to me</div>
|
||
</button>
|
||
<button type="button" data-tab="documents" class="employee-portal-tab af-metric-card text-left hover:border-brand-200">
|
||
<div class="text-xs font-semibold uppercase text-slate-500">Documents</div>
|
||
<div class="mt-2 text-3xl font-semibold text-slate-900">{{ own_documents|length }}</div>
|
||
<div class="mt-1 text-xs text-slate-500">Recent records</div>
|
||
</button>
|
||
</section>
|
||
|
||
<section class="grid gap-6 xl:grid-cols-[minmax(0,1fr)_420px]">
|
||
<div class="space-y-6">
|
||
<div class="af-card">
|
||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||
<div>
|
||
<h3 class="text-lg font-semibold text-slate-900">Today’s Priority Work</h3>
|
||
<p class="mt-1 text-sm text-slate-600">Overdue and due-today work appears first. Open the engagement to continue, add remarks, upload documents or submit work.</p>
|
||
</div>
|
||
<a href="/employee/work" class="af-btn af-btn-primary">Open Full Work Board</a>
|
||
</div>
|
||
<div class="mt-5 space-y-3">
|
||
{% set ns = namespace(count=0) %}
|
||
{% if work_payload %}
|
||
{% for column in work_payload.columns %}
|
||
{% for card in column.cards %}
|
||
{% if ns.count < 6 and (card.overdue_count or card.due_today_count) %}
|
||
{% set ns.count = ns.count + 1 %}
|
||
<article class="rounded-2xl border {% if card.overdue_count %}border-red-200 bg-red-50{% elif card.due_today_count %}border-amber-200 bg-amber-50{% else %}border-slate-200 bg-white{% endif %} p-4">
|
||
<div class="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
|
||
<div>
|
||
<div class="text-xs font-semibold uppercase tracking-wide {% if card.overdue_count %}text-red-700{% elif card.due_today_count %}text-amber-700{% else %}text-slate-500{% endif %}">{{ card.client_code or 'Client' }}</div>
|
||
<h4 class="mt-1 text-sm font-semibold text-slate-900">{{ card.client_name }} · {{ card.service_name }}</h4>
|
||
<p class="mt-1 text-xs text-slate-600">FY {{ card.financial_year }} · Due {{ card.due_date or '-' }} · {{ card.open_count }} open · {{ card.overdue_count }} overdue · {{ card.due_today_count }} due today</p>
|
||
</div>
|
||
<a href="/employee/work/engagements/{{ card.engagement_id }}" class="inline-flex justify-center rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white hover:bg-brand-700">Open</a>
|
||
</div>
|
||
</article>
|
||
{% endif %}
|
||
{% endfor %}
|
||
{% endfor %}
|
||
{% endif %}
|
||
{% if ns.count == 0 %}
|
||
<div class="rounded-2xl border border-dashed border-slate-300 bg-slate-50 p-6 text-sm text-slate-500">No overdue or due-today work is pending.</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grid gap-6 lg:grid-cols-2">
|
||
<div class="af-card">
|
||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||
<div>
|
||
<h3 class="text-lg font-semibold text-slate-900">Returned / Blocked Work</h3>
|
||
<p class="mt-1 text-sm text-slate-600">Items marked blocked require clarification, correction or client/manager input.</p>
|
||
</div>
|
||
<button type="button" data-tab="returned" class="employee-portal-tab af-btn af-btn-secondary">View</button>
|
||
</div>
|
||
<div class="mt-4 space-y-3">
|
||
{% set blocked = namespace(count=0) %}
|
||
{% if work_payload %}
|
||
{% for column in work_payload.columns if column.code == 'blocked' %}
|
||
{% for card in column.cards[:4] %}
|
||
{% set blocked.count = blocked.count + 1 %}
|
||
<a href="/employee/work/engagements/{{ card.engagement_id }}" class="block rounded-2xl border border-amber-200 bg-amber-50 p-4 hover:border-amber-300">
|
||
<div class="text-sm font-semibold text-slate-900">{{ card.client_name }}</div>
|
||
<div class="mt-1 text-xs text-amber-700">{{ card.service_name }} · {{ card.blocked_count }} blocked task(s)</div>
|
||
</a>
|
||
{% endfor %}
|
||
{% endfor %}
|
||
{% endif %}
|
||
{% if blocked.count == 0 %}<div class="rounded-2xl border border-dashed border-slate-300 p-5 text-sm text-slate-500">No blocked work pending.</div>{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="af-card">
|
||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||
<div>
|
||
<h3 class="text-lg font-semibold text-slate-900">Leave & Availability</h3>
|
||
<p class="mt-1 text-sm text-slate-600">Balances and recent leave requests.</p>
|
||
</div>
|
||
<a href="/employee/leave" class="af-btn af-btn-secondary">Open Leave</a>
|
||
</div>
|
||
<div class="mt-4 grid gap-3 md:grid-cols-2">
|
||
{% for bal in leave_balances[:4] %}
|
||
<div class="rounded-2xl border border-slate-200 bg-slate-50 p-4">
|
||
<div class="text-xs font-semibold uppercase text-slate-500">{{ bal.leave_type.name if bal.leave_type else bal.leave_type_id }}</div>
|
||
<div class="mt-2 text-2xl font-semibold text-slate-900">{{ bal.balance_days }}</div>
|
||
<div class="text-xs text-slate-500">days balance</div>
|
||
</div>
|
||
{% else %}
|
||
<div class="rounded-2xl border border-dashed border-slate-300 p-6 text-sm text-slate-500 md:col-span-2">No leave balance available yet.</div>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<aside class="space-y-6">
|
||
{% include "modules/employees/templates/employees/portal_partials/attendance_punch_card.html" %}
|
||
|
||
<div class="af-card">
|
||
<h3 class="font-semibold text-slate-900">Today’s Attendance Summary</h3>
|
||
<dl class="mt-4 grid gap-3 text-sm">
|
||
<div class="flex justify-between gap-3"><dt class="text-slate-500">Status</dt><dd class="font-medium text-slate-900">{% if today_attendance %}{{ today_attendance.status.replace('_',' ').title() }}{% else %}Not Marked{% endif %}</dd></div>
|
||
<div class="flex justify-between gap-3"><dt class="text-slate-500">Punch In</dt><dd class="font-medium text-slate-900">{{ today_attendance.punch_in_local_at.strftime('%H:%M') if today_attendance and today_attendance.punch_in_local_at else (today_attendance.punch_in_utc.strftime('%H:%M UTC') if today_attendance and today_attendance.punch_in_utc else '-') }}</dd></div>
|
||
<div class="flex justify-between gap-3"><dt class="text-slate-500">Punch Out</dt><dd class="font-medium text-slate-900">{{ today_attendance.punch_out_local_at.strftime('%H:%M') if today_attendance and today_attendance.punch_out_local_at else (today_attendance.punch_out_utc.strftime('%H:%M UTC') if today_attendance and today_attendance.punch_out_utc else '-') }}</dd></div>
|
||
<div class="flex justify-between gap-3"><dt class="text-slate-500">Duration</dt><dd class="font-medium text-slate-900">{{ (today_attendance.work_duration_minutes ~ ' min') if today_attendance and today_attendance.work_duration_minutes else '-' }}</dd></div>
|
||
</dl>
|
||
<button type="button" data-tab="attendance" class="employee-portal-tab mt-5 inline-flex af-btn af-btn-secondary">View Attendance Details</button>
|
||
</div>
|
||
|
||
<div class="af-card">
|
||
<h3 class="font-semibold text-slate-900">Profile Summary</h3>
|
||
<dl class="mt-4 grid gap-4 text-sm">
|
||
<div><dt class="text-slate-500">Name</dt><dd class="font-medium text-slate-900">{{ employee.full_name }}</dd></div>
|
||
<div><dt class="text-slate-500">Code / Status</dt><dd class="font-medium text-slate-900">{{ employee.employee_code }} · {{ employee.status.replace('_',' ').title() }}</dd></div>
|
||
<div><dt class="text-slate-500">Designation</dt><dd class="font-medium text-slate-900">{{ employee.designation or '-' }}</dd></div>
|
||
</dl>
|
||
<button type="button" data-tab="profile" class="employee-portal-tab mt-5 inline-flex af-btn af-btn-secondary">Update My Profile</button>
|
||
</div>
|
||
</aside>
|
||
</section>
|
||
{% elif pending_request %}
|
||
<div class="rounded-2xl border border-amber-200 bg-amber-50 p-6 text-sm text-amber-900 shadow-soft"><h3 class="font-semibold">Employee profile request is pending</h3><p class="mt-1">Your request #{{ pending_request.id }} is waiting for approval.</p></div>
|
||
{% else %}
|
||
<div class="rounded-2xl border border-amber-200 bg-amber-50 p-6 shadow-soft"><h3 class="font-semibold text-amber-900">Your login is not linked to an employee master</h3><p class="mt-1 text-sm text-amber-900">Submit an employee link request or ask Firm Admin/Partner/Branch Manager to link your user account from Employee Master.</p><a href="/employee/register" class="mt-4 inline-flex rounded-xl bg-amber-700 px-4 py-2 text-sm font-semibold text-white hover:bg-amber-800">Request Employee Link</a></div>
|
||
{% endif %}
|