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

랭킹 UI와 hook 연결 및 msw 도입 (+변경된 랭킹 객체 타입 적용) #525

Merged
merged 7 commits into from
Sep 5, 2023
4 changes: 2 additions & 2 deletions frontend/src/api/ranking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export const getUserRanking = async (isLoggedIn: boolean) => {
};

export const getPassionUserRanking = async () => {
return await getFetch<PassionUser>(`${BASE_URL}/members/ranking/passion/guest`);
return await getFetch<PassionUser[]>(`${BASE_URL}/members/ranking/passion/guest`);
};

export const getPopularPostRanking = async () => {
return await getFetch<RankingPost>(`${BASE_URL}/posts/ranking/popular/guest`);
return await getFetch<RankingPost[]>(`${BASE_URL}/posts/ranking/popular/guest`);
};
2 changes: 1 addition & 1 deletion frontend/src/hooks/query/ranking/usePassionUserRanking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getPassionUserRanking } from '@api/ranking';
import { QUERY_KEY } from '@constants/queryKey';

export const usePassionUserRanking = () => {
const { data, error, isLoading, isError } = useQuery<PassionUser>(
const { data, error, isLoading, isError } = useQuery<PassionUser[]>(
[QUERY_KEY.PASSION_RANKING],
getPassionUserRanking,
{
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/hooks/query/ranking/usePopularPostRanking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getPopularPostRanking } from '@api/ranking';
import { QUERY_KEY } from '@constants/queryKey';

export const usePopularPostRanking = () => {
const { data, error, isLoading, isError } = useQuery<RankingPost>(
const { data, error, isLoading, isError } = useQuery<RankingPost[]>(
[QUERY_KEY.POPULAR_RANKING],
getPopularPostRanking,
{
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/hooks/query/ranking/useUserRanking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getUserRanking } from '@api/ranking';

import { QUERY_KEY } from '@constants/queryKey';

export const usePassionUserRanking = (isLoggedIn: boolean) => {
export const useUserRanking = (isLoggedIn: boolean) => {
const { data, error, isLoading, isError } = useQuery<PassionUser | null>(
[QUERY_KEY.USER_INFO, isLoggedIn, QUERY_KEY.PASSION_RANKING],
() => getUserRanking(isLoggedIn),
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { example } from './example/get';
import { mockVoteResult } from './getVoteDetail';
import { mockPost } from './post';
import { mockPostList } from './postList';
import { mockRanking } from './ranking';
import { mockReport } from './report';
import { mockUserInfo } from './userInfo';
import { mockVote } from './vote';
Expand All @@ -18,4 +19,5 @@ export const handlers = [
...mockUserInfo,
...mockComment,
...mockReport,
...mockRanking,
];
50 changes: 50 additions & 0 deletions frontend/src/mocks/ranking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { rest } from 'msw';

import { PassionUser, RankingPost } from '@type/ranking';

const userRankingInfo: PassionUser = {
ranking: 1111,
nickname: 'wow',
postCount: 1,
voteCount: 3,
score: 8,
};

const rankerInfo: PassionUser = {
ranking: 1,
nickname: 'gil-dong',
postCount: 11,
voteCount: 79,
score: 134,
};

const rankerList: PassionUser[] = new Array(10)
.fill(rankerInfo)
.map((ranker, index) => ({ ...ranker, ranking: index + 1 }));

const rankingPostInfo: RankingPost = {
ranking: 1,
post: {
id: 29,
writer: 'writer',
title: '이것은 엄청나게 많은 투표가 이루어진 대단한 글이지요',
voteCount: 10,
},
};
const rankingPostList: RankingPost[] = new Array(10)
.fill(rankingPostInfo)
.map((post, index) => ({ ...post, ranking: index + 1 }));
Copy link
Member

Choose a reason for hiding this comment

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

호오.. 레전드 선언형 코드인걸요?


export const mockRanking = [
rest.get('/members/me/ranking', (req, res, ctx) => {
return res(ctx.status(200), ctx.delay(500), ctx.json(userRankingInfo));
}),

rest.get('/members/ranking/passion/guest', (req, res, ctx) => {
return res(ctx.status(200), ctx.delay(1000), ctx.json(rankerList));
}),

rest.get('/posts/ranking/popular/guest', (req, res, ctx) => {
return res(ctx.status(200), ctx.delay(500), ctx.json(rankingPostList));
}),
];
26 changes: 2 additions & 24 deletions frontend/src/pages/Ranking/PassionUser/PassionUser.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react';

import { PassionUser } from '@type/ranking';

import PassionUserRanking from '.';

const meta: Meta<typeof PassionUserRanking> = {
Expand All @@ -11,30 +9,10 @@ const meta: Meta<typeof PassionUserRanking> = {
export default meta;
type Story = StoryObj<typeof PassionUserRanking>;

const rankerInfo: PassionUser = {
rank: 1,
nickname: 'gil-dong',
postCount: 11,
voteCount: 79,
score: 134,
};

const userRankingInfo: PassionUser = {
rank: 1111,
nickname: 'wow',
postCount: 1,
voteCount: 3,
score: 8,
};

const rankerList: PassionUser[] = new Array(10)
.fill(rankerInfo)
.map((ranker, index) => ({ ...ranker, rank: index + 1 }));

export const User: Story = {
render: () => <PassionUserRanking rankerList={rankerList} userRanking={userRankingInfo} />,
render: () => <PassionUserRanking />,
};

export const Guest: Story = {
render: () => <PassionUserRanking rankerList={rankerList} />,
render: () => <PassionUserRanking />,
};
25 changes: 25 additions & 0 deletions frontend/src/pages/Ranking/PassionUser/UserRanking/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { useContext } from 'react';

import { AuthContext } from '@hooks/context/auth';
import { useUserRanking } from '@hooks/query/ranking/useUserRanking';

import * as S from '../style';

export default function UserRanking() {
const { loggedInfo } = useContext(AuthContext);
const { isLoggedIn } = loggedInfo;

const { data: userRanking } = useUserRanking(isLoggedIn);

return (
userRanking && (
<S.Tr>
<S.Td>{userRanking.ranking}</S.Td>
<S.Td>{userRanking.nickname}</S.Td>
<S.Td>{userRanking.postCount}</S.Td>
<S.Td>{userRanking.voteCount}</S.Td>
<S.Td>{userRanking.score}</S.Td>
</S.Tr>
)
);
}
65 changes: 34 additions & 31 deletions frontend/src/pages/Ranking/PassionUser/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { PassionUser } from '@type/ranking';
import { Suspense } from 'react';

import { usePassionUserRanking } from '@hooks/query/ranking/usePassionUserRanking';

import ErrorBoundary from '@pages/ErrorBoundary';

import LoadingSpinner from '@components/common/LoadingSpinner';

import firstRankIcon from '@assets/first-rank.svg';
import secondRankIcon from '@assets/second-rank.svg';
import thirdRankIcon from '@assets/third-rank.svg';

import * as RS from '../RankingTableStyle';

import * as S from './style';
import UserRanking from './UserRanking';

const columnNameList = ['등수', '닉네임', '작성글 수', '투표 수', '점수'];

Expand All @@ -16,45 +21,43 @@ const rankIconUrl: Record<number, string> = {
3: thirdRankIcon,
};

interface PassionUserRankingProps {
rankerList: PassionUser[];
userRanking?: PassionUser;
}
export default function PassionUserRanking() {
const { data: rankerList } = usePassionUserRanking();

export default function PassionUserRanking({ rankerList, userRanking }: PassionUserRankingProps) {
return (
<RS.Background>
<S.Table>
<S.Tr>
{columnNameList.map(text => (
<S.Th key={text}>{text}</S.Th>
))}
</S.Tr>
{rankerList.map(ranker => {
const rankIcon = rankIconUrl[ranker.rank] && (
<img src={rankIconUrl[ranker.rank]} alt={ranker.rank.toString()} />
<S.Table>
<S.Tr>
{columnNameList.map(text => (
<S.Th key={text}>{text}</S.Th>
))}
</S.Tr>
{rankerList &&
rankerList.map(ranker => {
const rankIcon = rankIconUrl[ranker.ranking] && (
<img src={rankIconUrl[ranker.ranking]} alt={ranker.ranking.toString()} />
);

return (
<S.Tr key={ranker.rank}>
<S.RankingTd>{rankIcon ?? ranker.rank}</S.RankingTd>
<S.Tr key={ranker.ranking}>
<S.RankingTd>{rankIcon ?? ranker.ranking}</S.RankingTd>
<S.Td>{ranker.nickname}</S.Td>
<S.Td>{ranker.postCount}</S.Td>
<S.Td>{ranker.voteCount}</S.Td>
<S.Td>{ranker.score}</S.Td>
</S.Tr>
);
})}
{userRanking && (
<S.Tr>
<S.Td>{userRanking.rank}</S.Td>
<S.Td>{userRanking.nickname}</S.Td>
<S.Td>{userRanking.postCount}</S.Td>
<S.Td>{userRanking.voteCount}</S.Td>
<S.Td>{userRanking.score}</S.Td>
</S.Tr>
)}
</S.Table>
</RS.Background>
<ErrorBoundary>
<Suspense
fallback={
<S.LoadingSpinnerWrapper>
<LoadingSpinner size="sm" />
</S.LoadingSpinnerWrapper>
}
>
<UserRanking />
</Suspense>
</ErrorBoundary>
</S.Table>
);
}
9 changes: 9 additions & 0 deletions frontend/src/pages/Ranking/PassionUser/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,12 @@ export const RankingTd = styled.td`
export const Td = styled.td`
padding: 10px 0;
`;

export const LoadingSpinnerWrapper = styled.div`
display: flex;
align-items: center;
justify-content: center;

height: 50px;
padding: 0;
`;
17 changes: 1 addition & 16 deletions frontend/src/pages/Ranking/PopularPost/PopularPost.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react';

import { RankingPost } from '@type/ranking';

import PopularPost from '.';

const meta: Meta<typeof PopularPost> = {
Expand All @@ -11,19 +9,6 @@ const meta: Meta<typeof PopularPost> = {
export default meta;
type Story = StoryObj<typeof PopularPost>;

const rankingPostInfo: RankingPost = {
rank: 1,
post: {
id: 29,
writer: 'writer',
title: '이것은 엄청나게 많은 투표가 이루어진 대단한 글이지요',
voteCount: 10,
},
};
const rankingPostList: RankingPost[] = new Array(10)
.fill(rankingPostInfo)
.map((post, index) => ({ ...post, ranking: index + 1 }));

export const Default: Story = {
render: () => <PopularPost rankingPostList={rankingPostList} />,
render: () => <PopularPost />,
};
37 changes: 16 additions & 21 deletions frontend/src/pages/Ranking/PopularPost/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { Link } from 'react-router-dom';

import { RankingPost } from '@type/ranking';
import { usePopularPostRanking } from '@hooks/query/ranking/usePopularPostRanking';

import { PATH } from '@constants/path';

import firstRankIcon from '@assets/first-rank.svg';
import secondRankIcon from '@assets/second-rank.svg';
import thirdRankIcon from '@assets/third-rank.svg';

import * as RS from '../RankingTableStyle';

import * as S from './style';

const rankIconUrl: Record<number, string> = {
Expand All @@ -20,27 +18,25 @@ const rankIconUrl: Record<number, string> = {

const columnNameList = ['등수', '닉네임', '글 제목', '투표 수'];

interface PopularPostProps {
rankingPostList: RankingPost[];
}
export default function PopularPost() {
const { data: rankingPostList } = usePopularPostRanking();

export default function PopularPost({ rankingPostList }: PopularPostProps) {
return (
<RS.Background>
<S.Table>
<S.Tr>
{columnNameList.map(text => (
<S.Th key={text}>{text}</S.Th>
))}
</S.Tr>
{rankingPostList.map(rankingPost => {
const rankIcon = rankIconUrl[rankingPost.rank] && (
<img src={rankIconUrl[rankingPost.rank]} alt={rankingPost.rank.toString()} />
<S.Table>
<S.Tr>
{columnNameList.map(text => (
<S.Th key={text}>{text}</S.Th>
))}
</S.Tr>
{rankingPostList &&
rankingPostList.map(rankingPost => {
const rankIcon = rankIconUrl[rankingPost.ranking] && (
<img src={rankIconUrl[rankingPost.ranking]} alt={rankingPost.ranking.toString()} />
);

return (
<S.Tr key={rankingPost.rank}>
<S.RankingTd>{rankIcon ?? rankingPost.rank}</S.RankingTd>
<S.Tr key={rankingPost.ranking}>
<S.RankingTd>{rankIcon ?? rankingPost.ranking}</S.RankingTd>
<S.Td>{rankingPost.post.writer}</S.Td>
<S.Td>
<Link to={`${PATH.POST}/${rankingPost.post.id}`}>{rankingPost.post.title}</Link>
Expand All @@ -49,7 +45,6 @@ export default function PopularPost({ rankingPostList }: PopularPostProps) {
</S.Tr>
);
})}
</S.Table>
</RS.Background>
</S.Table>
);
}
5 changes: 5 additions & 0 deletions frontend/src/pages/Ranking/RankingTableStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import { styled } from 'styled-components';
import { theme } from '@styles/theme';

export const Background = styled.div`
display: flex;
align-items: center;
justify-content: center;

height: fit-content;
min-height: 500px;
border-radius: 4px;

background-color: var(--gray);
Expand Down
Loading
Loading