diff --git a/app/modules/workspace_navigation/__init__.py b/app/modules/workspace_navigation/__init__.py
new file mode 100644
index 0000000..4d6f851
--- /dev/null
+++ b/app/modules/workspace_navigation/__init__.py
@@ -0,0 +1 @@
+"""Workspace navigation module."""
diff --git a/app/modules/workspace_navigation/service.py b/app/modules/workspace_navigation/service.py
new file mode 100644
index 0000000..627ca7a
--- /dev/null
+++ b/app/modules/workspace_navigation/service.py
@@ -0,0 +1,139 @@
+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 ""
diff --git a/app/modules/workspace_navigation/templates/workspace_navigation/index.html b/app/modules/workspace_navigation/templates/workspace_navigation/index.html
new file mode 100644
index 0000000..bdda384
--- /dev/null
+++ b/app/modules/workspace_navigation/templates/workspace_navigation/index.html
@@ -0,0 +1,34 @@
+{% extends "ui/templates/base/layout.html" %}
+
+{% block content %}
+ Navigation Centre Open the workspace allowed for your role. This page does not replace any existing module; it only gives a clean entry point to dashboards and reports. {{ card.description }} Current workspaceMy Workspaces
+ {{ card.title }}
+