286 lines
10 KiB
TypeScript
286 lines
10 KiB
TypeScript
'use client';
|
||
|
||
import Link from 'next/link';
|
||
import { usePathname } from 'next/navigation';
|
||
import { useState } from 'react';
|
||
import { useTheme } from './ThemeProvider';
|
||
|
||
const navGroups = [
|
||
{
|
||
label: 'Ana',
|
||
items: [
|
||
{ href: '/', label: 'Anasayfa', icon: '~' },
|
||
{ href: '/merhaba', label: 'Merhaba', icon: '>' },
|
||
{ href: '/hakkimda', label: 'Hakkımda', icon: '@' },
|
||
{ href: '/su-anda', label: 'Şu Anda', icon: '◉' },
|
||
{ href: '/misyon', label: 'Misyon', icon: '⚑' },
|
||
],
|
||
},
|
||
{
|
||
label: 'İçerik',
|
||
items: [
|
||
{ href: '/blog', label: 'Personal Blog', icon: '✍' },
|
||
{ href: '/notebook', label: 'Notebook', icon: '◎' },
|
||
{ href: '/infosec', label: 'Infosec Posts', icon: '⚔' },
|
||
{ href: '/seyir-defteri', label: 'Seyir Defteri', icon: '⚓' },
|
||
{ href: '/projeler', label: 'Projeler', icon: '◈' },
|
||
{ href: '/podcast', label: 'Podcast', icon: '◉' },
|
||
],
|
||
},
|
||
{
|
||
label: 'Koleksiyon',
|
||
items: [
|
||
{ href: '/faydali-linkler', label: 'Faydalı Linkler', icon: '⊞' },
|
||
{ href: '/roadmap', label: 'Roadmap', icon: '◆' },
|
||
{ href: '/takim-cantam', label: 'Takım Çantam', icon: '⊡' },
|
||
{ href: '/hobilerim', label: 'Hobilerim', icon: '♦' },
|
||
{ href: '/fikirlerim', label: 'Fikirlerim', icon: '◇' },
|
||
],
|
||
},
|
||
{
|
||
label: 'Bilgi',
|
||
items: [
|
||
{ href: '/iletisim', label: 'İletişim', icon: '✉' },
|
||
{ href: '/ozgecmis', label: 'Özgeçmiş', icon: '▤' },
|
||
{ href: '/aktivite', label: 'Aktivite', icon: '▶' },
|
||
{ href: '/rss-beslemeleri', label: 'RSS Beslemeleri', icon: '◈' },
|
||
{ href: '/statboard', label: 'Statboard', icon: '▦' },
|
||
{ href: '/altyapi', label: 'Altyapı', icon: '⊟' },
|
||
{ href: '/tesekkurler', label: 'Teşekkürler', icon: '♡' },
|
||
],
|
||
},
|
||
{
|
||
label: 'Meta',
|
||
items: [
|
||
{ href: '/gizlilik', label: 'Gizlilik', icon: '⊘' },
|
||
{ href: '/kullanim-kosullari', label: 'Kullanım Koşulları', icon: '⊘' },
|
||
{ href: '/humans.txt', label: 'humans.txt', icon: '▸', external: true },
|
||
{ href: '/security.txt', label: 'security.txt', icon: '▸', external: true },
|
||
{ href: '/public.pgp', label: 'public.pgp', icon: '▸', external: true },
|
||
],
|
||
},
|
||
{
|
||
label: 'Harici',
|
||
items: [
|
||
{ href: '/mastodon', label: 'Mastodon', icon: '⊕', external: true },
|
||
{ href: 'mailto:info@denizbektas.com.tr', label: 'E-Mail', icon: '✉', external: true },
|
||
],
|
||
},
|
||
];
|
||
|
||
export default function Navigation() {
|
||
const pathname = usePathname();
|
||
const { theme, toggle } = useTheme();
|
||
const [mobileOpen, setMobileOpen] = useState(false);
|
||
|
||
const isActive = (href: string) => {
|
||
if (href === '/') return pathname === '/';
|
||
return pathname.startsWith(href);
|
||
};
|
||
|
||
const sidebarContent = (
|
||
<nav style={{ display: 'flex', flexDirection: 'column', gap: '1.25rem' }}>
|
||
{navGroups.map((group) => (
|
||
<div key={group.label}>
|
||
<div className="section-header">{group.label}</div>
|
||
<ul style={{ listStyle: 'none', display: 'flex', flexDirection: 'column', gap: '1px' }}>
|
||
{group.items.map((item) => (
|
||
<li key={item.href}>
|
||
{item.external && item.href.startsWith('mailto:') ? (
|
||
<a
|
||
href={item.href}
|
||
style={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: '0.5rem',
|
||
padding: '0.3rem 0.5rem',
|
||
borderRadius: '4px',
|
||
fontSize: '0.93rem',
|
||
color: 'var(--text-muted)',
|
||
transition: 'all 0.15s',
|
||
}}
|
||
>
|
||
<span style={{ color: 'var(--accent)', width: '1.1rem', flexShrink: 0, fontSize: '0.82rem' }}>{item.icon}</span>
|
||
{item.label}
|
||
</a>
|
||
) : item.external && !item.href.startsWith('/') ? (
|
||
<a
|
||
href={item.href}
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
style={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: '0.5rem',
|
||
padding: '0.3rem 0.5rem',
|
||
borderRadius: '4px',
|
||
fontSize: '0.93rem',
|
||
color: 'var(--text-muted)',
|
||
}}
|
||
>
|
||
<span style={{ color: 'var(--accent)', width: '1.1rem', flexShrink: 0, fontSize: '0.82rem' }}>{item.icon}</span>
|
||
{item.label}
|
||
<span style={{ marginLeft: 'auto', fontSize: '0.7rem', opacity: 0.5 }}>↗</span>
|
||
</a>
|
||
) : (
|
||
<Link
|
||
href={item.href}
|
||
target={item.external ? '_blank' : undefined}
|
||
onClick={() => setMobileOpen(false)}
|
||
style={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: '0.5rem',
|
||
padding: '0.35rem 0.5rem',
|
||
borderRadius: '4px',
|
||
fontSize: '0.93rem',
|
||
color: isActive(item.href) ? 'var(--accent)' : 'var(--text-muted)',
|
||
background: isActive(item.href) ? 'var(--tag-bg)' : 'transparent',
|
||
fontWeight: isActive(item.href) ? '600' : '400',
|
||
transition: 'all 0.15s',
|
||
opacity: 1,
|
||
}}
|
||
>
|
||
<span style={{ color: 'var(--accent)', width: '1.1rem', flexShrink: 0, fontSize: '0.82rem' }}>{item.icon}</span>
|
||
{item.label}
|
||
{item.external && <span style={{ marginLeft: 'auto', fontSize: '0.7rem', opacity: 0.5 }}>↗</span>}
|
||
</Link>
|
||
)}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
))}
|
||
</nav>
|
||
);
|
||
|
||
return (
|
||
<>
|
||
{/* Desktop Sidebar */}
|
||
<aside
|
||
className="desktop-sidebar"
|
||
style={{
|
||
width: '272px',
|
||
flexShrink: 0,
|
||
background: 'var(--sidebar-bg)',
|
||
borderRight: '1px solid var(--border)',
|
||
height: '100vh',
|
||
position: 'sticky',
|
||
top: 0,
|
||
overflowY: 'auto',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
}}
|
||
>
|
||
{/* Logo */}
|
||
<div style={{ padding: '1.25rem 1rem', borderBottom: '1px solid var(--border)' }}>
|
||
<Link href="/" style={{ display: 'block', color: 'var(--accent)', fontWeight: '800', fontSize: '1.1rem', letterSpacing: '-0.02em' }}>
|
||
denizbektas<span style={{ color: 'var(--text-muted)', fontWeight: 400 }}>.com.tr</span>
|
||
</Link>
|
||
<div style={{ fontSize: '0.78rem', color: 'var(--text-muted)', marginTop: '0.25rem' }}>siber güvenlik uzmanı</div>
|
||
</div>
|
||
|
||
{/* Theme Toggle */}
|
||
<div style={{ padding: '0.75rem 1rem', borderBottom: '1px solid var(--border)' }}>
|
||
<button
|
||
onClick={toggle}
|
||
style={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: '0.5rem',
|
||
fontSize: '0.88rem',
|
||
color: 'var(--text-muted)',
|
||
background: 'none',
|
||
border: 'none',
|
||
cursor: 'pointer',
|
||
padding: '0.35rem 0.5rem',
|
||
borderRadius: '4px',
|
||
width: '100%',
|
||
fontFamily: 'inherit',
|
||
transition: 'color 0.15s',
|
||
}}
|
||
>
|
||
<span style={{ fontSize: '0.9rem' }}>{theme === 'dark' ? '☀' : '◑'}</span>
|
||
{theme === 'dark' ? 'Light Mode' : 'Dark Mode'}
|
||
</button>
|
||
</div>
|
||
|
||
{/* Nav */}
|
||
<div style={{ padding: '1rem', flex: 1 }}>
|
||
{sidebarContent}
|
||
</div>
|
||
|
||
{/* Footer */}
|
||
<div style={{ padding: '0.75rem 1rem', borderTop: '1px solid var(--border)', fontSize: '0.6rem', color: 'var(--text-muted)' }}>
|
||
<div>© 2026 denizbektas</div>
|
||
<div style={{ marginTop: '0.2rem', color: 'var(--accent)', opacity: 0.6 }}>
|
||
<span className="blink">█</span>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
{/* Mobile Header */}
|
||
<header
|
||
className="mobile-header"
|
||
style={{
|
||
display: 'none',
|
||
position: 'fixed',
|
||
top: 0,
|
||
left: 0,
|
||
right: 0,
|
||
height: '52px',
|
||
background: 'var(--header-bg)',
|
||
backdropFilter: 'blur(8px)',
|
||
borderBottom: '1px solid var(--border)',
|
||
zIndex: 100,
|
||
alignItems: 'center',
|
||
justifyContent: 'space-between',
|
||
padding: '0 1rem',
|
||
}}
|
||
>
|
||
<Link href="/" style={{ color: 'var(--accent)', fontWeight: '800', fontSize: '0.95rem' }}>
|
||
denizbektas<span style={{ color: 'var(--text-muted)', fontWeight: 400 }}>.dev</span>
|
||
</Link>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
|
||
<button onClick={toggle} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: '1rem', color: 'var(--text-muted)' }}>
|
||
{theme === 'dark' ? '☀' : '◑'}
|
||
</button>
|
||
<button
|
||
onClick={() => setMobileOpen(!mobileOpen)}
|
||
style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text)', fontSize: '1.2rem', fontFamily: 'inherit' }}
|
||
>
|
||
{mobileOpen ? '✕' : '☰'}
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
{/* Mobile Nav Overlay */}
|
||
{mobileOpen && (
|
||
<div
|
||
style={{
|
||
position: 'fixed',
|
||
top: '52px',
|
||
left: 0,
|
||
right: 0,
|
||
bottom: 0,
|
||
background: 'var(--sidebar-bg)',
|
||
zIndex: 99,
|
||
overflowY: 'auto',
|
||
padding: '1rem',
|
||
borderTop: '1px solid var(--border)',
|
||
}}
|
||
>
|
||
{sidebarContent}
|
||
</div>
|
||
)}
|
||
|
||
<style>{`
|
||
@media (max-width: 768px) {
|
||
.desktop-sidebar { display: none !important; }
|
||
.mobile-header { display: flex !important; }
|
||
}
|
||
`}</style>
|
||
</>
|
||
);
|
||
}
|