Skip to content

feat: 티켓 구매 API 연동#93

Merged
hyeeuncho merged 7 commits intodevelopfrom
feat/#92/ticket-order-api
Apr 8, 2025
Merged

feat: 티켓 구매 API 연동#93
hyeeuncho merged 7 commits intodevelopfrom
feat/#92/ticket-order-api

Conversation

@hyeeuncho
Copy link
Copy Markdown
Member

@hyeeuncho hyeeuncho commented Apr 4, 2025

구매 API 연동

스크린샷 2025-04-04 오후 4 27 58

페이지 이동 후 티켓 상세 조회 API 연동

스크린샷 2025-04-04 오후 4 26 29

취소 API 연동

스크린샷 2025-04-05 오전 2 03 15

Summary by CodeRabbit

  • New Features
    • 티켓 조회, 주문, 취소 기능이 강화되어 개별 티켓 상세 정보 확인 및 주문 후 결제 확인 페이지로 전환됩니다.
    • 이벤트 구매 배너가 동적으로 이벤트 정보를 표시하며, 주최자 정보 컴포넌트가 배경 색상 커스터마이징을 지원합니다.
  • Refactor
    • 티켓 관리 API와 UI의 상태 관리 및 렌더링 로직이 개선되어 보다 안정적인 티켓 처리가 가능합니다.
  • Chore
    • 불필요한 코드와 사용되지 않는 컴포넌트가 제거되어 코드 정리가 이루어졌습니다.

@hyeeuncho hyeeuncho added the 🔧 Feature 기능 구현 label Apr 4, 2025
@hyeeuncho hyeeuncho self-assigned this Apr 4, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 4, 2025

Walkthrough

이번 풀 리퀘스트는 티켓 관리 API와 UI 컴포넌트의 기능을 확장하고 리팩토링하는 변경사항을 포함합니다. API 측면에서는 기존의 readMyTicketsreadTicket으로 대체되고, 티켓 목록 조회(getAll), 티켓 상세 조회(getDetail), 주문 생성(orderTickets), 티켓 취소(cancleTickets) 기능이 추가되었습니다. 또한, 티켓 주문 요청에 사용되는 OrderTicketRequest 인터페이스가 도입되었습니다. 대시보드와 메뉴 페이지에서는 해당 API 변경사항에 맞춰 티켓 조회 및 취소 로직이 업데이트되었으며, 일부 불필요한 UI 컴포넌트가 삭제되고 새로운 prop 기반 컴포넌트 업데이트가 이루어졌습니다.

Changes

파일 경로 변경 사항 요약
src/features/ticket/api/order.ts readMyTicketsreadTicket 리팩토링, getAllgetDetail 메서드 추가, 주문(orderTickets) 및 취소(cancleTickets) 함수 추가
src/features/ticket/model/OrderCreation.ts 주문 요청 인터페이스 OrderTicketRequest 추가 (속성: ticketId, eventId, ticketCnt)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx 티켓 확인 페이지 업데이트: 위치 상태 활용, readTicket.getDetail 호출, 티켓 취소 처리 함수 cancleOrderTicket 추가
src/pages/menu/ui/MyTicketPage.tsx 티켓 조회 로직 업데이트: API 호출을 readTicket.getAll로 변경, 리스트 렌더링 시 key를 티켓 id 사용하도록 수정
src/pages/event/ui/EventDetailsPage.tsx 불필요한 빈 줄 제거 (기능에는 영향 없음)
src/shared/types/api/http-client.ts response.config.data가 정의되어 있는지 조건부 확인 후 JSON 파싱하여 로깅하도록 개선
src/widgets/dashboard/ui/TicketConfirmPage/LocationInfo.tsx
src/widgets/dashboard/ui/TicketConfirmPage/OrganizerInfo.tsx
src/widgets/dashboard/ui/TicketConfirmPage/PurchaseBanner.tsx
대시보드 티켓 확인 관련 컴포넌트 변경: LocationInfo와 대시보드용 OrganizerInfo 삭제, PurchaseBanner 컴포넌트는 새 인터페이스 PurchaseBannerPrpos 도입 및 동적 prop 적용
src/widgets/event/ui/OrganizerInfo.tsx OrganizerInfoProps에 선택적 프로퍼티 bgColor 추가 (기본값: "bg-gray-100")
src/widgets/event/ui/TicketInfo.tsx 티켓 구매 프로세스 개선: 새 orderTicket 비동기 함수 도입, API 호출 후 주문 결과 기반 페이지 네비게이션(useNavigate) 처리 및 사용자 피드백 로직 추가

Sequence Diagram(s)

sequenceDiagram
    participant U as 사용자
    participant TI as TicketInfo 컴포넌트
    participant API as 티켓 API (orderTickets)
    participant Nav as 네비게이션

    U->>TI: 구매 버튼 클릭
    TI->>API: orderTickets(OrderTicketRequest) 호출
    API-->>TI: 주문 결과 (orderIds) 반환
    TI->>Nav: 결제 확인 페이지로 이동
Loading
sequenceDiagram
    participant U as 사용자
    participant TCP as TicketConfirmPage 컴포넌트
    participant API as 티켓 API (cancleTickets)
    participant Nav as 네비게이션

    U->>TCP: 티켓 취소 요청
    TCP->>API: 각 orderId별로 cancleTickets 호출
    API-->>TCP: 취소 결과 반환
    TCP->>Nav: 마이티켓 메뉴로 이동
Loading

Possibly related PRs

Suggested reviewers

  • Yejiin21
  • xaexunxang

Poem

토끼가 말하죠, "풀밭 위에서 코드 춤추며,
티켓 주문과 취소가 깔끔해졌네!
API의 바람 따라 주문 날아가고,
페이지는 반짝이며 새로운 길 열리네.
귀여운 발자국으로 모두 축하하자,
🐇 새로운 변화에 즐거움 가득!"

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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

github-actions bot commented Apr 4, 2025

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: 2

🧹 Nitpick comments (7)
src/widgets/event/ui/OrganizerInfo.tsx (1)

15-15: 동적 스타일링 적용이 잘 되었습니다.

템플릿 리터럴을 사용해 동적으로 bgColor를 적용하는 구현이 적절합니다.

향후에는 bgColor prop에 대해 좀 더 타입 안전한 접근 방식을 고려해볼 수 있습니다. 예를 들어:

// 예시: 허용된 배경색 타입 정의
type BackgroundColor = "bg-gray-100" | "bg-white" | "bg-blue-50";

interface OrganizerInfoProps {
  // ... 다른 props
  bgColor?: BackgroundColor;
}

이렇게 하면 컴포넌트에 잘못된 배경색 클래스가 전달되는 것을 방지할 수 있습니다.

src/widgets/dashboard/ui/TicketConfirmPage/PurchaseBanner.tsx (3)

5-12: 인터페이스 이름에 오타가 있습니다.

인터페이스 이름이 PurchaseBannerPrpos로 되어 있는데, 올바른 이름은 PurchaseBannerProps일 것입니다. 오타를 수정해주세요.

-interface PurchaseBannerPrpos {
+interface PurchaseBannerProps {
  title: string;
  startDate: string;
  startTime: string;
  ticketName: string;
  quantity: number;
  setIsModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
}

13-13: 인터페이스 이름과 구조 분해 시 공백 수정이 필요합니다.

  1. 인터페이스 이름이 수정되었으므로 컴포넌트에서도 일치시켜야 합니다.
  2. title,startDate 사이에 공백이 누락되어 일관성이 없습니다.
-const PurchaseBanner = ({ title,startDate, startTime, ticketName, quantity, setIsModalOpen }: PurchaseBannerPrpos) => {
+const PurchaseBanner = ({ title, startDate, startTime, ticketName, quantity, setIsModalOpen }: PurchaseBannerProps) => {

15-15: TODO 주석을 제거해주세요.

API 연동 작업이 완료되었으므로 TODO 주석을 제거하는 것이 좋습니다.

-  //@TODO:api연동하면서 props 변경
src/features/ticket/api/order.ts (1)

28-31: 함수 이름에 오타가 있습니다.

함수 이름이 cancleTickets로 되어 있는데, 올바른 이름은 cancelTickets일 것입니다.
취소를 의미하는 영단어 'cancel'의 철자가 잘못되었습니다.

-export const cancleTickets = async (orderId: number) => {
+export const cancelTickets = async (orderId: number) => {
  const response = await axiosClient.post(`/orders/cancel?orderId=${orderId}`);
  return response.data;
}

또한, POST 요청에 쿼리 파라미터를 사용하는 것보다 요청 본문(body)에 데이터를 포함시키는 것이 REST API 설계 관행에 더 부합합니다. 백엔드 API가 현재 이 형태로 구현되어 있다면 그대로 사용해도 되지만, 향후 API 설계 시 고려해보세요.

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

33-49: 상태 관리와 데이터 로딩이 잘 구현되었습니다.

티켓 상세 정보를 불러오는 로직이 잘 구현되어 있지만, 불필요한 console.log가 남아있습니다.

-  console.log(ticketId, eventId, orderIds);

또한, useEffect의 의존성 배열에 사용되는 변수들을 포함시키는 것이 좋습니다.

-  }, []);
+  }, [ticketId, eventId]);

53-62: 함수 이름에 오타가 있습니다.

함수 이름이 cancleOrderTicket으로 되어 있는데, 올바른 이름은 cancelOrderTicket입니다.
'cancel'의 철자가 잘못되었습니다.

-  const cancleOrderTicket = async (orderIds: number[]) => {
+  const cancelOrderTicket = async (orderIds: number[]) => {

또한, 이 함수는 API 응답에 따라 성공/실패 처리를 추가하는 것이 좋습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bcf7f5d and 9cc1d3e.

📒 Files selected for processing (11)
  • src/features/ticket/api/order.ts (1 hunks)
  • src/features/ticket/model/OrderCreation.ts (1 hunks)
  • src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (2 hunks)
  • src/pages/event/ui/EventDetailsPage.tsx (0 hunks)
  • src/pages/menu/ui/MyTicketPage.tsx (3 hunks)
  • src/shared/types/api/http-client.ts (1 hunks)
  • src/widgets/dashboard/ui/TicketConfirmPage/LocationInfo.tsx (0 hunks)
  • src/widgets/dashboard/ui/TicketConfirmPage/OrganizerInfo.tsx (0 hunks)
  • src/widgets/dashboard/ui/TicketConfirmPage/PurchaseBanner.tsx (2 hunks)
  • src/widgets/event/ui/OrganizerInfo.tsx (1 hunks)
  • src/widgets/event/ui/TicketInfo.tsx (3 hunks)
💤 Files with no reviewable changes (3)
  • src/pages/event/ui/EventDetailsPage.tsx
  • src/widgets/dashboard/ui/TicketConfirmPage/OrganizerInfo.tsx
  • src/widgets/dashboard/ui/TicketConfirmPage/LocationInfo.tsx
🧰 Additional context used
🧬 Code Definitions (4)
src/features/ticket/api/order.ts (2)
src/shared/types/api/http-client.ts (1)
  • axiosClient (6-13)
src/features/ticket/model/OrderCreation.ts (1)
  • OrderTicketRequest (1-5)
src/pages/menu/ui/MyTicketPage.tsx (1)
src/features/ticket/api/order.ts (1)
  • readTicket (4-19)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (1)
src/features/ticket/api/order.ts (2)
  • readTicket (4-19)
  • cancleTickets (28-31)
src/widgets/event/ui/TicketInfo.tsx (2)
src/features/ticket/model/OrderCreation.ts (1)
  • OrderTicketRequest (1-5)
src/features/ticket/api/order.ts (1)
  • orderTickets (22-25)
🪛 ESLint
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx

[error] 93-93: Expected an assignment or function call and instead saw an expression.

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

🔇 Additional comments (13)
src/features/ticket/model/OrderCreation.ts (1)

1-5: 코드가 명확하고 간결합니다.

인터페이스 정의가 명확하며 필요한 속성들이 적절하게 정의되어 있습니다. 티켓 주문 요청에 필요한 데이터 구조가 잘 설계되었습니다.

다만, 각 속성에 대한 JSDoc 주석을 추가하여 다음과 같이 문서화하면 코드의 가독성과 유지보수성이 더욱 향상될 것입니다:

export interface OrderTicketRequest {
+    /** 구매할 티켓의 고유 ID */
    ticketId: number;
+    /** 이벤트의 고유 ID */
    eventId: number;
+    /** 구매할 티켓 수량 */
    ticketCnt: number;
}
src/shared/types/api/http-client.ts (1)

33-36: 방어적 코딩으로 안정성이 향상되었습니다.

response.config.data가 존재하는지 확인하는 조건문을 추가하여 정의되지 않은 데이터를 파싱하려고 할 때 발생할 수 있는 잠재적인 오류를 방지했습니다. 이는 API 요청 처리 중 오류 발생 가능성을 줄이는 좋은 방어적 프로그래밍 방식입니다.

src/widgets/event/ui/OrganizerInfo.tsx (2)

4-10: 새로운 bgColor 속성 추가가 적절합니다.

OrganizerInfo 컴포넌트에 선택적 배경색 속성을 추가하여 재사용성과 유연성을 향상시켰습니다. 선택적 속성으로 정의하여 이전 코드와의 호환성도 유지하고 있습니다.


12-12: props에 기본값 설정이 적절합니다.

bgColor prop에 "bg-gray-100"이라는 기본값을 설정하여 prop이 전달되지 않아도 컴포넌트가 올바르게 렌더링될 수 있도록 했습니다.

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

7-7: API 통합이 적절하게 업데이트되었습니다.

readMyTickets에서 readTicket으로의 가져오기 변경이 리팩토링된 API 구조와 일치합니다. 이는 코드의 일관성을 유지하고 새로운 API 기능을 활용할 수 있게 합니다.


40-40: API 메서드 호출 업데이트가 적절합니다.

readMyTickets.get(0, 10) 대신 readTicket.getAll(0, 10)을 사용하도록 변경했습니다. 이는 새로운 API 구조에 맞게 적절히 수정되었습니다.


54-57: 리스트 렌더링 최적화가 잘 되었습니다.

인덱스 대신 ticket.id를 키로 사용하여 React의 재조정 알고리즘에 안정적인 식별자를 제공하도록 개선되었습니다. 이는 React 성능 최적화에 좋은 방법입니다.

src/widgets/dashboard/ui/TicketConfirmPage/PurchaseBanner.tsx (1)

29-29: 동적 데이터 적용이 잘 되었습니다.

하드코딩된 값들을 props로 받은 동적 데이터로 교체한 것이 잘 되었습니다.

Also applies to: 32-32, 36-36

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

4-19: readTicket 객체 구현이 잘 되었습니다.

기존의 readMyTickets를 대체하는 readTicket 객체와 메서드가 잘 구현되어 있습니다. 주석으로 각 메서드의 목적을 명확히 한 것도 좋습니다.


22-25: 티켓 구매 API 연동이 잘 되었습니다.

orderTickets 함수가 간결하고 명확하게 구현되어 있습니다.

src/widgets/event/ui/TicketInfo.tsx (1)

128-128: 구매 버튼이 적절하게 연결되었습니다.

구매하기 버튼에 orderTicket 함수가 잘 연결되어 있습니다.

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

11-27: Ticket 타입 정의가 잘 되었습니다.

티켓 정보를 위한 타입 정의가 상세하게 잘 구현되어 있습니다.


72-86: 티켓 정보 표시 UI가 잘 구현되었습니다.

티켓 정보가 로드되었을 때와 로딩 중일 때의 상태 처리가 잘 되어 있습니다.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2025

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

♻️ Duplicate comments (1)
src/widgets/event/ui/TicketInfo.tsx (1)

55-79: 🛠️ Refactor suggestion

티켓 구매 함수 구현에 개선이 필요합니다.

티켓 구매 기능이 구현되었지만, 다음과 같은 개선 사항이 있습니다:

  1. 개발용 console.log가 남아있습니다.
  2. 에러 처리가 부족합니다. catch 블록에서 error 변수를 활용하지 않습니다.
  3. 사용자에게 더 자세한 피드백이 필요합니다.

아래 수정사항을 적용하는 것이 좋겠습니다:

const orderTicket = async (ticketId: number, eventId: number, ticketCnt: number) => {
  try {
    const requestData: OrderTicketRequest = {
      ticketId,
      eventId,
      ticketCnt,
    };

    const response = await orderTickets(requestData);

-   console.log("API 응답:", response);

    if (response.isSuccess && Array.isArray(response.result)) {
      const orderIds = response.result;

      navigate('/payment/ticket-confirm', { state: { orderIds, ticketId, eventId } });
    } else {
-     alert("주문 정보를 불러올 수 없습니다.");
+     alert(`주문 처리 중 오류가 발생했습니다: ${response.message || '알 수 없는 오류'}`);
    }

  } catch (error) {
-   alert("티켓 구매 중 오류가 발생했습니다.");
+   console.error("티켓 구매 오류:", error);
+   alert(`티켓 구매 중 오류가 발생했습니다: ${error instanceof Error ? error.message : '알 수 없는 오류'}`);
  }
};
🧰 Tools
🪛 ESLint

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

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

🧹 Nitpick comments (1)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (1)

88-88: 모달 내용과 클릭 핸들러가 개선되었습니다.

  1. 모달 내용이 실제 티켓 정보를 반영하도록 동적으로 표시되어 좋습니다.
  2. 이전에 지적된 콤마 연산자 문제가 Promise chain(.then)으로 적절히 수정되었습니다.

다만, 함수명 오타(cancleOrderTicket)가 여기서도 사용되고 있습니다.

- onClick={() => { cancleOrderTicket(orderIds).then(() => { navigate('/menu/myticket'); }); }}
+ onClick={() => { cancelOrderTicket(orderIds).then(() => { navigate('/menu/myticket'); }); }}

Also applies to: 92-92

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9cc1d3e and 73943f1.

📒 Files selected for processing (3)
  • src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (2 hunks)
  • src/pages/menu/ui/MyTicketPage.tsx (4 hunks)
  • src/widgets/event/ui/TicketInfo.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/menu/ui/MyTicketPage.tsx
🧰 Additional context used
🧬 Code Definitions (2)
src/widgets/event/ui/TicketInfo.tsx (2)
src/features/ticket/model/OrderCreation.ts (1)
  • OrderTicketRequest (1-5)
src/features/ticket/api/order.ts (1)
  • orderTickets (22-25)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (1)
src/features/ticket/api/order.ts (2)
  • readTicket (4-19)
  • cancleTickets (28-31)
🪛 ESLint
src/widgets/event/ui/TicketInfo.tsx

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

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

🔇 Additional comments (6)
src/widgets/event/ui/TicketInfo.tsx (2)

6-8: 새로운 기능 추가에 필요한 import와 hook이 적절히 추가되었습니다.

새로운 티켓 구매 기능 구현을 위한 OrderTicketRequest 인터페이스, orderTickets API 함수 import 및 페이지 이동을 위한 useNavigate hook이 잘 추가되었습니다.

Also applies to: 14-14


112-112: 구매하기 버튼 처리가 잘 구현되었습니다.

티켓 구매 버튼 클릭 시 새로 추가된 orderTicket 함수를 적절하게 호출하고 있으며, 필요한 파라미터들(티켓 ID, 이벤트 ID, 티켓 수량)도 올바르게 전달되고 있습니다.

src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (4)

1-1: 필요한 컴포넌트와 API가 적절히 import 되었습니다.

React hooks, 라우팅 관련 기능, 그리고 티켓 관리를 위한 API들이 잘 import 되었습니다.

Also applies to: 4-4, 7-9


11-27: 티켓 타입 정의가 상세하게 작성되었습니다.

티켓에 관련된 모든 필요 속성들이 포함된 잘 구조화된 타입 정의입니다. 티켓 데이터를 명확하게 표현하고 있어 타입 안전성이 보장됩니다.


32-35: 라우터 상태에서 필요한 데이터를 적절히 추출하고 있습니다.

location state에서 orderIds, eventId, ticketId를 가져오는 코드가 잘 작성되었으며, 기본값 처리도 되어 있습니다.


71-85: 티켓 정보 표시 UI가 적절히 구현되었습니다.

티켓 정보 로딩 상태에 따라 conditional rendering을 사용하여 UI를 표시하는 방식이 잘 구현되었습니다. 티켓 정보, 주최자 정보, 장소 정보 등 다양한 컴포넌트들이 적절히 배치되었습니다.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 8, 2025

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

♻️ Duplicate comments (2)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (2)

37-48: ⚠️ Potential issue

useEffect의 의존성 배열 수정이 필요합니다.

useEffect에 의존성 배열이 비어 있어, ticketIdeventId가 변경되어도 티켓 정보를 다시 불러오지 않습니다. 또한 이 값들이 유효하지 않을 때의 처리가 없습니다.

다음과 같이 수정하세요:

  useEffect(() => {
+   if (!ticketId || !eventId) return;
+   
    const fetchOrderTicket = async () => {
      try {
        const response = await readTicket.getDetail(ticketId, eventId);
        setTicket(response.result || []);
      } catch (error) {
        console.error("구매한 티켓 정보 불러오기 실패:", error);
+       alert("티켓 정보를 불러오는 데 실패했습니다.");
      }
    };
    fetchOrderTicket();
- }, []);
+ }, [ticketId, eventId]);

52-61: ⚠️ Potential issue

티켓 취소 함수 개선이 필요합니다.

현재 티켓 취소 함수에는 몇 가지 개선이 필요합니다:

  1. 함수명에 오타가 있습니다: cancleOrderTicketcancelOrderTicket
  2. 성공/실패 결과를 사용자에게 알리는 코드가 없습니다
  3. 취소 처리 결과를 반환하지 않습니다

다음과 같이 개선하세요:

- const cancleOrderTicket = async (orderIds: number[]) => {
+ const cancelOrderTicket = async (orderIds: number[]) => {
+   let successCount = 0;
+   let failCount = 0;
    for (const orderId of orderIds) {
      try {
        const response = await cancelTickets(orderId);
-       console.log("티켓 취소 API 응답:", response);
+       if (response.isSuccess) {
+         successCount++;
+       } else {
+         failCount++;
+       }
      } catch (error) {
        console.error(`orderId ${orderId} 취소 실패:`, error);
+       failCount++;
      }
    }
+   
+   if (failCount > 0) {
+     alert(`${successCount}개 티켓 취소 성공, ${failCount}개 티켓 취소 실패했습니다.`);
+   } else {
+     alert(`${successCount}개 티켓이 성공적으로 취소되었습니다.`);
+   }
+   
+   return { success: successCount, fail: failCount };
  }
🧹 Nitpick comments (3)
src/features/ticket/api/order.ts (1)

32-34: 불필요한 빈 줄 제거 필요

파일 끝에 여러 개의 빈 줄이 있습니다. 코드 스타일 일관성을 위해 파일 끝에는 빈 줄을 한 줄만 남기는 것이 좋습니다.

}

-
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (2)

1-10: import 구문이 잘 정리되었습니다.

필요한 모듈과 컴포넌트를 명확하게 가져왔습니다. cancelTicketsreadTicket API 함수를 올바르게 가져온 점이 좋습니다.

한 가지 주의할 점은 5번 줄의 EmailDeleteMoal에 오타가 있는 것 같습니다 (Modal이 아닌 Moal).


92-92: 모달의 onClick 핸들러가 개선되었습니다.

이전 코드에서 콤마 연산자를 사용하던 방식이 Promise 체인을 사용하도록 수정되어 더 명확해졌습니다. 다만 취소가 실패했을 때도 항상 마이티켓 페이지로 이동하게 되는 점이 아쉽습니다.

취소 결과에 따라 조건부로 이동하도록 수정하는 것이 좋겠습니다:

-  onClick={() => { cancleOrderTicket(orderIds).then(() => { navigate('/menu/myticket'); }); }}
+  onClick={() => { 
+    cancelOrderTicket(orderIds).then((result) => { 
+      if (result && result.success > 0) {
+        navigate('/menu/myticket');
+      }
+    });
+  }}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 73943f1 and a47e060.

📒 Files selected for processing (2)
  • src/features/ticket/api/order.ts (1 hunks)
  • src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (2 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (1)
src/features/ticket/api/order.ts (2)
  • readTicket (4-19)
  • cancelTickets (28-31)
🔇 Additional comments (7)
src/features/ticket/api/order.ts (4)

1-3: OrderTicketRequest 인터페이스를 올바르게 가져왔습니다.

티켓 주문을 위한 데이터 구조를 명확하게 정의하여 타입 안전성을 확보했습니다.


4-19: API 객체 구조가 잘 설계되었습니다.

티켓 조회 API를 readTicket으로 통합하고, 전체 조회와 상세 조회 기능을 분리한 것은 좋은 설계입니다. 각 함수의 목적이 주석으로 명확하게 표시되어 있어 이해하기 쉽습니다.


21-25: 티켓 구매 API 구현이 적절합니다.

티켓 구매 기능이 명확하게 구현되었습니다. API 응답을 그대로 반환하는 것이 일관된 패턴으로 보입니다.


27-31: 티켓 취소 API에서 URL 파라미터 사용 방식 검토 필요

POST 요청에 URL 쿼리 파라미터로 orderId를 전달하고 있습니다. RESTful API 설계 원칙상 POST 요청의 데이터는 보통 요청 본문에 포함시키는 것이 더 일반적입니다.

백엔드 API 스펙이 이 방식을 요구하는지 확인해보세요. 만약 변경 가능하다면, 다음과 같이 수정하는 것이 더 표준적입니다:

-export const cancelTickets = async (orderId: number) => {
-  const response = await axiosClient.post(`/orders/cancel?orderId=${orderId}`);
+export const cancelTickets = async (orderId: number) => {
+  const response = await axiosClient.post("/orders/cancel", { orderId });
  return response.data;
}
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (3)

11-27: 티켓 타입 정의가 명확합니다.

티켓 정보를 위한 타입을 잘 정의했습니다. 모든 필요한 속성이 포함되어 있고, 특히 orderStatus에 가능한 값을 명시한 것이 좋은 접근입니다.


71-85: 조건부 렌더링이 잘 구현되었습니다.

티켓 정보 로딩 상태에 따른 조건부 렌더링이 잘 구현되었습니다. 티켓 정보가 있는 경우 필요한 컴포넌트를 렌더링하고, 없는 경우 로딩 메시지를 보여주는 방식이 적절합니다.


88-88: 모달 텍스트가 동적으로 표시되도록 잘 개선되었습니다.

티켓 취소 모달의 내용이 실제 티켓 정보(제목, 티켓 이름, 수량)를 반영하도록 잘 수정되었습니다.

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.

수고하셨습니다!

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 8, 2025

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: 2

♻️ Duplicate comments (2)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (2)

52-61: 취소 함수명 오타 수정 및 사용자 피드백 추가가 필요합니다.

함수명 cancleOrderTicketcancelOrderTicket로 수정되어야 합니다. 또한 현재 코드는 취소 성공/실패 시 사용자에게 알림을 제공하지 않습니다.

- const cancleOrderTicket = async (orderIds: number[]) => {
+ const cancelOrderTicket = async (orderIds: number[]) => {
+   let successCount = 0;
+   let failCount = 0;
    for (const orderId of orderIds) {
      try {
        const response = await cancelTickets(orderId);
-       console.log("티켓 취소 API 응답:", response);
+       if (response.isSuccess) {
+         successCount++;
+       } else {
+         failCount++;
+       }
      } catch (error) {
+       failCount++;
        console.error(`orderId ${orderId} 취소 실패:`, error);
      }
    }
+   
+   if (failCount > 0) {
+     alert(`${successCount}개 티켓 취소 성공, ${failCount}개 티켓 취소 실패했습니다.`);
+   } else {
+     alert(`${successCount}개 티켓이 성공적으로 취소되었습니다.`);
+   }
+   
+   return { success: successCount, fail: failCount };
  }

9-9: API 함수명 수정 필요

cancelTickets 함수를 올바르게 가져왔지만, 코드 내에서는 여전히 cancleOrderTicket처럼 오타가 있는 함수명을 사용하고 있습니다.

🧹 Nitpick comments (1)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (1)

88-88: 모달 텍스트 문구 개선 필요

모달 텍스트에 불필요한 마침표가 있으며, 문구가 어색합니다.

- mainText={`${ticket?.title}의 ${ticket?.ticketName} ${orderIds.length}매 구매를 취소하시겠습니까?. 취소 후에는 복구가 불가능합니다.`}
+ mainText={`${ticket?.title}의 ${ticket?.ticketName} ${orderIds.length}매 구매를 취소하시겠습니까? 취소 후에는 복구가 불가능합니다.`}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a47e060 and 3167e6e.

📒 Files selected for processing (1)
  • src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (2 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (1)
src/features/ticket/api/order.ts (2)
  • readTicket (4-19)
  • cancelTickets (28-31)
🔇 Additional comments (4)
src/pages/dashboard/ui/ticket/TIcketConfirmPage.tsx (4)

33-35: location.state 유효성 검사 추가 필요

orderIds, eventId, ticketId의 기본값은 설정되었지만, 필수 파라미터가 없을 경우 사용자에게 알림을 표시하고 적절히 리디렉션하는 로직이 필요합니다.

  const orderIds: number[] = location.state?.orderIds || [];
  const eventId = location.state?.eventId || 0;
  const ticketId = location.state?.ticketId || 0;
+ 
+ useEffect(() => {
+   if (orderIds.length === 0 || !eventId || !ticketId) {
+     alert('티켓 정보가 없습니다.');
+     navigate('/menu/myticket');
+   }
+ }, [orderIds, eventId, ticketId, navigate]);

92-92: 비동기 처리 개선됨

이전 리뷰 의견을 반영하여 비동기 처리가 올바르게 개선되었습니다. Promise 체인을 사용하여 취소 후 페이지를 이동하도록 처리했습니다.


71-85: 컴포넌트 조건부 렌더링 잘 구현됨

티켓 정보 로딩 상태에 따른 조건부 렌더링이 잘 구현되었습니다. 로딩 중일 때는 적절한 메시지를 표시하고, 데이터가 로드된 후에는 상세 정보를 보여줍니다.


11-27: Ticket 타입 정의가 명확함

티켓 정보에 대한 타입이 상세하게 정의되어 있어 코드의 가독성과 타입 안전성이 향상되었습니다.

Comment on lines +37 to +48
const [ticket, setTicket] = useState<Ticket | null>(null);
useEffect(() => {
const fetchOrderTicket = async () => {
try {
const response = await readTicket.getDetail(ticketId, eventId);
setTicket(response.result || []);
} catch (error) {
console.error("구매한 티켓 정보 불러오기 실패:", error);
}
};
fetchOrderTicket();
}, []);
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

useEffect 의존성 배열에 ticketId와 eventId를 추가해야 합니다.

useEffect의 의존성 배열이 비어 있어 컴포넌트가 마운트될 때만 한 번 실행됩니다. ticketId나 eventId가 변경될 경우에도 티켓 정보를 다시 불러와야 합니다.

  useEffect(() => {
+   if (!ticketId || !eventId) return;
+   
    const fetchOrderTicket = async () => {
      try {
        const response = await readTicket.getDetail(ticketId, eventId);
        setTicket(response.result || []);
      } catch (error) {
        console.error("구매한 티켓 정보 불러오기 실패:", error);
      }
    };
    fetchOrderTicket();
- }, []);
+ }, [ticketId, eventId]);
📝 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
const [ticket, setTicket] = useState<Ticket | null>(null);
useEffect(() => {
const fetchOrderTicket = async () => {
try {
const response = await readTicket.getDetail(ticketId, eventId);
setTicket(response.result || []);
} catch (error) {
console.error("구매한 티켓 정보 불러오기 실패:", error);
}
};
fetchOrderTicket();
}, []);
const [ticket, setTicket] = useState<Ticket | null>(null);
useEffect(() => {
if (!ticketId || !eventId) return;
const fetchOrderTicket = async () => {
try {
const response = await readTicket.getDetail(ticketId, eventId);
setTicket(response.result || []);
} catch (error) {
console.error("구매한 티켓 정보 불러오기 실패:", error);
}
};
fetchOrderTicket();
}, [ticketId, eventId]);

const fetchOrderTicket = async () => {
try {
const response = await readTicket.getDetail(ticketId, eventId);
setTicket(response.result || []);
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

API 응답 처리 검증 필요

API 응답에서 response.result || []를 사용하고 있는데, Ticket 타입은 객체이지만 빈 배열을 기본값으로 설정하고 있습니다. 이는 타입 불일치를 발생시킬 수 있습니다.

- setTicket(response.result || []);
+ setTicket(response.result || null);
📝 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
setTicket(response.result || []);
setTicket(response.result || null);

@hyeeuncho hyeeuncho merged commit 449162a into develop Apr 8, 2025
2 checks passed
@hyeeuncho hyeeuncho deleted the feat/#92/ticket-order-api branch April 8, 2025 11:01
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.

2 participants