From 20ca82a82d355b5dca4345e48b78992321332a17 Mon Sep 17 00:00:00 2001 From: chsua Date: Fri, 15 Sep 2023 14:39:07 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20(#619)=20=ED=86=B5=EA=B3=84=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EB=A6=AC=EC=95=A1=ED=8A=B8=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=EB=A1=9C=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=84=9C?= =?UTF-8?q?=EC=8A=A4=ED=8E=9C=EC=8A=A4,=20=EC=97=90=EB=9F=AC=EB=B0=94?= =?UTF-8?q?=EC=9A=B4=EB=8D=94=EB=A6=AC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/constants/queryKey.ts | 1 + .../src/hooks/query/useVoteStatistics.tsx | 21 +++++ .../OptionStatistics/index.tsx | 45 ++++------- .../OptionWrapper/index.tsx | 35 +++++++++ .../StatisticsWrapper/index.tsx | 19 +++++ .../src/pages/VoteStatisticsPage/index.tsx | 77 +++++-------------- 6 files changed, 112 insertions(+), 86 deletions(-) create mode 100644 frontend/src/hooks/query/useVoteStatistics.tsx create mode 100644 frontend/src/pages/VoteStatisticsPage/OptionWrapper/index.tsx create mode 100644 frontend/src/pages/VoteStatisticsPage/StatisticsWrapper/index.tsx diff --git a/frontend/src/constants/queryKey.ts b/frontend/src/constants/queryKey.ts index 5d4821fa8..0d4991e29 100644 --- a/frontend/src/constants/queryKey.ts +++ b/frontend/src/constants/queryKey.ts @@ -6,4 +6,5 @@ export const QUERY_KEY = { USER_INFO: 'user_info', PASSION_RANKING: 'passion_ranking', POPULAR_RANKING: 'popular_ranking', + VOTE_STATISTICS: 'vote_statistics', }; diff --git a/frontend/src/hooks/query/useVoteStatistics.tsx b/frontend/src/hooks/query/useVoteStatistics.tsx new file mode 100644 index 000000000..61eba626b --- /dev/null +++ b/frontend/src/hooks/query/useVoteStatistics.tsx @@ -0,0 +1,21 @@ +import { useQuery } from '@tanstack/react-query'; + +import { getOptionStatistics, getPostStatistics } from '@api/voteResult'; + +import { VoteResult } from '@components/VoteStatistics/type'; + +import { QUERY_KEY } from '@constants/queryKey'; + +export const useVoteStatistics = (postId: number, optionId?: number) => { + const { data } = useQuery( + optionId ? [QUERY_KEY.VOTE_STATISTICS, postId, optionId] : [QUERY_KEY.VOTE_STATISTICS, postId], + () => (optionId ? getOptionStatistics({ postId, optionId }) : getPostStatistics(postId)), + { + cacheTime: 60 * 60 * 1000, + staleTime: 60 * 60 * 1000, + suspense: true, + } + ); + + return { data }; +}; diff --git a/frontend/src/pages/VoteStatisticsPage/OptionStatistics/index.tsx b/frontend/src/pages/VoteStatisticsPage/OptionStatistics/index.tsx index 109d720eb..e47c030fe 100644 --- a/frontend/src/pages/VoteStatisticsPage/OptionStatistics/index.tsx +++ b/frontend/src/pages/VoteStatisticsPage/OptionStatistics/index.tsx @@ -1,17 +1,14 @@ -import { useState } from 'react'; +import { Suspense, useState } from 'react'; import { WrittenVoteOptionType } from '@type/post'; import { Size } from '@type/style'; -import { useFetch } from '@hooks/useFetch'; -import { useToast } from '@hooks/useToast'; - -import { getOptionStatistics } from '@api/voteResult'; +import ErrorBoundary from '@pages/ErrorBoundary'; import LoadingSpinner from '@components/common/LoadingSpinner'; -import Toast from '@components/common/Toast'; import WrittenVoteOption from '@components/optionList/WrittenVoteOptionList/WrittenVoteOption'; -import VoteStatistics from '@components/VoteStatistics'; + +import StatisticsWrapper from '../StatisticsWrapper'; import * as S from './style'; @@ -29,17 +26,8 @@ export default function OptionStatistics({ size, }: OptionStatisticsProps) { const [isStatisticsOpen, setIsStatisticsOpen] = useState(false); - const { isToastOpen, openToast, toastMessage } = useToast(); - - const { - data: voteResult, - errorMessage, - isLoading, - } = useFetch(() => getOptionStatistics({ postId, optionId: voteOption.id })); const toggleOptionStatistics = () => { - if (!voteResult) return openToast('투표 통계 불러오기를 실패했습니다.'); - setIsStatisticsOpen(!isStatisticsOpen); }; @@ -60,26 +48,25 @@ export default function OptionStatistics({ 투표 선택지를 클릭하여 투표 통계를 열어 확인할 수 있습니다. )} - {isStatisticsOpen && voteResult && ( + {isStatisticsOpen && ( <> 투표 선택지를 클릭하여 투표 통계를 닫을 수 있습니다. - + + + + + } + > + + + )} - {isStatisticsOpen && isLoading && ( - - - - )} - {isStatisticsOpen && errorMessage} - {isToastOpen && ( - - {toastMessage} - - )} ); } diff --git a/frontend/src/pages/VoteStatisticsPage/OptionWrapper/index.tsx b/frontend/src/pages/VoteStatisticsPage/OptionWrapper/index.tsx new file mode 100644 index 000000000..2939a4452 --- /dev/null +++ b/frontend/src/pages/VoteStatisticsPage/OptionWrapper/index.tsx @@ -0,0 +1,35 @@ +import { useContext } from 'react'; +import { Navigate } from 'react-router-dom'; + +import { AuthContext } from '@hooks/context/auth'; +import { usePostDetail } from '@hooks/query/post/usePostDetail'; + +import { PATH } from '@constants/path'; + +import { checkWriter } from '@utils/post/checkWriter'; + +import OptionStatistics from '../OptionStatistics'; + +export default function OptionWrapper({ postId }: { postId: number }) { + const { isLoggedIn } = useContext(AuthContext).loggedInfo; + const { data: postDetail } = usePostDetail(isLoggedIn, postId); + + if (!isLoggedIn && postDetail && !checkWriter(postDetail.writer.id)) + return ; + + return ( + postDetail && + postDetail.voteInfo.options.map(option => { + const { postId, voteInfo } = postDetail; + return ( + + ); + }) + ); +} diff --git a/frontend/src/pages/VoteStatisticsPage/StatisticsWrapper/index.tsx b/frontend/src/pages/VoteStatisticsPage/StatisticsWrapper/index.tsx new file mode 100644 index 000000000..b249b28fa --- /dev/null +++ b/frontend/src/pages/VoteStatisticsPage/StatisticsWrapper/index.tsx @@ -0,0 +1,19 @@ +import { Size } from '@type/style'; + +import { useVoteStatistics } from '@hooks/query/useVoteStatistics'; + +import VoteStatistics from '@components/VoteStatistics'; + +export default function StatisticsWrapper({ + size, + postId, + optionId, +}: { + size: Size; + postId: number; + optionId?: number; +}) { + const { data: voteResult } = useVoteStatistics(postId, optionId); + + return voteResult && ; +} diff --git a/frontend/src/pages/VoteStatisticsPage/index.tsx b/frontend/src/pages/VoteStatisticsPage/index.tsx index a541b684a..cdb943923 100644 --- a/frontend/src/pages/VoteStatisticsPage/index.tsx +++ b/frontend/src/pages/VoteStatisticsPage/index.tsx @@ -1,44 +1,22 @@ -import { Navigate, useNavigate, useParams } from 'react-router-dom'; +import { Suspense } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; -import { useFetch } from '@hooks/useFetch'; +import ErrorBoundary from '@pages/ErrorBoundary'; -import { getPost } from '@api/post'; -import { getPostStatistics } from '@api/voteResult'; - -import ErrorMessage from '@components/common/ErrorMessage'; import IconButton from '@components/common/IconButton'; import Layout from '@components/common/Layout'; +import LoadingSpinner from '@components/common/LoadingSpinner'; import NarrowTemplateHeader from '@components/common/NarrowTemplateHeader'; -import Skeleton from '@components/common/Skeleton'; -import VoteStatistics from '@components/VoteStatistics'; - -import { PATH } from '@constants/path'; -import { checkWriter } from '@utils/post/checkWriter'; - -import OptionStatistics from './OptionStatistics'; +import OptionWrapper from './OptionWrapper'; +import StatisticsWrapper from './StatisticsWrapper'; import * as S from './style'; export default function VoteStatisticsPage() { const params = useParams() as { postId: string }; const postId = Number(params.postId); - const navigate = useNavigate(); - const { - data: postDetail, - errorMessage: postError, - isLoading: isPostLoading, - } = useFetch(() => getPost(postId)); - - const { - data: voteResultResponse, - errorMessage: voteResultError, - isLoading: isVoteResultLoading, - } = useFetch(() => getPostStatistics(postId)); - - if (postDetail && !checkWriter(postDetail.writer.id)) return ; - return ( @@ -48,37 +26,22 @@ export default function VoteStatisticsPage() { 투표 통계 - {postError && } - {isPostLoading && ( - - - - )} - {postDetail && ( - - {voteResultError && } - {isVoteResultLoading && ( + + - + - )} - {voteResultResponse && ( - - )} - {postDetail.voteInfo.options.map(option => { - const { postId, voteInfo } = postDetail; - return ( - - ); - })} - - )} + } + > + + + + + + + + );