-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
각각의 폴더에 header, stockitem, list 파일 생성 메뉴 아이콘 클릭시 전체종목, 관심종목, 보유종목 버튼 생성 Issues #19
- Loading branch information
김병현
authored and
김병현
committed
Sep 15, 2023
1 parent
9eaa5e1
commit 558490f
Showing
10 changed files
with
560 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import React from 'react'; | ||
import styled from 'styled-components'; | ||
import Menu_icon from "../../asset/images/menu.png"; | ||
|
||
const ALL_LIST = "전체종목"; | ||
const INTEREST_LIST = "관심종목"; | ||
const HOLDING_LIST = "보유종목"; | ||
|
||
const Header: React.FC<HeaderProps> = ({ currentListType, onChangeListType, isMenuOpen, setMenuOpen }) => { | ||
return ( | ||
<HeaderWrapper> | ||
<Icon | ||
src={Menu_icon} | ||
alt="menu icon" | ||
onClick={() => setMenuOpen(!isMenuOpen)} | ||
/> | ||
<HeaderText>{currentListType}</HeaderText> | ||
{isMenuOpen && ( | ||
<SlideMenu> | ||
<MenuItem onClick={() => { onChangeListType(ALL_LIST); setMenuOpen(false); }}>{ALL_LIST}</MenuItem> | ||
<MenuItem onClick={() => { onChangeListType(INTEREST_LIST); setMenuOpen(false); }}>{INTEREST_LIST}</MenuItem> | ||
<MenuItem onClick={() => { onChangeListType(HOLDING_LIST); setMenuOpen(false); }}>{HOLDING_LIST}</MenuItem> | ||
</SlideMenu> | ||
)} | ||
</HeaderWrapper> | ||
); | ||
}; | ||
|
||
type HeaderProps = { | ||
currentListType: string; | ||
onChangeListType: (type: "전체종목" | "관심종목" | "보유종목") => void; | ||
isMenuOpen: boolean; | ||
setMenuOpen: React.Dispatch<React.SetStateAction<boolean>>; | ||
}; | ||
|
||
|
||
const HeaderWrapper = styled.div` | ||
display: flex; | ||
align-items: center; | ||
position: relative; | ||
`; | ||
|
||
const Icon = styled.img` | ||
margin-top: 9.5px; | ||
width: 24px; | ||
height: 24px; | ||
cursor: pointer; | ||
margin-right: 10px; | ||
`; | ||
|
||
const HeaderText = styled.span` | ||
margin-top: 9.5px; | ||
font-size: 18px; | ||
`; | ||
|
||
const SlideMenu = styled.div` | ||
position: absolute; | ||
top: 100%; | ||
left: 0; | ||
width: 248px; | ||
background-color: #f7f7f7; | ||
border: 1px solid #e0e0e0; /* 밑에 가로줄 추가 */ | ||
display: flex; | ||
flex-direction: column; | ||
`; | ||
|
||
const MenuItem = styled.button` | ||
padding: 8px 16px; | ||
border: none; | ||
background-color: transparent; | ||
cursor: pointer; | ||
text-align: left; | ||
`; | ||
|
||
export default Header; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import React from 'react'; | ||
import styled from 'styled-components'; | ||
import logo from '../../asset/logos/SK_logo.png'; | ||
|
||
const StockItem: React.FC<StockItemProps> = ({ company, setShowChangePrice, showChangePrice }) => { | ||
const isPositiveChange = parseFloat(company.stockChangeRate) > 0; | ||
const priceColor = isPositiveChange ? 'red' : 'blue'; | ||
|
||
return ( | ||
<StockItemWrapper> | ||
<Logo src={logo} alt="stock logo" /> | ||
<StockInfo> | ||
<StockName>{company.korName}</StockName> | ||
<StockCode>{company.code}</StockCode> | ||
</StockInfo> | ||
<StockPriceSection> | ||
<StockPrice change={priceColor}>{company.stockPrice}</StockPrice> | ||
<StockChange | ||
change={priceColor} | ||
onMouseEnter={() => setShowChangePrice(true)} | ||
onMouseLeave={() => setShowChangePrice(false)} | ||
> | ||
{showChangePrice ? `${company.stockChangeAmount}%` : `${company.stockChangeRate}%`} | ||
</StockChange> | ||
</StockPriceSection> | ||
</StockItemWrapper> | ||
); | ||
}; | ||
|
||
type NewCompanyData = { | ||
companyId: number; | ||
code: string; | ||
korName: string; | ||
stockPrice: string; | ||
stockChangeAmount: string; | ||
stockChangeRate: string; | ||
}; | ||
|
||
type StockItemProps = { | ||
company: NewCompanyData; | ||
setShowChangePrice: React.Dispatch<React.SetStateAction<boolean>>; | ||
showChangePrice: boolean; | ||
}; | ||
|
||
const StockItemWrapper = styled.div` | ||
display: flex; | ||
flex-direction: row; /* 수평으로 정렬 */ | ||
justify-content: flex-start; /* 왼쪽 정렬 */ | ||
align-items: flex-start; /* 위로 정렬 */ | ||
padding: 8px 0; | ||
border-bottom: 1px solid #e0e0e0; | ||
width: 100%; | ||
background-color: transparent; | ||
cursor: pointer; | ||
`; | ||
|
||
const Logo = styled.img` | ||
border-radius: 50%; | ||
width: 40px; | ||
height: 40px; | ||
margin-right: 12px; | ||
`; | ||
|
||
const StockInfo = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
align-items: flex-start; | ||
margin-right: 16px; | ||
`; | ||
|
||
const StockName = styled.span` | ||
font-weight: bold; | ||
`; | ||
|
||
const StockCode = styled.span` | ||
color: gray; | ||
`; | ||
|
||
const StockPriceSection = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
align-items: flex-start; | ||
margin-left: auto; /* 자동으로 왼쪽 여백 추가 */ | ||
`; | ||
|
||
const StockPrice = styled.span<{ change: string }>` | ||
color: ${(props) => props.change}; | ||
`; | ||
|
||
const StockChange = styled.span<{ change: string }>` | ||
color: ${(props) => props.change}; | ||
cursor: pointer; | ||
`; | ||
|
||
export default StockItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import React from 'react'; | ||
import styled from 'styled-components'; | ||
import Menu_icon from "../../asset/images/menu.png"; | ||
|
||
const ALL_LIST = "전체종목"; | ||
const INTEREST_LIST = "관심종목"; | ||
const HOLDING_LIST = "보유종목"; | ||
|
||
const Header: React.FC<HeaderProps> = ({ currentListType, onChangeListType, isMenuOpen, setMenuOpen }) => { | ||
return ( | ||
<HeaderWrapper> | ||
<Icon | ||
src={Menu_icon} | ||
alt="menu icon" | ||
onClick={() => setMenuOpen(!isMenuOpen)} | ||
/> | ||
<HeaderText>{currentListType}</HeaderText> | ||
{isMenuOpen && ( | ||
<SlideMenu> | ||
<MenuItem onClick={() => { onChangeListType(ALL_LIST); setMenuOpen(false); }}>{ALL_LIST}</MenuItem> | ||
<MenuItem onClick={() => { onChangeListType(INTEREST_LIST); setMenuOpen(false); }}>{INTEREST_LIST}</MenuItem> | ||
<MenuItem onClick={() => { onChangeListType(HOLDING_LIST); setMenuOpen(false); }}>{HOLDING_LIST}</MenuItem> | ||
</SlideMenu> | ||
)} | ||
</HeaderWrapper> | ||
); | ||
}; | ||
|
||
type HeaderProps = { | ||
currentListType: string; | ||
onChangeListType: (type: "전체종목" | "관심종목" | "보유종목") => void; | ||
isMenuOpen: boolean; | ||
setMenuOpen: React.Dispatch<React.SetStateAction<boolean>>; | ||
}; | ||
|
||
|
||
const HeaderWrapper = styled.div` | ||
display: flex; | ||
align-items: center; | ||
position: relative; | ||
`; | ||
|
||
const Icon = styled.img` | ||
margin-top: 9.5px; | ||
width: 24px; | ||
height: 24px; | ||
cursor: pointer; | ||
margin-right: 10px; | ||
`; | ||
|
||
const HeaderText = styled.span` | ||
margin-top: 9.5px; | ||
font-size: 18px; | ||
`; | ||
|
||
const SlideMenu = styled.div` | ||
position: absolute; | ||
top: 100%; | ||
left: 0; | ||
width: 248px; | ||
background-color: #f7f7f7; | ||
border: 1px solid #e0e0e0; /* 밑에 가로줄 추가 */ | ||
display: flex; | ||
flex-direction: column; | ||
`; | ||
|
||
const MenuItem = styled.button` | ||
padding: 8px 16px; | ||
border: none; | ||
background-color: transparent; | ||
cursor: pointer; | ||
text-align: left; | ||
`; | ||
|
||
export default Header; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import React, { useState } from 'react'; | ||
import styled from 'styled-components'; | ||
import Header from './Header'; | ||
import StockItem from './StockItem'; | ||
import useCompanyData from '../../hooks/useCompanyData'; | ||
|
||
const WatchList: React.FC<WatchListProps> = ({ currentListType, onChangeListType }) => { | ||
const [isMenuOpen, setMenuOpen] = useState(false); | ||
const [showChangePrice, setShowChangePrice] = useState(false); | ||
|
||
// useCompanyData 훅 사용하여 데이터 가져오기 | ||
const { data: companies, isLoading, isError } = useCompanyData(1, 14); | ||
|
||
// 'companies'가 'undefined'인 경우를 처리하기 위해 빈 배열로 초기화 | ||
const companiesList = companies || []; | ||
|
||
return ( | ||
<WatchListContainer> | ||
<Header | ||
currentListType={currentListType} | ||
onChangeListType={onChangeListType} | ||
isMenuOpen={isMenuOpen} | ||
setMenuOpen={setMenuOpen} | ||
/> | ||
<Divider1 /> | ||
<EvaluationProfit>평가 수익금: +5,000,000원</EvaluationProfit> {/* 임의의 평가 수익금 */} | ||
<Divider2 /> | ||
<StockList> | ||
{isLoading ? ( | ||
<div>Loading...</div> | ||
) : isError ? ( | ||
<div>Error fetching data</div> | ||
) : ( | ||
companiesList.map((company) => ( | ||
<StockItem | ||
key={company.companyId} | ||
company={company} | ||
setShowChangePrice={setShowChangePrice} | ||
showChangePrice={showChangePrice} | ||
/> | ||
)) | ||
)} | ||
</StockList> | ||
</WatchListContainer> | ||
); | ||
}; | ||
|
||
// Props와 상태에 대한 타입 정의 | ||
type WatchListProps = { | ||
currentListType: '전체종목' | '관심종목' | '보유종목'; | ||
onChangeListType: (type: '전체종목' | '관심종목' | '보유종목') => void; | ||
}; | ||
|
||
// WatchList 컴포넌트에 대한 스타일드 컴포넌트 정의 | ||
const WatchListContainer = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
align-items: flex-start; | ||
`; | ||
|
||
const Divider1 = styled.div` | ||
margin:0px; | ||
padding:0px; | ||
width: 100%; | ||
height: 10px; | ||
display: flex; | ||
flex-direction: row; | ||
border-bottom: 1px solid #2f4f4f; | ||
`; | ||
|
||
const Divider2 = styled.div` | ||
margin:0px; | ||
padding:0px; | ||
width: 100%; | ||
height: 4.5px; | ||
display: flex; | ||
flex-direction: row; | ||
border-bottom: 1px solid #2f4f4f; | ||
`; | ||
|
||
|
||
|
||
const EvaluationProfit = styled.div` | ||
font-size: 16px; | ||
font-weight: bold; | ||
margin: 8px 0; | ||
text-align: center; | ||
color: red; // 수익금이 플러스일 경우 초록색으로 표시 | ||
`; | ||
const StockList = styled.div` | ||
width: 90%; | ||
max-height: 800px; /* 스크롤이 발생할 최대 높이를 지정하세요 */ | ||
overflow-y: auto; /* 세로 스크롤을 활성화합니다 */ | ||
`; | ||
|
||
export default WatchList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.