Skip to content

[feat] 동아리 클릭 게임 폭죽·다크모드 추가 및 resetAt 안내 제거#1682

Merged
seongwon030 merged 9 commits into
develop-fefrom
refactor/#1681-remove-game-ranking-reset-info-MOA-977
Jun 17, 2026
Merged

[feat] 동아리 클릭 게임 폭죽·다크모드 추가 및 resetAt 안내 제거#1682
seongwon030 merged 9 commits into
develop-fefrom
refactor/#1681-remove-game-ranking-reset-info-MOA-977

Conversation

@seongwon030

@seongwon030 seongwon030 commented Jun 16, 2026

Copy link
Copy Markdown
Member

배경

동아리 클릭 게임(GamePage) 관련 작업을 모았습니다. 백엔드의 랭킹 자동 초기화 제거에 따른 안내 문구 정리와 함께, 게임 페이지의 인터랙션/반응형/테마를 개선했습니다.

⚠️ 원래 이 PR은 resetAt 안내 제거(MOA-977)만 다뤘으나, 동일 브랜치에서 GamePage 후속 작업이 이어져 함께 포함되었습니다.

변경 사항

1. resetAt 기반 랭킹 초기화 안내 제거 (refactor, MOA-977)

백엔드에서 랭킹 매주 월요일 자정 자동 초기화가 제거되고 관리자 수동 초기화로 변경됨. resetAt는 더 이상 '실제 초기화 예정 시각'이 아니라 무의미한 표시값이 되어 안내 문구를 제거.

  • RankingBoard.tsx매일 ○○ 초기화 렌더 + resetTime 계산 제거, 미사용 resetAt prop 제거
  • GamePage.tsx — orphan 된 resetAt prop 2곳 제거
  • RankingBoard.styles.ts — orphan 된 ResetInfo styled 제거
  • types/game.tsresetAt 필드는 API 응답 스펙 유지 위해 보존

2. 클릭 배칭 로직 훅 분리 (refactor)

  • GamePage.tsx에 인라인으로 있던 클릭 배칭(5회 또는 500ms 디바운스) 로직을 useBatchedClick 훅으로 분리
  • 언마운트 시 미전송 클릭 보존 동작 유지

3. 폭죽 이펙트 및 다크모드 토글 (feat)

  • 반응형 수정: 순위표 겹침 해결 (전환 기준 tabletlaptop, 순위표 중앙 정렬), 배경 blob 그라데이션 제거
  • 클릭 폭죽: 클릭 버튼 누를 때마다 파티클이 방사형으로 터지는 이펙트
  • 100회 배경 폭죽: 랭킹의 어떤 동아리든 누적 클릭이 100단위를 넘기면 화면 전체 대형 폭죽 발사 (BackgroundFirework, 신규)
  • 다크모드 토글: GamePage 한정 다크모드. SVG 해/달 슬라이딩 스위치, sessionStorage 영속화. DotTextEffectdotColor prop화

검증

  • npm run typecheck 통과
  • npm run format 적용

Resolves MOA-977 (#1681)

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 게임 페이지에 다크모드 토글 추가 및 세션에 상태 유지
    • 클릭 시 버튼 중심의 폭죽/파티클 이펙트 표시
    • 100 클릭 단위로 고정 배경 폭죽 애니메이션 노출
  • Bug Fixes

    • 라이트모드 리더보드 카드 배경/구분을 더 선명하게 개선
  • Documentation

    • 게임 페이지 이펙트 및 트래킹 정책 문서 보강
  • Style

    • 다크모드에 따라 제목/설명/토글/랭킹 및 카드 스타일을 조건부로 개선, 반응형 기준 조정 및 중앙 배치 개선

자동 초기화가 관리자 수동 초기화로 변경되어 resetAt이 무의미한 표시값이 됨.
'매일 OO 초기화' 안내 문구와 연관 prop/스타일 제거.
@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
moadong Ready Ready Preview, Comment Jun 17, 2026 11:45am

@github-actions github-actions Bot added 💻 FE Frontend 🔨 Refactor 코드 리팩토링 labels Jun 16, 2026
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid regex pattern for base branch. at "reviews.auto_review.base_branches[0]"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

GamePage에 클릭 시 버튼 중심 파티클 폭죽(ClickButton), 100회 단위 배경 폭죽(BackgroundFirework), 세션스토리지 기반 다크모드 토글($dark prop 전파)을 추가했다. 클릭 배칭 로직은 useBatchedClick 훅으로 분리되었으며, 기존 Blob 배경 애니메이션과 resetAt prop이 제거됐다. 게임 시작 버튼 이벤트 추적이 추가되었다.

Changes

GamePage 폭죽 이펙트 및 다크모드 토글

Layer / File(s) Summary
useBatchedClick 훅 신규 도입
frontend/src/pages/GamePage/hooks/useBatchedClick.ts
클릭을 pendingRef에 누적하고 임계치(5회) 도달 시 즉시 flush, 미달 시 500ms 디바운스로 전송하는 훅을 신규 추가했다. 언마운트 cleanup에서 ref 미러링으로 미전송 클릭을 처리한다.
BackgroundFirework 컴포넌트 신규 추가
frontend/src/pages/GamePage/components/BackgroundFirework/BackgroundFirework.tsx
framer-motion 기반 70개 파티클 폭죽 컴포넌트를 신규 추가했다. position: fixed + zIndex: 0으로 콘텐츠 뒤에 렌더링되며 memo로 최적화됐다.
ClickButton 클릭 파티클 이펙트 및 다크모드 지원
frontend/src/pages/GamePage/components/ClickButton/ClickButton.styles.ts, frontend/src/pages/GamePage/components/ClickButton/ClickButton.tsx
bursts 상태와 1200ms 타이머로 클릭 파티클 오버레이를 표시·제거한다. isDark prop이 추가되어 ClubLabel/CountLabel 색상이 조건부로 적용되고, ButtonArea styled 컴포넌트가 신규 추가됐다.
DotTextEffect 다크모드 색상 지원
frontend/src/pages/GamePage/components/DotTextEffect/DotTextEffect.tsx
dotColor prop을 추가하여 기존 고정 상수 대신 동적 색상을 받도록 변경했다. 도트 렌더링 경로 모두에서 fillStyledotColor로 적용된다.
RankingBoard 다크모드 지원 및 resetAt 제거
frontend/src/pages/GamePage/components/RankingBoard/RankingBoard.styles.ts, frontend/src/pages/GamePage/components/RankingBoard/RankingBoard.tsx
resetAt prop 제거, isDark prop 추가, Title/Item/ClubName/EmptyMessage$dark 조건부 색상으로 렌더링되도록 변경했다. Wrappermargin: 0 auto 중앙 정렬이 추가됐다.
GamePage 스타일 업데이트 및 오케스트레이션
frontend/src/pages/GamePage/GamePage.styles.ts, frontend/src/pages/GamePage/GamePage.tsx
Blob 스타일 제거, ToggleBar/ToggleSwitch/ToggleKnob 신규 추가, 미디어 기준 media.laptop 변경을 적용했다. useBatchedClick 위임, sessionStorage 다크모드 상태, 마일스톤 기반 BackgroundFirework 트리거 effect, $dark prop 전파를 구현했다.
ClubNameInput 다크모드 및 게임 시작 이벤트 추적
frontend/src/pages/GamePage/components/ClubNameInput/ClubNameInput.styles.ts, frontend/src/pages/GamePage/components/ClubNameInput/ClubNameInput.tsx
ClubNameInput 스타일에 $dark 조건부 색상을 적용했다. isDark prop 추가 후 게임 시작 버튼 성공 시 trackEvent(USER_EVENT.GAME_START_BUTTON_CLICKED, { clubName })을 발송한다.
이벤트 상수 및 기능 문서화
frontend/src/constants/eventName.ts, frontend/docs/features/game/game-effects-darkmode.md, frontend/docs/features/game/game-tracking.md
eventName.ts에 GAME_START_BUTTON_CLICKED 이벤트와 GAME_PAGE 페이지뷰를 추가했다. 게임 이펙트/다크모드 및 게임 추적 정책을 신규 문서에 정리했다.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant GamePage
  participant sessionStorage
  participant ClickButton
  participant BackgroundFirework

  rect rgba(99, 179, 237, 0.5)
    Note over User,sessionStorage: 다크모드 토글 흐름
    User->>GamePage: 토글 버튼 클릭
    GamePage->>sessionStorage: game_dark_mode 저장
    GamePage->>GamePage: isDark 상태 갱신
    GamePage->>ClickButton: isDark prop 전달
  end

  rect rgba(154, 230, 180, 0.5)
    Note over User,BackgroundFirework: 클릭 및 파티클 폭죽 흐름
    User->>ClickButton: 클릭
    ClickButton->>ClickButton: handleClick 호출 (useBatchedClick)
    ClickButton->>ClickButton: pendingRef 증가 / threshold 도달 시 즉시 flush<br/>미달 시 500ms 디바운스
    ClickButton->>ClickButton: bursts에 id 추가 → Firework 파티클 렌더
    ClickButton->>ClickButton: 1200ms 후 burst 제거
  end

  rect rgba(251, 211, 141, 0.5)
    Note over GamePage,BackgroundFirework: 배경 폭죽 마일스톤 트리거 흐름
    GamePage->>GamePage: 2초 폴링으로 랭킹 clickCount 감지
    GamePage->>GamePage: MILESTONE_UNIT(100) 단위 돌파 확인
    alt 마일스톤 돌파 감지
      GamePage->>BackgroundFirework: bgBursts에 ID 추가하여 position:fixed 렌더
      BackgroundFirework->>BackgroundFirework: 70개 파티클 x/y 경로, opacity, rotate 애니메이션
      BackgroundFirework-->>GamePage: 애니메이션 완료 후 ID 제거
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Moadong/moadong#1487: clickGame 카운트 기반 배칭 전송 목표가 이번 PR의 useBatchedClick 훅 및 GamePage.tsx 클릭 처리 리팩터링과 직접 연관된다.
  • Moadong/moadong#1471: DotTextEffect, RankingBoard, ClickButton 컴포넌트의 초기 구현이 이번 PR에서 변경되는 동일한 파일들과 직접 연관된다.

Suggested labels

✨ Feature, 🎨 Design

Suggested reviewers

  • suhyun113
  • oesnuj
  • lepitaaar
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 주요 변경 사항을 정확하게 반영하고 있습니다. '폭죽(confetti effects)', '다크모드(dark mode toggle)', 'resetAt 안내 제거(removal of resetAt guidance)'라는 세 가지 핵심 변경 사항이 명확하고 간결하게 표현되어 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/#1681-remove-game-ranking-reset-info-MOA-977

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@seongwon030 seongwon030 changed the base branch from main to develop-fe June 16, 2026 03:19
@seongwon030 seongwon030 changed the title refactor(game): resetAt 기반 랭킹 초기화 안내 제거 [refactor] resetAt 기반 랭킹 초기화 안내 제거 Jun 16, 2026
@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown

✅ UI 변경사항 없음

구분 링크
📖 Storybook https://67904e61c16daa99a63b44a7-xkthzeohyu.chromatic.com/

전체 60개 스토리 · 23개 컴포넌트

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a mobile-responsive settings tab (SettingsTab) for the admin page, extracts admin tab configurations, and modularizes logout logic into a reusable useLogout hook. It also removes daily reset time displays from the game ranking board and refines global and component styles. Feedback focuses on ensuring local logout cleanup runs in a finally block to handle API failures gracefully, utilizing currentColor in SVG icons for dynamic color styling, and adhering to the design system by using typography tokens instead of hardcoded styles.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

I am having trouble creating individual review comments. Click here to see my feedback.

frontend/src/hooks/useLogout.ts (10-22)

high

logout() API 호출이 실패하더라도 클라이언트 측의 토큰 삭제 및 로그인 페이지로의 이동은 항상 수행되어야 합니다. 현재 구현에서는 API 호출이 실패하면 catch 블록으로 빠져 에러 메시지만 보여주고 로컬 로그아웃 처리가 되지 않아, 세션이 만료되었거나 서버 에러가 발생했을 때 사용자가 로그아웃할 수 없는 상태에 빠질 수 있습니다. finally 블록을 사용하여 항상 로컬 로그아웃 처리가 완료되도록 개선하는 것을 권장합니다.

  const handleLogout = async () => {
    const confirmed = window.confirm('정말 로그아웃하시겠습니까?');
    if (!confirmed) return;

    try {
      await logout();
      trackEvent(ADMIN_EVENT.LOGOUT_BUTTON_CLICKED);
    } catch {
      alert('로그아웃에 실패했습니다.');
    } finally {
      localStorage.removeItem('accessToken');
      navigate('/admin/login', { replace: true });
    }
  };

frontend/src/assets/images/icons/right_arrow_icon.svg (2)

medium

SVG 내부의 stroke 값을 currentColor로 설정하면, styled-components에서 color 속성을 통해 아이콘 색상을 동적으로 제어할 수 있어 유지보수성이 향상됩니다. 이렇게 변경하면 SettingsTab.styles.ts나 SettingsCard.styles.ts에서 nested path 선택자를 사용하지 않고 부모 컴포넌트의 color 지정만으로 색상을 변경할 수 있습니다.

<path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>

frontend/src/pages/AdminPage/tabs/SettingsTab/SettingsTab.styles.ts (23-28)

medium

PageTitle 컴포넌트에 font-size, font-weight, line-height가 하드코딩되어 있습니다. 프로젝트의 디자인 시스템 일관성을 유지하기 위해, 하드코딩 대신 setTypography 유틸리티와 정의된 타이틀 토큰(예: typography.title 계열)을 사용하도록 수정해 주세요. 스타일을 구현할 때는 토큰 이름이 의미상 맞지 않는 것처럼 보이더라도 디자인 시스템(예: Figma)에 지정된 타이틀 토큰과 일치시키는 것을 우선시하고, 불일치 사항은 임의의 코드 변경 대신 디자인 팀과의 논의를 통해 해결해야 합니다.

References
  1. 스타일을 구현할 때, 토큰 이름이 의미상 맞지 않는 것처럼 보이더라도 디자인 시스템(예: Figma)에 지정된 타이틀 토큰과 일치시키는 것을 우선시하고, 불일치 사항은 임의의 코드 변경 대신 디자인 팀과의 논의를 통해 해결해야 합니다.

frontend/src/pages/AdminPage/tabs/SettingsTab/SettingsTab.styles.ts (91-99)

medium

right_arrow_icon.svg 파일의 stroke 속성을 currentColor로 변경하면, nested path 선택자를 사용할 필요 없이 color 속성만으로 간단하게 색상을 지정할 수 있습니다.

export const RightArrowIcon = styled(RightArrowSvg)`
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  color: ${colors.base.white};
`;

@lepitaaar lepitaaar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

제거 수고하셧습니다~

GamePage에 인라인으로 있던 클릭 배칭(5회 또는 500ms 디바운스로
모아 전송) 로직을 별도 훅으로 추출해 페이지 컴포넌트 가독성 확보
- 순위표 반응형 겹침 수정 (전환 기준 tablet→laptop, 순위표 중앙 정렬)
- 클릭 버튼 폭죽 파티클 이펙트 추가
- 랭킹 100회 단위 돌파 시 화면 전체 배경 대형 폭죽 발사
- GamePage 한정 다크모드 토글(SVG 슬라이딩 스위치) 추가
- DotTextEffect dotColor prop화, 배경 blob 그라데이션 제거
@seongwon030 seongwon030 changed the title [refactor] resetAt 기반 랭킹 초기화 안내 제거 [feat] 동아리 클릭 게임 폭죽·다크모드 추가 및 resetAt 안내 제거 Jun 16, 2026
- PAGE_VIEW.GAME_PAGE, USER_EVENT.GAME_START_BUTTON_CLICKED 추가
- GamePage 진입 시 useTrackPageView 적용
- ClubNameInput 동아리명 검증 성공 시 게임 시작 이벤트 전송

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/pages/GamePage/GamePage.tsx (1)

191-200: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

모바일 순위표에 다크모드 prop 전달이 누락되었습니다.

Line 197-200의 RankingBoardisDark를 받지 않아 모바일에서는 Title/EmptyMessage가 항상 라이트 모드 색상으로 렌더링됩니다. 데스크톱(Line 144-148)과 동작이 불일치합니다.

🔧 제안 수정안
             <RankingBoard
               ranking={rankingData?.clubs ?? []}
               myClubName={clubName}
+              isDark={isDark}
             />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/GamePage/GamePage.tsx` around lines 191 - 200, The
RankingBoard component in the mobile view (inside the S.MobileOnly section at
lines 197-200) is missing the isDark prop that is present in the desktop version
(lines 144-148). Add the isDark prop to the mobile RankingBoard component to
ensure consistent dark mode styling between desktop and mobile views. The isDark
value should be sourced from the same state or props that is being used for the
desktop RankingBoard component.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/pages/GamePage/components/ClickButton/ClickButton.tsx`:
- Around line 93-95: The setTimeout callback that filters bursts (line 93-95) is
not being cleaned up when the component unmounts, which can cause the callback
to execute after unmounting and trigger state updates on an unmounted component.
Store the timeout ID returned by setTimeout in a useRef, then add a useEffect
hook with a cleanup function that calls clearTimeout with that ref to ensure the
timer is cancelled when the component unmounts. Apply this same pattern to all
other setTimeout or async operations in the component that modify state.
- Around line 105-124: Move the inline style object from the motion.button
component (lines 105-124) into a new styled-component in ClickButton.styles.ts
following the styled-components pattern. Create a styled motion.button component
that contains all the CSS properties currently defined inline (width, height,
borderRadius, border, background, color, fontSize, fontWeight, cursor,
boxShadow, userSelect, position, zIndex), then replace the motion.button in
ClickButton.tsx with this new styled component while preserving the onClick
handler and motion attributes (whileTap, whileHover, transition). This
consolidation will enable responsive style rules to be applied consistently and
align with the project's styled-components coding guidelines.

In `@frontend/src/pages/GamePage/hooks/useBatchedClick.ts`:
- Around line 20-24: The click count in pendingRef.current is being reset to 0
before the clickGame request is sent on line 22-23, so if the request fails, the
count is lost and cannot be recovered. Move the pendingRef.current reset to only
happen after the clickGame request succeeds. Wrap the clickGame call to handle
failures by restoring pendingRef.current back to the original count value, and
consider scheduling a retry of the failed batch.

---

Outside diff comments:
In `@frontend/src/pages/GamePage/GamePage.tsx`:
- Around line 191-200: The RankingBoard component in the mobile view (inside the
S.MobileOnly section at lines 197-200) is missing the isDark prop that is
present in the desktop version (lines 144-148). Add the isDark prop to the
mobile RankingBoard component to ensure consistent dark mode styling between
desktop and mobile views. The isDark value should be sourced from the same state
or props that is being used for the desktop RankingBoard component.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3470479b-1c6f-481f-8335-ab5c3c83c031

📥 Commits

Reviewing files that changed from the base of the PR and between 8ccd142 and 500d91c.

📒 Files selected for processing (10)
  • frontend/docs/features/game/game-effects-darkmode.md
  • frontend/src/pages/GamePage/GamePage.styles.ts
  • frontend/src/pages/GamePage/GamePage.tsx
  • frontend/src/pages/GamePage/components/BackgroundFirework/BackgroundFirework.tsx
  • frontend/src/pages/GamePage/components/ClickButton/ClickButton.styles.ts
  • frontend/src/pages/GamePage/components/ClickButton/ClickButton.tsx
  • frontend/src/pages/GamePage/components/DotTextEffect/DotTextEffect.tsx
  • frontend/src/pages/GamePage/components/RankingBoard/RankingBoard.styles.ts
  • frontend/src/pages/GamePage/components/RankingBoard/RankingBoard.tsx
  • frontend/src/pages/GamePage/hooks/useBatchedClick.ts

Comment thread frontend/src/pages/GamePage/components/ClickButton/ClickButton.tsx Outdated
Comment thread frontend/src/pages/GamePage/components/ClickButton/ClickButton.tsx Outdated
Comment thread frontend/src/pages/GamePage/hooks/useBatchedClick.ts
- ClubNameInput 다크모드 미적용 보강 (제목/입력창/드롭다운)
- RankingBoard 순위 카드 다크 톤 전환 (내 동아리 카드는 주황 강조 유지)
- 라이트모드에서 페이지 배경과 동일색이던 일반 카드를 흰색+보더+그림자로 분리

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/pages/GamePage/components/ClubNameInput/ClubNameInput.tsx (1)

58-76: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

중복 제출 방지 가드가 필요합니다.

Line 58에서 isValidating 재진입 방어가 없어 Enter 연타 시 검증/이벤트/시작 로직이 중복 실행될 수 있습니다. 버튼 disabled만으로는 키보드 경로를 막지 못합니다.

수정 예시
 const handleSubmit = async () => {
+  if (isValidating) return;
   const trimmed = value.trim();
   if (!trimmed) return;

   setIsValidating(true);
   try {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/GamePage/components/ClubNameInput/ClubNameInput.tsx`
around lines 58 - 76, The handleSubmit function lacks a guard against duplicate
submissions when users rapidly press Enter, allowing validation and onStart
logic to execute multiple times concurrently. Add an early return guard at the
beginning of the handleSubmit function that checks if isValidating is already
true, returning immediately before any validation or event tracking occurs. This
prevents re-entrance even when triggered via keyboard input that bypasses the
disabled button state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/pages/GamePage/components/ClickButton/ClickButton.tsx`:
- Around line 86-104: The timersRef.current array accumulates timer IDs
indefinitely because timers are only pushed to the array but never removed after
they execute. In the handleClick function, after the setTimeout callback
completes and updates the bursts state, the timer ID should be removed from
timersRef.current to prevent unbounded memory growth. Modify the setTimeout
callback to also remove the timer ID from the timersRef array once it has
executed, ensuring completed timers do not persist in memory during long gaming
sessions.

---

Outside diff comments:
In `@frontend/src/pages/GamePage/components/ClubNameInput/ClubNameInput.tsx`:
- Around line 58-76: The handleSubmit function lacks a guard against duplicate
submissions when users rapidly press Enter, allowing validation and onStart
logic to execute multiple times concurrently. Add an early return guard at the
beginning of the handleSubmit function that checks if isValidating is already
true, returning immediately before any validation or event tracking occurs. This
prevents re-entrance even when triggered via keyboard input that bypasses the
disabled button state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 94928a40-65bb-453f-a00b-df99195222c8

📥 Commits

Reviewing files that changed from the base of the PR and between 500d91c and 24cb593.

📒 Files selected for processing (10)
  • frontend/docs/features/game/game-effects-darkmode.md
  • frontend/docs/features/game/game-tracking.md
  • frontend/src/constants/eventName.ts
  • frontend/src/pages/GamePage/GamePage.tsx
  • frontend/src/pages/GamePage/components/ClickButton/ClickButton.tsx
  • frontend/src/pages/GamePage/components/ClubNameInput/ClubNameInput.styles.ts
  • frontend/src/pages/GamePage/components/ClubNameInput/ClubNameInput.tsx
  • frontend/src/pages/GamePage/components/RankingBoard/RankingBoard.styles.ts
  • frontend/src/pages/GamePage/components/RankingBoard/RankingBoard.tsx
  • frontend/src/pages/GamePage/hooks/useBatchedClick.ts
✅ Files skipped from review due to trivial changes (2)
  • frontend/docs/features/game/game-tracking.md
  • frontend/docs/features/game/game-effects-darkmode.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/pages/GamePage/components/RankingBoard/RankingBoard.tsx
  • frontend/src/pages/GamePage/GamePage.tsx

Comment thread frontend/src/pages/GamePage/components/ClickButton/ClickButton.tsx
@seongwon030 seongwon030 merged commit 77a60bc into develop-fe Jun 17, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend 🔨 Refactor 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants