Skip to content

Commit

Permalink
Merge pull request #239 from bankidz/refactor/reactQuery
Browse files Browse the repository at this point in the history
Refactor/react query
  • Loading branch information
9yujin authored Sep 16, 2022
2 parents 53e6147 + 49fe543 commit 0d6ec4e
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 113 deletions.
47 changes: 18 additions & 29 deletions src/components/register/RegisterRole.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import styled from 'styled-components';
import { useState } from 'react';
import { useAppDispatch, useAppSelector } from '@store/app/hooks';
import { register, selectBirthday } from '@store/slices/authSlice';
import useAxiosPrivate from '@lib/hooks/auth/useAxiosPrivate';
import { selectBirthday, setProfile } from '@store/slices/authSlice';
import RoleButton from '../common/buttons/RoleButton';
import useModals from '../../lib/hooks/useModals';
import Modals from '../common/modals/Modals';
import { modals } from '../common/modals/Modals';
import { TFetchStatus } from '@lib/types/TFetchStatus';
import useGlobalBottomSheet from '@lib/hooks/useGlobalBottomSheet';
import GuideTemplate from '@components/manage/guides/GuideTemplate';
import userApi from '@lib/apis/user/userApi';
import { useMutation } from 'react-query';

function RegisterRole() {
const birthday = useAppSelector(selectBirthday);
Expand All @@ -18,7 +18,7 @@ function RegisterRole() {
const [isTutorial, setIsTutorial] = useState<boolean>(false);

const { openModal } = useModals();
function handleModalOpen(isKid: boolean, isFemale: boolean) {
const handleModalOpen = (isKid: boolean, isFemale: boolean) => {
openModal(modals.primaryModal, {
onSubmit: () => {
setIsTutorial(true);
Expand All @@ -28,36 +28,25 @@ function RegisterRole() {
headerText: '뱅키즈 첫 가입을 축하해요',
bodyText: '뱅키와 저금을 통해 돈길만 걸어요',
});
}
};

const dispatch = useAppDispatch();
const { isOpen, setOpenBottomSheet, setCloseBottomSheet } =
useGlobalBottomSheet();
const axiosPrivate = useAxiosPrivate();
const [registerStatus, setRegisterStatus] = useState<TFetchStatus>('idle');
const canRegister = birthday && registerStatus === 'idle';

async function handleSubmit(isKid: boolean, isFemale: boolean) {
if (canRegister) {
try {
setRegisterStatus('pending');
await dispatch(
register({
axiosPrivate,
birthday,
isKid,
isFemale,
}),
).unwrap();
setCloseBottomSheet();
handleModalOpen(isKid, isFemale);
} catch (error: any) {
console.error(error);
} finally {
setRegisterStatus('idle');
}
}
}
// PATCH: 생년월일과 역할 정보가 없는 회원에 대해 입력받은 정보를 서버로 전송
const patchUserMutation = useMutation(userApi.patchUser, {
onSuccess: (data) => {
const { username, isFemale, isKid, birthday, phone } = data;
dispatch(setProfile({ username, isFemale, isKid, birthday, phone }));
setCloseBottomSheet();
handleModalOpen(isKid, isFemale);
},
});

const handleSubmit = async (isKid: boolean, isFemale: boolean) => {
patchUserMutation.mutate({ isKid, isFemale, birthday });
};

const openSelectProfileSheet = (isKid: boolean, isFemale: boolean) => {
setOpenBottomSheet({
Expand Down
2 changes: 1 addition & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ root.render(
<ThemeProvider theme={theme}>
<ModalsContextProvider>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
<ReactQueryDevtools initialIsOpen />
<App />
<GlobalBottomSheet />
</QueryClientProvider>
Expand Down
11 changes: 11 additions & 0 deletions src/lib/apis/challenge/challengeAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { axiosPrivateTemp } from '../axios';
import { IDongilDTO } from './challengeDTO';

const challengeAPI = {
getChallenge: async (): Promise<IDongilDTO> => {
const response = await axiosPrivateTemp.get('/challenge/progress');
return response.data;
},
};

export default challengeAPI;
32 changes: 32 additions & 0 deletions src/lib/apis/challenge/challengeDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { TDongilCategory } from '@lib/types/TDongilCategory';
import { TDongilStatus } from '@lib/types/TDongilStatus';
import { TItemName } from '@lib/types/TItemName';

export interface IProgressDTO {
approvedAt: string;
challengeId: number;
challengeStatus: TDongilStatus;
isAchieved: boolean;
weeks: number;
}

export interface IDongilDTO {
challengeCategory: string;
challengeStatus: TDongilStatus;
comment: {
content: string;
id: number;
};
createdAt: string;
fileName: string;
interestPrice: number;
interestRate: number;
isMom: boolean;
itemName: TItemName;
progressList: IDongilDTO[];
successWeeks: number;
title: string;
totalPrice: number;
weekPrice: number;
weeks: number;
}
11 changes: 11 additions & 0 deletions src/lib/apis/kakao/kakaoAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { axiosPublic } from '../axios';
import { ILoginDTO } from './kakaoDTO';

const kakaoAPI = {
login: async (code: string): Promise<ILoginDTO> => {
const response = await axiosPublic.post('/kakao/login', code);
return response.data.data;
},
};

export default kakaoAPI;
8 changes: 8 additions & 0 deletions src/lib/apis/kakao/kakaoDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { TLevel } from '@lib/types/TLevel';

export interface ILoginDTO {
accessToken: string;
isKid: boolean;
level: TLevel;
provider: string;
}
6 changes: 6 additions & 0 deletions src/lib/apis/user/user.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ export interface IUserDTO {
phone: string | null;
}

export interface IUserTypeRequest {
birthday: string;
isFemale: boolean;
isKid: boolean;
}

export interface IKidDTO {
achievedChallenge: number;
totalChallenge: number;
Expand Down
18 changes: 17 additions & 1 deletion src/lib/apis/user/userApi.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { axiosPrivateTemp } from '../axios';
import { IMyPageDTO, IOptInDTO } from './user.dto';
import { IMyPageDTO, IOptInDTO, IUserDTO, IUserTypeRequest } from './user.dto';

const userApi = {
getUser: async (): Promise<IMyPageDTO> => {
Expand All @@ -8,16 +8,32 @@ const userApi = {
const data = response.data;
return data;
},

patchUser: async ({
birthday,
isFemale,
isKid,
}: IUserTypeRequest): Promise<IUserDTO> => {
const response = await axiosPrivateTemp.patch('/user', {
birthday,
isFemale,
isKid,
});
return response.data;
},

getUserOptIn: async (): Promise<IOptInDTO> => {
const response = await axiosPrivateTemp.get('/user/opt-in');
const data = response.data;
return data;
},

patchNoticeAlert: async (): Promise<IOptInDTO> => {
const response = await axiosPrivateTemp.patch('/user/notice');
const data = response.data;
return data;
},

patchServiceAlert: async (): Promise<IOptInDTO> => {
const response = await axiosPrivateTemp.patch('/user/service');
const data = response.data;
Expand Down
35 changes: 25 additions & 10 deletions src/lib/constants/queryKeys.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
const queryKeys = {
FAMILY: 'family',
FAMILY_KID: 'family_kid',

USER: 'user',
USER_OPTIN: 'user_optIn',

NOTICE: 'notice',

NOTIFICATION: 'notification',
NOTIFICATION_IS_READ: 'notification_isRead',
/** apple-controller */
APPLE_LOGIN: '/apple/login',
APPLE_REVOKE: '/apple/revoke',
/** challenge-controller */
CHALLENGE: '/challenge',
CHALLENGE_ACHIEVED: '/challenge/achieved',
CHALLENGE_KID: '/challenge/kid',
CHALLENGE_KID_ACHIEVED: '/challenge/kid/achieved',
CHALLENGE_KID_PROGRESS: '/challenge/kid/progress',
CHALLENGE_PROGRESS: '/challenge/progress',
/** family-controller */
FAMILY: '/family',
FAMILY_KID: '/family_kid',
/** health-check-controller */
HEALTH: '/health',
/** notice-controller */
NOTICE: '/notice',
/** notification-controller */
NOTIFICATION: '/notification',
NOTIFICATION_IS_READ: '/notification_isRead',
/** s-3-controller */
S3_URL: '/s3/url',
/** user-controller */
USER: '/user',
USER_OPTIN: '/user_optIn',
};

export default queryKeys;
2 changes: 1 addition & 1 deletion src/lib/utils/localStorage/setLocalStorage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TLocalStorageKey } from '../../types/TLocalStorageKey';

/**
* @param key 필요 시 key를 TKey에 추가해주세요.
* @param key 필요 시 key를 TLocalStorageKey에 추가해주세요.
*/
function setLocalStorage(key: TLocalStorageKey, value: any) {
localStorage.setItem(key, JSON.stringify(value));
Expand Down
69 changes: 40 additions & 29 deletions src/pages/Home/KidHomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import {
} from '@store/slices/familySlice';
import { useEffect } from 'react';
import usePreventGoBack from '@lib/hooks/usePreventGoBack';
import { useQuery } from 'react-query';
import queryKeys from '@lib/constants/queryKeys';
import familyApi from '@lib/apis/family/familyApi';
import { AxiosError } from 'axios';
import { IFamilyDTO } from '@lib/apis/family/family.dto';
import CustomSyncLoader from '@components/common/CustomSyncLoader';
import styled from 'styled-components';

// 자녀홈의 계층 구조는 다음과 같습니다.
// 1. KidHomePage: 연결된 가족 fetch
Expand All @@ -18,37 +25,41 @@ import usePreventGoBack from '@lib/hooks/usePreventGoBack';
// 3. ParentHome: FixedBar, Background 제외 UI 요소 랜더링 및 관련 데이터 fetch

function KidHomePage() {
const familyStatus = useAppSelector(selectFamilyStatus);
const dispatch = useAppDispatch();
const axiosPrivate = useAxiosPrivate();
useEffect(() => {
async function dispatchFetchFamily() {
try {
familyStatus === 'idle' &&
(await dispatch(fetchFamily({ axiosPrivate })).unwrap());
} catch (error: any) {
console.log(error);
}
}
dispatchFetchFamily();
}, []);

const family = useAppSelector(selectFamily);
const hasNoFamily = family?.length === 0 && familyStatus === 'succeeded';

usePreventGoBack();
const {
status,
data: family,
error,
} = useQuery<IFamilyDTO, AxiosError>(queryKeys.FAMILY, familyApi.getFamily);
const hasNoFamily = family?.familyUserList.length === 0;

return (
<>
{hasNoFamily ? (
<NoFamily />
) : (
<HomeTemplate>
<KidHome />
</HomeTemplate>
)}
</>
);
let content;
if (status === 'loading') {
content = (
<CustomSyncLoaderWrapper>
<CustomSyncLoader />
</CustomSyncLoaderWrapper>
);
} else if (
(status === 'success' && hasNoFamily) ||
(status === 'error' && error?.response?.status === 400)
) {
content = <NoFamily />;
} else if (status === 'success' && !hasNoFamily) {
content = (
<HomeTemplate>
<KidHome />
</HomeTemplate>
);
}

return <>{content}</>;
}

export default KidHomePage;

const CustomSyncLoaderWrapper = styled.div`
overflow-y: auto;
overflow-x: hidden;
height: calc(var(--vh, 1vh) * 100);
`;
2 changes: 1 addition & 1 deletion src/pages/Manage/Notices.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const Notices = () => {
return (
<ForegroundTemplate label="공지사항">
<>
{data?.map((notice) => (
{data?.map((notice: any) => (
<NoticeItem
key={notice.id}
onClick={() => {
Expand Down
28 changes: 15 additions & 13 deletions src/pages/OnBoarding/KAKAOAuthRedirectPage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { useAppDispatch } from '@store/app/hooks';
import { login } from '@store/slices/authSlice';
import { setCredentials } from '@store/slices/authSlice';
import { useNavigate } from 'react-router-dom';
import { useEffect } from 'react';
import CustomSyncLoader from '@components/common/CustomSyncLoader';
import setLocalStorage from '@lib/utils/localStorage/setLocalStorage';
import registerEXPOToken from '@lib/utils/registerEXPOToken';
import { ILoginDTO } from '@lib/apis/kakao/kakaoDTO';
import kakaoAPI from '@lib/apis/kakao/kakaoAPI';
import { useMutation } from 'react-query';

function KAKAOAuthRedirectPage() {
// @ts-expect-error
Expand All @@ -13,19 +16,18 @@ function KAKAOAuthRedirectPage() {
const dispatch = useAppDispatch();
const navigate = useNavigate();

const kakaoLoginMutation = useMutation(kakaoAPI.login, {
onSuccess: (data: ILoginDTO) => {
const { accessToken, isKid, level, provider } = data;
setLocalStorage('accessToken', accessToken);
dispatch(setCredentials({ accessToken, isKid, level, provider })); // TODO: exclude aT
registerEXPOToken();
navigate('/');
},
});

useEffect(() => {
async function proceedLogin() {
try {
if (code) {
const response = await dispatch(login({ code })).unwrap();
}
registerEXPOToken();
navigate('/');
} catch (error: any) {
console.error(error);
}
}
code && proceedLogin();
code && kakaoLoginMutation.mutate(code);
}, []);

return <CustomSyncLoader />;
Expand Down
Loading

0 comments on commit 0d6ec4e

Please sign in to comment.