Files
personalsite/components/Navigation.tsx
2026-04-03 16:20:51 +03:00

286 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'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>
</>
);
}