From bed369de9e206d56489c5691560909fb133d5624 Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Sun, 2 Nov 2025 15:06:16 +0900 Subject: (김준회) login-form 리팩터링 (S-GIPS 제거) 및 배경 영상으로 변경 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/login/login-form.tsx | 393 ++++----------------- public/background-videos/1.yard.mp4 | Bin 0 -> 4890582 bytes public/background-videos/2.SN2635_LNGC_CARDIFF.mp4 | Bin 0 -> 3161018 bytes public/background-videos/3.SN2628_CONT_WAN HAI.mp4 | Bin 0 -> 2447830 bytes public/background-videos/4.SN2612_LNGC_KGL.mp4 | Bin 0 -> 3070863 bytes .../background-videos/5.SN2596_LNGC_JP MORGAN.mp4 | Bin 0 -> 4426638 bytes public/background-videos/6.2235_FLNG_ENI_CORAL.mp4 | Bin 0 -> 3121327 bytes public/background-videos/7.2126_FLNG_PETRONAS.mp4 | Bin 0 -> 3605598 bytes 8 files changed, 71 insertions(+), 322 deletions(-) create mode 100644 public/background-videos/1.yard.mp4 create mode 100644 public/background-videos/2.SN2635_LNGC_CARDIFF.mp4 create mode 100644 public/background-videos/3.SN2628_CONT_WAN HAI.mp4 create mode 100644 public/background-videos/4.SN2612_LNGC_KGL.mp4 create mode 100644 public/background-videos/5.SN2596_LNGC_JP MORGAN.mp4 create mode 100644 public/background-videos/6.2235_FLNG_ENI_CORAL.mp4 create mode 100644 public/background-videos/7.2126_FLNG_PETRONAS.mp4 diff --git a/components/login/login-form.tsx b/components/login/login-form.tsx index bcfa1ec6..51d54531 100644 --- a/components/login/login-form.tsx +++ b/components/login/login-form.tsx @@ -12,7 +12,6 @@ import { useRouter, useParams, usePathname, useSearchParams } from 'next/navigat import { signIn, useSession } from 'next-auth/react'; import { buttonVariants } from "@/components/ui/button" import Link from "next/link" -import Image from 'next/image'; import { useFormState } from 'react-dom'; import { InputOTP, @@ -23,16 +22,16 @@ import { requestPasswordResetAction } from "@/lib/users/auth/partners-auth"; import { checkEmailAndStartAuth, resendEmailOtp } from "@/lib/users/auth/email-auth"; import Loading from "../common/loading/loading"; -type LoginMethod = 'username' | 'sgips'; - -type OtpUser = { - name: string; - vndrcd: string; - phone: string; - email: string; - nation_cd: string; - userId: number; // 백엔드에서 생성된 로컬 DB 사용자 ID -}; +// 배경 영상 목록 +const BACKGROUND_VIDEOS = [ + '/background-videos/1.yard.mp4', + '/background-videos/2.SN2635_LNGC_CARDIFF.mp4', + '/background-videos/3.SN2628_CONT_WAN HAI.mp4', + '/background-videos/4.SN2612_LNGC_KGL.mp4', + '/background-videos/5.SN2596_LNGC_JP MORGAN.mp4', + '/background-videos/6.2235_FLNG_ENI_CORAL.mp4', + '/background-videos/7.2126_FLNG_PETRONAS.mp4', +]; export function LoginForm() { const params = useParams() || {}; @@ -45,8 +44,10 @@ export function LoginForm() { const { toast } = useToast(); const { data: session, status } = useSession(); + // 배경 영상 상태 + const [currentVideoIndex, setCurrentVideoIndex] = useState(0); + // 상태 관리 - const [loginMethod, setLoginMethod] = useState('username'); const [isFirstAuthLoading, setIsFirstAuthLoading] = useState(false); const [showForgotPassword, setShowForgotPassword] = useState(false); @@ -69,15 +70,6 @@ export function LoginForm() { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); - // S-Gips 로그인 폼 데이터 - const [sgipsUsername, setSgipsUsername] = useState(''); - const [sgipsPassword, setSgipsPassword] = useState(''); - - // OTP 사용자 선택 관련 상태 - const [otpUsers, setOtpUsers] = useState([]); - const [showUserSelectionDialog, setShowUserSelectionDialog] = useState(false); - const [selectedOtpUser, setSelectedOtpUser] = useState(null); - const [isMfaLoading, setIsMfaLoading] = useState(false); const [isSmsLoading, setIsSmsLoading] = useState(false); @@ -91,11 +83,14 @@ export function LoginForm() { // 호스트명 확인 상태 추가 const [isDataRoomHost, setIsDataRoomHost] = useState(false); - // 컴포넌트 마운트 시 호스트명 확인 + // 컴포넌트 마운트 시 호스트명 확인 및 랜덤 비디오 선택 useEffect(() => { if (typeof window !== 'undefined') { const hostname = window.location.hostname; setIsDataRoomHost(hostname.includes('shidataroom')); + + // 랜덤한 비디오 인덱스 선택 + setCurrentVideoIndex(Math.floor(Math.random() * BACKGROUND_VIDEOS.length)); } }, []); @@ -144,7 +139,7 @@ export function LoginForm() { const currentLanguageText = i18n.language === 'ko' ? t('languages.korean') : t('languages.english'); // 세분화된 에러 메시지 처리 함수 - const getErrorMessage = (error: { errorCode?: string; message?: string }, provider: 'email' | 'sgips') => { + const getErrorMessage = (error: { errorCode?: string; message?: string }) => { const errorCode = error.errorCode; if (!errorCode) { @@ -153,7 +148,7 @@ export function LoginForm() { switch (errorCode) { case 'INVALID_CREDENTIALS': - return provider === 'sgips' ? t('sgipsInvalidCredentials') : t('invalidCredentials'); + return t('invalidCredentials'); case 'ACCOUNT_LOCKED': return t('accountLocked'); case 'ACCOUNT_DEACTIVATED': @@ -173,6 +168,11 @@ export function LoginForm() { router.push(`/${lng}/partners/repository`); }; + // 비디오 종료 시 다음 비디오로 전환 + const handleVideoEnd = () => { + setCurrentVideoIndex((prevIndex) => (prevIndex + 1) % BACKGROUND_VIDEOS.length); + }; + // MFA 카운트다운 효과 useEffect(() => { if (mfaCountdown > 0) { @@ -234,13 +234,7 @@ export function LoginForm() { setIsSmsLoading(true); try { - const requestBody: { userId: number; phone?: string; name?: string } = { userId: targetUserId }; - - // S-GIPS 사용자인 경우 추가 정보 포함 - if (selectedOtpUser) { - requestBody.phone = selectedOtpUser.phone; - requestBody.name = selectedOtpUser.name; - } + const requestBody: { userId: number } = { userId: targetUserId }; const response = await fetch('/api/auth/send-sms', { method: 'POST', @@ -250,17 +244,10 @@ export function LoginForm() { if (response.ok) { setMfaCountdown(60); - if (selectedOtpUser) { - toast({ - title: t('smsSent'), - description: t('smsCodeSentTo', { name: selectedOtpUser.name, phone: selectedOtpUser.phone }), - }); - } else { - toast({ - title: t('smsSent'), - description: t('smsCodeSent'), - }); - } + toast({ + title: t('smsSent'), + description: t('smsCodeSent'), + }); } else { const errorData = await response.json(); toast({ @@ -428,8 +415,7 @@ export function LoginForm() { if (!result.success) { const errorMessage = getErrorMessage( - { errorCode: result.errorCode, message: result.error }, - 'email' + { errorCode: result.errorCode, message: result.error } ); toast({ @@ -526,8 +512,7 @@ export function LoginForm() { console.error('Password submit error:', error); const errorMessage = getErrorMessage( - error as { errorCode?: string; message?: string }, - 'email' + error as { errorCode?: string; message?: string } ); toast({ @@ -540,124 +525,6 @@ export function LoginForm() { } }; - // S-Gips 1차 인증 처리 - const handleSgipsLogin = async (e: React.FormEvent) => { - e.preventDefault(); - - if (!sgipsUsername || !sgipsPassword) { - toast({ - title: t('errorTitle'), - description: t('credentialsRequired'), - variant: 'destructive', - }); - return; - } - - setIsFirstAuthLoading(true); - - try { - // S-Gips 1차 인증만 수행 (세션 생성 안함) - const authResult = await performFirstAuth(sgipsUsername, sgipsPassword, 'sgips'); - - if (authResult.success) { - const users = authResult.otpUsers || []; - - if (users.length === 0) { - toast({ - title: t('errorTitle'), - description: t('noUsersFound'), - variant: 'destructive', - }); - return; - } - - // 사용자 선택 다이얼로그 표시 (항상) - setOtpUsers(users); - setShowUserSelectionDialog(true); - } - } catch (error: unknown) { - console.error('S-Gips login error:', error); - - const errorMessage = getErrorMessage(error as { errorCode?: string; message?: string }, 'sgips'); - - toast({ - title: t('errorTitle'), - description: errorMessage, - variant: 'destructive', - }); - } finally { - setIsFirstAuthLoading(false); - } - }; - - // 선택된 OTP 사용자와 함께 MFA 진행 - const proceedWithSelectedUser = async (user: OtpUser, tempAuthKey: string) => { - try { - - // 사용자 정보를 기반으로 MFA 진행 - setTempAuthKey(tempAuthKey); - setSelectedOtpUser(user); - setMfaUserId(user.userId); // 선택된 사용자의 userId 설정 - setMfaUserEmail(user.email); - setShowMfaForm(true); - - // 선택된 사용자의 userId를 직접 전달하여 SMS 전송 - setTimeout(() => { - handleSendSms(user.userId); - }, 2000); - - toast({ - title: t('sgipsAuthComplete'), - description: t('sendingCodeToSelectedUser', { name: user.name }), - }); - } catch (error) { - console.error('Proceeding with selected user error:', error); - toast({ - title: t('errorTitle'), - description: t('mfaSetupError'), - variant: 'destructive', - }); - } - }; - - // OTP 사용자 선택 처리 - const handleUserSelection = async (user: OtpUser) => { - setShowUserSelectionDialog(false); - - try { - // 선택된 사용자에 대한 임시 인증 세션 생성 요청 - const response = await fetch('/api/auth/select-sgips-user', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - userId: user.userId, - email: user.email, - name: user.name - }), - }); - - const result = await response.json(); - - if (!response.ok || !result.success) { - toast({ - title: t('errorTitle'), - description: result.error || t('mfaSetupError'), - variant: 'destructive', - }); - return; - } - - // 임시 인증 세션 생성 성공, MFA 진행 - await proceedWithSelectedUser(user, result.tempAuthKey); - } catch (error) { - console.error('User selection error:', error); - toast({ - title: t('errorTitle'), - description: t('mfaSetupError'), - variant: 'destructive', - }); - } - }; // MFA 화면 또는 패스워드 입력에서 뒤로 가기 const handleBackToLogin = () => { @@ -692,11 +559,6 @@ export function LoginForm() { setPassword(''); setUsername(''); } - - // S-Gips 관련 초기화 - setSelectedOtpUser(null); - setShowUserSelectionDialog(false); - setOtpUsers([]); }; // 세션 로딩 중이거나 이미 인증된 상태에서는 로딩 표시 @@ -758,11 +620,9 @@ export function LoginForm() { {mfaType === 'email' ? t('emailVerification') : t('smsVerification')}

- {selectedOtpUser - ? t('firstAuthCompleteForSgips', { name: selectedOtpUser.name, email: mfaUserEmail }) - : mfaType === 'email' - ? t('emailOtpSentTo', { email: mfaUserEmail }) - : t('firstAuthCompleteFor', { email: mfaUserEmail }) + {mfaType === 'email' + ? t('emailOtpSentTo', { email: mfaUserEmail }) + : t('firstAuthCompleteFor', { email: mfaUserEmail }) }

@@ -777,42 +637,10 @@ export function LoginForm() { {/* 로그인 폼 또는 MFA 폼 */} {!showMfaForm ? ( <> - {/* Login Method Tabs */} -

- - {/* S-Gips 로그인은 영문 페이지에서 비활성화 0925 구매 요청사항*/} - {lng !== 'en' && ( - - )} -
- - {/* Username Login Form */} - {loginMethod === 'username' && ( - <> - {!showPasswordInput ? ( - // 1단계: 이메일만 입력 + {/* Login Form */} + <> + {!showPasswordInput ? ( + // 1단계: 이메일만 입력
)} - - )} - - {/* S-Gips Login Form - 영문 페이지에서 비활성화 0925 구매 요청사항*/} - {loginMethod === 'sgips' && lng !== 'en' && ( - -
- setSgipsUsername(e.target.value)} - disabled={isFirstAuthLoading} - /> -
-
- setSgipsPassword(e.target.value)} - disabled={isFirstAuthLoading} - /> -
- -

- {t('sgipsAutoSms')} -

-
- )} + {/* Additional Links */}
@@ -944,7 +730,7 @@ export function LoginForm() { )} {/* 비밀번호 찾기는 패스워드 입력 단계에서만 표시 */} - {loginMethod === 'username' && showPasswordInput && ( + {showPasswordInput && ( -
-
-

- {t('selectUserDescription')} -

- {otpUsers.map((user, index) => ( -
handleUserSelection(user)} - > -
-
-
{user.name}
-
{user.email}
-
{user.phone}
-
Vendor: {user.vndrcd}
-
- -
-
- ))} -
-
- -
- - - )} - {/* 비밀번호 재설정 다이얼로그 */} {showForgotPassword && !showMfaForm && (
@@ -1218,23 +948,42 @@ export function LoginForm() {
- {/* Right BG 이미지 영역 */} -
+ {/* Right BG 영상 영역 */} +
- Background image + + {/* 어두운 오버레이 */} +
-
-

“{t("blockquote")}”

+
+

“{t("blockquote")}”

+ {/* 비디오 인디케이터 */} +
+ {BACKGROUND_VIDEOS.map((_, index) => ( +
setCurrentVideoIndex(index)} + /> + ))} +
) diff --git a/public/background-videos/1.yard.mp4 b/public/background-videos/1.yard.mp4 new file mode 100644 index 00000000..3edf7f8d Binary files /dev/null and b/public/background-videos/1.yard.mp4 differ diff --git a/public/background-videos/2.SN2635_LNGC_CARDIFF.mp4 b/public/background-videos/2.SN2635_LNGC_CARDIFF.mp4 new file mode 100644 index 00000000..2a061a2a Binary files /dev/null and b/public/background-videos/2.SN2635_LNGC_CARDIFF.mp4 differ diff --git a/public/background-videos/3.SN2628_CONT_WAN HAI.mp4 b/public/background-videos/3.SN2628_CONT_WAN HAI.mp4 new file mode 100644 index 00000000..75ecdb61 Binary files /dev/null and b/public/background-videos/3.SN2628_CONT_WAN HAI.mp4 differ diff --git a/public/background-videos/4.SN2612_LNGC_KGL.mp4 b/public/background-videos/4.SN2612_LNGC_KGL.mp4 new file mode 100644 index 00000000..4fbf0a40 Binary files /dev/null and b/public/background-videos/4.SN2612_LNGC_KGL.mp4 differ diff --git a/public/background-videos/5.SN2596_LNGC_JP MORGAN.mp4 b/public/background-videos/5.SN2596_LNGC_JP MORGAN.mp4 new file mode 100644 index 00000000..044d420f Binary files /dev/null and b/public/background-videos/5.SN2596_LNGC_JP MORGAN.mp4 differ diff --git a/public/background-videos/6.2235_FLNG_ENI_CORAL.mp4 b/public/background-videos/6.2235_FLNG_ENI_CORAL.mp4 new file mode 100644 index 00000000..65f813be Binary files /dev/null and b/public/background-videos/6.2235_FLNG_ENI_CORAL.mp4 differ diff --git a/public/background-videos/7.2126_FLNG_PETRONAS.mp4 b/public/background-videos/7.2126_FLNG_PETRONAS.mp4 new file mode 100644 index 00000000..f5bf0d2c Binary files /dev/null and b/public/background-videos/7.2126_FLNG_PETRONAS.mp4 differ -- cgit v1.2.3