Skip to content

Commit

Permalink
Merge pull request #187 from 100-hours-a-week/feature/veronica
Browse files Browse the repository at this point in the history
Feat : 년도별 게임 화면
  • Loading branch information
Yeonsu00-12 authored Sep 11, 2024
2 parents fedd051 + 0496622 commit c5f0413
Show file tree
Hide file tree
Showing 23 changed files with 980 additions and 155 deletions.
40 changes: 40 additions & 0 deletions src/Component/Game/GameButtons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import info from "../../img/GameButton/infoImg.png";
import trade from "../../img/GameButton/tradeImg.png";
import pass from "../../img/GameButton/passImg.png";
import "./GameButtonsStyle.css";
import { useNavigate, useParams } from "react-router-dom";

interface GameButtonsProps {
openTradeModal: () => void;
}

const GameButtons = ({ openTradeModal }: GameButtonsProps) => {
const nav = useNavigate();
const { year } = useParams<{ year: string }>();

// 정보 거래소로 이동
const goToInfoPage = () => {
if (year) {
nav(`/game/info/${year}`);
}
};

return (
<div className="GameButtonsWrapper">
<div className="GameButton" onClick={goToInfoPage}>
<img src={info}></img>
<span>정보거래소</span>
</div>
<div className="GameButton" onClick={openTradeModal}>
<img src={trade}></img>
<span>거래하기</span>
</div>
<div className="GameButton">
<img src={pass}></img>
<span>넘어가기</span>
</div>
</div>
);
};

export default GameButtons;
46 changes: 46 additions & 0 deletions src/Component/Game/GameButtonsStyle.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.GameButtonsWrapper {
display: flex;
align-items: center;
justify-content: center;
gap: 30px;
margin-top: 30px;
}

.GameButton {
width: 75px;
height: 80px;
background-color: #615efc;
display: flex;
flex-direction: column;
border-radius: 20px;
border: 4px solid rgb(255, 255, 255);
align-items: center;
justify-content: center;
position: relative;
transition: box-shadow 0.3s ease;
transform: 1s ease;
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.6);
cursor: pointer;
}

.GameButton img {
width: 30px;
margin-top: -20px;
}

.GameButton span {
position: absolute;
bottom: 7px;
color: white;
font-size: 12px;
}

.GameButton:active {
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.4); /* 눌렀을 때 그림자가 작아짐 */
transform: translateY(4px); /* 버튼이 살짝 눌리는 효과 */
}

/* 클릭 후 원래 크기로 돌아오는 애니메이션 */
.GameButton {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
22 changes: 11 additions & 11 deletions src/Component/Game/GameHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ import { Colors } from "../../Styles/Colors";
import { GameHeaderProp } from "../../constants/interface";

const Container = styled.div`
width: 100%;
height: 60px;
background-color: ${Colors.main};
color: white;
font-family: "SCDream6";
font-size: x-large;
text-align: center;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
padding-top: 15px;
width: 100%;
height: 60px;
background-color: ${Colors.main};
color: white;
font-family: "SCDream6";
font-size: x-large;
text-align: center;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
padding-top: 15px;
`;

const GameHeader: React.FC<GameHeaderProp> = ({ text }) => {
return <Container>{text}</Container>;
return <Container>{text}</Container>;
};

export default GameHeader;
65 changes: 65 additions & 0 deletions src/Component/Game/GameMoney.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import styled from "styled-components";

const GameMoneyContainer = styled.div`
width: 85%;
height: 150px;
border-radius: 20px;
box-shadow: 3px 3px 3px rgb(213, 213, 213);
padding: 20px 40px;
position: relative;
margin-top: 20px;
margin-bottom: 20px;
`;

const GameMoneyTitle = styled.div`
margin-bottom: 30px;
`;

const GameMoneyBalance = styled.div`
display: flex;
margin: 15px 0;
flex-direction: row;
`;

const BalanceDetailButton = styled.div`
position: absolute;
bottom: 20px;
right: 20px;
`;

const BalanceTitle = styled.div`
color: #6c6c6c;
width: 110px;
`;

const Button = styled.button`
width: 78px;
height: 46px;
border-radius: 50px;
border: none;
background-color: #f1f1f1;
cursor: pointer;
`;

const GameMoney = () => {
return (
<GameMoneyContainer>
<GameMoneyTitle>
<strong>루시는왜안돼요</strong> 님의 계좌잔고 💰
</GameMoneyTitle>
<GameMoneyBalance>
<BalanceTitle>총 평가금액</BalanceTitle>
<div className="BalanceValue">0</div>
</GameMoneyBalance>
<GameMoneyBalance>
<BalanceTitle>작년 대비</BalanceTitle>
<div className="BalanceValue">0 (0%)</div>
</GameMoneyBalance>
<BalanceDetailButton>
<Button>더보기</Button>
</BalanceDetailButton>
</GameMoneyContainer>
);
};

export default GameMoney;
165 changes: 165 additions & 0 deletions src/Component/Game/GameTradeSwipe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { useEffect, useState } from "react";
import "./GameTradeSwipeStyle.css";
import TradeChoice from "./TradeChoice";
import TradeConfirmModal from "./TradeConfirmModal"; // 모달 컴포넌트 불러오기
import axios from "axios";
import swal from "sweetalert";

interface GameTradeSwipeProps {
onClose: () => void;
isVisible: boolean;
year: string;
}

const GameTradeSwipe = ({ onClose, isVisible, year }: GameTradeSwipeProps) => {
const [show, setShow] = useState(isVisible);
const [selectedStock, setSelectedStock] = useState("A뷰티");
const [quantity, setQuantity] = useState(0);
const [acting, setActing] = useState<"BUY" | "SELL">();
const [isModalOpen, setIsModalOpen] = useState(false); // 모달 상태 추가

const stockOptions = ["A뷰티", "B전기", "C전자", "D건설"];

useEffect(() => {
setShow(isVisible);
}, [isVisible]);

// 종목 선택 핸들러
const handleStockChange = (direction: "left" | "right") => {
const currentIndex = stockOptions.indexOf(selectedStock);

if (direction === "left") {
const newIndex =
(currentIndex - 1 + stockOptions.length) % stockOptions.length;
setSelectedStock(stockOptions[newIndex]);
} else {
const newIndex = (currentIndex + 1) % stockOptions.length;
setSelectedStock(stockOptions[newIndex]);
}
};

// 수량 선택 핸들러
const handleQuantityChange = (direction: "left" | "right") => {
if (direction === "left" && quantity > 0) {
setQuantity(quantity - 1);
} else if (direction === "right") {
setQuantity(quantity + 1);
}
};

// 모달에서 확인 버튼 클릭 시 거래 처리
const handleTradeConfirm = () => {
// 데이터 전송하기
const handleTrade = async () => {
const data = {
year: year,
gameId: 0,
stockId: 0, // stockId로 stock 전달해야함. 수정 필요
stock: selectedStock,
quantity: quantity,
acting: acting, // 팔기 : SELL, 사기 : BUY
};

// 서버로 데이터 전송
// try {
// const res = await axios.post(
// `${process.env.REACT_APP_API_URL}/v1/game/stock`,
// {
// withCredentials: true,
// }
// );
// console.log(res);

// if (res.status === 200) {
// swal({
// title: "거래 성공",
// icon: "success",
// }).then(() => {
// window.location.reload();
// });
// }
// } catch (error: any) {
// console.error(error);
// }
swal({
title: "거래 성공",
icon: "success",
}).then(() => {
handleClose();
});

console.log("선택한 년도 : ", year);
console.log("선택한 종목 : ", selectedStock);
console.log("선택한 수량 : ", quantity);
console.log("선택한 acting : ", acting);
};
handleTrade();
setIsModalOpen(false); // 모달 닫기
};

// 모달 열기
const openTradeConfirmModal = (action: "BUY" | "SELL") => {
setActing(action); // 거래 종류 설정 (구매 or 판매)
setIsModalOpen(true); // 모달 열기
};

// 모달 닫기 핸들러
const handleClose = () => {
setShow(false);
setTimeout(() => {
onClose();
}, 700);
};

return (
<div className="GameTradeSwipe">
<div
className={`swipeModal ${show ? "open" : "closed"}`}
style={{ width: "90%", position: "absolute", bottom: "0" }}
>
<div className="swipeContainer">
<div style={{ display: "flex", justifyContent: "center" }}>
<button onClick={handleClose}></button>
</div>
<span>주식 거래하기</span>
<TradeChoice
title="종목"
choiceLeft="←"
choiceRight="→"
selectedOption={selectedStock}
onLeftClick={() => handleStockChange("left")}
onRightClick={() => handleStockChange("right")}
/>
<TradeChoice
title="수량"
choiceLeft="-"
choiceRight="+"
selectedOption={quantity.toString()}
onLeftClick={() => handleQuantityChange("left")}
onRightClick={() => handleQuantityChange("right")}
/>
<div className="trade-button">
<button onClick={() => openTradeConfirmModal("SELL")}>
팔기
</button>
<button onClick={() => openTradeConfirmModal("BUY")}>
사기
</button>
</div>
</div>
</div>

{/* 거래 확인 모달 */}
<TradeConfirmModal
isOpen={isModalOpen}
onConfirm={handleTradeConfirm}
onRequestClose={() => setIsModalOpen(false)}
stock={selectedStock}
quantity={quantity}
acting={acting!} // acting 값 전달 (BUY or SELL)
/>
</div>
);
};

export default GameTradeSwipe;
Loading

0 comments on commit c5f0413

Please sign in to comment.