Skip to content

Commit

Permalink
[Feat] 우측 주식주문 관련 거래가, 거래량 설정 기능 구현
Browse files Browse the repository at this point in the history
- 주식주문 창의 거래가, 거래량 설정 기능 구현 완료
- 매수/매도 구분하여 적용되도록 기능 구현
- 보유자금 및 종목별 주식 Get API, 매도/매수 체결 API 구현 후 로직 추가 예정

Issues #17
  • Loading branch information
novice1993 committed Sep 9, 2023
1 parent 066327d commit db99234
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 67 deletions.
4 changes: 2 additions & 2 deletions client/src/components/CentralChartMenu/StockOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,14 @@ const Container = styled.div<{ priceChangeRate: number }>`
.StockPrice {
font-size: 18px;
color: ${(props) => (props.priceChangeRate > 0 ? "#ed2926" : "#3177d7")};
color: ${(props) => (props.priceChangeRate > 0 ? "#ed2926" : props.priceChangeRate === 0 ? "black" : "#3177d7")};
font-weight: 530;
}
.PriceChangeRate,
.PriceChangeAmount {
font-size: 14px;
color: ${(props) => (props.priceChangeRate > 0 ? "#ed2926" : "#3177d7")};
color: ${(props) => (props.priceChangeRate > 0 ? "#ed2926" : props.priceChangeRate === 0 ? "black" : "#3177d7")};
display: flex;
flex-direction: row;
Expand Down
8 changes: 4 additions & 4 deletions client/src/components/StockOrderSection/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ const Container = styled.aside<{ orderSet: boolean }>`
width: 26%;
min-width: 400px;
height: 100%;
border-left: 1px solid black;
box-shadow: -1px 0px 10px darkgray;
background-color: #ffffff;
`;

Expand All @@ -81,8 +82,8 @@ const UpperBar = styled.div`
justify-content: center;
align-items: center;
width: 100%;
min-height: 43px;
border-bottom: 1px solid black;
min-height: 44px;
border-bottom: 1px solid darkgray;
.Title {
font-size: 17px;
Expand Down Expand Up @@ -112,7 +113,6 @@ const StockName = styled.section`
padding-bottom: 8px;
padding-left: 16px;
gap: 9px;
border-bottom: 1px solid black;
.CorpLogo {
width: 28px;
Expand Down
1 change: 0 additions & 1 deletion client/src/components/StockOrderSection/OrderRequest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export default OrderRequest;

const Container = styled.div`
height: 414px;
border-bottom: 1px solid black;
display: flex;
flex-direction: row;
Expand Down
34 changes: 26 additions & 8 deletions client/src/components/StockOrderSection/StockOrderBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import { styled } from "styled-components";
import { StateProps } from "../../models/stateProps";
import { OrderTypeProps } from "../../models/orderTypeProps";

const availableMoneyText01: string = "최대";
const availableMoneyText02: string = "원";
const totalAmountText01: string = "주문총액";
const totalAmountText02: string = "원";
const totalAmountText: string = "주문총액";
const totalAmountUnit: string = "원";

// dummyData
import { availableMoney } from "./dummyData";
const dummyAmount: string = "0";
const dummyMoney = availableMoney.toLocaleString();

const StockOrderBtn = () => {
const StockOrderBtn = (props: OwnProps) => {
const { orderVolume, setOrderVolume } = props;

const stockOrderType = useSelector((state: StateProps) => state.stockOrderType);
const orderPrice = useSelector((state: StateProps) => state.stockOrderPrice);
const [totalOrderAmout, setTotalOrderAmout] = useState(0);
const orderBtnText: string = stockOrderType ? "매도" : "매수";

useEffect(() => {
setTotalOrderAmout(orderPrice * orderVolume);
}, [orderPrice, orderVolume]);

useEffect(() => {
setOrderVolume(0);
setTotalOrderAmout(0);
}, [stockOrderType]);

return (
<Container>
<AvailableMoney orderType={stockOrderType}>
Expand All @@ -25,9 +38,9 @@ const StockOrderBtn = () => {
<span>{availableMoneyText02}</span>
</AvailableMoney>
<TotalAmount>
<div className="totalAmountText01">{totalAmountText01}</div>
<div className="totalAmount">{dummyAmount}</div>
<div>{totalAmountText02}</div>
<div className="totalAmountText">{totalAmountText}</div>
<div className="totalAmount">{totalOrderAmout.toLocaleString()}</div>
<div>{totalAmountUnit}</div>
</TotalAmount>
<OrderBtn ordertype={stockOrderType}>{orderBtnText}</OrderBtn>
</Container>
Expand All @@ -36,6 +49,11 @@ const StockOrderBtn = () => {

export default StockOrderBtn;

interface OwnProps {
orderVolume: number;
setOrderVolume: (orderVolume: number) => void;
}

const Container = styled.div``;

const AvailableMoney = styled.div<{ orderType: boolean }>`
Expand Down Expand Up @@ -67,7 +85,7 @@ const TotalAmount = styled.div`
align-items: center;
}
.totalAmountText01 {
.totalAmountText {
flex: 8 0 0;
}
Expand Down
12 changes: 8 additions & 4 deletions client/src/components/StockOrderSection/StockOrderSetting.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import useGetStockInfo from "../../hooks/useGetStockInfo";
import { orderTypeBuying, orderTypeSelling } from "../../reducer/StockOrderType-Reducer";
Expand All @@ -19,6 +20,8 @@ const StockOrderSetting = () => {
const companyId = useSelector((state: StateProps) => state.companyId);
const { stockInfo, stockInfoLoading, stockInfoError } = useGetStockInfo(companyId);

const [orderVolume, setOrderVolume] = useState(0);

if (stockInfoLoading) {
return <></>;
}
Expand All @@ -45,17 +48,18 @@ const StockOrderSetting = () => {
{orderType02}
</Selling>
</div>
<DecorationLine />
<OrderTypeChangeEffetLine />
<PriceSetting stockInfo={stockInfo.stockAsBiResponseDto} companyId={companyId} />
<VolumeSetting />
<StockOrderBtn />
<VolumeSetting orderVolume={orderVolume} setOrderVolume={setOrderVolume} />
<StockOrderBtn orderVolume={orderVolume} setOrderVolume={setOrderVolume} />
</Container>
);
};

export default StockOrderSetting;

const DecorationLine = () => {
// 매수/매도 탭 전환 시 하단에 시각화 되는 선
const OrderTypeChangeEffetLine = () => {
const stockOrderType = useSelector((state: StateProps) => state.stockOrderType);

return (
Expand Down
15 changes: 10 additions & 5 deletions client/src/components/StockOrderSection/StockPrice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { styled } from "styled-components";
import { setStockOrderPrice } from "../../reducer/StockOrderPrice-Reducer";
import { StateProps } from "../../models/stateProps";

const changeRateUnit = `%`;

const StockPrice = (props: StockPriceProps) => {
const { index, price, volume, totalSellingVolume, totalBuyingVolum } = props;

Expand Down Expand Up @@ -62,13 +64,16 @@ const StockPrice = (props: StockPriceProps) => {
}

// 전날 종가대비 매도/매수호가 변동률
const changeRate = `${(((price - previousDayStockClosingPrice) / previousDayStockClosingPrice) * 100).toFixed(2)}%`;
const changeRate = (((price - previousDayStockClosingPrice) / previousDayStockClosingPrice) * 100).toFixed(2);

return (
<Container index={index} ref={index === 9 ? ref : null} price={price} orderPrice={orderPrice} onClick={handleSetOrderPrice}>
<Price>
<Price changeRate={parseFloat(changeRate)}>
<div className="price">{price.toLocaleString()}</div>
<div className="changeRate">{changeRate}</div>
<div className="changeRate">
{changeRate}
{changeRateUnit}
</div>
</Price>
<Volume index={index}>
<div className="volume">{volume.toLocaleString()}</div>
Expand Down Expand Up @@ -118,7 +123,7 @@ const Container = styled.div<{ index: number; price: number; orderPrice: number
}
`;

const Price = styled.div`
const Price = styled.div<{ changeRate: number }>`
width: 50%;
display: flex;
padding-right: 11px;
Expand All @@ -134,7 +139,7 @@ const Price = styled.div`
.changeRate {
font-size: 12px;
font-weight: 400;
color: #e22926;
color: ${(props) => (props.changeRate > 0 ? "#ed2926" : props.changeRate === 0 ? "black" : "#3177d7")};
padding-top: 1px;
}
`;
Expand Down
59 changes: 37 additions & 22 deletions client/src/components/StockOrderSection/StockPriceList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { StateProps } from "../../models/stateProps";
import StockPrice from "./StockPrice";

const StockPriceList = () => {
const stockOrderType = useSelector((state: StateProps) => state.stockOrderType);
const companyId = useSelector((state: StateProps) => state.companyId);
const { stockInfo, stockInfoLoading, stockInfoError } = useGetStockInfo(companyId);

Expand Down Expand Up @@ -43,7 +44,7 @@ const StockPriceList = () => {
}

/*
[문제점] 주가 리스트 개수가 너무 적음 (매도호가 5개 + 매수호가 5개 = 총 10개) → 더미데이터를 추가하여 가격 리스트 확장 (매도 10개 + 매수 10개 = 총 20개)
[문제점] 주가 리스트 개수가 너무 적음 (매도호가 5개 + 매수호가 5개 = 총 10개) → UX를 저해하는 요소로 판단되어, 더미데이터를 추가 (매도/매수 각각 5개씩)
[해결방안] 1) fetching 해온 데이터 중 가격 0인 데이터 제외 (한국투자증권 API에서 간혹 보내는 경우 있음) → 호가 간격 계산 후, 더미 데이터 추가 (거래량은 0으로 설정)
*/
const existSellingPrice = sellingPrice.filter((selling) => selling.price !== 0);
Expand All @@ -70,20 +71,20 @@ const StockPriceList = () => {
}, 0);

return (
<Container>
<HighFigure>
<div className="price"></div>
<div className="volume"></div>
</HighFigure>
<Container orderType={stockOrderType}>
<div className="priceIndicator">
<div className="sellingPrice">매도호가</div>
<div className="sellingVolume">거래량</div>
</div>
<PriceList>
{sellingAndBuyingPrice.map((item, idx) => (
<StockPrice key={item.price} index={idx} price={item.price} volume={item.volume} totalSellingVolume={totalSellingVolume} totalBuyingVolum={totalBuyingVolum} />
))}
</PriceList>
<LowerFigure>
<div className="price"></div>
<div className="volume"></div>
</LowerFigure>
<div className="priceIndicator">
<div className="buyingPrice">매수호가</div>
<div className="buyingVolume">거래량</div>
</div>
</Container>
);
};
Expand All @@ -97,31 +98,45 @@ interface PriceProps {
}

// component 생성
const Container = styled.div`
const Container = styled.div<{ orderType: boolean }>`
width: 40%;
height: 100%;
margin-right: 16px;
`;
const HighFigure = styled.div`
width: 100%;
height: 32px;
border-bottom: 1px solid black;
.priceIndicator {
display: flex;
flex-direction: row;
width: 100%;
height: 32px;
font-size: 13px;
padding-left: 15px;
& div {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.sellingPrice,
.sellingVolume {
color: ${(props) => (props.orderType ? "#9999" : "#e22926")};
}
.buyingPrice,
.buyingVolume {
color: ${(props) => (props.orderType ? "#2679ed" : "#9999")};
}
}
`;

const PriceList = styled.ul`
width: 100%;
height: 348px;
padding: 0px;
border-bottom: 1px solid black;
overflow-y: scroll;
&::-webkit-scrollbar {
display: none;
}
`;

const LowerFigure = styled.div`
width: 100%;
height: 32px;
`;
Loading

0 comments on commit db99234

Please sign in to comment.