diff options
Diffstat (limited to 'components/login')
| -rw-r--r-- | components/login/login-form-shi.tsx | 32 | ||||
| -rw-r--r-- | components/login/login-form.tsx | 42 |
2 files changed, 72 insertions, 2 deletions
diff --git a/components/login/login-form-shi.tsx b/components/login/login-form-shi.tsx index 862f9f8a..1a554cbc 100644 --- a/components/login/login-form-shi.tsx +++ b/components/login/login-form-shi.tsx @@ -15,13 +15,14 @@ import { InputOTPGroup, InputOTPSlot, } from "@/components/ui/input-otp" -import { signIn } from 'next-auth/react'; +import { signIn, useSession } from 'next-auth/react'; import { sendOtpAction } from "@/lib/users/send-otp"; import { verifyTokenAction } from "@/lib/users/verifyToken"; import { buttonVariants } from "@/components/ui/button" import Link from "next/link" import Image from 'next/image'; // 추가: Image 컴포넌트 import import { KnoxSSOButton } from './saml-login-button'; // SAML 로그인 버튼 import +import Loading from "../common/loading/loading"; export function LoginFormSHI({ className, @@ -39,6 +40,7 @@ export function LoginFormSHI({ const { t, i18n } = useTranslation(lng, 'login'); const { toast } = useToast(); + const { data: session, status } = useSession(); const handleChangeLanguage = (lang: string) => { const segments = pathname.split('/'); @@ -181,6 +183,34 @@ export function LoginFormSHI({ verifyToken(); }, [token, toast, t]); + // 이미 로그인된 사용자 리다이렉트 처리 + useEffect(() => { + if (status === 'authenticated' && session?.user) { + const callbackUrlParam = searchParams?.get('callbackUrl'); + + if (callbackUrlParam) { + try { + const callbackUrl = new URL(callbackUrlParam); + const relativeUrl = callbackUrl.pathname + callbackUrl.search; + router.push(relativeUrl); + } catch { + router.push(callbackUrlParam); + } + } else { + router.push(`/${lng}/evcp/report`); + } + } + }, [status, session, router, lng, searchParams]); + + // 세션 로딩 중이거나 이미 인증된 상태에서는 로딩 표시 + if (status === 'loading') { + return <Loading message={t('loading')} />; + } + + if (status === 'authenticated' && session?.user) { + return <Loading message={t('redirecting')} />; + } + return ( <div className="container relative flex h-screen flex-col items-center justify-center md:grid lg:max-w-none lg:grid-cols-2 lg:px-0"> {/* Left Content */} diff --git a/components/login/login-form.tsx b/components/login/login-form.tsx index 7453edb6..6aca755f 100644 --- a/components/login/login-form.tsx +++ b/components/login/login-form.tsx @@ -9,7 +9,7 @@ import { useToast } from "@/hooks/use-toast"; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem } from "@/components/ui/dropdown-menu" import { useTranslation } from '@/i18n/client' import { useRouter, useParams, usePathname, useSearchParams } from 'next/navigation'; -import { signIn } from 'next-auth/react'; +import { signIn, useSession } from 'next-auth/react'; import { buttonVariants } from "@/components/ui/button" import Link from "next/link" import Image from 'next/image'; @@ -20,6 +20,7 @@ import { InputOTPSlot, } from "@/components/ui/input-otp" import { requestPasswordResetAction } from "@/lib/users/auth/partners-auth"; +import Loading from "../common/loading/loading"; type LoginMethod = 'username' | 'sgips'; @@ -32,6 +33,7 @@ export function LoginForm() { const lng = params.lng as string; const { t, i18n } = useTranslation(lng, 'login'); const { toast } = useToast(); + const { data: session, status } = useSession(); // 상태 관리 const [loginMethod, setLoginMethod] = useState<LoginMethod>('username'); @@ -64,6 +66,30 @@ export function LoginForm() { message: undefined, }); + // 이미 로그인된 사용자 리다이렉트 처리 + useEffect(() => { + if (status === 'authenticated' && session?.user) { + const callbackUrlParam = searchParams?.get('callbackUrl'); + + if (callbackUrlParam) { + try { + // URL 객체로 파싱 + const callbackUrl = new URL(callbackUrlParam); + + // pathname + search만 사용 (호스트 제거) + const relativeUrl = callbackUrl.pathname + callbackUrl.search; + router.push(relativeUrl); + } catch { + // 유효하지 않은 URL이면 그대로 사용 (이미 상대 경로일 수 있음) + router.push(callbackUrlParam); + } + } else { + // callbackUrl이 없으면 기본 대시보드로 리다이렉트 + router.push(`/${lng}/partners/report`); + } + } + }, [status, session, router, lng, searchParams]); + const handleChangeLanguage = (lang: string) => { const segments = pathname.split('/'); segments[1] = lang; @@ -404,6 +430,20 @@ export function LoginForm() { setMfaCountdown(0); }; + // 세션 로딩 중이거나 이미 인증된 상태에서는 로딩 표시 + if (status === 'loading') { + return ( + <Loading message={t('loading')} /> + ); + } + + // 이미 인증된 상태에서는 빈 화면 (리다이렉트 중) + if (status === 'authenticated' && session?.user) { + return ( + <Loading message={t('redirecting')} /> + ); + } + return ( <div className="container relative flex h-screen flex-col items-center justify-center md:grid lg:max-w-none lg:grid-cols-2 lg:px-0"> {/* Left Content */} |
