Skip to content

[FE] SISC1-77 [FEAT] : 베팅 취소 및 페이지네이션#94

Merged
DongEun02 merged 2 commits intomainfrom
SISC1-77-FE-betting-cancel
Nov 12, 2025
Merged

[FE] SISC1-77 [FEAT] : 베팅 취소 및 페이지네이션#94
DongEun02 merged 2 commits intomainfrom
SISC1-77-FE-betting-cancel

Conversation

@DongEun02
Copy link
Contributor

@DongEun02 DongEun02 commented Nov 11, 2025

1) 작업한 이슈번호

SISC1-77

2) 변경 요약 (What & Why)

  • 무엇을 변경했는지: 베팅 시 취소하기 텍스트 생성 및 border와 체크표시 추가, 베팅 이력 페이지네이션
  • 변경했는지(문제/목표):

3) 스크린샷/동영상 (UI 변경 시)

전/후 비교, 반응형(모바일/데스크톱) 캡쳐

  • Before:
  • After:
    상승 베팅 시
image 하락 베팅 시 image

페이지네이션
image
image

4) 상세 변경사항 (전부 다)

  • 라우팅/페이지:
  • 컴포넌트: Pagination.jsx 추가
  • 상태관리:
  • API 호출:
  • 스타일: Pagination.module.css 추가
  • 기타:

5) 참고사항

사이드바 수정하면서 CSS가 틀어진 거 같은데, 현재 올라와있는 사이드바 pr 적용하면 베팅 카드 피그마와 동일하게 디자인되어 있습니다.
사이드바 pr 머지 후, 다시 스타일 수정할 예정입니다.

Summary by CodeRabbit

새로운 기능

  • 베팅 선택 시 활성 표시와 확인 표시가 나타나는 인터랙티브 베팅 컨트롤 추가
  • 베팅 취소 옵션 추가
  • 베팅 내역에 페이지네이션 기능 추가로 데이터 조회 효율성 개선

@DongEun02 DongEun02 requested a review from gxuoo as a code owner November 11, 2025 15:12
@coderabbitai
Copy link

coderabbitai bot commented Nov 11, 2025

요약

Walkthrough

배팅 컴포넌트에 인터랙티브한 상태 관리와 버튼 핸들러를 추가하고, 베팅 이력에 클라이언트 측 페이지네이션 기능을 도입했습니다. 새로운 Pagination 컴포넌트를 추가하고 테스트 데이터를 확장했습니다.

Changes

Cohort / File(s) 변경 요약
배팅 UI 개선
frontend/src/components/stockgame/Betting.jsx, frontend/src/components/stockgame/Betting.module.css
배팅 상태 추적을 위한 isBetting 상태 변수 추가, 상단/하단 배팅 핸들러 구현, 활성 스타일과 체크 인디케이터 추가, 취소 옵션 UI 통합
페이지네이션 기능
frontend/src/components/stockgame/Pagination.jsx, frontend/src/components/stockgame/Pagination.module.css, frontend/src/components/stockgame/BettingHistory.jsx, frontend/src/components/stockgame/BettingHistory.module.css
새로운 Pagination 컴포넌트 작성 (페이지 네비게이션, 동적 페이지 렌더링, 생략 부호 지원), BettingHistory에 클라이언트 측 페이지네이션 로직 추가, 페이지네이션 컨테이너 스타일 추가
스타일 조정
frontend/src/pages/StockGame.module.css
.daily-betting의 수직 간격 10px에서 30px로 증가
테스트 데이터 확장
frontend/src/utils/dailyBettingHistory.js, frontend/src/utils/weeklyBettingHistory.js
반복된 배팅 이력 항목 추가로 데이터셋 확장

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Betting Component
    participant State

    User->>Betting Component: Up/Down 버튼 클릭
    Betting Component->>State: isBetting 상태 업데이트
    State->>Betting Component: 활성 스타일 + 체크 표시
    Betting Component->>User: UI 반영

    User->>Betting Component: 취소(X) 클릭
    Betting Component->>State: isBetting = 'none'
    State->>Betting Component: 상태 초기화
    Betting Component->>User: 버튼 상태 복구
Loading
sequenceDiagram
    participant User
    participant BettingHistory
    participant Pagination Component

    User->>BettingHistory: 페이지 이력 타입 변경
    BettingHistory->>BettingHistory: currentPage = 0 (초기화)
    BettingHistory->>Pagination Component: currentPage, totalPages 전달
    
    User->>Pagination Component: 다음/이전 버튼 클릭
    Pagination Component->>BettingHistory: onPageChange(newPage)
    BettingHistory->>BettingHistory: currentData 계산 및 업데이트
    BettingHistory->>User: 페이지 데이터 렌더링
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

  • 주의 필요 영역:
    • Betting.jsx의 상태 관리 로직과 중복 배팅 방지 로직 검증
    • Pagination.jsx의 경계 조건 처리 및 페이지 계산 로직 (getPages 함수)
    • 여러 컴포넌트 간 데이터 흐름이 일관되는지 확인 (BettingHistory → Pagination)
    • 테스트 데이터의 목적과 규모 검증

Possibly related PRs

Suggested reviewers

  • gxuoo

Poem

🐰 배팅 버튼들 활짝 열리고,
페이지 넘김 부드럽게 흘러가며,
상태 추적 명확해지고,
취소도 쉽게, 체크도 선명하게,
주식 게임 한 걸음 더 나아가네! 📈✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 두 가지 주요 변경사항(베팅 취소 기능과 페이지네이션)을 정확하게 반영하며, 변경사항 전체를 잘 요약하고 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch SISC1-77-FE-betting-cancel

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.

Copy link

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (7)
frontend/src/utils/dailyBettingHistory.js (1)

35-794: 테스트 데이터 다양성을 개선하세요.

페이지네이션 테스트를 위해 동일한 3개의 레코드(2025-08-24, 2025-08-23, 2025-08-22)를 반복하고 있습니다. 이는 페이지네이션 기능 테스트에는 충분하지만, 더 현실적인 테스트를 위해 다음을 고려하세요:

  • 다양한 날짜 범위 사용
  • 여러 종목 심볼 추가 (AAPL 외에 GOOGL, MSFT 등)
  • 다양한 가격 변동 및 백분율
  • 무작위 참가자 수 및 포인트

더 다양한 테스트 데이터를 생성하는 헬퍼 함수를 작성할 수 있습니다:

// 테스트 데이터 생성 헬퍼 추가
const generateTestData = (count) => {
  const symbols = ['AAPL', 'GOOGL', 'MSFT', 'TSLA'];
  const results = ['UP', 'DOWN'];
  const data = [];
  
  for (let i = 0; i < count; i++) {
    const date = new Date(2025, 7, 24 - i);
    const dateStr = date.toISOString().split('T')[0];
    data.push({
      date: dateStr,
      symbol: symbols[i % symbols.length],
      closePrice: 70 + Math.random() * 30,
      nextClosePrice: 70 + Math.random() * 30,
      changePercent: -30 + Math.random() * 60,
      points: 200 + Math.floor(Math.random() * 200),
      participants: 100 + Math.floor(Math.random() * 300),
      result: results[i % 2],
      isCorrect: Math.random() > 0.5,
    });
  }
  return data;
};
frontend/src/components/stockgame/BettingHistory.module.css (1)

130-133: 하드코딩된 여백 값을 개선하세요.

margin-left: 230px는 고정값으로 다양한 화면 크기나 레이아웃 변경에 취약합니다. 더 유연한 중앙 정렬을 위해 다음을 고려하세요:

 .paginationContainer {
   display: flex;
-  margin-left: 230px;
+  justify-content: center;
+  width: 100%;
 }

또는 페이지네이션을 베팅 카드와 정렬해야 하는 경우:

 .paginationContainer {
   display: flex;
-  margin-left: 230px;
+  justify-content: flex-start;
+  padding-left: 0;
+  /* 부모 요소의 패딩/여백과 일치시키기 */
 }
frontend/src/utils/weeklyBettingHistory.js (1)

35-133: 테스트 데이터 다양성을 개선하세요.

dailyBettingHistory.js와 동일한 문제가 있습니다. 동일한 3개 레코드를 4번 반복하는 대신, 더 다양하고 현실적인 주간 베팅 이력 데이터를 생성하세요. 다른 주차, 종목, 가격 변동을 사용하여 페이지네이션과 UI 렌더링을 더 효과적으로 테스트할 수 있습니다.

frontend/src/components/stockgame/BettingHistory.jsx (1)

15-16: 페이지네이션 상태 관리가 올바릅니다.

currentPage 상태와 itemsPerPage 상수를 사용한 페이지네이션 설정이 적절합니다.

향후 유연성을 위해 itemsPerPage를 props로 받는 것을 고려하세요:

-const BettingHistory = ({ type }) => {
+const BettingHistory = ({ type, itemsPerPage = 5 }) => {
   const formatDate = (dateStr) => {
     const [year, month, day] = dateStr.split('-');
     return `${year}년 ${month}월 ${day}일`;
   };

   const [currentPage, setCurrentPage] = useState(1);
-  const itemsPerPage = 5;
frontend/src/components/stockgame/Betting.jsx (2)

11-31: 네이티브 다이얼로그 대신 커스텀 모달을 사용하세요.

confirm()alert()는 작동하지만 사용자 경험을 저해하고 브랜드 일관성이 없습니다.

커스텀 모달 컴포넌트를 사용하는 것을 권장합니다:

// 예시: 커스텀 모달 라이브러리 또는 자체 구현
const onClickUpBet = () => {
  if (isBetting !== 'none') {
    showToast('이미 베팅하셨습니다.', 'warning');
    return;
  }
  
  showConfirmModal({
    title: '상승 베팅',
    message: '상승에 베팅하시겠습니까?',
    onConfirm: () => {
      setIsBetting('up');
      // API 호출 추가
    }
  });
};

추가로 핸들러 로직에 중복이 있습니다. 리팩토링을 고려하세요:

const handleBet = (betType, message) => {
  if (isBetting !== 'none') {
    alert('이미 베팅하셨습니다.');
    return;
  }
  if (confirm(message)) {
    setIsBetting(betType);
    // TODO: API 호출 추가
  }
};

const onClickUpBet = () => handleBet('up', '상승에 베팅하시겠습니까?');
const onClickDownBet = () => handleBet('down', '하락에 베팅하시겠습니까?');

57-63: 아이콘 문자 대신 실제 아이콘을 사용하세요.

체크 표시로 텍스트 'v'를 사용하고 있습니다. 더 나은 시각적 표현과 접근성을 위해 실제 체크 아이콘을 사용하세요.

// 체크 아이콘을 import
import checkIcon from '../../assets/check_icon.svg';

// JSX에서:
{isBetting === 'up' && (
  <div className={styles.upBetCheck}>
    <img src={checkIcon} alt="체크" />
  </div>
)}

또는 SVG 아이콘 라이브러리 사용:

import { Check } from 'react-icons/fa'; // 또는 다른 아이콘 라이브러리

{isBetting === 'up' && (
  <div className={styles.upBetCheck}>
    <Check size={10} />
  </div>
)}

Also applies to: 73-81

frontend/src/components/stockgame/Pagination.jsx (1)

25-76: 접근성 속성을 추가하세요.

페이지네이션 컴포넌트에 스크린 리더 사용자를 위한 접근성 속성이 누락되었습니다.

다음과 같이 접근성을 개선하세요:

-    <div className={styles.pagination}>
+    <nav className={styles.pagination} role="navigation" aria-label="페이지네이션">
       <button
         className={styles.arrow}
         onClick={() => handleClick(currentPage - 1)}
         disabled={currentPage === 1}
+        aria-label="이전 페이지"
       >
         &lt; 이전
       </button>
       
       ...
       
       {pages.map((page) => (
         <button
           key={page}
           className={`${styles.page} ${
             page === currentPage ? styles.active : ''
           }`}
           onClick={() => handleClick(page)}
+          aria-label={`${page}페이지`}
+          aria-current={page === currentPage ? 'page' : undefined}
         >
           {page}
         </button>
       ))}
       
       ...
       
       <button
         className={styles.arrow}
         onClick={() => handleClick(currentPage + 1)}
         disabled={currentPage === totalPages}
+        aria-label="다음 페이지"
       >
         다음 &gt;
       </button>
-    </div>
+    </nav>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e54bbd and 2ecf742.

📒 Files selected for processing (9)
  • frontend/src/components/stockgame/Betting.jsx (3 hunks)
  • frontend/src/components/stockgame/Betting.module.css (3 hunks)
  • frontend/src/components/stockgame/BettingHistory.jsx (2 hunks)
  • frontend/src/components/stockgame/BettingHistory.module.css (1 hunks)
  • frontend/src/components/stockgame/Pagination.jsx (1 hunks)
  • frontend/src/components/stockgame/Pagination.module.css (1 hunks)
  • frontend/src/pages/StockGame.module.css (1 hunks)
  • frontend/src/utils/dailyBettingHistory.js (1 hunks)
  • frontend/src/utils/weeklyBettingHistory.js (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
frontend/src/components/stockgame/Pagination.jsx (1)
frontend/src/components/stockgame/BettingHistory.jsx (2)
  • totalPages (26-26)
  • currentPage (15-15)
frontend/src/components/stockgame/Betting.jsx (1)
frontend/src/utils/bettingInfo.js (4)
  • mockDailyBet (1-9)
  • mockDailyBet (1-9)
  • mockWeeklyBet (11-19)
  • mockWeeklyBet (11-19)
frontend/src/components/stockgame/BettingHistory.jsx (3)
frontend/src/utils/weeklyBettingHistory.js (2)
  • weeklyBettingHistory (1-134)
  • weeklyBettingHistory (1-134)
frontend/src/utils/dailyBettingHistory.js (2)
  • dailyBettingHistory (1-794)
  • dailyBettingHistory (1-794)
frontend/src/components/stockgame/Pagination.jsx (1)
  • Pagination (3-77)
🔇 Additional comments (14)
frontend/src/pages/StockGame.module.css (1)

51-51: 간격 조정이 새로운 UI 요소를 수용합니다.

gap을 10px에서 30px으로 증가시킨 것은 Betting.jsx에 추가된 취소 버튼과 활성 상태 표시기를 위한 공간을 확보하는 데 적합합니다.

frontend/src/components/stockgame/BettingHistory.jsx (3)

19-21: 타입 변경 시 페이지 초기화가 올바르게 구현되었습니다.

type prop이 변경될 때 currentPage를 1로 리셋하는 것은 주간/일간 베팅 전환 시 사용자 경험을 위한 올바른 접근입니다.


26-36: 페이지네이션 계산 로직이 정확합니다.

totalPages 계산, currentData 슬라이싱, handlePageChange 핸들러가 모두 올바르게 구현되었습니다.


83-89: Pagination 컴포넌트 통합이 적절합니다.

Pagination 컴포넌트에 필요한 모든 props(currentPage, totalPages, onPageChange)를 올바르게 전달하고 있습니다.

frontend/src/components/stockgame/Betting.module.css (4)

12-12: 상대 위치 지정이 올바르게 추가되었습니다.

position: relative를 추가하여 내부의 절대 위치 요소(취소 버튼)를 위한 컨테이너 역할을 하도록 합니다.


82-101: 상승 베팅 활성 상태 스타일이 잘 구현되었습니다.

position: relative, .upActive 보더, .upBetCheck 체크 표시의 조합이 활성 베팅 상태를 명확하게 시각화합니다.


115-134: 하락 베팅 활성 상태 스타일이 잘 구현되었습니다.

상승 베팅과 일관된 패턴으로 하락 베팅의 활성 상태를 표시합니다. 색상 구분(#ff6348)이 명확합니다.


136-145: 취소 버튼 위치와 스타일이 적절합니다.

절대 위치(bottom: 15px, right: 30px)를 사용하여 카드 하단 우측에 취소 옵션을 배치한 것이 UI/UX 관점에서 적절합니다.

frontend/src/components/stockgame/Pagination.module.css (1)

1-35: 페이지네이션 스타일이 깔끔하고 접근성이 좋습니다.

새로운 Pagination.module.css가 잘 구성되어 있습니다:

  • Flexbox 레이아웃으로 중앙 정렬
  • 버튼에 적절한 패딩과 border-radius
  • 비활성화 상태에 cursor: not-allowed 사용
  • 활성 페이지를 위한 명확한 시각적 구분
  • 부드러운 전환 효과
frontend/src/components/stockgame/Betting.jsx (3)

8-8: 베팅 상태 관리가 적절히 초기화되었습니다.

isBetting 상태를 'none'으로 초기화하여 세 가지 상태('none', 'up', 'down')를 관리하는 것이 적절합니다.


11-31: API 통합을 위한 준비를 확인하세요.

현재 구현은 로컬 상태만 업데이트합니다. 실제 베팅을 서버에 저장하는 API 호출이 필요합니다. TODO 주석을 추가하거나 다음 단계로 API 통합을 계획하고 있는지 확인하세요.

API 엔드포인트가 준비되어 있나요? 다음과 같은 호출이 필요합니다:

const onClickUpBet = async () => {
  if (isBetting !== 'none') {
    alert('이미 베팅하셨습니다.');
    return;
  }
  if (confirm('상승에 베팅하시겠습니까?')) {
    try {
      await api.placeBet({ type: 'up', period, date: mockBettingInfo.date });
      setIsBetting('up');
    } catch (error) {
      alert('베팅에 실패했습니다.');
    }
  }
};

84-88: 취소 기능이 잘 구현되었습니다.

isBetting !== 'none'일 때만 취소 버튼을 조건부 렌더링하는 것이 적절합니다. 사용자에게 명확한 시각적 피드백을 제공합니다.

frontend/src/components/stockgame/Pagination.jsx (2)

3-7: 페이지 검증 로직이 정확합니다.

유효하지 않은 페이지 번호에 대한 방어 로직이 올바르게 구현되어 있습니다.


9-21: 슬라이딩 윈도우 계산 로직이 올바릅니다.

최대 5개의 페이지를 표시하는 윈도우가 현재 페이지를 중심으로 정확하게 계산되며, 시작과 끝 경계에서의 엣지 케이스도 적절히 처리됩니다.

<button className={styles.page} onClick={() => handleClick(1)}>
1
</button>
{totalPages > 10 && <span className={styles.ellipsis}>...</span>}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

말줄임표 표시 조건을 의미적으로 개선하세요.

현재 totalPages > 10 조건은 페이지 간 실제 간격이 아닌 전체 페이지 수만 확인합니다. 말줄임표는 표시되는 페이지 사이에 숨겨진 페이지가 있을 때만 나타나야 합니다.

다음 diff를 적용하여 조건을 개선하세요:

-          {totalPages > 10 && <span className={styles.ellipsis}>...</span>}
+          {pages[0] > 2 && <span className={styles.ellipsis}>...</span>}

그리고:

-          {totalPages > 10 && <span className={styles.ellipsis}>...</span>}
+          {pages[pages.length - 1] < totalPages - 1 && <span className={styles.ellipsis}>...</span>}

Also applies to: 58-58

🤖 Prompt for AI Agents
In frontend/src/components/stockgame/Pagination.jsx around lines 40 and 58, the
ellipsis display currently uses the semantic-less check `totalPages > 10`;
change it to show ellipses only when there are hidden pages outside the
displayed range: use the component's computed startPage and endPage (or the
equivalent variables that determine the visible page window) and render a
leading ellipsis only when startPage > 1 and a trailing ellipsis only when
endPage < totalPages so ellipses appear only when pages are actually hidden.

@DongEun02 DongEun02 merged commit 18d028f into main Nov 12, 2025
1 check passed
@DongEun02 DongEun02 deleted the SISC1-77-FE-betting-cancel branch November 12, 2025 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant