'use client'; import { useState, useEffect } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import Link from 'next/link'; import { createClient } from '@/lib/supabase/client'; import { Suspense } from 'react'; function LoginForm() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [isSignUp, setIsSignUp] = useState(false); const [loading, setLoading] = useState(false); const [message, setMessage] = useState(''); const router = useRouter(); const searchParams = useSearchParams(); const supabase = createClient(); useEffect(() => { if (searchParams.get('error')) { setMessage('인증 중 오류가 발생했습니다. 다시 시도해주세요.'); } // 이미 로그인된 경우 리다이렉트 supabase.auth.getUser().then(({ data }) => { if (data.user) router.push('/mypage'); }); }, []); const handleAuth = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); setMessage(''); if (isSignUp) { const { data, error } = await supabase.auth.signUp({ email, password, options: { emailRedirectTo: `${window.location.origin}/auth/callback`, }, }); if (error) { setMessage('회원가입 실패: ' + error.message); } else if (data.user?.identities?.length === 0) { setMessage('이미 가입된 이메일입니다. 로그인해주세요.'); setIsSignUp(false); } else { setMessage('가입 완료! 이메일 인증 링크를 확인해주세요.'); } } else { const { error } = await supabase.auth.signInWithPassword({ email, password }); if (error) { setMessage('로그인 실패: 이메일 또는 비밀번호를 확인해주세요.'); } else { router.push('/mypage'); router.refresh(); } } setLoading(false); }; const handleGoogleLogin = async () => { // dev 환경에서는 NEXT_PUBLIC_SITE_URL을 무시하고 현재 브라우저 origin 사용 // (NEXT_PUBLIC_SITE_URL이 .env.local에 있어도 localhost로 콜백 돌아옴) const base = process.env.NODE_ENV === 'development' ? window.location.origin : (process.env.NEXT_PUBLIC_SITE_URL ?? window.location.origin); const { error } = await supabase.auth.signInWithOAuth({ provider: 'google', options: { redirectTo: `${base}/auth/callback` }, }); if (error) setMessage('Google 로그인 오류: ' + error.message); }; const isSuccess = message.includes('완료') || message.includes('확인해주세요'); return (
{/* 워드마크 */}
쟁승메이드

{isSignUp ? '가입 후 의뢰 현황과 구매 내역을 관리하세요' : '로그인하고 의뢰 현황과 구매 내역을 확인하세요'}

{/* 카드 */}
{/* 카드 헤더 */}

{isSignUp ? '회원가입' : '로그인'}

{/* Google 로그인 */} {/* 구분선 */}
또는
{/* 오류/성공 메시지 */} {message && (
{message}
)} {/* 이메일/비밀번호 폼 */}
setEmail(e.target.value)} required className="w-full px-3.5 py-2.5 rounded-lg text-sm outline-none focus-visible:ring-2 focus-visible:ring-[var(--jsm-accent)]" style={{ background: 'var(--jsm-surface)', border: '1px solid var(--jsm-line)', color: 'var(--jsm-ink)', transition: 'border-color 0.15s', }} onFocus={(e) => { e.currentTarget.style.borderColor = 'var(--jsm-accent)'; }} onBlur={(e) => { e.currentTarget.style.borderColor = 'var(--jsm-line)'; }} />
setPassword(e.target.value)} required minLength={6} className="w-full px-3.5 py-2.5 rounded-lg text-sm outline-none focus-visible:ring-2 focus-visible:ring-[var(--jsm-accent)]" style={{ background: 'var(--jsm-surface)', border: '1px solid var(--jsm-line)', color: 'var(--jsm-ink)', transition: 'border-color 0.15s', }} onFocus={(e) => { e.currentTarget.style.borderColor = 'var(--jsm-accent)'; }} onBlur={(e) => { e.currentTarget.style.borderColor = 'var(--jsm-line)'; }} />
{/* 가입/로그인 전환 */}
{/* 홈으로 */}
{ (e.currentTarget as HTMLAnchorElement).style.color = 'var(--jsm-ink-soft)'; }} onMouseLeave={(e) => { (e.currentTarget as HTMLAnchorElement).style.color = 'var(--jsm-ink-faint)'; }} > 홈으로 돌아가기
); } export default function LoginPage() { return (
}>
); }