HR-ATS-Portal/frontend/src/app/Sidebar.jsx

90 lines
3.1 KiB
JavaScript

import { NavLink } from 'react-router-dom'
import { NAV_GROUPS, ROUTES } from './routes'
import { useAuth } from '../auth/AuthContext'
import { HIRING_MANAGER_NAV, isHiringManager } from '../auth/permissions'
import Icon from '../ui/icons'
import { BrandGlyph } from '../components/BrandMark'
export default function Sidebar({ collapsed, mobileOpen, onToggleCollapse, badges }) {
const { can, user } = useAuth()
// A group heading renders only if something under it survived the permission
// filter — otherwise a low-privilege user sees orphaned section labels.
const visible = ROUTES.filter((r) => {
if (r.hidden) return false
if (!can(r.permission)) return false
if (isHiringManager(user) && !HIRING_MANAGER_NAV.has(r.path)) return false
return true
})
return (
<aside
className={`sidebar${collapsed ? ' collapsed' : ''}${mobileOpen ? ' mobile-open' : ''}`}
id="sidebar"
>
<div className="sidebar-brand">
<div className="brand-logo">
<BrandGlyph />
</div>
<div className="brand-text">
<span className="brand-name">TalentFlow</span>
<span className="brand-sub">Utopia Brands · ATS</span>
</div>
<button
className="sidebar-collapse-btn"
onClick={onToggleCollapse}
title={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
>
<Icon name="chevron-left" />
</button>
</div>
<nav className="sidebar-nav" aria-label="Primary">
{NAV_GROUPS.map((group) => {
const items = visible.filter((r) => r.group === group)
if (!items.length) return null
return (
<div key={group}>
<div className="nav-section-label">{group}</div>
{items.map((r) => {
const count = r.badge ? badges?.[r.badge] : null
return (
<NavLink
key={r.path}
to={`/${r.path}`}
className={({ isActive }) => `nav-item${isActive ? ' active' : ''}`}
>
<Icon name={r.icon} />
<span>{r.title}</span>
{r.tag && <span className="nav-badge nav-badge-ai">{r.tag}</span>}
{count ? (
<span
className={`nav-badge${r.badge === 'inbox' || r.badge === 'notifications' ? ' nav-badge-alert' : ''}`}
>
{count}
</span>
) : null}
</NavLink>
)
})}
</div>
)
})}
</nav>
<div className="sidebar-footer">
<div className="usage-card">
<div className="usage-top">
<span>Seats used</span>
<span>14 / 20</span>
</div>
<div className="usage-bar">
<div className="usage-fill" style={{ width: '70%' }} />
</div>
</div>
</div>
</aside>
)
}