From ef4c533ebacc2cdc97e518f30e9a9350004fcdfb Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 28 Apr 2025 02:13:30 +0000 Subject: ~20250428 작업사항 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/login/login-form copy 2.tsx | 470 +++++++++++++++++++++++++++++++++ components/login/login-form copy.tsx | 468 ++++++++++++++++++++++++++++++++ components/login/login-form-shi.tsx | 34 ++- components/login/login-form.tsx | 67 ++++- components/login/partner-auth-form.tsx | 128 +++++++-- 5 files changed, 1125 insertions(+), 42 deletions(-) create mode 100644 components/login/login-form copy 2.tsx create mode 100644 components/login/login-form copy.tsx (limited to 'components/login') diff --git a/components/login/login-form copy 2.tsx b/components/login/login-form copy 2.tsx new file mode 100644 index 00000000..d5ac01b9 --- /dev/null +++ b/components/login/login-form copy 2.tsx @@ -0,0 +1,470 @@ +'use client'; + +import { useState, useEffect } from "react"; +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { Card, CardContent } from "@/components/ui/card" +import { Input } from "@/components/ui/input" +import { SendIcon, Loader2, GlobeIcon, ChevronDownIcon, Ship, InfoIcon, ArrowRight } from "lucide-react"; +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 { + InputOTP, + InputOTPGroup, + InputOTPSlot, +} from "@/components/ui/input-otp" +import { signIn } 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'; +import { + Alert, + AlertDescription, + AlertTitle, +} from "@/components/ui/alert"; + +export function LoginForm({ + className, + ...props +}: React.ComponentProps<"div">) { + + const params = useParams() || {}; + const pathname = usePathname() || ''; + const router = useRouter(); + const searchParams = useSearchParams(); + const token = searchParams?.get('token') || null; + const [showCredentialsForm, setShowCredentialsForm] = useState(false); + // 새로운 상태: 업체 등록 안내 표시 여부 + const [showVendorRegistrationInfo, setShowVendorRegistrationInfo] = useState(false); + + const lng = params.lng as string; + const { t, i18n } = useTranslation(lng, 'login'); + + const { toast } = useToast(); + + const handleChangeLanguage = (lang: string) => { + const segments = pathname.split('/'); + segments[1] = lang; + router.push(segments.join('/')); + }; + + const currentLanguageText = i18n.language === 'ko' ? t('languages.korean') : t('languages.english'); + + const [email, setEmail] = useState(''); + const [otpSent, setOtpSent] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [otp, setOtp] = useState(''); + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + + // 업체 등록 페이지로 이동하는 함수 + const goToVendorRegistration = () => { + router.push(`/${lng}/partners/repository`); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsLoading(true); + try { + const result = await sendOtpAction(email, lng); + + if (result.success) { + setOtpSent(true); + toast({ + title: t('otpSentTitle'), + description: t('otpSentMessage'), + }); + } else { + // Handle specific error types + let errorMessage = t('defaultErrorMessage'); + + // 업체 미등록 사용자 에러 처리 + if (result.error === 'userNotFound' || result.error === 'vendorNotRegistered') { + setShowVendorRegistrationInfo(true); + errorMessage = t('vendorNotRegistered') || '등록된 업체가 아닙니다. 먼저 업체 등록 신청을 해주세요.'; + } + + 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('networkErrorMessage'), + variant: 'destructive', + }); + } finally { + setIsLoading(false); + } + }; + + async function handleOtpSubmit(e: React.FormEvent) { + e.preventDefault(); + setIsLoading(true); + + try { + // next-auth의 Credentials Provider로 로그인 시도 + const result = await signIn('credentials', { + email, + code: otp, + redirect: false, // 커스텀 처리 위해 redirect: false + }); + + if (result?.ok) { + // 토스트 메시지 표시 + toast({ + title: t('loginSuccess'), + description: t('youAreLoggedIn'), + }); + + router.push(`/${lng}/partners/dashboard`); + } else { + // 로그인 실패 시 에러 메시지에 업체 등록 관련 정보 포함 + if (result?.error === 'vendorNotRegistered') { + setShowVendorRegistrationInfo(true); + toast({ + title: t('errorTitle'), + description: t('vendorNotRegistered') || '등록된 업체가 아닙니다. 먼저 업체 등록 신청을 해주세요.', + variant: 'destructive', + }); + } else { + toast({ + title: t('errorTitle'), + description: t('defaultErrorMessage'), + variant: 'destructive', + }); + } + } + } catch (error) { + console.error('Login error:', error); + toast({ + title: t('errorTitle'), + description: t('defaultErrorMessage'), + variant: 'destructive', + }); + } finally { + setIsLoading(false); + } + } + + // 새로운 로그인 처리 함수 추가 + 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 { + // 로그인 실패 시 업체 등록 관련 정보 표시 여부 결정 + if (result?.error === 'vendorNotRegistered') { + setShowVendorRegistrationInfo(true); + toast({ + title: t('errorTitle'), + description: t('vendorNotRegistered') || '등록된 업체가 아닙니다. 먼저 업체 등록 신청을 해주세요.', + variant: 'destructive', + }); + } 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; + setIsLoading(true); + + try { + const data = await verifyTokenAction(token); + + if (data.valid) { + setOtpSent(true); + setEmail(data.email ?? ''); + } else { + toast({ + title: t('errorTitle'), + description: t('invalidToken'), + variant: 'destructive', + }); + } + } catch (error) { + toast({ + title: t('errorTitle'), + description: t('defaultErrorMessage'), + variant: 'destructive', + }); + } finally { + setIsLoading(false); + } + }; + verifyToken(); + }, [token, toast, t]); + + return ( +
+ {/* Left Content */} +
+ {/* Top bar with Logo + eVCP (left) and "Request Vendor Repository" (right) */} +
+
+ + eVCP +
+ + {/* 업체 등록 신청 버튼 - 가시성 향상을 위해 variant 변경 */} + + + {t('registerVendor') || '업체 등록 신청'} + +
+ + {/* Content section that occupies remaining space, centered vertically */} +
+ {/* Your form container */} +
+ {/* 업체 등록 안내 알림 - 특정 상황에서만 표시 */} + {showVendorRegistrationInfo && ( + + + + {t('vendorRegistrationRequired') || '업체 등록이 필요합니다'} + + + {t('vendorRegistrationMessage') || '로그인하시려면 먼저 업체 등록이 필요합니다. 아래 버튼을 클릭하여 등록을 진행해주세요.'} + + + + )} + +
+
+
+

{t('loginMessage')}

+ + {/* 설명 텍스트 추가 - 업체 등록 관련 안내 */} +

+ {t('loginDescription') || '등록된 업체만 로그인하실 수 있습니다. 아직 등록되지 않은 업체라면 상단의 업체 등록 신청 버튼을 이용해주세요.'} +

+
+ + {/* S-chips 로그인 폼이 표시되지 않을 때만 이메일 입력 필드 표시 */} + {!showCredentialsForm && ( + <> +
+ setEmail(e.target.value)} + /> +
+ + + {/* 구분선과 "Or continue with" 섹션 추가 */} +
+
+ +
+
+ + {t('orContinueWith')} + +
+
+ + {/* S-chips 로그인 버튼 */} + + + {/* 업체 등록 안내 링크 추가 */} + + + )} + + {/* ID/비밀번호 로그인 폼 - 버튼 클릭 시에만 표시 */} + {showCredentialsForm && ( + <> +
+ setUsername(e.target.value)} + /> + setPassword(e.target.value)} + /> + + + {/* 뒤로 가기 버튼 */} + + + {/* 업체 등록 안내 링크 추가 */} + +
+ + )} + +
+ + + + + + handleChangeLanguage(value)} + > + + {t('languages.english')} + + + {t('languages.korean')} + + + + +
+
+
+ +
+ {t('termsMessage')} {t('termsOfService')} {t('and')} + {t('privacyPolicy')}. +
+
+
+
+ + {/* Right BG 이미지 영역 - Image 컴포넌트로 수정 */} +
+ {/* Image 컴포넌트로 대체 */} +
+ Background image +
+
+
+

“{t("blockquote")}”

+ {/*
SHI
*/} +
+
+
+
+ ) +} \ No newline at end of file diff --git a/components/login/login-form copy.tsx b/components/login/login-form copy.tsx new file mode 100644 index 00000000..ef9eba10 --- /dev/null +++ b/components/login/login-form copy.tsx @@ -0,0 +1,468 @@ +'use client'; + +import { useState, useEffect } from "react"; +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { Card, CardContent } from "@/components/ui/card" +import { Input } from "@/components/ui/input" +import { SendIcon, Loader2, GlobeIcon, ChevronDownIcon, Ship, InfoIcon } from "lucide-react"; +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 { + InputOTP, + InputOTPGroup, + InputOTPSlot, +} from "@/components/ui/input-otp" +import { signIn } 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 + +export function LoginForm({ + className, + ...props +}: React.ComponentProps<"div">) { + + const params = useParams() || {}; + const pathname = usePathname() || ''; + 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'); + + const { toast } = useToast(); + + const handleChangeLanguage = (lang: string) => { + const segments = pathname.split('/'); + segments[1] = lang; + router.push(segments.join('/')); + }; + + const currentLanguageText = i18n.language === 'ko' ? t('languages.korean') : t('languages.english'); + + const [email, setEmail] = useState(''); + const [otpSent, setOtpSent] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [otp, setOtp] = useState(''); + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + + const goToVendorRegistration = () => { + router.push(`/${lng}/partners/repository`); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsLoading(true); + try { + const result = await sendOtpAction(email, lng); + + 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('networkErrorMessage'), + variant: 'destructive', + }); + } finally { + setIsLoading(false); + } + }; + + async function handleOtpSubmit(e: React.FormEvent) { + e.preventDefault(); + setIsLoading(true); + + try { + // next-auth의 Credentials Provider로 로그인 시도 + const result = await signIn('credentials', { + email, + code: otp, + redirect: false, // 커스텀 처리 위해 redirect: false + }); + + if (result?.ok) { + // 토스트 메시지 표시 + toast({ + title: t('loginSuccess'), + description: t('youAreLoggedIn'), + }); + + router.push(`/${lng}/partners/dashboard`); + + } else { + toast({ + title: t('errorTitle'), + description: t('defaultErrorMessage'), + variant: 'destructive', + }); + } + } catch (error) { + console.error('Login error:', error); + toast({ + title: t('errorTitle'), + description: t('defaultErrorMessage'), + variant: 'destructive', + }); + } finally { + setIsLoading(false); + } + } + + // 새로운 로그인 처리 함수 추가 + 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; + setIsLoading(true); + + try { + const data = await verifyTokenAction(token); + + if (data.valid) { + setOtpSent(true); + setEmail(data.email ?? ''); + } else { + toast({ + title: t('errorTitle'), + description: t('invalidToken'), + variant: 'destructive', + }); + } + } catch (error) { + toast({ + title: t('errorTitle'), + description: t('defaultErrorMessage'), + variant: 'destructive', + }); + } finally { + setIsLoading(false); + } + }; + verifyToken(); + }, [token, toast, t]); + + return ( +
+ {/* Left Content */} +
+ {/* Top bar with Logo + eVCP (left) and "Request Vendor Repository" (right) */} +
+
+ {/* logo */} + + eVCP +
+ + + {'업체 등록 신청'} + +
+ + {/* Content section that occupies remaining space, centered vertically */} +
+ {/* Your form container */} +
+ + {/* Here's your existing login/OTP forms: */} + {/* {!otpSent ? ( */} + + {/*
*/} + +
+
+

{t('loginMessage')}

+ + {/* 설명 텍스트 추가 - 업체 등록 관련 안내 */} +

+ {'등록된 업체만 로그인하실 수 있습니다. 아직 등록되지 않은 업체라면 상단의 업체 등록 신청 버튼을 이용해주세요.'} +

+
+ + {/* S-Gips 로그인 폼이 표시되지 않을 때만 이메일 입력 필드 표시 */} + {!showCredentialsForm && ( + <> +
+ setEmail(e.target.value)} + /> +
+ + + {/* 구분선과 "Or continue with" 섹션 추가 */} +
+
+ +
+
+ + {t('orContinueWith')} + +
+
+ + {/* S-Gips 로그인 버튼 */} + + + {/* 업체 등록 안내 링크 추가 */} + + + )} + + {/* ID/비밀번호 로그인 폼 - 버튼 클릭 시에만 표시 */} + {showCredentialsForm && ( + <> +
+ setUsername(e.target.value)} + /> + setPassword(e.target.value)} + /> + + + {/* 뒤로 가기 버튼 */} + +
+ + )} + +
+ + + + + + handleChangeLanguage(value)} + > + + {t('languages.english')} + + + {t('languages.korean')} + + + + +
+
+
+ {/* ) : ( +
+
+
+

{t('loginMessage')}

+
+
+ setOtp(value)} + > + + + + + + + + + +
+ +
+ + + + + + handleChangeLanguage(value)} + > + + {t('languages.english')} + + + {t('languages.korean')} + + + + +
+
+
+ )} */} + +
+ {t('termsMessage')} {t('termsOfService')} {t('and')} + {t('privacyPolicy')}. +
+
+
+
+ + {/* Right BG 이미지 영역 - Image 컴포넌트로 수정 */} +
+ {/* Image 컴포넌트로 대체 */} +
+ Background image +
+
+
+

“{t("blockquote")}”

+ {/*
SHI
*/} +
+
+
+
+ ) +} \ No newline at end of file diff --git a/components/login/login-form-shi.tsx b/components/login/login-form-shi.tsx index fb985592..ef39d122 100644 --- a/components/login/login-form-shi.tsx +++ b/components/login/login-form-shi.tsx @@ -110,8 +110,25 @@ export function LoginFormSHI({ title: t('loginSuccess'), description: t('youAreLoggedIn'), }); - - router.push(`/${lng}/evcp/report`); + + 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 (e) { + // 유효하지 않은 URL이면 그대로 사용 (이미 상대 경로일 수 있음) + router.push(callbackUrlParam); + } + } else { + // callbackUrl이 없으면 기본 대시보드로 리다이렉트 + router.push(`/${lng}/evcp/report`); + } } else { toast({ @@ -186,8 +203,10 @@ export function LoginFormSHI({
{/* Here's your existing login/OTP forms: */} - {!otpSent ? ( -
+ {/* {!otpSent ? + ( */} + {/* */} +

{t('loginMessage')}

@@ -232,7 +251,10 @@ export function LoginFormSHI({
- ) : ( + {/* ) + + + : (
@@ -283,7 +305,7 @@ export function LoginFormSHI({
- )} + )} */}
{t('termsMessage')} {t('termsOfService')} {t('and')} diff --git a/components/login/login-form.tsx b/components/login/login-form.tsx index 92fa6e2c..7236c02e 100644 --- a/components/login/login-form.tsx +++ b/components/login/login-form.tsx @@ -5,7 +5,7 @@ import { cn } from "@/lib/utils" import { Button } from "@/components/ui/button" import { Card, CardContent } from "@/components/ui/card" import { Input } from "@/components/ui/input" -import { SendIcon, Loader2, GlobeIcon, ChevronDownIcon, Ship } from "lucide-react"; +import { SendIcon, Loader2, GlobeIcon, ChevronDownIcon, Ship, InfoIcon } from "lucide-react"; import { useToast } from "@/hooks/use-toast"; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem } from "@/components/ui/dropdown-menu" import { useTranslation } from '@/i18n/client' @@ -55,6 +55,10 @@ export function LoginForm({ const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); + const goToVendorRegistration = () => { + router.push(`/${lng}/partners/repository`); + }; + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setIsLoading(true); @@ -114,7 +118,24 @@ export function LoginForm({ description: t('youAreLoggedIn'), }); - router.push(`/${lng}/partners/dashboard`); + 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 (e) { + // 유효하지 않은 URL이면 그대로 사용 (이미 상대 경로일 수 있음) + router.push(callbackUrlParam); + } + } else { + // callbackUrl이 없으면 기본 대시보드로 리다이렉트 + router.push(`/${lng}/partners/dashboard`); + } } else { toast({ @@ -232,7 +253,8 @@ export function LoginForm({ href="/partners/repository" className={cn(buttonVariants({ variant: "ghost" }))} > - Request Vendor Repository + + {'업체 등록 신청'}
@@ -242,14 +264,21 @@ export function LoginForm({
{/* Here's your existing login/OTP forms: */} - {!otpSent ? ( -
+ {/* {!otpSent ? ( */} + + {/* */} +
-
-

{t('loginMessage')}

-
+
+

{t('loginMessage')}

+ + {/* 설명 텍스트 추가 - 업체 등록 관련 안내 */} +

+ {'등록된 업체만 로그인하실 수 있습니다. 아직 등록되지 않은 업체라면 상단의 업체 등록 신청 버튼을 이용해주세요.'} +

+
- {/* S-chips 로그인 폼이 표시되지 않을 때만 이메일 입력 필드 표시 */} + {/* S-Gips 로그인 폼이 표시되지 않을 때만 이메일 입력 필드 표시 */} {!showCredentialsForm && ( <>
@@ -279,15 +308,25 @@ export function LoginForm({
- {/* S-chips 로그인 버튼 */} + {/* S-Gips 로그인 버튼 */} + + {/* 업체 등록 안내 링크 추가 */} + )} @@ -298,7 +337,7 @@ export function LoginForm({ setUsername(e.target.value)} @@ -360,7 +399,7 @@ export function LoginForm({
- ) : ( + {/* ) : (
@@ -411,7 +450,7 @@ export function LoginForm({
- )} + )} */}
{t('termsMessage')} {t('termsOfService')} {t('and')} diff --git a/components/login/partner-auth-form.tsx b/components/login/partner-auth-form.tsx index effd7bd3..ada64d96 100644 --- a/components/login/partner-auth-form.tsx +++ b/components/login/partner-auth-form.tsx @@ -16,11 +16,22 @@ import { DropdownMenuRadioItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" -import { GlobeIcon, ChevronDownIcon, Loader, Ship } from "lucide-react" +import { GlobeIcon, ChevronDownIcon, Loader, Ship, LogIn, InfoIcon, HelpCircle } from "lucide-react" import { languages } from "@/config/language" import { cn } from "@/lib/utils" import { buttonVariants } from "@/components/ui/button" import { siteConfig } from "@/config/site" +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip" +import { + Alert, + AlertDescription, + AlertTitle, +} from "@/components/ui/alert" import { checkJoinPortal } from "@/lib/vendors/service" import Image from "next/image" @@ -30,11 +41,13 @@ interface UserAuthFormProps extends React.HTMLAttributes { } export function CompanyAuthForm({ className, ...props }: UserAuthFormProps) { const [isLoading, setIsLoading] = React.useState(false) + const [showInfoBanner, setShowInfoBanner] = React.useState(true) const router = useRouter() const { toast } = useToast() - const params = useParams() - const pathname = usePathname() + const params = useParams() || {}; + const pathname = usePathname() || ''; + const lng = params.lng as string const { t, i18n } = useTranslation(lng, "login") @@ -51,6 +64,11 @@ export function CompanyAuthForm({ className, ...props }: UserAuthFormProps) { ? t("languages.japanese") : t("languages.english") + // 로그인 페이지로 이동 + const goToLogin = () => { + router.push(`/${lng}/partners`); + } + // --------------------------- // 1) onSubmit -> 서버 액션 호출 // --------------------------- @@ -86,11 +104,26 @@ export function CompanyAuthForm({ className, ...props }: UserAuthFormProps) { // 가입 가능 → signup 페이지 이동 router.push(`/partners/signup?taxID=${taxID}`) } else { + // 이미 등록된 기업인 경우 - 로그인으로 안내하는 토스트와 함께 추가 액션 제공 toast({ variant: "destructive", title: "가입이 진행 중이거나 완료된 회사", description: `${result.data} 에 연락하여 계정 생성 요청을 하시기 바랍니다.`, }) + + // 로그인 액션 버튼이 있는 알림 표시 + setTimeout(() => { + toast({ + title: "이미 등록된 회사이신가요?", + description: "로그인 페이지로 이동하여 계정에 접속하세요.", + action: ( + + ), + }) + }, 1000); } } catch (error: any) { console.error(error) @@ -111,43 +144,80 @@ export function CompanyAuthForm({ className, ...props }: UserAuthFormProps) {
{/* Top bar */} -
+
- {/* logo */} eVCP
- {/* Remove 'absolute right-4 top-4 ...', just use buttonVariants */} + {/* 로그인 버튼 가시성 개선 */} - Login + + {t("login") || "로그인"}
-
+
+ {/* 정보 알림 배너 - 업체 등록과 로그인의 관계 설명 */} + {showInfoBanner && ( + + + + {t("registrationInfoTitle") || "업체 등록 신청 안내"} + + + {t("registrationInfoDescription") || "이미 등록된 업체의 직원이신가요? 상단의 로그인 버튼을 눌러 로그인하세요. 새로운 업체 등록을 원하시면 아래 양식을 작성해주세요."} + + + + )} +

- {t("heading")} + {t("heading") || "업체 등록 신청"}

-

{t("subheading")}

+

+ {t("subheading") || "귀사의 사업자 등록 번호를 입력하여 등록을 시작하세요"} +

-
-
- +
+
+
+ + + + + + + +

+ {t("taxIdTooltip") || "법인/개인사업자 사업자등록번호를 '-' 포함하여 입력해주세요 (예: 123-45-67890)"} +

+
+
+
+
+

+ {t("taxIdHint") || "사업자 등록 번호는 업체 인증에 사용됩니다"} +

+ {/* 로그인 안내 링크 추가 */} +
+ +
+ {/* 언어 선택 Dropdown */}
-- cgit v1.2.3