chore: standardize security and quality foundations
This commit is contained in:
@@ -1,82 +1,79 @@
|
||||
'use client'
|
||||
"use client";
|
||||
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { canAccess, featureForPath } from '../lib/features'
|
||||
import { useFeatureUser } from './FeatureGate'
|
||||
import { usePathname } from "next/navigation";
|
||||
import { canAccess, featureForPath } from "../lib/features";
|
||||
import { useFeatureUser } from "./FeatureGate";
|
||||
|
||||
export default function HeaderActions() {
|
||||
const pathname = usePathname()
|
||||
const { user, ready } = useFeatureUser()
|
||||
const role = user?.role ?? null
|
||||
const showRequestsNav = canAccess(user, 'new_requests')
|
||||
if (!ready || !user) return null
|
||||
const pathname = usePathname();
|
||||
const { user, ready } = useFeatureUser();
|
||||
const role = user?.role ?? null;
|
||||
const showRequestsNav = canAccess(user, "new_requests");
|
||||
if (!ready || !user) return null;
|
||||
|
||||
const roleItems =
|
||||
role === null
|
||||
? []
|
||||
: role === 'admin'
|
||||
: role === "admin"
|
||||
? [
|
||||
{
|
||||
href: '/profile/invites',
|
||||
label: 'Invites',
|
||||
match: (path: string) => path.startsWith('/profile/invites'),
|
||||
href: "/profile/invites",
|
||||
label: "Invites",
|
||||
match: (path: string) => path.startsWith("/profile/invites"),
|
||||
},
|
||||
{
|
||||
href: '/admin',
|
||||
label: 'Config',
|
||||
match: (path: string) => path.startsWith('/admin') || path.startsWith('/users'),
|
||||
href: "/admin",
|
||||
label: "Config",
|
||||
match: (path: string) => path.startsWith("/admin") || path.startsWith("/users"),
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
href: '/profile/invites',
|
||||
label: 'Invites',
|
||||
match: (path: string) => path.startsWith('/profile/invites'),
|
||||
href: "/profile/invites",
|
||||
label: "Invites",
|
||||
match: (path: string) => path.startsWith("/profile/invites"),
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
const commonItems = [
|
||||
...(showRequestsNav
|
||||
? [
|
||||
{
|
||||
href: '/new-requests',
|
||||
label: 'New Requests',
|
||||
match: (path: string) => path === '/new-requests',
|
||||
href: "/new-requests",
|
||||
label: "New Requests",
|
||||
match: (path: string) => path === "/new-requests",
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
href: '/',
|
||||
label: 'My Requests',
|
||||
match: (path: string) => path === '/' || path.startsWith('/requests/'),
|
||||
href: "/",
|
||||
label: "My Requests",
|
||||
match: (path: string) => path === "/" || path.startsWith("/requests/"),
|
||||
},
|
||||
{
|
||||
href: '/insights',
|
||||
label: 'My Stats',
|
||||
match: (path: string) => path === '/insights' || path.startsWith('/insights/'),
|
||||
href: "/insights",
|
||||
label: "My Stats",
|
||||
match: (path: string) => path === "/insights" || path.startsWith("/insights/"),
|
||||
},
|
||||
{
|
||||
href: '/portal/issues',
|
||||
label: 'Issues',
|
||||
match: (path: string) => path === '/portal/issues' || path === '/admin/issues',
|
||||
href: "/portal/issues",
|
||||
label: "Issues",
|
||||
match: (path: string) => path === "/portal/issues" || path === "/admin/issues",
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
const items = [
|
||||
...commonItems,
|
||||
...roleItems,
|
||||
].filter((item) => canAccess(user, featureForPath(item.href)))
|
||||
const items = [...commonItems, ...roleItems].filter((item) => canAccess(user, featureForPath(item.href)));
|
||||
|
||||
return (
|
||||
<nav className="header-actions" aria-label="Primary">
|
||||
{items.map((item) => {
|
||||
const active = item.match(pathname)
|
||||
const active = item.match(pathname);
|
||||
return (
|
||||
<a key={item.href} href={item.href} className={active ? 'is-active' : undefined}>
|
||||
<a key={item.href} href={item.href} className={active ? "is-active" : undefined}>
|
||||
{item.label}
|
||||
</a>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user