diff --git a/app/dashboard/admin/layout.tsx b/app/dashboard/admin/layout.tsx
index f0d17f5..a181e2e 100644
--- a/app/dashboard/admin/layout.tsx
+++ b/app/dashboard/admin/layout.tsx
@@ -1,39 +1,24 @@
"use client"
import type React from "react"
-import { useEffect } from "react"
-import { Loader2 } from "lucide-react"
-import { useRouter } from "next/navigation"
import { AdminShell } from "@/components/dashboard/admin/admin-shell"
+import { DashboardGuard } from "@/components/dashboard/dashboard-guard"
import { useAuth } from "@/hooks/use-auth"
-export default function AdminLayout({ children }: { children: React.ReactNode }) {
- const { user: authUser, loading: authLoading } = useAuth()
- const router = useRouter()
-
- useEffect(() => {
- if (!authLoading && (!authUser || authUser.role !== "admin")) {
- router.replace("/signin")
- }
- }, [authLoading, authUser, router])
-
- if (authLoading || !authUser) {
- return (
-
+ {dashboardRole ? (
+
+ ) : null}
+
{
+ const session = await getSessionFromCookies()
+ if (!session?.userId) {
+ redirect("/signin")
+ }
+
+ if (allow) {
+ const allowedRoles = Array.isArray(allow) ? allow : [allow]
+ if (!isDashboardRole(session.role) || !allowedRoles.includes(session.role)) {
+ redirect(getDashboardHomePath(session.role))
+ }
+ }
+
+ return session
+}
diff --git a/lib/dashboard/roles.ts b/lib/dashboard/roles.ts
new file mode 100644
index 0000000..65432e8
--- /dev/null
+++ b/lib/dashboard/roles.ts
@@ -0,0 +1,83 @@
+import type { ComponentType } from "react"
+import { Compass, FileText, PlusCircle, Receipt, ShieldCheck, Wallet } from "lucide-react"
+
+type DashboardIcon = ComponentType<{ className?: string }>
+
+/**
+ * Central source of truth for the role-aware dashboard shell.
+ *
+ * Sidebar navigation, header role badges, quick actions and route guards all
+ * derive their behaviour from this module so new dashboard modules can be added
+ * for a role without duplicating layout or authorization logic.
+ */
+export type DashboardRole = "driver" | "investor" | "admin"
+
+export const DASHBOARD_ROLES: DashboardRole[] = ["driver", "investor", "admin"]
+
+export interface DashboardQuickAction {
+ label: string
+ href: string
+ icon: DashboardIcon
+ /** Highlights the primary call to action for the role. */
+ primary?: boolean
+}
+
+export interface DashboardRoleConfig {
+ role: DashboardRole
+ /** Short label used in badges and headings. */
+ label: string
+ /** Landing route a member of this role is sent to. */
+ homePath: string
+ /** Quick action slots rendered in the dashboard header for the role. */
+ quickActions: DashboardQuickAction[]
+}
+
+export const DASHBOARD_ROLE_CONFIG: Record = {
+ investor: {
+ role: "investor",
+ label: "Investor",
+ homePath: "/dashboard/investor",
+ quickActions: [
+ { label: "Fund Wallet", href: "/dashboard/investor/wallet", icon: PlusCircle, primary: true },
+ { label: "Explore Opportunities", href: "/dashboard/investor/opportunities", icon: Compass },
+ ],
+ },
+ driver: {
+ role: "driver",
+ label: "Driver",
+ homePath: "/dashboard/driver",
+ quickActions: [
+ { label: "Make Payment", href: "/dashboard/driver/repayment", icon: Wallet, primary: true },
+ { label: "Payment History", href: "/dashboard/driver/payments", icon: Receipt },
+ ],
+ },
+ admin: {
+ role: "admin",
+ label: "Admin",
+ homePath: "/dashboard/admin",
+ quickActions: [
+ { label: "Review KYC", href: "/dashboard/admin/kyc-management", icon: ShieldCheck, primary: true },
+ { label: "Reports", href: "/dashboard/admin/reports", icon: FileText },
+ ],
+ },
+}
+
+/** Type guard that narrows an arbitrary value to a known {@link DashboardRole}. */
+export function isDashboardRole(value: unknown): value is DashboardRole {
+ return typeof value === "string" && (DASHBOARD_ROLES as string[]).includes(value)
+}
+
+/** Returns the config for a role, or `null` when the value is not a dashboard role. */
+export function getDashboardRoleConfig(value: unknown): DashboardRoleConfig | null {
+ return isDashboardRole(value) ? DASHBOARD_ROLE_CONFIG[value] : null
+}
+
+/** Normalizes the list of roles allowed to view a section into an array. */
+export function resolveAllowedRoles(allow: DashboardRole | DashboardRole[]): DashboardRole[] {
+ return Array.isArray(allow) ? allow : [allow]
+}
+
+/** Resolves the home path for a role, falling back to the generic dashboard root. */
+export function getDashboardHomePath(value: unknown): string {
+ return getDashboardRoleConfig(value)?.homePath ?? "/dashboard"
+}