94 lines
2.4 KiB
TypeScript
94 lines
2.4 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
import { usePathname } from 'next/navigation'
|
|
import { authFetch, clearToken, getApiBase, getToken } from '../lib/auth'
|
|
|
|
export default function HeaderActions() {
|
|
const [signedIn, setSignedIn] = useState(false)
|
|
const [role, setRole] = useState<string | null>(null)
|
|
const pathname = usePathname()
|
|
|
|
useEffect(() => {
|
|
const token = getToken()
|
|
setSignedIn(Boolean(token))
|
|
if (!token) {
|
|
return
|
|
}
|
|
const load = async () => {
|
|
try {
|
|
const baseUrl = getApiBase()
|
|
const response = await authFetch(`${baseUrl}/auth/me`)
|
|
if (!response.ok) {
|
|
clearToken()
|
|
setSignedIn(false)
|
|
setRole(null)
|
|
return
|
|
}
|
|
const data = await response.json()
|
|
setRole(data?.role ?? null)
|
|
} catch (err) {
|
|
console.error(err)
|
|
}
|
|
}
|
|
void load()
|
|
}, [])
|
|
|
|
if (!signedIn) {
|
|
return null
|
|
}
|
|
|
|
const roleItems =
|
|
role === null
|
|
? []
|
|
: role === 'admin'
|
|
? [
|
|
{
|
|
href: '/admin',
|
|
label: 'Config',
|
|
match: (path: string) => path.startsWith('/admin'),
|
|
},
|
|
]
|
|
: [
|
|
{
|
|
href: '/profile',
|
|
label: 'Profile',
|
|
match: (path: string) => path.startsWith('/profile') && !path.startsWith('/profile/invites'),
|
|
},
|
|
{
|
|
href: '/profile/invites',
|
|
label: 'Invites',
|
|
match: (path: string) => path.startsWith('/profile/invites'),
|
|
},
|
|
]
|
|
|
|
const items = [
|
|
{ href: '/', label: 'Health', match: (path: string) => path === '/' },
|
|
{
|
|
href: '/portal/requests',
|
|
label: 'Requests',
|
|
match: (path: string) => path === '/portal/requests' || path.startsWith('/requests/'),
|
|
},
|
|
{
|
|
href: '/portal/issues',
|
|
label: 'Issues',
|
|
match: (path: string) => path === '/portal/issues' || path === '/admin/issues',
|
|
},
|
|
...roleItems,
|
|
]
|
|
|
|
return (
|
|
<nav className="header-actions" aria-label="Primary">
|
|
{items.map((item, index) => {
|
|
const active = item.match(pathname)
|
|
return (
|
|
<a key={item.href} href={item.href} className={active ? 'is-active' : undefined}>
|
|
<span aria-hidden="true">{String(index + 1).padStart(2, '0')}</span>
|
|
{item.label}
|
|
</a>
|
|
)
|
|
})}
|
|
</nav>
|
|
)
|
|
}
|