feat : Initial commit
This commit is contained in:
150
nest-intra/src/components/layout/IntranetLayout.tsx
Normal file
150
nest-intra/src/components/layout/IntranetLayout.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
import { NavLink, Outlet, useNavigate } from 'react-router-dom';
|
||||
import { useAuth } from '../../contexts/AuthContext';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
const INTRANET_LINKS = [
|
||||
{ to: '/intranet', label: 'Dashboard', icon: '[>]', end: true },
|
||||
{ to: '/intranet/bugs', label: 'Bug Reports', icon: '[!]', end: false },
|
||||
{ to: '/intranet/feed', label: 'Team Feed', icon: '[~]', end: false },
|
||||
{ to: '/intranet/events', label: 'Events', icon: '[E]', end: false },
|
||||
{ to: '/intranet/users', label: 'Users', icon: '[U]', end: false },
|
||||
{ to: '/intranet/moderation', label: 'Moderation', icon: '[M]', end: false },
|
||||
];
|
||||
|
||||
export function IntranetLayout() {
|
||||
const { user, logout } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleLogout = useCallback(() => {
|
||||
logout();
|
||||
navigate('/');
|
||||
}, [logout, navigate]);
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', minHeight: '100vh', background: 'var(--color-bg)' }}>
|
||||
{/* Sidebar */}
|
||||
<aside
|
||||
style={{
|
||||
width: '220px',
|
||||
flexShrink: 0,
|
||||
background: 'var(--color-bg-alt)',
|
||||
borderRight: '2px solid var(--color-border)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: '1.5rem 0',
|
||||
}}
|
||||
>
|
||||
{/* Logo */}
|
||||
<div style={{ padding: '0 1.25rem 1.25rem', borderBottom: '1px solid var(--color-border)' }}>
|
||||
<div
|
||||
style={{
|
||||
fontFamily: 'var(--font-heading)',
|
||||
color: 'var(--color-yellow)',
|
||||
fontSize: '1.3rem',
|
||||
letterSpacing: '0.08em',
|
||||
}}
|
||||
>
|
||||
INTRANET
|
||||
</div>
|
||||
<div style={{ fontFamily: 'var(--font-mono)', color: 'var(--color-text-muted)', fontSize: '0.62rem', marginTop: '2px' }}>
|
||||
CROWMATE STUDIO
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Nav links */}
|
||||
<nav style={{ flex: 1, padding: '0.75rem 0' }}>
|
||||
{INTRANET_LINKS.map(({ to, label, icon, end }) => (
|
||||
<NavLink
|
||||
key={to}
|
||||
to={to}
|
||||
end={end}
|
||||
style={({ isActive }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.6rem',
|
||||
padding: '0.55rem 1.25rem',
|
||||
fontFamily: 'var(--font-mono)',
|
||||
fontSize: '0.78rem',
|
||||
color: isActive ? 'var(--color-yellow)' : 'var(--color-text-muted)',
|
||||
background: isActive ? 'rgba(37,99,235,0.08)' : 'transparent',
|
||||
borderLeft: isActive ? '3px solid var(--color-yellow)' : '3px solid transparent',
|
||||
textDecoration: 'none',
|
||||
transition: 'color 0.1s, background 0.1s',
|
||||
letterSpacing: '0.05em',
|
||||
})}
|
||||
>
|
||||
<span style={{ opacity: 0.6, fontSize: '0.68rem' }}>{icon}</span>
|
||||
{label}
|
||||
</NavLink>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* User info */}
|
||||
<div
|
||||
style={{
|
||||
padding: '1rem 1.25rem',
|
||||
borderTop: '1px solid var(--color-border)',
|
||||
fontFamily: 'var(--font-mono)',
|
||||
}}
|
||||
>
|
||||
<div style={{ color: 'var(--color-text-dim)', fontSize: '0.75rem', marginBottom: '0.4rem' }}>
|
||||
{user?.username}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
background: 'rgba(255,255,0,0.08)',
|
||||
border: '1px solid var(--color-yellow)',
|
||||
color: 'var(--color-yellow)',
|
||||
fontSize: '0.6rem',
|
||||
padding: '0.1rem 0.4rem',
|
||||
letterSpacing: '0.1em',
|
||||
textTransform: 'uppercase',
|
||||
marginBottom: '0.75rem',
|
||||
}}
|
||||
>
|
||||
{user?.role}
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '0.5rem' }}>
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
style={{
|
||||
background: 'transparent',
|
||||
border: '1px solid var(--color-red)',
|
||||
color: 'var(--color-red)',
|
||||
fontFamily: 'var(--font-mono)',
|
||||
fontSize: '0.63rem',
|
||||
padding: '0.2rem 0.5rem',
|
||||
cursor: 'pointer',
|
||||
letterSpacing: '0.05em',
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
<NavLink
|
||||
to="/"
|
||||
style={{
|
||||
background: 'transparent',
|
||||
border: '1px solid var(--color-border)',
|
||||
color: 'var(--color-text-muted)',
|
||||
fontFamily: 'var(--font-mono)',
|
||||
fontSize: '0.63rem',
|
||||
padding: '0.2rem 0.5rem',
|
||||
letterSpacing: '0.05em',
|
||||
textDecoration: 'none',
|
||||
display: 'inline-block',
|
||||
}}
|
||||
>
|
||||
Public
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{/* Main content */}
|
||||
<main style={{ flex: 1, overflowY: 'auto', padding: '2rem', background: 'var(--color-bg)' }}>
|
||||
<Outlet />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user