관리 페이지에서 평가 탭에서는 중간 / 최종 평가 그래프를 보여준다고 했다.
그래프를 보여주는 기능은 recharts 라이브러리를 사용해서 구현을 했다.
처음에 그래프를 보여주는 기능 자체에는 문제가 없었는데, 인원수가 너무 많아지니까 한 그래프로 전체 인원 평가 그래프를 보여주기에는 무리가 있었다.
그래서, 스크롤하면서 넘겨볼 수 있는 기능이 있으면 좋겠다고 생각해서, recharts 공식 문서도 찾아보고 구글링도 해봤지만, 해결 방법을 찾을 수 없었다.
아마 recharts 측에서 공식적으로 지원하지 않는 기능인 것 같았다.
그러다가, 팀원 중 한 분이 인원 수가 일정 기준을 넘어가면 카드 슬라이드처럼 넘기면서 볼 수 있도록 하는 것은 어떤 지 의견을 내주셨다.
물론, 한 그래프로 전체 인원의 차트 현황을 보는 것이 가장 좋지만, 지금 상황에서는 그게 가장 좋은 해결 방법 같았다.
그래서, 인원 수가 너무 많아지면 카드 슬라이드처럼 그래프를 볼 수 있게 구현해 봤다.
코드는 다음과 같다.
import { BarChart, Bar, XAxis, YAxis, Tooltip } from "recharts";
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import { useState } from "react";
const CustomTooltip = ({ isCompleted, active, payload, label }) => {
if (active && payload && payload.length) {
return (
<div className="custom-tooltip">
{isCompleted ? (
<>
<p className="label">
{`${label}`} <br />
{`성실도: ${payload[0].value}`}점<br />
{`시간 엄수: ${payload[1].value}`}점<br />
{`업무 수행 능력: ${payload[2].value}`}점<br />
{`의사 소통: ${payload[3].value}`}점
</p>
</>
) : (
<>
<p className="label">
{`${label}`} <br />
{`아이디어 뱅크: ${payload[0].value}`}개<br />
{`열정적인 참여자: ${payload[1].value}`}개<br />
{`최고의 서포터: ${payload[2].value}`}개<br />
{`탁월한 리더: ${payload[3].value}`}개
</p>
</>
)}
</div>
);
}
return null;
};
const settings = {
dots: true,
infinite: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1,
};
const evaluateBadgeMaxNumRounded = (data) => {
let maxBadgeNum = 0;
data.forEach((memberData) => {
for (let evaluationData in memberData.evaluation) {
if (memberData.evaluation[evaluationData] > maxBadgeNum) {
maxBadgeNum = memberData.evaluation[evaluationData];
}
}
});
return maxBadgeNum + (5 - (maxBadgeNum % 5));
};
const chartIndices = (data, chunkSize) => {
let indexArray = [];
for (let i = 0; i < data.length / chunkSize; i++) {
indexArray.push(i);
}
return indexArray;
};
const ShowEvaluationChart = ({ chartData = null, isCompleted }) => {
const data = chartData.map((memberData) => {
const evaluation = memberData.evaluation[0];
return isCompleted
? {
name: memberData.name,
communication: evaluation.communication,
jobPerformance: evaluation.jobPerformance,
punctuality: evaluation.punctuality,
sincerity: evaluation.sincerity,
}
: {
name: memberData.name,
ideaBankBadge: memberData.evaluation["아이디어_뱅크"],
bestSupporterBadge: memberData.evaluation["최고의_서포터"],
goodLeaderBadge: memberData.evaluation["탁월한_리더"],
enthusiasticParticipantBadge:
memberData.evaluation["열정적인_참여자"],
};
});
const [chartDataNum, setChartDataNum] = useState(
data.length < 9 ? data.length : Math.ceil(data.length / 3)
);
return chartData && isCompleted ? (
<div className="evaluation-management-chart-wrapper">
<h1>최종 평가 차트</h1>
<div className="evaluation-management-show-evaluation-chart">
<Slider className="slider" {...settings}>
{chartIndices(data, chartDataNum).map((i) => (
<div key={i}>
<BarChart
className="chart"
width={495}
height={320}
data={data.slice(i * chartDataNum, (i + 1) * chartDataNum)}
>
<Tooltip
content={<CustomTooltip isCompleted={isCompleted} />}
/>
<XAxis dataKey="name" tickSize={8} />
<YAxis
dataKey="evaluation"
domain={[0, evaluateBadgeMaxNumRounded(chartData)]}
/>
<Bar dataKey="sincerity" fill="#01E89E" />
<Bar dataKey="punctuality" fill="#00AA72" />
<Bar dataKey="jobPerformance" fill="#D7D7D7" />
<Bar dataKey="communication" fill="#01E89E" />
</BarChart>
</div>
))}
</Slider>
</div>
</div>
) : (
<div className="evaluation-management-chart-wrapper">
<h1>배지 차트</h1>
<div className="evaluation-management-show-evaluation-chart">
<Slider className="slider" {...settings}>
{chartIndices(data, chartDataNum).map((i) => (
<div key={i}>
<BarChart
className="chart"
width={495}
height={320}
data={data.slice(i * chartDataNum, (i + 1) * chartDataNum)}
>
<Tooltip content={<CustomTooltip />} />
<XAxis dataKey="name" tickSize={8} />
<YAxis
dataKey="evaluation"
domain={[0, evaluateBadgeMaxNumRounded(chartData)]}
/>
<Bar dataKey="ideaBankBadge" fill="#01E89E" />
<Bar dataKey="enthusiasticParticipantBadge" fill="#00AA72" />
<Bar dataKey="bestSupporterBadge" fill="#D7D7D7" />
<Bar dataKey="goodLeaderBadge" fill="#01E89E" />
</BarChart>
</div>
))}
</Slider>
</div>
</div>
);
};
export default ShowEvaluationChart;
로직에 대해서 조금 더 알아보자.
중요한 부분은 아래 코드이다.
const [chartDataNum, setChartDataNum] = useState(
data.length < 9 ? data.length : Math.ceil(data.length / 3)
);
차트 상에 보여주어야 하는 데이터가 9개 이상이면 세 차트로 나눠서 볼 수 있게 설정했다.
8개 이하이면 그냥 한 차트로 볼 수 있게 설정해 놓았다.
이렇게 chartDataNum을 이용해서 한 번에 보여줄 차트 데이터 개수를 정하고 이를 사용해서 서버에서 불러온 차트 데이터를 슬라이싱해서 화면에 보여주게 된다.
그렇게 구현된 차트 사진은 다음과 같다.
'프로젝트 개발일지 > 플케어' 카테고리의 다른 글
[에러 해결] 프로젝트 삭제 후 뒤로 가기로 인한 에러 해결 (0) | 2023.08.05 |
---|---|
[리팩터링] 프로젝트 관리 메인 페이지 api 호출 개수 줄이기 (0) | 2023.08.05 |
[에러 해결] 로그인이 필요한 페이지 접근 시 로그인 모달창 띄우기 (4) | 2023.08.05 |
[기능 구현] 프로젝트 관리 탭을 구현해보자. (0) | 2023.08.05 |
[기능 구현] 프로젝트 목록 페이지를 개발해보자. (0) | 2023.07.25 |