From 9ceed79cf32c896f8a998399bf1b296506b2cd4a Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Tue, 8 Apr 2025 03:08:19 +0000
Subject: 로그인 및 미들웨어 처리. 구조 변경
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 components/login/login-form.tsx | 201 ++++++++++++++++++++++++++++++++--------
 1 file changed, 162 insertions(+), 39 deletions(-)

(limited to 'components/login/login-form.tsx')

diff --git a/components/login/login-form.tsx b/components/login/login-form.tsx
index 41d232f8..92fa6e2c 100644
--- a/components/login/login-form.tsx
+++ b/components/login/login-form.tsx
@@ -32,7 +32,8 @@ export function LoginForm({
     const router = useRouter();
     const searchParams = useSearchParams();
     const token = searchParams?.get('token') || null;
-    
+    const [showCredentialsForm, setShowCredentialsForm] = useState(false);
+
 
     const lng = params.lng as string;
     const { t, i18n } = useTranslation(lng, 'login');
@@ -51,6 +52,8 @@ export function LoginForm({
     const [otpSent, setOtpSent] = useState(false);
     const [isLoading, setIsLoading] = useState(false);
     const [otp, setOtp] = useState('');
+    const [username, setUsername] = useState('');
+    const [password, setPassword] = useState('');
 
     const handleSubmit = async (e: React.FormEvent) => {
         e.preventDefault();
@@ -58,17 +61,33 @@ export function LoginForm({
         try {
             const result = await sendOtpAction(email, lng);
 
-            if (result?.success) {
+            if (result.success) {
                 setOtpSent(true);
                 toast({
                     title: t('otpSentTitle'),
                     description: t('otpSentMessage'),
                 });
+            } else {
+                // Handle specific error types
+                let errorMessage = t('defaultErrorMessage');
+
+                // You can handle different error types differently
+                if (result.error === 'userNotFound') {
+                    errorMessage = t('userNotFoundMessage');
+                }
+
+                toast({
+                    title: t('errorTitle'),
+                    description: result.message || errorMessage,
+                    variant: 'destructive',
+                });
             }
         } catch (error) {
+            // This will catch network errors or other unexpected issues
+            console.error(error);
             toast({
                 title: t('errorTitle'),
-                description: t('defaultErrorMessage'),
+                description: t('networkErrorMessage'),
                 variant: 'destructive',
             });
         } finally {
@@ -76,11 +95,10 @@ export function LoginForm({
         }
     };
 
-
     async function handleOtpSubmit(e: React.FormEvent) {
         e.preventDefault();
         setIsLoading(true);
-        
+
         try {
             // next-auth의 Credentials Provider로 로그인 시도
             const result = await signIn('credentials', {
@@ -88,30 +106,16 @@ export function LoginForm({
                 code: otp,
                 redirect: false, // 커스텀 처리 위해 redirect: false
             });
-            
+
             if (result?.ok) {
                 // 토스트 메시지 표시
                 toast({
                     title: t('loginSuccess'),
                     description: t('youAreLoggedIn'),
                 });
-                
-                // NextAuth에서 유저 정보 API 호출 (최신 상태 보장)
-                const response = await fetch('/api/auth/session');
-                const session = await response.json();
-                
-                // domain 값에 따라 동적으로 리다이렉션
-                const userDomain = session?.user?.domain;
-                console.log(session)
-                
-                if (userDomain === 'evcp') {
-                    router.push(`/${lng}/evcp/report`);
-                } else if (userDomain === 'partners') {
-                    router.push(`/${lng}/partners/dashboard`);
-                } else {
-                    // 기본 리다이렉션 경로
-                    router.push(`/${lng}/dashboard`);
-                }
+
+                router.push(`/${lng}/partners/dashboard`);
+
             } else {
                 toast({
                     title: t('errorTitle'),
@@ -131,6 +135,53 @@ export function LoginForm({
         }
     }
 
+    // 새로운 로그인 처리 함수 추가
+    const handleCredentialsLogin = async () => {
+        if (!username || !password) {
+            toast({
+                title: t('errorTitle'),
+                description: t('credentialsRequired'),
+                variant: 'destructive',
+            });
+            return;
+        }
+
+        setIsLoading(true);
+
+        try {
+            // next-auth의 다른 credentials provider로 로그인 시도
+            const result = await signIn('credentials-password', {
+                username,
+                password,
+                redirect: false,
+            });
+
+            if (result?.ok) {
+                toast({
+                    title: t('loginSuccess'),
+                    description: t('youAreLoggedIn'),
+                });
+
+                router.push(`/${lng}/partners/dashboard`);
+            } else {
+                toast({
+                    title: t('errorTitle'),
+                    description: t('invalidCredentials'),
+                    variant: 'destructive',
+                });
+            }
+        } catch (error) {
+            console.error('Login error:', error);
+            toast({
+                title: t('errorTitle'),
+                description: t('defaultErrorMessage'),
+                variant: 'destructive',
+            });
+        } finally {
+            setIsLoading(false);
+        }
+    };
+
     useEffect(() => {
         const verifyToken = async () => {
             if (!token) return;
@@ -197,20 +248,92 @@ export function LoginForm({
                                     <div className="flex flex-col items-center text-center">
                                         <h1 className="text-2xl font-bold">{t('loginMessage')}</h1>
                                     </div>
-                                    <div className="grid gap-2">
-                                        <Input
-                                            id="email"
-                                            type="email"
-                                            placeholder={t('email')}
-                                            required
-                                            className="h-10"
-                                            value={email}
-                                            onChange={(e) => setEmail(e.target.value)}
-                                        />
-                                    </div>
-                                    <Button type="submit" className="w-full" variant="samsung" disabled={isLoading}>
-                                        {isLoading ? t('sending') : t('ContinueWithEmail')}
-                                    </Button>
+
+                                    {/* S-chips 로그인 폼이 표시되지 않을 때만 이메일 입력 필드 표시 */}
+                                    {!showCredentialsForm && (
+                                        <>
+                                            <div className="grid gap-2">
+                                                <Input
+                                                    id="email"
+                                                    type="email"
+                                                    placeholder={t('email')}
+                                                    required
+                                                    className="h-10"
+                                                    value={email}
+                                                    onChange={(e) => setEmail(e.target.value)}
+                                                />
+                                            </div>
+                                            <Button type="submit" className="w-full" variant="samsung" disabled={isLoading}>
+                                                {isLoading ? t('sending') : t('ContinueWithEmail')}
+                                            </Button>
+
+                                            {/* 구분선과 "Or continue with" 섹션 추가 */}
+                                            <div className="relative">
+                                                <div className="absolute inset-0 flex items-center">
+                                                    <span className="w-full border-t"></span>
+                                                </div>
+                                                <div className="relative flex justify-center text-xs uppercase">
+                                                    <span className="bg-background px-2 text-muted-foreground">
+                                                        {t('orContinueWith')}
+                                                    </span>
+                                                </div>
+                                            </div>
+
+                                            {/* S-chips 로그인 버튼 */}
+                                            <Button
+                                                type="button"
+                                                className="w-full"
+                                                // variant=""
+                                                onClick={() => setShowCredentialsForm(true)}
+                                            >
+                                                S-chips로 로그인하기
+                                            </Button>
+                                        </>
+                                    )}
+
+                                    {/* ID/비밀번호 로그인 폼 - 버튼 클릭 시에만 표시 */}
+                                    {showCredentialsForm && (
+                                        <>
+                                            <div className="grid gap-4">
+                                                <Input
+                                                    id="username"
+                                                    type="text"
+                                                    placeholder="S-chips ID"
+                                                    className="h-10"
+                                                    value={username}
+                                                    onChange={(e) => setUsername(e.target.value)}
+                                                />
+                                                <Input
+                                                    id="password"
+                                                    type="password"
+                                                    placeholder="비밀번호"
+                                                    className="h-10"
+                                                    value={password}
+                                                    onChange={(e) => setPassword(e.target.value)}
+                                                />
+                                                <Button
+                                                    type="button"
+                                                    className="w-full"
+                                                    variant="samsung"
+                                                    onClick={handleCredentialsLogin}
+                                                    disabled={isLoading}
+                                                >
+                                                    {isLoading ? "로그인 중..." : "로그인"}
+                                                </Button>
+
+                                                {/* 뒤로 가기 버튼 */}
+                                                <Button
+                                                    type="button"
+                                                    variant="ghost"
+                                                    className="w-full text-sm"
+                                                    onClick={() => setShowCredentialsForm(false)}
+                                                >
+                                                    이메일로 로그인하기
+                                                </Button>
+                                            </div>
+                                        </>
+                                    )}
+
                                     <div className="text-center text-sm mx-auto">
                                         <DropdownMenu>
                                             <DropdownMenuTrigger asChild>
@@ -302,8 +425,8 @@ export function LoginForm({
             <div className="relative hidden h-full flex-col p-10 text-white dark:border-r md:flex">
                 {/* Image 컴포넌트로 대체 */}
                 <div className="absolute inset-0">
-                    <Image 
-                        src="/images/02.jpg" 
+                    <Image
+                        src="/images/02.jpg"
                         alt="Background image"
                         fill
                         priority
-- 
cgit v1.2.3

