Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[기능구현] 회원가입 #59

Merged
merged 8 commits into from
Oct 11, 2024
18 changes: 16 additions & 2 deletions src/pages/common/register/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { RegisterType } from './components/register-type';
import { Tos } from './components/tos';
import { FormValues } from './types';
import { BasicButton } from '@/shared/components/common/button';
import useRegister from '@/shared/hooks/useRegister';
import { Divider } from '@chakra-ui/react';
import styled from '@emotion/styled';

Expand All @@ -17,13 +18,26 @@ const RegisterPage = () => {
formState: { errors },
} = useForm<FormValues>();

// 회원가입 처리
const mutation = useRegister();

const handleUserType = (id: string) => {
setUserType(id);
};

const onSubmit = (data: FormValues) => {
// 회원가입 api
console.log(userType, data);
// request 에 맞게 데이터 병합
const isSinitto = userType === 'sinitto';

const requestData = {
name: data.name,
phoneNumber: data.phoneNumber,
email: '[email protected]', // 임시 (카카오 로그인 후 넘겨받기)
isSinitto,
};
console.log(requestData);
// 회원가입 API 호출
mutation.mutate(requestData);
};

return (
Expand Down
53 changes: 53 additions & 0 deletions src/shared/api/auth/user-register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { fetchInstance } from '../instance';

// request(요청) 타입
export type SignupReguestParams = {
name: string;
phoneNumber: string;
email: string;
isSinitto: boolean;
};

// response(응답) 타입 - 성공
export type SignupResponse = {
accessToken: string;
refreshToken: string;
isSinitto?: 'true' | 'false';
};

// 에러(아직 정확히 에러코드 확인 x) or 예외
export type SignupErrorResponse = {
status: number;
detail: string;
};

// 공통 타입 정의 (onSuccess 내부에서 분기)
export type SignupApiResponse = SignupResponse | SignupErrorResponse;

export const registerUser = async ({
name,
phoneNumber,
email,
isSinitto,
}: SignupReguestParams): Promise<SignupApiResponse> => {
try {
// 시니또 보호자에 따라 API 엔드포인트 구분
const endpoint = isSinitto ? 'sinitto' : 'guard';

const response = await fetchInstance.post(`/api/members/${endpoint}`, {
name,
phoneNumber,
email,
isSinitto,
});
if (response.status === 207) {
return {
status: response.status,
detail: response.data.detail,
} as SignupErrorResponse; // 207 (예외 - 중복 이메일)
}
return response.data; // 200
} catch (err) {
throw new Error('회원가입 실패');
}
};
4 changes: 3 additions & 1 deletion src/shared/api/instance/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ const initInstance = (config: AxiosRequestConfig): AxiosInstance => {
return instance;
};

export const BASE_URL = 'http://43.201.254.198:8080';

export const fetchInstance = initInstance({
baseURL: 'https://api.example.com',
baseURL: 'http://43.201.254.198:8080',
Comment on lines +20 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이부분은 제가 수정할게요..

});

export const queryClient = new QueryClient({
Expand Down
47 changes: 47 additions & 0 deletions src/shared/hooks/useRegister.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useRegister.ts는 회원가입 페이지에서만 쓰이는데, pages/common/register 폴더 안에 /api 또는 /api/hooks를 만들어야할 것 같습니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 그렇네요!

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useNavigate } from 'react-router-dom';

import { AxiosError } from 'axios';

import { RouterPath } from '@/app/routes/path';
import {
SignupApiResponse,
registerUser,
} from '@/shared/api/auth/user-register';
import { authLocalStorage } from '@/shared/utils/storage';
import { useMutation } from '@tanstack/react-query';

const useRegister = () => {
const navigate = useNavigate();

const handleSuccess = (data: SignupApiResponse) => {
if ('status' in data && data.status === 207) {
alert(data.detail);
} else {
console.log(data);
if ('accessToken' in data) {
authLocalStorage.set(data.accessToken);
authLocalStorage.set(data.refreshToken);
alert('회원가입이 완료되었습니다.');
navigate(data.isSinitto === 'true' ? RouterPath.ROOT : RouterPath.ROOT);
}
}
};

const handleError = (error: AxiosError) => {
if (error.response && error.response.data) {
alert('회원가입 중 오류가 발생했습니다.');
} else {
alert('회원가입 중 네트워크 오류가 발생했습니다.');
}
};

const mutation = useMutation({
mutationFn: registerUser,
onSuccess: handleSuccess,
onError: handleError,
});

return mutation;
};

export default useRegister;
24 changes: 24 additions & 0 deletions src/shared/utils/storage/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
type StorageKey = {
accessToken?: string;
};

const initStorage = <T extends keyof StorageKey>(key: T, storage: Storage) => {
const storageKey = `${key}`;

const get = (): StorageKey[T] => {
const value = storage.getItem(storageKey);
return value as StorageKey[T];
};

const set = (value: StorageKey[T]) => {
if (value == undefined || value == null) {
return storage.removeItem(storageKey);
}
const stringifiedValue = JSON.stringify(value);
storage.setItem(storageKey, stringifiedValue);
};

return { get, set };
};

export const authLocalStorage = initStorage('accessToken', localStorage);
Comment on lines +1 to +24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 코드는 step2에서 강사님이 사용하신 코드 같은데, 혹시 어떤 기능을 하는지 알 수 있을까요? 제가 이 코드에 대해 잘 이해를 못해서..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

부족하지만, 제가 정리한 내용입니다..!