Skip to content

[FE] SISC1-164 [FEAT] : 베팅 페이지 API 연동#108

Merged
DongEun02 merged 6 commits intomainfrom
SISC1-164-FE-API-betting
Nov 14, 2025
Merged

[FE] SISC1-164 [FEAT] : 베팅 페이지 API 연동#108
DongEun02 merged 6 commits intomainfrom
SISC1-164-FE-API-betting

Conversation

@DongEun02
Copy link
Contributor

@DongEun02 DongEun02 commented Nov 14, 2025

1) 작업한 이슈번호

SISC1-164

2) 변경 요약 (What & Why)

  • 무엇을 변경했는지: 슬라이더 바 WIDTH 헤더와 통일, 베팅 카드, 이력 카드 간격 수정, 베팅 라운드 조회 API 연동
  • 변경했는지(문제/목표):

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

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

  • Before:
  • After:

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

  • 라우팅/페이지:
  • 컴포넌트:
  • 상태관리:
  • API 호출:
  • 스타일:
  • 기타:

5) 참고사항

베팅 이력 백엔드 해결 후 다시 연결 예정
이력 -> 내 이력, 전체 이력으로 나눌 예정
베팅 참여인원/포인트 백엔드 구현 후 다시 추가할 예정

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 베팅 UI가 일일/주간 베팅 및 베팅 내역을 실제 API에서 가져오도록 전환 — 로딩·빈 상태·에러 처리 추가
  • Style

    • 사이드바 너비 확대(200px → 264px)
    • 베팅 카드 높이 및 간격 조정(여러 컴포넌트에서 높이 증가, gap 추가)
    • 주식게임 페이지 레이아웃(좌측 마진 추가, 일부 타이포그래피 선택자 조정)
  • Chores

    • 기존 모의(mock) 베팅 및 히스토리 데이터 제거, API 호출용 유틸 함수 추가

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

coderabbitai bot commented Nov 14, 2025

Walkthrough

사이드바 너비를 확장하고, 모의 베팅 데이터를 제거하여 API 기반 비동기 호출(dailyBet/weeklyBet, getDailyBetHistory/getWeeklyBetHistory)으로 전환하고 관련 컴포넌트 및 CSS를 조정했습니다. 정적 모의 파일들이 삭제되었습니다.

Changes

응집도 / 파일(s) 변경 요약
사이드바 스타일 조정
frontend/src/components/Sidebar.module.css
.homeSidebarMenu 너비를 200px264px로 변경
베팅 컴포넌트 — 동적 데이터 통합
frontend/src/components/stockgame/Betting.jsx
모의 데이터 제거, dailyBet/weeklyBet 비동기 호출로 전환; data/loading 상태 및 useEffect 추가; 로딩 처리 및 렌더 필드 변경 (data.round, previousClosePrice 등)
베팅 카드 스타일
frontend/src/components/stockgame/Betting.module.css, frontend/src/components/stockgame/BettingHistory.module.css
.daily-betting-card 높이 증가(170/130 → 200px), .daily-betting-cardgap: 25px 추가
베팅 이력 컴포넌트 재구성
frontend/src/components/stockgame/BettingHistory.jsx
모의 이력 제거, getDailyBetHistory/getWeeklyBetHistory 호출로 변경; data 상태, 로딩/빈상태/에러 처리, getPercentChange 추가; 페이지네이션과 렌더가 item.round.* 구조 사용
스톡게임 페이지 스타일
frontend/src/pages/StockGame.module.css
.stock-gamemargin-left: 50px 추가; .title, .tab, .typefont-style 관련 선언 제거; .daily-betting 선택자 변경
베팅 이력 유틸리티 추가
frontend/src/utils/bettingHistory.js
/api/user-bets/history에서 페칭하는 getDailyBetHistory()getWeeklyBetHistory() 비동기 함수 추가 (round.scope 필터링 포함)
베팅 정보 유틸리티 전환
frontend/src/utils/bettingInfo.js
mockDailyBet/mockWeeklyBet 정적 객체 제거; dailyBet() / weeklyBet() 비동기 함수로 대체하여 `/api/bet-rounds/DAILY
모의 데이터 파일 삭제
frontend/src/utils/dailyBettingHistory.js, frontend/src/utils/weeklyBettingHistory.js
정적 모의 데이터셋(dailyBettingHistory, weeklyBettingHistory) 전체 삭제

Sequence Diagram(s)

sequenceDiagram
    participant UI as UI 컴포넌트\n(Betting / BettingHistory)
    participant State as React State\n(data, loading)
    participant Util as Utils\n(dailyBet / bettingHistory)
    participant API as Backend API

    Note over UI,Util: 이전(모의 데이터)
    UI->>UI: 정적 mock 데이터로 즉시 렌더

    Note over UI,API: 변경된 흐름 (API 기반)
    UI->>State: setLoading(true)
    UI->>Util: dailyBet()/weeklyBet() 또는 getDailyBetHistory()/getWeeklyBetHistory()
    Util->>API: HTTP GET /api/bet-rounds/... or /api/user-bets/history
    API-->>Util: 데이터 응답 또는 에러
    Util-->>State: setData(...) / setLoading(false)
    State->>UI: 렌더 (item.round.*, previousClosePrice, settleClosePrice 등)
    alt 에러/빈 데이터
        UI->>UI: 빈 상태 또는 에러 메시지 표시
    end
Loading

Estimated code review effort

🎯 3 (중간) | ⏱️ ~25분

주의 깊게 검토할 파일/영역:

  • frontend/src/utils/bettingInfo.js / bettingHistory.js의 에러 처리 및 반환형(널/빈배열) 일관성
  • Betting.jsxBettingHistory.jsx의 useEffect 의존성 배열과 로딩/초기화 경계
  • 삭제된 mock 파일들을 참조하는 잔여 임포트/코드 여부
  • CSS 높이/간격 변경이 레이아웃에 미치는 영향(오버플로/정렬)

Possibly related PRs

Suggested reviewers

  • gxuoo

🐰 안녕, 모의 데이터야 — 안녕, 실시간 API여.
옆구리 넓어져 더 푸근한 사이드바,
데이터 오면 깡총깡총 춤출 준비 됐네.
로딩 지나면 숫자들이 반짝, 토끼는 박수. 🎰✨

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 변경 사항의 주요 내용을 명확하게 반영합니다. 베팅 페이지의 API 연동이라는 핵심 변경 사항을 정확하게 설명하고 있으며, Jira 이슈 추적 정보도 포함되어 있습니다.
✨ 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-164-FE-API-betting

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: 7

🧹 Nitpick comments (1)
frontend/src/components/stockgame/Betting.jsx (1)

13-24: 에러 상태 처리 추가 권장

현재 로딩 상태만 처리하고 있지만, API 호출 실패 시 사용자에게 피드백을 제공할 에러 상태 처리가 없습니다. bettingInfo.js에서 에러 발생 시 undefined를 반환하면 로딩 화면이 무한히 표시될 수 있습니다.

에러 상태를 추가하는 것을 권장합니다:

 const DailyBetting = ({ period }) => {
   const [isBetting, setIsBetting] = useState('none');
   const [data, setData] = useState(null);
+  const [error, setError] = useState(null);

   useEffect(() => {
     async function fetchData() {
+      setError(null);
       if (period === 'daily') {
         const res = await dailyBet();
-        setData(res);
+        if (res) {
+          setData(res);
+        } else {
+          setError('데이터를 불러오는데 실패했습니다.');
+        }
       } else {
         const res = await weeklyBet();
-        setData(res);
+        if (res) {
+          setData(res);
+        } else {
+          setError('데이터를 불러오는데 실패했습니다.');
+        }
       }
     }
     fetchData();
   }, [period]);

그리고 렌더링 부분에서:

   if (!data) return <div>Loading...</div>;
+  if (error) return <div>{error}</div>;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6fb55f and e113a7d.

📒 Files selected for processing (10)
  • frontend/src/components/Sidebar.module.css (1 hunks)
  • frontend/src/components/stockgame/Betting.jsx (3 hunks)
  • frontend/src/components/stockgame/Betting.module.css (1 hunks)
  • frontend/src/components/stockgame/BettingHistory.jsx (3 hunks)
  • frontend/src/components/stockgame/BettingHistory.module.css (1 hunks)
  • frontend/src/pages/StockGame.module.css (2 hunks)
  • frontend/src/utils/bettingHistory.js (1 hunks)
  • frontend/src/utils/bettingInfo.js (1 hunks)
  • frontend/src/utils/dailyBettingHistory.js (0 hunks)
  • frontend/src/utils/weeklyBettingHistory.js (0 hunks)
💤 Files with no reviewable changes (2)
  • frontend/src/utils/weeklyBettingHistory.js
  • frontend/src/utils/dailyBettingHistory.js
🧰 Additional context used
🧬 Code graph analysis (4)
frontend/src/utils/bettingHistory.js (3)
frontend/src/utils/bettingInfo.js (2)
  • res (5-5)
  • res (14-14)
frontend/src/components/stockgame/Betting.jsx (1)
  • data (11-11)
frontend/src/components/stockgame/BettingHistory.jsx (1)
  • data (12-12)
frontend/src/utils/bettingInfo.js (1)
frontend/src/utils/bettingHistory.js (1)
  • res (5-5)
frontend/src/components/stockgame/Betting.jsx (2)
frontend/src/utils/bettingInfo.js (6)
  • res (5-5)
  • res (14-14)
  • dailyBet (3-10)
  • dailyBet (3-10)
  • weeklyBet (12-19)
  • weeklyBet (12-19)
frontend/src/components/stockgame/StockInfoItem.jsx (1)
  • StockInfoItem (3-10)
frontend/src/components/stockgame/BettingHistory.jsx (2)
frontend/src/utils/bettingHistory.js (7)
  • data (13-13)
  • data (19-19)
  • res (5-5)
  • getDailyBetHistory (12-16)
  • getDailyBetHistory (12-16)
  • getWeeklyBetHistory (18-22)
  • getWeeklyBetHistory (18-22)
frontend/src/components/stockgame/StockInfoItem.jsx (1)
  • StockInfoItem (3-10)
🔇 Additional comments (9)
frontend/src/components/Sidebar.module.css (1)

1-13: 레이아웃 조정 확인 필요

사이드바 너비가 200px에서 264px로 증가했습니다. StockGame.module.css에서 추가된 margin-left: 50px와 함께 전체 레이아웃이 의도대로 작동하는지 확인이 필요합니다.

frontend/src/pages/StockGame.module.css (2)

1-8: LGTM!

사이드바 너비 변경에 맞춰 margin-left: 50px를 추가한 것은 적절합니다.


54-59: LGTM!

선택자를 .daily-betting span에서 .daily-betting > span으로 변경하여 직계 자식만 대상으로 지정한 것은 더 명확하고 안전한 스타일 적용 방식입니다.

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

1-14: LGTM!

카드 높이를 130px에서 200px로 증가시킨 것은 Betting.module.css의 변경 사항과 일관성을 유지하며, 더 많은 데이터를 표시할 수 있는 공간을 확보합니다.

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

1-14: LGTM!

카드 높이를 200px로 증가시키고 gap: 25px를 추가하여 콘텐츠 간격을 개선했습니다. BettingHistory.module.css의 변경 사항과 일관성을 유지합니다.

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

48-48: LGTM!

데이터가 로드될 때까지 로딩 상태를 표시하는 것은 좋은 사용자 경험을 제공합니다.

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

46-48: LGTM!

퍼센트 변화율을 계산하는 헬퍼 함수가 올바르게 구현되었습니다.


50-53: LGTM!

로딩 상태와 빈 데이터 상태를 모두 처리하여 좋은 사용자 경험을 제공합니다. 이는 Betting.jsx에서 누락된 에러 처리의 좋은 예시입니다.


16-27: 데이터 페칭 로직 확인

데이터 페칭 패턴은 올바르게 구현되었습니다. 다만 bettingHistory.js에서 betHitsory 함수명 오타가 수정되면 정상적으로 작동할 것입니다.

@@ -1,12 +1,27 @@
import styles from './Betting.module.css';
import icon1 from '../../assets/at_icon_1.png';
// import icon1 from '../../assets/at_icon_1.png';
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

주석 처리된 코드 제거 필요

주석 처리된 코드는 버전 관리 시스템에서 이력을 확인할 수 있으므로, 코드베이스를 깔끔하게 유지하기 위해 제거하는 것이 좋습니다.

다음 주석 처리된 코드를 제거하세요:

  • Line 2: // import icon1 from '../../assets/at_icon_1.png';
  • Lines 9-10: 주석 처리된 data 할당
  • Lines 61-66: 상승 베팅 정보 표시 부분
  • Lines 77-82: 하락 베팅 정보 표시 부분

Also applies to: 9-10, 61-66, 77-82

🤖 Prompt for AI Agents
frontend/src/components/stockgame/Betting.jsx around lines 2, 9-10, 61-66, and
77-82: remove the leftover commented-out code to keep the codebase clean —
specifically delete the commented import on line 2, the commented data
assignment on lines 9-10, the commented "up bet" display block on lines 61-66,
and the commented "down bet" display block on lines 77-82; ensure no functional
code is altered and run the component build/test to verify no references to
those comments remain.

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: 4

Caution

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

⚠️ Outside diff range comments (1)
frontend/src/components/stockgame/BettingHistory.jsx (1)

60-97: 중첩된 속성에 대한 null 안전성 검사가 누락되었습니다.

API가 불완전한 데이터를 반환하거나 data.roundnull/undefined인 경우 런타임 에러가 발생합니다.

옵셔널 체이닝을 사용하거나 데이터 유효성을 검증하세요:

방법 1: 옵셔널 체이닝 사용

-          <span className={styles['date']}>{data.round.title}</span>
+          <span className={styles['date']}>{data.round?.title || 'N/A'}</span>

방법 2: 렌더링 전 데이터 유효성 검증

       {currentData.map((data, index) => {
+        if (!data.round) return null;
         return (
           <div
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e113a7d and 016a4f2.

📒 Files selected for processing (3)
  • frontend/src/components/stockgame/BettingHistory.jsx (2 hunks)
  • frontend/src/utils/bettingHistory.js (1 hunks)
  • frontend/src/utils/bettingInfo.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/utils/bettingHistory.js
  • frontend/src/utils/bettingInfo.js
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/components/stockgame/BettingHistory.jsx (2)
frontend/src/utils/bettingHistory.js (7)
  • data (14-14)
  • data (20-20)
  • res (5-5)
  • getDailyBetHistory (13-17)
  • getDailyBetHistory (13-17)
  • getWeeklyBetHistory (19-23)
  • getWeeklyBetHistory (19-23)
frontend/src/components/stockgame/StockInfoItem.jsx (1)
  • StockInfoItem (3-10)
🔇 Additional comments (3)
frontend/src/components/stockgame/BettingHistory.jsx (3)

6-9: 임포트 구조가 적절합니다.

새로운 베팅 이력 유틸리티 함수들을 올바르게 임포트하고 있습니다.


29-32: 페이지 초기화 로직이 올바릅니다.

타입 변경 시 페이지를 1로 초기화하는 것은 적절한 UX 처리입니다.


102-108: 페이지네이션 구현이 적절합니다.

totalPagescurrentPage 상태 관리가 올바르게 구현되어 있습니다.

Comment on lines +46 to +48
const getPercentChange = (prev, next) => {
return (((next - prev) / prev) * 100).toFixed(2);
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

0으로 나누기 오류 가능성이 있습니다.

prev가 0인 경우 Infinity 또는 NaN이 반환되어 UI가 깨질 수 있습니다.

다음과 같이 가드를 추가하세요:

 const getPercentChange = (prev, next) => {
+  if (!prev || prev === 0) return '0.00';
   return (((next - prev) / prev) * 100).toFixed(2);
 };
📝 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.

Suggested change
const getPercentChange = (prev, next) => {
return (((next - prev) / prev) * 100).toFixed(2);
};
const getPercentChange = (prev, next) => {
if (!prev || prev === 0) return '0.00';
return (((next - prev) / prev) * 100).toFixed(2);
};
🤖 Prompt for AI Agents
In frontend/src/components/stockgame/BettingHistory.jsx around lines 46 to 48,
the getPercentChange function can divide by zero when prev is 0; add a guard at
the start that validates prev is a finite non-zero number and handle
zero/invalid cases by returning a safe value (e.g. a placeholder string like "—"
or "0.00" depending on UI expectations) instead of performing the division,
while keeping the existing toFixed(2) formatting for normal cases.

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

♻️ Duplicate comments (1)
frontend/src/components/stockgame/BettingHistory.jsx (1)

57-59: 0으로 나누기 오류가 여전히 존재합니다.

이전 리뷰에서 지적된 문제가 아직 수정되지 않았습니다. prev가 0이거나 유효하지 않은 값인 경우 Infinity 또는 NaN이 반환되어 UI가 손상될 수 있습니다.

다음과 같이 가드를 추가하세요:

 const getPercentChange = (prev, next) => {
+  if (!prev || prev === 0) return '0.00';
   return (((next - prev) / prev) * 100).toFixed(2);
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 016a4f2 and 29c4468.

📒 Files selected for processing (1)
  • frontend/src/components/stockgame/BettingHistory.jsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/components/stockgame/BettingHistory.jsx (2)
frontend/src/utils/bettingHistory.js (7)
  • data (14-14)
  • data (20-20)
  • res (5-5)
  • getDailyBetHistory (13-17)
  • getDailyBetHistory (13-17)
  • getWeeklyBetHistory (19-23)
  • getWeeklyBetHistory (19-23)
frontend/src/components/stockgame/StockInfoItem.jsx (1)
  • StockInfoItem (3-10)
🔇 Additional comments (1)
frontend/src/components/stockgame/BettingHistory.jsx (1)

99-104: 주석 처리된 코드 확인.

포인트 및 참가자 수 표시 코드가 주석 처리되어 있습니다. PR 설명에 따르면 백엔드 구현 후 추가 예정이라고 명시되어 있으나, 향후 재활성화 시점을 명확히 해두는 것이 좋습니다.

TODO 주석을 추가하여 의도를 명확히 하는 것을 권장합니다:

  {/* 베팅 결과 */}
  <div className={styles['bet-result']}>
-   {/* <div className={styles['bet-point']}>
+   {/* TODO: 백엔드 API 구현 후 재활성화
+       <div className={styles['bet-point']}>
      <img src={icon1} className={styles['icon']} />+
      <span>{item.points}P</span>
    </div>
    <div className={styles['divider']} />
    <span>{item.participants}명</span> */}

Comment on lines +18 to +38
useEffect(() => {
async function fetchData() {
setLoading(true);
setError(null);
try {
if (type === 'daily') {
const res = await getDailyBetHistory();
setData(res);
} else {
const res = await getWeeklyBetHistory();
setData(res);
}
} catch (err) {
setError(err.message || '데이터를 불러오는데 실패했습니다.');
setData([]);
} finally {
setLoading(false);
}
}
fetchData();
}, [type]);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

비동기 작업 정리 메커니즘이 누락되었습니다.

컴포넌트가 언마운트되는 동안 비동기 작업이 진행 중인 경우, 언마운트된 컴포넌트에서 상태 업데이트가 발생하여 메모리 누수 및 React 경고가 발생할 수 있습니다.

다음과 같이 cleanup 함수를 추가하세요:

  useEffect(() => {
+   let isMounted = true;
    async function fetchData() {
      setLoading(true);
      setError(null);
      try {
        if (type === 'daily') {
          const res = await getDailyBetHistory();
-         setData(res);
+         if (isMounted) setData(res);
        } else {
          const res = await getWeeklyBetHistory();
-         setData(res);
+         if (isMounted) setData(res);
        }
      } catch (err) {
-       setError(err.message || '데이터를 불러오는데 실패했습니다.');
-       setData([]);
+       if (isMounted) {
+         setError(err.message || '데이터를 불러오는데 실패했습니다.');
+         setData([]);
+       }
      } finally {
-       setLoading(false);
+       if (isMounted) setLoading(false);
      }
    }
    fetchData();
+   return () => {
+     isMounted = false;
+   };
  }, [type]);
🤖 Prompt for AI Agents
In frontend/src/components/stockgame/BettingHistory.jsx around lines 18 to 38,
the useEffect fetchData flow lacks a cleanup to prevent state updates after
unmount — add a cleanup that cancels or ignores the async work: create an
AbortController or an isMounted flag before calling fetchData, pass the signal
if using fetch-based helpers or check the flag after awaited calls, and in the
effect return a cleanup that either aborts the request or sets the flag to
false; before every setState (setLoading, setError, setData) verify the
controller is not aborted or isMounted is true so updates won’t run on an
unmounted component.

@DongEun02 DongEun02 merged commit a886920 into main Nov 14, 2025
1 check passed
@DongEun02 DongEun02 deleted the SISC1-164-FE-API-betting branch November 14, 2025 16:04
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