Files
next-fiber/components/header.tsx
Beyhan Oğur b2825e1698 first commit
2026-04-26 22:14:08 +03:00

182 lines
6.4 KiB
TypeScript
Raw Permalink 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 React, { useEffect, useState } from "react";
import Link from "next/link";
import { useSession, signOut } from "next-auth/react";
import clsx from "clsx";
import { Search, ShoppingCart, ChevronDown, LogOut, User } from "lucide-react";
import { Button } from "@/components/ui/button";
import { ThemeToggle } from "@/components/theme-toggle";
import {
getCookieSession,
logoutViaCookie,
clearTokens,
AUTH_CHANGE_EVENT,
notifyAuthChange,
} from "@/lib/auth-api";
const navItems = [
{ label: "Home", href: "/", hasDropdown: true },
{ label: "About Us", href: "/about", hasDropdown: false },
{ label: "Pages", href: "/pages", hasDropdown: true },
{ label: "Blog", href: "/blog", hasDropdown: true, active: true },
{ label: "Contact", href: "/contact", hasDropdown: false },
];
function TechwixLogo() {
return (
<Link href="/" className="flex items-center gap-2">
<svg
width="32"
height="32"
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="shrink-0"
>
<defs>
<linearGradient id="logoGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stopColor="#3b82f6" />
<stop offset="100%" stopColor="#8b5cf6" />
</linearGradient>
</defs>
{/* Single gradient shape - diamond/arrowhead */}
<path
d="M16 5L27 16L16 27L5 16L16 5Z"
fill="url(#logoGrad)"
/>
<path
d="M16 9L23 16L16 23L9 16L16 9Z"
fill="white"
fillOpacity="0.2"
/>
</svg>
<span className="text-xl font-semibold text-neutral-800 dark:text-neutral-100">
Techwix
</span>
</Link>
);
}
export default function Header() {
const [scrolled, setScrolled] = useState(false);
const { data: session, status } = useSession();
const [cookieLoggedIn, setCookieLoggedIn] = useState(false);
const isLoggedIn = Boolean(session?.user) || cookieLoggedIn;
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 8);
window.addEventListener("scroll", onScroll, { passive: true });
onScroll();
return () => window.removeEventListener("scroll", onScroll);
}, []);
const refreshCookieSession = () => {
getCookieSession().then((s) => setCookieLoggedIn(s.loggedIn));
};
useEffect(() => {
refreshCookieSession();
const handler = () => refreshCookieSession();
window.addEventListener(AUTH_CHANGE_EVENT, handler);
return () => window.removeEventListener(AUTH_CHANGE_EVENT, handler);
}, []);
const handleLogout = async () => {
clearTokens(); // eski localStorage token varsa temizle
await logoutViaCookie();
signOut({ callbackUrl: "/" });
setCookieLoggedIn(false);
notifyAuthChange();
};
return (
<header
className={clsx(
"sticky top-0 z-40 w-full border-b border-neutral-200/80 transition-colors duration-200 backdrop-blur dark:border-neutral-800",
scrolled
? "bg-white/95 shadow-sm dark:bg-neutral-950/95"
: "bg-white dark:bg-neutral-950/90"
)}
>
<div className="container mx-auto flex h-16 items-center justify-between gap-6 px-4 lg:px-6">
<TechwixLogo />
<nav className="hidden items-center gap-1 md:flex">
{navItems.map((item) => (
<Link
key={item.href}
href={item.href}
className={clsx(
"flex items-center gap-0.5 rounded-md px-3 py-2 text-sm font-medium transition-colors",
item.active
? "text-blue-500 dark:text-blue-400"
: "text-neutral-700 hover:text-neutral-900 dark:text-neutral-300 dark:hover:text-white"
)}
>
{item.label}
{item.hasDropdown && (
<ChevronDown className="size-3.5 text-current opacity-70" />
)}
</Link>
))}
</nav>
<div className="flex items-center gap-2">
<ThemeToggle />
<button
type="button"
className="relative rounded-md p-2 text-neutral-600 hover:bg-neutral-100 hover:text-neutral-900 dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-white"
aria-label="Cart"
>
<ShoppingCart className="size-5" />
<span className="absolute -right-0.5 -top-0.5 flex size-4 items-center justify-center rounded-full bg-blue-500 text-[10px] font-medium text-white">
0
</span>
</button>
<button
type="button"
className="rounded-md p-2 text-neutral-600 hover:bg-neutral-100 hover:text-neutral-900 dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-white"
aria-label="Search"
>
<Search className="size-5" />
</button>
{status === "loading" ? null : isLoggedIn ? (
<>
<Link
href="/profile"
className="flex items-center gap-1.5 rounded-md px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-100 hover:text-neutral-900 dark:text-neutral-300 dark:hover:bg-neutral-800 dark:hover:text-white"
>
<User className="size-4" />
<span className="hidden sm:inline">Profil</span>
</Link>
<button
type="button"
onClick={handleLogout}
className="flex items-center gap-1.5 rounded-md px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-100 hover:text-neutral-900 dark:text-neutral-300 dark:hover:bg-neutral-800 dark:hover:text-white"
>
<LogOut className="size-4" />
<span className="hidden sm:inline">Çıkış</span>
</button>
</>
) : (
<>
<Button variant="ghost" size="sm" asChild>
<Link href="/auth/login">Giriş</Link>
</Button>
<Button
asChild
size="sm"
className="rounded-md bg-gradient-to-r from-blue-500 to-blue-400 text-white shadow-sm hover:from-blue-600 hover:to-blue-500 dark:from-blue-600 dark:to-blue-500 dark:hover:from-blue-700 dark:hover:to-blue-600"
>
<Link href="/auth/register">Kayıt</Link>
</Button>
</>
)}
</div>
</div>
</header>
);
}