From e7ac35c80da02b1a22694bd9c8d72c7543bcf262 Mon Sep 17 00:00:00 2001 From: bakhacode Date: Thu, 26 Oct 2023 15:58:28 +0900 Subject: [PATCH] =?UTF-8?q?#52=20feat:=20=ED=8F=AC=ED=8A=B8=ED=8F=B4?= =?UTF-8?q?=EB=A6=AC=EC=98=A4=20=EC=A2=85=EB=AA=A9=EB=B3=84=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=B4=EC=B0=A8=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Portfolio/HoldingsPieChart.tsx | 177 ++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 fe/src/components/Portfolio/HoldingsPieChart.tsx diff --git a/fe/src/components/Portfolio/HoldingsPieChart.tsx b/fe/src/components/Portfolio/HoldingsPieChart.tsx new file mode 100644 index 0000000..c5fe4f2 --- /dev/null +++ b/fe/src/components/Portfolio/HoldingsPieChart.tsx @@ -0,0 +1,177 @@ +import { PortfolioHolding } from "@api/portfolio"; +import { useCallback, useState } from "react"; +import styled from "styled-components"; +import { PieChart, Pie, Sector } from "recharts"; +import { addComma } from "@utils/addComma"; +import Legend from "@components/common/PieChart/Legend"; +import { colorPalette } from "styles/ColorPalette"; + +type PieEntry = { + percent: number; + cornerRadius?: number; + name: string; + tooltipPayload: any[]; + midAngle: number; + cx: number; + cy: number; + endAngle: number; + fill: string; + innerRadius: number; + maxRadius: number; + outerRadius: number; + paddingAngle: number; + startAngle: number; + stroke: string; + tooltipPosition: { + x: number; + y: number; + }; + value: number; +}; + +const TOTAL_VALUATION_INDEX = -1; + +export default function HoldingsPieChart({ + data, +}: { + data: PortfolioHolding[]; +}) { + console.log(data); + + const pieData = data.map((item, index) => { + return { + name: item.companyName, + value: item.currentValuation, + fill: colorPalette[index], + }; + }); + const totalValuation = pieData.reduce((acc, cur) => acc + cur.value, 0); + + const [activeIndex, setActiveIndex] = useState(TOTAL_VALUATION_INDEX); + const onPieEnter = useCallback( + (_: PieEntry, index: number) => { + setActiveIndex(index); + }, + [setActiveIndex] + ); + + const onPieLeave = useCallback(() => { + setActiveIndex(TOTAL_VALUATION_INDEX); + }, [setActiveIndex]); + + return ( + + {activeIndex === TOTAL_VALUATION_INDEX ? ( + +

총 자산 현황

+
{addComma(totalValuation)}
+
+ ) : null} + + + + + + +
+ ); +} + +const renderActiveShape = (props: any) => { + const { + cx, + cy, + innerRadius, + outerRadius, + startAngle, + endAngle, + fill, + payload, + } = props; + + return ( + + + {payload.name} + + + {addComma(payload.value)} + + + + ); +}; + +const StyledHoldingsPieChart = styled.div` + width: 600px; + height: 318px; + display: flex; + justify-content: center; + align-items: center; + position: relative; + border-radius: 8px; + border: 1px solid #e0e0e0; +`; +const TotalValue = styled.div` + display: flex; + flex-direction: column; + + position: absolute; + top: 39%; + left: 45%; + z-index: 3; + > p { + font-size: 15px; + font-weight: bold; + color: #000000; + } + + > div { + display: flex; + justify-content: center; + font-size: 14px; + font-weight: bold; + color: #000000; + } +`; + +const PieChartWrapper = styled.div` + top: 10px; + width: 250px; + height: 250px; + position: absolute; + z-index: 2; +`;