ERP-node/frontend/components/auth/AuthGuard.tsx

112 lines
2.8 KiB
TypeScript
Raw Normal View History

2025-08-21 09:41:46 +09:00
"use client";
import { useEffect, ReactNode } from "react";
2025-08-21 09:41:46 +09:00
import { useRouter } from "next/navigation";
import { useAuth } from "@/hooks/useAuth";
import { Loader2 } from "lucide-react";
2025-08-21 09:41:46 +09:00
interface AuthGuardProps {
children: ReactNode;
requireAuth?: boolean;
requireAdmin?: boolean;
redirectTo?: string;
fallback?: ReactNode;
}
/**
*
*
* - /401 client.ts
* -
2025-08-21 09:41:46 +09:00
*/
export function AuthGuard({
children,
requireAuth = true,
requireAdmin = false,
redirectTo = "/login",
fallback,
}: AuthGuardProps) {
const { isLoggedIn, isAdmin, loading } = useAuth();
2025-08-21 09:41:46 +09:00
const router = useRouter();
useEffect(() => {
if (loading) return;
// 토큰이 있는데 아직 인증 확인 중이면 대기
if (typeof window !== "undefined") {
const token = localStorage.getItem("authToken");
if (token && !isLoggedIn && !loading) {
return;
}
}
2025-08-21 09:41:46 +09:00
if (requireAuth && !isLoggedIn) {
router.push(redirectTo);
2025-08-21 09:41:46 +09:00
return;
}
if (requireAdmin && !isAdmin) {
router.push(redirectTo);
2025-08-21 09:41:46 +09:00
return;
}
}, [requireAuth, requireAdmin, loading, isLoggedIn, isAdmin, redirectTo, router]);
2025-08-21 09:41:46 +09:00
if (loading) {
return (
fallback || (
<div className="flex h-screen items-center justify-center">
<div className="flex flex-col items-center gap-3">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
<p className="text-sm text-muted-foreground"> ...</p>
</div>
2025-08-21 09:41:46 +09:00
</div>
)
2025-08-21 09:41:46 +09:00
);
}
if (requireAuth && !isLoggedIn) {
2025-08-21 09:41:46 +09:00
return (
fallback || (
<div className="flex h-screen items-center justify-center">
<div className="flex flex-col items-center gap-3">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
<p className="text-sm text-muted-foreground"> ...</p>
</div>
2025-08-21 09:41:46 +09:00
</div>
)
2025-08-21 09:41:46 +09:00
);
}
if (requireAdmin && !isAdmin) {
return (
fallback || (
<div className="flex h-screen items-center justify-center">
<p className="text-sm text-muted-foreground"> .</p>
2025-08-21 09:41:46 +09:00
</div>
)
2025-08-21 09:41:46 +09:00
);
}
return <>{children}</>;
}
/**
*
*/
export function RequireAuth({ children }: { children: ReactNode }) {
return <AuthGuard requireAuth={true}>{children}</AuthGuard>;
}
/**
*
*/
export function RequireAdmin({ children }: { children: ReactNode }) {
return (
<AuthGuard requireAuth={true} requireAdmin={true}>
{children}
</AuthGuard>
);
}
export default AuthGuard;