From bd0a43148547d16c2333e8e51f55710582e8586e Mon Sep 17 00:00:00 2001 From: swimmingRiver Date: Mon, 16 Jun 2025 16:15:14 +0900 Subject: [PATCH 01/29] =?UTF-8?q?refactor:=20validate=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/auths/signup/page.tsx | 31 +++++++++------------- src/utils/validators/auth.ts | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 19 deletions(-) create mode 100644 src/utils/validators/auth.ts diff --git a/src/app/auths/signup/page.tsx b/src/app/auths/signup/page.tsx index 408404a0..325a7834 100644 --- a/src/app/auths/signup/page.tsx +++ b/src/app/auths/signup/page.tsx @@ -13,6 +13,12 @@ import Button from '@/components/common/Button/Button'; import useBoolean from '@/hooks/useBoolean'; import { APP_ROUTES } from '@/constants/appRoutes'; import { useAuth } from '@/providers/auth-provider/AuthProvider.client'; +import { + emailValidation, + favoriteValidation, + passwordCheckValidation, + passwordValidation, +} from '@/utils/validators/auth'; const SignUp = () => { const { value: showPassword, toggle: toggleShowPassword } = useBoolean(); @@ -88,17 +94,13 @@ const SignUp = () => { emailValidation(value), }), }} /> @@ -131,11 +133,7 @@ const SignUp = () => { placeholder="비밀번호를 입력해주세요" register={{ ...register('password', { - required: '비밀번호가 8자 이상이 되도록 해 주세요', - pattern: { - value: /^[^\s]{8,}$/, - message: '비밀번호가 8자 이상이 되도록 해 주세요', - }, + validate: (value) => passwordValidation(value), }), }} hasError={!!errors.password} @@ -171,12 +169,8 @@ const SignUp = () => { placeholder="비밀번호를 다시 한 번 입력해주세요" register={{ ...register('passwordCheck', { - required: '비밀번호를 다시 한 번 입력해주세요', - validate: (value) => { - if (value !== getValues('password')) { - return '비밀번호가 일치하지 않습니다'; - } - }, + validate: (value) => + passwordCheckValidation(value, getValues('password')), }), }} hasError={!!errors.passwordCheck} @@ -191,7 +185,7 @@ const SignUp = () => { placeholder="(ex. 위대한 개츠비,원피스)" register={{ ...register('companyName', { - required: '좋아하는 작품을 1개 이상 입력해 주세요.', + validate: (value) => favoriteValidation(value), }), }} hasError={!!errors.companyName} @@ -223,7 +217,6 @@ const SignUp = () => {
이미 회원이신가요? diff --git a/src/utils/validators/auth.ts b/src/utils/validators/auth.ts new file mode 100644 index 00000000..fc49a466 --- /dev/null +++ b/src/utils/validators/auth.ts @@ -0,0 +1,49 @@ +export const emailValidation = (email: string): string | true => { + if (!email) { + return '이메일을 입력해주세요'; + } + if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) { + return '이메일 형식이 올바르지 않습니다'; + } + return true; +}; + +export const passwordValidation = (password: string): string | true => { + if (!password) { + return '비밀번호를 입력해주세요'; + } + if (password.length < 8) { + return '비밀번호는 8자 이상이 되도록 해 주세요'; + } + if (!/^[^\s]{8,}$/.test(password)) { + return '비밀번호는 숫자와 문자로 이루어진 8자 이상이 되도록 해 주세요'; + } + return true; +}; + +export const passwordCheckValidation = ( + passwordCheck: string, + password: string +): string | true => { + if (!passwordCheck) { + return '비밀번호를 다시 한 번 입력해주세요'; + } + if (passwordCheck !== password) { + return '비밀번호가 일치하지 않습니다'; + } + return true; +}; + +export const nameValidation = (name: string): string | true => { + if (!name) { + return '닉네임을 입력해주세요'; + } + return true; +}; + +export const favoriteValidation = (favorite: string): string | true => { + if (!favorite) { + return '좋아하는 작품을 입력해주세요'; + } + return true; +}; From b019f2e1c16669f3b2120a5168ba559a7264e4e5 Mon Sep 17 00:00:00 2001 From: swimmingRiver Date: Mon, 16 Jun 2025 16:31:50 +0900 Subject: [PATCH 02/29] =?UTF-8?q?refactor:=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99replace=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/auths/signup/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/auths/signup/page.tsx b/src/app/auths/signup/page.tsx index 325a7834..dbdc4b09 100644 --- a/src/app/auths/signup/page.tsx +++ b/src/app/auths/signup/page.tsx @@ -63,7 +63,7 @@ const SignUp = () => { const { isSignIn } = useAuth(); useEffect(() => { if (isSignIn) { - router.push(APP_ROUTES.social); + router.replace(APP_ROUTES.social); } }, []); if (isSignIn) { From 7dbdbdefadfdf61d971220bf6aba8662ed489ee4 Mon Sep 17 00:00:00 2001 From: swimmingRiver Date: Mon, 16 Jun 2025 17:33:06 +0900 Subject: [PATCH 03/29] =?UTF-8?q?refactor:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=ED=8E=98=EC=9D=B4=EC=A7=80=20ssr=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/auths/signup/page.tsx | 228 ++-------------------------------- 1 file changed, 13 insertions(+), 215 deletions(-) diff --git a/src/app/auths/signup/page.tsx b/src/app/auths/signup/page.tsx index dbdc4b09..c0427aec 100644 --- a/src/app/auths/signup/page.tsx +++ b/src/app/auths/signup/page.tsx @@ -1,73 +1,17 @@ -'use client'; +import { getMyInfoOnServer } from '@/providers/auth-provider/authProviderUtil'; +import SignupForm from './_components/SignupForm'; +import LinkComponent from './_components/LinkComponent'; +import { redirect } from 'next/navigation'; +import { headers } from 'next/headers'; -import Link from 'next/link'; -import { useEffect } from 'react'; -import { SubmitHandler, useForm } from 'react-hook-form'; -import { SignUpFormData } from '@/api/auth/type'; -import useCreateUser from '@/hooks/api/auth/useCreateUser'; -import { useRouter } from 'next/navigation'; +const SignUp = async () => { + const { isSignIn } = await getMyInfoOnServer(); + const referer = (await headers()).get('referer'); -import InputForm from '@/components/common/Form/InputForm'; -import { VisibilityOff, VisibilityOn } from '@public/assets/icons'; -import Button from '@/components/common/Button/Button'; -import useBoolean from '@/hooks/useBoolean'; -import { APP_ROUTES } from '@/constants/appRoutes'; -import { useAuth } from '@/providers/auth-provider/AuthProvider.client'; -import { - emailValidation, - favoriteValidation, - passwordCheckValidation, - passwordValidation, -} from '@/utils/validators/auth'; - -const SignUp = () => { - const { value: showPassword, toggle: toggleShowPassword } = useBoolean(); - const { value: showPasswordCheck, toggle: toggleShowPasswordCheck } = - useBoolean(); - const { - register, - handleSubmit, - formState: { isSubmitting, errors }, - getValues, - setError, - } = useForm(); - - const { mutate: createUser } = useCreateUser(); //회원 가입 요청 hooks 호출 - - const router = useRouter(); - - // 회원가입 제출 함수 - const onSubmit: SubmitHandler = (data) => { - const signUpData = { - //form 데이터 중 비밀번호 확인 제외 데이터 - name: data.name, - email: data.email, - password: data.password, - companyName: data.companyName, - }; - - createUser(signUpData, { - onSuccess: () => { - alert('회원가입이 완료되었습니다.'); - router.push(`${APP_ROUTES.signin}`); - }, - onError: (error: Error) => { - // 이메일 중복확인 오류 처리 - setError('email', { - type: 'manual', - message: error.message, - }); - }, - }); - }; - const { isSignIn } = useAuth(); - useEffect(() => { - if (isSignIn) { - router.replace(APP_ROUTES.social); - } - }, []); if (isSignIn) { - return
Loading...
; + if (referer) { + redirect(referer ?? '/'); + } } return ( @@ -76,154 +20,8 @@ const SignUp = () => {

회원가입

-
- - - emailValidation(value), - }), - }} - /> - -
-
- - {showPassword ? ( - - ) : ( - - )} - - } - type={showPassword ? 'text' : 'password'} - placeholder="비밀번호를 입력해주세요" - register={{ - ...register('password', { - validate: (value) => passwordValidation(value), - }), - }} - hasError={!!errors.password} - helperText={errors.password?.message} - /> -
-
-
-
- - {showPasswordCheck ? ( - - ) : ( - - )} - - } - type={showPasswordCheck ? 'text' : 'password'} - placeholder="비밀번호를 다시 한 번 입력해주세요" - register={{ - ...register('passwordCheck', { - validate: (value) => - passwordCheckValidation(value, getValues('password')), - }), - }} - hasError={!!errors.passwordCheck} - helperText={errors.passwordCheck?.message} - /> -
-
- - favoriteValidation(value), - }), - }} - hasError={!!errors.companyName} - helperText={errors.companyName?.message} - /> - - -
- 이미 회원이신가요? - - 로그인 - -
- + +
); From 381c646271a115f2f6ee7483bfbad3b1bcd949e3 Mon Sep 17 00:00:00 2001 From: swimmingRiver Date: Mon, 16 Jun 2025 17:35:17 +0900 Subject: [PATCH 04/29] =?UTF-8?q?refactor:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../signup/_components/LinkComponent.tsx | 17 ++ .../auths/signup/_components/SignupForm.tsx | 168 ++++++++++++++++++ src/hooks/api/auth/useSignUpForm.ts | 41 +++++ 3 files changed, 226 insertions(+) create mode 100644 src/app/auths/signup/_components/LinkComponent.tsx create mode 100644 src/app/auths/signup/_components/SignupForm.tsx create mode 100644 src/hooks/api/auth/useSignUpForm.ts diff --git a/src/app/auths/signup/_components/LinkComponent.tsx b/src/app/auths/signup/_components/LinkComponent.tsx new file mode 100644 index 00000000..093ca7cd --- /dev/null +++ b/src/app/auths/signup/_components/LinkComponent.tsx @@ -0,0 +1,17 @@ +import { APP_ROUTES } from '@/constants/appRoutes'; +import Link from 'next/link'; + +const LinkComponent = () => { + return ( +
+ 이미 회원이신가요? + + 로그인 + +
+ ); +}; +export default LinkComponent; diff --git a/src/app/auths/signup/_components/SignupForm.tsx b/src/app/auths/signup/_components/SignupForm.tsx new file mode 100644 index 00000000..74bf88c9 --- /dev/null +++ b/src/app/auths/signup/_components/SignupForm.tsx @@ -0,0 +1,168 @@ +'use client'; +import { SignUpFormData } from '@/api/auth/type'; +import Button from '@/components/common/Button/Button'; +import InputForm from '@/components/common/Form/InputForm'; +import { useForm } from 'react-hook-form'; +import { + emailValidation, + passwordValidation, + passwordCheckValidation, + favoriteValidation, +} from '@/utils/validators/auth'; +import { VisibilityOff, VisibilityOn } from '@public/assets/icons'; +import useBoolean from '@/hooks/useBoolean'; +import useSignUpForm from '@/hooks/api/auth/useSignUpForm'; + +const SignupForm = () => { + const { value: showPassword, toggle: toggleShowPassword } = useBoolean(); + const { value: showPasswordCheck, toggle: toggleShowPasswordCheck } = + useBoolean(); + + const { + register, + handleSubmit, + formState: { isSubmitting, errors }, + getValues, + setError, + } = useForm(); + + const { onSubmit } = useSignUpForm({ setError }); + + return ( +
+ + + emailValidation(value), + }), + }} + /> + +
+
+ + {showPassword ? ( + + ) : ( + + )} + + } + type={showPassword ? 'text' : 'password'} + placeholder="비밀번호를 입력해주세요" + register={{ + ...register('password', { + validate: (value) => passwordValidation(value), + }), + }} + hasError={!!errors.password} + helperText={errors.password?.message} + /> +
+
+
+
+ + {showPasswordCheck ? ( + + ) : ( + + )} + + } + type={showPasswordCheck ? 'text' : 'password'} + placeholder="비밀번호를 다시 한 번 입력해주세요" + register={{ + ...register('passwordCheck', { + validate: (value) => + passwordCheckValidation(value, getValues('password')), + }), + }} + hasError={!!errors.passwordCheck} + helperText={errors.passwordCheck?.message} + /> +
+
+ + favoriteValidation(value), + }), + }} + hasError={!!errors.companyName} + helperText={errors.companyName?.message} + /> + + + + ); +}; + +export default SignupForm; diff --git a/src/hooks/api/auth/useSignUpForm.ts b/src/hooks/api/auth/useSignUpForm.ts new file mode 100644 index 00000000..50a3dfdd --- /dev/null +++ b/src/hooks/api/auth/useSignUpForm.ts @@ -0,0 +1,41 @@ +'use client'; +import { useRouter } from 'next/navigation'; +import { SubmitHandler, UseFormSetError } from 'react-hook-form'; +import { SignUpFormData } from '@/api/auth/type'; +import useCreateUser from '@/hooks/api/auth/useCreateUser'; +import { APP_ROUTES } from '@/constants/appRoutes'; + +interface UseSignUpFormProps { + setError: UseFormSetError; +} + +const useSignUpForm = ({ setError }: UseSignUpFormProps) => { + const router = useRouter(); + const { mutate: createUser } = useCreateUser(); + + const onSubmit: SubmitHandler = (data) => { + const signUpData = { + name: data.name, + email: data.email, + password: data.password, + companyName: data.companyName, + }; + + createUser(signUpData, { + onSuccess: () => { + alert('회원가입이 완료되었습니다.'); + router.push(APP_ROUTES.signin); + }, + onError: (error: Error) => { + setError('email', { + type: 'manual', + message: error.message, + }); + }, + }); + }; + + return { onSubmit }; +}; + +export default useSignUpForm; From 6c78dc6615dafa9989bba13f0a380d5388b4b9d0 Mon Sep 17 00:00:00 2001 From: swimmingRiver Date: Mon, 16 Jun 2025 17:46:24 +0900 Subject: [PATCH 05/29] =?UTF-8?q?chore:=20=ED=83=80=EC=9E=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/api/auth/useSignUpForm.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hooks/api/auth/useSignUpForm.ts b/src/hooks/api/auth/useSignUpForm.ts index 50a3dfdd..ee72684c 100644 --- a/src/hooks/api/auth/useSignUpForm.ts +++ b/src/hooks/api/auth/useSignUpForm.ts @@ -5,11 +5,11 @@ import { SignUpFormData } from '@/api/auth/type'; import useCreateUser from '@/hooks/api/auth/useCreateUser'; import { APP_ROUTES } from '@/constants/appRoutes'; -interface UseSignUpFormProps { +const useSignUpForm = ({ + setError, +}: { setError: UseFormSetError; -} - -const useSignUpForm = ({ setError }: UseSignUpFormProps) => { +}) => { const router = useRouter(); const { mutate: createUser } = useCreateUser(); From 5e2b217447a6858244339cc62038afe29b55a253 Mon Sep 17 00:00:00 2001 From: swimmingRiver Date: Mon, 16 Jun 2025 18:46:39 +0900 Subject: [PATCH 06/29] =?UTF-8?q?refactor:=20=ED=8F=BC=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=ED=95=84=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/auths/_components/FormField.tsx | 29 ++++ .../auths/_components/PasswordFormField.tsx | 43 ++++++ src/app/auths/_components/type.ts | 18 +++ .../auths/signup/_components/SignupForm.tsx | 125 +++++------------- src/utils/validators/auth.ts | 21 +++ src/utils/validators/type.ts | 7 + 6 files changed, 150 insertions(+), 93 deletions(-) create mode 100644 src/app/auths/_components/FormField.tsx create mode 100644 src/app/auths/_components/PasswordFormField.tsx create mode 100644 src/app/auths/_components/type.ts create mode 100644 src/utils/validators/type.ts diff --git a/src/app/auths/_components/FormField.tsx b/src/app/auths/_components/FormField.tsx new file mode 100644 index 00000000..bce03b05 --- /dev/null +++ b/src/app/auths/_components/FormField.tsx @@ -0,0 +1,29 @@ +import InputForm from '@/components/common/Form/InputForm'; + +import { FormFieldProps } from './type'; + +const FormField = ({ + name, + label, + placeholder, + register, + errors, + validate, +}: FormFieldProps) => { + return ( + validate({ value, name }), + }), + }} + /> + ); +}; +export default FormField; diff --git a/src/app/auths/_components/PasswordFormField.tsx b/src/app/auths/_components/PasswordFormField.tsx new file mode 100644 index 00000000..55410a41 --- /dev/null +++ b/src/app/auths/_components/PasswordFormField.tsx @@ -0,0 +1,43 @@ +import InputForm from '@/components/common/Form/InputForm'; +import { PasswordFormFieldProps } from './type'; +import { Eye, EyeOff } from 'lucide-react'; + +const PasswordFormField = ({ + name, + label, + placeholder, + register, + errors, + validate, + isShowPassword, + toggleShowPassword, + password = '', +}: PasswordFormFieldProps) => { + return ( + validate({ value, name, password }), + }), + }} + suffixIcon={ + + } + /> + ); +}; +export default PasswordFormField; diff --git a/src/app/auths/_components/type.ts b/src/app/auths/_components/type.ts new file mode 100644 index 00000000..810fd97d --- /dev/null +++ b/src/app/auths/_components/type.ts @@ -0,0 +1,18 @@ +import { SignUpFormData } from '@/api/auth/type'; +import { SignUpValidateProps } from '@/utils/validators/type'; +import { FieldErrors, UseFormRegister } from 'react-hook-form'; + +export interface FormFieldProps { + name: keyof SignUpFormData; + label: string; + placeholder: string; + register: UseFormRegister; + errors: FieldErrors; + validate: (props: SignUpValidateProps) => string | true; +} + +export interface PasswordFormFieldProps extends FormFieldProps { + isShowPassword: boolean; + toggleShowPassword: () => void; + password?: string; +} diff --git a/src/app/auths/signup/_components/SignupForm.tsx b/src/app/auths/signup/_components/SignupForm.tsx index 74bf88c9..c5f2c88d 100644 --- a/src/app/auths/signup/_components/SignupForm.tsx +++ b/src/app/auths/signup/_components/SignupForm.tsx @@ -1,17 +1,14 @@ 'use client'; import { SignUpFormData } from '@/api/auth/type'; import Button from '@/components/common/Button/Button'; -import InputForm from '@/components/common/Form/InputForm'; + import { useForm } from 'react-hook-form'; -import { - emailValidation, - passwordValidation, - passwordCheckValidation, - favoriteValidation, -} from '@/utils/validators/auth'; -import { VisibilityOff, VisibilityOn } from '@public/assets/icons'; +import { singUpValidate } from '@/utils/validators/auth'; + import useBoolean from '@/hooks/useBoolean'; import useSignUpForm from '@/hooks/api/auth/useSignUpForm'; +import FormField from '@/app/auths/_components/FormField'; +import PasswordFormField from '@/app/auths/_components/PasswordFormField'; const SignupForm = () => { const { value: showPassword, toggle: toggleShowPassword } = useBoolean(); @@ -30,119 +27,61 @@ const SignupForm = () => { return (
- - emailValidation(value), - }), - }} + register={register} + validate={singUpValidate} + errors={errors} />
- - {showPassword ? ( - - ) : ( - - )} - - } - type={showPassword ? 'text' : 'password'} + label="비밀번호" placeholder="비밀번호를 입력해주세요" - register={{ - ...register('password', { - validate: (value) => passwordValidation(value), - }), - }} - hasError={!!errors.password} - helperText={errors.password?.message} + register={register} + validate={singUpValidate} + errors={errors} + isShowPassword={showPassword} + toggleShowPassword={toggleShowPassword} />
- - {showPasswordCheck ? ( - - ) : ( - - )} - - } - type={showPasswordCheck ? 'text' : 'password'} + label="비밀번호 확인" placeholder="비밀번호를 다시 한 번 입력해주세요" - register={{ - ...register('passwordCheck', { - validate: (value) => - passwordCheckValidation(value, getValues('password')), - }), - }} - hasError={!!errors.passwordCheck} - helperText={errors.passwordCheck?.message} + register={register} + validate={singUpValidate} + password={getValues('password') ?? ''} + errors={errors} + isShowPassword={showPasswordCheck} + toggleShowPassword={toggleShowPasswordCheck} />
- favoriteValidation(value), - }), - }} - hasError={!!errors.companyName} - helperText={errors.companyName?.message} + register={register} + validate={singUpValidate} + errors={errors} /> + + ); +}; + +export default SignInForm; diff --git a/src/hooks/api/auth/useSignInForm.ts b/src/hooks/api/auth/useSignInForm.ts new file mode 100644 index 00000000..32a6a6aa --- /dev/null +++ b/src/hooks/api/auth/useSignInForm.ts @@ -0,0 +1,42 @@ +import { SignInFormData } from '@/api/auth/type'; +import { SubmitHandler, UseFormSetError } from 'react-hook-form'; +import { usePostSignin } from './usePostSignin'; +import { useRouter } from 'next/navigation'; + +export const useSignInForm = ({ + setError, +}: { + setError: UseFormSetError; +}) => { + const { mutate: signIn } = usePostSignin(); + const router = useRouter(); + const onSubmit: SubmitHandler = (data) => { + signIn(data, { + onSuccess: () => { + router.push('/social'); //TODO: useReferer 추가 + }, + onError: (error: Error) => { + const errorData = JSON.parse(error.message); + if ( + errorData.code === 'VALIDATION_ERROR' || + errorData.code === 'USER_NOT_FOUND' + ) { + setError('email', { + type: 'manual', + message: errorData.message, + }); + } + if (errorData.code === 'INVALID_CREDENTIALS') { + setError('password', { + type: 'manual', + message: errorData.message, + }); + } + }, + }); + }; + + return { onSubmit }; +}; + +export default useSignInForm; From da356cba1cdef65fcafa589117f414cdb76f0773 Mon Sep 17 00:00:00 2001 From: swimmingRiver Date: Tue, 17 Jun 2025 10:47:34 +0900 Subject: [PATCH 09/29] =?UTF-8?q?refactor:=20ssr=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/auths/signin/page.tsx | 135 +++------------------------------- 1 file changed, 11 insertions(+), 124 deletions(-) diff --git a/src/app/auths/signin/page.tsx b/src/app/auths/signin/page.tsx index 2b31c3cd..e6e1b449 100644 --- a/src/app/auths/signin/page.tsx +++ b/src/app/auths/signin/page.tsx @@ -1,63 +1,15 @@ -'use client'; -import Button from '@/components/common/Button/Button'; -import InputForm from '@/components/common/Form/InputForm'; +import SignInForm from './_components/SignInForm'; +import { getMyInfoOnServer } from '@/providers/auth-provider/authProviderUtil'; +import { headers } from 'next/headers'; +import { redirect } from 'next/navigation'; +import LinkComponent from './_components/LinkComponent'; -import { VisibilityOff, VisibilityOn } from '@public/assets/icons'; -import { usePostSignin } from '@/hooks/api/auth/usePostSignin'; -import { SigninRequest } from '@/api/auth/type'; +const SignIn = async () => { + const { isSignIn } = await getMyInfoOnServer(); + const referer = (await headers()).get('referer'); -import Link from 'next/link'; -import { useRouter } from 'next/navigation'; - -import { useEffect } from 'react'; -import { SubmitHandler, useForm } from 'react-hook-form'; -import useBoolean from '@/hooks/useBoolean'; -import { useAuth } from '@/providers/auth-provider/AuthProvider.client'; -import { APP_ROUTES } from '@/constants/appRoutes'; - -const SignIn = () => { - const { value: isShowPassword, toggle: toggleIsShowPassword } = useBoolean(); - const router = useRouter(); - const { - register, - handleSubmit, - setError, - formState: { isSubmitting, errors }, - } = useForm(); - const { mutate: signIn } = usePostSignin(); - const { isSignIn } = useAuth(); - const onSubmit: SubmitHandler = (data) => { - signIn(data, { - onSuccess: () => { - router.push('/social'); - }, - onError: (error: Error) => { - const errorData = JSON.parse(error.message); - if ( - errorData.code === 'VALIDATION_ERROR' || - errorData.code === 'USER_NOT_FOUND' - ) { - setError('email', { - type: 'manual', - message: errorData.message, - }); - } - if (errorData.code === 'INVALID_CREDENTIALS') { - setError('password', { - type: 'manual', - message: errorData.message, - }); - } - }, - }); - }; - useEffect(() => { - if (isSignIn) { - router.push(APP_ROUTES.social); - } - }, []); if (isSignIn) { - return
Loading...
; + redirect(referer ?? '/'); } return (
@@ -65,73 +17,8 @@ const SignIn = () => {

로그인

-
-
- -
-
- - {isShowPassword ? ( - - ) : ( - - )} - - } - type={isShowPassword ? 'text' : 'password'} - /> -
- -
-
- WE WRITE가 처음이신가요? - - 회원가입 - -
+ +
); From f00632b9c6b071e419792beec92a0a076203a5d1 Mon Sep 17 00:00:00 2001 From: swimmingRiver Date: Tue, 17 Jun 2025 11:52:26 +0900 Subject: [PATCH 10/29] =?UTF-8?q?fix:=20=ED=83=80=EC=9E=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/auths/_components/FormField.tsx | 13 +++++++------ src/app/auths/_components/PasswordFormField.tsx | 3 ++- src/app/auths/signup/_components/SignupForm.tsx | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/app/auths/_components/FormField.tsx b/src/app/auths/_components/FormField.tsx index 80e55f2f..dee22707 100644 --- a/src/app/auths/_components/FormField.tsx +++ b/src/app/auths/_components/FormField.tsx @@ -3,25 +3,26 @@ import InputForm from '@/components/common/Form/InputForm'; import { FormFieldProps } from './type'; import { SignInFormData } from '@/api/auth/type'; import { SignUpFormData } from '@/api/auth/type'; +import { FieldErrors, Path } from 'react-hook-form'; -const FormField = ({ +const FormField = ({ name, label, placeholder, register, errors, validate, -}: FormFieldProps) => { +}: FormFieldProps) => { return ( } size={46} // 입력 필드 너비 지정 label={label} placeholder={placeholder} - hasError={!!errors[name]} - helperText={errors[name]?.message as string} + hasError={!!errors[name as keyof FieldErrors]} + helperText={errors[name as keyof FieldErrors]?.message as string} register={{ - ...register(name, { + ...register(name as Path, { validate: (value) => validate({ value, name }), }), }} diff --git a/src/app/auths/_components/PasswordFormField.tsx b/src/app/auths/_components/PasswordFormField.tsx index 33d2dcb2..fd76b4cd 100644 --- a/src/app/auths/_components/PasswordFormField.tsx +++ b/src/app/auths/_components/PasswordFormField.tsx @@ -2,6 +2,7 @@ import InputForm from '@/components/common/Form/InputForm'; import { PasswordFormFieldProps } from './type'; import { Eye, EyeOff } from 'lucide-react'; import { SignInFormData, SignUpFormData } from '@/api/auth/type'; +import { Path } from 'react-hook-form'; const PasswordFormField = ({ name, @@ -24,7 +25,7 @@ const PasswordFormField = ({ hasError={!!errors[name as keyof typeof errors]} helperText={errors[name as keyof typeof errors]?.message as string} register={{ - ...register(name as keyof T, { + ...register(name as Path, { validate: (value) => validate({ value, name, password }), }), }} diff --git a/src/app/auths/signup/_components/SignupForm.tsx b/src/app/auths/signup/_components/SignupForm.tsx index c5f2c88d..20b2eb96 100644 --- a/src/app/auths/signup/_components/SignupForm.tsx +++ b/src/app/auths/signup/_components/SignupForm.tsx @@ -27,7 +27,7 @@ const SignupForm = () => { return (
- name="name" label="닉네임" placeholder="닉네임을 입력해주세요" @@ -67,7 +67,7 @@ const SignupForm = () => { placeholder="비밀번호를 다시 한 번 입력해주세요" register={register} validate={singUpValidate} - password={getValues('password') ?? ''} + password={getValues('password')} errors={errors} isShowPassword={showPasswordCheck} toggleShowPassword={toggleShowPasswordCheck} From 3fd19100f70dd99cae0e022cb724d15a1421b4ef Mon Sep 17 00:00:00 2001 From: swimmingRiver Date: Tue, 17 Jun 2025 13:28:49 +0900 Subject: [PATCH 11/29] =?UTF-8?q?refactor:=20=EC=A0=91=EA=B7=BC=EC=84=B1?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/auths/_components/PasswordFormField.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/auths/_components/PasswordFormField.tsx b/src/app/auths/_components/PasswordFormField.tsx index 55410a41..57c7ca50 100644 --- a/src/app/auths/_components/PasswordFormField.tsx +++ b/src/app/auths/_components/PasswordFormField.tsx @@ -29,7 +29,8 @@ const PasswordFormField = ({ }} suffixIcon={ - } - /> - ); -}; -export default PasswordFormField; diff --git a/src/app/auths/_components/type.ts b/src/app/auths/_components/type.ts deleted file mode 100644 index a3d9ffce..00000000 --- a/src/app/auths/_components/type.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { SigninRequest, SignUpFormData } from '@/api/auth/type'; -import { AuthValidateProps } from '@/utils/validators/type'; -import { FieldErrors, UseFormRegister } from 'react-hook-form'; - -export interface FormFieldProps { - name: keyof T; - label: string; - placeholder: string; - register: UseFormRegister; - errors: FieldErrors; - validate: (props: AuthValidateProps) => string | true; -} - -export interface PasswordFormFieldProps< - T extends SignUpFormData | SigninRequest, -> extends FormFieldProps { - isShowPassword: boolean; - toggleShowPassword: () => void; - password?: string; -} diff --git a/src/app/auths/signin/_components/SignInForm.tsx b/src/app/auths/signin/_components/SignInForm.tsx index 4d2b4394..d371e749 100644 --- a/src/app/auths/signin/_components/SignInForm.tsx +++ b/src/app/auths/signin/_components/SignInForm.tsx @@ -1,10 +1,10 @@ 'use client'; import Button from '@/components/common/Button/Button'; -import PasswordFormField from '../../_components/PasswordFormField'; +import InputForm from '@/components/common/Form/InputForm'; import useBoolean from '@/hooks/useBoolean'; -import { signInValidate } from '@/utils/validators/auth'; -import FormField from '../../_components/FormField'; import { useSignInForm } from '@/hooks/api/auth/useSignInForm'; +import { VisibilityOff, VisibilityOn } from '@public/assets/icons'; +import { signInValidate } from '@/utils/validators/auth'; const SignInForm = () => { const { value: isShowPassword, toggle: toggleIsShowPassword } = useBoolean(); @@ -14,24 +14,41 @@ const SignInForm = () => { return ( - signInValidate({ value, name: 'email' }), + })} + type="email" + hasError={!!errors.email} + helperText={errors.email?.message} /> - signInValidate({ value, name: 'password' }), + })} + type={isShowPassword ? 'text' : 'password'} + hasError={!!errors.password} + helperText={errors.password?.message} + suffixIcon={ + + } /> + } + type={showPassword ? 'text' : 'password'} placeholder="비밀번호를 입력해주세요" - register={register} - validate={signUpValidate} - errors={errors} - isShowPassword={showPassword} - toggleShowPassword={toggleShowPassword} + register={{ + ...register('password', { + validate: (value) => + signUpValidate({ value, name: 'password' }), + }), + }} + hasError={!!errors.password} + helperText={errors.password?.message} />
- + {showPasswordCheck ? ( + + ) : ( + + )} + + } + type={showPasswordCheck ? 'text' : 'password'} placeholder="비밀번호를 다시 한 번 입력해주세요" - register={register} - validate={signUpValidate} - password={getValues('password')} - errors={errors} - isShowPassword={showPasswordCheck} - toggleShowPassword={toggleShowPasswordCheck} + register={{ + ...register('passwordCheck', { + validate: (value) => + signUpValidate({ + value, + name: 'passwordCheck', + password: getValues('password'), + }), + }), + }} + hasError={!!errors.passwordCheck} + helperText={errors.passwordCheck?.message} />
- signUpValidate({ value, name: 'companyName' }), + }), + }} + hasError={!!errors.companyName} + helperText={errors.companyName?.message} />