61 lines
1.6 KiB
TypeScript
61 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { type ReactNode, useEffect, useState } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import { GraphQLProvider } from "@/providers/graphql-provider";
|
|
import { AuthProvider, useAuth } from "@/providers/auth-provider";
|
|
import { ToastProvider } from "@/providers/toast-provider";
|
|
import { AdminShell } from "@/components/admin-shell";
|
|
import { MswInitializer } from "@/components/msw-initializer";
|
|
import { WebVitalsInitializer } from "@/components/web-vitals-initializer";
|
|
|
|
function AuthGuard({ children }: { children: ReactNode }) {
|
|
const { isAuthenticated, isLoading } = useAuth();
|
|
const router = useRouter();
|
|
|
|
useEffect(() => {
|
|
if (!isLoading && !isAuthenticated) {
|
|
router.replace("/login");
|
|
}
|
|
}, [isLoading, isAuthenticated, router]);
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
minHeight: "100vh",
|
|
}}
|
|
>
|
|
<p style={{ color: "var(--color-ink-muted)" }}>加载中...</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!isAuthenticated) return null;
|
|
|
|
return <>{children}</>;
|
|
}
|
|
|
|
export default function AdminLayout({ children }: { children: ReactNode }) {
|
|
const [mswReady, setMswReady] = useState(false);
|
|
|
|
return (
|
|
<GraphQLProvider>
|
|
<WebVitalsInitializer />
|
|
<MswInitializer onReady={() => setMswReady(true)} />
|
|
{mswReady && (
|
|
<AuthProvider>
|
|
<ToastProvider>
|
|
<AuthGuard>
|
|
<AdminShell>{children}</AdminShell>
|
|
</AuthGuard>
|
|
</ToastProvider>
|
|
</AuthProvider>
|
|
)}
|
|
</GraphQLProvider>
|
|
);
|
|
}
|