diff --git a/src/app/(auth)/login/_components/LoginForm/OpenPasswordResetModal.tsx b/src/app/(auth)/login/_components/LoginForm/OpenPasswordResetModal.tsx
index 1669e7a5..868eb3aa 100644
--- a/src/app/(auth)/login/_components/LoginForm/OpenPasswordResetModal.tsx
+++ b/src/app/(auth)/login/_components/LoginForm/OpenPasswordResetModal.tsx
@@ -4,13 +4,11 @@ import ResetPasswordModal from '@/components/common/Modal/content/ResetPasswordM
import { postResetPasswordToEmail } from '@/lib/apis/user';
import { ResetPasswordToEmailBody } from '@/lib/apis/user/type';
import { useModalStore } from '@/store/useModalStore';
-import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import { toast } from 'react-toastify';
export default function OpenPasswordResetModal({ ...props }) {
const { openModal } = useModalStore();
- const router = useRouter();
useEffect(() => {
const unsubscribe = useModalStore.subscribe(
@@ -30,7 +28,7 @@ export default function OpenPasswordResetModal({ ...props }) {
}
);
return () => {
- unsubscribe(); // 언마운트, 구독 해제
+ unsubscribe();
};
}, []);
@@ -49,10 +47,9 @@ export default function OpenPasswordResetModal({ ...props }) {
if (error instanceof Error) {
const errorMessage = error.message;
- // 존재하지 않는 유저 : User not found
+ // User not found
if (errorMessage.includes('User not found')) {
toast.error('존재하지 않는 이메일입니다. 회원가입을 먼저 해주세요.');
- router.push('/signup');
} else {
toast.error(`Error : ${error}`);
}
@@ -71,14 +68,13 @@ export default function OpenPasswordResetModal({ ...props }) {
title: '비밀번호 재설정',
description: '비밀번호 재설정 링크를 보내드립니다.',
button: {
- formId: 'reset-password-form', // formId 연결
+ formId: 'reset-password-form', // form 연결
number: 2,
text: '링크 보내기',
// 기존 모달 컴포넌트의 onRequest 호출 방식과의 일관성을 위해 빈 함수 전달
onRequest: () => {},
},
},
-
(() => )()
);
}}
diff --git a/src/app/(auth)/reset-password/ResetPasswordForm.tsx b/src/app/(auth)/reset-password/ResetPasswordForm.tsx
index 402784a8..deefeb67 100644
--- a/src/app/(auth)/reset-password/ResetPasswordForm.tsx
+++ b/src/app/(auth)/reset-password/ResetPasswordForm.tsx
@@ -2,11 +2,15 @@
import InputWithLabel from '@/components/auth/InputWithLabel';
import Button from '@/components/common/Button';
+import { ROUTES } from '@/constants/routes';
+import { patchResetPassword } from '@/lib/apis/user';
import {
validatePassword,
validatePasswordConfirm,
} from '@/utils/inputValidation';
+import { useRouter, useSearchParams } from 'next/navigation';
import { useMemo, useState } from 'react';
+import { toast } from 'react-toastify';
import { z } from 'zod';
// reset password schema
@@ -20,7 +24,6 @@ const resetPasswordSchema = z
const { password, passwordConfirm } = val;
if (!password) {
- // 비밀번호가 비어있음
ctx.addIssue({
path: ['password'],
code: z.ZodIssueCode.custom,
@@ -28,7 +31,6 @@ const resetPasswordSchema = z
fatal: true, // 조건 실패 시, 유효성 검사 중단
});
} else if (!validatePassword(password)) {
- // 비밀번호가 입력은 되었지만, 유효하지 않음
ctx.addIssue({
path: ['password'],
code: z.ZodIssueCode.custom,
@@ -38,7 +40,6 @@ const resetPasswordSchema = z
}
if (!passwordConfirm) {
- // 비밀번호 확인이 비어있는 경우
ctx.addIssue({
path: ['passwordConfirm'],
code: z.ZodIssueCode.custom,
@@ -46,7 +47,6 @@ const resetPasswordSchema = z
fatal: true,
});
} else if (!validatePasswordConfirm({ password, passwordConfirm })) {
- // 비밀번호 확인이 입력은 되었지만, 비밀번호와 일치하지 않음
ctx.addIssue({
path: ['passwordConfirm'],
code: z.ZodIssueCode.custom,
@@ -71,6 +71,9 @@ export default function ResetPasswordForm() {
passwordConfirm: [],
});
+ const router = useRouter();
+ const searchParams = useSearchParams();
+
const isFormValid = useMemo(() => {
return (
formValues.password !== '' &&
@@ -96,18 +99,52 @@ export default function ResetPasswordForm() {
} else {
setFormErrors((prev) => ({
...prev,
- [key]: '',
+ [key]: [],
}));
}
setFormValues(newFormValues);
};
- const handleFormSubmit = () => {
- console.log('form submit');
+ const handleFormSubmit = async (e: React.FormEvent) => {
+ e.preventDefault();
+
+ if (!isFormValid) return;
+
+ // formErrors 초기화
setFormErrors({
password: [],
passwordConfirm: [],
});
+
+ try {
+ const token = searchParams.get('token');
+ // early return
+ if (!token) {
+ toast.error('유효하지 않은 링크입니다. 다시 시도해주세요.');
+ return;
+ }
+
+ const res = await patchResetPassword({
+ body: {
+ passwordConfirmation: formValues.passwordConfirm,
+ password: formValues.password,
+ token,
+ },
+ });
+ console.log('res', res);
+ toast.success('비밀번호 재설정이 완료되었습니다.');
+ router.push(ROUTES.LOGIN);
+ } catch (error) {
+ if (error instanceof Error) {
+ const errorMessage = error.message;
+ if (errorMessage.includes('유효하지 않은 토큰입니다.')) {
+ toast.error(
+ '비밀번호 재설정 링크카 만료되었습니다. 다시 요청해주세요.'
+ );
+ }
+ console.error(errorMessage);
+ }
+ }
};
return (