'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'), }); 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({ 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 (
*/}
“{t("blockquote")}”
{/* */}