Fix admin sidebar missing on /curator/* routes
- Extract AdminShell component (sidebar + wrapper) - admin/layout.tsx uses AdminShell - curator/layout.tsx uses AdminShell for admin role (was rendering children only) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,55 +1,12 @@
|
|||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { AdminNav } from "@/components/admin/admin-nav";
|
import { AdminShell } from "@/components/admin/admin-shell";
|
||||||
import { LogoutButton } from "@/components/layout/logout-button";
|
|
||||||
|
|
||||||
export default async function AdminLayout({ children }: { children: React.ReactNode }) {
|
export default async function AdminLayout({ children }: { children: React.ReactNode }) {
|
||||||
const session = await auth.api.getSession({ headers: await headers() });
|
const session = await auth.api.getSession({ headers: await headers() });
|
||||||
if (!session) redirect("/login");
|
if (!session) redirect("/login");
|
||||||
if (session.user.role !== "admin") redirect("/dashboard");
|
if (session.user.role !== "admin") redirect("/dashboard");
|
||||||
|
|
||||||
return (
|
return <AdminShell userName={session.user.name}>{children}</AdminShell>;
|
||||||
<div className="min-h-screen flex">
|
|
||||||
{/* Sidebar */}
|
|
||||||
<aside
|
|
||||||
className="w-52 flex flex-col shrink-0 fixed h-full z-10"
|
|
||||||
style={{ backgroundColor: "var(--sidebar-bg)", color: "var(--sidebar-text)" }}
|
|
||||||
>
|
|
||||||
{/* Logo */}
|
|
||||||
<div
|
|
||||||
className="px-5 py-5"
|
|
||||||
style={{ borderBottom: "2px solid var(--sidebar-border)" }}
|
|
||||||
>
|
|
||||||
<p className="font-bold text-base tracking-wide" style={{ color: "#E8F0D8" }}>
|
|
||||||
Second Brain
|
|
||||||
</p>
|
|
||||||
<p className="text-xs mt-0.5 uppercase tracking-widest" style={{ color: "var(--sidebar-text)", fontSize: "0.6rem" }}>
|
|
||||||
Администратор
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Navigation */}
|
|
||||||
<nav className="flex-1 px-2 py-4 space-y-0.5 overflow-y-auto">
|
|
||||||
<AdminNav />
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* User info */}
|
|
||||||
<div
|
|
||||||
className="px-4 py-4"
|
|
||||||
style={{ borderTop: "2px solid var(--sidebar-border)" }}
|
|
||||||
>
|
|
||||||
<p className="text-xs mb-3 truncate" style={{ color: "var(--sidebar-text)" }}>
|
|
||||||
{session.user.name}
|
|
||||||
</p>
|
|
||||||
<LogoutButton />
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
{/* Main content */}
|
|
||||||
<div className="ml-52 flex-1 min-h-screen" style={{ backgroundColor: "var(--background)" }}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ import { auth } from "@/lib/auth";
|
|||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { LogoutButton } from "@/components/layout/logout-button";
|
import { LogoutButton } from "@/components/layout/logout-button";
|
||||||
|
import { AdminShell } from "@/components/admin/admin-shell";
|
||||||
|
|
||||||
export default async function CuratorLayout({ children }: { children: React.ReactNode }) {
|
export default async function CuratorLayout({ children }: { children: React.ReactNode }) {
|
||||||
const session = await auth.api.getSession({ headers: await headers() });
|
const session = await auth.api.getSession({ headers: await headers() });
|
||||||
if (!session) redirect("/login");
|
if (!session) redirect("/login");
|
||||||
if (session.user.role !== "curator" && session.user.role !== "admin") redirect("/dashboard");
|
if (session.user.role !== "curator" && session.user.role !== "admin") redirect("/dashboard");
|
||||||
|
|
||||||
// Admin uses their own layout — render content only
|
// Admin uses the admin shell with sidebar
|
||||||
if (session.user.role === "admin") {
|
if (session.user.role === "admin") {
|
||||||
return <>{children}</>;
|
return <AdminShell userName={session.user.name}>{children}</AdminShell>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { AdminNav } from "@/components/admin/admin-nav";
|
||||||
|
import { LogoutButton } from "@/components/layout/logout-button";
|
||||||
|
|
||||||
|
export function AdminShell({
|
||||||
|
children,
|
||||||
|
userName,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
userName: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen flex">
|
||||||
|
<aside
|
||||||
|
className="w-52 flex flex-col shrink-0 fixed h-full z-10"
|
||||||
|
style={{ backgroundColor: "var(--sidebar-bg)", color: "var(--sidebar-text)" }}
|
||||||
|
>
|
||||||
|
<div className="px-5 py-5" style={{ borderBottom: "2px solid var(--sidebar-border)" }}>
|
||||||
|
<p className="font-bold text-base tracking-wide" style={{ color: "#E8F0D8" }}>
|
||||||
|
Second Brain
|
||||||
|
</p>
|
||||||
|
<p className="text-xs mt-0.5 uppercase tracking-widest" style={{ color: "var(--sidebar-text)", fontSize: "0.6rem" }}>
|
||||||
|
Администратор
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<nav className="flex-1 px-2 py-4 space-y-0.5 overflow-y-auto">
|
||||||
|
<AdminNav />
|
||||||
|
</nav>
|
||||||
|
<div className="px-4 py-4" style={{ borderTop: "2px solid var(--sidebar-border)" }}>
|
||||||
|
<p className="text-xs mb-3 truncate" style={{ color: "var(--sidebar-text)" }}>
|
||||||
|
{userName}
|
||||||
|
</p>
|
||||||
|
<LogoutButton />
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<div className="ml-52 flex-1 min-h-screen" style={{ backgroundColor: "var(--background)" }}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user