diff --git a/.gitignore b/.gitignore
index fd3dbb5..8585166 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,4 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
+.env
diff --git a/src/app/reset-password/[token]/_actions/actions.ts b/src/app/reset-password/[token]/_actions/actions.ts
new file mode 100644
index 0000000..038e18d
--- /dev/null
+++ b/src/app/reset-password/[token]/_actions/actions.ts
@@ -0,0 +1,21 @@
+'use server';
+
+import { ActionStatus } from '@/enums/ActionStatus';
+
+export const requestTokenValidation = async (token: string) => {
+ try {
+ // api 개발 완료되면 엔드 포인트 추가 예정
+ const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ token }),
+ });
+
+ return { status: ActionStatus.Success, fields: response.json() };
+ } catch (error) {
+ alert('토큰 확인 요망 👾');
+ return { status: ActionStatus.Error, issues: [error] };
+ }
+};
diff --git a/src/app/reset-password/[token]/page.tsx b/src/app/reset-password/[token]/page.tsx
index 1fbe882..c31ee34 100644
--- a/src/app/reset-password/[token]/page.tsx
+++ b/src/app/reset-password/[token]/page.tsx
@@ -3,8 +3,12 @@ import Link from 'next/link';
import ResetPasswordForm from '../_forms/ResetPasswordForm';
import { HeadingWithDescription } from '@/components/HeadingWithDescription/HeadingWithDescription';
import { redirect } from 'next/navigation';
+import { requestTokenValidation } from './_actions/actions';
+
+export default async function Page({ params: { token } }: { params: { token: string } }) {
+ const response = await requestTokenValidation(token);
+ const { email } = await response.fields;
-export default function Page() {
const handleSuccess = async () => {
'use server';
@@ -21,7 +25,7 @@ export default function Page() {
-
+
);
}
diff --git a/src/app/reset-password/_forms/ResetPasswordForm.action.ts b/src/app/reset-password/_forms/ResetPasswordForm.action.ts
index da182d6..3d9b288 100644
--- a/src/app/reset-password/_forms/ResetPasswordForm.action.ts
+++ b/src/app/reset-password/_forms/ResetPasswordForm.action.ts
@@ -11,6 +11,14 @@ export async function resetPassword(prevState: FormState, data: FormData): Promi
setTimeout(() => resolve(null), 1500);
});
+ // const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/password/confirm`, {
+ // method: 'POST',
+ // headers: {
+ // 'Content-Type': 'application/json',
+ // },
+ // body: JSON.stringify(Object.fromEntries(data)),
+ // });
+
// return { status: ActionStatus.Error, issues: ['에러여 에러'] };
return { status: ActionStatus.Success, fields: Object.fromEntries(data) as Record };
}
diff --git a/src/app/reset-password/_forms/ResetPasswordForm.tsx b/src/app/reset-password/_forms/ResetPasswordForm.tsx
index 77e77c6..c4e9423 100644
--- a/src/app/reset-password/_forms/ResetPasswordForm.tsx
+++ b/src/app/reset-password/_forms/ResetPasswordForm.tsx
@@ -11,10 +11,26 @@ import { Control, useForm } from 'react-hook-form';
import { z } from 'zod';
import { resetPassword } from './ResetPasswordForm.action';
-const formSchema = z.object({
- password: z.string(),
- passwordConfirm: z.string(),
-});
+const passwordRegex = new RegExp(/^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,15}$/);
+
+const formSchema = z
+ .object({
+ password: z
+ .string()
+ .min(8, { message: '비밀번호는 최소 8자 이상이어야 합니다.' })
+ .max(15, { message: '비밀번호는 최대 15자 이내이어야 합니다.' })
+ .regex(passwordRegex, { message: '영문, 숫자, 특수문자 포함해서 머시기해라.' }),
+ passwordConfirm: z.string(),
+ })
+ .superRefine(({ password, passwordConfirm }, ctx) => {
+ if (password !== passwordConfirm) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: '비밀번호가 일치하지 않네요.',
+ path: ['passwordConfirm'],
+ });
+ }
+ });
export type ResetPasswordRequest = z.infer;
@@ -25,9 +41,10 @@ const initialValues: ResetPasswordRequest = {
type ResetPasswordFormProps = {
onSuccess: () => void;
+ email: string;
};
-export default function ResetPasswordForm({ onSuccess }: ResetPasswordFormProps) {
+export default function ResetPasswordForm({ onSuccess, email }: ResetPasswordFormProps) {
const [isPending, startTransition] = useTransition();
const [state, setState] = useState({
@@ -52,6 +69,9 @@ export default function ResetPasswordForm({ onSuccess }: ResetPasswordFormProps)
const formData = new FormData(formRef.current);
+ // input hidden 대신 email 값을 formData에 포함시켰어요.
+ formData.append('email', email);
+
setState({
status: ActionStatus.Idle,
fields: { ...(Object.fromEntries(formData) as Record) },