first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 22:15:25 +03:00
commit 9eb7aea821
56 changed files with 20630 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
'use client'
import { useEffect, useSyncExternalStore } from 'react'
import { Button } from '@/components/ui/button'
import { Moon, Sun } from 'lucide-react'
type Theme = 'light' | 'dark'
function getSnapshot(): Theme {
const saved = localStorage.getItem('theme')
if (saved === 'dark' || saved === 'light') return saved
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
function getServerSnapshot(): Theme {
return 'light'
}
function subscribe(cb: () => void): () => void {
window.addEventListener('storage', cb)
return () => window.removeEventListener('storage', cb)
}
export default function ThemeToggle() {
const theme = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)
useEffect(() => {
document.documentElement.classList.toggle('dark', theme === 'dark')
}, [theme])
function toggleTheme() {
const next: Theme = theme === 'dark' ? 'light' : 'dark'
localStorage.setItem('theme', next)
window.dispatchEvent(new StorageEvent('storage', { key: 'theme', newValue: next }))
}
return (
<Button
variant="ghost"
size="icon"
onClick={toggleTheme}
suppressHydrationWarning
aria-label="Tema değiştir"
>
{theme === 'dark'
? <Sun className="size-4" />
: <Moon className="size-4" />}
</Button>
)
}

59
app/components/TopBar.tsx Normal file
View File

@@ -0,0 +1,59 @@
'use client'
import Link from 'next/link'
import ThemeToggle from './ThemeToggle'
import { signOut } from 'next-auth/react'
import { Button } from '@/components/ui/button'
import { LogOut, Zap } from 'lucide-react'
type Props = {
isLoggedIn: boolean
}
export default function TopBar({ isLoggedIn }: Props) {
async function onLogout() {
await signOut({ callbackUrl: '/auth/login' })
}
return (
<header className="sticky top-0 z-50 border-b bg-background/80 backdrop-blur-sm">
<div className="mx-auto flex w-full max-w-7xl items-center justify-between px-4 py-2.5">
{/* Logo */}
<Link href="/" className="flex items-center gap-2">
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-primary text-primary-foreground">
<Zap className="size-4" />
</div>
<span className="text-base font-bold tracking-tight">NextGo</span>
</Link>
{/* Actions */}
<nav className="flex items-center gap-1">
<ThemeToggle />
{isLoggedIn ? (
<>
<Button variant="ghost" size="sm" asChild>
<Link href="/admin/users">Admin</Link>
</Button>
<Button type="button" onClick={onLogout} variant="destructive" size="sm">
<LogOut className="size-4" />
Çıkış
</Button>
</>
) : (
<>
<Button variant="ghost" size="sm" asChild>
<Link href="/auth/login">Giriş</Link>
</Button>
<Button size="sm" asChild>
<Link href="/auth/register">Kayıt Ol</Link>
</Button>
</>
)}
</nav>
</div>
</header>
)
}