Add login gate, calculation history, and AI markdown download.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+66
-9
@@ -1,27 +1,41 @@
|
||||
"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: "易经学习" },
|
||||
{ href: "/liuyao", label: "六爻算卦" },
|
||||
{ href: "/bazi", label: "生辰八字" },
|
||||
{ href: "/combined", label: "综合测算" },
|
||||
];
|
||||
{ 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 }: { href: string; label: string }) {
|
||||
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={href}
|
||||
href={target}
|
||||
className={`whitespace-nowrap text-sm transition-colors ${
|
||||
active
|
||||
? "font-medium text-foreground"
|
||||
@@ -34,6 +48,8 @@ function NavLink({ href, label }: { href: string; label: string }) {
|
||||
}
|
||||
|
||||
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
|
||||
@@ -43,13 +59,54 @@ export default function Header() {
|
||||
<TaijiIcon />
|
||||
<span className="font-medium tracking-wide">知命阁</span>
|
||||
</Link>
|
||||
<div className="justify-self-end sm:order-last">
|
||||
<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} />
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user