Files
career-ops-vbleroy/web/src/components/app-shell.tsx
T
redlineo d295c7f139
Release Please / release-please (push) Failing after 4m2s
Web CI / web typecheck + build (push) Successful in 3m39s
CodeQL Analysis / Analyze (javascript-typescript) (push) Failing after 1h1m49s
CodeQL Analysis / Analyze (go) (push) Failing after 1h1m49s
init
2026-07-13 10:14:00 +03:00

84 lines
3.3 KiB
TypeScript

"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { cn } from "@/lib/cn";
import { CoMark } from "@/components/co-mark";
import { AssistantConsole } from "@/components/assistant-console";
import { MobileNav } from "@/components/mobile-nav";
import { ThemeToggle } from "@/components/theme-toggle";
import { JobsProvider } from "@/components/jobs/job-store";
import { PipelineProvider } from "@/components/pipeline/pipeline-provider";
import { ApplyProvider } from "@/components/apply/apply-provider";
import { ExploreProvider } from "@/components/explore/explore-provider";
import { FirstScoreView } from "@/components/explore/first-score-view";
import { BetaBanner } from "@/components/beta/beta-banner";
import { WorkerPills } from "@/components/jobs/worker-pills";
import { UsageMeter } from "@/components/usage-meter";
import { instrumentSerif } from "@/lib/fonts";
import { NAV_ITEMS, isActivePath } from "@/lib/nav-items";
export function AppShell({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
return (
<JobsProvider>
<PipelineProvider>
<ApplyProvider>
<ExploreProvider>
<MobileNav />
<div className="flex min-h-screen">
<aside className="sticky top-0 hidden h-screen w-60 shrink-0 flex-col overflow-y-auto border-r border-border bg-surface/30 p-4 md:flex">
<Link href="/" className="mb-8 flex items-center gap-2.5 px-1">
<CoMark size={32} />
<span className={`${instrumentSerif.className} relative -top-px text-2xl font-normal tracking-tight text-landing`}>
career-ops
</span>
</Link>
<nav className="flex flex-col gap-1">
{NAV_ITEMS.map(({ href, label, icon: Icon, chip }) => {
const active = isActivePath(href, pathname);
return (
<Link
key={href}
href={href}
className={cn(
"flex items-center gap-3 rounded-md px-3 py-2 text-sm transition-colors",
active
? "bg-brand-soft text-brand"
: "text-muted hover:bg-surface-hover hover:text-foreground",
)}
>
<Icon className="size-4" />
{label}
{chip && (
<span className="ml-auto rounded-full border border-brand/30 bg-brand-soft px-1.5 py-0.5 text-[9px] font-bold uppercase tracking-wide text-brand">
{chip}
</span>
)}
</Link>
);
})}
</nav>
<WorkerPills />
<div className="mt-auto space-y-3 pt-4">
<UsageMeter />
<div className="flex items-center justify-between px-1">
<span className={`${instrumentSerif.className} text-sm text-faint`}>local-first · v0</span>
<ThemeToggle />
</div>
</div>
</aside>
<main className="flex-1 overflow-x-hidden">{children}</main>
<AssistantConsole />
<FirstScoreView />
<BetaBanner />
</div>
</ExploreProvider>
</ApplyProvider>
</PipelineProvider>
</JobsProvider>
);
}