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

[FEAT] 라운드 통계 화면 및 게임 결과 화면 구현 #73

Merged
merged 28 commits into from
Jul 25, 2024

Conversation

rbgksqkr
Copy link
Contributor

Issue Number

#50

As-Is

라운드 통계 화면과 전체 결과 화면 디자인만 완료되고 페이지 구현 x

To-Be

  • 라운드 통계 화면 구현
    • 탭 UI 구현
    • 막대바 애니메이션 적용
    • 숫자 카운팅 애니메이션 적용
  • 게임 결과 화면 구현

Check List

  • 테스트가 전부 통과되었나요?
  • 모든 commit이 push 되었나요?
  • merge할 branch를 확인했나요?
  • Assignee를 지정했나요?
  • Label을 지정했나요?

Test Screenshot

(Optional) Additional Description

  • git branch 이슈로 인해 라운드 통계 화면과 게임 결과 화면을 함께 작업해서 파일 체인지가 많이 발생함ㅜ

라운드 통계 데모 영상

_._.mov

게임 결과 데모 영상

_.mov

rbgksqkr added 25 commits July 24, 2024 20:10
@rbgksqkr rbgksqkr added ✨ feat 기능 추가 🫧 FE front end labels Jul 25, 2024
@rbgksqkr rbgksqkr added this to the FE Sprint2 milestone Jul 25, 2024
@rbgksqkr rbgksqkr requested review from useon and novice0840 July 25, 2024 10:43
@rbgksqkr rbgksqkr self-assigned this Jul 25, 2024
@rbgksqkr rbgksqkr linked an issue Jul 25, 2024 that may be closed by this pull request
4 tasks
@@ -27,6 +27,7 @@
"jest.polyfills.js"
],
"rules": {
"no-console": "error",
Copy link
Contributor

Choose a reason for hiding this comment

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

L5 - 참고 의견

no console 이거 흔히 하는 실수인데 방지하는 옵션 좋네요 굿

Comment on lines +1 to +25
export interface RoundVoteResult {
group: Group;
total: Total;
}

export interface Group {
firstOption: GroupOption;
secondOption: GroupOption;
}

export interface Total {
firstOption: TotalOption;
secondOption: TotalOption;
}

export interface GroupOption extends TotalOption {
members: string[];
memberCount: number;
}

export interface TotalOption {
optionId: number;
name: string;
percent: number;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

L5 - 참고 의견

도메인 용어들 공통 타입으로 만들어 둔 거 좋네요

Comment on lines +14 to +18
return {
...roundVoteResultQuery,
groupRoundResult: roundVoteResultQuery.data?.group,
totalResult: roundVoteResultQuery.data?.total,
};
Copy link
Contributor

Choose a reason for hiding this comment

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

L5 - 참고 의견

groupRoundResult랑 totalResult는 이미 roundVoteResultQuery에 있는 요소들 같은데 따로 분리한 이유가 있나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

useBalanceContentQuery 에서 작성한 것과 같이 데이터 변수명을 사용처에서 고정적으로 사용하도록 따로 분리해서 선언하였습니다! 범용적으로 활용되는 훅이라면 useQuery를 그대로 반환할 수도 있지만, 팀에서 맞춘 도메인 용어를 통일해서 사용하는 것이 더 좋다고 판단하여 구현하게 되었습니다!!

Comment on lines 14 to 33
const useCountAnimation = ({ target, start = 50, duration = 2000 }: UseCountAnimationProps) => {
const [count, setCount] = useState(start);
const frameRate = 500 / 60;
const totalFrame = Math.round(duration / frameRate);

useEffect(() => {
if (typeof target === 'undefined' || target === start) return; // target 값을 API로 불러올 경우 초기값이 애니메이션에 반영되므로 예외처리
let currentNumber = start;
const counter = setInterval(() => {
const progress = easeOutRate(++currentNumber / totalFrame);
setCount(Math.round(target * progress));

if (progress === 1) {
clearInterval(counter);
}
}, frameRate);
}, [target, frameRate, start, totalFrame]);

return count;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

L4 - 변경 제안

애니메이션 관련된 코드는 사실 직접 브라우저에서 보지 않고는 무슨 동작인지 알기가 힘들어서 위에 짧게 나마 주석이 있으면 좋을 것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오 그럴 것 같아요! 위에 커스텀 훅 설명에 작성하겠습니당

Comment on lines 3 to 9
type Tab = 'group' | 'total';

interface TabItemProps {
tab: Tab;
activeTab: Tab;
handleClickTab: (tab: Tab) => void;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

L4 - 변경 제안

지금은 라운드 투표의 탭으로 사용되는 것 같은데 Tab이라는 단어는 조금 더 포괄적이라고 생각해서요.
그래서 Tab 안에 들어가는 값들인 group, total을 제너릭으로 만드는 것 어때요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오호 좋은 의견인 것 같아요!! Tab 같은 경우 이름이 추상적으로 보일 것 같긴해요. 근데 공통 캄포넌트로 만들기에는 여러 곳에서 사용되고 있진 않아서, 이름을 도메인 넣어 만들어보겠습니다!

Copy link
Contributor

@useon useon left a comment

Choose a reason for hiding this comment

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

데모데이를 위해 일단 어프루브하고 뒤에 리뷰하겠습니다 꼼꼼하고 맛있는 구현 마칭 !!!!!!!!!

@rbgksqkr rbgksqkr merged commit 4310280 into develop Jul 25, 2024
1 check passed
Copy link
Contributor

@useon useon left a comment

Choose a reason for hiding this comment

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

말우 ! 멋진 애니메이션으로 이번 데모를 빛 내주어 고맙읍니다 그의 장인 정신이 엿보였던 ^. ^!!!!!!! 뿐만 아니라 만들어 놓은 맛있는 훅 저도 잘 사용했어요 푸하하 ! ! ! 저희의 깃 이슈 .. 때문에 어쩔 수 없이 PR이 커져서 두려웠는데, 말우가 커밋 단위로 잘 나눠 놓아서 커밋 하나하나 들여다 보면서 리뷰하기가 수월했네요 감사링 .. 👏 달다 보니 리뷰 고봉밥이 되었는데 오히려 좋아할 것 같은 말우 😂😂 고생 많았습니다 짱 ✨ !

dotenv.config();

module.exports = {
entry: './src/index.tsx',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname + '/dist'),
publicPath: '/',
Copy link
Contributor

Choose a reason for hiding this comment

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

L5 - 참고 의견

저도 이거 몰라서 어 왜 페이지 이동이 안 되지 했는데 마루 덕분에 알아갑니다 푸하하 !!!!

@@ -13,7 +13,7 @@ const SelectContainer = () => {
const [selectedId, setSelectedId] = useState(0);

const goToRoundResult = () => {
navigate('/round-result');
navigate(`/round/result`);
Copy link
Contributor

Choose a reason for hiding this comment

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

L5 - 참고 의견

변수가 없는데 혹시 백틱으로 감싼 이유가 있나요 ?!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

앗 원래 round를 url에 넣었다가 구현이 변경되어 지운 부분인데, 현재 상태에서는 백틱이 필요 없을 것 같아요!!

clearInterval(counter);
}
}, frameRate);
}, [target, frameRate, start, totalFrame]);
Copy link
Contributor

Choose a reason for hiding this comment

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

L3 - 중요 질문

의존성 배열에 상수로 정의된 frameRate 와 totalFrame도 들어간 이유가 무엇인가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

의존성 배열에는 반응형 값이 들어가야하는데, states, props, 컴포넌트 내에서 선언한 변수 중 useEffect에서 사용되는 데이터들이 추가되어야 합니다! frameRate와 totalFrame은 컴포넌트 내에 선언되었고, useEffect에서 사용되므로 의존성 배열에 추가되는 것이 맞습니다.

그런데 다시 보니 상수가 불필요하게 의존되는 것 같아 useEffect 내부로 옮겨 반응형 값이 안되도록 수정하겠습니다!

useEffect(() => {
if (target === start) return; // target 값을 API로 불러올 경우 초기값이 애니메이션에 반영되므로 예외처리
let currentNumber = start;
const counter = setInterval(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

L5 - 참고 의견

setInterval이 외에도 웹 애니메이션을 최적화하는 requestAnimationFrame 이라는 것도 있더라고요? 저도 이번에 리뷰하면서 알게되었답니다 ㅎ .ㅎ 다음에 최적화하면서 적용해 봐도 좋을 것 같아요 ~!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오 저도 숫자 올라갈 때마다 렌더링되는게 문제가 될 수 있다고 생각했는데 requestAnimationFrame 을 적용해볼 수 있겠군요! 나중에 시간이나 성능 비교해보면서 한번에 적용해보면 좋을 것 같아요 ㅎㅎ

https://velog.io/@younghwanjoe/requestAnimationFrame%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EC%95%A0%EB%8B%88%EB%A9%94%EC%9D%B4%EC%85%98-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-%EC%83%81

Copy link
Contributor

Choose a reason for hiding this comment

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

말우 ! 좋은 자료 공유 호라락 읽어보았읍니다 감사룡. . 지금 당장은 이해가 완벽히 안됐지만 역시 해 봐야겠죠 ? 푸하하 최적화 때 야무지게 써 버립시다 ^ .^ ~ ~

queryFn: async () => await fetchRoundVoteResult(),
});

roundVoteResultQuery.data?.group;
Copy link
Contributor

Choose a reason for hiding this comment

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

L3 - 중요 질문

해당 코드는 어떤 의미인가요? 없어도 괜찮지 않나 싶어서요 👏

Copy link
Contributor Author

Choose a reason for hiding this comment

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

엇 현재 코드에선 제거되었는데 다음부턴 커밋에 안들어가게 주의하겠습니다!!

roundResult: '/round/result',
roundResultVote: '/round/result/vote',
gameResult: '/game/result',
} as const;
Copy link
Contributor

Choose a reason for hiding this comment

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

L5 - 참고 의견

오오오 루트 상수화 좋은데요오~

Copy link
Contributor Author

Choose a reason for hiding this comment

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

루트(x) 라우트(o)

Copy link
Contributor

Choose a reason for hiding this comment

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

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 아니 이 코멘트 달면서 웃었지 ? ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

<div css={rankListContainer}>
{gameResult &&
gameResult.map((item) => <GameResultItem key={item.rank} gameFinalResult={item} />)}
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

L4 - 변경 제안

게임 결과에서 매칭도가 순위대로 나열되는 것을 리스트로 볼 수 있을 것 같아서, div 대신에 ol 태그로 수정하는 것은 어떻게 생각하시나요? 😊

Copy link
Contributor Author

@rbgksqkr rbgksqkr Jul 27, 2024

Choose a reason for hiding this comment

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

오 좋습니다아 웹표준 고려하여 태그 사용하는 것 너무 좋네요 ㅎㅎ

});

return (
<div css={rankItem}>
Copy link
Contributor

Choose a reason for hiding this comment

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

L4 - 변경 제안

상위 태그가 ol로 변경된다면 여기는 li 태그로 리스트임을 알려줄 수 있을 것 같아요 !

Copy link
Contributor Author

Choose a reason for hiding this comment

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

좋습니당


return (
<div css={tabLayout}>
<div css={tabWrapperStyle}>
Copy link
Contributor

Choose a reason for hiding this comment

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

L4 - 변경 제안

tab이라서 div 대신에 nav 태그면 어떨까요 ?! 🙌

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오호 nav 태그는 페이지에서 다른 페이지로 이동하는 navbar에만 사용하는 줄 알았는데, 탭을 이동하여 다른 데이터를 보여준다는 점에서 nav 태그도 좋을 것 같아요!

<span></span>
</header>
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

L5 - 참고 의견

이렇게 분기가 나누어 져야 할 경우가 많이 생기니 기본 Header를 두고 각각의 Header를 만들어 관리해도 좋을 것 같네요! 함께 이야기 나눠 봅시다 😊

Copy link
Contributor Author

Choose a reason for hiding this comment

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

맞아여 그래서 TODO에도 적어놨습니다! 그런데 각각의 Header를 만들고 사용처에서 사용하면 react-router의 Layout으로 설정하지 못하는 문제가 발생합니다,,, 그래서 각각의 Header는 만들되 Header 컴포넌트 내에서 switch문으로 분기처리하는 방법도 좋을 것 같아요!

Copy link
Contributor

Choose a reason for hiding this comment

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

아하 !! layout 문제가 있군요. . . 마루 말대로 그렇게 하는 것이 지금의 최선인 것 같네요.. 더 좋은 방안 있으면 생각나는대로 공유해 봐요 > ,<

@GIVEN53 GIVEN53 deleted the feat/#50 branch December 10, 2024 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🫧 FE front end ✨ feat 기능 추가
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[FEAT] 라운드 통계 화면 구현
3 participants