비밀번호 변경 수정2
This commit is contained in:
@@ -228,17 +228,17 @@ class ApiService {
|
|||||||
async verifyPasswordResetCode(email: string, code: string) {
|
async verifyPasswordResetCode(email: string, code: string) {
|
||||||
return this.request('/auth/password/confirm', {
|
return this.request('/auth/password/confirm', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: { email, code },
|
body: { email, emailCode: code },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 비밀번호 재설정
|
* 비밀번호 재설정
|
||||||
*/
|
*/
|
||||||
async resetPassword(email: string, code: string, newPassword: string, confirmPassword: string) {
|
async resetPassword(email: string, emailCode: string, newPassword: string, newPasswordConfirm: string) {
|
||||||
return this.request('/auth/password/reset', {
|
return this.request('/auth/password/reset', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: { email, code, newPassword, confirmPassword },
|
body: { email, emailCode, newPassword, newPasswordConfirm },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
import ModalCloseSvg from "../svgs/closexsvg";
|
import ModalCloseSvg from "../svgs/closexsvg";
|
||||||
import apiService from "../lib/apiService";
|
import apiService from "../lib/apiService";
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function ChangePasswordModal({ open, onClose, onSubmit, showVerification = false, devVerificationState, initialEmail }: Props) {
|
export default function ChangePasswordModal({ open, onClose, onSubmit, showVerification = false, devVerificationState, initialEmail }: Props) {
|
||||||
|
const router = useRouter();
|
||||||
const [email, setEmail] = useState(initialEmail || "");
|
const [email, setEmail] = useState(initialEmail || "");
|
||||||
const [code, setCode] = useState("");
|
const [code, setCode] = useState("");
|
||||||
const [newPassword, setNewPassword] = useState("");
|
const [newPassword, setNewPassword] = useState("");
|
||||||
@@ -25,6 +27,7 @@ export default function ChangePasswordModal({ open, onClose, onSubmit, showVerif
|
|||||||
const [isVerified, setIsVerified] = useState(false);
|
const [isVerified, setIsVerified] = useState(false);
|
||||||
const [isSending, setIsSending] = useState(false);
|
const [isSending, setIsSending] = useState(false);
|
||||||
const [isVerifying, setIsVerifying] = useState(false);
|
const [isVerifying, setIsVerifying] = useState(false);
|
||||||
|
const [showSuccessModal, setShowSuccessModal] = useState(false);
|
||||||
const hasError = !!error;
|
const hasError = !!error;
|
||||||
|
|
||||||
// initialEmail이 변경되면 email state 업데이트
|
// initialEmail이 변경되면 email state 업데이트
|
||||||
@@ -71,9 +74,18 @@ export default function ChangePasswordModal({ open, onClose, onSubmit, showVerif
|
|||||||
}
|
}
|
||||||
}, [devVerificationState]);
|
}, [devVerificationState]);
|
||||||
|
|
||||||
if (!open) return null;
|
const handleLoginClick = () => {
|
||||||
|
// 토큰 삭제 (로그아웃)
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
document.cookie = 'token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT';
|
||||||
|
}
|
||||||
|
// 로그인 페이지로 이동
|
||||||
|
router.push('/login');
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = async () => {
|
||||||
setError(null);
|
setError(null);
|
||||||
if (requireCode) {
|
if (requireCode) {
|
||||||
if (!code) {
|
if (!code) {
|
||||||
@@ -89,10 +101,87 @@ export default function ChangePasswordModal({ open, onClose, onSubmit, showVerif
|
|||||||
setError("새 비밀번호가 일치하지 않습니다.");
|
setError("새 비밀번호가 일치하지 않습니다.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onSubmit?.({ email, code: requireCode ? code : undefined, newPassword });
|
if (!email.trim()) {
|
||||||
|
setError("이메일을 입력해 주세요.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (requireCode && !code.trim()) {
|
||||||
|
setError("인증번호를 입력해 주세요.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await apiService.resetPassword(email, code, newPassword, confirmPassword);
|
||||||
|
onSubmit?.({ email, code: requireCode ? code : undefined, newPassword });
|
||||||
|
setShowSuccessModal(true);
|
||||||
|
} catch (err) {
|
||||||
|
setError(err instanceof Error ? err.message : "비밀번호 변경에 실패했습니다.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
// 모든 상태 초기화
|
||||||
|
setEmail(initialEmail || "");
|
||||||
|
setCode("");
|
||||||
|
setNewPassword("");
|
||||||
|
setConfirmPassword("");
|
||||||
|
setError(null);
|
||||||
|
setRequireCode(showVerification);
|
||||||
|
setIsCodeSent(showVerification);
|
||||||
|
setIsVerified(false);
|
||||||
|
setIsSending(false);
|
||||||
|
setIsVerifying(false);
|
||||||
onClose();
|
onClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 완료 팝업은 open prop과 관계없이 표시
|
||||||
|
if (showSuccessModal) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-[2px]"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<div className="w-[480px] rounded-[12px] border border-[#dee1e6] bg-white">
|
||||||
|
{/* header */}
|
||||||
|
<div className="flex items-center justify-end h-[80px] p-6">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-label="닫기"
|
||||||
|
onClick={handleLoginClick}
|
||||||
|
className="inline-flex size-6 items-center justify-center text-neutral-700 hover:opacity-80 cursor-pointer"
|
||||||
|
>
|
||||||
|
<ModalCloseSvg />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* body */}
|
||||||
|
<div className="flex flex-col gap-4 items-center px-6 pb-0 pt-[60px]">
|
||||||
|
<h2 className="text-[24px] font-extrabold leading-[1.45] text-[#333c47] text-center">
|
||||||
|
비밀번호 변경이 완료됐습니다.
|
||||||
|
</h2>
|
||||||
|
<p className="text-[18px] font-normal leading-[1.5] text-[#6c7682] text-center mb-[148px]">
|
||||||
|
새로운 비밀번호로 다시 로그인 해주세요.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* footer */}
|
||||||
|
<div className="flex gap-8 items-end justify-center p-6 h-[72px]">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleLoginClick}
|
||||||
|
className="h-12 w-[284px] rounded-[10px] bg-[#1f2b91] px-2 text-[16px] font-semibold leading-[1.5] text-white cursor-pointer"
|
||||||
|
>
|
||||||
|
로그인
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!open) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-[2px]"
|
className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-[2px]"
|
||||||
@@ -143,6 +232,9 @@ export default function ChangePasswordModal({ open, onClose, onSubmit, showVerif
|
|||||||
await apiService.sendPasswordReset(email);
|
await apiService.sendPasswordReset(email);
|
||||||
setRequireCode(true);
|
setRequireCode(true);
|
||||||
setIsCodeSent(true);
|
setIsCodeSent(true);
|
||||||
|
// 재전송 시 기존 인증 상태 초기화
|
||||||
|
setCode("");
|
||||||
|
setIsVerified(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err instanceof Error ? err.message : "인증번호 전송에 실패했습니다.");
|
setError(err instanceof Error ? err.message : "인증번호 전송에 실패했습니다.");
|
||||||
} finally {
|
} finally {
|
||||||
@@ -258,7 +350,7 @@ export default function ChangePasswordModal({ open, onClose, onSubmit, showVerif
|
|||||||
<div className="flex items-center justify-center gap-3 p-6">
|
<div className="flex items-center justify-center gap-3 p-6">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onClose}
|
onClick={handleCancel}
|
||||||
className="h-12 w-[136px] rounded-[10px] bg-bg-gray-light px-4 text-[16px] font-semibold leading-[1.5] text-basic-text cursor-pointer"
|
className="h-12 w-[136px] rounded-[10px] bg-bg-gray-light px-4 text-[16px] font-semibold leading-[1.5] text-basic-text cursor-pointer"
|
||||||
>
|
>
|
||||||
취소
|
취소
|
||||||
|
|||||||
Reference in New Issue
Block a user