diff --git a/src/api/services/user/login.api.ts b/src/api/services/user/login.api.ts index 52ee0699..0d851764 100644 --- a/src/api/services/user/login.api.ts +++ b/src/api/services/user/login.api.ts @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query' -import { fetchInstance } from '@/api/instance' +import { authorizationInstance, fetchInstance } from '@/api/instance' type KakaoLoginParam = { code: string @@ -8,6 +8,7 @@ type KakaoLoginParam = { type KakaoLoginResponse = { userId: number + role: 'USER' | 'TEMP' } const kakaoLogin = async ({ code }: KakaoLoginParam) => { @@ -16,7 +17,7 @@ const kakaoLogin = async ({ code }: KakaoLoginParam) => { ) const accessToken = response.headers.authorization - return { accessToken, userId: response.data.userId } + return { accessToken, userId: response.data.userId, role: response.data.role } } export const useKakaoLogin = ({ code }: KakaoLoginParam) => { @@ -25,3 +26,27 @@ export const useKakaoLogin = ({ code }: KakaoLoginParam) => { queryFn: () => kakaoLogin({ code }), }) } + +export type RegisterUserRequestBody = { + name: string + gender: string + year: number + month: number + day: number +} + +type RegisterUeserResponse = { + userId: number + jwt: string + role: 'USER' +} + +export const registerUser = async (data: RegisterUserRequestBody) => { + const response = await authorizationInstance.post( + '/api/user/information', + data + ) + const accessToken = response.headers.authorization + + return { accessToken, userId: response.data.userId } +} diff --git a/src/pages/Layout/MainLayout/GlobalErrorFallback/index.tsx b/src/pages/Layout/MainLayout/GlobalErrorFallback/index.tsx index 56fbac6b..2cd69b6f 100644 --- a/src/pages/Layout/MainLayout/GlobalErrorFallback/index.tsx +++ b/src/pages/Layout/MainLayout/GlobalErrorFallback/index.tsx @@ -1,3 +1,4 @@ +import { useEffect } from 'react' import { FallbackProps } from 'react-error-boundary' import { useNavigate } from 'react-router-dom' @@ -18,6 +19,12 @@ export const GlobalErrorFallback = ({ const navigate = useNavigate() + useEffect(() => { + if (status === 428) { + navigate('/register') + } + }, [status, navigate]) + return ( } diff --git a/src/pages/LoginRedirectPage/LoginRedirectSection/index.tsx b/src/pages/LoginRedirectPage/LoginRedirectSection/index.tsx index 8edbacf3..6c0da335 100644 --- a/src/pages/LoginRedirectPage/LoginRedirectSection/index.tsx +++ b/src/pages/LoginRedirectPage/LoginRedirectSection/index.tsx @@ -19,6 +19,12 @@ export const LoginRedirectSection = ({ code }: LoginRedirectSectionProps) => { useEffect(() => { if (data) { + if (data.role === 'TEMP') { + setAuthToken(data.accessToken) + setMyUserId(data.userId) + navigate('/register') + return + } setAuthToken(data.accessToken) setMyUserId(data.userId) navigate('/') diff --git a/src/pages/RegisterPage/index.tsx b/src/pages/RegisterPage/index.tsx index ffdcc37f..2e885478 100644 --- a/src/pages/RegisterPage/index.tsx +++ b/src/pages/RegisterPage/index.tsx @@ -1,16 +1,70 @@ +import { useForm } from 'react-hook-form' +import { useNavigate } from 'react-router-dom' + import { - Box, Button, Flex, Heading, Input, Radio, RadioGroup, - Stack, Text, } from '@chakra-ui/react' +import { zodResolver } from '@hookform/resolvers/zod' +import { useMutation } from '@tanstack/react-query' + +import { + RegisterUserRequestBody, + registerUser, +} from '@/api/services/user/login.api' +import { + Form, + FormControl, + FormField, + FormItem, + FormMessage, +} from '@/components/Form' +import { RegisterUserFields, RegisterUserSchema } from '@/schema/user' +import { useAuthTokenStore } from '@/stores/auth-token' +import { useMyUserIdStore } from '@/stores/my-user-id' export default function RegisterPage() { + const navigate = useNavigate() + + const form = useForm({ + resolver: zodResolver(RegisterUserSchema), + mode: 'onBlur', + defaultValues: { + name: '', + gender: undefined, + year: '', + month: '', + day: '', + }, + }) + + const setAuthToken = useAuthTokenStore((state) => state.setAuthToken) + const setMyUserId = useMyUserIdStore((state) => state.setMyUserId) + + const { mutate } = useMutation({ + mutationFn: (data: RegisterUserRequestBody) => registerUser(data), + onSuccess: (data) => { + setAuthToken(data.accessToken) + setMyUserId(data.userId) + navigate('/') + }, + }) + + const onValid = () => { + mutate({ + name: form.getValues('name'), + gender: form.getValues('gender'), + year: Number(form.getValues('year')), + month: Number(form.getValues('month')), + day: Number(form.getValues('day')), + }) + } + return ( 회원가입 @@ -26,48 +80,124 @@ export default function RegisterPage() { 가입을 통해 더 다양한 서비스를 만나보세요! - - - - 이름 - - - - - - - 성별 - - - - - 남 - - - 여 - - - - - - - - 나이 - - - - - +
+ + + ( + + + + 이름 + + + + + + )} + /> + ( + + + + 성별 + + + + + 남 + + + 여 + + + + + + + )} + /> + + + 생년월일 + + + ( + + + + + + + )} + /> + ( + + + + + + + )} + /> + ( + + + + + + + )} + /> + + + + +
+
) } diff --git a/src/schema/user.ts b/src/schema/user.ts new file mode 100644 index 00000000..03d67fd2 --- /dev/null +++ b/src/schema/user.ts @@ -0,0 +1,18 @@ +import { z } from 'zod' + +export const RegisterUserSchema = z.object({ + name: z + .string() + .min(1, { message: '이름을 입력해주세요' }) + .regex(/^[가-힣]+$/, { message: '공백없이 한글만 입력해주세요' }), + gender: z.enum(['male', 'female'], { + errorMap: () => ({ message: '성별을 선택해주세요' }), + }), + year: z + .string() + .regex(/^[0-9]{4}$/, { message: '연도는 4자리 숫자로 입력해 주세요' }), + month: z.string().regex(/^[0-9]{1,2}$/, { message: '숫자만 입력해주세요' }), + day: z.string().regex(/^[0-9]{1,2}$/, { message: '숫자만 입력해주세요' }), +}) + +export type RegisterUserFields = z.infer