from __future__ import annotations from dataclasses import dataclass from typing import Iterable @dataclass(frozen=True) class WorkspaceCard: code: str title: str description: str url: str badge: str priority: int def _role_set(roles: Iterable[str] | None) -> set[str]: return {str(role).strip() for role in (roles or []) if str(role).strip()} def _has_employee_portal_access(roles: set[str], permissions: set[str]) -> bool: employee_permissions = { "employees.ess.view", "employees.work.view_self", "employees.attendance.view_self", "employees.leave.view_self", "employees.documents.view_self", "employees.payroll.view_self", } return bool({"Staff", "Employee"}.intersection(roles) or employee_permissions.intersection(permissions)) def build_workspace_cards(roles: Iterable[str] | None, permissions: Iterable[str] | None) -> list[WorkspaceCard]: role_set = _role_set(roles) permission_set = {str(permission).strip() for permission in (permissions or []) if str(permission).strip()} cards: list[WorkspaceCard] = [] if "System Admin" in role_set: cards.append(WorkspaceCard( code="system-admin", title="System Admin", description="Platform control, firms, SMTP, storage, reports and setup health.", url="/system-admin/dashboard", badge="Platform", priority=10, )) if "Firm Admin" in role_set: cards.append(WorkspaceCard( code="firm-admin", title="Firm Administration", description="Firm settings, branches, users, roles, services, FY and setup reports.", url="/firm-admin/dashboard", badge="Firm setup", priority=20, )) if "Partner" in role_set: cards.append(WorkspaceCard( code="partner", title="Partner Operations", description="Branch work, clients, staff workload, review, billing and partner reports.", url="/partner/dashboard", badge="Branch control", priority=30, )) if {"Manager", "Branch Manager"}.intersection(role_set): cards.append(WorkspaceCard( code="manager", title="Manager Workspace", description="Team work, review queue, client pending, documents, escalations and reports.", url="/manager/dashboard", badge="Execution control", priority=40, )) if _has_employee_portal_access(role_set, permission_set): cards.append(WorkspaceCard( code="employee", title="Employee Portal", description="Attendance, my work board, leave, documents, payslips, alerts and my reports.", url="/employee/dashboard", badge="My work", priority=50, )) if "Client" in role_set: cards.append(WorkspaceCard( code="client", title="Client Portal", description="Pending documents, services, billing, messages and client reports.", url="/client/dashboard", badge="Client view", priority=60, )) if "Consultant" in role_set: cards.append(WorkspaceCard( code="consultant", title="Consultant Workspace", description="Assigned work, clients, documents, clarifications, requests and consultant reports.", url="/consultant/dashboard", badge="External work", priority=70, )) # Reports centre is available as a role-aware workspace for every authenticated user. cards.append(WorkspaceCard( code="reports", title="Reports Centre", description="Role-aware reports grouped by work, clients, billing, HR, system and audit areas.", url="/reports", badge="Reports", priority=90, )) return sorted(cards, key=lambda card: card.priority) def current_workspace_code(current_path: str | None) -> str: path = current_path or "" if path.startswith("/system-admin"): return "system-admin" if path.startswith("/firm-admin"): return "firm-admin" if path.startswith("/partner"): return "partner" if path.startswith("/manager"): return "manager" if path.startswith("/employee") or path.startswith("/employees"): return "employee" if path.startswith("/client"): return "client" if path.startswith("/consultant"): return "consultant" if path.startswith("/reports"): return "reports" return ""