Skip to content

Commit

Permalink
merge: 라운드 결과 페이지 버그 개선 #366
Browse files Browse the repository at this point in the history
[FIX] 라운드 결과 페이지 버그 개선
  • Loading branch information
rbgksqkr authored Oct 24, 2024
2 parents 28fc3b4 + 5ad7f80 commit e5d9179
Show file tree
Hide file tree
Showing 37 changed files with 420 additions and 337 deletions.
4 changes: 2 additions & 2 deletions frontend/src/components/GameResult/GameResult.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export const noMatchingLayout = css`
`;

export const noMatchingImg = css`
width: 18rem;
height: 30vh;
width: 16rem;
height: 16rem;
`;

export const noMatchingText = css`
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/NicknameItem/NicknameItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { nicknameItemLayout, nicknameText, profileImage } from './NicknameItem.s

import SillyDdangkongMedium from '@/assets/images/sillyDdangkongMedium.webp';
import { memberInfoState } from '@/recoil/atom';

interface NicknameItemProp {
nickName: string;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,36 @@
import { useParams } from 'react-router-dom';

import {
horizontalDivider,
optionParticipantsContainerLayout,
} from './OptionParticipantsContainer.styled';
import OptionParticipants from '../OptionParticipants/OptionParticipants';

import useBalanceContentQuery from '@/hooks/useBalanceContentQuery';
import useMyGameStatus from '@/hooks/useMyGameStatus';
import useRoundVoteResultQuery from '@/hooks/useRoundVoteResultQuery';

const OptionParticipantsContainer = () => {
const { roomId } = useParams();
const { balanceContent } = useBalanceContentQuery(Number(roomId));
const { groupRoundResult } = useRoundVoteResultQuery({
roomId: Number(roomId),
contentId: balanceContent?.contentId,
});

useMyGameStatus({ roomId: Number(roomId) });
import { Group } from '@/types/roundVoteResult';

if (!groupRoundResult) {
return <div>데이터가 없습니다</div>;
}
interface OptionParticipantsContainerProps {
groupRoundResult: Group;
}

const OptionParticipantsContainer = ({ groupRoundResult }: OptionParticipantsContainerProps) => {
return (
<>
<section css={optionParticipantsContainerLayout}>
<OptionParticipants
optionName={groupRoundResult.firstOption.name}
members={groupRoundResult.firstOption.members}
memberCount={groupRoundResult.firstOption.memberCount}
/>
<div css={horizontalDivider}></div>
<OptionParticipants
optionName={groupRoundResult.secondOption.name}
members={groupRoundResult.secondOption.members}
memberCount={groupRoundResult.secondOption.memberCount}
/>
<div css={horizontalDivider}></div>
<OptionParticipants
optionName={'투표에 참여하지 않으셨어요'}
members={groupRoundResult.giveUp.members}
memberCount={groupRoundResult.giveUp.memberCount}
/>
</section>
</>
<section css={optionParticipantsContainerLayout}>
<OptionParticipants
optionName={groupRoundResult.firstOption.name}
members={groupRoundResult.firstOption.members}
memberCount={groupRoundResult.firstOption.memberCount}
/>
<div css={horizontalDivider}></div>
<OptionParticipants
optionName={groupRoundResult.secondOption.name}
members={groupRoundResult.secondOption.members}
memberCount={groupRoundResult.secondOption.memberCount}
/>
<div css={horizontalDivider}></div>
<OptionParticipants
optionName={'투표에 참여하지 않으셨어요'}
members={groupRoundResult.giveUp.members}
memberCount={groupRoundResult.giveUp.memberCount}
/>
</section>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import useCountAnimation from '@/hooks/useCountAnimation';
import { Group } from '@/types/roundVoteResult';

const useTotalCountAnimation = (groupRoundResult?: Group) => {
const animatedFirstPercent = useCountAnimation({ target: groupRoundResult?.firstOption.percent });
const useTotalCountAnimation = (groupRoundResult: Group) => {
const animatedFirstPercent = useCountAnimation({ target: groupRoundResult.firstOption.percent });
const animatedSecondPercent = useCountAnimation({
target: groupRoundResult?.secondOption.percent,
target: groupRoundResult.secondOption.percent,
});

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { useGameStart } from './hooks/useGameStart';
import getStartButtonText from './StartButton.utils';

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

const StartButton = () => {
const { memberInfo, handleGameStart } = useGameStart();
const { memberInfo, handleGameStart, isPending, isSuccess } = useGameStart();

return (
<Button
text={memberInfo.isMaster ? '시작' : '방장이 시작해 주세요'}
disabled={!memberInfo.isMaster}
text={getStartButtonText(memberInfo.isMaster, isPending || isSuccess)}
disabled={!memberInfo.isMaster || isPending || isSuccess}
onClick={handleGameStart}
bottom
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const getStartButtonText = (isMaster: boolean, isPending: boolean) => {
if (isMaster && isPending) return '시작중...';
if (isMaster) return '시작';
return '방장이 진행해 주세요';
};

export default getStartButtonText;
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ export const useGameStart = () => {
}
};

return { memberInfo, handleGameStart, setMemberInfo };
return { memberInfo, handleGameStart, setMemberInfo, ...startGameMutation };
};
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import { screen, waitFor } from '@testing-library/react';
import { userEvent } from '@testing-library/user-event';
import type { MutableSnapshot } from 'recoil';

import StartButtonContainer from './StartButtonContainer';

import { memberInfoState } from '@/recoil/atom';
import { customRender } from '@/utils/test-utils';
import { customRenderWithIsMaster } from '@/utils/test-utils';

describe('StartButtonContainer 테스트', () => {
it('게임 시작 버튼을 클릭하면 카운트 다운을 시작한다.', async () => {
const initializeIsMaster = (snap: MutableSnapshot) => {
snap.set(memberInfoState, { memberId: 1, nickname: 'Test User', isMaster: true });
};

const user = userEvent.setup();
customRender(<StartButtonContainer />, { initializeState: initializeIsMaster });
customRenderWithIsMaster(<StartButtonContainer />, true);
const COUNTDOWN_LABEL_TEXT = '게임 시작 3초 전';

const button = await screen.findByRole('button', { name: '시작' });
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { css } from '@emotion/react';

import { Theme } from '@/styles/Theme';

export const emptyVoteTextContainer = css`
display: flex;
flex-direction: column;
align-items: center;
`;

export const emptyVoteText = css`
display: flex;
justify-content: center;
align-items: center;
height: 8vh;
${Theme.typography.headline3}
`;

export const angryImage = css`
width: 16rem;
height: 14rem;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { angryImage, emptyVoteText, emptyVoteTextContainer } from './EmptyVoteContent.styled';

import AngryDdangkong from '@/assets/images/angryDdangkong.webp';

const EmptyVoteContent = () => {
return (
<div css={emptyVoteTextContainer}>
<img src={AngryDdangkong} alt="" css={angryImage} />
<span css={emptyVoteText}>아무도 투표하지 않으셨네요 :{`)`}</span>
</div>
);
};

export default EmptyVoteContent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { css } from '@emotion/react';

import { Theme } from '@/styles/Theme';

export const barContainer = css`
display: flex;
overflow: hidden;
align-items: center;
width: inherit;
border-radius: 1.6rem;
`;

export const barWrapper = css`
display: flex;
justify-content: center;
align-items: center;
height: 8vh;
color: black;
font-weight: bold;
font-size: 1.6rem;
transition: all 1s;
`;

export const firstBar = (percent: number, isBigFirstOption: boolean) => css`
${barWrapper}
overflow: hidden;
width: ${percent}%;
border-radius: 1.6rem 0 0 1.6rem;
background-color: ${isBigFirstOption ? Theme.color.peanut400 : Theme.color.gray};
transform: translateX(5px);
clip-path: ${percent === 100 ? 'none' : 'polygon(0 0, 100% 0, calc(100% - 10px) 100%, 0 100%)'};
`;

export const secondBar = (percent: number, isBigFirstOption: boolean) => css`
${barWrapper}
overflow: hidden;
width: ${percent}%;
border-radius: 0 1.6rem 1.6rem 0;
background-color: ${isBigFirstOption ? Theme.color.gray : Theme.color.peanut400};
transform: translateX(-5px);
clip-path: ${percent === 100 ? 'none' : 'polygon(10px 0, 100% 0, 100% 100%, 0 100%)'};
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useEffect, useState } from 'react';

import { barContainer, firstBar, secondBar } from './StatisticBar.styled';

import useTotalCountAnimation from '@/components/RoundVoteContainer/RoundVoteContainer.hook';
import { Group } from '@/types/roundVoteResult';

const INITIAL_OPTION_PERCENT = 50;

interface StatisticBarProps {
groupRoundResult: Group;
}
const StatisticBar = ({ groupRoundResult }: StatisticBarProps) => {
const { animatedFirstPercent, animatedSecondPercent } = useTotalCountAnimation(groupRoundResult);
const [optionPercent, setOptionPercent] = useState({
first: INITIAL_OPTION_PERCENT,
second: INITIAL_OPTION_PERCENT,
});

const isBigFirstOption = optionPercent.first >= 50;

useEffect(() => {
setOptionPercent((prev) => ({
...prev,
first: groupRoundResult.firstOption.percent,
second: groupRoundResult.secondOption.percent,
}));
}, [groupRoundResult]);

return (
<div css={barContainer}>
<span css={firstBar(optionPercent.first, isBigFirstOption)}>{animatedFirstPercent}%</span>
<span css={secondBar(optionPercent.second, isBigFirstOption)}>{animatedSecondPercent}%</span>
</div>
);
};

export default StatisticBar;
Loading

0 comments on commit e5d9179

Please sign in to comment.