import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; import { Button } from "@/components/ui/button"; import { ArrowRight } from "lucide-react"; import { useToast } from "@/hooks/useToast.wrapper"; import { verifyServerConnection } from "@/contexts/auth/auth.utils"; import { ServerStatus, SignUpResponse } from "./types"; import EmailConfirmation from "./EmailConfirmation"; import RegisterFormFields from "./RegisterFormFields"; import { supabase } from "@/lib/supabase"; interface RegisterFormProps { signUp: (email: string, password: string, username: string) => Promise; serverStatus: ServerStatus; setServerStatus: React.Dispatch>; setRegisterError: React.Dispatch>; } const RegisterForm: React.FC = ({ signUp, serverStatus, setServerStatus, setRegisterError, }) => { const [username, setUsername] = useState(""); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [showPassword, setShowPassword] = useState(false); const [isLoading, setIsLoading] = useState(false); const [emailConfirmationSent, setEmailConfirmationSent] = useState(false); const { toast } = useToast(); const navigate = useNavigate(); const validateForm = (): boolean => { if (!username || !email || !password || !confirmPassword) { toast({ title: "입력 오류", description: "모든 필드를 입력해주세요.", variant: "destructive", }); return false; } if (password !== confirmPassword) { toast({ title: "비밀번호 불일치", description: "비밀번호와 비밀번호 확인이 일치하지 않습니다.", variant: "destructive", }); return false; } // 비밀번호 강도 검사 if (password.length < 8) { toast({ title: "비밀번호 강도 부족", description: "비밀번호는 최소 8자 이상이어야 합니다.", variant: "destructive", }); return false; } // 이메일 형식 검사 const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailPattern.test(email)) { toast({ title: "이메일 형식 오류", description: "유효한 이메일 주소를 입력해주세요.", variant: "destructive", }); return false; } return true; }; const checkServerConnectivity = async (): Promise => { // 서버 연결 상태 재확인 if (!serverStatus.connected) { try { const currentStatus = await verifyServerConnection(); setServerStatus({ checked: true, connected: currentStatus.connected, message: currentStatus.message }); if (!currentStatus.connected) { toast({ title: "서버 연결 실패", description: "서버에 연결할 수 없습니다. 네트워크 또는 서버 상태를 확인하세요.", variant: "destructive" }); return false; } } catch (error: any) { toast({ title: "연결 확인 오류", description: error.message || "서버 연결 확인 중 오류가 발생했습니다.", variant: "destructive" }); return false; } } return true; }; // 인증 이메일 재전송 기능 const handleResendVerificationEmail = async () => { try { // 현재 브라우저 URL 가져오기 const currentUrl = window.location.origin; const redirectUrl = `${currentUrl}/login?auth_callback=true`; const { error } = await supabase.auth.resend({ type: 'signup', email, options: { emailRedirectTo: redirectUrl, }, }); if (error) { console.error('인증 메일 재전송 실패:', error); toast({ title: "인증 메일 재전송 실패", description: error.message || "인증 메일을 재전송하는 중 오류가 발생했습니다.", variant: "destructive" }); return; } toast({ title: "인증 메일 재전송 완료", description: `${email}로 인증 메일이 재전송되었습니다. 이메일과 스팸 폴더를 확인해주세요.`, }); console.log('인증 메일 재전송 성공:', email); } catch (error: any) { console.error('인증 메일 재전송 중 예외 발생:', error); toast({ title: "인증 메일 재전송 오류", description: error.message || "인증 메일을 재전송하는 중 오류가 발생했습니다.", variant: "destructive" }); } }; const handleRegister = async (e: React.FormEvent) => { e.preventDefault(); setRegisterError(null); // 서버 연결 확인 const isServerConnected = await checkServerConnectivity(); if (!isServerConnected) return; // 폼 유효성 검사 if (!validateForm()) return; setIsLoading(true); try { // 회원가입 시도 const { error, user, redirectToSettings, emailConfirmationRequired } = await signUp(email, password, username); if (error) { // 오류 메시지 출력 setRegisterError(error.message || '알 수 없는 오류가 발생했습니다.'); // 설정 페이지 리디렉션이 필요한 경우 if (redirectToSettings) { toast({ title: "Supabase 설정 필요", description: "Supabase 설정을 확인하고 올바른 값을 입력해주세요.", variant: "destructive" }); // 2초 후 설정 페이지로 이동 setTimeout(() => { navigate("/supabase-settings"); }, 2000); return; } // 네트워크 관련 오류인 경우 자세한 안내 if (error.message && ( error.message.includes('fetch') || error.message.includes('네트워크') || error.message.includes('CORS'))) { toast({ title: "네트워크 오류", description: "서버에 연결할 수 없습니다. 설정에서 CORS 프록시가 활성화되어 있는지 확인하세요.", variant: "destructive" }); } // 서버 응답 관련 오류인 경우 else if (error.message && ( error.message.includes('400') || error.message.includes('401') || error.message.includes('403') || error.message.includes('500'))) { toast({ title: "서버 응답 오류", description: error.message, variant: "destructive" }); } } else if (user) { // 이메일 확인이 필요한 경우 if (emailConfirmationRequired) { setEmailConfirmationSent(true); toast({ title: "이메일 인증 필요", description: `${email}로 인증 메일이 발송되었습니다. 메일함을 확인하고 인증을 완료해주세요.`, }); } else { // 이메일 확인이 필요하지 않은 경우 (자동 승인 등) toast({ title: "회원가입 성공", description: "회원가입이 완료되었습니다. 로그인 페이지로 이동합니다.", }); // 로그인 페이지로 이동 navigate("/login"); } } } catch (error: any) { console.error("회원가입 처리 중 예외 발생:", error); setRegisterError(error.message || '예상치 못한 오류가 발생했습니다.'); toast({ title: "회원가입 오류", description: error.message || "회원가입 처리 중 오류가 발생했습니다.", variant: "destructive" }); } finally { setIsLoading(false); } }; // 이메일 인증 안내 화면 (인증 메일이 발송된 경우) if (emailConfirmationSent) { return setEmailConfirmationSent(false)} onResendEmail={handleResendVerificationEmail} />; } // 일반 회원가입 양식 return (
); }; export default RegisterForm;