diff --git a/frontend/src/components/Header.module.css b/frontend/src/components/Header.module.css index c4b6c16c..226dd2e0 100644 --- a/frontend/src/components/Header.module.css +++ b/frontend/src/components/Header.module.css @@ -12,6 +12,7 @@ padding: 0 30px; gap: 30px; } + .brand { display: flex; align-items: center; @@ -37,10 +38,12 @@ border: none; cursor: pointer; padding: 0; + flex-shrink: 0; } .menuButton span { display: block; + width: 100%; height: 2px; background: white; border-radius: 2px; diff --git a/frontend/src/components/stockgame/Betting.jsx b/frontend/src/components/stockgame/Betting.jsx index 25fc2ec2..7b535d3d 100644 --- a/frontend/src/components/stockgame/Betting.jsx +++ b/frontend/src/components/stockgame/Betting.jsx @@ -1,47 +1,122 @@ import styles from './Betting.module.css'; -// import icon1 from '../../assets/at_icon_1.png'; +import icon1 from '../../assets/at_icon_1.png'; import StockInfoItem from './StockInfoItem'; import { useState, useEffect } from 'react'; import { dailyBet, weeklyBet } from '../../utils/bettingInfo'; +import { + getDailyBetHistory, + getWeeklyBetHistory, +} from '../../utils/bettingHistory'; +import { api } from '../../utils/axios'; -const DailyBetting = ({ period }) => { +const Betting = ({ period }) => { const [isBetting, setIsBetting] = useState('none'); - // const data = period === 'daily' ? mockDailyBet : mockWeeklyBet; - // const data = period === 'daily' ? dailyBet() : weeklyBet(); const [data, setData] = useState(null); + const [userBets, setUserBets] = useState(null); useEffect(() => { async function fetchData() { if (period === 'daily') { const res = await dailyBet(); setData(res); + const history = await getDailyBetHistory(); + setUserBets(history && history.length > 0 ? history[0] : null); } else { const res = await weeklyBet(); setData(res); + const history = await getWeeklyBetHistory(); + setUserBets(history && history.length > 0 ? history[0] : null); } } fetchData(); }, [period]); - const onClickUpBet = () => { + // userBets 또는 data가 바뀔 때 베팅 여부 체크 + useEffect(() => { + if (!data || !userBets) { + setIsBetting('none'); + return; + } + + if (data.betRoundId === userBets.betRoundId) { + userBets.option === 'RISE' ? setIsBetting('up') : setIsBetting('down'); + } else { + setIsBetting('none'); + } + }, [data, userBets]); + + const update = async () => { + const updatedData = + period === 'daily' ? await dailyBet() : await weeklyBet(); + setData(updatedData); + const history = + period === 'daily' + ? await getDailyBetHistory() + : await getWeeklyBetHistory(); + setUserBets(history && history.length > 0 ? history[0] : null); + }; + + const onClickUpBet = async () => { if (isBetting !== 'none') { alert('이미 베팅하셨습니다.'); } else if (confirm('상승에 베팅하시겠습니까?')) { - setIsBetting('up'); + try { + const res = await api.post('/api/user-bets', { + roundId: data.betRoundId, + option: 'RISE', + stakePoints: 0, + isFree: true, + }); + await update(); + alert('베팅이 완료되었습니다.'); + return res; + } catch (error) { + // 409 처리 + if (error.status === 409) { + alert('베팅 가능 시간이 아닙니다.'); + return; + } + alert('오류가 발생했습니다. 다시 시도해주세요.'); + return null; + } } }; - const onClickDownBet = () => { + const onClickDownBet = async () => { if (isBetting !== 'none') { alert('이미 베팅하셨습니다.'); } else if (confirm('하락에 베팅하시겠습니까?')) { - setIsBetting('down'); + try { + const res = await api.post('/api/user-bets', { + roundId: data.betRoundId, + option: 'FALL', + stakePoints: 0, + isFree: true, + }); + await update(); + alert('베팅이 완료되었습니다.'); + return res; + } catch (error) { + // 409 처리 + if (error.status === 409) { + alert('베팅 가능 시간이 아닙니다.'); + return; + } + alert('오류가 발생했습니다. 다시 시도해주세요.'); + return null; + } } }; - const onClickCancelBet = () => { + const onClickCancelBet = async () => { if (confirm('베팅을 취소하시겠습니까?')) { - setIsBetting('none'); + try { + await api.delete(`/api/user-bets/${userBets.userBetId}`); + await update(); + alert('베팅이 취소되었습니다.'); + } catch (error) { + alert(error.message); + } } }; @@ -58,12 +133,12 @@ const DailyBetting = ({ period }) => {
{/* 상승 베팅 */}
- {/*
+
- +{data.upperBet}P + +{data.upTotalPoints}P
- {data.upBetCount}명 */} + {data.upBetCount}명
{/* 하락 베팅 */}
- {/*
+
- -{data.lowerBet}P + -{data.downTotalPoints}P
- {data.downBetCount}명 */} + {data.downBetCount}명 - {item.round.title} + {item.roundTitle}
- - - + + +
{'->'} {getPercentChange( - item.round.previousClosePrice, - item.round.settleClosePrice + item.previousClosePrice, + item.settleClosePrice )} %
{/* 베팅 결과 */}
- {/*
+
+ - {item.points}P + {item.earnedPoints}P
- {item.participants}명 */} - {item.round.resultOption === 'RISE' ? ( + + {item.resultOption === 'RISE' + ? item.upBetCount + : item.downBetCount} + 명 + + {item.resultOption === 'RISE' ? ( ) : ( diff --git a/frontend/src/components/stockgame/BettingHistory.module.css b/frontend/src/components/stockgame/BettingHistory.module.css index 3a1279ec..91956398 100644 --- a/frontend/src/components/stockgame/BettingHistory.module.css +++ b/frontend/src/components/stockgame/BettingHistory.module.css @@ -129,5 +129,6 @@ .paginationContainer { display: flex; - margin-left: 230px; + /* margin-left: 230px; */ + justify-content: center; } diff --git a/frontend/src/utils/bettingHistory.js b/frontend/src/utils/bettingHistory.js index c4ab69a3..94f7bb11 100644 --- a/frontend/src/utils/bettingHistory.js +++ b/frontend/src/utils/bettingHistory.js @@ -3,6 +3,7 @@ import { api } from '../utils/axios.js'; const betHistory = async () => { try { const res = await api.get('/api/user-bets/history'); + // 백엔드에서 최신순으로 정렬된 데이터 반환 return res.data; } catch (error) { console.log(error.message); @@ -13,11 +14,11 @@ const betHistory = async () => { export const getDailyBetHistory = async () => { const data = await betHistory(); if (!data) return []; - return data.filter((item) => item.round.scope === 'DAILY'); + return data.filter((item) => item.roundTitle.includes('DAILY')); }; export const getWeeklyBetHistory = async () => { const data = await betHistory(); if (!data) return []; - return data.filter((item) => item.round.scope === 'WEEKLY'); + return data.filter((item) => item.roundTitle.includes('WEEKLY')); };