ㄱㄱㄱ
This commit is contained in:
@@ -1,27 +1,74 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import ModalCloseSvg from "../svgs/closexsvg";
|
||||
|
||||
type Props = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onSubmit?: (payload: { email: string; code: string; newPassword: string }) => void;
|
||||
onSubmit?: (payload: { email: string; code?: string; newPassword: string }) => void;
|
||||
showVerification?: boolean;
|
||||
devVerificationState?: 'initial' | 'sent' | 'verified' | 'failed';
|
||||
};
|
||||
|
||||
export default function ChangePasswordModal({ open, onClose, onSubmit }: Props) {
|
||||
export default function ChangePasswordModal({ open, onClose, onSubmit, showVerification = false, devVerificationState }: Props) {
|
||||
const [email, setEmail] = useState("xrlms2025@gmail.com");
|
||||
const [code, setCode] = useState("");
|
||||
const [newPassword, setNewPassword] = useState("");
|
||||
const [confirmPassword, setConfirmPassword] = useState("");
|
||||
const [error, setError] = useState<string | null>(null); // 인증번호 오류 등
|
||||
const [requireCode, setRequireCode] = useState<boolean>(showVerification);
|
||||
const [isCodeSent, setIsCodeSent] = useState<boolean>(showVerification);
|
||||
const canConfirm = code.trim().length > 0;
|
||||
const [isVerified, setIsVerified] = useState(false);
|
||||
const hasError = !!error;
|
||||
|
||||
// 외부에서 전달된 개발모드 상태(devVerificationState)에 따라 UI 동기화
|
||||
useEffect(() => {
|
||||
if (!devVerificationState) return;
|
||||
switch (devVerificationState) {
|
||||
case 'initial':
|
||||
setRequireCode(false);
|
||||
setIsCodeSent(false);
|
||||
setCode("");
|
||||
setError(null);
|
||||
setIsVerified(false);
|
||||
break;
|
||||
case 'sent':
|
||||
setRequireCode(true);
|
||||
setIsCodeSent(true);
|
||||
setCode("");
|
||||
setError(null);
|
||||
setIsVerified(false);
|
||||
break;
|
||||
case 'verified':
|
||||
setRequireCode(true);
|
||||
setIsCodeSent(true);
|
||||
setCode("123456");
|
||||
setError(null);
|
||||
setIsVerified(true);
|
||||
break;
|
||||
case 'failed':
|
||||
setRequireCode(true);
|
||||
setIsCodeSent(true);
|
||||
setCode("");
|
||||
setError("올바르지 않은 인증번호입니다. 인증번호를 확인해주세요.");
|
||||
setIsVerified(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}, [devVerificationState]);
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
const handleSubmit = () => {
|
||||
setError(null);
|
||||
if (!code) {
|
||||
setError("인증번호를 입력해 주세요.");
|
||||
return;
|
||||
if (requireCode) {
|
||||
if (!code) {
|
||||
setError("인증번호를 입력해 주세요.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!newPassword || !confirmPassword) {
|
||||
setError("새 비밀번호를 입력해 주세요.");
|
||||
@@ -31,7 +78,7 @@ export default function ChangePasswordModal({ open, onClose, onSubmit }: Props)
|
||||
setError("새 비밀번호가 일치하지 않습니다.");
|
||||
return;
|
||||
}
|
||||
onSubmit?.({ email, code, newPassword });
|
||||
onSubmit?.({ email, code: requireCode ? code : undefined, newPassword });
|
||||
onClose();
|
||||
};
|
||||
|
||||
@@ -49,11 +96,9 @@ export default function ChangePasswordModal({ open, onClose, onSubmit }: Props)
|
||||
type="button"
|
||||
aria-label="닫기"
|
||||
onClick={onClose}
|
||||
className="inline-flex size-6 items-center justify-center text-[#333c47] hover:opacity-80"
|
||||
className="inline-flex size-6 items-center justify-center text-[#333c47] hover:opacity-80 cursor-pointer"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="size-[15.2px]">
|
||||
<path fillRule="evenodd" d="M6.225 4.811a1 1 0 0 1 1.414 0L12 9.172l4.361-4.361a1 1 0 1 1 1.414 1.414L13.414 10.586l4.361 4.361a1 1 0 0 1-1.414 1.414L12 12l-4.361 4.361a1 1 0 1 1-1.414-1.414l4.361-4.361-4.361-4.361a1 1 0 0 1 0-1.414z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<ModalCloseSvg />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -66,47 +111,75 @@ export default function ChangePasswordModal({ open, onClose, onSubmit }: Props)
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
className="h-10 flex-1 rounded-[8px] border border-[#dee1e6] bg-white px-3 text-[16px] leading-[1.5] text-[#333c47] placeholder-[#b1b8c0] outline-none"
|
||||
className={[
|
||||
"h-10 flex-1 rounded-[8px] border border-[#dee1e6] px-3 text-[16px] leading-[1.5] text-[#333c47] placeholder-[#b1b8c0] outline-none",
|
||||
hasError ? "bg-white" : isCodeSent ? "bg-neutral-50" : "bg-white",
|
||||
].join(" ")}
|
||||
placeholder="이메일"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="h-10 w-[136px] rounded-[8px] bg-[#f1f3f5] px-3 text-[16px] font-semibold leading-[1.5] text-[#333c47]"
|
||||
onClick={() => {
|
||||
setRequireCode(true);
|
||||
setIsCodeSent(true);
|
||||
setError(null);
|
||||
}}
|
||||
className="h-10 w-[136px] rounded-[8px] bg-[#f1f3f5] px-3 text-[16px] font-semibold leading-[1.5] text-[#333c47] cursor-pointer"
|
||||
>
|
||||
인증번호 재전송
|
||||
{isCodeSent ? "인증번호 재전송" : "인증번호 전송"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="w-[100px] text-[15px] font-semibold leading-[1.5] text-[#6c7682]">인증번호</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<input
|
||||
type="text"
|
||||
value={code}
|
||||
onChange={(e) => setCode(e.target.value)}
|
||||
className="h-10 flex-1 rounded-[8px] border border-[#dee1e6] bg-white px-3 text-[16px] leading-[1.5] text-[#333c47] placeholder-[#b1b8c0] outline-none"
|
||||
placeholder="인증번호 6자리"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="h-10 w-[136px] rounded-[8px] bg-[#f1f3f5] px-3 text-[16px] font-semibold leading-[1.5] text-[#4c5561]"
|
||||
>
|
||||
인증번호 확인
|
||||
</button>
|
||||
{requireCode ? (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="w-[100px] text-[15px] font-semibold leading-[1.5] text-[#6c7682]">인증번호</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<input
|
||||
type="text"
|
||||
value={code}
|
||||
onChange={(e) => setCode(e.target.value)}
|
||||
className="h-10 flex-1 rounded-[8px] border border-[#dee1e6] bg-white px-3 text-[16px] leading-[1.5] text-[#333c47] placeholder-[#b1b8c0] outline-none"
|
||||
placeholder="인증번호를 입력해 주세요."
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
disabled={!canConfirm}
|
||||
className={[
|
||||
"h-10 w-[136px] rounded-[8px] px-3 text-[16px] font-semibold leading-[1.5] cursor-pointer disabled:cursor-default",
|
||||
canConfirm ? "bg-[#f1f3f5] text-[#4c5561]" : "bg-gray-50 text-[#b1b8c0]",
|
||||
].join(" ")}
|
||||
>
|
||||
인증번호 확인
|
||||
</button>
|
||||
</div>
|
||||
{isCodeSent && !hasError && !isVerified ? (
|
||||
<div className="px-1">
|
||||
<p className="text-[13px] font-semibold leading-[1.4] text-[#384fbf]">
|
||||
인증 확인을 위해 작성한 이메일로 인증번호를 발송했습니다.
|
||||
</p>
|
||||
<p className="text-[13px] font-semibold leading-[1.4] text-[#384fbf]">
|
||||
이메일을 확인해 주세요.
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
{error ? (
|
||||
<p className="px-1 text-[13px] font-semibold leading-[1.4] text-[#f64c4c]">
|
||||
{error}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
{error ? (
|
||||
<p className="px-1 text-[13px] font-semibold leading-[1.4] text-[#f64c4c]">
|
||||
{error}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-[15px] font-semibold leading-[1.5] text-[#6c7682]">새 비밀번호</label>
|
||||
<input
|
||||
type="password"
|
||||
value={newPassword}
|
||||
onChange={(e) => setNewPassword(e.target.value)}
|
||||
className="h-10 rounded-[8px] border border-[#dee1e6] bg-neutral-50 px-3 text-[16px] leading-[1.5] text-[#333c47] placeholder-[#b1b8c0] outline-none"
|
||||
disabled={!isVerified}
|
||||
className={[
|
||||
"h-10 rounded-[8px] border border-[#dee1e6] px-3 text-[16px] leading-[1.5] text-[#333c47] placeholder-[#b1b8c0] outline-none",
|
||||
isVerified ? "bg-white" : "bg-neutral-50",
|
||||
].join(" ")}
|
||||
placeholder="새 비밀번호"
|
||||
/>
|
||||
</div>
|
||||
@@ -118,7 +191,11 @@ export default function ChangePasswordModal({ open, onClose, onSubmit }: Props)
|
||||
type="password"
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
className="h-10 rounded-[8px] border border-[#dee1e6] bg-neutral-50 px-3 text-[16px] leading-[1.5] text-[#333c47] placeholder-[#b1b8c0] outline-none"
|
||||
disabled={!isVerified}
|
||||
className={[
|
||||
"h-10 rounded-[8px] border border-[#dee1e6] px-3 text-[16px] leading-[1.5] text-[#333c47] placeholder-[#b1b8c0] outline-none",
|
||||
isVerified ? "bg-white" : "bg-neutral-50",
|
||||
].join(" ")}
|
||||
placeholder="새 비밀번호 확인"
|
||||
/>
|
||||
</div>
|
||||
@@ -129,14 +206,14 @@ export default function ChangePasswordModal({ open, onClose, onSubmit }: Props)
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="h-12 w-[136px] rounded-[10px] bg-[#f1f3f5] px-4 text-[16px] font-semibold leading-[1.5] text-[#4c5561]"
|
||||
className="h-12 w-[136px] rounded-[10px] bg-[#f1f3f5] px-4 text-[16px] font-semibold leading-[1.5] text-[#4c5561] cursor-pointer"
|
||||
>
|
||||
취소
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleSubmit}
|
||||
className="h-12 w-[136px] rounded-[10px] bg-[#8598e8] px-4 text-[16px] font-semibold leading-[1.5] text-white"
|
||||
className="h-12 w-[136px] rounded-[10px] bg-[#8598e8] px-4 text-[16px] font-semibold leading-[1.5] text-white cursor-pointer"
|
||||
>
|
||||
비밀번호 변경
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user