Add firm admin dashboard and workspace switcher
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
{% extends "ui/templates/base/layout.html" %}
|
||||
{% block content %}
|
||||
<section class="space-y-6">
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-6 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-600">Firm Setup Control Centre</p>
|
||||
<h1 class="mt-2 text-2xl font-bold text-slate-900">Firm Administration Dashboard</h1>
|
||||
<p class="mt-1 text-sm text-slate-500">Configure firm details, branches, users, roles, services, task templates, financial years, branding and billing readiness.</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<a href="/system-settings/branches" class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white shadow-soft hover:bg-brand-700">+ Add Branch</a>
|
||||
<a href="/system-settings/users" class="rounded-xl border border-slate-200 px-4 py-2 text-sm font-semibold text-slate-700 hover:bg-slate-50">Users & Roles</a>
|
||||
{% if 'Partner' in current_user_roles %}<a href="/partner/dashboard" class="rounded-xl border border-brand-200 bg-brand-50 px-4 py-2 text-sm font-semibold text-brand-700 hover:bg-brand-100">Partner Operations</a>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% set tabs = [
|
||||
('overview','Overview'),
|
||||
('branches','Branches'),
|
||||
('users','Users & Roles'),
|
||||
('firm-settings','Firm Settings'),
|
||||
('services','Services Setup'),
|
||||
('financial-years','Financial Years'),
|
||||
('reports','Reports'),
|
||||
('wizards','Wizards'),
|
||||
('audit-logs','Audit Logs')
|
||||
] %}
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-2 shadow-soft">
|
||||
<div class="flex gap-2 overflow-x-auto" id="firm-admin-tabs">
|
||||
{% for code, label in tabs %}
|
||||
<button type="button" data-tab="{{ code }}" class="firm-admin-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>
|
||||
</div>
|
||||
|
||||
<div id="firm-admin-panel" class="min-h-[24rem]">
|
||||
{% include "modules/firm_admin_dashboard/templates/firm_admin_dashboard/partials/" ~ active_tab ~ ".html" ignore missing %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
const panel = document.getElementById('firm-admin-panel');
|
||||
const buttons = Array.from(document.querySelectorAll('.firm-admin-tab'));
|
||||
if (!panel || !buttons.length) return;
|
||||
function activate(tab){
|
||||
buttons.forEach(btn => {
|
||||
const on = btn.dataset.tab === tab;
|
||||
btn.classList.toggle('bg-brand-600', on);
|
||||
btn.classList.toggle('text-white', on);
|
||||
btn.classList.toggle('text-slate-600', !on);
|
||||
btn.classList.toggle('hover:bg-slate-100', !on);
|
||||
});
|
||||
}
|
||||
async function loadTab(tab){
|
||||
activate(tab);
|
||||
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('/firm-admin/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.toString());
|
||||
} catch (err) {
|
||||
panel.innerHTML = '<div class="rounded-3xl border border-red-200 bg-red-50 p-6 text-sm font-semibold text-red-800 shadow-soft">Unable to load tab. Please refresh the page.</div>';
|
||||
}
|
||||
}
|
||||
buttons.forEach(btn => btn.addEventListener('click', () => loadTab(btn.dataset.tab)));
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
|
||||
<div class="flex flex-col gap-3 border-b border-slate-100 p-5 md:flex-row md:items-center md:justify-between">
|
||||
<div><h2 class="text-lg font-bold text-slate-900">Recent Audit Logs</h2><p class="text-sm text-slate-500">Latest firm-level activity, if audit log model is available.</p></div>
|
||||
<a href="/system-settings/audit-logs" class="rounded-xl border border-slate-200 px-4 py-2 text-sm font-semibold text-slate-700 hover:bg-slate-50">Open Audit Logs</a>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-slate-100 text-sm">
|
||||
<thead class="bg-slate-50 text-left text-xs font-semibold uppercase tracking-wide text-slate-500"><tr><th class="px-5 py-3">Time</th><th class="px-5 py-3">User</th><th class="px-5 py-3">Action</th><th class="px-5 py-3">Entity</th><th class="px-5 py-3">Status</th></tr></thead>
|
||||
<tbody class="divide-y divide-slate-100">
|
||||
{% for log in audit_logs %}
|
||||
<tr class="hover:bg-slate-50"><td class="px-5 py-3">{{ log.created_at_utc }}</td><td class="px-5 py-3">{{ log.actor_email or '-' }}</td><td class="px-5 py-3 font-semibold text-slate-900">{{ log.action }}</td><td class="px-5 py-3">{{ log.entity_type }}{% if log.entity_name %} > {{ log.entity_name }}{% endif %}</td><td class="px-5 py-3">{{ log.status or '-' }}</td></tr>
|
||||
{% else %}
|
||||
<tr><td colspan="5" class="px-5 py-8 text-center text-slate-500">No audit logs found or audit model is not available.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
|
||||
<div class="flex flex-col gap-3 border-b border-slate-100 p-5 md:flex-row md:items-center md:justify-between">
|
||||
<div><h2 class="text-lg font-bold text-slate-900">Branches</h2><p class="text-sm text-slate-500">Create branches and assign partner/users for each branch.</p></div>
|
||||
<a href="/system-settings/branches" class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white hover:bg-brand-700">Manage Branches</a>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-slate-100 text-sm">
|
||||
<thead class="bg-slate-50 text-left text-xs font-semibold uppercase tracking-wide text-slate-500"><tr><th class="px-5 py-3">Branch</th><th class="px-5 py-3">Status</th><th class="px-5 py-3 text-right">Partners</th><th class="px-5 py-3 text-right">Users</th><th class="px-5 py-3 text-right">Clients</th><th class="px-5 py-3">Login / Assignment</th><th class="px-5 py-3">Storage / SMTP</th></tr></thead>
|
||||
<tbody class="divide-y divide-slate-100">
|
||||
{% for branch in branches %}
|
||||
<tr class="hover:bg-slate-50">
|
||||
<td class="px-5 py-3"><div class="font-semibold text-slate-900">{{ branch.name }}</div><div class="text-xs text-slate-500">{{ branch.code }}{% if branch.is_head_office %} > Head Office{% endif %}</div></td>
|
||||
<td class="px-5 py-3"><span class="rounded-full px-2.5 py-1 text-xs font-semibold {% if branch.is_active %}bg-emerald-50 text-emerald-700{% else %}bg-slate-100 text-slate-600{% endif %}">{% if branch.is_active %}Active{% else %}Inactive{% endif %}</span></td>
|
||||
<td class="px-5 py-3 text-right font-semibold {% if branch.partner_count %}text-slate-900{% else %}text-amber-700{% endif %}">{{ branch.partner_count }}</td>
|
||||
<td class="px-5 py-3 text-right font-semibold">{{ branch.user_count }}</td>
|
||||
<td class="px-5 py-3 text-right font-semibold">{{ branch.client_count }}</td>
|
||||
<td class="px-5 py-3 text-xs text-slate-600">Login: {{ 'Allowed' if branch.allow_login else 'Blocked' }}<br>Assignments: {{ 'Allowed' if branch.allow_new_assignments else 'Blocked' }}</td>
|
||||
<td class="px-5 py-3 text-xs text-slate-600">Storage: {{ branch.local_storage_path or 'Not set' }}<br>SMTP: {{ 'Configured' if branch.smtp_configured else 'Pending' }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="7" class="px-5 py-8 text-center text-slate-500">No branches found. Create the first branch from System Settings.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
|
||||
<div class="flex flex-col gap-3 border-b border-slate-100 p-5 md:flex-row md:items-center md:justify-between">
|
||||
<div><h2 class="text-lg font-bold text-slate-900">Financial Years</h2><p class="text-sm text-slate-500">Create, mark current, lock and manage financial years from existing FY settings.</p></div>
|
||||
<a href="/system-settings/financial-years" class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white hover:bg-brand-700">Manage FY</a>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-slate-100 text-sm">
|
||||
<thead class="bg-slate-50 text-left text-xs font-semibold uppercase tracking-wide text-slate-500"><tr><th class="px-5 py-3">FY</th><th class="px-5 py-3">AY</th><th class="px-5 py-3">Period</th><th class="px-5 py-3">Current</th><th class="px-5 py-3">Lock Status</th></tr></thead>
|
||||
<tbody class="divide-y divide-slate-100">
|
||||
{% for fy in financial_years %}
|
||||
<tr class="hover:bg-slate-50"><td class="px-5 py-3 font-semibold text-slate-900">{{ fy.year_code }}</td><td class="px-5 py-3">{{ fy.assessment_year }}</td><td class="px-5 py-3 text-slate-600">{{ fy.start_date }} to {{ fy.end_date }}</td><td class="px-5 py-3">{% if fy.is_current %}<span class="rounded-full bg-emerald-50 px-2 py-1 text-xs font-semibold text-emerald-700">Current</span>{% else %}<span class="text-slate-400">-</span>{% endif %}</td><td class="px-5 py-3">{% if fy.is_locked %}<span class="rounded-full bg-slate-100 px-2 py-1 text-xs font-semibold text-slate-700">Locked</span>{% else %}<span class="rounded-full bg-amber-50 px-2 py-1 text-xs font-semibold text-amber-700">Open</span>{% endif %}</td></tr>
|
||||
{% else %}
|
||||
<tr><td colspan="5" class="px-5 py-8 text-center text-slate-500">No financial years created yet.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
<div class="space-y-6">
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-6 shadow-soft">
|
||||
<h2 class="text-lg font-bold text-slate-900">Firm Settings Readiness</h2>
|
||||
<p class="mt-1 text-sm text-slate-500">This tab gives shortcuts to existing firm setup pages. No duplicate settings are created here.</p>
|
||||
</div>
|
||||
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||
<a href="/system-settings" class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft hover:border-brand-200"><div class="font-bold text-slate-900">System Settings</div><p class="mt-1 text-sm text-slate-500">Firm, branch and year configuration dashboard.</p></a>
|
||||
<a href="/system-settings/branding" class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft hover:border-brand-200"><div class="font-bold text-slate-900">Branding Settings</div><p class="mt-1 text-sm text-slate-500">Logo, favicon, colours, contact and display name.</p></a>
|
||||
<a href="/email/settings" class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft hover:border-brand-200"><div class="font-bold text-slate-900">Email Settings</div><p class="mt-1 text-sm text-slate-500">Branch/firm SMTP and email sender settings.</p></a>
|
||||
<a href="/billing/settings" class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft hover:border-brand-200"><div class="font-bold text-slate-900">Billing Settings</div><p class="mt-1 text-sm text-slate-500">Invoice series, GST, bank and payment settings.</p></a>
|
||||
<a href="/documents/storage-nodes" class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft hover:border-brand-200"><div class="font-bold text-slate-900">Local Storage Agent</div><p class="mt-1 text-sm text-slate-500">Branch storage node readiness.</p></a>
|
||||
<a href="/system-settings/audit-logs" class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft hover:border-brand-200"><div class="font-bold text-slate-900">Audit Logs</div><p class="mt-1 text-sm text-slate-500">Firm setup and security audit trail.</p></a>
|
||||
</div>
|
||||
</div>
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<div class="space-y-6">
|
||||
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Setup Score</div><div class="mt-2 text-3xl font-bold {% if overview.setup_percent >= 80 %}text-emerald-700{% else %}text-amber-700{% endif %}">{{ overview.setup_score }}/{{ overview.setup_total }}</div><div class="text-xs text-slate-500">{{ overview.setup_percent }}% firm setup readiness</div></div>
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Branches</div><div class="mt-2 text-3xl font-bold text-slate-900">{{ overview.branch_count }}</div><div class="text-xs text-slate-500">{{ overview.active_branch_count }} active</div></div>
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Users</div><div class="mt-2 text-3xl font-bold text-slate-900">{{ overview.user_count }}</div><div class="text-xs text-slate-500">{{ overview.firm_admin_count }} firm admin / {{ overview.partner_count }} partner</div></div>
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Services Enabled</div><div class="mt-2 text-3xl font-bold text-slate-900">{{ overview.enabled_service_count }}</div><div class="text-xs {% if overview.services_without_templates %}text-amber-700{% else %}text-slate-500{% endif %}">{{ overview.services_without_templates }} without task templates</div></div>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Clients</div><div class="mt-2 text-2xl font-bold">{{ overview.client_count }}</div><div class="text-xs text-slate-500">Active client master</div></div>
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Current FY</div><div class="mt-2 text-2xl font-bold {% if overview.current_fy %}text-emerald-700{% else %}text-amber-700{% endif %}">{{ overview.current_fy.year_code if overview.current_fy else 'Not Set' }}</div><div class="text-xs text-slate-500">{{ overview.fy_count }} financial year(s)</div></div>
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Branding</div><div class="mt-2 text-2xl font-bold {% if overview.branding_ready %}text-emerald-700{% else %}text-amber-700{% endif %}">{% if overview.branding_ready %}Started{% else %}Pending{% endif %}</div><div class="text-xs text-slate-500">Logo/contact/colours</div></div>
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Billing Settings</div><div class="mt-2 text-2xl font-bold {% if overview.billing_settings_count %}text-emerald-700{% else %}text-amber-700{% endif %}">{{ overview.billing_settings_count }}</div><div class="text-xs text-slate-500">Configured rows</div></div>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-6 xl:grid-cols-[minmax(0,1fr)_360px]">
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft">
|
||||
<h2 class="text-lg font-bold text-slate-900">Setup Checklist</h2>
|
||||
<p class="mt-1 text-sm text-slate-500">Firm Admin should complete these items before branch operations start.</p>
|
||||
<div class="mt-4 grid gap-3 md:grid-cols-2">
|
||||
{% for item in setup_checks %}
|
||||
<a href="/firm-admin/dashboard?tab={% if item.key == 'branches' or item.key == 'partners' %}branches{% elif item.key == 'firm_admin' %}users{% elif item.key == 'services' or item.key == 'templates' %}services{% elif item.key == 'fy' %}financial-years{% else %}firm-settings{% endif %}" class="rounded-2xl border p-4 {% if item.ok %}border-emerald-100 bg-emerald-50{% else %}border-amber-100 bg-amber-50{% endif %}">
|
||||
<div class="flex items-center justify-between gap-3"><span class="font-semibold {% if item.ok %}text-emerald-900{% else %}text-amber-900{% endif %}">{{ item.label }}</span><span class="rounded-full bg-white px-2 py-1 text-xs font-bold {% if item.ok %}text-emerald-700{% else %}text-amber-700{% endif %}">{% if item.ok %}Done{% else %}Pending{% endif %}</span></div>
|
||||
<div class="mt-1 text-xs {% if item.ok %}text-emerald-700{% else %}text-amber-700{% endif %}">{{ item.detail }}</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft">
|
||||
<h2 class="text-lg font-bold text-slate-900">Quick Actions</h2>
|
||||
<div class="mt-4 space-y-3">
|
||||
<a href="/system-settings/branches" class="block rounded-2xl bg-brand-600 px-4 py-3 text-sm font-semibold text-white hover:bg-brand-700">+ Add / Manage Branches</a>
|
||||
<a href="/system-settings/users" class="block rounded-2xl border border-slate-200 px-4 py-3 text-sm font-semibold text-slate-700 hover:bg-slate-50">Invite Users & Assign Roles</a>
|
||||
<a href="/system-settings/branding" class="block rounded-2xl border border-slate-200 px-4 py-3 text-sm font-semibold text-slate-700 hover:bg-slate-50">Firm Branding</a>
|
||||
<a href="/services" class="block rounded-2xl border border-slate-200 px-4 py-3 text-sm font-semibold text-slate-700 hover:bg-slate-50">Select Services</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,13 @@
|
||||
<div class="space-y-6">
|
||||
{% set groups = reports|groupby('group') %}
|
||||
{% for group, items in groups %}
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft">
|
||||
<h2 class="text-lg font-bold text-slate-900">{{ group }}</h2>
|
||||
<div class="mt-4 grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||
{% for report in items %}
|
||||
<a href="{{ report.href }}" class="rounded-2xl border border-slate-200 p-4 hover:border-brand-200 hover:bg-brand-50/40"><div class="font-semibold text-slate-900">{{ report.title }}</div><p class="mt-1 text-sm text-slate-500">{{ report.desc }}</p><div class="mt-3 text-xs font-semibold text-brand-700">View report</div></a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<div class="space-y-6">
|
||||
<div class="grid gap-4 md:grid-cols-3">
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Enabled Services</div><div class="mt-2 text-2xl font-bold">{{ overview.enabled_service_count }}</div></div>
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Missing Templates</div><div class="mt-2 text-2xl font-bold {% if overview.services_without_templates %}text-amber-700{% else %}text-emerald-700{% endif %}">{{ overview.services_without_templates }}</div></div>
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase text-slate-500">Action</div><div class="mt-3"><a href="/services" class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white hover:bg-brand-700">Open Firm Services</a></div></div>
|
||||
</div>
|
||||
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
|
||||
<div class="border-b border-slate-100 p-5"><h2 class="text-lg font-bold text-slate-900">Services Setup</h2><p class="text-sm text-slate-500">Enabled services and firm task template readiness.</p></div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-slate-100 text-sm">
|
||||
<thead class="bg-slate-50 text-left text-xs font-semibold uppercase tracking-wide text-slate-500"><tr><th class="px-5 py-3">Service</th><th class="px-5 py-3">Category</th><th class="px-5 py-3">Recurrence</th><th class="px-5 py-3 text-right">Task Templates</th><th class="px-5 py-3">Status</th></tr></thead>
|
||||
<tbody class="divide-y divide-slate-100">
|
||||
{% for service in services %}
|
||||
<tr class="hover:bg-slate-50"><td class="px-5 py-3"><div class="font-semibold text-slate-900">{{ service.service_name }}</div><div class="text-xs text-slate-500">{{ service.service_code }}</div></td><td class="px-5 py-3">{{ service.category }}</td><td class="px-5 py-3">{{ service.recurrence_type }}</td><td class="px-5 py-3 text-right font-semibold">{{ service.template_count }}</td><td class="px-5 py-3"><span class="rounded-full px-2 py-1 text-xs font-semibold {% if service.ready %}bg-emerald-50 text-emerald-700{% else %}bg-amber-50 text-amber-700{% endif %}">{% if service.ready %}Ready{% else %}Template Pending{% endif %}</span></td></tr>
|
||||
{% else %}
|
||||
<tr><td colspan="5" class="px-5 py-8 text-center text-slate-500">No firm services selected yet.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,24 @@
|
||||
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
|
||||
<div class="flex flex-col gap-3 border-b border-slate-100 p-5 md:flex-row md:items-center md:justify-between">
|
||||
<div><h2 class="text-lg font-bold text-slate-900">Users & Roles</h2><p class="text-sm text-slate-500">Firm Admin controls user invitations, branch mapping and role mapping.</p></div>
|
||||
<a href="/system-settings/users" class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white hover:bg-brand-700">Manage Users</a>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-slate-100 text-sm">
|
||||
<thead class="bg-slate-50 text-left text-xs font-semibold uppercase tracking-wide text-slate-500"><tr><th class="px-5 py-3">User</th><th class="px-5 py-3">Roles</th><th class="px-5 py-3">Login Status</th><th class="px-5 py-3">Designation</th><th class="px-5 py-3">Mobile</th></tr></thead>
|
||||
<tbody class="divide-y divide-slate-100">
|
||||
{% for user in users %}
|
||||
<tr class="hover:bg-slate-50">
|
||||
<td class="px-5 py-3"><div class="font-semibold text-slate-900">{{ user.name }}</div><div class="text-xs text-slate-500">{{ user.email }}</div></td>
|
||||
<td class="px-5 py-3"><div class="flex flex-wrap gap-1">{% for role in user.roles %}<span class="rounded-full bg-slate-100 px-2 py-1 text-xs font-semibold text-slate-700">{{ role }}</span>{% else %}<span class="text-xs text-amber-700">No role</span>{% endfor %}</div></td>
|
||||
<td class="px-5 py-3 text-xs"><span class="rounded-full px-2 py-1 font-semibold {% if user.is_active and user.allow_login and not user.is_locked %}bg-emerald-50 text-emerald-700{% else %}bg-red-50 text-red-700{% endif %}">{% if user.is_locked %}Locked{% elif not user.is_active %}Inactive{% elif not user.allow_login %}Login Blocked{% else %}Active{% endif %}</span>{% if user.must_change_password %}<div class="mt-1 font-semibold text-amber-700">Invite/password pending</div>{% endif %}</td>
|
||||
<td class="px-5 py-3 text-slate-600">{{ user.designation or '-' }}</td>
|
||||
<td class="px-5 py-3 text-slate-600">{{ user.mobile or '-' }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="5" class="px-5 py-8 text-center text-slate-500">No users found.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft">
|
||||
<h2 class="text-lg font-bold text-slate-900">Firm Admin Wizards & Setup Shortcuts</h2>
|
||||
<p class="mt-1 text-sm text-slate-500">These cards link to existing setup screens. They do not duplicate existing features.</p>
|
||||
<div class="mt-5 grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||
{% for wizard in wizards %}
|
||||
<a href="{{ wizard.href }}" class="rounded-2xl border border-slate-200 p-4 hover:border-brand-200 hover:bg-brand-50/40"><div class="font-semibold text-slate-900">{{ wizard.title }}</div><p class="mt-1 text-sm text-slate-500">{{ wizard.desc }}</p><div class="mt-3 text-xs font-semibold text-brand-700">Open</div></a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user