Skip to content

feat: 사용자 응답 관리 페이지 API 연동#146

Merged
hyeeuncho merged 18 commits intodevelopfrom
feat/#128/response-management-api
May 28, 2025
Merged

feat: 사용자 응답 관리 페이지 API 연동#146
hyeeuncho merged 18 commits intodevelopfrom
feat/#128/response-management-api

Conversation

@hyeeuncho
Copy link
Copy Markdown
Member

@hyeeuncho hyeeuncho commented May 27, 2025

요약 그래프 및 주관식 구현

스크린샷 2025-05-28 오후 5 44 36

개별 조회

스크린샷 2025-05-28 오후 8 12 22

구매/참가자 관리에서 개별 조회 시 모달 띄우기

스크린샷 2025-05-28 오후 8 29 17

주문 로직 수정 반영 (1번 구매한 티켓 재구매 불가 문제 해결됨)

스크린샷 2025-05-28 오후 7 24 58

Summary by CodeRabbit

Summary by CodeRabbit

  • 신규 기능

    • 여러 티켓 옵션 응답을 파이 차트로 시각화하는 컴포넌트가 추가되었습니다.
    • 티켓 옵션 및 응답을 위한 API 및 관련 훅이 추가되었습니다.
    • 개인별 티켓 옵션 응답을 확인할 수 있는 개별 응답 뷰어와 주문 응답 모달이 도입되었습니다.
  • 기능 개선

    • 응답 관리 페이지에서 응답 데이터를 실시간으로 불러오고, 요약/질문형 보기 대신 파이 차트로 시각화합니다.
    • 필터 바에서 '질문' 보기 옵션이 제거되어 '요약'과 '개별'만 지원합니다.
    • 필수 티켓 옵션에 빨간색 별표(*)가 표시됩니다.
    • 티켓 주문 상세 조회 및 주문 처리 로직이 단일 주문 ID 기반으로 변경되어 간소화되었습니다.
    • 티켓 옵션 선택 레이아웃에서 필수 옵션 검증 및 답변 일괄 제출 방식으로 개선되었습니다.
    • 참가자 카드 및 관련 스토어에서 주문 번호 대신 주문 ID를 사용하도록 변경되었습니다.
    • 티켓 주문 페이지에서 옵션이 없는 티켓은 바로 주문 처리하는 기능이 추가되었습니다.
  • 버그 수정

    • 불필요한 콘솔 로그가 제거되었습니다.
  • 리팩터

    • 티켓 주문 상세 조회, 옵션 응답 관련 API 및 훅 구조가 단순화 및 분리되었습니다.
    • 여러 컴포넌트의 props와 내부 데이터 흐름이 개선되었습니다.
    • 응답 리스트 컴포넌트가 불필요한 상태 및 필터링 로직을 제거하고 간결해졌습니다.
    • 선택된 응답 리스트 컴포넌트가 삭제되었습니다.
  • 문서 및 타입

    • 티켓 옵션 응답 관련 타입이 추가 및 명확화되었습니다.

@hyeeuncho hyeeuncho self-assigned this May 27, 2025
@hyeeuncho hyeeuncho linked an issue May 27, 2025 that may be closed by this pull request
2 tasks
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented May 27, 2025

"""

Walkthrough

이 변경사항은 티켓 옵션 응답의 시각화 및 관리 기능을 대폭 확장합니다. 티켓 옵션 관련 API와 훅이 별도 파일로 분리·추가되고, 응답을 파이 차트로 시각화하는 컴포넌트가 도입되었습니다. 여러 API 시그니처가 단순화되거나 파라미터가 변경되었으며, 응답 필터링 및 리스트 타입에서 'query' 옵션이 제거되었습니다.

Changes

파일/경로 요약 변경 내용 요약
package.json recharts 라이브러리 의존성 추가
src/features/dashboard/api/participants.ts getParticipants 함수 시그니처를 eventId 필수 파라미터로 변경, 타입 명시 강화
src/features/dashboard/ui/MultiplePieCharts.tsx 여러 티켓 옵션 응답을 파이 차트로 시각화하는 새 컴포넌트 추가
src/features/dashboard/ui/ParicipantCard.tsx useNavigate 제거, onCheckClick 콜백 추가, orderNumberorderId 변경
src/features/dashboard/ui/ResponseFilter.tsx
src/widgets/dashboard/ui/ResponsesFilterBar.tsx
리스트 타입에서 'query' 옵션 제거, 필터링 로직 단순화 및 UI 버튼 제거
src/features/dashboard/ui/ResponsesList.tsx 필드 기반 필터링 및 텍스트 응답 섹션 제거, MultiplePieCharts로 시각화 통합, ticketOptionResponsesticketId prop 추가
src/features/payment/ui/TicketOption.tsx 디버깅용 console.log 제거, 필수 옵션 표시 별표 활성화
src/features/ticket/api/order.ts
src/features/ticket/hooks/useOrderHook.ts
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx
주문 상세 조회 API 및 훅 시그니처를 orderId 단일 파라미터로 변경, 관련 호출부 수정
src/features/ticket/api/ticket.ts
src/features/ticket/hooks/useTicketHook.ts
티켓 옵션 관련 API 및 훅 삭제, 관련 타입 및 함수 제거
src/features/ticket/api/ticketOption.ts
src/features/ticket/hooks/useTicketOptionHook.ts
티켓 옵션 및 응답 관련 API/훅 신규 파일로 분리 및 추가, 타입 안전성 강화
src/features/ticket/model/ticketInformation.ts 티켓 옵션 응답 관련 타입(TicketOptionAnswer, TicketOptionAnswerResponse, PersonalTicketOptionAnswerResponse) 추가 및 확장
src/pages/dashboard/ui/ResponseManagementPage.tsx 응답 데이터 소스를 store→훅 기반으로 변경, 리스트 타입에서 'query' 제거, ticketOptionResponses prop 전달
src/pages/dashboard/ui/ticket/TicketOptionResponsePage.tsx 티켓 옵션 훅 import 경로 수정, TicketOptionLayoutoptions prop 추가
src/pages/menu/ui/MyTicketPage.tsx 티켓 목록 조회를 커스텀 훅(useTicketOrders)으로 일원화, 상태 관리 단순화
src/shared/ui/backgrounds/TicketOptionLayout.tsx options prop 추가, 필수 옵션 유효성 검사 로직 도입, 네비게이션 state 단순화 및 응답 제출 방식 변경
src/features/dashboard/model/store/ParticipantStore.tsx 참가자 상태에 selectedTicketId, selectedOrderId 추가 및 orderNumberorderId 키 변경
src/features/dashboard/ui/IndividualResponseViewer.tsx 개별 주문 응답을 보여주는 새 컴포넌트 추가
src/features/dashboard/ui/PariticipantsList.tsx 참가자 리스트에 모달 상태 및 선택된 주문 관리 로직 추가, onCheckClick 콜백으로 모달 열기 구현
src/widgets/dashboard/ui/response/OrderAnswerModal.tsx 주문 응답 모달 컴포넌트 추가, 개별 응답 뷰어 포함
src/shared/types/participantInfoType.ts participantsData 타입에서 orderNumberorderIdticketId로 분리
src/features/ticket/model/orderInformation.ts OrderTicketRequestticketOptionAnswers 배열 속성 추가
src/features/ticket/util/buildTicketOptionAnswers.tsx 선택된 옵션 데이터를 티켓 옵션 응답 배열로 변환하는 유틸 함수 추가
src/widgets/event/ui/TicketInfo.tsx 티켓 옵션 유무에 따라 즉시 주문 또는 옵션 응답 페이지로 분기하는 로직 추가 및 개선

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ResponseManagementPage
  participant usePurchaserAnswers
  participant ResponsesList
  participant MultiplePieCharts

  User->>ResponseManagementPage: 페이지 진입
  ResponseManagementPage->>usePurchaserAnswers: 티켓ID로 응답 데이터 fetch
  usePurchaserAnswers-->>ResponseManagementPage: 응답 데이터 반환
  ResponseManagementPage->>ResponsesList: listType, ticketOptionResponses 전달
  ResponsesList->>MultiplePieCharts: ticketOptionResponses 전달
  MultiplePieCharts-->>User: 파이 차트로 응답 시각화
Loading

Possibly related PRs

Suggested labels

🔧 Feature

Suggested reviewers

  • Yejiin21

Poem

🥕
차트가 둥글게, 응답이 춤추네
티켓 옵션, 이제는 한눈에
필수 답변 꼼꼼히 확인하고
API와 훅도 새로워졌지
토끼는 기뻐, 코드를 뛰어넘어
파이처럼 달콤한
대시보드의 봄!
🐰📊
"""

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (7)
src/features/dashboard/ui/MultiplePieCharts.tsx (1)

27-27: 사용되지 않는 매개변수를 제거하세요.

ESLint에서 지적한 대로 _index 매개변수가 사용되지 않습니다. 매개변수를 제거하거나 실제로 필요한 경우 사용하세요.

-      {responses.map((option, _index) => {
+      {responses.map((option) => {
🧰 Tools
🪛 ESLint

[error] 27-27: '_index' is defined but never used.

(@typescript-eslint/no-unused-vars)

src/pages/dashboard/ui/ResponseManagementPage.tsx (1)

8-14: API 연동으로의 리팩토링이 좋습니다.

usePurchaserAnswers 훅을 사용하여 동적 데이터 가져오기로 전환한 것이 좋습니다. 하지만 프로덕션 코드에서 console.log를 제거해야 합니다.

   const { data } = usePurchaserAnswers(selectedTicketId);
-  console.log(data)
src/shared/ui/backgrounds/TicketOptionLayout.tsx (2)

32-32: 프로덕션 코드에서 console.log를 제거하세요.

디버깅용 console.log가 남아있습니다.

-console.log(selectedOptions)

43-61: 검증 로직 개선 제안

현재 검증 로직은 잘 작동하지만, 다음과 같은 개선사항을 고려해보세요:

  1. 사용자에게 더 구체적인 오류 메시지 제공
  2. 어떤 필수 옵션이 누락되었는지 명시
-        if (!isValid) {
-            alert("필수 옵션을 모두 입력해주세요.");
-            return;
-        }
+        if (!isValid) {
+            const missingOptions = requiredOptions
+                .filter((opt) => {
+                    const answer = currentOptions?.[opt.id];
+                    if (opt.type === "TEXT") {
+                        return !(typeof answer === "string" && answer.trim() !== "");
+                    }
+                    if (opt.type === "SINGLE") {
+                        return !(typeof answer === "number");
+                    }
+                    if (opt.type === "MULTIPLE") {
+                        return !(Array.isArray(answer) && answer.length > 0);
+                    }
+                    return true;
+                })
+                .map(opt => opt.name);
+            
+            alert(`다음 필수 옵션을 입력해주세요: ${missingOptions.join(", ")}`);
+            return;
+        }
src/features/dashboard/ui/ResponsesList.tsx (1)

31-36: 인라인 스타일 대신 CSS 클래스 사용을 고려하세요.

유지보수성과 일관성을 위해 Tailwind CSS 클래스나 별도의 스타일 시트를 사용하는 것이 좋습니다.

-            <div className="flex justify-center">
-              <div style={{ minWidth: '300px', maxWidth: '600px', width: '100%' }}>
-                <MultiplePieCharts responses={ticketOptionResponses} />
-              </div>
-              
-            </div>
+            <div className="flex justify-center">
+              <div className="min-w-[300px] max-w-[600px] w-full">
+                <MultiplePieCharts responses={ticketOptionResponses} />
+              </div>
+            </div>
src/features/ticket/api/ticketOption.ts (2)

11-14: 반환 타입 명시가 필요합니다.

다른 함수들과 달리 이 함수는 반환 타입이 명시되지 않았습니다. 일관성을 위해 반환 타입을 추가하는 것이 좋겠습니다.

다음과 같이 반환 타입을 명시해주세요:

-export const createTicketOptionAnswers = async (answers: TicketOptionAnswerRequest) => {
+export const createTicketOptionAnswers = async (answers: TicketOptionAnswerRequest): Promise<any> => {

또는 정확한 응답 타입이 있다면 해당 타입을 사용해주세요.


5-30: 에러 처리 개선을 고려해보세요.

현재 모든 API 함수에 에러 처리가 없어서 네트워크 오류나 서버 오류 시 애플리케이션이 예상치 못한 동작을 할 수 있습니다. 각 함수에 try-catch 블록을 추가하거나 상위 레벨에서 일관된 에러 처리를 구현하는 것을 권장합니다.

예시:

export const readTicketOptions = async (ticketId: number): Promise<{ isSuccess: boolean; result: TicketOptionResponse[] }> => {
  try {
    const response = await axiosClient.get(`/ticket-options/tickets/${ticketId}`);
    return response.data;
  } catch (error) {
    console.error('Failed to fetch ticket options:', error);
    throw error;
  }
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b85c540 and a1bde0c.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (20)
  • package.json (1 hunks)
  • src/features/dashboard/api/participants.ts (1 hunks)
  • src/features/dashboard/ui/MultiplePieCharts.tsx (1 hunks)
  • src/features/dashboard/ui/ParicipantCard.tsx (3 hunks)
  • src/features/dashboard/ui/ResponseFilter.tsx (2 hunks)
  • src/features/dashboard/ui/ResponsesList.tsx (1 hunks)
  • src/features/payment/ui/TicketOption.tsx (1 hunks)
  • src/features/ticket/api/order.ts (1 hunks)
  • src/features/ticket/api/ticket.ts (1 hunks)
  • src/features/ticket/api/ticketOption.ts (1 hunks)
  • src/features/ticket/hooks/useOrderHook.ts (1 hunks)
  • src/features/ticket/hooks/useTicketHook.ts (2 hunks)
  • src/features/ticket/hooks/useTicketOptionHook.ts (1 hunks)
  • src/features/ticket/model/ticketInformation.ts (1 hunks)
  • src/pages/dashboard/ui/ResponseManagementPage.tsx (1 hunks)
  • src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (1 hunks)
  • src/pages/dashboard/ui/ticket/TicketOptionResponsePage.tsx (2 hunks)
  • src/pages/menu/ui/MyTicketPage.tsx (3 hunks)
  • src/shared/ui/backgrounds/TicketOptionLayout.tsx (5 hunks)
  • src/widgets/dashboard/ui/ResponsesFilterBar.tsx (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (10)
src/features/ticket/api/order.ts (1)
src/shared/types/api/http-client.ts (1)
  • axiosClient (6-13)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (1)
src/features/ticket/hooks/useOrderHook.ts (1)
  • useTicketOrderDetail (14-20)
src/features/dashboard/ui/MultiplePieCharts.tsx (1)
src/features/ticket/model/ticketInformation.ts (2)
  • TicketOptionAnswerResponse (55-59)
  • TicketOptionAnswer (50-53)
src/features/ticket/hooks/useOrderHook.ts (1)
src/features/ticket/api/order.ts (1)
  • readTicket (4-19)
src/features/ticket/hooks/useTicketOptionHook.ts (2)
src/features/ticket/model/ticketInformation.ts (5)
  • TicketOptionResponse (33-40)
  • TicketResponse (14-19)
  • TicketOptionAnswerRequest (43-47)
  • TicketOptionAnswerResponse (55-59)
  • PersonalTicketOptionAnswerResponse (62-65)
src/features/ticket/api/ticketOption.ts (4)
  • readTicketOptions (5-8)
  • createTicketOptionAnswers (11-14)
  • readPurchaserAnswers (17-22)
  • readPersonalTicketOptionAnswers (25-30)
src/shared/ui/backgrounds/TicketOptionLayout.tsx (2)
src/features/ticket/model/orderInformation.ts (1)
  • OrderTicketRequest (1-5)
src/features/ticket/model/ticketInformation.ts (1)
  • TicketOptionResponse (33-40)
src/features/dashboard/ui/ResponsesList.tsx (2)
src/features/ticket/model/ticketInformation.ts (1)
  • TicketOptionAnswerResponse (55-59)
src/features/dashboard/model/store/ResponseStore.tsx (1)
  • useResponseStore (21-61)
src/pages/menu/ui/MyTicketPage.tsx (1)
src/features/ticket/hooks/useOrderHook.ts (1)
  • useTicketOrders (6-11)
src/features/ticket/api/ticketOption.ts (2)
src/features/ticket/model/ticketInformation.ts (4)
  • TicketOptionResponse (33-40)
  • TicketOptionAnswerRequest (43-47)
  • TicketOptionAnswerResponse (55-59)
  • PersonalTicketOptionAnswerResponse (62-65)
src/shared/types/api/http-client.ts (1)
  • axiosClient (6-13)
src/pages/dashboard/ui/ResponseManagementPage.tsx (2)
src/features/dashboard/model/store/ResponseStore.tsx (1)
  • useResponseStore (21-61)
src/features/ticket/hooks/useTicketOptionHook.ts (1)
  • usePurchaserAnswers (28-34)
🪛 ESLint
src/features/dashboard/ui/MultiplePieCharts.tsx

[error] 27-27: '_index' is defined but never used.

(@typescript-eslint/no-unused-vars)

🔇 Additional comments (31)
package.json (1)

35-35:

Details

❓ Verification inconclusive

recharts 라이브러리 추가 승인

사용자 응답 관리 페이지의 시각화 기능 구현을 위한 recharts 라이브러리 추가가 적절합니다. 차트 컴포넌트 구현에 필요한 의존성입니다.

라이브러리 버전의 보안성과 최신성을 확인해주세요:


🏁 Script executed:

#!/bin/bash
# recharts 라이브러리의 최신 버전과 보안 취약점 확인

# 최신 버전 확인
npm view recharts version

# 보안 취약점 확인
npm audit --audit-level=moderate

Length of output: 418


recharts (^2.15.3) 최신 버전 확인 완료 – 보안 검증 진행 필요

npm view recharts version 명령으로 현재 버전이 2.15.3임을 확인했습니다. 다만 잠금 파일(package-lock.json 또는 yarn.lock)이 없어 npm audit를 실행할 수 없으므로, CI 또는 로컬 환경에서 보안 취약점 검사를 별도로 수행해 주세요.

검증 방법 예시:

  • package-lock.json 생성
    npm i --package-lock-only
  • 보안 취약점 검사
    npm audit --audit-level=moderate
src/features/dashboard/ui/ParicipantCard.tsx (1)

6-6: useParams 훅 import 적절함

동적 라우팅 구현을 위한 useParams 훅 추가가 적절합니다.

Also applies to: 18-18

src/features/payment/ui/TicketOption.tsx (1)

37-37: 필수 항목 표시 기능 활성화 승인

필수 옵션에 대한 빨간 별표(*) 표시 기능을 활성화한 것이 사용자 경험 개선에 도움이 됩니다. 사용자가 어떤 필드가 필수인지 명확하게 알 수 있어 좋은 변경사항입니다.

src/pages/dashboard/ui/ticket/TicketOptionResponsePage.tsx (2)

4-4:

Details

✅ Verification successful

훅 import 경로 변경 승인

티켓 옵션 관련 로직을 전용 모듈로 분리한 리팩토링이 코드 구조 개선에 도움이 됩니다. 관심사 분리 원칙에 따른 좋은 변경사항입니다.

새로운 훅 모듈이 올바르게 구현되었는지 확인해주세요:


🏁 Script executed:

#!/bin/bash
# 새로운 useTicketOptionHook 모듈 존재 확인
fd "useTicketOptionHook" --type f

# 기존 useTicketHook에서 티켓 옵션 관련 코드가 제거되었는지 확인
rg -A 5 "useTicketOptions" src/features/ticket/hooks/useTicketHook.ts || echo "File not found or function removed"

Length of output: 231


훅 모듈 분리 및 import 변경 확인 완료

  • src/features/ticket/hooks/useTicketOptionHook.ts 모듈이 존재함을 확인했습니다.
  • 기존 useTicketHook에서 티켓 옵션 관련 로직이 제거된 것도 확인했습니다.

리팩토링에 따라 TicketOptionResponsePage가 올바르게 새로운 훅을 참조하고 있으며, TicketOptionLayout에 전달되는 options prop도 정상 동작할 것으로 보입니다. 변경 사항을 승인합니다.


18-18:

Details

✅ Verification successful

TicketOptionLayout에 options prop 추가 승인

TicketOptionLayout 컴포넌트에 options prop을 전달하여 데이터 흐름과 검증 로직을 개선한 것이 좋습니다. 컴포넌트가 필요한 데이터를 직접 받아 처리할 수 있게 되었습니다.

TicketOptionLayout 컴포넌트의 인터페이스 변경사항을 확인해주세요:


🏁 Script executed:

#!/bin/bash
# TicketOptionLayout 컴포넌트의 props 인터페이스 확인
ast-grep --pattern $'interface $_ {
  $$$
  options$_
  $$$
}'

Length of output: 63


아래 스크립트를 실행해서 TicketOptionLayout 컴포넌트 정의 위치와 props 타입(인터페이스 혹은 타입 별칭)에 실제로 options 필드가 포함되어 있는지 확인해주세요.


🏁 Script executed:

#!/bin/bash
# 1. TicketOptionLayout 컴포넌트가 정의된 파일 위치 확인
rg -n "export (const|function) TicketOptionLayout" -t tsx

# 2. 해당 파일 내 Props 타입(interface 또는 type) 정의 검색
rg -n "interface .*TicketOptionLayout.*" -t tsx
rg -n "type .*TicketOptionLayout.*" -t tsx

# 3. Props 정의 내에 options 필드가 있는지 확인
# (위에서 확인된 파일 경로를 FILE_PATH에, Props 이름을 PropsName에 치환)
# 예시:
# ast-grep --pattern $'interface PropsName { $$$ options$_ $$$ }' FILE_PATH

Length of output: 238


아래 스크립트를 실행해서 TicketOptionLayout 컴포넌트 정의 위치와 그 파일 내 Props 타입 및 options 필드 포함 여부를 확인해 주세요.


🏁 Script executed:

#!/bin/bash
# 1. 컴포넌트 정의된 파일 목록 조회(.ts/.tsx 모두 검색)
component_files=$(rg -l "export (const|function) TicketOptionLayout" --glob '*.ts' --glob '*.tsx')
echo "찾은 파일들:"
echo "$component_files"

# 2. 각 파일에서 Props 타입(interface 또는 type) 및 options 키워드 검색
for f in $component_files; do
  echo -e "\n===== $f ====="
  echo "Props 타입(interface/type) 위치:"
  rg -nE "interface .*|type .*" "$f"
  echo "파일 내 'options' 키워드 사용 위치:"
  rg -n "options" "$f"
done

Length of output: 137


아래 스크립트를 실행하여 TicketOptionLayout 컴포넌트 정의 위치와, 해당 파일 내 Props 타입에 options 필드가 포함되어 있는지 확인해주세요.


🏁 Script executed:

#!/bin/bash
# 1. 컴포넌트 정의(export) 위치 검색 (.ts/.tsx 모두)
echo "=== 컴포넌트 정의 (export) ==="
rg -nE "export (const|function)( *default)? +TicketOptionLayout" --glob '*.ts*'

# 2. default export 형태 검색
echo -e "\n=== default export 검색 ==="
rg -nE "export default TicketOptionLayout" --glob '*.ts*'

# 3. TicketOptionResponsePage.tsx 내 import 경로 확인
echo -e "\n=== TicketOptionResponsePage.tsx 내 import ==="
rg -n "import .*TicketOptionLayout" src/pages/dashboard/ui/ticket/TicketOptionResponsePage.tsx

# 4. 정의된 파일에서 Props 타입(interface 또는 type)과 'options' 필드 확인
#    ➜ 위에서 확인된 파일 경로를 FILE_PATH, Props 이름을 PropsName으로 치환 후 실행
# ast-grep --pattern $'interface PropsName { $$$ options$_ $$$ }' FILE_PATH
# 또는
# ast-grep --pattern $'type PropsName = { $$$ options$_ $$$ }' FILE_PATH

Length of output: 1354


아래 스크립트를 실행해서 TicketOptionLayout 컴포넌트 파일을 찾고, Props 정의에 options 필드가 포함되어 있는지 확인해 주세요.


🏁 Script executed:

#!/bin/bash
# 1. 컴포넌트 파일 경로 확인
echo "=== TicketOptionLayout 파일 ==="
ls shared/ui/backgrounds/TicketOptionLayout.* 2>/dev/null

# 2. 해당 파일 변수에 저장
file=$(ls shared/ui/backgrounds/TicketOptionLayout.* 2>/dev/null)
echo "파일 경로: $file"

# 3. Props 타입(interface 또는 type) 정의 확인
echo -e "\n=== Props 타입 정의 ==="
rg -nE "interface .*|type .*" "$file"

# 4. 파일 내 'options' 사용 위치 확인
echo -e "\n=== 'options' 키워드 검색 ==="
rg -n "options" "$file"

Length of output: 481


아래 스크립트를 실행하여 TicketOptionLayout 컴포넌트 파일 위치와, 해당 파일 내 Props 정의에 options 필드가 포함되어 있는지 확인해주세요.


🏁 Script executed:

#!/bin/bash
# 1. 컴포넌트 파일 전체 검색 (ts, tsx, js, jsx)
echo "=== TicketOptionLayout 파일 검색 ==="
find . -type f -regextype posix-egrep -regex '\./.*TicketOptionLayout\.(ts|tsx|js|jsx)' -print

# 2. 검색된 파일별로 Props 타입(interface 또는 type) 및 options 키워드 확인
for file in $(find . -type f -regextype posix-egrep -regex '\./.*TicketOptionLayout\.(ts|tsx|js|jsx)'); do
  echo -e "\n===== $file ====="
  echo "Props 타입(interface/type) 정의:"
  rg -nE "interface .*Props|type .*Props" "$file" || echo "  ➜ Props 정의 패턴 미발견"
  echo "'options' 키워드 검색:"
  rg -n "options" "$file" || echo "  ➜ options 필드 미발견"
done

Length of output: 1355


TicketOptionLayout 인터페이스에 options prop 반영 확인 및 승인

  • src/shared/ui/backgrounds/TicketOptionLayout.tsxTicketOptionLayoutProps
    options: TicketOptionResponse[] 필드 정의가 존재함을 확인했습니다.
  • TicketOptionLayout 컴포넌트에서 options를 정상적으로 받아 필터링 및 렌더링 로직에 사용하고 있습니다.

위 사항으로 변경 내용에 문제가 없으므로 승인합니다.

src/features/ticket/api/order.ts (1)

13-15: API 시그니처 단순화가 잘 구현되었습니다.

단일 orderId 매개변수를 사용하도록 변경한 것이 코드를 더 간결하고 이해하기 쉽게 만듭니다.

src/features/ticket/hooks/useOrderHook.ts (1)

14-18: 훅 시그니처 변경이 올바르게 구현되었습니다.

API 변경사항과 일치하며, enabled: !!orderId 조건을 통해 적절한 쿼리 실행 제어가 이루어지고 있습니다.

src/features/ticket/api/ticket.ts (1)

2-2: 사용하지 않는 타입 import가 적절히 제거되었습니다.

코드 정리와 모듈화가 잘 이루어졌습니다. 티켓 옵션 관련 기능을 별도 모듈로 분리한 것도 좋은 아키텍처 결정입니다.

src/features/dashboard/ui/ResponseFilter.tsx (2)

10-10: 타입 변경 확인

listType에서 'query' 옵션이 제거되었습니다. 이 변경이 다른 관련 컴포넌트들과 일관성 있게 적용되었는지 확인하세요.


52-54: 로직 단순화 승인

onSelect 핸들러에서 listType === 'query' 조건부 로직이 제거되고 직접적인 매칭으로 단순화되었습니다. 이는 'query' 타입 제거에 따른 적절한 변경입니다.

src/widgets/dashboard/ui/ResponsesFilterBar.tsx (1)

4-5: 인터페이스 업데이트 승인

ResponsesFilterBarProps에서 'query' 옵션이 제거되어 'summary''individual'만 남게 되었습니다. 이는 전체적인 리팩토링과 일치하는 변경사항입니다.

src/features/dashboard/api/participants.ts (1)

3-13:

Details

✅ Verification successful

API 시그니처 변경 검증 필요

getParticipants 함수가 명시적인 eventId 파라미터를 요구하도록 변경되었습니다. 이는 breaking change이므로 모든 호출 위치에서 eventId를 명시적으로 전달하고 있는지 확인하세요.

다음 스크립트를 실행하여 getParticipants 함수의 모든 사용 위치를 확인하세요:


🏁 Script executed:

#!/bin/bash
# Description: getParticipants 함수 사용 위치 확인

# getParticipants 호출 위치 검색
rg -A 3 "getParticipants" --type ts --type tsx

Length of output: 74


다음 스크립트를 실행하여 getParticipants 함수의 호출 위치를 다시 검색해 주세요:


🏁 Script executed:

#!/bin/bash
# Description: getParticipants 함수 사용 위치 재확인

# 확장자 .ts 및 .tsx 파일에서 호출 위치 검색
rg -n "getParticipants" -C 3 --glob "*.ts" --glob "*.tsx"

Length of output: 1516


API 시그니처 변경 확인 완료

getParticipants 호출이 모두 업데이트되어 eventId를 명시적으로 전달하고 있습니다 (src/features/dashboard/hook/useParticipants.ts). 추가 조치는 필요하지 않습니다.

src/features/ticket/hooks/useTicketHook.ts (1)

2-3:

Details

✅ Verification successful

모듈 분리 승인 및 검증 요청

티켓 옵션 관련 import가 제거되었습니다. AI 요약에 따르면 이들이 useTicketOptionHook.ts로 분리되었다고 하는데, 기존 코드에서 이 훅들을 사용하던 모든 위치가 새로운 import 경로로 업데이트되었는지 확인하세요.

다음 스크립트를 실행하여 분리된 훅들의 사용 위치를 확인하세요:


🏁 Script executed:

#!/bin/bash
# Description: 분리된 티켓 옵션 훅들의 사용 위치 확인

# 기존 파일에서 티켓 옵션 훅 import 검색 (잔여 참조 확인)
rg "useTicketOptions|useCreateTicketOptionAnswers" --type ts --type tsx

# 새로운 파일의 존재 확인
fd "useTicketOptionHook.ts"

Length of output: 178


다음 스크립트를 실행하여 “옛” 티켓 옵션 훅 사용 잔여 여부와 “새” 훅 사용 여부를 모두 확인해주세요:


🏁 Script executed:

#!/bin/bash
# 1. 기존 티켓 옵션 훅(useTicketOptions, useCreateTicketOptionAnswers) 사용 잔여 확인
rg "useTicketOptions|useCreateTicketOptionAnswers" -g "*.ts" -g "*.tsx" || true

# 2. 새로운 티켓 옵션 훅(useTicketOptionHook) import/사용 확인
rg "useTicketOptionHook" -g "*.ts" -g "*.tsx" || true

Length of output: 1297


추가 검증 요청: usePurchaserAnswers 훅 정의·내보내기 여부 확인

다음 스크립트를 실행해 useTicketOptionHook.tsusePurchaserAnswers가 제대로 정의(export)되어 있는지 확인해주세요.


🏁 Script executed:

#!/bin/bash
# Description: usePurchaserAnswers 훅이 export 되어 있는지 확인
rg -n "export.*usePurchaserAnswers" src/features/ticket/hooks/useTicketOptionHook.ts || true

Length of output: 155


모듈 분리 검증 완료

프로젝트 내 기존 티켓 옵션 훅 관련 모든 참조가 useTicketOptionHook.ts의 새로운 훅(useTicketOptions, useCreateTicketOptionAnswers, usePurchaserAnswers)으로 업데이트된 것을 확인했습니다. 더 이상 잔여 사용이 없습니다.

src/pages/menu/ui/MyTicketPage.tsx (3)

34-35: useTicketOrders 훅 사용법이 올바릅니다.

useEffect와 수동 상태 관리를 useTicketOrders 훅으로 대체한 리팩토링이 깔끔합니다. 데이터 가져오기 로직을 중앙화하여 코드의 재사용성과 일관성을 향상시켰습니다.


41-45: 로딩 및 에러 상태 처리가 적절합니다.

isLoadingisError 상태를 사용하여 사용자에게 적절한 피드백을 제공하고 있습니다. 에러 메시지에 적절한 스타일링(text-red-500)도 적용되어 있어 좋습니다.


63-63: Alt 텍스트 개선이 적절합니다.

이미지의 alt 텍스트를 "날짜"에서 "티켓"으로 변경한 것이 더 정확한 설명입니다.

src/features/dashboard/ui/MultiplePieCharts.tsx (3)

11-19: 응답 데이터 집계 로직이 효율적입니다.

aggregateAnswers 함수가 응답 데이터를 적절히 집계하고 있으며, Record<string, number> 타입을 사용하여 타입 안전성도 보장하고 있습니다.


21-23: 빈 데이터 상태 처리가 좋습니다.

응답 데이터가 없을 때 사용자에게 명확한 메시지를 표시하는 처리가 적절합니다.


4-4:

Details

❓ Verification inconclusive

색상 접근성을 검증해 보세요.

정의된 색상 팔레트가 색각 이상자나 접근성 요구사항을 충족하는지 확인하는 것이 좋겠습니다.


🏁 Script executed:

#!/bin/bash
# Description: Check color contrast ratios for accessibility compliance

echo "Color palette used in the component:"
echo "['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40']"
echo ""
echo "Please manually verify these colors meet WCAG contrast requirements"
echo "for charts and ensure they are distinguishable for colorblind users."

Length of output: 564


색상 접근성 검증 필요

컴포넌트에 사용된 팔레트(['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40'])가 WCAG 대비 비율과 색각 이상 사용자 관점에서 충분히 구분되는지 확인해 주세요.

• WCAG 대비 비율

  • 배경 대비 최소 3:1 (그래프 내부 요소) 또는 4.5:1 (텍스트 포함 요소) 충족 여부
    • 색각 이상 시 가독성
  • 프로토노팡(적색 약화), 듀테라노팡(녹색 약화), 트리타노팡(청색 약화) 시 색 분별 가능 여부
    • 검증 도구 활용
  • 온라인 대비 비율 체크(예: WebAIM Contrast Checker)
  • 색각 이상 시뮬레이터(예: Coblis, Color Oracle 등)
  • 자동화 테스트 통합(예: axe-core, contrast-checker npm 패키지)

위 항목을 기반으로 팔레트를 조정하거나 대체 색상을 추가해 접근성을 보강해 주세요.

src/pages/dashboard/ui/ResponseManagementPage.tsx (3)

11-11: listType에서 'query' 옵션 제거가 적절합니다.

UI 변경사항과 일치하게 'query' 옵션을 제거한 것이 좋습니다. 타입 정의가 더 명확해졌습니다.


31-31: 동적 응답 개수 표시가 좋습니다.

API에서 가져온 실제 데이터를 사용하여 응답 개수를 표시하는 것이 정확하고 사용자에게 유용한 정보를 제공합니다.


35-35: null 병합 연산자 사용이 안전합니다.

data?.result ?? []를 사용하여 undefined 상태를 안전하게 처리하고 있습니다.

src/features/ticket/model/ticketInformation.ts (3)

42-47: 타입 정의에 명확한 주석이 추가되었습니다.

기존 TicketOptionAnswerRequest 인터페이스에 "티켓 옵션 응답 전송" 주석을 추가하여 사용 목적을 명확히 했습니다.


49-59: 새로운 응답 타입 정의가 적절합니다.

TicketOptionAnswerTicketOptionAnswerResponse 타입이 API 응답 구조를 정확히 반영하고 있으며, MultiplePieCharts 컴포넌트에서 사용하기에 적합한 구조입니다.


61-65: 개별 응답 타입이 간결하고 명확합니다.

PersonalTicketOptionAnswerResponse 타입이 개별 응답 조회에 필요한 최소한의 정보만을 포함하여 효율적입니다.

src/shared/ui/backgrounds/TicketOptionLayout.tsx (2)

10-12: LGTM! 훅 모듈화가 잘 되었습니다.

티켓 옵션 관련 훅을 별도 모듈로 분리한 것은 코드 구조화에 도움이 됩니다.


100-100: 네비게이션 state 단순화가 적절합니다.

불필요한 ticketInfo 정보를 제거하고 orderIds만 전달하는 것은 좋은 결정입니다.

src/features/dashboard/ui/ResponsesList.tsx (1)

9-9: 'query' 타입이 여전히 props 인터페이스에 정의되어 있지만 처리되지 않습니다.

listType prop에 'query'가 포함되어 있지만 switch 문에서 처리되지 않아 null이 반환됩니다. 이것이 의도적인 변경인지 확인이 필요합니다.

'query' 타입을 제거하려면 타입 정의도 업데이트해야 합니다:

 interface ResponsesListProps {
-  listType: 'summary' | 'query' | 'individual';
+  listType: 'summary' | 'individual';
   ticketOptionResponses: TicketOptionAnswerResponse[];
 }

또는 'query' 케이스를 'summary'와 동일하게 처리하려면:

       case 'summary':
+      case 'query':
         return (

Also applies to: 39-39

src/features/ticket/api/ticketOption.ts (3)

1-2: imports가 적절하게 구성되어 있습니다.

필요한 타입 정의와 HTTP 클라이언트를 올바르게 import하고 있습니다.


5-8: 티켓 옵션 조회 함수가 잘 구현되어 있습니다.

함수 시그니처와 반환 타입이 명확하게 정의되어 있고, RESTful API 패턴을 잘 따르고 있습니다.


17-22: 구매자 응답 조회 함수가 올바르게 구현되어 있습니다.

쿼리 파라미터를 사용한 API 호출과 타입 정의가 적절합니다.

@github-actions
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (6)
src/features/ticket/model/orderInformation.ts (1)

7-7: 2차원 배열 구조에 대한 문서화 필요.

ticketOptionAnswers가 2차원 배열로 정의된 것은 페이지별 답변 그룹화를 위한 것으로 보입니다만, 이 구조의 목적을 명확히 하기 위해 JSDoc 주석을 추가하는 것을 권장합니다.

다음과 같이 주석을 추가해보세요:

+    /** 
+     * 페이지별로 그룹화된 티켓 옵션 답변 배열
+     * 외부 배열: 각 페이지를 나타냄
+     * 내부 배열: 해당 페이지의 옵션 답변들
+     */
     ticketOptionAnswers: TicketOptionAnswerRequest[][];
src/widgets/dashboard/ui/response/OrderAnswerModal.tsx (2)

24-28: IndividualResponseViewer의 불필요한 props 전달.

setCurrentIndex에 빈 함수를 전달하고 있으며, currentIndex가 항상 0으로 고정되어 있습니다. 단일 order만 표시하는 경우라면 이러한 네비게이션 관련 props가 필요한지 검토해보세요.

IndividualResponseViewer가 단일 아이템 표시를 위한 간소화된 모드를 지원한다면 더 적절할 것 같습니다.


15-22: 모달 접근성 및 사용성 개선 제안.

현재 모달 구현에서 다음 개선사항을 고려해보세요:

  1. 키보드 ESC 키로 모달 닫기
  2. 모달 외부 클릭으로 닫기
  3. 접근성을 위한 ARIA 속성 추가
  4. 포커스 트랩

다음과 같이 개선할 수 있습니다:

+    useEffect(() => {
+        const handleEscape = (e: KeyboardEvent) => {
+            if (e.key === 'Escape') onClose();
+        };
+        if (isOpen) {
+            document.addEventListener('keydown', handleEscape);
+            return () => document.removeEventListener('keydown', handleEscape);
+        }
+    }, [isOpen, onClose]);

     return (
-        <div className="fixed inset-0 flex items-center justify-center w-full max-w-lg h-full mx-auto bg-black bg-opacity-30 z-30">
+        <div 
+            className="fixed inset-0 flex items-center justify-center w-full max-w-lg h-full mx-auto bg-black bg-opacity-30 z-30"
+            onClick={onClose}
+            role="dialog"
+            aria-modal="true"
+        >
-            <div className="relative flex flex-col w-[95%] px-4 py-4 gap-7 rounded-[5px] bg-white">
+            <div 
+                className="relative flex flex-col w-[95%] px-4 py-4 gap-7 rounded-[5px] bg-white"
+                onClick={(e) => e.stopPropagation()}
+            >
src/features/ticket/util/buildTicketOptionAnswers.tsx (2)

1-32: 파일 확장자 변경 및 입력 검증 추가 제안.

이 파일은 React 컴포넌트가 아닌 순수 유틸리티 함수이므로 .ts 확장자를 사용하는 것이 더 적절합니다.

또한 함수의 견고성을 위해 입력 검증을 추가하는 것을 권장합니다:

 export const buildTicketOptionAnswers = (
   selectedOptions: Record<number, Record<number, string | number | number[]>>
 ): TicketOptionAnswerRequest[][] => {
+  if (!selectedOptions || typeof selectedOptions !== 'object') {
+    return [];
+  }
+
   const ticketOptionAnswers: TicketOptionAnswerRequest[][] = [];

19-26: 빈 값 및 잘못된 값 처리 추가 제안.

현재 구현에서는 빈 문자열이나 빈 배열 등의 경우를 처리하지 않습니다. 데이터 일관성을 위해 이러한 경우들을 필터링하는 것을 고려해보세요.

       if (typeof value === "string") {
+        if (value.trim()) {
           answerList.push({ ticketOptionId, answerText: value });
+        }
       } else if (typeof value === "number") {
+        if (value > 0) {
           answerList.push({ ticketOptionId, ticketOptionChoiceId: value });
+        }
       } else if (Array.isArray(value)) {
+        const validIds = value.filter(id => typeof id === 'number' && id > 0);
+        if (validIds.length > 0) {
-          answerList.push({ ticketOptionId, ticketOptionChoiceIds: value });
+          answerList.push({ ticketOptionId, ticketOptionChoiceIds: validIds });
+        }
       }
src/features/dashboard/ui/PariticipantsList.tsx (1)

48-49: 사용자 경험 개선을 위해 alert 대신 더 나은 UI 피드백을 사용하세요.

alert는 사용자 경험을 방해합니다. Toast 알림이나 모달 내 메시지 표시를 고려해보세요.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e4575f and d7a64a1.

📒 Files selected for processing (18)
  • src/features/dashboard/model/store/ParticipantStore.tsx (2 hunks)
  • src/features/dashboard/model/store/ResponseStore.tsx (1 hunks)
  • src/features/dashboard/ui/IndividualResponseViewer.tsx (1 hunks)
  • src/features/dashboard/ui/ParicipantCard.tsx (2 hunks)
  • src/features/dashboard/ui/PariticipantsList.tsx (3 hunks)
  • src/features/dashboard/ui/ResponsesList.tsx (1 hunks)
  • src/features/dashboard/ui/SelectedResponseList.tsx (0 hunks)
  • src/features/ticket/api/order.ts (1 hunks)
  • src/features/ticket/model/orderInformation.ts (1 hunks)
  • src/features/ticket/model/ticketInformation.ts (1 hunks)
  • src/features/ticket/util/buildTicketOptionAnswers.tsx (1 hunks)
  • src/pages/dashboard/ui/ResponseManagementPage.tsx (1 hunks)
  • src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (1 hunks)
  • src/shared/types/participantInfoType.ts (1 hunks)
  • src/shared/ui/backgrounds/TicketOptionLayout.tsx (3 hunks)
  • src/widgets/dashboard/ui/response/OrderAnswerModal.tsx (1 hunks)
  • src/widgets/dashboard/ui/response/ResponseModal.tsx (0 hunks)
  • src/widgets/event/ui/TicketInfo.tsx (2 hunks)
💤 Files with no reviewable changes (2)
  • src/widgets/dashboard/ui/response/ResponseModal.tsx
  • src/features/dashboard/ui/SelectedResponseList.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/features/dashboard/model/store/ResponseStore.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/features/ticket/api/order.ts
  • src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx
  • src/features/dashboard/ui/ParicipantCard.tsx
  • src/pages/dashboard/ui/ResponseManagementPage.tsx
  • src/shared/ui/backgrounds/TicketOptionLayout.tsx
  • src/features/ticket/model/ticketInformation.ts
🧰 Additional context used
🧬 Code Graph Analysis (7)
src/features/ticket/model/orderInformation.ts (1)
src/features/ticket/model/ticketInformation.ts (1)
  • TicketOptionAnswerRequest (43-48)
src/widgets/event/ui/TicketInfo.tsx (4)
src/features/ticket/hooks/useTicketHook.ts (1)
  • useTickets (7-13)
src/features/ticket/api/order.ts (1)
  • orderTickets (20-23)
src/features/ticket/hooks/useOrderHook.ts (1)
  • useOrderTicket (36-43)
src/features/ticket/api/ticketOption.ts (1)
  • readTicketOptions (5-8)
src/features/dashboard/ui/PariticipantsList.tsx (2)
src/features/dashboard/model/store/ParticipantStore.tsx (1)
  • useParticipantStore (19-87)
src/features/ticket/hooks/useTicketOptionHook.ts (1)
  • usePersonalTicketOptionAnswers (42-53)
src/features/dashboard/ui/IndividualResponseViewer.tsx (1)
src/features/ticket/model/ticketInformation.ts (1)
  • Order (68-71)
src/features/ticket/util/buildTicketOptionAnswers.tsx (1)
src/features/ticket/model/ticketInformation.ts (1)
  • TicketOptionAnswerRequest (43-48)
src/widgets/dashboard/ui/response/OrderAnswerModal.tsx (1)
src/features/ticket/model/ticketInformation.ts (1)
  • Order (68-71)
src/features/dashboard/ui/ResponsesList.tsx (3)
src/features/ticket/model/ticketInformation.ts (1)
  • TicketOptionAnswerResponse (55-60)
src/features/ticket/hooks/useTicketOptionHook.ts (1)
  • usePersonalTicketOptionAnswers (42-53)
src/features/dashboard/model/store/ResponseStore.tsx (1)
  • useResponseStore (21-61)
🪛 ESLint
src/widgets/event/ui/TicketInfo.tsx

[error] 72-72: 'e' is defined but never used.

(@typescript-eslint/no-unused-vars)

src/features/dashboard/ui/PariticipantsList.tsx

[error] 30-30: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

src/features/dashboard/ui/ResponsesList.tsx

[error] 62-64: Unexpected lexical declaration in case block.

(no-case-declarations)


[error] 80-80: Unexpected lexical declaration in case block.

(no-case-declarations)

🪛 Biome (1.9.4)
src/features/dashboard/ui/ResponsesList.tsx

[error] 62-65: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 80-82: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: storybook
🔇 Additional comments (6)
src/widgets/event/ui/TicketInfo.tsx (3)

6-7: 새로운 API 통합이 잘 구현되었습니다.

티켓 옵션과 주문 관련 기능이 올바르게 분리되어 import되었습니다.


14-14: 훅 사용법이 적절합니다.

useOrderTicket 훅을 통해 주문 기능을 깔끔하게 활용하고 있습니다.


40-59: 직접 주문 기능이 잘 구현되었습니다.

옵션이 없는 티켓에 대한 직접 주문 플로우가 명확하고 적절한 에러 처리와 함께 구현되었습니다. 성공 시 적절한 페이지로 네비게이션하는 로직도 올바릅니다.

src/features/ticket/model/orderInformation.ts (1)

1-1: import 문 승인.

TicketOptionAnswerRequest 타입의 import가 올바르게 추가되었습니다.

src/features/ticket/util/buildTicketOptionAnswers.tsx (1)

8-10: 페이지 인덱스 정렬 로직 승인.

페이지 인덱스를 숫자로 변환하여 정렬하는 로직이 올바르게 구현되었습니다. 이는 순서가 중요한 티켓 옵션 답변에서 중요한 부분입니다.

src/features/dashboard/ui/IndividualResponseViewer.tsx (1)

1-82: 잘 구현된 컴포넌트입니다!

개별 응답 뷰어가 깔끔하게 구현되었습니다. 그룹화 로직과 네비게이션 처리가 적절합니다.

@github-actions
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/features/dashboard/ui/IndividualResponseViewer.tsx (1)

18-24: 성능 최적화를 위해 메모이제이션을 적용하세요.

groupedAnswers 계산이 매 렌더링마다 실행됩니다. useMemo를 사용하여 최적화할 수 있습니다.

다음과 같이 성능을 개선하세요:

+import { useMemo } from 'react';

-    const groupedAnswers = currentOrder.optionAnswers.reduce<Record<string, { optionType: string; answers: string[] }>>((acc, cur) => {
-        if (!acc[cur.optionName]) {
-            acc[cur.optionName] = { optionType: cur.optionType, answers: [] };
-        }
-        acc[cur.optionName].answers.push(cur.answer);
-        return acc;
-    }, {});
+    const groupedAnswers = useMemo(() => 
+        currentOrder.optionAnswers.reduce<Record<string, { optionType: string; answers: string[] }>>((acc, cur) => {
+            if (!acc[cur.optionName]) {
+                acc[cur.optionName] = { optionType: cur.optionType, answers: [] };
+            }
+            acc[cur.optionName].answers.push(cur.answer);
+            return acc;
+        }, {}), [currentOrder.optionAnswers]
+    );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d7a64a1 and 3fcc41d.

📒 Files selected for processing (6)
  • src/features/dashboard/model/store/ParticipantStore.tsx (2 hunks)
  • src/features/dashboard/ui/IndividualResponseViewer.tsx (1 hunks)
  • src/features/dashboard/ui/PariticipantsList.tsx (3 hunks)
  • src/features/dashboard/ui/ResponsesList.tsx (1 hunks)
  • src/features/ticket/model/orderInformation.ts (1 hunks)
  • src/widgets/event/ui/TicketInfo.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/features/ticket/model/orderInformation.ts
  • src/features/dashboard/ui/PariticipantsList.tsx
  • src/widgets/event/ui/TicketInfo.tsx
  • src/features/dashboard/model/store/ParticipantStore.tsx
  • src/features/dashboard/ui/ResponsesList.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/features/dashboard/ui/IndividualResponseViewer.tsx (1)
src/features/ticket/model/ticketInformation.ts (1)
  • Order (68-71)
🪛 ESLint
src/features/dashboard/ui/IndividualResponseViewer.tsx

[error] 6-6: 'UnderlineTextField' is defined but never used.

(@typescript-eslint/no-unused-vars)

🔇 Additional comments (3)
src/features/dashboard/ui/IndividualResponseViewer.tsx (3)

55-60: TEXT 타입 응답의 안전성을 검증하세요.

answers[0]에 접근할 때 배열이 비어있을 수 있는 경우를 고려해야 합니다.

다음과 같이 안전한 접근을 구현하세요:

                        {optionType === 'TEXT' ? (
                            <div className="mb-4">
                                <p className="w-full border-b border-gray-300 py-2 px-1 text-sm font-semibold text-gray-800">
-                                    {answers[0]}
+                                    {answers[0] || '응답 없음'}
                                </p>
                            </div>

26-32: 네비게이션 로직이 올바르게 구현되었습니다.

경계값 체크가 적절히 구현되어 있어 배열 인덱스 범위를 벗어나는 것을 방지합니다.


8-12: 인터페이스 정의가 적절합니다.

setCurrentIndex의 함수 시그니처가 React의 setState 패턴을 올바르게 따르고 있습니다.

@github-actions
Copy link
Copy Markdown

@hyeeuncho hyeeuncho added the 🔧 Feature 기능 구현 label May 28, 2025
@hyeeuncho hyeeuncho requested a review from Yejiin21 May 28, 2025 11:52
Copy link
Copy Markdown
Contributor

@Yejiin21 Yejiin21 left a comment

Choose a reason for hiding this comment

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

어려운 로직이었는데 수고하셨습니다 LGTM~

@hyeeuncho hyeeuncho force-pushed the feat/#128/response-management-api branch from f58adf9 to ee03543 Compare May 28, 2025 12:36
@github-actions
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
src/features/ticket/hooks/useTicketHook.ts (1)

15-39: 🛠️ Refactor suggestion

사용자 경험 개선을 위한 에러 핸들링 리팩토링 제안

현재 alert()window.location.reload()를 사용한 방식은 다음과 같은 개선이 필요합니다:

  1. Toast 알림 시스템 도입: alert() 대신 비침입적인 토스트 알림 사용
  2. 쿼리 무효화: window.location.reload() 대신 React Query의 쿼리 무효화 사용
  3. 중앙화된 에러 처리: 공통 에러 핸들링 훅 활용

개선된 구현 예시:

export const useCreateTicket = () => {
+ const queryClient = useQueryClient();
+ const { showToast } = useToast();
+ 
  return useMutation<ApiResponse<null>, AxiosError, CreateTicketRequest>({
    mutationFn: createTicket,
    onSuccess: () => {
-     alert('티켓이 성공적으로 저장되었습니다.');
-     window.location.reload();
+     showToast('티켓이 성공적으로 저장되었습니다.', 'success');
+     queryClient.invalidateQueries({ queryKey: ['tickets'] });
    },
    onError: () => {
-     alert('티켓 저장에 실패했습니다. 다시 시도해주세요.');
+     showToast('티켓 저장에 실패했습니다. 다시 시도해주세요.', 'error');
    },
  });
};
🧹 Nitpick comments (4)
src/features/dashboard/ui/MultiplePieCharts.tsx (4)

1-4: 컬러 팔레트 개선 및 상수 관리 최적화 권장

현재 컬러 배열이 하드코딩되어 있으며, 접근성과 확장성 측면에서 개선이 필요합니다.

다음과 같이 개선할 수 있습니다:

-const COLORS = ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40'];
+// 접근성을 고려한 대비가 높은 컬러 팔레트
+const COLORS = [
+  '#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b',
+  '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'
+] as const;

더 많은 색상과 더 나은 색상 대비를 제공하여 접근성을 향상시킬 수 있습니다.


10-19: 데이터 변환 로직 최적화 및 타입 안전성 강화

aggregateAnswers 함수의 로직은 올바르지만, 성능과 타입 안전성 측면에서 개선할 수 있습니다.

다음과 같이 최적화할 수 있습니다:

+type ChartData = {
+  name: string;
+  value: number;
+};
+
-const aggregateAnswers = (answers: TicketOptionAnswer[]) => {
+const aggregateAnswers = (answers: TicketOptionAnswer[]): ChartData[] => {
   const countMap: Record<string, number> = {};

   answers.forEach(({ answer }) => {
     countMap[answer] = (countMap[answer] || 0) + 1;
   });

-  return Object.entries(countMap).map(([name, value]) => ({ name, value }));
+  return Object.entries(countMap)
+    .map(([name, value]) => ({ name, value }))
+    .sort((a, b) => b.value - a.value); // 값에 따라 정렬하여 시각적 일관성 향상
};

명시적인 반환 타입과 정렬을 추가하여 더 나은 사용자 경험을 제공할 수 있습니다.


10-57: 성능 최적화를 위한 메모이제이션 추가 권장

현재 구현은 매 렌더링마다 데이터 집계를 수행하므로, 큰 데이터셋에서 성능 이슈가 발생할 수 있습니다.

React의 useMemo를 사용하여 성능을 최적화할 수 있습니다:

+import { useMemo } from 'react';
 import { PieChart, Pie, Cell, Legend, ResponsiveContainer } from 'recharts';

 const MultiplePieCharts = ({ responses }: MultiplePieChartsProps) => {
+  const processedResponses = useMemo(() => {
+    return responses.map(option => ({
+      ...option,
+      chartData: aggregateAnswers(option.answers)
+    }));
+  }, [responses]);

   // ... 나머지 로직에서 processedResponses 사용

이렇게 하면 responses가 변경되지 않는 한 데이터 집계를 다시 수행하지 않습니다.

🧰 Tools
🪛 ESLint

[error] 27-27: '_index' is defined but never used.

(@typescript-eslint/no-unused-vars)


21-23: 빈 상태 처리 개선

현재 빈 상태 처리는 적절하지만, 더 나은 사용자 경험을 위해 개선할 수 있습니다.

더 나은 시각적 피드백을 위해 다음과 같이 개선할 수 있습니다:

 if (responses.length === 0) {
-  return <p className="text-center text-gray-500 py-8">응답 데이터가 없습니다.</p>;
+  return (
+    <div className="flex flex-col items-center justify-center py-12">
+      <div className="text-gray-400 mb-2">
+        <svg className="w-12 h-12 mx-auto" fill="currentColor" viewBox="0 0 20 20">
+          <path fillRule="evenodd" d="M3 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clipRule="evenodd" />
+        </svg>
+      </div>
+      <p className="text-center text-gray-500">응답 데이터가 없습니다.</p>
+    </div>
+  );
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f58adf9 and ee03543.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (31)
  • package.json (1 hunks)
  • src/features/dashboard/api/participants.ts (1 hunks)
  • src/features/dashboard/model/store/ParticipantStore.tsx (2 hunks)
  • src/features/dashboard/model/store/ResponseStore.tsx (1 hunks)
  • src/features/dashboard/ui/IndividualResponseViewer.tsx (1 hunks)
  • src/features/dashboard/ui/MultiplePieCharts.tsx (1 hunks)
  • src/features/dashboard/ui/ParicipantCard.tsx (2 hunks)
  • src/features/dashboard/ui/PariticipantsList.tsx (3 hunks)
  • src/features/dashboard/ui/ResponseFilter.tsx (2 hunks)
  • src/features/dashboard/ui/ResponsesList.tsx (1 hunks)
  • src/features/dashboard/ui/SelectedResponseList.tsx (0 hunks)
  • src/features/payment/ui/TicketOption.tsx (1 hunks)
  • src/features/ticket/api/order.ts (1 hunks)
  • src/features/ticket/api/ticket.ts (1 hunks)
  • src/features/ticket/api/ticketOption.ts (1 hunks)
  • src/features/ticket/hooks/useOrderHook.ts (1 hunks)
  • src/features/ticket/hooks/useTicketHook.ts (2 hunks)
  • src/features/ticket/hooks/useTicketOptionHook.ts (1 hunks)
  • src/features/ticket/model/orderInformation.ts (1 hunks)
  • src/features/ticket/model/ticketInformation.ts (1 hunks)
  • src/features/ticket/util/buildTicketOptionAnswers.tsx (1 hunks)
  • src/pages/dashboard/ui/ResponseManagementPage.tsx (1 hunks)
  • src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (1 hunks)
  • src/pages/dashboard/ui/ticket/TicketOptionResponsePage.tsx (2 hunks)
  • src/pages/menu/ui/MyTicketPage.tsx (3 hunks)
  • src/shared/types/participantInfoType.ts (1 hunks)
  • src/shared/ui/backgrounds/TicketOptionLayout.tsx (3 hunks)
  • src/widgets/dashboard/ui/ResponsesFilterBar.tsx (1 hunks)
  • src/widgets/dashboard/ui/response/OrderAnswerModal.tsx (1 hunks)
  • src/widgets/dashboard/ui/response/ResponseModal.tsx (0 hunks)
  • src/widgets/event/ui/TicketInfo.tsx (2 hunks)
💤 Files with no reviewable changes (2)
  • src/widgets/dashboard/ui/response/ResponseModal.tsx
  • src/features/dashboard/ui/SelectedResponseList.tsx
✅ Files skipped from review due to trivial changes (2)
  • src/features/dashboard/model/store/ResponseStore.tsx
  • src/features/ticket/api/ticket.ts
🚧 Files skipped from review as they are similar to previous changes (25)
  • src/features/payment/ui/TicketOption.tsx
  • package.json
  • src/features/ticket/api/order.ts
  • src/features/ticket/model/orderInformation.ts
  • src/shared/types/participantInfoType.ts
  • src/pages/dashboard/ui/ticket/TicketOptionResponsePage.tsx
  • src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx
  • src/features/dashboard/ui/ParicipantCard.tsx
  • src/features/dashboard/api/participants.ts
  • src/pages/menu/ui/MyTicketPage.tsx
  • src/features/ticket/util/buildTicketOptionAnswers.tsx
  • src/features/dashboard/ui/PariticipantsList.tsx
  • src/widgets/dashboard/ui/ResponsesFilterBar.tsx
  • src/features/dashboard/ui/IndividualResponseViewer.tsx
  • src/widgets/dashboard/ui/response/OrderAnswerModal.tsx
  • src/features/ticket/hooks/useOrderHook.ts
  • src/pages/dashboard/ui/ResponseManagementPage.tsx
  • src/features/dashboard/ui/ResponseFilter.tsx
  • src/features/ticket/hooks/useTicketOptionHook.ts
  • src/widgets/event/ui/TicketInfo.tsx
  • src/shared/ui/backgrounds/TicketOptionLayout.tsx
  • src/features/dashboard/model/store/ParticipantStore.tsx
  • src/features/ticket/model/ticketInformation.ts
  • src/features/dashboard/ui/ResponsesList.tsx
  • src/features/ticket/api/ticketOption.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/features/dashboard/ui/MultiplePieCharts.tsx (1)
src/features/ticket/model/ticketInformation.ts (2)
  • TicketOptionAnswerResponse (55-60)
  • TicketOptionAnswer (51-54)
🪛 ESLint
src/features/dashboard/ui/MultiplePieCharts.tsx

[error] 27-27: '_index' is defined but never used.

(@typescript-eslint/no-unused-vars)

🔇 Additional comments (2)
src/features/ticket/hooks/useTicketHook.ts (2)

2-3: 관심사 분리를 위한 리팩토링 승인

티켓 옵션 관련 API 및 타입을 별도 모듈로 분리한 것은 좋은 설계입니다. 이를 통해 각 훅이 단일 책임을 가지도록 개선되었습니다.


1-39:

Details

✅ Verification successful

제거된 티켓 옵션 기능의 가용성 확인

티켓 옵션 관련 훅들이 이 파일에서 제거되었습니다. 새로운 전용 모듈에서 동일한 기능을 제공하는지 확인이 필요합니다.


🏁 Script executed:

#!/bin/bash
# 새로운 티켓 옵션 모듈들이 존재하고 예상된 기능을 제공하는지 확인

echo "=== 새로운 티켓 옵션 파일들 확인 ==="
fd -t f -e ts "ticketOption" src/features/ticket/

echo -e "\n=== useTicketOptionHook.ts 내용 확인 ==="
cat src/features/ticket/hooks/useTicketOptionHook.ts 2>/dev/null || echo "파일이 존재하지 않음"

echo -e "\n=== ticketOption.ts API 파일 확인 ==="
cat src/features/ticket/api/ticketOption.ts 2>/dev/null || echo "파일이 존재하지 않음"

echo -e "\n=== 티켓 옵션 훅 사용처 확인 ==="
rg -A 3 "useTicketOptions|useCreateTicketOptionAnswers" src/ --type ts

Length of output: 5459


티켓 옵션 기능 전용 모듈 이전 완료 확인

새로운 src/features/ticket/api/ticketOption.ts
src/features/ticket/hooks/useTicketOptionHook.ts 에서
티켓 옵션 조회, 응답 생성·조회 기능이 모두 구현되어 있으며,
TicketOptionResponsePage.tsx 등에서도 해당 훅을 정상적으로 사용하고 있습니다.
따라서 기존 useTicketHook.ts에서 제거된 티켓 옵션 기능은
전용 모듈로 완전히 대체되었음을 확인했습니다. 추가 조치가 필요 없습니다.

Comment on lines +25 to +57
return (
<div className="grid grid-cols-1 gap-6 p-4">
{responses.map((option, _index) => {
const data = aggregateAnswers(option.answers);

return (
<div key={option.optionId} className="flex flex-col items-center">
<h3 className="mb-2 font-semibold text-lg">{option.optionName}</h3>
<ResponsiveContainer width="100%" height={300}>
<PieChart>
<Pie
data={data}
dataKey="value"
nameKey="name"
cx="50%"
cy="50%"
outerRadius={80}
label
stroke="none"
>
{data.map((_, i) => (
<Cell key={`cell-${i}`} fill={COLORS[i % COLORS.length]} />
))}
</Pie>
<Legend />
</PieChart>
</ResponsiveContainer>
</div>
);
})}
</div>
);
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

사용되지 않는 변수 제거 및 매직 넘버 상수화

정적 분석에서 지적한 사용되지 않는 변수와 매직 넘버들을 개선해야 합니다.

다음 diff를 적용하여 문제를 해결하세요:

+// 차트 설정 상수
+const CHART_CONFIG = {
+  HEIGHT: 300,
+  OUTER_RADIUS: 80,
+} as const;
+
 return (
   <div className="grid grid-cols-1 gap-6 p-4">
-    {responses.map((option, _index) => {
+    {responses.map((option) => {
       const data = aggregateAnswers(option.answers);

       return (
         <div key={option.optionId} className="flex flex-col items-center">
           <h3 className="mb-2 font-semibold text-lg">{option.optionName}</h3>
-          <ResponsiveContainer width="100%" height={300}>
+          <ResponsiveContainer width="100%" height={CHART_CONFIG.HEIGHT}>
             <PieChart>
               <Pie
                 data={data}
                 dataKey="value"
                 nameKey="name"
                 cx="50%"
                 cy="50%"
-                outerRadius={80}
+                outerRadius={CHART_CONFIG.OUTER_RADIUS}
                 label
                 stroke="none"
               >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return (
<div className="grid grid-cols-1 gap-6 p-4">
{responses.map((option, _index) => {
const data = aggregateAnswers(option.answers);
return (
<div key={option.optionId} className="flex flex-col items-center">
<h3 className="mb-2 font-semibold text-lg">{option.optionName}</h3>
<ResponsiveContainer width="100%" height={300}>
<PieChart>
<Pie
data={data}
dataKey="value"
nameKey="name"
cx="50%"
cy="50%"
outerRadius={80}
label
stroke="none"
>
{data.map((_, i) => (
<Cell key={`cell-${i}`} fill={COLORS[i % COLORS.length]} />
))}
</Pie>
<Legend />
</PieChart>
</ResponsiveContainer>
</div>
);
})}
</div>
);
};
// 차트 설정 상수
const CHART_CONFIG = {
HEIGHT: 300,
OUTER_RADIUS: 80,
} as const;
return (
<div className="grid grid-cols-1 gap-6 p-4">
{responses.map((option) => {
const data = aggregateAnswers(option.answers);
return (
<div key={option.optionId} className="flex flex-col items-center">
<h3 className="mb-2 font-semibold text-lg">{option.optionName}</h3>
<ResponsiveContainer width="100%" height={CHART_CONFIG.HEIGHT}>
<PieChart>
<Pie
data={data}
dataKey="value"
nameKey="name"
cx="50%"
cy="50%"
outerRadius={CHART_CONFIG.OUTER_RADIUS}
label
stroke="none"
>
{data.map((_, i) => (
<Cell key={`cell-${i}`} fill={COLORS[i % COLORS.length]} />
))}
</Pie>
<Legend />
</PieChart>
</ResponsiveContainer>
</div>
);
})}
</div>
);
🧰 Tools
🪛 ESLint

[error] 27-27: '_index' is defined but never used.

(@typescript-eslint/no-unused-vars)

🤖 Prompt for AI Agents
In src/features/dashboard/ui/MultiplePieCharts.tsx between lines 25 and 57,
remove the unused variable _index from the map function parameters and replace
the hardcoded height value 300 with a named constant defined at the top of the
file. This eliminates unused variables and magic numbers, improving code clarity
and maintainability.

@hyeeuncho hyeeuncho merged commit b8153a7 into develop May 28, 2025
2 checks passed
@hyeeuncho hyeeuncho deleted the feat/#128/response-management-api branch May 28, 2025 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔧 Feature 기능 구현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 사용자 응답 관리 페이지 API 연동

2 participants