diff --git a/src/components/Feed/FeedDetail.jsx b/src/components/Feed/FeedDetail.jsx
new file mode 100644
index 0000000..0dd645b
--- /dev/null
+++ b/src/components/Feed/FeedDetail.jsx
@@ -0,0 +1,31 @@
+import React from "react";
+import FeedBoard from "./FeedShow/FeedBoard";
+import * as S from "../../style/GlobalStyle";
+import styled from "styled-components";
+
+const FeedDetail = ({ setShowDetail }) => {
+ console.log("detail");
+ return (
+
+
+ setShowDetail(false)}
+ src="/icon/X.svg"
+ alt="x"
+ />
+
+
+
+ );
+};
+
+const BtnDiv = styled.div`
+ display: flex;
+ background-color: white;
+`;
+
+const CloseButton = styled.img`
+ margin: 10px 10px 10px auto;
+`;
+
+export default FeedDetail;
diff --git a/src/components/Feed/FeedShow/Feed.jsx b/src/components/Feed/FeedShow/Feed.jsx
new file mode 100644
index 0000000..38eee56
--- /dev/null
+++ b/src/components/Feed/FeedShow/Feed.jsx
@@ -0,0 +1,74 @@
+import React, { useEffect, useState } from "react";
+import FeedBoard from "./FeedBoard";
+import FeedOrder from "./FeedOrder";
+import FeedReturns from "./FeedReturns";
+import FeedVoteNot from "./FeedVoteNot";
+import FeedVoteYes from "./FeedVoteYes";
+import FeedDetail from "../FeedDetail";
+import styled from "styled-components";
+import { fetchAllFeed } from "../../../store/reducers/Feed/feed";
+import { useDispatch, useSelector } from "react-redux";
+
+const Feed = () => {
+ const [showDetail, setShowDetail] = useState(false);
+ const toggleDetail = () => {
+ setShowDetail(true);
+ };
+
+ useEffect(() => {
+ setShowDetail(false);
+ dispatch(fetchAllFeed());
+ }, []);
+ console.log(showDetail);
+
+ const dispatch = useDispatch();
+ const allFeedData = useSelector((state) => state.feed.allFeed);
+ console.log("allFeedData", allFeedData);
+ return (
+ <>
+ {allFeedData.map((item, idx) => {
+ console.log("item", item);
+ return (
+
+ {item.isOrder ? (
+
+ ) : item.isProfit ? (
+
+ ) : item.isVote && item.myVote ? (
+
+ ) : item.isVote ? (
+
+ ) : (
+
+ )}
+
+ );
+ })}
+
+
+ {showDetail ? (
+ <>
+
+ >
+ ) : (
+ <>>
+ )}
+
+ >
+ );
+};
+
+const DetailContainer = styled.div`
+ width: 400px;
+ height: 100%;
+ background-color: #fff;
+ transform: translateX(${(props) => (props.$showdetail ? "0" : "100%")});
+ transition: transform 0.3s ease;
+ position: absolute;
+ top: 0;
+ left: 0;
+ overflow: hidden;
+ z-index: 999;
+`;
+
+export default Feed;
diff --git a/src/components/Feed/FeedShow/FeedBoard.jsx b/src/components/Feed/FeedShow/FeedBoard.jsx
new file mode 100644
index 0000000..9af8833
--- /dev/null
+++ b/src/components/Feed/FeedShow/FeedBoard.jsx
@@ -0,0 +1,52 @@
+import React from "react";
+import styled from "styled-components";
+import * as S from "../../../style/GlobalStyle";
+
+const FeedBoard = ({ item, toggleDetail }) => {
+ console.log("board", item);
+ return (
+ <>
+
+
+ {item.user.nickname}
+ {item.createdAt}
+
+
+ {item.body}
+ {item.photoUrl ? (
+
+
+
+ ) : (
+ <>>
+ )}
+
+
+
+
+ {item.like}
+
+
+
+ 7
+
+
+
+ >
+ );
+};
+
+const Img = styled.img`
+ width: 100%;
+ /* object-fit: cover; */
+`;
+
+export default FeedBoard;
diff --git a/src/components/Feed/FeedShow/FeedOrder.jsx b/src/components/Feed/FeedShow/FeedOrder.jsx
new file mode 100644
index 0000000..674040e
--- /dev/null
+++ b/src/components/Feed/FeedShow/FeedOrder.jsx
@@ -0,0 +1,98 @@
+import React from "react";
+import styled from "styled-components";
+import * as S from "../../../style/GlobalStyle";
+
+//TODO : 로고 사진 변경
+import default_Img from "/icon/+.svg";
+const FeedOrder = ({ item }) => {
+ console.log("order", item);
+ const getLogoFileName = (name, code) => {
+ if (name.includes("스팩")) {
+ return "SPAC_230706";
+ } else if (name.includes("ETN")) {
+ return "ETN_230706";
+ } else if (
+ name.includes("KODEX") ||
+ name.includes("KOSEF") ||
+ name.includes("KoAct") ||
+ name.includes("TIGER") ||
+ name.includes("ACE") ||
+ name.includes("ARIRANG") ||
+ name.includes("합성 H") ||
+ name.includes("HANARO") ||
+ name.includes("SOL")
+ ) {
+ return "ETF_230706";
+ } else {
+ return `kr/${code}`;
+ }
+ };
+
+ const onErrorImg = (e) => {
+ e.target.src = default_Img;
+ };
+ return (
+ <>
+
+
+ {item.user.nickname}
+ {item.createdAt}
+
+
+
+
+
+ 삼성생명
+ 10주
+ 매수
+
+
+
+
+
+
+ {item.like}
+
+
+
+ 7
+
+
+
+ >
+ );
+};
+
+const QuantityDiv = styled.div`
+ margin-left: 7px;
+ color: #000;
+ font-size: 16px;
+ font-weight: 500;
+`;
+
+const OrderDiv = styled.div`
+ margin-left: 7px;
+ color: #000;
+ font-size: 16px;
+ font-weight: 500;
+`;
+
+export default FeedOrder;
diff --git a/src/components/Feed/FeedShow/FeedReturns.jsx b/src/components/Feed/FeedShow/FeedReturns.jsx
new file mode 100644
index 0000000..b5c2620
--- /dev/null
+++ b/src/components/Feed/FeedShow/FeedReturns.jsx
@@ -0,0 +1,51 @@
+import React from "react";
+import styled from "styled-components";
+import * as S from "../../../style/GlobalStyle";
+
+const FeedReturns = ({ item }) => {
+ console.log("profit", item);
+ return (
+ <>
+
+
+ {item.user.nickname}
+ {item.createdAt}
+
+
+
+
+ 나의 전체 수익률은?
+ {item.profit}
+
+
+
+
+
+
+ {item.like}
+
+
+
+ 7
+
+
+
+ >
+ );
+};
+
+const ReturnDiv = styled.div`
+ margin-left: auto;
+ color: ${(props) =>
+ parseFloat(props.$returns) >= 0 ? "#ee2f2a" : "#2679ed"};
+`;
+
+export default FeedReturns;
diff --git a/src/components/Feed/FeedShow/FeedVoteNot.jsx b/src/components/Feed/FeedShow/FeedVoteNot.jsx
new file mode 100644
index 0000000..655ad21
--- /dev/null
+++ b/src/components/Feed/FeedShow/FeedVoteNot.jsx
@@ -0,0 +1,55 @@
+import React from "react";
+import styled from "styled-components";
+import * as S from "../../../style/GlobalStyle";
+
+const FeedVoteNot = ({ item }) => {
+ console.log("votenot", item);
+ return (
+ <>
+
+
+ {item.user.nickname}
+ {item.createdAt}
+
+
+
+ {item.body}
+
+
+ O
+
+
+ X
+
+
+
+
+
+ >
+ );
+};
+
+const ButtonWrapper = styled.div`
+ display: flex;
+ gap: 30px;
+ margin-bottom: 25px;
+ margin-top: 5px;
+`;
+
+const VoteBtn = styled.button`
+ width: 150px;
+ height: 44px;
+ border: none;
+ border-radius: 10px;
+ background: ${(props) => props.color};
+
+ color: #fff;
+ font-size: 25px;
+ font-weight: 600;
+
+ &:hover {
+ background: ${(props) => props.$hover};
+ }
+`;
+
+export default FeedVoteNot;
diff --git a/src/components/Feed/FeedShow/FeedVoteYes.jsx b/src/components/Feed/FeedShow/FeedVoteYes.jsx
new file mode 100644
index 0000000..bf8dda2
--- /dev/null
+++ b/src/components/Feed/FeedShow/FeedVoteYes.jsx
@@ -0,0 +1,79 @@
+import React from "react";
+import styled from "styled-components";
+import * as S from "../../../style/GlobalStyle";
+
+const FeedVoteYes = ({ item }) => {
+ console.log("voteyes", item);
+ const calc = (num) => {
+ return Math.round((num / (item.vote.yes + item.vote.no)) * 100);
+ };
+ return (
+ <>
+
+
+ {item.user.nickname}
+ {item.createdAt}
+
+
+
+ {item.body}
+
+
+ O
+ {calc(item.vote.yes)}%
+
+
+
+
+
+
+ X
+ {calc(item.vote.no)}%
+
+
+
+
+
+ >
+ );
+};
+
+const BarDiv = styled.div`
+ position: relative;
+ width: 250px;
+ height: 30px;
+`;
+
+const ODiv = styled.div`
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: ${(props) => props.$width}%;
+ height: 30px;
+ border-radius: 10px 0px 0px 10px;
+ background: #bee4ff;
+`;
+
+const XDiv = styled.div`
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: ${(props) => props.$width}%;
+ height: 30px;
+ border-radius: 0px 10px 10px 0px;
+ background: #ffe3d7;
+`;
+
+const OXWrapper = styled.div`
+ display: flex;
+ gap: 10px;
+ margin-bottom: 25px;
+ margin-top: 5px;
+`;
+
+const OXDiv = styled.div`
+ text-align: center;
+ font-size: 15px;
+`;
+
+export default FeedVoteYes;
diff --git a/src/lib/apis/api.jsx b/src/lib/apis/api.jsx
index ae786db..d53f757 100644
--- a/src/lib/apis/api.jsx
+++ b/src/lib/apis/api.jsx
@@ -22,3 +22,10 @@ export const baseUserInstance = axios.create({
},
});
+export const formdataInstance = axios.create({
+ baseURL: BASE_URL,
+ headers: {
+ "Content-Type": "multipart/form-data",
+ Authorization: `Bearer ${getCookie("token")}`,
+ },
+});
diff --git a/src/lib/apis/feed.jsx b/src/lib/apis/feed.jsx
new file mode 100644
index 0000000..8c9074f
--- /dev/null
+++ b/src/lib/apis/feed.jsx
@@ -0,0 +1,60 @@
+import { baseUserInstance, formdataInstance } from "./api";
+
+export const fetchAFeed = async (feedId) => {
+ const baseUrl = `/feed/${feedId}`;
+ try {
+ const response = await baseUserInstance.get(baseUrl);
+ const data = response.data;
+ return data;
+ } catch (err) {
+ console.error(err);
+ }
+};
+
+export const fetchMyFeed = async (userId) => {
+ const baseUrl = `/feed/user/${userId}`;
+ try {
+ const response = await baseUserInstance.get(baseUrl);
+ const data = response.data;
+ return data;
+ } catch (err) {
+ console.error(err);
+ }
+};
+
+export const fetchAllFeed = async () => {
+ const baseUrl = `/feed`;
+ try {
+ const response = await baseUserInstance.get(baseUrl);
+ const data = response.data;
+ return data;
+ } catch (err) {
+ console.error(err);
+ }
+};
+
+export const postBoardFeed = async (formData) => {
+ const baseUrl = "/feed";
+ try {
+ const response = await formdataInstance.post(baseUrl, formData);
+ const data = response.data;
+ console.log(data);
+ return data;
+ } catch (err) {
+ console.error(err);
+ }
+};
+
+export const postVoteFeed = async (body) => {
+ const baseUrl = "/feed/vote";
+ try {
+ const response = await baseUserInstance.post(baseUrl, {
+ body,
+ });
+ const data = response.data;
+ console.log(data);
+ return data;
+ } catch (err) {
+ console.error(err);
+ }
+};
diff --git a/src/routes/Feed/FeedPage.jsx b/src/routes/Feed/FeedPage.jsx
index f2b34f7..c0613f0 100644
--- a/src/routes/Feed/FeedPage.jsx
+++ b/src/routes/Feed/FeedPage.jsx
@@ -1,9 +1,9 @@
import React, { useState } from "react";
import styled from "styled-components";
-import FeedWriting from "../../components/Feed/FeedWriting";
+import * as S from "../../style/GlobalStyle";
-//TODO : 로고 사진 변경
-import default_Img from "/icon/+.svg";
+import FeedWriting from "~/components/Feed/FeedWriting";
+import Feed from "../../components/Feed/FeedShow/Feed";
const FeedPage = () => {
const [isWrite, setIsWrite] = useState(false);
@@ -12,33 +12,8 @@ const FeedPage = () => {
setIsWrite(true);
};
- const getLogoFileName = (name, code) => {
- if (name.includes("스팩")) {
- return "SPAC_230706";
- } else if (name.includes("ETN")) {
- return "ETN_230706";
- } else if (
- name.includes("KODEX") ||
- name.includes("KOSEF") ||
- name.includes("KoAct") ||
- name.includes("TIGER") ||
- name.includes("ACE") ||
- name.includes("ARIRANG") ||
- name.includes("합성 H") ||
- name.includes("HANARO") ||
- name.includes("SOL")
- ) {
- return "ETF_230706";
- } else {
- return `kr/${code}`;
- }
- };
-
- const onErrorImg = (e) => {
- e.target.src = default_Img;
- };
return (
-
+
{isWrite ? (
) : (
@@ -48,168 +23,12 @@ const FeedPage = () => {
)}
-
-
- 게시글 쓰는 미나리
- 2024.03.08
-
-
-
- 저번주 공시인데 괜찮아 보이네요! 시가배당률도 매년 올라가고 있어서
- 눈여겨 보는 중입니다.
-
-
-
-
-
-
- 3
-
-
-
- 7
-
-
-
-
-
- 매수한 미나리
- 2024.03.08
-
-
-
-
- 삼성생명
- 10주
- 매수
-
-
-
-
-
- 3
-
-
-
- 7
-
-
-
-
-
- 수익률 공유한 미나리
- 2024.03.08
-
-
-
- 나의 전체 수익률은?
- 0.01%
-
-
-
-
-
- 3
-
-
-
- 7
-
-
-
-
-
- 투표 아직 안 한 미나리
- 2024.03.08
-
-
-
- 티웨이 항공 vs 에어부산, 에어부산이 더 오른다
-
-
-
- O
-
-
- X
-
-
-
-
-
-
- 투표한 미나리
- 2024.03.08
-
-
-
- 티웨이 항공 vs 에어부산, 에어부산이 더 오른다
-
-
-
- O
- 32%
-
-
-
-
-
-
- X
- 68%
-
-
-
-
+
-
+
);
};
-const Container = styled.div`
- display: flex;
- flex-direction: column;
- width: 400px;
- height: 100%;
- position: relative;
- overflow: hidden;
- background-color: #f3f3f3;
-`;
-
const WritingContainer = styled.div`
display: flex;
flex-direction: row;
@@ -249,169 +68,4 @@ const FeedContainer = styled.div`
}
`;
-const FeedWrapper = styled.div`
- display: flex;
- flex-direction: column;
- background-color: white;
- margin-bottom: 5px;
-`;
-
-const UserDiv = styled.div`
- margin: 20px 25px 0px 25px;
-`;
-
-const UserNickname = styled.div`
- font-size: 16px;
- font-weight: 600;
- line-height: normal;
- margin-bottom: 5px;
-`;
-
-const DateDiv = styled.div`
- color: #c1c1c1;
- font-size: 13px;
- font-style: normal;
- font-weight: 600;
- line-height: normal;
-`;
-
-const BodyWrapper = styled.div`
- display: flex;
- flex-direction: column;
- align-items: center;
- margin: 15px 25px 0px 25px;
-`;
-
-const BodyDiv = styled.div`
- margin-bottom: 15px;
- font-weight: ${(props) => props.$weight || "400"};
-`;
-
-const Img = styled.img`
- width: 100%;
- /* object-fit: cover; */
-`;
-
-const BottomWrapper = styled.div`
- display: flex;
- margin: 20px 25px 0px 25px;
- padding: 15px 0px;
- border-top: 1px solid #dadada;
- gap: 20px;
-`;
-
-const IconDiv = styled.div`
- display: flex;
- align-items: center;
-`;
-
-const Div = styled.div``;
-
-const StockWrapper = styled.div`
- display: flex;
- flex-direction: row;
- align-items: center;
- width: 95%;
- padding: 11px 22px;
- border-radius: 10px;
- background-color: ${(props) =>
- props.$buy === "sell"
- ? "#FFE3D7"
- : props.$buy === "returns"
- ? "#EFEFEF"
- : "#BEE4FF"};
-`;
-
-const StockDiv = styled.div`
- margin-left: ${(props) => props.$margin || "10px"};
- color: #000;
- font-size: 18px;
- font-style: normal;
- font-weight: 600;
- line-height: normal;
-`;
-
-const QuantityDiv = styled.div`
- margin-left: 7px;
- color: #000;
- font-size: 16px;
- font-weight: 500;
-`;
-
-const OrderDiv = styled.div`
- margin-left: 7px;
- color: #000;
- font-size: 16px;
- font-weight: 500;
-`;
-
-const ReturnDiv = styled.div`
- margin-left: auto;
- color: ${(props) =>
- parseFloat(props.$returns) >= 0 ? "#ee2f2a" : "#2679ed"};
-`;
-
-const ButtonWrapper = styled.div`
- display: flex;
- gap: 30px;
- margin-bottom: 25px;
- margin-top: 5px;
-`;
-
-const VoteBtn = styled.button`
- width: 150px;
- height: 44px;
- border: none;
- border-radius: 10px;
- background: ${(props) => props.color};
-
- color: #fff;
- font-size: 25px;
- font-weight: 600;
-
- &:hover {
- background: ${(props) => props.$hover};
- }
-`;
-
-const BarDiv = styled.div`
- position: relative;
- width: 250px;
- height: 30px;
- /* background-color: #ffe3d7;
- border-radius: 10px; */
-`;
-
-const ODiv = styled.div`
- position: absolute;
- left: 0;
- top: 0;
- width: 32%;
- height: 30px;
- border-radius: 10px 0px 0px 10px;
- background: #bee4ff;
-`;
-
-const XDiv = styled.div`
- position: absolute;
- right: 0;
- top: 0;
- width: 68%;
- height: 30px;
- border-radius: 0px 10px 10px 0px;
- background: #ffe3d7;
-`;
-
-const OXWrapper = styled.div`
- display: flex;
- gap: 10px;
- margin-bottom: 25px;
- margin-top: 5px;
-`;
-
-const OXDiv = styled.div`
- text-align: center;
- font-size: 15px;
-`;
-
export default FeedPage;
diff --git a/src/store/store.js b/src/store/store.js
index 93b40c8..880a844 100644
--- a/src/store/store.js
+++ b/src/store/store.js
@@ -15,28 +15,29 @@ import logger from "redux-logger";
import tradingReducer from "./reducers/Trading/trading";
import chartValuesReducer from "./reducers/Trading/chartValues";
import indicatorValuesReducer from "./reducers/Trading/indicatorValues";
-import chartReducer from './reducers/Chart/chart.jsx';
-import companyReducer from './reducers/Chart/clickCompany.jsx';
-import clickIndicatorsReducer from './reducers/Chart/Indicators/clickIndicators.jsx';
-import getChartIndicatorReducer from './reducers/Chart/Indicators/chart.jsx';
-import getSubIndicatorReducer from './reducers/Chart/Indicators/sub.jsx';
+import chartReducer from "./reducers/Chart/chart.jsx";
+import companyReducer from "./reducers/Chart/clickCompany.jsx";
+import clickIndicatorsReducer from "./reducers/Chart/Indicators/clickIndicators.jsx";
+import getChartIndicatorReducer from "./reducers/Chart/Indicators/chart.jsx";
+import getSubIndicatorReducer from "./reducers/Chart/Indicators/sub.jsx";
import searchReducer from "./reducers/Trading/search";
import userReducer from "./reducers/User/user";
+import feedReducer from "./reducers/Feed/feed";
const rootPersistConfig = {
key: "root",
storage: storage,
// whitelist: ["chartValues", "indicatorValues"],
whitelist: [
- "user",
- "chartValues",
- "indicatorValues",
- "search",
+ "user",
+ "chartValues",
+ "indicatorValues",
+ "search",
"chart",
"clickIndicator",
- "getChartIndicator",
+ "getChartIndicator",
"getSubIndicator",
- "company"
+ "company",
],
};
@@ -54,6 +55,7 @@ const rootReducer = persistReducer(
getSubIndicator: getSubIndicatorReducer,
search: searchReducer,
user: userReducer,
+ feed: feedReducer,
})
);
const myMiddlewares = [logger];