Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FE] feat: 리뷰 모아보기에서 질문별 통계 차트 구현 #803

Merged
merged 43 commits into from
Oct 10, 2024
Merged
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
6697bae
feat: Switch 컴포넌트 제작
ImxYJL Oct 4, 2024
04450f5
chore: Switch 컴포넌트 이름 변경
ImxYJL Oct 5, 2024
ecd84ec
feat: 리뷰 모아보기에 대한 라우팅 추가 및 임시 페이지 구현
ImxYJL Oct 5, 2024
e87ac79
feat: 리뷰 모아보기와 리뷰 목록 페이지의 공통 레이아웃 제작
ImxYJL Oct 5, 2024
6525223
refactor: 공통 레이아웃 제작에 따른 ReviewList 리팩토링
ImxYJL Oct 5, 2024
2741550
feat: 리뷰 목록 반응형 적용
ImxYJL Oct 5, 2024
09b6aab
feat: OptionSwitch 반응형 적용
ImxYJL Oct 6, 2024
b609099
refactor: ReviewDisplayLayout 반응형 수정
ImxYJL Oct 6, 2024
9d858da
feat: 공통 Dropdown 컴포넌트 작성
chysis Oct 6, 2024
35f66c5
design: 화살표 버튼 오른쪽 고정 및 옵션을 드래그하지 못하게 수정
chysis Oct 6, 2024
d501de8
feat: Dropdown 외부 클릭 시 닫히도록 하는 기능 구현
chysis Oct 6, 2024
074f519
refactor: Dropdown 로직을 훅으로 분리
chysis Oct 6, 2024
44b9f67
chore: props 명칭 변경 및 선택된 아이템 ellipsis 처리
chysis Oct 6, 2024
7ec01ab
feat: Accordion 공통 컴포넌트 작성
chysis Oct 6, 2024
e2544a4
chore: index에 Dropdown, Accordion 추가
chysis Oct 6, 2024
7350b6e
feat: theme에 Dropdown의 z-index 추가
chysis Oct 6, 2024
b4b3033
chore: 누락된 index 추가
chysis Oct 6, 2024
fd088ac
design: Dropdown border 색상 변경
chysis Oct 6, 2024
76b2141
refactor: Accordion 로직 훅으로 분리
chysis Oct 6, 2024
3026dbe
fix: px을 rem으로 수정
ImxYJL Oct 7, 2024
3095e1c
Merge branch 'fe/refactor/768-common-review-list-layout' of https://g…
chysis Oct 7, 2024
27c5286
design: Dropdown 및 Accordion의 margin-bottom 속성 제거
chysis Oct 7, 2024
b3bfb91
feat: 초기에 열려있는 Accordion 구현을 위해 prop 추가
chysis Oct 7, 2024
d984f19
feat: 모아보기 페이지 type 정의
chysis Oct 7, 2024
424e3cc
feat: 모아보기 페이지 목 데이터 작성
chysis Oct 7, 2024
8590919
design: Accordion 컴포넌트에서 불필요한 props 제거
chysis Oct 8, 2024
41ead48
design: Accordion 반응형 구현
chysis Oct 8, 2024
037e423
feat: 목 데이터를 사용하여 모아보기 페이지 퍼블리싱
chysis Oct 8, 2024
9c0ffd1
feat: 질문별 통계 차트 구현
soosoo22 Oct 8, 2024
34a25a7
feat: 통계 차트 세부사항 표시
soosoo22 Oct 8, 2024
e9e6737
Merge remote-tracking branch 'origin/fe/feat/773-dropdown-accordion' …
soosoo22 Oct 8, 2024
0ab8d0a
feat: 질문 길이에 따라 색상을 생성하는 함수 구현
soosoo22 Oct 9, 2024
2b83d32
chore: DoughnutChart 파일 위치 변경
soosoo22 Oct 9, 2024
2a7f900
feat: 차트 애니메이션 적용 및 비율을 텍스트로 시각화
soosoo22 Oct 9, 2024
c429a53
chore: 비율을 'n표' 형식으로 수정
soosoo22 Oct 9, 2024
76312d7
chore: 불필요한 텍스트 제거
soosoo22 Oct 9, 2024
fbc97c7
feat: ReviewCollectionPage에 DoughnutChart 컴포넌트 적용
soosoo22 Oct 9, 2024
c752e50
feat: 통계 차트에 반응형 적용
soosoo22 Oct 9, 2024
90a1f61
refactor: theme에 있는 primary 색상 활용
soosoo22 Oct 10, 2024
82749ef
chore: 불필요한 코드 제거
soosoo22 Oct 10, 2024
63ff584
Merge remote-tracking branch 'origin/develop' into fe/feat/770-review…
soosoo22 Oct 10, 2024
281f5bf
refactor: 차트 애니메이션 제거
soosoo22 Oct 10, 2024
ac98ba4
chore: Accordion에 넘겨주는 props 변수명 수정
soosoo22 Oct 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useEffect, useState } from 'react';

import { ReviewVotes } from '@/types';

import generateGradientColors from '../../utils/generateGradientColors';
Expand All @@ -13,6 +15,8 @@ const DOUGHNUT_COLOR = {
const DoughnutChart = ({ reviewVotes }: { reviewVotes: ReviewVotes[] }) => {
const radius = 90; // 차트의 반지름
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사실상 상수 역할인 것 같은데 소문자로 선언한 이유가 있을까요?

Copy link
Contributor Author

@soosoo22 soosoo22 Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이유는 없습니다... 대문자로 변경하는 걸 잊었을 뿐.... 😭

Copy link
Contributor

@BadaHertz52 BadaHertz52 Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

svg를 위한 상수들인 것 같아, 같이 변경되지 않는 변수들은 대문자로 변수명을 변경하는 것 어떨가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

상수 정의... 접수완료...

const circumference = 2 * Math.PI * radius; // 차트의 둘레
const centerX = 125; // svg의 중앙 좌표 (x)
const centerY = 125; // svg의 중앙 좌표 (y)

const total = reviewVotes.reduce((acc, reviewVote) => acc + reviewVote.count, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

total, ratio. acc 라는 변수명이 구체적이었으면 해요.

무엇에 대한 총합인지, 어떤 것에 대한 비율인지, 계산한 결과값이 무엇을 의미하는 지가 변수에 담겼으면 해요

const ratios = reviewVotes.map((reviewVote) => reviewVote.count / total);
Expand All @@ -29,32 +33,79 @@ const DoughnutChart = ({ reviewVotes }: { reviewVotes: ReviewVotes[] }) => {
// 색상 시작 및 끝값 정의
const colors = generateGradientColors(reviewVotes.length, DOUGHNUT_COLOR.START, DOUGHNUT_COLOR.END);

// 애니메이션 상태 관리
const [animateIndex, setAnimateIndex] = useState(0);

// 애니메이션 트리거 설정
useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

애니메이션 구현하느라 고생했어요.

고생한것 같아 말하지 미안하지만, 애니메이션의 필요성에 대해서는 느끼지 못하겠어요.
아코디언이 열리는 애니메이션이 있고, 만약 하나의 section에 여러 객관식이 있다면 아코디언을 열때마다 애니메이션이 실행될 경우, 눈이 피로하다?라는 느낌이 들 것 같아요(제가 지금 피곤해서 더 예민할 수도... .🥲) 성능이 느린 컴퓨터에서는 애니메이션 로딩 속도로 답답할 수 도 있을 거라는 우려도 있어요

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 애니메이션을 구현하면서 필요성에 대해 고민해 봤는데요. 생각해보니 아코디언이 펼쳐지면서 차트에도 애니메이션이 실행되니 다소 피로할 수 있을 것 같다는 느낌이 드네요. 더군다나 아코디언을 클릭할때마다 애니메이션이 실행되니까 충분히 피로할 수 있을 것 같아요.

일단, 애니메이션... Bye....

if (animateIndex < reviewVotes.length - 1) {
const timer = setTimeout(() => {
setAnimateIndex(animateIndex + 1); // 다음 애니메이션 트리거
}, 40);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추후 40도 상수화하면 좋을 것 같아요~~

return () => clearTimeout(timer);
}
}, [animateIndex, reviewVotes.length]);

// 각 조각의 중심 좌표를 계산하는 함수
const calculateLabelPosition = (startAngle: number, endAngle: number) => {
const midAngle = (startAngle + endAngle) / 2; // 중간 각도
const labelRadius = radius * 1; // 텍스트가 배치될 반지름 (차트 내부)
const x = centerX + labelRadius * Math.cos((midAngle * Math.PI) / 180);
const y = centerY + labelRadius * Math.sin((midAngle * Math.PI) / 180);
return { x, y };
};

return (
<S.DoughnutChartContianer>
<S.DoughnutChartContainer>
<svg viewBox="0 0 250 250" width="250" height="250">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vieBox, width, height도 상수화하면 좋겠네요

{reviewVotes.map((reviewVote, index) => {
Copy link
Contributor

@BadaHertz52 BadaHertz52 Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return 반환값안에서 svg를 생성하기 위해 계산하는 코드들이 있으니 가독성이 좋지 않아요.
혹시 이를 컴포넌트로 따로 뺄 수 있을까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구현할 때는 몰랐는데 코드를 다시 보니.... 와우.... 가독성이 정말 좋지 않네요...^^ 추후에 컴포넌트로 분리하겠습니다!

const ratio = reviewVote.count / total;
const fillSpace = circumference * ratio;
const emptySpace = circumference - fillSpace;
const offset = (acc[index] / total) * circumference;

// 시작 각도와 끝 각도를 계산
const startAngle = (acc[index] / total) * 360 + 90;
const endAngle = ((acc[index] + reviewVote.count) / total) * 360 - 90;

// 비율 레이블의 위치를 계산
const { x, y } = calculateLabelPosition(startAngle, endAngle);

return (
<circle
key={index}
cx="125" // 중앙에 배치
cy="125"
r={radius}
fill="none"
stroke={colors[index]}
strokeWidth="65"
strokeDasharray={`${fillSpace} ${emptySpace}`} // 조각의 길이와 나머지 길이 설정
strokeDashoffset={-offset} // 시작 위치 설정
/>
<g key={index}>
<circle
cx={centerX} // 중앙에 배치
cy={centerY}
r={radius}
fill="none"
stroke={colors[index]}
strokeWidth="65"
strokeDasharray={`${fillSpace} ${emptySpace}`} // 조각의 길이와 나머지 길이 설정
strokeDashoffset={-offset} // 시작 위치 설정
style={{
transition: 'stroke-dasharray 1s ease', // 애니메이션 추가
opacity: index <= animateIndex ? 1 : 0, // 해당 인덱스까지의 애니메이션만 보여줌
}}
/>
<text
x={x}
y={y}
textAnchor="middle"
dominantBaseline="middle"
fontSize="14"
opacity={index <= animateIndex ? 1 : 0} // 애니메이션과 함께 텍스트 보이기
style={{
transition: 'opacity 0.4s ease', // 텍스트의 투명도 애니메이션
}}
>
{Math.floor(ratios[index] * 100)}%
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금은 floor로 항상 버림 처리되어 각 퍼센트를 다 합쳤을 때 97%로, 오차가 꽤 있어요. toFixed(1)로 소수점 한 자리수까지 반올림한 값을 보여주는 것은 어떤가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아.. 예리하십니다 에프이!
소수점을 바로 버리기보다는 toFixed(1)로 소수점 한 자리수까지 반올림한 값이 더 좋겠네요!!👍

</text>
</g>
);
})}
</svg>
<DoughnutChartDetails reviewVotes={reviewVotes} ratios={ratios} colors={colors} />
</S.DoughnutChartContianer>
<DoughnutChartDetails reviewVotes={reviewVotes} colors={colors} />
</S.DoughnutChartContainer>
);
};

Expand Down