From 6f681e8722ecaee40ae67246e0f17c8147201f40 Mon Sep 17 00:00:00 2001 From: lucy726j Date: Thu, 10 Oct 2024 17:01:21 +0900 Subject: [PATCH] =?UTF-8?q?Fix=20:=20=EC=A2=85=EB=AA=A9=20=EC=95=88?= =?UTF-8?q?=EB=B6=88=EB=9F=AC=EC=99=80=EC=A7=80=EB=8A=94=20=EC=9D=B4?= =?UTF-8?q?=EC=8A=88=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Component/Dropdown/gameDropdown.tsx | 7 +- src/Component/Game/StocksTable.tsx | 122 ++--- src/Component/SearchBar/SearchBar.tsx | 143 +++--- src/Game/Main/gameStart.tsx | 6 +- src/Pages/game/playPage.tsx | 566 ++++++++++++++++-------- src/store/stockContext.tsx | 2 +- 6 files changed, 533 insertions(+), 313 deletions(-) diff --git a/src/Component/Dropdown/gameDropdown.tsx b/src/Component/Dropdown/gameDropdown.tsx index 751f2ed..db8a28a 100644 --- a/src/Component/Dropdown/gameDropdown.tsx +++ b/src/Component/Dropdown/gameDropdown.tsx @@ -1,8 +1,6 @@ import { Variants, motion } from "framer-motion"; import { useState } from "react"; -import { Colors } from "../../Styles/Colors"; -import { StocksStore, useStock } from "../../store/stockContext"; -import styled from "styled-components"; +import { useStock } from "../../store/stockContext"; import { itemVariants, dropdownVariants, @@ -29,7 +27,8 @@ interface Stock { const StockItem: React.FC = ({ onSelectStock }) => { const [isOpen, setIsOpen] = useState(false); const [selectedStock, setSelectedStock] = useState(null); - const { stockData, setStockData } = StocksStore(); + // const { stockData, setStockData } = StocksStore(); + const { stockData, setStockData } = useStock(); const { purchaseHints, setPurchaseHints } = useHintStore(); const toggleDropdown = () => { diff --git a/src/Component/Game/StocksTable.tsx b/src/Component/Game/StocksTable.tsx index e390477..9cfe34f 100644 --- a/src/Component/Game/StocksTable.tsx +++ b/src/Component/Game/StocksTable.tsx @@ -5,65 +5,65 @@ import "./StocksTableStyle.css"; import styled, { keyframes } from "styled-components"; const StocksTable: React.FC = ({ stocks, year }) => { - const header = ["번호", "종목", "전년", "올해", "등락"]; + const header = ["번호", "종목", "전년", "올해", "등락"]; + console.log(stocks, year); - return ( -
- - - - {header.map((item, index) => ( - - ))} - - - - {stocks && - stocks.map((stock, index) => ( - - - - - - - - ))} - -
{item}
{index + 1}{stock.name} - {formatPriceWithYear(stock.prev, year)} - 0 - ? "red" - : stock.changeRate < 0 - ? "blue" - : "black", - textAlign: "right", - }} - > - {formatPriceWithYear(stock.current, year)} - 0 - ? "red" - : stock.changeRate < 0 - ? "blue" - : "black", - }} - > - {formatChangeRate(stock.changeRate)} -
-
- ); + return ( +
+ + + + {header.map((item, index) => ( + + ))} + + + + {stocks && + stocks.map((stock, index) => ( + + + + + + + + ))} + +
{item}
{index + 1}{stock.name} + {formatPriceWithYear(stock.prev, year)} + 0 + ? "red" + : stock.changeRate < 0 + ? "blue" + : "black", + textAlign: "right", + }} + > + {formatPriceWithYear(stock.current, year)} + 0 + ? "red" + : stock.changeRate < 0 + ? "blue" + : "black", + }} + > + {formatChangeRate(stock.changeRate)} +
+
+ ); }; // 부드럽게 나타나는 애니메이션 정의 @@ -79,9 +79,9 @@ const fadeIn = keyframes` `; const TableRow = styled.tr<{ index: number }>` - animation: ${fadeIn} 0.5s ease-out forwards; - animation-delay: ${({ index }) => index * 0.1}s; - opacity: 0; + animation: ${fadeIn} 0.5s ease-out forwards; + animation-delay: ${({ index }) => index * 0.1}s; + opacity: 0; `; export default StocksTable; diff --git a/src/Component/SearchBar/SearchBar.tsx b/src/Component/SearchBar/SearchBar.tsx index e394d9c..87c92cb 100644 --- a/src/Component/SearchBar/SearchBar.tsx +++ b/src/Component/SearchBar/SearchBar.tsx @@ -19,75 +19,86 @@ const SearchBar: React.FC = () => { }; // debounce 함수 : 1000ms 디바운스를 걸고, 마지막 keyword로만 api 요청 - const handelDebounce = useCallback( - debounce((input: string) => { - if (input.trim() === "") { - setList([]); - return; - } - axios - .get( - `${process.env.REACT_APP_API_URL}/v1/stocks/search?query=${input}`, - { - withCredentials: true, - headers: { - "Content-Type": "application/json", - }, - } - ) - .then((res) => { - if (res.status === 200) { - const result = res.data; - setList(result); - } else if (res.status === 401) { - nav("/login"); - } - }) - .catch((error) => {}); - }, 300), - [] - ); + // const handelDebounce = useCallback( + // debounce((input: string) => { + // if (input.trim() === "") { + // setList([]); + // return; + // } + // axios + // .get( + // `${process.env.REACT_APP_API_URL}/v1/stocks/search?query=${input}`, + // { + // withCredentials: true, + // headers: { + // "Content-Type": "application/json", + // }, + // } + // ) + // .then((res) => { + // if (res.status === 200) { + // const result = res.data; + // setList(result); + // } else if (res.status === 401) { + // nav("/login"); + // } + // }) + // .catch((error) => {}); + // }, 300), + // [] + // ); + + // // input 태그에 입력되는 값으로 keyword 업데이트, debounce 함수에 keyword 전달 + // const handleSearch = useCallback( + // (e: React.ChangeEvent) => { + // let input = e.target.value; + // const regExp = /[ \{\}\[\]\/?.,;:|\)*~`!^\-_+┼<>@\#$%&\'\"\\\(\=]/gi; + // if (regExp.test(input)) { + // input = input.replace(regExp, ""); + // } + // setKeyword(input); + // handelDebounce(input); + // }, + // [handelDebounce] + // ); + + // // # Debounce 적용 전 ver // input 태그에 입력되는 값으로 keyword 업데이트, debounce 함수에 keyword 전달 - const handleSearch = useCallback( - (e: React.ChangeEvent) => { - let input = e.target.value; - const regExp = /[ \{\}\[\]\/?.,;:|\)*~`!^\-_+┼<>@\#$%&\'\"\\\(\=]/gi; - if (regExp.test(input)) { - input = input.replace(regExp, ""); - } - setKeyword(input); - handelDebounce(input); - }, - [handelDebounce] - ); + const handleSearch = (e: React.ChangeEvent) => { + let input = e.target.value; + const regExp = /[ \{\}\[\]\/?.,;:|\)*~`!^\-_+┼<>@\#$%&\'\"\\\(\=]/gi; + if (regExp.test(input)) { + input = input.replace(regExp, ""); + } + setKeyword(input); + }; - // # Debounce 적용 전 ver - // useEffect(() => { - // if (keyword.trim() === "") { - // setList([]); - // return; - // } - // axios - // .get( - // `${process.env.REACT_APP_API_URL}/v1/stocks/search?query=${keyword}`, - // { - // withCredentials: true, - // headers: { - // "Content-Type": "application/json", - // }, - // } - // ) - // .then((res) => { - // if (res.status === 200) { - // const result = res.data; - // setList(result); - // } else if (res.status === 401) { - // nav("/login"); - // } - // }) - // .catch((error) => {}); - // }, [keyword]); + useEffect(() => { + if (keyword.trim() === "") { + setList([]); + return; + } + axios + .get( + `${process.env.REACT_APP_API_URL}/v1/stocks/search?query=${keyword}`, + { + withCredentials: true, + headers: { + "Content-Type": "application/json", + }, + } + ) + .then((res) => { + if (res.status === 200) { + const result = res.data; + setList(result); + } else if (res.status === 401) { + nav("/login"); + } + }) + .catch((error) => {}); + }, [keyword]); const handleSelectStock = (event: StockDataProps) => { nav(`/stocks/${event.code}`); diff --git a/src/Game/Main/gameStart.tsx b/src/Game/Main/gameStart.tsx index b1c9555..57dcb42 100644 --- a/src/Game/Main/gameStart.tsx +++ b/src/Game/Main/gameStart.tsx @@ -9,11 +9,13 @@ import axios from "axios"; import swal from "sweetalert"; import { ButtonDiv, GameTitle } from "./styleMain"; import Loading from "../Loading/loading"; -import { StocksStore } from "../../store/stockContext"; +// import { StocksStore } from "../../store/stockContext"; +import { useStock } from "../../store/stockContext"; import audioFile from "../../audio/Lucy_skrrr.m4a"; const GameMain: React.FC = () => { - const { setStockData } = StocksStore(); + // const { setStockData } = StocksStore(); + const { setStockData } = useStock(); const [isLoadingFinished, setIsLoadingFinished] = useState(false); // skip 로딩 const [loading, setLoading] = useState(false); // axios 요청 로딩 const [isFlying, setIsFlying] = useState(false); diff --git a/src/Pages/game/playPage.tsx b/src/Pages/game/playPage.tsx index 4dc5d58..a73c139 100644 --- a/src/Pages/game/playPage.tsx +++ b/src/Pages/game/playPage.tsx @@ -1,3 +1,214 @@ +// import { useNavigate, useParams } from "react-router-dom"; +// import GameButtons from "../../Component/Game/GameButtons"; +// import GameHeader from "../../Component/Game/GameHeader"; +// import GameMoney from "../../Component/Game/GameMoney"; +// import StocksTable from "../../Component/Game/StocksTable"; +// import styled from "styled-components"; +// import GameTradeSwipe from "../../Component/Game/GameTradeSwipe"; +// import { useState } from "react"; +// import PassConfirmModal from "../../Component/Game/PassConfirmModal"; +// import axios from "axios"; +// import "./gameStyle.css"; +// import HappyNewYearModal from "./HappyNewYearModal"; +// import { useStock } from "../../store/stockContext"; +// import { usePortfolioStore } from "../../store/usePortfolioStore"; +// import { useGameStore } from "../../store/useGameStore"; +// import ProgressBar from "../../Game/Loading/progressBar"; +// import { GoAlert } from "react-icons/go"; +// import { Colors } from "../../Styles/Colors"; +// import Button from "../../Component/Button/button"; +// import { useHintStore } from "../../store/hintStore"; + +// const Container = styled.div` +// display: flex; +// flex-direction: column; +// justify-content: center; +// align-items: center; +// text-align: center; +// `; + +// const PlayPage = () => { +// const { year } = useParams<{ year?: string }>(); +// const { stockData, setStockData } = useStock(); +// const nav = useNavigate(); +// const yearValue = year || "2014"; +// // 페이지 유효성 검사를 위한 변수 +// const yearNumber = parseInt(yearValue, 10); +// const [isTradeModalVisible, setIsTradeModalVisible] = useState(false); +// const [isPassModalVisible, setIsPassModalVisible] = useState(false); +// const [isHappyNewYearModal, setIsHappyNewYearModal] = useState(false); +// const [budget, setBudget] = useState(0); +// const [, setLoading] = useState(false); + +// const { check, setCheck } = usePortfolioStore((state) => ({ +// check: state.check, +// setCheck: state.setCheck, +// })); + +// const { checkYear, setCheckGameDone } = useGameStore((state) => ({ +// checkYear: state.checkYear, +// setCheckGameDone: state.setCheckGameDone, +// })); + +// const startYear = 2014; +// const lastYear = 2023; + +// // 년도 진행률 표시 +// const calculateProgress = () => { +// return ( +// ((parseInt(yearValue, 10) - startYear) / (lastYear - startYear)) * +// 100 +// ); +// }; + +// const [progress, setProgress] = useState(calculateProgress); + +// // 거래하기 모달 핸들러 +// const openTradeModal = () => { +// setIsTradeModalVisible(true); +// }; + +// const closeTradeModal = () => { +// setIsTradeModalVisible(false); +// }; + +// // 넘어가기 모달 핸들러 +// const openPassModal = () => { +// setIsPassModalVisible(true); +// }; + +// const closePassModal = () => { +// setIsPassModalVisible(false); +// }; + +// // 넘어가기 버튼 누르면 중간결과 호출 +// const handleConfirmPass = async () => { +// try { +// setLoading(true); +// setIsHappyNewYearModal(true); +// setIsPassModalVisible(false); + +// if (year === "2023") { +// setCheckGameDone(true); +// nav("/game/result/total"); +// } else { +// const response = await axios.get( +// `${process.env.REACT_APP_API_URL}/v1/game/interim`, +// { +// withCredentials: true, +// headers: { +// "Content-Type": "application/json", +// }, +// } +// ); +// if (response.status === 200) { +// if ( +// (parseInt(yearValue, 10) + 1).toString() === +// response.data.year.toString() +// ) { +// const updatedStockList = response.data.stockList; +// setStockData(updatedStockList); +// } + +// // API 완료 후 모달 닫고 페이지 이동 +// setIsHappyNewYearModal(false); +// const nextYear = (parseInt(yearValue, 10) + 1).toString(); +// nav(`/game/play/${nextYear}`); +// setCheck(!check); +// setProgress( +// ((parseInt(nextYear, 10) - startYear) / +// (lastYear - startYear)) * +// 100 +// ); +// // 로컬 스토리지에서 삭제 +// localStorage.removeItem("hint-storage"); +// // 주스탠드 스토어 상태 초기화 +// useHintStore.getState().resetPurchaseHints(); +// } +// } +// } catch (error) { +// console.error(error); +// } finally { +// setLoading(false); +// closePassModal(); +// } +// }; + +// return ( +// <> +// {yearNumber !== checkYear ? ( +//
+// +//

+// 정상적인 접근 경로가 아닙니다 +//

+//
+// ) : ( +// +// + +//
+// +//
+// +// +// +// +// +// +//
+// )} +// +// ); +// }; + +// export default PlayPage; + import { useNavigate, useParams } from "react-router-dom"; import GameButtons from "../../Component/Game/GameButtons"; import GameHeader from "../../Component/Game/GameHeader"; @@ -20,191 +231,188 @@ import Button from "../../Component/Button/button"; import { useHintStore } from "../../store/hintStore"; const Container = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - text-align: center; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; `; const PlayPage = () => { - const { year } = useParams<{ year?: string }>(); - const { stockData, setStockData } = useStock(); - const nav = useNavigate(); - const yearValue = year || "2014"; - // 페이지 유효성 검사를 위한 변수 - const yearNumber = parseInt(yearValue, 10); - const [isTradeModalVisible, setIsTradeModalVisible] = useState(false); - const [isPassModalVisible, setIsPassModalVisible] = useState(false); - const [isHappyNewYearModal, setIsHappyNewYearModal] = useState(false); - const [budget, setBudget] = useState(0); - const [, setLoading] = useState(false); - - const { check, setCheck } = usePortfolioStore((state) => ({ - check: state.check, - setCheck: state.setCheck, - })); - - const { checkYear, setCheckGameDone } = useGameStore((state) => ({ - checkYear: state.checkYear, - setCheckGameDone: state.setCheckGameDone, - })); - - const startYear = 2014; - const lastYear = 2023; - - // 년도 진행률 표시 - const calculateProgress = () => { - return ( - ((parseInt(yearValue, 10) - startYear) / (lastYear - startYear)) * - 100 - ); - }; - - const [progress, setProgress] = useState(calculateProgress); - - // 거래하기 모달 핸들러 - const openTradeModal = () => { - setIsTradeModalVisible(true); - }; - - const closeTradeModal = () => { - setIsTradeModalVisible(false); - }; - - // 넘어가기 모달 핸들러 - const openPassModal = () => { - setIsPassModalVisible(true); - }; - - const closePassModal = () => { - setIsPassModalVisible(false); - }; - - // 넘어가기 버튼 누르면 중간결과 호출 - const handleConfirmPass = async () => { - try { - setLoading(true); - setIsHappyNewYearModal(true); - setIsPassModalVisible(false); - - if (year === "2023") { - setCheckGameDone(true); - nav("/game/result/total"); - } else { - const response = await axios.get( - `${process.env.REACT_APP_API_URL}/v1/game/interim`, - { - withCredentials: true, - headers: { - "Content-Type": "application/json", - }, - } - ); - if (response.status === 200) { - if ( - (parseInt(yearValue, 10) + 1).toString() === - response.data.year.toString() - ) { - const updatedStockList = response.data.stockList; - setStockData(updatedStockList); - } - - // API 완료 후 모달 닫고 페이지 이동 - setIsHappyNewYearModal(false); - const nextYear = (parseInt(yearValue, 10) + 1).toString(); - nav(`/game/play/${nextYear}`); - setCheck(!check); - setProgress( - ((parseInt(nextYear, 10) - startYear) / - (lastYear - startYear)) * - 100 - ); - // 로컬 스토리지에서 삭제 - localStorage.removeItem("hint-storage"); - // 주스탠드 스토어 상태 초기화 - useHintStore.getState().resetPurchaseHints(); - } - } - } catch (error) { - console.error(error); - } finally { - setLoading(false); - closePassModal(); - } - }; + const { year } = useParams<{ year?: string }>(); + const { stockData, setStockData } = useStock(); + console.log("스톡데이터",stockData); + const nav = useNavigate(); + const yearValue = year || "2014"; + // 페이지 유효성 검사를 위한 변수 + const yearNumber = parseInt(yearValue, 10); + const [isTradeModalVisible, setIsTradeModalVisible] = useState(false); + const [isPassModalVisible, setIsPassModalVisible] = useState(false); + const [isHappyNewYearModal, setIsHappyNewYearModal] = useState(false); + const [budget, setBudget] = useState(0); + const [, setLoading] = useState(false); + + const { check, setCheck } = usePortfolioStore((state) => ({ + check: state.check, + setCheck: state.setCheck, + })); + + const { checkYear, setCheckGameDone } = useGameStore((state) => ({ + checkYear: state.checkYear, + setCheckGameDone: state.setCheckGameDone, + })); + + const startYear = 2014; + const lastYear = 2023; + // 년도 진행률 표시 + const calculateProgress = () => { return ( - <> - {yearNumber !== checkYear ? ( -
- -

- 정상적인 접근 경로가 아닙니다 -

-
- ) : ( - - - -
- -
- - - - - - -
- )} - + ((parseInt(yearValue, 10) - startYear) / (lastYear - startYear)) * 100 ); + }; + + const [progress, setProgress] = useState(calculateProgress); + + // 거래하기 모달 핸들러 + const openTradeModal = () => { + setIsTradeModalVisible(true); + }; + + const closeTradeModal = () => { + setIsTradeModalVisible(false); + }; + + // 넘어가기 모달 핸들러 + const openPassModal = () => { + setIsPassModalVisible(true); + }; + + const closePassModal = () => { + setIsPassModalVisible(false); + }; + + // 넘어가기 버튼 누르면 중간결과 호출 + const handleConfirmPass = async () => { + try { + setLoading(true); + setIsHappyNewYearModal(true); + setIsPassModalVisible(false); + + if (year === "2023") { + setCheckGameDone(true); + nav("/game/result/total"); + } else { + const response = await axios.get( + `${process.env.REACT_APP_API_URL}/v1/game/interim`, + { + withCredentials: true, + headers: { + "Content-Type": "application/json", + }, + } + ); + if (response.status === 200) { + if ( + (parseInt(yearValue, 10) + 1).toString() === + response.data.year.toString() + ) { + const updatedStockList = response.data.stockList; + setStockData(updatedStockList); + } + + // API 완료 후 모달 닫고 페이지 이동 + setIsHappyNewYearModal(false); + const nextYear = (parseInt(yearValue, 10) + 1).toString(); + nav(`/game/play/${nextYear}`); + setCheck(!check); + setProgress( + ((parseInt(nextYear, 10) - startYear) / (lastYear - startYear)) * + 100 + ); + // 로컬 스토리지에서 삭제 + localStorage.removeItem("hint-storage"); + // 주스탠드 스토어 상태 초기화 + useHintStore.getState().resetPurchaseHints(); + } + } + } catch (error) { + console.error(error); + } finally { + setLoading(false); + closePassModal(); + } + }; + + return ( + <> + {yearNumber !== checkYear ? ( +
+ +

정상적인 접근 경로가 아닙니다

+
+ ) : ( + + + +
+ +
+ + + + + + +
+ )} + + ); }; export default PlayPage; diff --git a/src/store/stockContext.tsx b/src/store/stockContext.tsx index 5fd2645..0689c26 100644 --- a/src/store/stockContext.tsx +++ b/src/store/stockContext.tsx @@ -15,7 +15,7 @@ export interface StockContextProps { setStockData: (data: Stock[]) => void; } -// 쥬스탠드 사용 +// // 쥬스탠드 사용 export const StocksStore = create((set) => ({ stockData: [], setStockData: (data: Stock[]) => set({ stockData: data }),