chore : move all to root

This commit is contained in:
Thibault Pouch
2026-02-26 16:16:44 +01:00
parent 308a758e79
commit c2d94a349c
44 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,264 @@
import { useState, useCallback } from 'react';
import { Link, NavLink, useNavigate } from 'react-router-dom';
import { useAuth } from '../../contexts/AuthContext';
const NAV_LINKS = [
{ to: '/', label: 'Home', end: true },
{ to: '/studio', label: 'Studio', end: false },
{ to: '/events', label: 'Events', end: false },
{ to: '/forum', label: 'Forum', end: false },
{ to: '/bugs', label: 'Bugs', end: false },
];
export function Navbar() {
const { user, isAuthenticated, isStaff, logout } = useAuth();
const navigate = useNavigate();
const [menuOpen, setMenuOpen] = useState(false);
const handleLogout = useCallback(() => {
logout();
setMenuOpen(false);
navigate('/');
}, [logout, navigate]);
const closeMenu = useCallback(() => setMenuOpen(false), []);
const navLinkStyle = ({ isActive }: { isActive: boolean }): React.CSSProperties => ({
fontFamily: 'var(--font-mono)',
fontSize: '0.82rem',
textTransform: 'uppercase',
letterSpacing: '0.12em',
textDecoration: 'none',
color: isActive ? 'var(--color-yellow)' : 'var(--color-text-dim)',
borderBottom: isActive ? '2px solid var(--color-yellow)' : '2px solid transparent',
paddingBottom: '2px',
transition: 'color 0.1s, border-color 0.1s',
});
return (
<header
style={{
background: 'var(--color-bg)',
borderBottom: '2px solid var(--color-border)',
position: 'sticky',
top: 0,
zIndex: 50,
}}
>
<nav
className="max-w-7xl mx-auto px-4 sm:px-6 h-14 flex items-center justify-between"
role="navigation"
aria-label="Main navigation"
>
{/* Logo */}
<Link
to="/"
onClick={closeMenu}
style={{
display: 'flex',
alignItems: 'baseline',
gap: '0.5rem',
textDecoration: 'none',
}}
>
<span
style={{
fontFamily: 'var(--font-heading)',
color: 'var(--color-yellow)',
fontSize: '1.5rem',
letterSpacing: '0.08em',
}}
>
CROWMATE
</span>
<span
style={{
fontFamily: 'var(--font-mono)',
color: 'var(--color-text-muted)',
fontSize: '0.62rem',
letterSpacing: '0.15em',
}}
>
STUDIO
</span>
</Link>
{/* Desktop Nav */}
<div className="hidden md:flex items-center gap-6">
{NAV_LINKS.map(({ to, label, end }) => (
<NavLink key={to} to={to} end={end} style={navLinkStyle}>
{label}
</NavLink>
))}
{/* Intranet — visually separated, highlighted button */}
{isStaff && (
<>
{/* Vertical divider */}
<span
aria-hidden="true"
style={{
display: 'inline-block',
width: '1px',
height: '18px',
background: 'var(--color-border)',
margin: '0 0.25rem',
}}
/>
<NavLink
to="/intranet"
style={({ isActive }) => ({
fontFamily: 'var(--font-mono)',
fontSize: '0.75rem',
textTransform: 'uppercase',
letterSpacing: '0.1em',
textDecoration: 'none',
background: isActive ? 'var(--color-yellow)' : 'var(--color-yellow)',
color: 'var(--color-bg)',
border: '2px solid var(--color-yellow)',
padding: '0.2rem 0.65rem',
fontWeight: 'bold',
opacity: isActive ? 1 : 0.85,
transition: 'opacity 0.1s',
})}
>
&#9646; INTRANET
</NavLink>
</>
)}
</div>
{/* Desktop Auth */}
<div className="hidden md:flex items-center gap-3">
{isAuthenticated ? (
<>
<Link
to="/account"
style={{
color: 'var(--color-text-dim)',
fontSize: '0.78rem',
fontFamily: 'var(--font-mono)',
textDecoration: 'none',
}}
>
[{user?.username}]
</Link>
<button className="btn-terminal btn-danger" onClick={handleLogout} style={{ padding: '0.3rem 0.85rem', fontSize: '0.75rem' }}>
Logout
</button>
</>
) : (
<>
<Link to="/login" className="btn-terminal" style={{ padding: '0.3rem 0.85rem', fontSize: '0.75rem' }}>
Login
</Link>
<Link to="/register" className="btn-terminal btn-amber" style={{ padding: '0.3rem 0.85rem', fontSize: '0.75rem' }}>
Register
</Link>
</>
)}
</div>
{/* Mobile hamburger */}
<button
className="md:hidden"
style={{ background: 'transparent', border: 'none', cursor: 'pointer', padding: '4px' }}
onClick={() => setMenuOpen((v) => !v)}
aria-label={menuOpen ? 'Close menu' : 'Open menu'}
aria-expanded={menuOpen}
>
{/* Three-bar icon using block chars */}
<div style={{ fontFamily: 'var(--font-mono)', color: 'var(--color-cyan)', fontSize: '1.2rem', lineHeight: 1 }}>
{menuOpen ? '✕' : '≡'}
</div>
</button>
</nav>
{/* Mobile menu */}
{menuOpen && (
<div
style={{
background: 'var(--color-bg)',
borderTop: '2px solid var(--color-border)',
padding: '1rem 1.25rem',
}}
>
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.85rem' }}>
{NAV_LINKS.map(({ to, label, end }) => (
<NavLink
key={to}
to={to}
end={end}
onClick={closeMenu}
style={navLinkStyle}
>
{label}
</NavLink>
))}
{/* Auth section */}
<div
style={{
borderTop: '1px solid var(--color-border)',
paddingTop: '0.85rem',
display: 'flex',
gap: '0.6rem',
flexWrap: 'wrap',
}}
>
{isAuthenticated ? (
<>
<Link
to="/account"
style={{ color: 'var(--color-text-dim)', fontSize: '0.78rem', textDecoration: 'none', fontFamily: 'var(--font-mono)' }}
onClick={closeMenu}
>
[{user?.username}]
</Link>
<button className="btn-terminal btn-danger" onClick={handleLogout} style={{ padding: '0.25rem 0.7rem', fontSize: '0.73rem' }}>
Logout
</button>
</>
) : (
<>
<Link to="/login" className="btn-terminal" onClick={closeMenu} style={{ padding: '0.25rem 0.7rem', fontSize: '0.73rem' }}>
Login
</Link>
<Link to="/register" className="btn-terminal btn-amber" onClick={closeMenu} style={{ padding: '0.25rem 0.7rem', fontSize: '0.73rem' }}>
Register
</Link>
</>
)}
</div>
{/* Intranet button — mobile: separated at the bottom */}
{isStaff && (
<div style={{ borderTop: '2px solid var(--color-yellow)', paddingTop: '0.85rem' }}>
<NavLink
to="/intranet"
onClick={closeMenu}
style={({ isActive }) => ({
display: 'inline-block',
fontFamily: 'var(--font-mono)',
fontSize: '0.8rem',
textTransform: 'uppercase' as const,
letterSpacing: '0.1em',
textDecoration: 'none',
background: 'var(--color-yellow)',
color: 'var(--color-bg)',
border: '2px solid var(--color-yellow)',
padding: '0.3rem 0.85rem',
fontWeight: 'bold',
opacity: isActive ? 0.85 : 1,
})}
>
&#9646; INTRANET
</NavLink>
</div>
)}
</div>
</div>
)}
</header>
);
}