Files
zhimingge/components/header.tsx
T
2026-06-13 09:39:38 +08:00

115 lines
3.6 KiB
TypeScript

"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { History, LogIn, LogOut } from "lucide-react";
import { TaijiIcon } from "@/components/svg/taiji";
import { ModeToggle } from "@/components/mode-toggle";
import { SITE_WIDTH_INNER } from "@/components/layout/site-width";
import { useAuth } from "@/components/auth/auth-provider";
import { Button } from "@/components/ui/button";
const NAV_ITEMS = [
{ href: "/learn", label: "易经学习", protected: false },
{ href: "/liuyao", label: "六爻算卦", protected: true },
{ href: "/bazi", label: "生辰八字", protected: true },
{ href: "/combined", label: "综合测算", protected: true },
] as const;
function NavLink({
href,
label,
needLogin,
}: {
href: string;
label: string;
needLogin: boolean;
}) {
const pathname = usePathname();
const active =
href === "/"
? pathname === "/"
: pathname === href || pathname.startsWith(`${href}/`);
const target = needLogin ? `/login?next=${encodeURIComponent(href)}` : href;
return (
<Link
href={target}
className={`whitespace-nowrap text-sm transition-colors ${
active
? "font-medium text-foreground"
: "text-muted-foreground hover:text-foreground"
}`}
>
{label}
</Link>
);
}
export default function Header() {
const { authEnabled, loggedIn, username, logout, loading } = useAuth();
return (
<header className="relative z-10 border-b border-border/40 bg-card/70 py-3 shadow-sm backdrop-blur-md">
<div
className={`site-content-shell ${SITE_WIDTH_INNER} grid grid-cols-[1fr_auto] items-center gap-y-2 sm:flex sm:justify-between`}
>
<Link href="/" className="flex items-center gap-2">
<TaijiIcon />
<span className="font-medium tracking-wide"></span>
</Link>
<div className="flex items-center justify-self-end gap-2 sm:order-last">
{!loading && authEnabled && loggedIn && (
<Link
href="/history"
className="hidden text-muted-foreground hover:text-foreground sm:inline-flex"
title="测算历史"
>
<History size={18} />
</Link>
)}
<ModeToggle />
{!loading && authEnabled && (
loggedIn ? (
<Button
variant="ghost"
size="sm"
className="h-9 gap-1 px-2 text-xs"
onClick={() => logout()}
>
<LogOut size={16} />
<span className="hidden sm:inline">{username ?? "退出"}</span>
</Button>
) : (
<Link href="/login">
<Button variant="ghost" size="sm" className="h-9 gap-1 px-2 text-xs">
<LogIn size={16} />
<span className="hidden sm:inline"></span>
</Button>
</Link>
)
)}
</div>
<nav className="col-span-2 flex flex-wrap items-center justify-center gap-x-4 gap-y-1 sm:order-none sm:col-span-1 sm:flex-1">
{NAV_ITEMS.map((item) => (
<NavLink
key={item.href}
{...item}
needLogin={item.protected && authEnabled && !loggedIn}
/>
))}
{!loading && authEnabled && loggedIn && (
<Link
href="/history"
className="whitespace-nowrap text-sm text-muted-foreground hover:text-foreground sm:hidden"
>
</Link>
)}
</nav>
</div>
</header>
);
}