Skip to content

Commit

Permalink
[Feat] 주가리스트 창에 렌더링 되는 매도/매수호가 리스트 확장
Browse files Browse the repository at this point in the history
- 주식주문 창 주가리스트의 매도/매수호가 개수가 너무 적다고 판단됨 (매도호가 5개 + 매수호가 5개 = 총 10개)
- UX를 저해하는 요소라고 판단하여 fetching 해온 실제 호가를 바탕으로 약간의 더미 데이터 추가해주는 로직 생성
- 호가 간 가격차이 계산 후 매도/매수호가 더미데이터 각각 5개씩 추가하여 총 20개로 확장
- 더미 데이터로 설정한 가격으로는 거래가 불가하도록 설정해야하니, 더미로 추가한 호가 거래량은 0으로 설정 (선택해도 거래가 이루어지지 않음을 유저에게 인식)

Issues #17
  • Loading branch information
novice1993 committed Sep 9, 2023
1 parent d1e2375 commit 066327d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 20 deletions.
33 changes: 16 additions & 17 deletions client/src/components/StockOrderSection/StockPrice.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import useGetStockData from "../../hooks/useGetStockData";
import { StockProps } from "../../models/stockProps";

import { useState, useEffect } from "react";
import { useState, useEffect, useRef } from "react";
import { useSelector, useDispatch } from "react-redux";
import { styled } from "styled-components";
import { setStockOrderPrice } from "../../reducer/StockOrderPrice-Reducer";
Expand All @@ -15,11 +15,20 @@ const StockPrice = (props: StockPriceProps) => {

const dispatch = useDispatch();
const orderPrice = useSelector((state: StateProps) => state.stockOrderPrice);
const ref = useRef<HTMLDivElement | null>(null);

const handleSetOrderPrice = () => {
dispatch(setStockOrderPrice(price));
};

// 가격 리스트 중 10번째 순서인 요소가 화면 렌더링 시 정중앙에 오도록 설정
useEffect(() => {
if (!stockPriceLoading && !stockPriceError) {
ref.current?.focus();
ref.current?.scrollIntoView({ behavior: "smooth", block: "center" });
}
}, [stockPrice]);

if (stockPriceLoading) {
return <></>;
}
Expand Down Expand Up @@ -56,7 +65,7 @@ const StockPrice = (props: StockPriceProps) => {
const changeRate = `${(((price - previousDayStockClosingPrice) / previousDayStockClosingPrice) * 100).toFixed(2)}%`;

return (
<Container index={index} price={price} orderPrice={orderPrice} onClick={handleSetOrderPrice}>
<Container index={index} ref={index === 9 ? ref : null} price={price} orderPrice={orderPrice} onClick={handleSetOrderPrice}>
<Price>
<div className="price">{price.toLocaleString()}</div>
<div className="changeRate">{changeRate}</div>
Expand All @@ -77,7 +86,7 @@ const VolumePercentge = (props: { index: number; volume: number; upperPriceVolum
const [width, setWidth] = useState(0);

useEffect(() => {
setWidth((volume / (index < 5 ? upperPriceVolumeSum : lowerPriceVolumeSum)) * 100);
setWidth((volume / (index < 10 ? upperPriceVolumeSum : lowerPriceVolumeSum)) * 100);
}, [volume]);

return <StockVolumePercentge index={index} volume={volume} upperPriceVolumeSum={upperPriceVolumeSum} lowerPriceVolumeSum={lowerPriceVolumeSum} style={{ width: `${width}%` }} />;
Expand All @@ -97,9 +106,9 @@ const Container = styled.div<{ index: number; price: number; orderPrice: number
width: 100%;
height: 36px;
margin-bottom: 2px;
background-color: ${(props) => (props.index > 4 ? "#FDE8E7" : "#E7F0FD")};
background-color: ${(props) => (props.index > 9 ? "#FDE8E7" : "#E7F0FD")};
border: ${(props) => (props.price === props.orderPrice ? "1.5px solid #2F4F4F" : "none")};
border-left: ${(props) => (props.price === props.orderPrice ? "3px solid red" : props.index > 4 ? "3px solid #FDE8E7" : "3px solid #E7F0FD")};
border-left: ${(props) => (props.price === props.orderPrice ? "3px solid red" : props.index > 9 ? "3px solid #FDE8E7" : "3px solid #E7F0FD")};
display: flex;
flex-direction: row;
transition: border 1s ease;
Expand Down Expand Up @@ -137,7 +146,7 @@ const Volume = styled.div<{ index: number }>`
justify-content: space-between;
align-items: flex-end;
font-size: 12px;
color: ${(props) => (props.index < 5 ? "#2679ed" : "#e22926")};
color: ${(props) => (props.index < 10 ? "#2679ed" : "#e22926")};
.volume {
height: 100%;
Expand All @@ -149,16 +158,6 @@ const Volume = styled.div<{ index: number }>`

const StockVolumePercentge = styled.span<{ index: number; volume: number; upperPriceVolumeSum: number; lowerPriceVolumeSum: number }>`
height: 2px;
background-color: ${(props) => (props.index < 5 ? "#2679ed" : "#e22926")};
background-color: ${(props) => (props.index < 10 ? "#2679ed" : "#e22926")};
transition: width 0.5s ease;
`;

// 🔴 보류
// ref 생성 코드
// const ref = useRef<HTMLDivElement | null>(null);

// ref 지정 요소 -> 렌더링 시 화면 정중앙에 배치
// useEffect(() => {
// ref.current?.focus();
// ref.current?.scrollIntoView({ behavior: "smooth", block: "center" });
// }, []);
24 changes: 21 additions & 3 deletions client/src/components/StockOrderSection/StockPriceList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,30 @@ const StockPriceList = () => {
buyingPrice.push(buyingInfo);
}

/*
[문제점] 주가 리스트 개수가 너무 적음 (매도호가 5개 + 매수호가 5개 = 총 10개) → 더미데이터를 추가하여 가격 리스트 확장 (매도 10개 + 매수 10개 = 총 20개)
[해결방안] 1) fetching 해온 데이터 중 가격 0인 데이터 제외 (한국투자증권 API에서 간혹 보내는 경우 있음) → 호가 간격 계산 후, 더미 데이터 추가 (거래량은 0으로 설정)
*/
const existSellingPrice = sellingPrice.filter((selling) => selling.price !== 0);
const existBuyingPrice = buyingPrice.filter((buyingPrice) => buyingPrice.price !== 0);
const priceInterval: number = existSellingPrice[existSellingPrice.length - 1].price - existBuyingPrice[0].price;

for (let i = 0; existSellingPrice.length < 10; i++) {
const dummySellingData = { price: existSellingPrice[0].price + priceInterval, volume: 0 };
existSellingPrice.unshift(dummySellingData);
}

for (let i = 0; existBuyingPrice.length < 10; i++) {
const dummyBuyingData = { price: existBuyingPrice[existBuyingPrice.length - 1].price - priceInterval, volume: 0 };
existBuyingPrice.push(dummyBuyingData);
}

// 1) 매도/매수호가 종합 2) 매수/매도호가 거래량 종합
const sellingAndBuyingPrice = [...sellingPrice, ...buyingPrice];
const totalSellingVolume = sellingPrice.reduce((acc, cur) => {
const sellingAndBuyingPrice = [...existSellingPrice, ...existBuyingPrice];
const totalSellingVolume = existSellingPrice.reduce((acc, cur) => {
return (acc = acc + cur.volume);
}, 0);
const totalBuyingVolum = buyingPrice.reduce((acc, cur) => {
const totalBuyingVolum = existBuyingPrice.reduce((acc, cur) => {
return (acc = acc + cur.volume);
}, 0);

Expand Down

0 comments on commit 066327d

Please sign in to comment.