- Introduced new components for BOM tree view and BOM item editor, enhancing the data management capabilities within the application. - Updated the ComponentsPanel to include these new components with appropriate descriptions and default sizes. - Integrated the BOM item editor into the V2PropertiesPanel for seamless editing of BOM items. - Adjusted the SplitLineComponent to improve the handling of canvas split positions, ensuring better user experience during component interactions.
112 lines
2.8 KiB
TypeScript
112 lines
2.8 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, ReactNode } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import { useAuth } from "@/hooks/useAuth";
|
|
import { Loader2 } from "lucide-react";
|
|
|
|
interface AuthGuardProps {
|
|
children: ReactNode;
|
|
requireAuth?: boolean;
|
|
requireAdmin?: boolean;
|
|
redirectTo?: string;
|
|
fallback?: ReactNode;
|
|
}
|
|
|
|
/**
|
|
* 인증 보호 컴포넌트
|
|
* 로그인 상태 및 권한에 따라 접근을 제어
|
|
* - 토큰 갱신/401 처리는 client.ts 인터셉터가 담당
|
|
* - 이 컴포넌트는 인증 상태 기반 라우팅 가드 역할만 수행
|
|
*/
|
|
export function AuthGuard({
|
|
children,
|
|
requireAuth = true,
|
|
requireAdmin = false,
|
|
redirectTo = "/login",
|
|
fallback,
|
|
}: AuthGuardProps) {
|
|
const { isLoggedIn, isAdmin, loading } = useAuth();
|
|
const router = useRouter();
|
|
|
|
useEffect(() => {
|
|
if (loading) return;
|
|
|
|
// 토큰이 있는데 아직 인증 확인 중이면 대기
|
|
if (typeof window !== "undefined") {
|
|
const token = localStorage.getItem("authToken");
|
|
if (token && !isLoggedIn && !loading) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (requireAuth && !isLoggedIn) {
|
|
router.push(redirectTo);
|
|
return;
|
|
}
|
|
|
|
if (requireAdmin && !isAdmin) {
|
|
router.push(redirectTo);
|
|
return;
|
|
}
|
|
}, [requireAuth, requireAdmin, loading, isLoggedIn, isAdmin, redirectTo, router]);
|
|
|
|
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>
|
|
</div>
|
|
)
|
|
);
|
|
}
|
|
|
|
if (requireAuth && !isLoggedIn) {
|
|
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>
|
|
</div>
|
|
)
|
|
);
|
|
}
|
|
|
|
if (requireAdmin && !isAdmin) {
|
|
return (
|
|
fallback || (
|
|
<div className="flex h-screen items-center justify-center">
|
|
<p className="text-sm text-muted-foreground">관리자 권한이 필요합니다.</p>
|
|
</div>
|
|
)
|
|
);
|
|
}
|
|
|
|
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;
|