Skip to content

Commit

Permalink
Merge pull request #113 from codestates-seb/dev-client#19/watchList
Browse files Browse the repository at this point in the history
[FE] 로그인 문제 오류 해결Dev client#19/watch list
  • Loading branch information
sirloinbh authored Sep 15, 2023
2 parents 0e8bb3c + 424b30b commit 3dca958
Show file tree
Hide file tree
Showing 18 changed files with 970 additions and 240 deletions.
96 changes: 96 additions & 0 deletions client/src/components/EntireList/EntireList.tsx
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 EntireList: React.FC<EntireListProps> = ({ 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 EntireListProps = {
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: 100%;
max-height: 740px; /* 스크롤이 발생할 최대 높이를 지정하세요 */
overflow-y: auto; /* 세로 스크롤을 활성화합니다 */
`;

export default EntireList;
76 changes: 76 additions & 0 deletions client/src/components/EntireList/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
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;
margin-left: 10px;
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;
95 changes: 95 additions & 0 deletions client/src/components/EntireList/StockItem.tsx
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;
75 changes: 75 additions & 0 deletions client/src/components/HoldingList/Header.tsx
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;
Loading

0 comments on commit 3dca958

Please sign in to comment.