-
Notifications
You must be signed in to change notification settings - Fork 1
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: 밸런스게임 조회 모바일 페이지 ui 구현 및 api 연동 #267
base: dev
Are you sure you want to change the base?
Conversation
개요Walkthrough이 풀 리퀘스트는 밸런스 게임의 모바일 페이지 UI를 구현하고 API와 연동하는 작업을 포함합니다. 주요 변경 사항은 모바일 환경에 최적화된 새로운 컴포넌트와 후크, 라우팅 로직 추가, 그리고 반응형 디자인을 위한 스타일 조정으로 구성됩니다. 모바일 사용자 경험을 개선하기 위해 다양한 컴포넌트와 후크가 새롭게 도입되었습니다. Changes
Assessment against linked issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 19
🧹 Nitpick comments (27)
src/hooks/game/useBalanceGameVote.ts (1)
38-61
: 게스트 투표 로직 확인
게스트 유저의 투표, 취소, 교체 로직을 배열 인덱스를 찾아 적절히 수정해주는 구조가 명확합니다. 다만, findIndex로 찾았을 때 없을 경우( return -1 )에 대한 추가 체크가 필요할 수 있습니다.가능하다면 currentVoteIndex가 -1일 때의 에러 처리를 명시적으로 추가하는 것이 안전합니다.
+ if (currentVoteIndex === -1 && selectedOption) { + // 혹은 별도 처리 로직 + }src/components/molecules/BalanceGameEndingBox/BalanceGameEndingBox.tsx (1)
11-11
: useGameEndBookmark 훅 사용
useGameEndBookmark를 사용하여 즐겨찾기(북마크) 로직을 단순화시킨 것은 유지보수성에 긍정적입니다. API 연동 및 에러 처리가 훅 내부에서 일관성 있게 처리되는지 재차 점검해 주세요.src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx (3)
42-50
: 컴포넌트 Props 설계
gameSetId, game, isMyGame 등 주요 상태를 명시적으로 전달받는 구조가 명확합니다. 후속 유지보수 시 props 증가 가능성이 높은 부분이니, 필요하다면 별도의 context나 상위 컴포넌트 분리도 고려할 수 있습니다.
61-67
: useGuestGameVote 훅 연동
guestVotedList의 상태와 함수를 훅으로 분리함으로써 로직 가독성이 향상되었습니다. 다만, 훅 내부에서 발생할 수 있는 에러 케이스(잘못된 currentStage 등)에 대한 방어 로직이 필요할 수 있습니다.
123-130
: handleBookmarkClick 파라미터 확인
콜백 함수를 통해 로그인 모달을 열어주는 형태는 유연도가 높습니다. 만약 비로그인에 대한 다른 처리가 필요해질 경우를 대비해, 콜백 이외의 로그인 리다이렉션 전략 등도 고려할 수 있겠습니다.src/components/organisms/BalanceGameSection/BalanceGameSection.tsx (3)
19-20
: useGuestGameVote 훅 도입
guest 투표 로직 분야가 명확히 분리되어 가독성이 좋아졌습니다. 가능하다면 회원 투표 로직과 함께 유사한 Hook 시그니처를 유지하여, 이후 확장성 및 재사용성을 높이는 것이 좋겠습니다.
123-130
: useGameBookmark 훅 사용
동일한 훅을 웹/모바일에서 공유하여 즐겨찾기 로직을 일원화한 점이 훌륭합니다. 북마크 생성/삭제에 대한 에러 상황(예: 네트워크 오류, 이미 북마크되어 있는 게임)에 대한 사용자 알림 처리도 곁들여 주시면 좋겠습니다.
239-239
: handleBookmarkClick 콜백 인자
콜백을 통해 비로그인 시 별도의 모달을 호출하는 로직이 유연하게 처리됩니다. 다만, 로그인 처리 후 재시도 로직이 필요한 상황에 대비하여 handleBookmarkClick 내부에서 다시 한 번 vote나 bookmark를 시도할 수 있도록 구조를 개선할 수도 있습니다.필요하다면 후속 로직 개선을 위한 추가 코드를 제안해 드릴 수 있습니다.
src/hooks/common/useIsMobile.ts (1)
14-16
: 이벤트 리스너 최적화가 필요합니다.리사이즈 이벤트가 너무 자주 발생하는 것을 방지하기 위해 디바운스 처리가 필요합니다.
다음과 같이 개선해보세요:
import { debounce } from 'lodash'; function useIsMobile() { const [isMobile, setIsMobile] = useState<boolean>(false); useEffect(() => { const checkIsMobile = () => { // ... existing code ... }; const debouncedCheck = debounce(checkIsMobile, 250); checkIsMobile(); window.addEventListener('resize', debouncedCheck); return () => { window.removeEventListener('resize', debouncedCheck); debouncedCheck.cancel(); }; }, []); return isMobile; }src/components/mobile/organisms/BalanceGameEndingSection/BalanceGameEndingSection.style.ts (1)
41-47
: 토스트 모달의 접근성 개선 필요현재 토스트 모달 구현에 다음 접근성 속성들이 누락되어 있습니다:
- ARIA 역할 및 라이브 리전
- 스크린 리더 지원
다음과 같은 개선을 제안드립니다:
export const toastModalStyling = css({ position: 'fixed', top: '65px', left: '50%', transform: 'translate(-50%)', zIndex: '1000', + role: 'alert', + 'aria-live': 'polite', });src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.style.ts (1)
36-41
: 이미지 최적화 속성 추가 필요이미지 스타일에 성능 및 사용자 경험 향상을 위한 속성들이 누락되어 있습니다.
다음과 같은 개선을 제안드립니다:
export const imageStyle = css({ width: '90px', height: '90px', borderRadius: '10px', objectFit: 'cover', + loading: 'lazy', + decoding: 'async', });src/layout/layout.tsx (2)
17-19
: 미디어 쿼리 브레이크포인트 상수화 필요하드코딩된 미디어 쿼리 브레이크포인트는 일관성 유지에 문제가 될 수 있습니다.
상수 파일을 생성하여 브레이크포인트를 관리하는 것을 추천드립니다:
// src/constants/breakpoints.ts export const BREAKPOINTS = { MOBILE: '430px', TABLET: '768px', DESKTOP: '1024px', } as const;그리고 다음과 같이 사용:
- '@media (max-width: 430px)': { + [`@media (max-width: ${BREAKPOINTS.MOBILE})`]: { paddingTop: '55px', },
24-24
: Footer 조건부 렌더링 최적화 필요삼항 연산자를 사용한 조건부 렌더링은 가독성이 떨어지며, 불필요한 null 반환이 있습니다.
다음과 같은 개선을 제안드립니다:
- {isMobile ? null : <Footer />} + {!isMobile && <Footer />}src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.tsx (3)
1-1
: ESLint 비활성화 주석에 대한 설명이 필요합니다.ESLint 규칙을 비활성화한 이유를 주석으로 설명해주시면 좋겠습니다.
6-14
: 타입 정의 개선이 필요합니다.다음 사항들을 개선하면 좋겠습니다:
id
prop이 선택적인 이유가 명확하지 않습니다.- 'A' | 'B' 타입이 반복되므로 별도의 타입으로 분리하는 것이 좋겠습니다.
+type OptionType = 'A' | 'B'; + export interface BalanceGameButtonProps { - id?: number; + id: number; name: string; imgUrl: string | null; description: string; - optionType: 'A' | 'B'; - selectedButton: 'A' | 'B' | null; - onClick: (optionType: 'A' | 'B') => void; + optionType: OptionType; + selectedButton: OptionType | null; + onClick: (optionType: OptionType) => void; }
31-33
: 조건부 렌더링 로직 개선이 필요합니다.
renderCheckedIcon
함수를 더 간단하게 작성할 수 있습니다.- const renderCheckedIcon = () => { - return optionType === 'A' ? <RedCheckIcon /> : <BlueCheckIcon />; - }; + const renderCheckedIcon = () => ( + optionType === 'A' ? <RedCheckIcon /> : <BlueCheckIcon /> + );src/stories/mobile/atoms/BalanceGameButton.stories.tsx (2)
1-1
: eslint-disable 주석 제거 필요프로덕션 코드에서 alert 사용을 피하고 더 적절한 피드백 메커니즘을 구현하는 것이 좋습니다.
38-43
: 테스트 데이터 개선 필요현재 사용 중인 샘플 데이터가 실제 사용 사례를 잘 반영하지 못하고 있습니다. 다음과 같은 개선을 제안합니다:
- 더 현실적인 제목과 설명 텍스트 사용
- 다양한 길이의 텍스트 케이스 추가
src/pages/mobile/BalanceGameMobilePage/BalanceGameMobilePage.tsx (1)
24-30
: 상태 업데이트 로직 최적화 필요
handleNextGame
과handlePrevGame
함수를 하나의 함수로 통합하여 코드 중복을 줄일 수 있습니다.- const handleNextGame = () => { - setCurrentStage((stage) => (stage < 10 ? stage + 1 : stage)); - }; - - const handlePrevGame = () => { - setCurrentStage((stage) => (stage > 0 ? stage - 1 : stage)); - }; + const handleStageChange = (direction: 'next' | 'prev') => { + setCurrentStage((stage) => { + if (direction === 'next') return stage < 10 ? stage + 1 : stage; + return stage > 0 ? stage - 1 : stage; + }); + };src/components/mobile/molecules/BalanceGameBox/BalanceGameBox.tsx (1)
53-62
: 옵션 A의 널 체크 개선 필요옵션 데이터의 안전한 처리를 위해 옵셔널 체이닝 사용이 중복되어 있습니다.
다음과 같이 구조 분해 할당과 기본값을 활용하여 코드를 개선할 수 있습니다:
- <BalanceGameButton - name={optionA?.name ?? ''} - imgUrl={optionA?.imgUrl ?? null} - description={optionA?.description ?? ''} - optionType={optionA?.optionType ?? 'A'} - selectedButton={selectedVote ?? null} - onClick={() => { - handleButtonClick('A'); - }} - /> + <BalanceGameButton + name={optionA?.name || ''} + imgUrl={optionA?.imgUrl || null} + description={optionA?.description || ''} + optionType="A" + selectedButton={selectedVote || null} + onClick={() => handleButtonClick('A')} + />src/components/molecules/BalanceGameBox/BalanceGameBox.tsx (1)
Line range hint
34-39
: 배경 이미지 초기화 로직 최적화 필요
getRandomImages
함수가 컴포넌트 렌더링마다 새로 생성되어 불필요한 메모리를 사용할 수 있습니다.다음과 같이
useMemo
를 사용하여 최적화하는 것을 권장드립니다:- const getRandomImages = () => { + const getRandomImages = useMemo(() => { const [randomNumberA, randomNumberB] = getRandomNumbers( S.gameBackgrounds.length, ); return [S.gameBackgrounds[randomNumberA], S.gameBackgrounds[randomNumberB]]; - }; + }, []);src/stories/mobile/molecules/BalanceGameBox.stories.tsx (2)
11-28
: 테스트 데이터 관리 개선 필요테스트용 예제 데이터가 하드코딩되어 있어 유지보수가 어려울 수 있습니다.
별도의 테스트 데이터 파일로 분리하여 관리하는 것을 권장드립니다:
// src/stories/fixtures/balanceGame.ts export const mockGameOptions: GameOption[] = [ { id: 0, name: '제목은글자제한30자제목은글자제한30자제목은글자제한30자', imgUrl: SampleWhole, description: '상황설명글자제한50상황설명글자제한50상황설명글자제한50상황설명글자제한50상황설명글자제한50', optionType: 'A', }, // ... 옵션 B ];
76-93
: 스토리 렌더링 구조 개선 필요현재 스토리 렌더링 구조가 반복적이며, 재사용성이 낮습니다.
다음과 같이 맵 함수를 사용하여 코드를 개선할 수 있습니다:
export const All: Story = { render: (args) => ( <ul css={storyContainer}> - <li css={storyInnerContainer}> - <h3>not selected</h3> - <BalanceGameBox {...args} /> - </li> - <li css={storyInnerContainer}> - <h3>A selected</h3> - <BalanceGameBox {...args} selectedVote="A" /> - </li> - <li css={storyInnerContainer}> - <h3>B selected</h3> - <BalanceGameBox {...args} selectedVote="B" /> - </li> + {[ + { title: 'not selected', vote: null }, + { title: 'A selected', vote: 'A' }, + { title: 'B selected', vote: 'B' }, + ].map(({ title, vote }) => ( + <li key={title} css={storyInnerContainer}> + <h3>{title}</h3> + <BalanceGameBox {...args} selectedVote={vote} /> + </li> + ))} </ul> ), };src/stories/mobile/organisms/BalanceGameSection.stories.tsx (1)
68-71
: 핸들러 함수의 기본 구현 개선 필요빈 함수 대신 콘솔 로그나 알림을 추가하여 Storybook에서 상호작용을 더 명확하게 표시하는 것이 좋습니다.
- setCurrentStage: () => {}, - handleNextGame: () => {}, - handlePrevGame: () => {}, + setCurrentStage: () => console.log('현재 스테이지 변경'), + handleNextGame: () => console.log('다음 게임으로 이동'), + handlePrevGame: () => console.log('이전 게임으로 이동'),src/components/mobile/organisms/BalanceGameEndingSection/BalanceGameEndingSection.tsx (1)
32-33
: 게스트 사용자 확인 로직 분리 제안게스트 사용자 확인 로직을 커스텀 훅으로 분리하면 재사용성이 향상되고 코드가 더 깔끔해질 것 같습니다.
- const isGuest = !localStorage.getItem('accessToken'); + const { isGuest } = useAuthStatus();src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.style.ts (1)
99-101
: 그라데이션 성능 최적화 고려선형 그라데이션은 모바일 기기에서 성능에 영향을 줄 수 있습니다.
가능하다면 더 가벼운 대안을 고려하거나, will-change 속성을 사용하여 최적화하세요.background: 'linear-gradient(to top, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0))', + willChange: 'transform',
src/App.tsx (1)
24-24
: 모바일 컴포넌트 import 구문 검토모바일 페이지 컴포넌트를 동적 import로 변경하여 초기 번들 크기를 최적화하는 것이 좋습니다.
다음과 같이 React.lazy를 사용하여 코드 분할을 구현하는 것을 추천드립니다:
-import BalanceGameMobilePage from './pages/mobile/BalanceGameMobilePage/BalanceGameMobilePage'; +const BalanceGameMobilePage = React.lazy(() => + import('./pages/mobile/BalanceGameMobilePage/BalanceGameMobilePage') +);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
src/assets/svg/blue-check-icon.svg
is excluded by!**/*.svg
src/assets/svg/red-check-icon.svg
is excluded by!**/*.svg
📒 Files selected for processing (27)
public/index.html
(1 hunks)src/App.tsx
(3 hunks)src/assets/index.ts
(1 hunks)src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.style.ts
(1 hunks)src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.tsx
(1 hunks)src/components/mobile/atoms/Button/Button.style.ts
(1 hunks)src/components/mobile/atoms/IconButton/IconButton.tsx
(1 hunks)src/components/mobile/atoms/InteractionButton/InteractionButton.tsx
(1 hunks)src/components/mobile/molecules/BalanceGameBox/BalanceGameBox.style.ts
(1 hunks)src/components/mobile/molecules/BalanceGameBox/BalanceGameBox.tsx
(1 hunks)src/components/mobile/organisms/BalanceGameEndingSection/BalanceGameEndingSection.style.ts
(1 hunks)src/components/mobile/organisms/BalanceGameEndingSection/BalanceGameEndingSection.tsx
(1 hunks)src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.style.ts
(1 hunks)src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx
(1 hunks)src/components/molecules/BalanceGameBox/BalanceGameBox.tsx
(2 hunks)src/components/molecules/BalanceGameEndingBox/BalanceGameEndingBox.tsx
(3 hunks)src/components/organisms/BalanceGameSection/BalanceGameSection.tsx
(5 hunks)src/hooks/common/useIsMobile.ts
(1 hunks)src/hooks/game/useBalanceGameBookmark.ts
(1 hunks)src/hooks/game/useBalanceGameVote.ts
(1 hunks)src/layout/layout.tsx
(1 hunks)src/pages/mobile/BalanceGameMobilePage/BalanceGameMobilePage.style.ts
(1 hunks)src/pages/mobile/BalanceGameMobilePage/BalanceGameMobilePage.tsx
(1 hunks)src/stories/mobile/atoms/BalanceGameButton.stories.tsx
(1 hunks)src/stories/mobile/molecules/BalanceGameBox.stories.tsx
(1 hunks)src/stories/mobile/organisms/BalanceGameEndingSection.stories.tsx
(1 hunks)src/stories/mobile/organisms/BalanceGameSection.stories.tsx
(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- public/index.html
- src/components/mobile/molecules/BalanceGameBox/BalanceGameBox.style.ts
- src/pages/mobile/BalanceGameMobilePage/BalanceGameMobilePage.style.ts
🔇 Additional comments (14)
src/hooks/game/useBalanceGameVote.ts (1)
1-7
: 임포트 구문 확인
필요한 모듈들을 깔끔하게 임포트하고 있습니다. 중복 임포트나 사용되지 않는 임포트가 없어 보이며, 기능별로 잘 분리되어 있어 가독성이 좋습니다.
src/components/molecules/BalanceGameEndingBox/BalanceGameEndingBox.tsx (2)
4-4
: 불필요 임포트 제거 확인
Bookmark 관련 로직이 별도 훅으로 이동하며 ERROR 임포트가 삭제된 것으로 보입니다. 임포트 누락이나 사용되지 않는 부분이 없는지 최종적으로 확인하시면 좋겠습니다.
102-106
: 컴포넌트의 onClick 핸들러
onClick에서 바로 훅 함수를 호출하고 있는데, 페이지 이동 또는 로그인 모달이 뜨기 전에 의도치 않은 사이드이펙트가 생기지 않는지 점검해 주세요. 필요하다면 useCallback, useMemo 등을 통해 함수 참조를 최적화할 수 있습니다.
src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx (2)
1-19
: 기본 구조와 임포트 검토
새로운 모바일 섹션 컴포넌트로, 필요한 컴포넌트와 훅들을 깔끔하게 임포트하고 있습니다. 중복되거나 사용하지 않는 모듈이 없어 보이나, IconButton, ToastModal 등 핵심 컴포넌트가 적절히 동작하는지 UI 테스트를 꼭 병행해주세요.
85-92
: handleNextButton 로직 점검
게스트 여부와 투표 여부를 조건으로 다음 단계 이동을 제한하는 로직이 정상적으로 작동해 보입니다. 다만, 사용자 입장에서 '투표 안 했을 경우' 어떤 UI/UX가 노출되는지(예: 토스트 안내, 비활성화 등) 명확히 처리되는지 확인 부탁드립니다.
src/components/organisms/BalanceGameSection/BalanceGameSection.tsx (2)
4-4
: VoteRecord 타입 추가
투표 정보를 명확히 관리하기 위해 VoteRecord를 임포트해 사용하는 것은 바람직한 설계입니다. 특히 게스트/회원 구분 로직에서 직관적인 타입 추론이 가능해집니다.
63-69
: handleGuestGameVote 호출
currentGame을 기반으로 guestVotedList를 업데이트하는 흐름이 직관적입니다. gameDetailResponses가 변경・추가될 경우 로직상의 경계값 오류(off-by-one 등)에 유의해 주세요.
src/components/mobile/atoms/IconButton/IconButton.tsx (1)
1-1
: ref 전달 구현이 개선되었습니다!
ComponentPropsWithRef
를 사용하여 ref 전달을 올바르게 처리하도록 개선되었습니다. 이는 React의 모범 사례를 잘 따르고 있습니다.
Also applies to: 4-4, 9-9
src/components/mobile/atoms/InteractionButton/InteractionButton.tsx (1)
1-1
: 컴포넌트 구조가 잘 개선되었습니다!
IconButton
과 일관된 패턴을 따르며, ref 처리가 올바르게 구현되었습니다. 프로퍼티 타입 정의와 스타일 분리도 잘 되어있습니다.
Also applies to: 4-4
src/stories/mobile/organisms/BalanceGameEndingSection.stories.tsx (2)
17-22
: 기본 props 구성이 적절해 보입니다.
스토리북 args 설정이 명확하고 테스트에 필요한 모든 필수 props가 포함되어 있습니다.
23-33
: 데코레이터 설정이 잘 구성되어 있습니다.
Provider들의 중첩 순서가 적절하며, 컴포넌트 테스트에 필요한 모든 컨텍스트가 제공되고 있습니다.
src/components/mobile/atoms/Button/Button.style.ts (1)
48-48
: 버튼 너비 변경에 대한 검증이 필요합니다.
primary 버튼의 medium 사이즈 너비가 130px에서 160px로 변경되었습니다. 이 변경이 기존 모바일 레이아웃에 미치는 영향을 확인해주세요.
✅ Verification successful
버튼 너비 변경은 안전합니다
primary variant의 medium 사이즈 버튼은 스토리북 예제에서만 사용되고 있으며, 실제 프로덕션 코드에서는 해당 조합으로 사용되는 곳이 없습니다. GameTagModal과 ShareModal 컴포넌트에서 Button을 임포트하고 있지만 primary variant와 medium 사이즈 조합으로는 사용하지 않습니다.
따라서 버튼 너비를 130px에서 160px로 변경하는 것은 기존 레이아웃에 영향을 주지 않을 것으로 판단됩니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# primary variant medium 버튼이 사용된 컴포넌트들을 검색합니다
rg -l "variant=\"?primary\"?.+size=\"?medium\"?" --type tsx
Length of output: 85
Script:
#!/bin/bash
# Search for Button component usage with primary variant and medium size
rg -l "variant.*primary.*size.*medium|size.*medium.*variant.*primary"
# Also check for any direct imports of the Button component
rg -l "import.*Button.*from.*components/mobile/atoms/Button"
Length of output: 342
Script:
#!/bin/bash
# Check the actual usage context in the files that import the Button
rg "Button.*variant.*primary|variant.*primary.*Button" -A 3 -B 3 src/components/mobile/molecules/GameTagModal/GameTagModal.tsx src/components/mobile/molecules/ShareModal/ShareModal.tsx
# Check the story file to see how the button is used in different scenarios
cat src/stories/mobile/atoms/Button.stories.tsx
Length of output: 2200
src/stories/mobile/organisms/BalanceGameSection.stories.tsx (1)
14-19
: 예시 데이터의 텍스트 길이 제한 검증 필요
예시 데이터의 텍스트가 실제 제한 길이와 일치하는지 확인이 필요합니다:
- 제목: 정확히 30자
- 설명: 정확히 50자
실제 사용자 입력이 이 제한을 초과할 경우의 처리도 테스트해야 합니다.
src/App.tsx (1)
51-51
: useIsMobile 훅 사용 검토
모바일 감지 로직이 올바르게 구현되었는지 확인이 필요합니다.
✅ Verification successful
모바일 감지 로직이 적절하게 구현되었습니다
useIsMobile 훅의 구현을 확인한 결과:
- 화면 너비가 430px 이하인 경우를 모바일로 감지
- 터치 이벤트를 지원하고 화면 너비가 430px 이하인 경우도 모바일로 감지
- window.matchMedia와 ontouchstart를 사용한 표준적인 모바일 감지 방식 사용
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# useIsMobile 훅의 구현 확인
rg -A 10 "useIsMobile" src/hooks/common/useIsMobile.ts
Length of output: 416
useEffect(() => { | ||
const updateGuestVotedList = () => { | ||
const storedVotes = localStorage.getItem(`game_${gameSetId}`); | ||
setGuestVotedList( | ||
storedVotes ? (JSON.parse(storedVotes) as VoteRecord[]) : [], | ||
); | ||
}; | ||
|
||
updateGuestVotedList(); | ||
|
||
const handleStorageChange = (event: StorageEvent) => { | ||
if (event.key === `game_${gameSetId}`) { | ||
updateGuestVotedList(); | ||
} | ||
}; | ||
|
||
window.addEventListener('storage', handleStorageChange); | ||
updateGuestVotedList(); | ||
return () => { | ||
window.removeEventListener('storage', handleStorageChange); | ||
}; | ||
}, [gameSetId, setGuestVotedList]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
로컬 스토리지 데이터 파싱 예외처리 필요
VoteRecord 타입 정의를 확인한 결과, localStorage에서 파싱된 데이터가 { gameId: number; votedOption: 'A' | 'B' }[]
형태의 배열이어야 합니다. 현재 코드에서는 JSON.parse 실패 시 예외처리가 없어 잘못된 형식의 데이터가 있을 경우 런타임 에러가 발생할 수 있습니다.
다음과 같이 수정이 필요합니다:
updateGuestVotedList
함수 내에서 try-catch 블록으로 JSON.parse를 감싸서 파싱 실패 시 빈 배열을 반환하도록 처리- 파싱된 데이터가 VoteRecord[] 타입과 일치하는지 검증하는 로직 추가
🔗 Analysis chain
로컬 스토리지 동기화 로직 검토
useEffect에서 로컬 스토리지 변경 감지를 통해 guest voting 리스트를 동기화하는 방식이 적절합니다. 다만, localStorage에 문자열로 저장된 데이터를 JSON.parse 할 때 예외처리(잘못된 형식 등)에 대한 처리가 필요할 수 있습니다.
로컬 스토리지에서 가져온 데이터가 JSON.parse 중에 에러가 나는 경우를 확인하기 위한 스크립트를 실행해 보세요:
Let me search for more context about how this data is being written to localStorage and the VoteRecord type definition.
Let me check the interface or type definition for VoteRecord since it wasn't found in the previous search.
Let me check the VoteRecord type definition from the types directory.
Let me try a different approach to find the vote types file.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 프로젝트 전역에서 game_<숫자> 형태로 localStorage 접근하는 코드가 있는지 검사
rg -A 5 "localStorage.getItem\(.*game_"
Length of output: 449
Script:
#!/bin/bash
# Search for localStorage.setItem with game_ prefix
rg "localStorage.setItem\(.*game_" -A 5
# Find VoteRecord type definition
ast-grep --pattern 'type VoteRecord = $_'
Length of output: 434
Script:
#!/bin/bash
# Search for VoteRecord interface definition
ast-grep --pattern 'interface VoteRecord $_'
# Get the full content of useBalanceGameVote.ts to see the type imports
rg -g "useBalanceGameVote.ts" "VoteRecord" -B 5 -A 5
Length of output: 1904
Script:
#!/bin/bash
# Find and show the content of the vote types file
fd "vote.ts" "types" --exec cat {}
Length of output: 127
Script:
#!/bin/bash
# Find the vote types file in src directory
fd "vote.ts" "src" --exec cat {}
# Also search for any JSON.parse error handling in the codebase
rg "try.*JSON\.parse" -A 5
Length of output: 4989
src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx
Show resolved
Hide resolved
src/components/mobile/organisms/BalanceGameEndingSection/BalanceGameEndingSection.tsx
Show resolved
Hide resolved
src/components/mobile/organisms/BalanceGameEndingSection/BalanceGameEndingSection.tsx
Show resolved
Hide resolved
src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.style.ts
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/stories/organisms/SideBar.stories.tsx (1)
16-22
: 데코레이터 중복 코드 개선 제안
ActionBox.stories.tsx
와 동일한 데코레이터 코드가 중복되어 있습니다. 공통 데코레이터를 별도의 파일로 분리하여 재사용하는 것을 제안드립니다.다음과 같이 구현할 수 있습니다:
// src/stories/decorators/withRouter.tsx +import { BrowserRouter } from 'react-router-dom'; + +export const withRouter = (Story) => ( + <BrowserRouter> + <Story /> + </BrowserRouter> +); // src/stories/organisms/SideBar.stories.tsx -decorators: [ - (Story) => ( - <BrowserRouter> - <Story /> - </BrowserRouter> - ), -], +decorators: [withRouter],
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.style.ts
(1 hunks)src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.tsx
(1 hunks)src/stories/molecules/ActionBox.stories.tsx
(2 hunks)src/stories/organisms/SideBar.stories.tsx
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.tsx
- src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.style.ts
🔇 Additional comments (2)
src/stories/molecules/ActionBox.stories.tsx (1)
3-3
: 라우팅 컨텍스트가 올바르게 추가되었습니다!
스토리북 데코레이터를 통해 BrowserRouter
를 추가한 것은 적절한 구현입니다. 이를 통해 라우팅 기능이 필요한 컴포넌트들을 스토리북에서 정상적으로 테스트할 수 있게 되었습니다.
Also applies to: 14-20
src/stories/organisms/SideBar.stories.tsx (1)
3-3
: 라우팅 컨텍스트가 올바르게 추가되었습니다!
스토리북 데코레이터를 통해 BrowserRouter
를 추가한 것은 적절한 구현입니다.
Also applies to: 16-22
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
밸런스게임 조회 모바일 페이지 구현하시느라 수고 많으셨습니다~!! 컴포넌트들이 구조적으로 명확하게 분리되어 있어서 감탄했습니당👏 코멘트 확인 부탁드립니당
src/hooks/game/useBalanceGameVote.ts
Outdated
) => { | ||
const updatedVotes = [...guestVotedList]; | ||
const currentVoteIndex = updatedVotes.findIndex( | ||
(vote) => vote.gameId === game?.gameDetailResponses[currentStage]?.id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
game?.gameDetailResponses[currentStage]?.id
반복적으로 사용되고 있는데 별도의 변수로 처리 후 사용하는건 어떨까용?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ac0003e 수정했습니다!!
const handleNextGame = () => { | ||
setCurrentStage((stage) => (stage < 10 ? stage + 1 : stage)); | ||
}; | ||
|
||
const handlePrevGame = () => { | ||
setCurrentStage((stage) => (stage > 0 ? stage - 1 : stage)); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
비슷한 로직이 반복되고 있는데
const changeStage = (step: number) => {
setCurrentStage((stage) => Math.min(10, Math.max(0, stage + step)));
};
로 공통 함수로 분리하는건 어떨까용
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3bdad95 수정했습니다!! props가 더 간결해졌네용 👏
Quality Gate failedFailed conditions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.style.ts (1)
5-14
: 🛠️ Refactor suggestion버튼의 접근성 및 반응형 디자인 개선 필요
버튼 컴포넌트의 기본 접근성이 누락되어 있으며, 고정된 너비 값은 다양한 화면 크기에서 문제를 일으킬 수 있습니다.
export const buttonWrapStyle = css({ all: 'unset', cursor: 'pointer', display: 'flex', flexDirection: 'column', - width: '305px', + width: '100%', + maxWidth: '305px', backgroundColor: color.WT, borderRadius: '10px', overflow: 'hidden', + role: 'button', + 'aria-pressed': 'false', });
🧹 Nitpick comments (4)
src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx (1)
9-9
: 불필요한 중복 슬래시를 제거해 주세요.import 구문에 중복된 슬래시가 있습니다. 경로 가독성을 위해 아래와 같이 변경하는 것을 권장합니다.
- import Button from '@/components/mobile//atoms/Button/Button'; + import Button from '@/components/mobile/atoms/Button/Button';src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.style.ts (3)
16-23
: 타입 안정성 개선 제안옵션 타입을 리터럴 유니온 타입으로 분리하여 타입 안정성을 향상시킬 수 있습니다.
+type OptionType = 'A' | 'B'; -export const getOutlineStyle = (option: 'A' | 'B', isSelected: boolean) => { +export const getOutlineStyle = (option: OptionType, isSelected: boolean) => {
33-36
: 타이포그래피 시스템 일관성 유지 필요타이포그래피 시스템을 재정의하는 것은 일관성을 해칠 수 있습니다. 기존 타이포그래피 시스템을 활용하거나, 필요한 경우 시스템을 확장하는 것이 좋습니다.
-export const nameStyle = css(typo.Mobile.Text.SemiBold_14, { - width: '220px', - fontSize: '16px', -}); +export const nameStyle = css(typo.Mobile.Text.SemiBold_16, { + width: '220px', +});
38-43
: 이미지 처리 방식 개선 제안고정된 이미지 크기는 이미지 품질에 영향을 줄 수 있습니다. 반응형 크기와 이미지 최적화를 고려해보세요.
이미지 컴포넌트에서 다음 사항들을 고려해주세요:
- 이미지 최적화 (next/image 사용)
- 반응형 크기 처리
- 이미지 로딩 상태 처리
- alt 텍스트 지원
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.style.ts
(1 hunks)src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.tsx
(1 hunks)src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx
(1 hunks)src/components/organisms/BalanceGameSection/BalanceGameSection.tsx
(8 hunks)src/hooks/game/useBalanceGameVote.ts
(1 hunks)src/pages/BalanceGamePage/BalanceGamePage.tsx
(2 hunks)src/pages/mobile/BalanceGameMobilePage/BalanceGameMobilePage.tsx
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.tsx
- src/pages/mobile/BalanceGameMobilePage/BalanceGameMobilePage.tsx
🔇 Additional comments (11)
src/components/mobile/organisms/BalanceGameSection/BalanceGameSection.tsx (3)
70-81
: 내려받은 데이터 변경 시 초기 북마크 스테이지 이동 로직 점검 필요.
useEffect에서 한 번만 동작하도록 설정하고 있으나, game 데이터가 새로 로드되거나 갱신될 때 재실행이 필요한 경우가 있을 수 있습니다. 필요하다면 의존성 배열을 조정해 보세요.
83-90
: 다음 단계 이동 로직이 명확합니다.
비로그인 상태와 로그인 상태를 모두 체크한 후에만 넘어가도록 설계된 부분이 좋습니다.
92-100
: 에러 핸들링 로직 재확인 필요 (북마크 훅).
북마크 처리 훅에서 에러가 발생할 경우를 대비해 별도의 에러 처리 로직을 도입하거나, 사용자에게 알림을 줄 방법을 고려해 보세요.
src/pages/BalanceGamePage/BalanceGamePage.tsx (1)
25-26
: 단일 함수로 단계 전환을 처리하는 방식이 깔끔합니다.
이전과 다음 단계를 일원화하여 처리함으로써 코드 복잡도가 낮아졌습니다. 이 로직으로 인해 stage 범위를 벗어나지 않도록 검증하는 부분도 잘 구현되었습니다.
src/components/mobile/atoms/BalanceGameButton/BalanceGameButton.style.ts (1)
45-56
: 구조가 잘 잡혀있습니다!
콘텐츠 래퍼와 설명 스타일이 잘 구성되어 있습니다. 모바일 타이포그래피를 적절히 확장하여 사용하고 있습니다.
src/hooks/game/useBalanceGameVote.ts (3)
67-81
: 🛠️ Refactor suggestion
뮤테이션 상태 관리 개선 필요
현재 구현에서 다음과 같은 개선이 필요합니다:
- 뮤테이션의 로딩 상태 관리
- 에러 처리
- 동시 호출 방지
다음과 같이 개선하는 것을 추천드립니다:
export const useUserGameVote = (
gameSetId: number,
gameId: number,
handleNextStage: () => void,
) => {
- const { mutate: createGameVote } = useCreateGameVoteMutation(
+ const {
+ mutate: createGameVote,
+ isLoading: isCreating
+ } = useCreateGameVoteMutation(
gameSetId,
gameId,
);
- const { mutate: editGameVote } = useEditGameVoteMutation(gameSetId, gameId);
- const { mutate: deleteGameVote } = useDeleteGameVoteMutation(
+ const {
+ mutate: editGameVote,
+ isLoading: isEditing
+ } = useEditGameVoteMutation(gameSetId, gameId);
+ const {
+ mutate: deleteGameVote,
+ isLoading: isDeleting
+ } = useDeleteGameVoteMutation(
gameSetId,
gameId,
);
+
+ const isLoading = isCreating || isEditing || isDeleting;
Likely invalid or redundant comment.
15-36
:
localStorage 데이터 처리 개선 필요
localStorage에서 데이터를 파싱할 때 발생할 수 있는 예외 상황에 대한 처리가 필요합니다:
다음과 같이 개선하는 것을 추천드립니다:
const updateGuestVotedList = () => {
const storedVotes = localStorage.getItem(`game_${gameSetId}`);
- setGuestVotedList(
- storedVotes ? (JSON.parse(storedVotes) as VoteRecord[]) : [],
- );
+ try {
+ if (!storedVotes) {
+ setGuestVotedList([]);
+ return;
+ }
+ const parsedVotes = JSON.parse(storedVotes);
+ if (Array.isArray(parsedVotes) &&
+ parsedVotes.every(vote =>
+ typeof vote.gameId === 'number' &&
+ (vote.votedOption === 'A' || vote.votedOption === 'B')
+ )) {
+ setGuestVotedList(parsedVotes);
+ } else {
+ console.error('Invalid vote data structure');
+ setGuestVotedList([]);
+ }
+ } catch (error) {
+ console.error('Failed to parse vote data:', error);
+ setGuestVotedList([]);
+ }
};
Likely invalid or redundant comment.
82-104
: 🛠️ Refactor suggestion
투표 처리의 일관성 개선 필요
현재 구현에서 다음과 같은 문제점이 있습니다:
- createGameVote만 onSuccess 콜백이 구현되어 있음
- 뮤테이션 진행 중 중복 호출 방지 로직 없음
- 에러 처리가 일관적이지 않음
다음과 같이 개선하는 것을 추천드립니다:
const handleUserGameVote = (
selectedOption: MyVoteOption,
voteOption: VoteOption,
) => {
+ if (isLoading) return;
+
if (!selectedOption) {
createGameVote(voteOption, {
onSuccess: () => {
const nextStageTimer = setTimeout(() => {
handleNextStage();
}, 500);
return () => clearTimeout(nextStageTimer);
},
+ onError: (error) => {
+ console.error('Failed to create vote:', error);
+ },
});
} else if (selectedOption === voteOption) {
- deleteGameVote();
+ deleteGameVote(undefined, {
+ onSuccess: () => {
+ console.log('Vote deleted successfully');
+ },
+ onError: (error) => {
+ console.error('Failed to delete vote:', error);
+ },
+ });
} else {
- editGameVote(voteOption);
+ editGameVote(voteOption, {
+ onSuccess: () => {
+ console.log('Vote updated successfully');
+ },
+ onError: (error) => {
+ console.error('Failed to update vote:', error);
+ },
+ });
}
};
Likely invalid or redundant comment.
src/components/organisms/BalanceGameSection/BalanceGameSection.tsx (3)
Line range hint 23-67
: 구조가 잘 정의되어 있습니다!
컴포넌트의 props 인터페이스가 명확하게 정의되어 있고, 게스트 투표 관리를 위한 커스텀 훅 사용이 적절합니다.
Line range hint 89-114
: 스테이지 네비게이션 로직이 적절합니다!
타이머 정리와 투표 여부 확인이 잘 구현되어 있습니다.
117-124
: 북마크 처리 로직이 잘 구현되어 있습니다!
useGameBookmark 훅을 통한 관심사 분리와 게스트 사용자 처리가 적절합니다.
const handleGuestGameVote = ( | ||
selectedOption: MyVoteOption, | ||
voteOption: VoteOption, | ||
) => { | ||
const updatedVotes = [...guestVotedList]; | ||
const gameStageId = game?.gameDetailResponses[currentStage]?.id; | ||
|
||
const currentVoteIndex = updatedVotes.findIndex( | ||
(vote) => vote.gameId === gameStageId, | ||
); | ||
|
||
if (!selectedOption) { | ||
updatedVotes.push({ | ||
gameId: gameStageId as number, | ||
votedOption: voteOption, | ||
}); | ||
} else if (selectedOption === voteOption) { | ||
updatedVotes.splice(currentVoteIndex, 1); | ||
} else { | ||
updatedVotes[currentVoteIndex].votedOption = voteOption; | ||
} | ||
|
||
setGuestVotedList(updatedVotes); | ||
localStorage.setItem(`game_${gameSetId}`, JSON.stringify(updatedVotes)); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
게임 스테이지 ID 처리 및 코드 최적화 필요
- gameStageId가 undefined일 수 있는 상황에 대한 처리가 필요합니다.
- gameStageId를 반복적으로 참조하는 부분을 최적화할 수 있습니다.
다음과 같이 개선하는 것을 추천드립니다:
const handleGuestGameVote = (
selectedOption: MyVoteOption,
voteOption: VoteOption,
) => {
+ const gameStageId = game?.gameDetailResponses[currentStage]?.id;
+ if (typeof gameStageId !== 'number') {
+ console.error('Invalid game stage ID');
+ return;
+ }
+
const updatedVotes = [...guestVotedList];
- const gameStageId = game?.gameDetailResponses[currentStage]?.id;
const currentVoteIndex = updatedVotes.findIndex(
(vote) => vote.gameId === gameStageId,
);
if (!selectedOption) {
updatedVotes.push({
- gameId: gameStageId as number,
+ gameId: gameStageId,
votedOption: voteOption,
});
} else if (selectedOption === voteOption) {
updatedVotes.splice(currentVoteIndex, 1);
} else {
updatedVotes[currentVoteIndex].votedOption = voteOption;
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const handleGuestGameVote = ( | |
selectedOption: MyVoteOption, | |
voteOption: VoteOption, | |
) => { | |
const updatedVotes = [...guestVotedList]; | |
const gameStageId = game?.gameDetailResponses[currentStage]?.id; | |
const currentVoteIndex = updatedVotes.findIndex( | |
(vote) => vote.gameId === gameStageId, | |
); | |
if (!selectedOption) { | |
updatedVotes.push({ | |
gameId: gameStageId as number, | |
votedOption: voteOption, | |
}); | |
} else if (selectedOption === voteOption) { | |
updatedVotes.splice(currentVoteIndex, 1); | |
} else { | |
updatedVotes[currentVoteIndex].votedOption = voteOption; | |
} | |
setGuestVotedList(updatedVotes); | |
localStorage.setItem(`game_${gameSetId}`, JSON.stringify(updatedVotes)); | |
}; | |
const handleGuestGameVote = ( | |
selectedOption: MyVoteOption, | |
voteOption: VoteOption, | |
) => { | |
const gameStageId = game?.gameDetailResponses[currentStage]?.id; | |
if (typeof gameStageId !== 'number') { | |
console.error('Invalid game stage ID'); | |
return; | |
} | |
const updatedVotes = [...guestVotedList]; | |
const currentVoteIndex = updatedVotes.findIndex( | |
(vote) => vote.gameId === gameStageId, | |
); | |
if (!selectedOption) { | |
updatedVotes.push({ | |
gameId: gameStageId, | |
votedOption: voteOption, | |
}); | |
} else if (selectedOption === voteOption) { | |
updatedVotes.splice(currentVoteIndex, 1); | |
} else { | |
updatedVotes[currentVoteIndex].votedOption = voteOption; | |
} | |
setGuestVotedList(updatedVotes); | |
localStorage.setItem(`game_${gameSetId}`, JSON.stringify(updatedVotes)); | |
}; |
flexDirection: 'column', | ||
alignItems: 'center', | ||
width: '335px', | ||
height: `calc(100vh - 80px)`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vh에서 80px을 줄이는건 모바일 컴포넌트인 점을 감안하면 나쁘지 않은 선택이네요..!
다만, 이 부분은 최근에 저희가 자주 만나는 사파리나 크롬에서 정상 작동하는지 검증이 필요한 것 같습니닷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+) 정상 작동이라 함은 깨짐이나 랜더링 문제를 말씀드린거에요!
title: string; | ||
gameSetId: number; | ||
isMyGame: boolean; | ||
isMyEndBookmark: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 props의 네이밍은 다소 어색하게 느껴질 수도 있는 거 같습니다!
const { mutate: createBookmark } = useCreateGameBookmarkMutation( | ||
gameSetId, | ||
gameId, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
api 호출 관련해서는 error 처리 정도는 있어야한다고 생각합니다! 물론, 현재 상태에서 추후 추가하는 식으로 진행하셔도 좋아보이네요 ㅎㅎ
}, | ||
decorators: [ | ||
(Story) => ( | ||
<Provider store={store}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이번에 추가된 스토리 파일들에는 다 redux store을 사용하던데 accessToken 관련 처리 때문에 생성한게 맞는지 질문드려요!!
const gameSetId = Number(setId); | ||
|
||
const { gameSet } = useGameBySetId(gameSetId); | ||
const [currentStage, setCurrentStage] = useState<number>(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요런 부분까지는 number을 명시하지 않아도 되지 않을까 의견 제시해봅니다!!
@@ -251,7 +185,7 @@ const BalanceGameSection = ({ | |||
? guestVotedList[currentStage]?.votedOption | |||
: currentGame.votedOption | |||
} | |||
handleNextStage={handleNextStage} | |||
handleNextStage={() => changeStage(1)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
함수 네이밍이나 가독성 면에서는 이전의 방식이 더 직관적이라고 생각하는데, 전 기존의 방식도 좋다고 생각합니다!
💡 작업 내용
💡 자세한 설명
✅ useBalanceGameVote, useBalanceGameBookmark
✅ BalanceGameSection, BalanceGameEndingSection
-.Clipchamp.5.mp4
테스트를 위해 헤더만 지우고 녹화했습니다!! 각각 웹 / 모바일 환경에서의 헤더 길이만큼 padding이 적용된 화면입니다 😊
📗 참고 자료 (선택)
📢 리뷰 요구 사항 (선택)
🚩 후속 작업 (선택)
✅ 셀프 체크리스트
closes #266
Summary by CodeRabbit
새로운 기능
버그 수정
문서화