/products (search), product pages with revisions, getting and staying on a revision, retracting; /products/:id/edit; /create and new revisions upload from the browser straight to the catalog with a token from the hub; /library; /catalogs (directory, registering with a once-shown key); /console/catalogs to approve or reject. Every page now sends a nonce-based CSP (proxy.ts), so product descriptions can't run scripts. buttonVariants now merges classes, so outline links get their border. Co-Authored-By: Claude Opus 5.5 <[email protected]>
57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
import Link from "next/link";
|
|
import { getMe, isModerator } from "@/lib/api";
|
|
import { buttonVariants } from "@/components/ui/button";
|
|
import { NavLink, SignOutButton } from "./header-client";
|
|
|
|
export function Logo() {
|
|
return (
|
|
<span
|
|
className="grid size-7 place-items-center rounded-md bg-foreground text-[11px] font-bold tracking-tight text-background"
|
|
aria-hidden
|
|
>
|
|
T5
|
|
</span>
|
|
);
|
|
}
|
|
|
|
export async function Header() {
|
|
const me = await getMe();
|
|
return (
|
|
<header className="border-b">
|
|
<div className="mx-auto flex max-w-5xl flex-wrap items-center gap-x-6 gap-y-2 px-4 py-3 sm:px-6">
|
|
<Link href="/" className="flex items-center gap-2 font-semibold">
|
|
<Logo />
|
|
T5DE Hub
|
|
</Link>
|
|
<nav className="order-last flex w-full flex-wrap items-center gap-1 text-sm sm:order-none sm:w-auto">
|
|
<NavLink href="/online">Online</NavLink>
|
|
<NavLink href="/rooms">Rooms</NavLink>
|
|
<NavLink href="/products">Products</NavLink>
|
|
<NavLink href="/catalogs">Catalogs</NavLink>
|
|
{me && <NavLink href="/library">Library</NavLink>}
|
|
{me && <NavLink href="/create">Create</NavLink>}
|
|
{me && <NavLink href="/account">Account</NavLink>}
|
|
{isModerator(me) && <NavLink href="/console">Console</NavLink>}
|
|
</nav>
|
|
<div className="ml-auto flex items-center gap-2 text-sm">
|
|
{me ? (
|
|
<>
|
|
<span className="hidden text-muted-foreground sm:inline">{me.username}</span>
|
|
<SignOutButton />
|
|
</>
|
|
) : (
|
|
<>
|
|
<Link href="/signin" className={buttonVariants({ variant: "ghost" })}>
|
|
Sign in
|
|
</Link>
|
|
<Link href="/signup" className={buttonVariants()}>
|
|
Create account
|
|
</Link>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|