mirror of
https://gitbruv.vercel.app/api/git/bruv/gitbruv.git
synced 2025-12-20 23:24:09 +01:00
117 lines
5.4 KiB
TypeScript
117 lines
5.4 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { useRouter } from "next/navigation";
|
|
import { Plus, LogOut, User, ChevronDown, Settings, Compass } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
|
import { signOut, useSession } from "@/lib/auth-client";
|
|
|
|
export function Header() {
|
|
const router = useRouter();
|
|
const { data: session } = useSession();
|
|
|
|
async function handleSignOut() {
|
|
await signOut();
|
|
router.push("/");
|
|
router.refresh();
|
|
}
|
|
|
|
return (
|
|
<header className="sticky top-0 z-50 w-full border-b border-border bg-[#010409]">
|
|
<div className="container flex h-16 items-center justify-between">
|
|
<div className="flex items-center gap-6">
|
|
<Link href="/" className="flex items-center gap-2.5 group">
|
|
<span className="font-bold text-xl tracking-tight hidden sm:inline">gitbruv</span>
|
|
</Link>
|
|
<nav className="hidden md:flex items-center gap-1">
|
|
<Button variant="ghost" size="sm" asChild className="text-muted-foreground hover:text-foreground">
|
|
<Link href="/explore" className="gap-2">
|
|
<Compass className="h-4 w-4" />
|
|
Explore
|
|
</Link>
|
|
</Button>
|
|
</nav>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2">
|
|
{session?.user ? (
|
|
<>
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button variant="ghost" size="sm" className="h-8 gap-1 px-2 text-muted-foreground hover:text-foreground">
|
|
<Plus className="h-4 w-4" />
|
|
<ChevronDown className="h-3 w-3" />
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" className="w-48">
|
|
<DropdownMenuItem asChild>
|
|
<Link href="/new" className="cursor-pointer gap-2">
|
|
<BookIcon className="h-4 w-4" />
|
|
New repository
|
|
</Link>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button variant="ghost" className="h-8 w-8 rounded-full p-0 overflow-hidden ring-2 ring-transparent hover:ring-accent/50 transition-all">
|
|
<Avatar className="h-8 w-8">
|
|
<AvatarImage src={session.user.image || undefined} />
|
|
<AvatarFallback className="bg-gradient-to-br from-accent/40 to-primary/40 text-foreground text-xs font-semibold">
|
|
{session.user.name?.charAt(0).toUpperCase() || "U"}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" className="w-56">
|
|
<div className="px-3 py-2">
|
|
<p className="text-sm font-medium">{session.user.name}</p>
|
|
<p className="text-xs text-muted-foreground">@{(session.user as { username?: string }).username}</p>
|
|
</div>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem asChild>
|
|
<Link href={`/${(session.user as { username?: string }).username}`} className="cursor-pointer gap-2">
|
|
<User className="h-4 w-4" />
|
|
Your profile
|
|
</Link>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem asChild>
|
|
<Link href="/settings" className="cursor-pointer gap-2">
|
|
<Settings className="h-4 w-4" />
|
|
Settings
|
|
</Link>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem onClick={handleSignOut} className="cursor-pointer gap-2 text-destructive focus:text-destructive focus:bg-destructive/10">
|
|
<LogOut className="h-4 w-4" />
|
|
Sign out
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</>
|
|
) : (
|
|
<div className="flex items-center gap-2">
|
|
<Button variant="ghost" size="sm" asChild className="text-muted-foreground hover:text-foreground">
|
|
<Link href="/login">Sign in</Link>
|
|
</Button>
|
|
<Button size="sm" asChild>
|
|
<Link href="/register">Sign up</Link>
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|
|
|
|
function BookIcon({ className }: { className?: string }) {
|
|
return (
|
|
<svg className={className} viewBox="0 0 16 16" fill="currentColor">
|
|
<path d="M0 1.75A.75.75 0 0 1 .75 1h4.253c1.227 0 2.317.59 3 1.501A3.743 3.743 0 0 1 11.006 1h4.245a.75.75 0 0 1 .75.75v10.5a.75.75 0 0 1-.75.75h-4.507a2.25 2.25 0 0 0-1.591.659l-.622.621a.75.75 0 0 1-1.06 0l-.622-.621A2.25 2.25 0 0 0 5.258 13H.75a.75.75 0 0 1-.75-.75Zm7.251 10.324.004-5.073-.002-2.253A2.25 2.25 0 0 0 5.003 2.5H1.5v9h3.757a3.75 3.75 0 0 1 1.994.574ZM8.755 4.75l-.004 7.322a3.752 3.752 0 0 1 1.992-.572H14.5v-9h-3.495a2.25 2.25 0 0 0-2.25 2.25Z" />
|
|
</svg>
|
|
);
|
|
}
|