first commit
This commit is contained in:
172
components/header/header.tsx
Normal file
172
components/header/header.tsx
Normal file
@@ -0,0 +1,172 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useTheme } from "next-themes";
|
||||
import { useAppSelector, useAppDispatch } from "@/lib/hooks";
|
||||
import { logout } from "@/lib/features/auth/authSlice";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { Sun, Moon, LogOut, User, LayoutDashboard, Menu } from "lucide-react";
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
|
||||
import { useState, useEffect } from "react";
|
||||
import { getAvatarUrl } from "@/lib/utils";
|
||||
|
||||
export function Header() {
|
||||
const { setTheme, theme } = useTheme();
|
||||
const dispatch = useAppDispatch();
|
||||
const { isAuthenticated, user } = useAppSelector((state) => state.auth);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
// Prevent hydration mismatch
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
const handleLogout = () => {
|
||||
dispatch(logout());
|
||||
};
|
||||
|
||||
if (!mounted) {
|
||||
return (
|
||||
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
||||
<div className="container flex h-14 items-center pl-10 pr-10">
|
||||
<div className="mr-4 hidden md:flex">
|
||||
<Link href="/" className="mr-6 flex items-center space-x-2">
|
||||
<span className="hidden font-bold sm:inline-block">
|
||||
NextGoBlog
|
||||
</span>
|
||||
</Link>
|
||||
<nav className="flex items-center space-x-6 text-sm font-medium">
|
||||
<Link href="/blog">Blog</Link>
|
||||
<Link href="/about">Hakkında</Link>
|
||||
</nav>
|
||||
</div>
|
||||
<div className="flex flex-1 items-center justify-end space-x-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="ghost" asChild>
|
||||
<Link href="/login">Giriş Yap</Link>
|
||||
</Button>
|
||||
<Button asChild>
|
||||
<Link href="/register">Kayıt Ol</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
||||
<div className="container flex h-14 items-center pl-10 pr-10">
|
||||
{/* Desktop Interface */}
|
||||
<div className="mr-4 hidden md:flex">
|
||||
<Link href="/" className="mr-6 flex items-center space-x-2">
|
||||
<span className="hidden font-bold sm:inline-block">
|
||||
NextGoBlog
|
||||
</span>
|
||||
</Link>
|
||||
<nav className="flex items-center space-x-6 text-sm font-medium">
|
||||
<Link href="/blog">Blog</Link>
|
||||
<Link href="/about">Hakkında</Link>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
{/* Mobile Interface */}
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="mr-2 px-0 text-base hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 md:hidden"
|
||||
>
|
||||
<Menu className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle Menu</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left" className="pr-0">
|
||||
<Link href="/" className="flex items-center">
|
||||
<span className="font-bold">NextGoBlog</span>
|
||||
</Link>
|
||||
<nav className="mt-8 flex flex-col gap-4">
|
||||
<Link href="/blog">Blog</Link>
|
||||
<Link href="/about">Hakkında</Link>
|
||||
</nav>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
|
||||
{/* Right Side */}
|
||||
<div className="flex flex-1 items-center justify-end space-x-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
|
||||
>
|
||||
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
|
||||
{isAuthenticated ? (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="relative h-8 w-8 rounded-full">
|
||||
<Avatar className="h-8 w-8">
|
||||
<AvatarImage src={getAvatarUrl(user?.avatar_url)} alt={user?.username} />
|
||||
<AvatarFallback>{user?.username?.slice(0, 2).toUpperCase()}</AvatarFallback>
|
||||
</Avatar>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56" align="end" forceMount>
|
||||
<DropdownMenuLabel className="font-normal">
|
||||
<div className="flex flex-col space-y-1">
|
||||
<p className="text-sm font-medium leading-none">{user?.username}</p>
|
||||
<p className="text-xs leading-none text-muted-foreground">
|
||||
{user?.email}
|
||||
</p>
|
||||
</div>
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
{user?.roles?.some((r: any) => r.name === "admin") && (
|
||||
<DropdownMenuItem asChild>
|
||||
<Link href="/admin">
|
||||
<LayoutDashboard className="mr-2 h-4 w-4" />
|
||||
<span>Admin Panel</span>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem asChild>
|
||||
<Link href="/profile">
|
||||
<User className="mr-2 h-4 w-4" />
|
||||
<span>Profil</span>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={handleLogout}>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
<span>Çıkış Yap</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="ghost" asChild>
|
||||
<Link href="/login">Giriş Yap</Link>
|
||||
</Button>
|
||||
<Button asChild>
|
||||
<Link href="/register">Kayıt Ol</Link>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user