diff --git a/frontend/src/apis/apis.ts b/frontend/src/apis/apis.ts index ae068277..f775eadf 100644 --- a/frontend/src/apis/apis.ts +++ b/frontend/src/apis/apis.ts @@ -4,8 +4,8 @@ import { GetDetailedRunnerPostResponse, GetOtherSupporterPostCountResponse, GetRunnerPostResponse, - ReviewStatus, getRunnerPostRequestParams, + GetPostCountResponse, } from '@/types/runnerPost'; import { GetSearchTagResponse } from '@/types/tags'; import { @@ -108,6 +108,10 @@ export const getSupporterRank = () => { return request.get('/rank/supporter', false); }; +export const getPostCount = () => { + return request.get('/posts/runner/count', false); +}; + export const postRunnerPostCreation = (formData: CreateRunnerPostRequest) => { const body = JSON.stringify(formData); return request.post(`/posts/runner`, body); diff --git a/frontend/src/components/RunnerPost/RunnerPostFilter/RunnerPostFilter.tsx b/frontend/src/components/RunnerPost/RunnerPostFilter/RunnerPostFilter.tsx index 704df672..d08a8513 100644 --- a/frontend/src/components/RunnerPost/RunnerPostFilter/RunnerPostFilter.tsx +++ b/frontend/src/components/RunnerPost/RunnerPostFilter/RunnerPostFilter.tsx @@ -3,8 +3,9 @@ import { css, keyframes, styled } from 'styled-components'; import { REVIEW_STATUS_FILTER_TEXT } from '@/constants'; import Text from '@/components/common/Text/Text'; import Flex from '@/components/common/Flex/Flex'; -import { ReviewStatusFilter } from '@/types/runnerPost'; -import useTotalCount from '@/hooks/query/useTotalCount'; +import { PostCount, ReviewStatusFilter } from '@/types/runnerPost'; +import { usePostCount } from '@/hooks/query/usePostCount'; +import useViewport from '@/hooks/useViewport'; interface Props { reviewStatus: ReviewStatusFilter; @@ -12,7 +13,26 @@ interface Props { } const RunnerPostFilter = ({ reviewStatus, handleClickRadioButton }: Props) => { - const { totalCounts, isAllLoaded } = useTotalCount(); + const { data: totalCount } = usePostCount(); + const { isMobile } = useViewport(); + + function transformPostCountToReviewStatusFilter(postCount: PostCount): { [key in ReviewStatusFilter]: number } { + const all = Object.values(postCount).reduce((acc, currentValue) => acc + currentValue, 0); + + return { + NOT_STARTED: postCount.notStarted, + IN_PROGRESS: postCount.inProgress, + OVERDUE: postCount.overdue, + DONE: postCount.done, + ALL: all, + }; + } + + if (!totalCount) { + return
; + } + + const reviewStatusCounts = transformPostCountToReviewStatusFilter(totalCount); return ( @@ -34,7 +54,7 @@ const RunnerPostFilter = ({ reviewStatus, handleClickRadioButton }: Props) => { {text} - ({isAllLoaded ? totalCounts[value as ReviewStatusFilter] : 0}) + ({reviewStatusCounts[value as ReviewStatusFilter]}) diff --git a/frontend/src/hooks/query/usePostCount.ts b/frontend/src/hooks/query/usePostCount.ts new file mode 100644 index 00000000..de1ebabd --- /dev/null +++ b/frontend/src/hooks/query/usePostCount.ts @@ -0,0 +1,16 @@ +import { getPostCount } from '@/apis/apis'; +import { PostCount } from '@/types/runnerPost'; +import { useQuery } from '@tanstack/react-query'; + +export const usePostCount = () => { + const queryResult = useQuery({ + queryKey: ['runnerPostCount'], + + queryFn: () => getPostCount().then((res) => res.data), + }); + + return { + ...queryResult, + data: queryResult.data, + }; +}; diff --git a/frontend/src/hooks/query/useTotalCount.ts b/frontend/src/hooks/query/useTotalCount.ts deleted file mode 100644 index 26119ac2..00000000 --- a/frontend/src/hooks/query/useTotalCount.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { useQueries } from '@tanstack/react-query'; -import { getRunnerPost } from '@/apis/apis'; -import { ReviewStatusFilter } from '@/types/runnerPost'; -import { REVIEW_STATUS_FILTER } from '@/constants'; - -const useTotalCount = () => { - const reviewStatuses = REVIEW_STATUS_FILTER; - - const queryResults = useQueries({ - queries: reviewStatuses.map((status) => ({ - queryKey: ['runnerPostTotalCount', status], - - queryFn: () => getRunnerPost({ limit: 0, reviewStatus: status }).then((res) => res.pageInfo.totalCount), - })), - }); - - const isLoaded = queryResults.map((data) => { - return data.isLoading; - }); - - const isAllLoaded = isLoaded.every((don) => don === false); - - const totalCounts = queryResults.reduce((acc, result, index) => { - if (result.isSuccess) { - acc[reviewStatuses[index]] = result.data; - } - - return acc; - }, {} as { [key in ReviewStatusFilter]?: number }); - - return { totalCounts, isAllLoaded }; -}; - -export default useTotalCount; diff --git a/frontend/src/layout/MyMenu.tsx b/frontend/src/layout/MyMenu.tsx index 770651f4..426b3790 100644 --- a/frontend/src/layout/MyMenu.tsx +++ b/frontend/src/layout/MyMenu.tsx @@ -51,7 +51,7 @@ const MyMenu = () => { { diff --git a/frontend/src/mocks/data/postCount.json b/frontend/src/mocks/data/postCount.json new file mode 100644 index 00000000..12617711 --- /dev/null +++ b/frontend/src/mocks/data/postCount.json @@ -0,0 +1,8 @@ +{ + "data": { + "notStarted": 1, + "inProgress": 2, + "overdue": 3, + "done": 4 + } +} diff --git a/frontend/src/mocks/data/runnerPostList.json b/frontend/src/mocks/data/runnerPostList.json index 89c55292..405c2183 100644 --- a/frontend/src/mocks/data/runnerPostList.json +++ b/frontend/src/mocks/data/runnerPostList.json @@ -103,7 +103,6 @@ ], "pageInfo": { "isLast": false, - "nextCursor": 1, - "totalCount": 129 + "nextCursor": 1 } } diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 03b084ba..47bc06cd 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -12,6 +12,7 @@ import myPagePostList from './data/myPagePost/myPagePostList.json'; import tagList from './data/tagList.json'; import notificationList from './data/notification.json'; import rank from './data/rank.json'; +import postCount from './data/postCount.json'; import { BATON_BASE_URL } from '@/constants'; import { getRestMinute } from '@/utils/jwt'; @@ -66,6 +67,10 @@ export const handlers = [ return res(ctx.delay(300), ctx.status(201)); }), + rest.get(`${BATON_BASE_URL}/posts/runner/count`, async (req, res, ctx) => { + return res(ctx.delay(300), ctx.status(200), ctx.json(postCount)); + }), + rest.get(`${BATON_BASE_URL}/profile/me`, async (req, res, ctx) => { const jwt = req.headers.get('Authorization'); diff --git a/frontend/src/types/runnerPost.ts b/frontend/src/types/runnerPost.ts index 73a3f03a..9903cbb9 100644 --- a/frontend/src/types/runnerPost.ts +++ b/frontend/src/types/runnerPost.ts @@ -19,6 +19,17 @@ export interface RunnerPost { reviewStatus: ReviewStatus; } +export interface PostCount { + notStarted: number; + inProgress: number; + overdue: number; + done: number; +} + +export interface GetPostCountResponse { + data: PostCount; +} + export interface RunnerProfile { name: string; imageUrl: string; @@ -63,7 +74,7 @@ export interface PageInfo { interface requestParams { tagName?: string; - reviewStatus: ReviewStatus | ReviewStatusFilter | null; + reviewStatus: ReviewStatus | null; } export interface getRunnerPostRequestParams extends pageParamsRequest, requestParams {}