import { cache } from "react";
import Link from "next/link";
import { listReposForUser } from "@/lib/repos";
import { SIGNUPS_ENABLED } from "@/lib/signups";
import type { Theme } from "@/lib/theme";
import type { User } from "@/lib/users";
import { BRAND, Logo, LogoMark } from "./brand";
import { PlusIcon } from "./icons";
import { NavLinks } from "./nav-links";
import { SearchBox } from "./search-box";
import { AppSidebar, MobileNav } from "./sidebar-nav";
import { ButtonLink } from "./ui";
// The sidebar and the search box both list them; one query per request.
const sidebarRepos = cache(async (viewerId: string) =>
(await listReposForUser(viewerId)).map((r) => ({ owner: r.owner, name: r.name, imageVersion: r.imageVersion })),
);
const viewerOf = (viewer: User) => ({ username: viewer.username, name: viewer.name });
/** Left rail for signed-in users: account menu, places and repository shortcuts. */
export async function SiteSidebar({ viewer, theme }: { viewer: User; theme: Theme }) {
return <AppSidebar viewer={viewerOf(viewer)} repos={await sidebarRepos(viewer.id)} theme={theme} />;
}
/** Thin bar above the sheet for signed-in users. On small screens it also carries the navigation. */
export async function TopBar({ viewer }: { viewer: User }) {
return (
<header className="flex h-14 shrink-0 items-center gap-2 px-3 lg:pl-1">
<div className="flex items-center gap-2 lg:hidden">
<MobileNav viewer={viewerOf(viewer)} />
<Link href="/" aria-label={`${BRAND.name} home`} className="rounded-lg transition hover:opacity-80">
<LogoMark size={22} />
</Link>
</div>
<div className="ml-auto flex items-center gap-2.5">
<SearchBox repos={await sidebarRepos(viewer.id)} signedIn />
<ButtonLink href="/new" variant="primary" icon={<PlusIcon />}>
New
</ButtonLink>
</div>
</header>
);
}
/** Header for signed-out visitors. */
export function SiteHeader() {
return (
<header className="flex h-14 shrink-0 items-center gap-3 px-3 md:px-4">
<Link href="/" aria-label={`${BRAND.name} home`} className="rounded-lg transition hover:opacity-80">
<Logo size={22} />
</Link>
<div className="ml-auto flex items-center gap-2">
<SearchBox />
<NavLinks links={[{ href: "/explore", label: "Explore" }]} />
<ButtonLink href="/login" variant="invisible">
Sign In
</ButtonLink>
{SIGNUPS_ENABLED && (
<ButtonLink href="/signup" variant="primary">
Create Account
</ButtonLink>
)}
</div>
</header>
);
}