Skip to content
3 changes: 3 additions & 0 deletions frontend/src/components/Header.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
padding: 0 30px;
gap: 30px;
}

.brand {
display: flex;
align-items: center;
Expand All @@ -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;
Expand Down
109 changes: 92 additions & 17 deletions frontend/src/components/stockgame/Betting.jsx
Original file line number Diff line number Diff line change
@@ -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);
}
}
};

Expand All @@ -58,12 +133,12 @@ const DailyBetting = ({ period }) => {
<div className={styles['bet-info']}>
{/* 상승 베팅 */}
<div className={styles['upper-bet']}>
{/* <div className={styles['bet-point']}>
<div className={styles['bet-point']}>
<img src={icon1} className={styles['icon']} />
<span>+{data.upperBet}P</span>
<span>+{data.upTotalPoints}P</span>
</div>
<div className={styles['divider']} />
<span>{data.upBetCount}명</span> */}
<span>{data.upBetCount}명</span>
<button
className={`${styles['up-button']} ${isBetting === 'up' && styles.upActive}`}
onClick={onClickUpBet}
Expand All @@ -74,12 +149,12 @@ const DailyBetting = ({ period }) => {
</div>
{/* 하락 베팅 */}
<div className={styles['lower-bet']}>
{/* <div className={styles['bet-point']}>
<div className={styles['bet-point']}>
<img src={icon1} className={styles['icon']} />
<span>-{data.lowerBet}P</span>
<span>-{data.downTotalPoints}P</span>
</div>
<div className={styles['divider']} />
<span>{data.downBetCount}명</span> */}
<span>{data.downBetCount}명</span>
<button
className={`${styles['down-button']} ${isBetting === 'down' && styles.downActive}`}
onClick={onClickDownBet}
Expand All @@ -101,4 +176,4 @@ const DailyBetting = ({ period }) => {
);
};

export default DailyBetting;
export default Betting;
36 changes: 19 additions & 17 deletions frontend/src/components/stockgame/BettingHistory.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import styles from './BettingHistory.module.css';
// import icon1 from '../../assets/at_icon_1.png';
import icon1 from '../../assets/at_icon_1.png';
import StockInfoItem from './StockInfoItem';
import Pagination from './Pagination';
import { useState, useEffect } from 'react';
Expand Down Expand Up @@ -69,40 +69,42 @@ const BettingHistory = ({ type }) => {
{currentData.map((item, index) => (
<div
key={index}
className={`${styles['daily-betting-card']} ${item.collect ? styles['correct-card'] : styles['incorrect-card']}`}
className={`${styles['daily-betting-card']} ${item.correct ? styles['correct-card'] : styles['incorrect-card']}`}
>
<button
className={`${styles['result-icon']} ${item.collect ? styles.correct : styles.incorrect}`}
className={`${styles['result-icon']} ${item.correct ? styles.correct : styles.incorrect}`}
>
{item.collect ? 'v' : 'x'}
{item.correct ? 'v' : 'x'}
</button>
<span className={styles['date']}>{item.round.title}</span>
<span className={styles['date']}>{item.roundTitle}</span>
<div className={styles['stock-info']}>
<StockInfoItem label="종목" value={item.round.symbol} />
<StockInfoItem
label="다음 날 종가"
value={item.round.settleClosePrice}
/>
<StockInfoItem label="종가" value={item.round.previousClosePrice} />
<StockInfoItem label="종목" value={item.symbol} />
<StockInfoItem label="다음 날 종가" value={item.settleClosePrice} />
<StockInfoItem label="종가" value={item.previousClosePrice} />
<div className={styles['stock-change']}>
<span className={styles['change-value']}>{'->'}</span>
<span className={styles['change-value']}>
{getPercentChange(
item.round.previousClosePrice,
item.round.settleClosePrice
item.previousClosePrice,
item.settleClosePrice
)}
%
</span>
</div>
{/* 베팅 결과 */}
<div className={styles['bet-result']}>
{/* <div className={styles['bet-point']}>
<div className={styles['bet-point']}>
<img src={icon1} className={styles['icon']} />+
<span>{item.points}P</span>
<span>{item.earnedPoints}P</span>
</div>
<div className={styles['divider']} />
<span>{item.participants}명</span> */}
{item.round.resultOption === 'RISE' ? (
<span>
{item.resultOption === 'RISE'
? item.upBetCount
: item.downBetCount}
</span>
{item.resultOption === 'RISE' ? (
<button className={styles['up-button']}>상승 ↑</button>
) : (
<button className={styles['down-button']}>하락 ↓</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,6 @@

.paginationContainer {
display: flex;
margin-left: 230px;
/* margin-left: 230px; */
justify-content: center;
}
5 changes: 3 additions & 2 deletions frontend/src/utils/bettingHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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'));
};