Refactor NavItems component

This commit is contained in:
2026-01-26 22:30:50 +01:00
parent c97393c751
commit 8bbe4a2e01
6 changed files with 107 additions and 97 deletions

View File

@@ -1,7 +1,5 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { ThemeProvider } from "next-themes";
import { Geist, Geist_Mono } from "next/font/google"; import { Geist, Geist_Mono } from "next/font/google";
import { ThemeToggle } from "../components/ThemeToggle";
import "./globals.css"; import "./globals.css";
const geistSans = Geist({ const geistSans = Geist({
@@ -26,9 +24,7 @@ export default function RootLayout({
}>) { }>) {
return ( return (
<html lang="en" className="dark"> <html lang="en" className="dark">
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}> <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>{children}</body>
{children}
</body>
</html> </html>
); );
} }

View File

@@ -8,10 +8,10 @@ const Header = () => {
<header className="sticky top-0 header"> <header className="sticky top-0 header">
<div className="container header-wrapper"> <div className="container header-wrapper">
<Link href="/"> <Link href="/">
<Image src="/logo.svg" alt="CGR Logo" width={100} height={100} className="h-8 w-auto cursor-pointer"/> <Image src="/logo.svg" alt="CGR Logo" width={100} height={100} className="h-8 w-auto cursor-pointer" />
</Link> </Link>
<nav className="hidden sm:block"> <nav className="hidden sm:block">
<NavItems /> <NavItems />
</nav> </nav>
<UserDropdown /> <UserDropdown />
</div> </div>

View File

@@ -1,36 +0,0 @@
"use client";
import { NAV_ITEMS } from "@/lib/constans";
import Link from "next/link";
import { usePathname } from "next/navigation";
const NavItems = () => {
const pathname = usePathname();
const isActive = (path: string) => {
if(path === '/') return pathname === '/';
return pathname.startsWith(path);
}
return (
<ul className="flex flex-col sm:flex-row p-2 gap-3 sm:gap-10 font-medium">
{NAV_ITEMS.map(({ label, href }) => {
const active = isActive(href);
return (
<li key={href}>
<Link href={href} className={`hover:text-yellow-500 transition-colors ${
active
? 'text-gray-100 font-bold'
: ''
}`}
>
{label}
</Link>
</li>
);
})}
</ul>
);
};
export default NavItems;

View File

@@ -0,0 +1,33 @@
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
type NavItemProps = {
item: {
label: string;
href: string;
};
};
export const NavItem: React.FC<NavItemProps> = ({ item: { label, href } }) => {
const pathname = usePathname();
const isActive = (path: string) => {
if (path === "/") return pathname === "/";
return pathname.startsWith(path);
};
const active = isActive(href);
return (
<li key={href}>
<Link
href={href}
className={`hover:text-yellow-500 transition-colors ${active ? "text-gray-100 font-bold" : ""}`}
>
{label}
</Link>
</li>
);
};

View File

@@ -0,0 +1,16 @@
"use client";
import { NAV_ITEMS } from "@/lib/constans";
import { NavItem } from "./NavItem";
const NavItems = () => {
return (
<ul className="flex flex-col sm:flex-row p-2 gap-3 sm:gap-10 font-medium">
{NAV_ITEMS.map((item) => (
<NavItem key={item.href} item={item} />
))}
</ul>
);
};
export default NavItems;

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@@ -9,63 +9,64 @@ import {
DropdownMenuLabel, DropdownMenuLabel,
DropdownMenuSeparator, DropdownMenuSeparator,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu" } from "@/components/ui/dropdown-menu";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { useRouter } from "next/navigation" import { useRouter } from "next/navigation";
import { LogOut } from "lucide-react"; import { LogOut } from "lucide-react";
import NavItems from "./NavItems"; import NavItems from "./NavItems";
const UserDropdown = () => { const UserDropdown = () => {
const router = useRouter(); const router = useRouter();
const handleSignOut = async() => { const handleSignOut = async () => {
router.push('/sign-in'); router.push("/sign-in");
} };
const user = { name: 'Ivan', email: 'ivan@cgr.js' }; const user = { name: "Ivan", email: "ivan@cgr.js" };
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button variant="ghost" className="flex items-center gap-3 text-gray-4 hover:text-yellow-500"> <Button variant="ghost" className="flex items-center gap-3 text-gray-4 hover:text-yellow-500">
<Avatar className="h-8 w-8"> <Avatar className="h-8 w-8">
{/* <AvatarImage src="https://github.com/shadcn.png" /> */} {/* <AvatarImage src="https://github.com/shadcn.png" /> */}
<AvatarFallback className="bg-yellow-500 text-yellow-900 text-sm font-bold"> <AvatarFallback className="bg-yellow-500 text-yellow-900 text-sm font-bold">{user.name[0]}</AvatarFallback>
{user.name[0]} </Avatar>
</AvatarFallback> <div className="hidden md:flex flex-col items-start">
</Avatar> <span className="text-base font-medium text-gray-400">{user.name}</span>
<div className="hidden md:flex flex-col items-start"> </div>
<span className="text-base font-medium text-gray-400">{user.name}</span> </Button>
</div> </DropdownMenuTrigger>
</Button> <DropdownMenuContent className="text-gray-400">
</DropdownMenuTrigger> <DropdownMenuLabel>
<DropdownMenuContent className="text-gray-400"> <div className="flex relative items-center gap-3 py-2">
<DropdownMenuLabel> <Avatar className="h-10 w-10">
<div className="flex relative items-center gap-3 py-2"> {/* <AvatarImage src="https://github.com/shadcn.png" /> */}
<Avatar className="h-10 w-10"> <AvatarFallback className="bg-yellow-500 text-yellow-900 text-sm font-bold">
{/* <AvatarImage src="https://github.com/shadcn.png" /> */} {user.name[0]}
<AvatarFallback className="bg-yellow-500 text-yellow-900 text-sm font-bold"> </AvatarFallback>
{user.name[0]} </Avatar>
</AvatarFallback> <div className="flex flex-col">
</Avatar> <span className="text-base font-medium text-gray-400">{user.name}</span>
<div className="flex flex-col"> <span className="text-sm text-gray-500">{user.email}</span>
<span className="text-base font-medium text-gray-400">{user.name}</span> </div>
<span className="text-sm text-gray-500">{user.email}</span> </div>
</div> </DropdownMenuLabel>
</div> <DropdownMenuSeparator className="bg-gray-600" />
</DropdownMenuLabel> <nav className="sm:hidden">
<DropdownMenuSeparator className="bg-gray-600" /> <NavItems />
<nav className="sm:hidden"> </nav>
<NavItems /> <DropdownMenuSeparator className="sm:hidden bg-gray-600" />
</nav> <DropdownMenuItem
<DropdownMenuSeparator className="sm:hidden bg-gray-600" /> onClick={handleSignOut}
<DropdownMenuItem onClick={handleSignOut} className="text-gray-100 text-md font-medium focus:bg-transparent focus:text-yellow-500 transition-colors cursor-pointer"> className="text-gray-100 text-md font-medium focus:bg-transparent focus:text-yellow-500 transition-colors cursor-pointer"
<LogOut className="mr-2 h-4 w-4" /> >
Logout <LogOut className="mr-2 h-4 w-4" />
</DropdownMenuItem> Logout
</DropdownMenuContent> </DropdownMenuItem>
</DropdownMenu> </DropdownMenuContent>
) </DropdownMenu>
} );
};
export default UserDropdown; export default UserDropdown;