From 588a352184a7dbd0f3628f15e0b2fa41a49aec64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=ED=98=84?= Date: Tue, 19 Sep 2023 11:33:05 +0900 Subject: [PATCH] =?UTF-8?q?[Feat]=EA=B4=80=EC=8B=AC=EC=A2=85=EB=AA=A9=20?= =?UTF-8?q?=EC=9E=AC=EA=B5=AC=ED=98=84=20useGetstars,=20usePosrstars,=20us?= =?UTF-8?q?eDeletestars=20=ED=9B=85=EC=9D=84=20=EC=83=9D=EC=84=B1.=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=EC=A2=85=EB=AA=A9=EA=B3=BC=20=EB=B3=B4?= =?UTF-8?q?=EC=9C=A0=EC=A2=85=EB=AA=A9=EC=97=90=EC=84=9C=20=EC=A2=85?= =?UTF-8?q?=EB=AA=A9=EC=97=90=20=EB=A7=88=EC=9A=B0=EC=8A=A4=20=ED=98=B8?= =?UTF-8?q?=EB=B2=84=20=EC=8B=9C=20=EB=B3=84=ED=91=9C=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20=EB=B3=B4=EC=9E=84=20=EB=B3=84=ED=91=9C=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=EC=9D=84=20=EB=88=84=EB=A5=B4=EB=A9=B4=20pos?= =?UTF-8?q?t=EC=9A=94=EC=B2=AD=20=EB=98=90=EB=8A=94=20delete=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EA=B4=80=EC=8B=AC=EC=A2=85=EB=AA=A9=EC=97=90?= =?UTF-8?q?=EC=84=9C=EB=8A=94=20get=EC=9A=94=EC=B2=AD=EC=9D=84=20=EB=B3=B4?= =?UTF-8?q?=EB=82=B4=EC=84=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=A5=BC=20?= =?UTF-8?q?=EB=B0=9B=EC=95=84=EC=98=B4=20=EA=B4=80=EC=8B=AC=EC=A2=85?= =?UTF-8?q?=EB=AA=A9=EC=97=90=EC=84=9C=20=EC=A2=85=EB=AA=A9=EC=97=90=20?= =?UTF-8?q?=EB=A7=88=EC=9A=B0=EC=8A=A4=20=ED=98=B8=EB=B2=84=20=EC=8B=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EB=B3=B4?= =?UTF-8?q?=EC=9E=84=20=EC=82=AD=EC=A0=9C=20=EC=95=84=EC=9D=B4=EC=BD=98?= =?UTF-8?q?=EC=9D=84=20=EB=88=84=EB=A5=B4=EB=A9=B4=20delete=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EC=84=9C=EB=B2=84=EC=99=80=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=ED=86=B5=EC=8B=A0=20=EB=AC=B8=EC=A0=9C=EA=B0=80=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EC=97=AC=20=EB=AF=B8=EC=99=84?= =?UTF-8?q?=EC=84=B1=20Isseus=20#19?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/asset/icon/delete_icon.png | Bin 0 -> 10147 bytes client/src/asset/icon/star_filled_icon.png | Bin 0 -> 27678 bytes client/src/asset/icon/star_icon.png | Bin 0 -> 8996 bytes client/src/components/EntireList/Header.tsx | 1 + .../src/components/EntireList/StockItem.tsx | 66 ++++++++- client/src/components/HoldingList/Header.tsx | 1 + .../src/components/HoldingList/StockItem.tsx | 86 ++++++++--- client/src/components/watchlist/Header.tsx | 1 + client/src/components/watchlist/StockItem.tsx | 135 +++++++++++++++--- client/src/components/watchlist/WatchList.tsx | 35 +---- client/src/hooks/stars/useDeletestars.ts | 27 ++++ client/src/hooks/stars/useGetstars.ts | 57 ++++++++ client/src/hooks/stars/usePoststars.ts | 26 ++++ client/src/page/MainPage.tsx | 3 - 14 files changed, 364 insertions(+), 74 deletions(-) create mode 100644 client/src/asset/icon/delete_icon.png create mode 100644 client/src/asset/icon/star_filled_icon.png create mode 100644 client/src/asset/icon/star_icon.png create mode 100644 client/src/hooks/stars/useDeletestars.ts create mode 100644 client/src/hooks/stars/useGetstars.ts create mode 100644 client/src/hooks/stars/usePoststars.ts diff --git a/client/src/asset/icon/delete_icon.png b/client/src/asset/icon/delete_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4911b9ffd48a891a76cda5cd14a922c02466411b GIT binary patch literal 10147 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 U>#wfI?O%;DHL}Du8G6M32kHb;WB>pF literal 0 HcmV?d00001 diff --git a/client/src/asset/icon/star_filled_icon.png b/client/src/asset/icon/star_filled_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3f5840ac59ca965fd85b0f59e140a4a954c57b30 GIT binary patch literal 27678 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 = ({ company }) => { // const priceColor2 = isPositiveChange ? "#f87369" : "#5a99f8"; const [showChangePrice, setShowChangePrice] = useState(false); // 상태를 여기로 이동 + const [isHovering, setIsHovering] = useState(false); // 마우스 호버 상태 + const { data: starredData } = useGetStar(); + const starredCompanyIds = starredData?.map(item => item.companyResponseDto.companyId) || []; + + // 해당 companyId가 이미 존재하는지 확인하고, isFavorited의 초기값을 설정합니다. + const [isFavorited, setIsFavorited] = useState(starredCompanyIds.includes(company.companyId)); + + // usePostStar 및 useDeleteStar 훅 사용 + const postMutation = usePostStar(); + const deleteMutation = useDeleteStar(); + + const toggleFavorite = () => { + // 현재 isFavorited 상태에 따라 요청을 결정합니다. + if (isFavorited) { + deleteMutation.mutate(company.companyId); + } else { + postMutation.mutate(company.companyId); + } + setIsFavorited(!isFavorited); + }; + + // 🔴 회계 단위 추가 const price = parseInt(company.stockPrice).toLocaleString(); @@ -55,11 +83,19 @@ const StockItem: React.FC = ({ company }) => { return ( setShowChangePrice(true)} // StockItemWrapper에 이벤트 리스너 적용 - onMouseLeave={() => setShowChangePrice(false)} + onMouseEnter={() => { + setShowChangePrice(true); + setIsHovering(true); + }} + onMouseLeave={() => { + setShowChangePrice(false); + setIsHovering(false); + }} > - + + + {company.korName} @@ -107,19 +143,39 @@ const StockItemWrapper = styled.div` // 🔴 로고 컨테이너 + 로고 크기 const LogoContainer = styled.div` height: 100%; + width: 48px; // 아이콘의 너비와 margin-left, margin-right의 합계를 기준으로 설정 display: flex; justify-content: center; align-items: center; + position: relative; `; -const Logo = styled.img` +const Logo = styled.img<{ opacity: number }>` border-radius: 50%; width: 28px; height: 28px; margin-left: 10px; margin-right: 10px; + position: absolute; + opacity: ${(props) => props.opacity}; +`; + +const FavoriteStar = styled.div<{ opacity: number }>` + position: absolute; + width: 28px; + height: 28px; + background: url(${star_icon}) no-repeat center; + background-size: contain; + cursor: pointer; + opacity: ${(props) => props.opacity}; +`; + +const FavoriteStarFilled = styled(FavoriteStar)<{ opacity: number }>` + background: url(${star_filled_icon}) no-repeat center; + background-size: contain; // 👈 이 부분도 추가 `; + // 🔴 font 사이즈 const StockInfo = styled.div` height: 100%; @@ -167,4 +223,6 @@ const StockChange = styled.span<{ change: string }>` font-size: 13px; `; + + export default StockItem; diff --git a/client/src/components/HoldingList/Header.tsx b/client/src/components/HoldingList/Header.tsx index b98b0d4c..472be2f3 100644 --- a/client/src/components/HoldingList/Header.tsx +++ b/client/src/components/HoldingList/Header.tsx @@ -73,6 +73,7 @@ const HeaderText = styled.span` `; const SlideMenu = styled.div` + z-index:30; position: absolute; top: 100%; left: 0; diff --git a/client/src/components/HoldingList/StockItem.tsx b/client/src/components/HoldingList/StockItem.tsx index 72b48450..d21f70b0 100644 --- a/client/src/components/HoldingList/StockItem.tsx +++ b/client/src/components/HoldingList/StockItem.tsx @@ -2,6 +2,13 @@ import React, { useState } from "react"; import styled from "styled-components"; import logo from "../../asset/images/StockHolmImage.png"; +import star_icon from "../../asset/icon/star_icon.png" +import star_filled_icon from "../../asset/icon/star_filled_icon.png" + +import usePostStar from "../../hooks/stars/usePoststars"; +import useDeleteStar from "../../hooks/stars/useDeletestars"; +import useGetStar from "../../hooks/stars/useGetstars"; + import kia from '../../asset/logos/기아.svg'; import dy from '../../asset/logos/디와이.jpeg'; import logosamsung from '../../asset/logos/삼성전자.svg'; @@ -55,7 +62,7 @@ const StockItem: React.FC = ({ companyData, stockData }) => { const formattedPercentage = parseFloat(percentage.toFixed(2)); // 이미 import된 로고들을 바탕으로 logos 객체 생성 - const logos: { [key: string]: string } = { + const logos: { [key: string]: string } = { '삼성전자': logosamsung, 'POSCO홀딩스': posco, '셀트리온': celltrion, @@ -71,19 +78,47 @@ const StockItem: React.FC = ({ companyData, stockData }) => { 'LG전자': LGelec, '기아': kia, }; - // 그리고 나서, 이 `logos` 객체를 사용하여 기업명에 따라 적절한 로고를 선택할 수 있습니다. - const companyLogo = company ? logos[company.korName] || logo : logo; // 기본 로고를 대체로 사용 + // 그리고 나서, 이 `logos` 객체를 사용하여 기업명에 따라 적절한 로고를 선택할 수 있습니다. + const companyLogo = company ? logos[company.korName] || logo : logo; // 기본 로고를 대체로 사용 + + const [isHovering, setIsHovering] = useState(false); // 마우스 호버 상태 + const { data: starredData } = useGetStar(); + const starredCompanyIds = starredData?.map(item => item.companyResponseDto.companyId) || []; + // 해당 companyId가 이미 존재하는지 확인하고, isFavorited의 초기값을 설정합니다. + const [isFavorited, setIsFavorited] = useState(starredCompanyIds.includes(stockData.companyId)); + + // usePostStar 및 useDeleteStar 훅 사용 + const postMutation = usePostStar(); + const deleteMutation = useDeleteStar(); + + const toggleFavorite = () => { + // 현재 isFavorited 상태에 따라 요청을 결정합니다. + if (isFavorited) { + deleteMutation.mutate(stockData.companyId); + } else { + postMutation.mutate(stockData.companyId); + } + setIsFavorited(!isFavorited); + }; return ( <> setShowChangePrice(true)} // Mouse event handlers - onMouseLeave={() => setShowChangePrice(false)} + onMouseEnter={() => { + setShowChangePrice(true); + setIsHovering(true); + }} + onMouseLeave={() => { + setShowChangePrice(false); + setIsHovering(false); + }} > - + + + {korName} @@ -141,14 +176,35 @@ const LogoContainer = styled.div` /* padding-right: 5px/; */ `; -const Logo = styled.img` +const Logo = styled.img<{ opacity: number }>` border-radius: 50%; width: 28px; height: 28px; - /* margin-left: 10px; */ - /* margin-right: 5px; */ + position: absolute; + opacity: ${(props) => props.opacity}; `; +const FavoriteStar = styled.div<{ opacity: number }>` + position: absolute; + width: 28px; + height: 28px; + background: url(${star_icon}) no-repeat center; + background-size: contain; + cursor: pointer; + opacity: ${(props) => props.opacity}; +`; + +const FavoriteStarFilled = styled(FavoriteStar)<{ opacity: number }>` + background: url(${star_filled_icon}) no-repeat center; + background-size: contain; +`; + + + + + + + const StockInfo = styled.div` flex: 5 0 0; height: 100%; @@ -252,19 +308,7 @@ const DetailData = styled.span` font-size: 14px; // Setting standardized font size for all data `; -// const getColorByValue = (value: string) => { -// if (value.startsWith("")) return "#ed2926"; -// if (value.startsWith("-")) return "#2679ed"; -// return "black"; -// }; - const ColoredDetailData = styled.span<{ priceChangeAmount: number }>` color: ${(props) => (props.priceChangeAmount > 0 ? "#e22926" : "#2679ed")}; font-size: 14px; `; - -// const ThickDivider = styled.div` -// height: 3px; -// background-color: #aaa; -// margin: 8px 0; -// `; diff --git a/client/src/components/watchlist/Header.tsx b/client/src/components/watchlist/Header.tsx index cf26c7c9..ea2c10f3 100644 --- a/client/src/components/watchlist/Header.tsx +++ b/client/src/components/watchlist/Header.tsx @@ -70,6 +70,7 @@ const HeaderText = styled.span` font-size: 18px; `; const SlideMenu = styled.div` + z-index:30; position: absolute; top: 100%; left: 0; diff --git a/client/src/components/watchlist/StockItem.tsx b/client/src/components/watchlist/StockItem.tsx index a6fda6ac..4758d1ea 100644 --- a/client/src/components/watchlist/StockItem.tsx +++ b/client/src/components/watchlist/StockItem.tsx @@ -1,32 +1,96 @@ import React,{ useState } from 'react'; import styled from 'styled-components'; import logo from '../../asset/images/StockHolmImage.png'; +import deleteIcon from '../../asset/icon/delete_icon.png'; +import useDeleteStar from '../../hooks/stars/useDeletestars'; + +import kia from '../../asset/logos/기아.svg'; +import dy from '../../asset/logos/디와이.jpeg'; +import logosamsung from '../../asset/logos/삼성전자.svg'; +import celltrion from '../../asset/logos/셀트리온.svg'; +import ecopro from '../../asset/logos/에코프로.jpeg'; +import ecoproBM from '../../asset/logos/에코프로비엠.svg'; +import kakaoBank from '../../asset/logos/카카오뱅크.svg'; +import kuckoo from '../../asset/logos/쿠쿠홀딩스.jpeg'; +import hanse from '../../asset/logos/한세엠케이.jpeg'; +import hyundai from '../../asset/logos/현대차.svg'; +import KG from '../../asset/logos/KG케미칼.png'; +import LGelec from '../../asset/logos/LG전자.svg'; +import LGchem from '../../asset/logos/LG화학.svg'; +import posco from '../../asset/logos/POSCO홀딩스.svg'; + const StockItem: React.FC = ({ company }) => { const [showChangePrice, setShowChangePrice] = useState(false); const isPositiveChange = parseFloat(company.stockChangeRate) > 0; - const priceColor1 = isPositiveChange ? "#ed2926" : "#2679ed"; - const priceColor2 = isPositiveChange ? "#f87369" : "#5a99f8"; + // 🔴 색깔 통일 (그냥 깔끔하게) + const priceColor1 = isPositiveChange ? "#e22926" : "#2679ed"; + const priceColor2 = isPositiveChange ? "#e22926" : "#2679ed"; + // const priceColor2 = isPositiveChange ? "#fba89f" : "#a3c5f9"; + // const priceColor2 = isPositiveChange ? "#f87369" : "#5a99f8"; + + const [isHovered, setIsHovered] = useState(false); // 마우스 호버 상태 + const deleteMutation = useDeleteStar(); + + const handleDelete = () => { + deleteMutation.mutate(company.companyId, { + onSuccess: () => { + // 성공적으로 삭제되면 컴포넌트를 리렌더링 (상위 컴포넌트에서 상태 변경을 통해 구현해야 할 수도 있음) + // 여기서는 간단하게 window.location.reload()를 사용하겠습니다. + window.location.reload(); + } + }); + }; + + // 🔴 회계 단위 추가 + const price = parseInt(company.stockPrice).toLocaleString(); + const changeAmout = parseInt(company.stockChangeAmount).toLocaleString(); + const priceUnit = "원"; + + // 이미 import된 로고들을 바탕으로 logos 객체 생성 + const logos: { [key: string]: string } = { + '삼성전자': logosamsung, + 'POSCO홀딩스': posco, + '셀트리온': celltrion, + '에코프로': ecopro, + '에코프로비엠': ecoproBM, + '디와이': dy, + '쿠쿠홀딩스': kuckoo, + '카카오뱅크': kakaoBank, + '한세엠케이': hanse, + 'KG케미칼': KG, + 'LG화학': LGchem, + '현대차': hyundai, + 'LG전자': LGelec, + '기아': kia, + }; + // 그리고 나서, 이 `logos` 객체를 사용하여 기업명에 따라 적절한 로고를 선택할 수 있습니다. + const companyLogo = logos[company.korName] || logo; // 기본 로고를 대체로 사용 return ( setShowChangePrice(true)} - onMouseLeave={() => setShowChangePrice(false)} + onMouseEnter={() => { setShowChangePrice(true); setIsHovered(true); }} + onMouseLeave={() => { setShowChangePrice(false); setIsHovered(false); }} > - + + + + {company.korName} {company.code} - {company.stockPrice} - - {showChangePrice ? `${company.stockChangeAmount}` : `${company.stockChangeRate}%`} - + + {price} {priceUnit} + + {showChangePrice ? `${changeAmout} ${priceUnit}` : `${company.stockChangeRate}%`} ); }; +export default StockItem; + type NewCompanyData = { companyId: number; @@ -49,50 +113,85 @@ const StockItemWrapper = styled.div` padding: 8px 0; border-bottom: 1px solid #e0e0e0; width: 100%; + height: 57px; background-color: transparent; cursor: pointer; `; -const Logo = styled.img` +// 🔴 로고 컨테이너 + 로고 크기 +const LogoContainer = styled.div` + height: 100%; + width: 48px; // 아이콘의 너비와 margin-left, margin-right의 합계를 기준으로 설정 + display: flex; + justify-content: center; + align-items: center; + position: relative; +`; + +const Logo = styled.img<{ isHovered: boolean }>` + border-radius: 50%; + width: 28px; + height: 28px; + margin-left: 10px; + margin-right: 10px; + position: absolute; + opacity: ${props => props.isHovered ? 0 : 1}; +`; + +const DeleteIcon = styled.img<{ isHovered: boolean }>` border-radius: 50%; - width: 40px; - height: 40px; - margin-right: 12px; + width: 28px; + height: 28px; + margin-left: 10px; + margin-right: 10px; + position: absolute; + cursor: pointer; + opacity: ${props => props.isHovered ? 1 : 0}; `; const StockInfo = styled.div` + height: 100%; display: flex; flex-direction: column; + justify-content: center; align-items: flex-start; + padding-top: 3px; margin-right: 16px; `; const StockName = styled.span` - font-weight: 500; + font-size: 15px; + font-weight: 400; `; const StockCode = styled.span` - color: gray; + /* color: gray; */ + /* color: #2f4f4f; */ + color: darkgray; font-weight: 400; - font-size: 14px; + font-size: 13px; `; const StockPriceSection = styled.div` + height: 100%; display: flex; flex-direction: column; + justify-content: center; align-items: flex-end; + padding-top: 3px; margin-left: auto; /* 자동으로 왼쪽 여백 추가 */ margin-right: 10px; `; const StockPrice = styled.span<{ change: string }>` + font-size: 15px; color: ${(props) => props.change}; `; const StockChange = styled.span<{ change: string }>` color: ${(props) => props.change}; cursor: pointer; - font-size:14px; + font-size: 13px; `; -export default StockItem; + diff --git a/client/src/components/watchlist/WatchList.tsx b/client/src/components/watchlist/WatchList.tsx index 885b8796..e5da762d 100644 --- a/client/src/components/watchlist/WatchList.tsx +++ b/client/src/components/watchlist/WatchList.tsx @@ -1,41 +1,22 @@ -import React, { useState, useEffect } from "react"; +import React, { useState } from "react"; import styled from "styled-components"; import StockSearchComponent from "./StockSearchComponent"; import Header from "./Header"; import StockItem from "./StockItem"; import useCompanyData from "../../hooks/useCompanyData"; +import useGetStars from "../../hooks/stars/useGetstars.ts"; // useGetStars 훅의 경로를 지정해주세요. import { useSelector } from "react-redux"; -import { RootState } from "../../store/config.ts"; // Redux store의 RootState를 import해야 합니다. +import { RootState } from "../../store/config.ts"; const WatchList: React.FC = ({ currentListType, onChangeListType }) => { const [isMenuOpen, setMenuOpen] = useState(false); - const loginStatus = useSelector((state: RootState) => state.login); - // useCompanyData 훅 사용하여 데이터 가져오기 const { data: companies, isLoading, isError } = useCompanyData(1, 14); - - // 'companies'가 'undefined'인 경우를 처리하기 위해 빈 배열로 초기화 const companiesList = companies || []; - // 이미 검색된 회사 ID들을 저장하는 스택 형태의 상태 - const [searchedCompanyIds, setSearchedCompanyIds] = useState([]); - - // Redux store에서 선택된 회사 ID 가져오기 - const selectedCompanyId = useSelector((state: RootState) => state.companyId); - - // 새로운 회사 ID가 검색될 때마다 스택에 추가 - useEffect(() => { - if (selectedCompanyId !== -1 && !searchedCompanyIds.includes(selectedCompanyId)) { - setSearchedCompanyIds((prevIds) => [...prevIds, selectedCompanyId]); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedCompanyId]); - - // - useEffect(() => { - localStorage.setItem("searchedCompanyIds", JSON.stringify(searchedCompanyIds)); - }, [searchedCompanyIds]); + const { data: starredData } = useGetStars(); + const starredCompanyIds = starredData?.map(item => item.companyResponseDto.companyId) || []; return ( @@ -53,7 +34,7 @@ const WatchList: React.FC = ({ currentListType, onChangeListType ) : isError ? (
Error fetching data
) : loginStatus === 1 ? ( - companiesList.filter((company) => searchedCompanyIds.includes(company.companyId)).map((company) => ) + companiesList.filter((company) => starredCompanyIds.includes(company.companyId)).map((company) => ) ) : (
로그인이 필요합니다.
)} @@ -62,13 +43,11 @@ const WatchList: React.FC = ({ currentListType, onChangeListType ); }; -// Props와 상태에 대한 타입 정의 type WatchListProps = { currentListType: "전체종목" | "관심종목" | "보유종목"; onChangeListType: (type: "전체종목" | "관심종목" | "보유종목") => void; }; -// WatchList 컴포넌트에 대한 스타일드 컴포넌트 정의 const WatchListContainer = styled.div` width: 247px; height: calc(100vh - 53px); @@ -97,7 +76,7 @@ const Divider = styled.div` const StockList = styled.div` height: 100%; width: 100%; - overflow-y: auto; /* 세로 스크롤을 활성화합니다 */ + overflow-y: auto; &::-webkit-scrollbar { display: none; diff --git a/client/src/hooks/stars/useDeletestars.ts b/client/src/hooks/stars/useDeletestars.ts new file mode 100644 index 00000000..5c3f9918 --- /dev/null +++ b/client/src/hooks/stars/useDeletestars.ts @@ -0,0 +1,27 @@ +import { useMutation } from 'react-query'; + +// DELETE 요청을 수행하는 함수 +const deleteStarData = async (companyId: number) => { + const accessToken = localStorage.getItem('accessToken'); + const response = await fetch('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/stars', { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `${accessToken}` + }, + body: JSON.stringify({ companyId }), + }); + + if (!response.ok) { + throw new Error('Failed to delete star data.'); + } + + return response.json(); +}; + +// react-query의 useMutation을 사용한 custom hook +const useDeleteStar = () => { + return useMutation(deleteStarData); +}; + +export default useDeleteStar; diff --git a/client/src/hooks/stars/useGetstars.ts b/client/src/hooks/stars/useGetstars.ts new file mode 100644 index 00000000..5dab186a --- /dev/null +++ b/client/src/hooks/stars/useGetstars.ts @@ -0,0 +1,57 @@ +import { useQuery } from 'react-query'; + +type StockAsBiResponseDto = { + stockAsBiId: number; + companyId: number; + askp1: string; + askp2: string; + // ... 나머지 필드들 +}; + +type StockInfResponseDto = { + stockInfId: number; + companyId: number; + stck_prpr: string; + prdy_vrss: string; + prdy_ctrt: string; + acml_vol: string; + acml_tr_pbmn: string; +}; + +type CompanyResponseDto = { + companyId: number; + code: string; + korName: string; + stockAsBiResponseDto: StockAsBiResponseDto; + stockInfResponseDto: StockInfResponseDto; +}; + +type StarDataItem = { + starId: number; + memberId: number; + companyResponseDto: CompanyResponseDto; +}; + +type StarData = StarDataItem[]; + +const fetchStarData = async (): Promise => { + const accessToken = localStorage.getItem('accessToken'); + const res = await fetch('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/stars', { + headers: { + 'Authorization': `${accessToken}` + } + }); + + if (!res.ok) { + const data = await res.json(); + throw new Error(data.message || 'Something went wrong'); + } + + return res.json(); +}; + +const useGetStar = () => { + return useQuery('starData', fetchStarData); +}; + +export default useGetStar; diff --git a/client/src/hooks/stars/usePoststars.ts b/client/src/hooks/stars/usePoststars.ts new file mode 100644 index 00000000..f3f56a09 --- /dev/null +++ b/client/src/hooks/stars/usePoststars.ts @@ -0,0 +1,26 @@ +import { useMutation } from 'react-query'; + +const postStarData = async (companyId: number) => { + const accessToken = localStorage.getItem('accessToken'); + const res = await fetch('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/stars', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `${accessToken}` + }, + body: JSON.stringify({ companyId }) + }); + + if (!res.ok) { + const data = await res.json(); + throw new Error(data.message || 'Something went wrong'); + } + + return res.json(); +}; + +const usePostStar = () => { + return useMutation(postStarData); +}; + +export default usePostStar; diff --git a/client/src/page/MainPage.tsx b/client/src/page/MainPage.tsx index 498d4771..8161a222 100644 --- a/client/src/page/MainPage.tsx +++ b/client/src/page/MainPage.tsx @@ -119,9 +119,6 @@ const MainPage = () => { openOAuthModal(); }, [openOAuthModal]); - const handleOAuthLoginSuccess = useCallback(() => { - setLoginConfirmationModalOpen(true); // 로그인 확인 모달 열기 - }, []); //프로필 모달 열고닫는 매커니즘 const openProfileModal = useCallback(() => {