diff --git a/src/app/register/RegisterForm.tsx b/src/app/register/RegisterForm.tsx index 2610ca7..96236f3 100644 --- a/src/app/register/RegisterForm.tsx +++ b/src/app/register/RegisterForm.tsx @@ -1,12 +1,12 @@ "use client"; -import { useMemo, useState } from "react"; +import { useMemo, useState, useEffect } from "react"; import Link from "next/link"; import LoginCheckboxActiveSvg from "@/app/svgs/logincheckboxactivesvg"; import LoginCheckboxInactiveSvg from "@/app/svgs/logincheckboxinactivesvg"; import LoginInputSvg from "@/app/svgs/inputformx"; -type Gender = "male" | "female" | ""; +type Gender = "MALE" | "FEMALE" | ""; type RegisterFormProps = { onOpenDone: () => void; @@ -73,10 +73,129 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo return Object.keys(nextErrors).length === 0; } - function handleSubmit(e: React.FormEvent) { + // 입력 필드가 유효해지면 해당 필드의 에러를 자동으로 지움 + useEffect(() => { + setErrors((prev) => { + const next = { ...prev }; + if (name.trim().length > 0 && prev.name) delete next.name; + if (isPhoneValid && prev.phone) delete next.phone; + if (isEmailValid && prev.email) delete next.email; + if (isPasswordValid && prev.password) delete next.password; + if (isPasswordConfirmValid && prev.passwordConfirm) delete next.passwordConfirm; + if (gender !== "" && prev.gender) delete next.gender; + if (birthdate.trim().length > 0 && prev.birthdate) delete next.birthdate; + if (allAgree && prev.agreements) delete next.agreements; + return next; + }); + }, [name, isPhoneValid, isEmailValid, isPasswordValid, isPasswordConfirmValid, gender, birthdate, allAgree]); + + async function handleSubmit(e: React.FormEvent) { + console.log("handleSubmit"); e.preventDefault(); if (!validateAll()) return; - onOpenDone(); + await RegisterUser(); + } + + async function verifyEmailCode() { + try{ + const response = await fetch( + "https://hrdi.coconutmeet.net/auth/verify-email/confirm", + { + method: "POST", headers: {"Content-Type": "application/json",}, + body: JSON.stringify({email: email,emailCode: emailCode}) + }); + if (!response.ok) { + console.error("이메일 인증번호 검증 실패:", response.statusText); + onOpenCodeError(); + return; + } + // 인증 성공 시 상태 업데이트 + setEmailCodeVerified(true); + } + catch(error){ + console.error("이메일 인증번호 검증 오류:", error); + onOpenCodeError(); + } + } + + + async function sendEmailCode() { + + if (!isEmailValid) return; + // INSERT_YOUR_CODE + try { + const response = await fetch( + "https://hrdi.coconutmeet.net/auth/verify-email/send", + { + method: "POST", + headers: {"Content-Type": "application/json",}, + body: JSON.stringify({email: email}) + } + ); + if (!response.ok) { + console.error("이메일 인증번호 전송 실패:", response.statusText); + alert("인증번호 전송실패"); + return; + } + // 성공 시에만 상태 업데이트 + setEmailCodeSent(true); + setEmailCode(""); + setEmailCodeVerified(false); + } catch (error) { + console.error("이메일 인증번호 전송 오류:", error); + alert("인증번호 전송실패"); + return; + } + } + + async function RegisterUser() { + if (!emailCodeVerified) { + onOpenCodeError("이메일 인증을 완료해주세요."); + return false; + } + try { + const response = await fetch("https://hrdi.coconutmeet.net/auth/signup", { + method: "POST", + headers: {"Content-Type": "application/json",}, + body: JSON.stringify({ + email: email, + emailCode: emailCode, + password: password, + passwordConfirm: passwordConfirm, + name: name, + phone: phone, + gender: gender, + birthDate: birthdate + }) + }); + if (!response.ok) { + let errorMessage = `회원가입 실패 (${response.status})`; + try { + const errorData = await response.json(); + if (errorData.error) { + errorMessage = errorData.error; + } else if (errorData.message) { + errorMessage = errorData.message; + } else if (response.statusText) { + errorMessage = `${response.statusText} (${response.status})`; + } + } catch (parseError) { + if (response.statusText) { + errorMessage = `${response.statusText} (${response.status})`; + } + } + console.error("회원가입 실패:", errorMessage); + onOpenCodeError(errorMessage); + return false; + } + onOpenDone(); + return true; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : "네트워크 오류가 발생했습니다."; + console.error("회원가입 오류:", errorMessage); + onOpenCodeError(errorMessage); + return false; + } } return ( @@ -87,7 +206,6 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo 회원가입 -
{/* 이름 */}
@@ -161,9 +279,10 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo onFocus={() => setFocused((p) => ({ ...p, email: true }))} onBlur={() => setFocused((p) => ({ ...p, email: false }))} placeholder="이메일을 입력해 주세요." - className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]" + disabled={emailCodeVerified} + className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] disabled:bg-gray-100 disabled:cursor-not-allowed" /> - {email.trim().length > 0 && focused.email && ( + {email.trim().length > 0 && focused.email && !emailCodeVerified && (
@@ -207,7 +320,8 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo onFocus={() => setFocused((p) => ({ ...p, emailCode: true }))} onBlur={() => setFocused((p) => ({ ...p, emailCode: false }))} placeholder="인증번호 6자리" - className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]" + disabled={emailCodeVerified} + className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] disabled:bg-gray-100 disabled:cursor-not-allowed" /> {emailCode.trim().length > 0 && focused.emailCode && !emailCodeVerified && ( +

+ {emailCodeVerified ? ( + "인증이 완료됐습니다" + ) : ( + <> + 인증 확인을 위해 작성한 이메일로 인증번호를 발송했습니다. +
+ 이메일을 확인해 주세요. + + )} +

)} @@ -306,13 +424,13 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo setGender("male")} + value="MALE" + checked={gender === "MALE"} + onChange={() => setGender("MALE")} className="sr-only" /> - - {gender === "male" && } + + {gender === "MALE" && } 남성 @@ -320,13 +438,13 @@ export default function RegisterForm({ onOpenDone, onOpenCodeError }: RegisterFo setGender("female")} + value="FEMALE" + checked={gender === "FEMALE"} + onChange={() => setGender("FEMALE")} className="sr-only" /> - - {gender === "female" && } + + {gender === "FEMALE" && } 여성 diff --git a/src/app/register/page.tsx b/src/app/register/page.tsx index e28f52f..a945344 100644 --- a/src/app/register/page.tsx +++ b/src/app/register/page.tsx @@ -14,6 +14,7 @@ export default function RegisterPage() { return ( <>
+ setDoneOpen(true)} onOpenCodeError={(msg) => { @@ -21,6 +22,7 @@ export default function RegisterPage() { setCodeErrorOpen(true); }} /> +