Skip to content

Commit

Permalink
[Feat] 보유현금 및 최대 매도가능 수량 설정 관련 기능 구현
Browse files Browse the repository at this point in the history
- 주식주문 시 필요한 회원별 보유현금 데이터 렌더링 및 처리 가능
- 매도 거래 관련 최대 거래량 설정 시 현재 각 회원이 보유한 회사별 주식만큼만 설정할 수 있도록 설정 (보유 주식 중 거래량이 없어 거래대기로 분류된 주식 수도 차감)

Issues #17
  • Loading branch information
novice1993 committed Sep 13, 2023
1 parent 97b5a6b commit 015e94d
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 24 deletions.
2 changes: 2 additions & 0 deletions client/src/components/CentralChartMenu/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import CompareChartBtn from "./CompareChartBtn";
const UpperMenuBar = () => {
const companyId = useSelector((state: StateProps) => state.companyId);

console.log(localStorage.getItem("authToken"));

return (
<Container>
<div className="FirstLine">
Expand Down
24 changes: 17 additions & 7 deletions client/src/components/StockOrderSection/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { useSelector, useDispatch } from "react-redux";
import { styled } from "styled-components";
import useGetStockInfo from "../../hooks/useGetStockInfo";
import useGetStockData from "../../hooks/useGetStockData";
import useGetCash from "../../hooks/useGetCash";
import useGetStockOrderRecord from "../../hooks/useGetStockOrderRecord";
import useGetHoldingStock from "../../hooks/useGetHoldingStock";
import { stockOrderClose } from "../../reducer/StockOrderSet-Reducer";
import { StateProps } from "../../models/stateProps";
import StockOrder from "./StockOrder";
Expand All @@ -27,19 +30,26 @@ const StockOrderSection = () => {

const { stockInfo, stockInfoLoading, stockInfoError } = useGetStockInfo(companyId);
const { stockPrice, stockPriceLoading, stockPriceError } = useGetStockData(companyId);
const { cashLoading, cashError } = useGetCash();
const { orderRecordLoading, orderRecordError } = useGetStockOrderRecord();
const { holdingStockLoading, holdingStockError } = useGetHoldingStock();

// 주식주문 창 닫기
const handleStockOrderClose = () => {
dispatch(stockOrderClose());
};
// fetching 데이터 loading, error 여부
const isLoading = stockInfoLoading || stockPriceLoading || cashLoading || orderRecordLoading || holdingStockLoading;
const isError = stockInfoError || stockPriceError || cashError || orderRecordError || holdingStockError;

// 1) 데이터 로딩 중
if (stockInfoLoading || stockPriceLoading) {
if (isLoading) {
return <Container orderSet={stockOrderSet}>로딩 중</Container>;
}

// 2) 데이터 받아오기 실패 + 성공했으나 빈 데이터일 때
if (stockInfoError || stockPriceError || stockPrice.length === 0) {
// 주식주문 창 닫기
const handleStockOrderClose = () => {
dispatch(stockOrderClose());
};

// 2) 데이터 받아오기 실패 or 성공했으나 빈 데이터일 때
if (isError || stockPrice.length === 0) {
return (
<Container orderSet={stockOrderSet}>
<div className="ErrorContainer">
Expand Down
9 changes: 5 additions & 4 deletions client/src/components/StockOrderSection/OrderDecisionBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { styled } from "styled-components";
import useGetCash from "../../hooks/useGetCash";
import { StateProps } from "../../models/stateProps";
import { OrderTypeProps } from "../../models/orderTypeProps";
import { setStockOrderVolume } from "../../reducer/StockOrderVolume-Reducer";
Expand All @@ -11,10 +12,10 @@ const availableMoneyText02: string = "원";
const totalAmountText: string = "주문총액";
const totalAmountUnit: string = "원";

// dummyData
const dummyMoney = 10000000;

const OrderDecisionBtn = () => {
const { cashData } = useGetCash();
const cash = cashData.toLocaleString();

const dispatch = useDispatch();
const orderType = useSelector((state: StateProps) => state.stockOrderType);
const orderPrice = useSelector((state: StateProps) => state.stockOrderPrice);
Expand All @@ -40,7 +41,7 @@ const OrderDecisionBtn = () => {
<div className="container">
<AvailableMoney orderType={orderType}>
<span>{availableMoneyText01}</span>
<span className="availableMoney">{dummyMoney.toLocaleString()}</span>
<span className="availableMoney">{cash}</span>
<span>{availableMoneyText02}</span>
</AvailableMoney>
<TotalAmount>
Expand Down
32 changes: 24 additions & 8 deletions client/src/components/StockOrderSection/VolumeSetteing.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { styled } from "styled-components";
import useGetCash from "../../hooks/useGetCash";
import useGetHoldingStock from "../../hooks/useGetHoldingStock";
import useGetStockOrderRecord from "../../hooks/useGetStockOrderRecord";
import { StateProps } from "../../models/stateProps";
import { HoldingStockProps } from "../../models/stockProps";
import { OrderRecordProps } from "../../models/stockProps";
import { setStockOrderVolume, plusStockOrderVolume, minusStockOrderVolume } from "../../reducer/StockOrderVolume-Reducer";

const volumeSettingTitle: string = "수량";
Expand All @@ -14,17 +19,28 @@ const volumPercentage03: number = 50;
const volumPercentage04: number = 100;
const percentageUnit: string = "%";

// dummyData
const dummyMoney: number = 10000000;
const dummyholdingStock = 10;

const VolumeSetting = () => {
const dispatch = useDispatch();
const companyId = useSelector((state: StateProps) => state.companyId);
const orderType = useSelector((state: StateProps) => state.stockOrderType);
const orderPrice = useSelector((state: StateProps) => state.stockOrderPrice);
const orderVolume = useSelector((state: StateProps) => state.stockOrderVolume);

const maximumBuyingVolume = orderPrice !== 0 ? Math.trunc(dummyMoney / orderPrice) : Math.trunc(dummyMoney / 1);
// 거래가능 주식 수 = 보유 주식 수 - 매도 대기 중인 주식 수
let avaiableSellingStock: number = 0;

const { cashData } = useGetCash();
const { holdingStockData } = useGetHoldingStock();
const { orderRecordData } = useGetStockOrderRecord();
const holdingCompanyStock = holdingStockData.filter((stock: HoldingStockProps) => stock.companyId === companyId);

const maximumBuyingVolume = orderPrice !== 0 ? Math.trunc(cashData / orderPrice) : Math.trunc(cashData / 1);

// 해당 company 보유 주식이 0이 아닐 때
if (holdingCompanyStock.length !== 0) {
const waitingForSaleStock = orderRecordData.filter((stock: OrderRecordProps) => stock.companyId === companyId && stock.orderTypes === "SELL" && stock.orderStates === "ORDER_WAIT");
avaiableSellingStock = holdingCompanyStock[0].stockCount - waitingForSaleStock.length;
}

const handlePlusOrderVolume = () => {
// 매수 -> 증가 버튼 클릭 시, 최대 구매수량 보다 낮으면 개수 1증가
Expand All @@ -33,7 +49,7 @@ const VolumeSetting = () => {
}
// 매도 -> 증가 버튼 클릭 시, 보유 주식수량 보다 낮으면 개수 1증가
if (orderType) {
orderVolume < dummyholdingStock && dispatch(plusStockOrderVolume());
orderVolume < avaiableSellingStock && dispatch(plusStockOrderVolume());
}
};

Expand Down Expand Up @@ -81,7 +97,7 @@ const VolumeSetting = () => {

// 매도 -> percentage 버튼 클릭 시, 보유 주식수량 내에서 계산
if (orderType) {
const orderVolume = Math.trunc(dummyholdingStock * (volumePerentage / 100));
const orderVolume = Math.trunc(avaiableSellingStock * (volumePerentage / 100));
dispatch(setStockOrderVolume(orderVolume));
}
};
Expand All @@ -99,7 +115,7 @@ const VolumeSetting = () => {
<div className="Title">{volumeSettingTitle}</div>
<div className="MaximumVolumeContainer">
<span>{maximumVolumeText01}</span>
<span className="maximumVolume">{orderType ? dummyholdingStock : maximumBuyingVolume}</span>
<span className="maximumVolume">{orderType ? avaiableSellingStock : maximumBuyingVolume}</span>
<span>{volumeUnit}</span>
</div>
</TitleContainer>
Expand Down
32 changes: 32 additions & 0 deletions client/src/hooks/useGetCash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useQuery } from "react-query";
import { useSelector } from "react-redux";
import axios from "axios";
import { StateProps } from "../models/stateProps";

// 🔴 API 수정 전으로 임시 파라미터 설정해놓음
const url = "http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/cash/3";

const useGetCash = () => {
const isLogin = useSelector((state: StateProps) => state.login);
const { data, isLoading, isError } = useQuery("cash", getCashData, {
enabled: isLogin === 1,
});

return { cashData: data, cashLoading: isLoading, cashError: isError };
};

export default useGetCash;

const getCashData = async () => {
const token = localStorage.getItem("authToken");
const options = {
headers: {
Authorization: `${token}`,
"Content-Type": "application/json",
},
};

const response = await axios.get(url, options);
const cash = await response.data.money;
return cash;
};
30 changes: 30 additions & 0 deletions client/src/hooks/useGetHoldingStock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useQuery } from "react-query";
import { useSelector } from "react-redux";
import axios from "axios";
import { StateProps } from "../models/stateProps";

const url = "http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/stock/stockholds";

const useGetHoldingStock = () => {
const isLogin = useSelector((state: StateProps) => state.login);
const { data, isLoading, isError } = useQuery("holdingStock", getHoldingStock, {
enabled: isLogin === 1,
});
return { holdingStockData: data, holdingStockLoading: isLoading, holdingStockError: isError };
};

export default useGetHoldingStock;

const getHoldingStock = async () => {
const authToken = localStorage.getItem("authToken");
const options = {
headers: {
Authorization: `${authToken}`,
"Content-Type": "application/json",
},
};

const response = await axios.get(url, options);
const holdingStock = await response.data;
return holdingStock;
};
31 changes: 31 additions & 0 deletions client/src/hooks/useGetStockOrderRecord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useQuery } from "react-query";
import { useSelector } from "react-redux";
import axios from "axios";
import { StateProps } from "../models/stateProps";

const url = "http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/stock/stockorders";

const useGetStockOrderRecord = () => {
const isLogin = useSelector((state: StateProps) => state.login);
const { data, isLoading, isError } = useQuery("record", getOrderRecord, {
enabled: isLogin === 1,
});

return { orderRecordData: data, orderRecordLoading: isLoading, orderRecordError: isError };
};

export default useGetStockOrderRecord;

const getOrderRecord = async () => {
const authToken = localStorage.getItem("authToken");
const options = {
headers: {
Authorization: `${authToken}`,
"Content-Type": "application/json",
},
};

const response = await axios.get(url, options);
const orderRecord = await response.data;
return orderRecord;
};
20 changes: 20 additions & 0 deletions client/src/models/stockProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,23 @@ export interface StockProps {
stck_hgpr: string;
stck_lwpr: string;
}

export interface HoldingStockProps {
companyId: number;
companyKorName: string;
memberId: number;
percentage: number;
price: number;
stockCount: number;
stockHoldId: number;
}

export interface OrderRecordProps {
companyId: number;
memberId: number;
orderStates: string;
orderTypes: string;
price: number;
stockCount: number;
stockOrderId: number;
}
10 changes: 5 additions & 5 deletions client/src/page/MainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { TabContainerPage } from "./TabPages/TabContainerPage";

// 🔴 로그아웃 관련 action 함수
import { setLogoutState } from "../reducer/member/loginSlice";
import { setLoginState } from "../reducer/member/loginSlice";

const MainPage = () => {
const expandScreen = useSelector((state: StateProps) => state.expandScreen);
Expand Down Expand Up @@ -98,11 +97,12 @@ const MainPage = () => {
const [isLoggedIn, setIsLoggedIn] = useState(false); // 로그인 상태 관리

useEffect(() => {
const authToken = localStorage.getItem("authToken");
// const authToken = localStorage.getItem("authToken");

if (authToken !== null) {
dispatch(setLoginState());
}
// if (authToken !== null) {
// dispatch(setLoginState());
// }
localStorage.removeItem("authToken");
}, []);

//프로필 모달 열고닫는 매커니즘
Expand Down

0 comments on commit 015e94d

Please sign in to comment.