Skip to content

Conversation

@HaeJungg
Copy link
Contributor

@HaeJungg HaeJungg commented Nov 13, 2024

🔖 Issue Ticket

#103

✍️ Description

디테일 페이지 get으로 요청 되는 부분 추가했습니다!

  • 디테일 카드
  • 약속 리스트
  • 약속 디테일 데이터

파일이 너무 많아져서 다른 요청은 다른 브렌치에 추가하겠습니다!

디테일 페이지 수정사항은 어차피 디자인이 바뀌면 다시 작업해야하기때문에,,, 나중에 수정하겠습니다!

어제 줌으로 전달했지만 fetch api에 baseUrl을 추가하고, next config rewrite 부분을 삭제했습니다!

제 실수로 env파일이 잘못 올라가는 바람에... 강사님이 도와주셔서 이전엔 커밋은 사라지고, 하나의 커밋만이 남았습니다ㅠㅠ

✅ Checklist

PR

  • Branch Convention 확인

    feat/ 피쳐, fix/ 버그 수정, refactor/ 개선

  • Base Branch 확인
  • 적절한 Label 지정
  • Assignee 및 Reviewer 지정

Test

  • 로컬 작동 확인

Summary by CodeRabbit

  • 신규 기능

    • 크루 및 모임 세부 정보를 가져오는 새로운 API 호출 기능 추가.
    • DetailCrewSectionGatheringListSection 컴포넌트 추가로 크루 상세 정보와 모임 목록 표시.
  • 버그 수정

    • API 요청 처리 개선 및 오류 핸들링 강화.
  • 문서화

    • Storybook 구성에서 DetailCrewCard의 데이터 구조 변경 및 업데이트.
  • 리팩토링

    • API 호출 및 상태 관리를 위한 쿼리 훅 통합으로 코드 간소화.

@HaeJungg HaeJungg self-assigned this Nov 13, 2024
@coderabbitai
Copy link

coderabbitai bot commented Nov 13, 2024

Walkthrough

이 풀 리퀘스트는 여러 파일에 대한 변경 사항을 포함하며, 주요 변경 사항은 .gitignore 파일의 업데이트, next.config.mjs 파일에서의 라우팅 변경, API 호출을 위한 함수 시그니처 수정, 새로운 React 컴포넌트 추가, 그리고 Storybook 구성의 수정입니다. 이러한 변경은 환경 변수 관리, API 요청 처리, 데이터 가져오기 및 UI 구성 요소의 상태 관리를 개선하기 위한 것입니다.

Changes

파일 경로 변경 요약
.gitignore .env, *storybook.log 추가 및 storybook-static 복원
next.config.mjs rewrites 함수 제거, headers 함수 유지
src/_apis/detail/get-crew-detail.ts getCrewDetail 함수 시그니처 변경: ID 매개변수 추가 및 반환 타입 수정
src/_apis/detail/get-gathering-detail.ts 새로운 GetGatheringDetail 함수 추가: crewId, gatheringId 매개변수 포함
src/_apis/detail/get-gathering-list.ts getGatheringList 함수 시그니처 변경: ID 매개변수 추가
src/_queries/detail/crew-detail-queries.ts 새로운 useGetCrewDetailQuery 함수 추가
src/_queries/detail/gathering-detail-queries.ts 새로운 useGetGatheringDetailQuery 함수 추가
src/_queries/detail/gathering-list-queries.ts 새로운 useGetGatheringListQuery 함수 추가
src/app/(crew)/crew/detail/[id]/_components/detail-crew-section.tsx 새로운 DetailCrewSection 컴포넌트 추가
src/app/(crew)/crew/detail/[id]/_components/gathering-list-section.tsx 새로운 GatheringListSection 컴포넌트 추가
src/app/(crew)/crew/detail/[id]/page.tsx CrewDetailPage 컴포넌트 수정: 새로운 컴포넌트로 교체 및 매개변수 추가
src/components/common/crew-list/detail-crew-card.stories.tsx Storybook에서 DetailCrewCard로 이름 변경 및 args 구조 수정
src/components/common/crew-list/detail-crew-card.tsx DetailCrewCardProps 인터페이스 수정: 데이터 객체로 구조 변경
src/components/common/gathering-card/container.tsx GatheringCard 컴포넌트 수정: 쿼리 훅 사용으로 데이터 가져오기 변경
src/components/common/gathering-card/gathering-card.stories.tsx Storybook에 React Query 통합 및 날짜 속성 수정
src/components/common/gathering-card/presenter.tsx cn 함수의 import 경로 변경
src/components/gathering-list/gathering-card-carousel.tsx crewId 속성 추가 및 컴포넌트 수정
src/components/gathering-list/gathering-carousel.stories.tsx Storybook에 React Query 통합 및 crewId 속성 추가
src/components/gathering-list/gathering-list.tsx currentPageData 렌더링 주석 처리
src/utils/api.ts ApiError 클래스 및 fetchApi 함수 수정: URL 구성 및 응답 처리 개선

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant API
    participant CrewDetailSection
    participant GatheringListSection

    User->>CrewDetailSection: 요청 (ID)
    CrewDetailSection->>API: getCrewDetail(ID)
    API-->>CrewDetailSection: CrewDetail 데이터
    CrewDetailSection-->>User: CrewDetail 표시

    User->>GatheringListSection: 요청 (ID)
    GatheringListSection->>API: getGatheringList(ID)
    API-->>GatheringListSection: GatheringList 데이터
    GatheringListSection-->>User: GatheringList 표시
Loading

Possibly related PRs

Suggested labels

pages

Suggested reviewers

  • yulrang
  • Rangbyeolang

🐰 변화의 날, 기뻐라!
새로운 코드로 세상이 밝아,
데이터 가져오고, 컴포넌트도 새로워!
모두 함께 즐겨보자,
Rabbit의 축제, 이제 시작이야! 🎉

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/_apis/detail/get-crew-detail.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't determine the plugin "react-hooks" uniquely.

  • /node_modules/eslint-plugin-react-hooks/index.js (loaded in ".eslintrc.js")
  • /node_modules/eslint-config-next/node_modules/eslint-plugin-react-hooks/index.js (loaded in ".eslintrc.js » eslint-config-next/core-web-vitals » /node_modules/eslint-config-next/index.js » plugin:react-hooks/recommended")

Please remove the "plugins" setting from either config or remove either plugin installation.

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • 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 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.

@HaeJungg HaeJungg added the api label Nov 13, 2024
@HaeJungg HaeJungg marked this pull request as ready for review November 13, 2024 08:03
@github-actions
Copy link

Copy link

@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: 9

🧹 Outside diff range and nitpick comments (22)
src/_queries/detail/crew-detail-queries.ts (1)

4-9: 에러 처리와 로딩 상태에 대한 타입 정의 추가를 고려해보세요.

데이터 타입과 함께 에러 및 로딩 상태에 대한 타입을 명시적으로 정의하면 컴포넌트에서 더 안전하게 사용할 수 있습니다.

+type CrewDetailResponse = {
+  // API 응답 타입 정의
+};

-export function useGetCrewDetailQuery(id: number) {
+export function useGetCrewDetailQuery(id: number) {
+  type QueryError = {
+    message: string;
+    status: number;
+  };

   return useQuery<CrewDetailResponse, QueryError>({
     queryKey: ['crewDetail', id],
     queryFn: () => getCrewDetail(id),
   });
 }
src/_queries/detail/gathering-detail-queries.ts (1)

4-9: 에러 처리와 로딩 상태 관리를 추가하는 것이 좋겠습니다.

현재 구현은 기본적인 데이터 fetching은 잘 처리하고 있지만, 다음 사항들을 고려해보시면 좋겠습니다:

  • 에러 발생 시의 재시도 로직
  • 캐시 무효화 전략
  • 로딩 상태에 대한 타임아웃 설정

다음과 같이 개선해보세요:

 export function useGetGatheringDetailQuery(crewId: number, gatheringId: number) {
   return useQuery({
     queryKey: ['gatheringDetail', crewId, gatheringId],
     queryFn: () => GetGatheringDetail(crewId, gatheringId),
+    retry: 1,
+    staleTime: 5 * 60 * 1000, // 5분
+    gcTime: 10 * 60 * 1000,  // 10분
+    timeout: 5000, // 5초
   });
 }
src/_queries/detail/gathering-list-queries.ts (1)

5-11: 캐싱 설정 추가를 고려해보세요.

쿼리 구현이 전반적으로 잘 되어있습니다. 다만, 데이터 신선도 관리를 위해 staleTime 설정을 추가하면 좋을 것 같습니다.

 export function useGetGatheringListQuery(id: number) {
   return useQuery<GatheringType[], Error>({
     queryKey: ['gatheringList', id],
     queryFn: () => getGatheringList(id),
     enabled: !!id,
+    staleTime: 5 * 60 * 1000, // 5분
   });
 }
.gitignore (1)

30-30: 환경 변수 파일이 적절히 무시되도록 설정되었습니다.

.env 파일을 .gitignore에 추가한 것은 보안상 매우 중요한 조치입니다. 이는 민감한 환경 변수가 실수로 저장소에 커밋되는 것을 방지합니다.

환경 변수 관리를 위해 다음 사항들을 고려해보세요:

  • .env.example 파일을 생성하여 필요한 환경 변수의 템플릿을 제공
  • 팀원들과 환경 변수 관리 방법에 대한 문서화 진행
src/app/(crew)/crew/detail/[id]/_components/gathering-list-section.tsx (1)

10-20: 상태 처리 개선이 필요합니다.

현재 구현은 기본적인 기능을 잘 수행하고 있지만, 다음과 같은 개선사항을 제안드립니다:

-  if (isLoading) return <p>로딩 중...</p>;
+  if (isLoading) return <LoadingSpinner />;

-  if (error) return <p>데이터를 불러오는 데 실패했습니다: {error.message}</p>;
+  if (error) return (
+    <ErrorMessage
+      title="데이터를 불러오는 데 실패했습니다"
+      message={error instanceof Error ? error.message : '알 수 없는 오류가 발생했습니다'}
+    />
+  );

-  if (!gatheringList || gatheringList.length === 0) return <p>데이터가 없습니다.</p>;
+  if (!gatheringList || gatheringList.length === 0) return (
+    <EmptyState
+      message="아직 등록된 모임이 없습니다"
+      description="새로운 모임을 등록해보세요!"
+    />
+  );
  1. 로딩 상태에 스피너 컴포넌트를 사용하여 사용자 경험을 개선
  2. 에러 처리에 타입 안전성을 추가하고 더 친숙한 에러 메시지를 표시
  3. 빈 데이터 상태에 대해 더 자세한 설명과 가이드를 제공
src/app/(crew)/crew/detail/[id]/_components/detail-crew-section.tsx (4)

7-9: 인터페이스에 문서화 추가 필요

인터페이스의 목적과 id 프로퍼티의 용도를 명확히 하기 위해 JSDoc 문서화를 추가하는 것이 좋습니다.

다음과 같이 수정하는 것을 제안합니다:

+/**
+ * 크루 상세 정보 섹션의 프로퍼티
+ */
 interface DetailCrewSectionProps {
+  /** 조회할 크루의 고유 식별자 */
   id: number;
 }

11-13: 데이터 타입 안전성 개선 필요

useGetCrewDetailQuery의 반환 타입이 명시적으로 지정되어 있지 않아 타입 안전성이 보장되지 않습니다.

다음과 같이 타입 지정을 추가하는 것을 제안합니다:

-  const { data, isLoading, error } = useGetCrewDetailQuery(id);
+  const { data, isLoading, error }: { 
+    data: CrewDetailType | undefined;
+    isLoading: boolean;
+    error: Error | null;
+  } = useGetCrewDetailQuery(id);

14-15: 로딩 상태 UI 개선 필요

현재 단순한 텍스트로 표시되는 로딩 상태를 사용자 경험을 고려한 컴포넌트로 개선해야 합니다.

TODO 주석을 해결하기 위한 스켈레톤 로딩 컴포넌트를 구현하는데 도움이 필요하신가요?


32-33: 조건부 렌더링 명확성 개선

현재 구현은 정확하지만, 널 체크의 의도를 더 명확하게 표현할 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

-  // data가 있을 때만 DetailCrewCard를 렌더링
-  return data ? <DetailCrewCard data={data} /> : null;
+  if (!data) {
+    return null;
+  }
+  
+  return <DetailCrewCard data={data} />;
src/app/(crew)/crew/detail/[id]/page.tsx (1)

26-26: TODO 주석을 더 구체적으로 작성해 주세요.

현재 TODO 주석과 주석 처리된 코드에 대해 몇 가지 제안사항이 있습니다:

  1. TODO 주석에 구체적인 완료 조건이나 관련 이슈 번호를 포함해 주세요
  2. CreateGathering 컴포넌트의 구현 계획을 주석으로 명시해 주세요

다음과 같이 개선하는 것을 추천드립니다:

-  {/* <CreateGathering /> */}
+  {/* TODO: #issue-number - CreateGathering 컴포넌트 구현 예정 (다음 스프린트) */}

-  {/* // TODO: 리뷰 완성되면 수정 */}
+  {/* TODO: #issue-number - 리뷰 기능 구현 후 활성화 예정
     - 백엔드 API 연동 필요
     - 디자인 시안 확인 필요
   */}

Also applies to: 33-39

src/components/gathering-list/gathering-carousel.stories.tsx (1)

51-57: QueryClientProvider 데코레이터 구현이 잘 되었습니다.

스토리북 데코레이터를 통해 QueryClientProvider를 적절히 설정하여 컴포넌트가 React Query 기능을 사용할 수 있도록 했습니다.

하지만 한 가지 제안사항이 있습니다:

  decorators: [
    (Story) => (
-     <QueryClientProvider client={queryClient}>
+     <QueryClientProvider client={queryClient} key="query-provider">
        <Story />
      </QueryClientProvider>
    ),
  ],

key prop을 추가하면 리렌더링 시 QueryClientProvider의 식별이 더 명확해집니다.

src/components/common/crew-list/detail-crew-card.stories.tsx (3)

2-6: Meta 타입 정의를 개선하세요

현재 Meta 타입이 제네릭 없이 정의되어 있습니다. 컴포넌트의 타입 안정성을 위해 제네릭을 추가하는 것이 좋습니다.

다음과 같이 수정하는 것을 제안합니다:

-const meta: Meta = {
+const meta: Meta<typeof DetailCrewCard> = {

15-39: 데이터 구조에 대한 문서화가 필요합니다

복잡한 중첩 데이터 구조에 대한 설명이 부족합니다. 각 필드의 의미와 제약 조건을 JSDoc으로 문서화하면 좋겠습니다.

예시:

/** 크루 카드 데이터 구조
 * @property {number} id - 크루 고유 식별자
 * @property {string} title - 크루 이름
 * @property {number} participantCount - 현재 참여자 수
 * ...
 */

58-58: 한글 주석을 영문으로 변경하고 스토리 설명을 추가하세요

코드 내 한글 주석이 있으며, 각 스토리의 목적과 차이점에 대한 설명이 부족합니다.

다음과 같이 수정하는 것을 제안합니다:

-      crewMembers: [], // 빈 배열이라도 기본값으로 설정
+      crewMembers: [], // Set empty array as default value

그리고 각 스토리에 대한 설명을 추가하세요:

export const Default: Story = {
  parameters: {
    docs: {
      description: {
        story: 'Displays a confirmed crew card with maximum participants'
      }
    }
  },
  args: {
    // ...
  }
};

Also applies to: 75-75

src/components/common/gathering-card/gathering-card.stories.tsx (2)

2-2: React Query 통합이 적절히 구현되었습니다.

QueryClient의 설정이 올바르게 이루어졌습니다. 단, 스토리북 환경에서는 QueryClient의 기본 설정을 조정하는 것이 좋을 수 있습니다.

다음과 같은 설정을 고려해보세요:

-const queryClient = new QueryClient();
+const queryClient = new QueryClient({
+  defaultOptions: {
+    queries: {
+      retry: false,
+      cacheTime: 0,
+    },
+  },
+});

Also applies to: 5-6


43-43: 날짜 업데이트가 적절히 이루어졌습니다.

스토리의 dateTime 값들이 미래 날짜로 적절하게 업데이트되었습니다. 다만, 테스트 데이터의 일관성을 위해 상대적인 날짜 사용을 고려해볼 수 있습니다.

다음과 같은 방식을 고려해보세요:

// utils/test-helpers.ts 파일 생성
export const getFutureDate = (daysFromNow: number) => {
  const date = new Date();
  date.setDate(date.getDate() + daysFromNow);
  return date.toISOString().slice(0, 16);
};

// stories에서 사용
dateTime: getFutureDate(30), // 30일 후

Also applies to: 57-57

src/components/gathering-list/gathering-list.tsx (1)

9-10: TODO 주석에 대한 추적성 확보 필요

TODO 주석이 다른 브랜치에서 수정될 예정이라고 명시되어 있습니다. 하지만 이러한 TODO 주석은 쉽게 잊혀질 수 있으며, 코드베이스에 장기간 남아있을 수 있습니다.

이 TODO 항목을 GitHub 이슈로 생성하여 추적하시겠습니까? 이슈에는 다음 내용이 포함될 수 있습니다:

  • 수정이 필요한 구체적인 내용
  • 예상 완료 시점
  • 관련 디자인 변경사항
src/components/gathering-list/gathering-card-carousel.tsx (1)

34-34: 계산식에 대한 설명을 더 자세히 추가하면 좋을 것 같습니다.

현재 주석은 "두 개일 경우"라고만 되어있는데, 계산식의 의미를 더 명확하게 설명하면 좋을 것 같습니다.

다음과 같이 주석을 개선하는 것을 제안드립니다:

-        newSlideSize = 'w-[calc(50%-8px)]'; // 두 개일 경우
+        newSlideSize = 'w-[calc(50%-8px)]'; // 두 개의 카드일 경우 (전체 너비의 50%에서 간격 16px의 절반을 뺌)
src/components/common/gathering-card/presenter.tsx (2)

Line range hint 11-11: 스켈레톤 UI 구현이 필요합니다.

초기 로딩 시 카드가 늘어나는 UX 이슈를 해결하기 위해 스켈레톤 UI 구현이 필요합니다.

스켈레톤 UI 구현을 위한 코드를 생성해드릴까요? 또는 이를 추적하기 위한 GitHub 이슈를 생성해드릴까요?


Line range hint 44-136: 컴포넌트 구조 개선을 제안드립니다.

현재 구현은 잘 작동하지만, 다음과 같은 개선사항을 고려해보시면 좋을 것 같습니다:

  1. 컴포넌트 분리

    • GatheringCardImage
    • GatheringCardDeadline
    • GatheringCardContent
    • GatheringCardOverlay
      등으로 분리하여 관리가 용이하도록 할 수 있습니다.
  2. 스타일 상수화

    • h-[310px], h-40 등의 매직 넘버를 상수로 추출
    • 반복되는 스타일 패턴을 유틸리티 클래스로 추출

리팩토링이 필요하시다면 구체적인 코드를 제안드릴 수 있습니다.

src/components/common/crew-list/detail-crew-card.tsx (2)

Line range hint 65-108: 주석 처리된 코드 정리가 필요합니다.

주석 처리된 captain/crew 관련 로직이 많은 공간을 차지하고 있습니다. 이는 코드 유지보수를 어렵게 만들 수 있습니다.

제안사항:

  1. 구현이 필요한 로직이라면 GitHub Issue로 관리하는 것이 좋습니다.
  2. 불필요한 코드라면 완전히 제거하는 것이 좋습니다.

GitHub Issue를 생성하여 해당 작업을 추적하도록 도와드릴까요?


Line range hint 47-57: 크루 삭제 및 탈퇴 로직 구현이 필요합니다.

handleConfirmDelete와 handleConfirmLeaveCrew 함수에 실제 구현이 필요합니다. 이는 중요한 비즈니스 로직이므로 우선적으로 구현되어야 합니다.

해당 기능 구현을 위한 코드를 제안해드릴까요?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 7c0c126 and d6fcd64.

📒 Files selected for processing (20)
  • .gitignore (2 hunks)
  • next.config.mjs (0 hunks)
  • src/_apis/detail/get-crew-detail.ts (1 hunks)
  • src/_apis/detail/get-gathering-detail.ts (1 hunks)
  • src/_apis/detail/get-gathering-list.ts (1 hunks)
  • src/_queries/detail/crew-detail-queries.ts (1 hunks)
  • src/_queries/detail/gathering-detail-queries.ts (1 hunks)
  • src/_queries/detail/gathering-list-queries.ts (1 hunks)
  • src/app/(crew)/crew/detail/[id]/_components/detail-crew-section.tsx (1 hunks)
  • src/app/(crew)/crew/detail/[id]/_components/gathering-list-section.tsx (1 hunks)
  • src/app/(crew)/crew/detail/[id]/page.tsx (1 hunks)
  • src/components/common/crew-list/detail-crew-card.stories.tsx (2 hunks)
  • src/components/common/crew-list/detail-crew-card.tsx (2 hunks)
  • src/components/common/gathering-card/container.tsx (3 hunks)
  • src/components/common/gathering-card/gathering-card.stories.tsx (3 hunks)
  • src/components/common/gathering-card/presenter.tsx (1 hunks)
  • src/components/gathering-list/gathering-card-carousel.tsx (5 hunks)
  • src/components/gathering-list/gathering-carousel.stories.tsx (3 hunks)
  • src/components/gathering-list/gathering-list.tsx (2 hunks)
  • src/utils/api.ts (2 hunks)
💤 Files with no reviewable changes (1)
  • next.config.mjs
🔇 Additional comments (25)
src/_queries/detail/crew-detail-queries.ts (2)

1-9: 구현이 깔끔하고 React Query 모범 사례를 잘 따르고 있습니다! 👍

쿼리 키 구조와 타입 정의가 명확하게 되어있습니다.


6-6: 쿼리 키가 적절히 구성되어 있는지 확인해주세요.

다른 곳에서 동일한 쿼리 키를 사용하고 있지 않은지 확인이 필요합니다.

✅ Verification successful

Let me check the actual implementation of the query to verify if there are any potential conflicts or issues.


쿼리 키 구성이 적절합니다.

'crewDetail' 쿼리 키는 해당 파일에서만 사용되고 있으며, id 파라미터와 함께 적절히 구성되어 있습니다. 다른 파일에서 중복 사용되지 않아 충돌 위험이 없습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 쿼리 키 'crewDetail'의 사용을 확인합니다.

# 쿼리 키 사용 검색
rg -l "queryKey.*crewDetail" 

Length of output: 73


Script:

#!/bin/bash
# Check the actual implementation and usage of crewDetail query
rg -A 5 "queryKey.*crewDetail" 

Length of output: 284

src/_queries/detail/gathering-detail-queries.ts (1)

1-2: import 경로 별칭(@/src)의 설정을 확인해주세요.

import 문이 올바르게 작성되었지만, @/src 별칭이 프로젝트의 tsconfig.json 또는 next.config에 올바르게 설정되어 있는지 확인이 필요합니다.

✅ Verification successful

경로 별칭(@/src)이 올바르게 설정되어 있습니다.

tsconfig.json에서 @/*@/src/_apis/* 경로 별칭이 정확하게 설정되어 있어, import 문의 경로가 유효합니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# tsconfig.json에서 경로 별칭 설정 확인
cat tsconfig.json | jq '.compilerOptions.paths'

# next.config 파일에서 경로 별칭 설정 확인
fd -e js -e mjs "next.config" -x cat {}

Length of output: 1598

src/_apis/detail/get-crew-detail.ts (2)

4-13: 구현이 깔끔하고 명확합니다!

함수 시그니처와 구현이 잘 정의되어 있습니다. API 엔드포인트도 RESTful 규칙을 잘 따르고 있습니다.


4-5: API 엔드포인트 사용 확인 필요

PR 설명에 따르면 base URL을 fetch API에 추가해야 한다고 언급되어 있습니다. 현재 구현된 엔드포인트가 올바른지 확인이 필요합니다.

✅ Verification successful

Let me check the API configuration in src/utils/api.ts to verify how the base URL is handled.


Let me check how the crew detail API is implemented.


API 엔드포인트가 올바르게 구현되어 있음을 확인했습니다

src/utils/api.tsfetchApi 함수에서 process.env.NEXT_PUBLIC_API_BASE_URL을 base URL로 사용하여 API 요청을 처리하고 있습니다. getCrewDetail 함수는 이 fetchApi를 올바르게 사용하고 있어 base URL이 자동으로 추가됩니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the API endpoint usage across the codebase

# Check for any environment configuration files
echo "Checking for API configuration files..."
fd -e env -e js -e ts -e json . -x grep -l "API_URL\|BASE_URL"

# Check for other API endpoint usages
echo "Checking for API endpoint patterns..."
rg "/api/crews/[^/]+" --type ts

Length of output: 773


Script:

#!/bin/bash
# Check the API configuration implementation
echo "Content of src/utils/api.ts:"
cat src/utils/api.ts

# Check if there are any fetch implementations
echo -e "\nChecking fetch implementations:"
rg "fetch\(" src/_apis/detail/get-crew-detail.ts -A 5

Length of output: 2024


Script:

#!/bin/bash
# Check the implementation of get-crew-detail.ts
echo "Content of src/_apis/detail/get-crew-detail.ts:"
cat src/_apis/detail/get-crew-detail.ts

# Check for any other files that might be using this API
echo -e "\nFiles importing get-crew-detail:"
rg "from.*get-crew-detail" --type ts

Length of output: 758

src/_queries/detail/gathering-list-queries.ts (1)

1-3: 깔끔한 import 구조입니다!

외부 라이브러리, 내부 API, 타입 순서로 잘 정리되어 있습니다.

src/_apis/detail/get-gathering-list.ts (2)

4-4: 함수 시그니처가 적절하게 수정되었습니다.

id 매개변수를 추가한 것은 특정 모임의 정보를 가져오기 위한 적절한 변경사항입니다.


5-5: URL 구성 검증이 필요합니다.

URL에 사용되는 id 값의 유효성을 검증하는 것이 좋습니다.

.gitignore (1)

41-42: Storybook 관련 파일들이 적절히 제외되었습니다.

빌드 출력물(/storybook-static)과 로그 파일(*storybook.log)을 무시하도록 설정한 것은 적절한 조치입니다. 이는 저장소를 깨끗하게 유지하고 불필요한 파일들이 커밋되는 것을 방지합니다.

src/_apis/detail/get-gathering-detail.ts (2)

1-2: 타입 임포트 위치 확인이 필요합니다

타입 정의가 올바른 위치에서 임포트되고 있는지 확인이 필요합니다.

다음 스크립트로 타입 정의 위치를 확인해보겠습니다:

#!/bin/bash
# 타입 정의 위치 확인
fd "gathering-data.ts" src/types

8-8: URL 구성 검증이 필요합니다

URL에 사용되는 파라미터들의 유효성 검사가 필요합니다.

다음 스크립트로 API 엔드포인트 사용을 확인해보겠습니다:

src/app/(crew)/crew/detail/[id]/_components/gathering-list-section.tsx (2)

1-9: 코드 구조가 깔끔하고 명확합니다!

'use client' 지시문의 올바른 사용과 함께 깔끔한 import 구문, 그리고 명확한 인터페이스 정의가 잘 되어있습니다.


4-4: GatheringCardCarousel 컴포넌트의 props 검증이 필요합니다.

GatheringCardCarousel 컴포넌트가 예상된 props를 올바르게 받는지 확인이 필요합니다.

Also applies to: 19-19

✅ Verification successful

GatheringCardCarousel 컴포넌트의 props가 정상적으로 구현되어 있습니다.

코드베이스 검증 결과:

  • GatheringCardCarousel 컴포넌트가 gatheringData: GatheringType[]crewId: number props를 올바르게 정의하고 있습니다.
  • gathering-list-section에서 전달하는 props 타입이 컴포넌트의 인터페이스와 일치합니다.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# GatheringCardCarousel 컴포넌트의 props 타입 정의 확인
ast-grep --pattern 'interface GatheringCardCarouselProps {
  $$$
  gatheringData: $_
  crewId: $_
  $$$
}'

Length of output: 108


Script:

#!/bin/bash
# Check the implementation of GatheringCardCarousel component
fd "gathering-card-carousel" --type f --exec cat {}

# Search for usage patterns of GatheringCardCarousel
rg "GatheringCardCarousel" -A 5

Length of output: 7979

src/app/(crew)/crew/detail/[id]/page.tsx (1)

3-9: 타입 정의와 임포트 구조가 깔끔합니다!

컴포넌트 임포트와 타입 정의가 명확하게 구성되어 있습니다.

src/utils/api.ts (2)

38-39: 환경 변수 설정 확인 필요

NEXT_PUBLIC_API_BASE_URL 환경 변수가 올바르게 설정되어 있는지 확인이 필요합니다.

✅ Verification successful

환경 변수 설정이 적절히 구성되어 있습니다

NEXT_PUBLIC_API_BASE_URL 환경 변수는 next.config.mjs에서 기본값 'https://foggy-sideways-saltasaurus.glitch.me/'로 적절하게 설정되어 있어 문제가 없습니다. 환경 변수가 없는 경우에도 기본값이 제공되므로 애플리케이션이 정상적으로 동작할 것입니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for environment variable usage in the codebase

# Check for environment variable references
echo "Checking for NEXT_PUBLIC_API_BASE_URL usage:"
rg "NEXT_PUBLIC_API_BASE_URL"

# Check if .env or similar files exist
echo -e "\nChecking for environment configuration files:"
fd -g ".env*"

Length of output: 643


Script:

#!/bin/bash
# Check the next.config.mjs file content to understand the default value
echo "Checking next.config.mjs configuration:"
cat next.config.mjs

# Check for .env files including hidden ones
echo -e "\nChecking for environment files (including hidden):"
fd -H -g ".env*"

# Check if there are any example env files
echo -e "\nChecking for example env files:"
fd -g "*env.example*"

Length of output: 1316


54-54: 응답 구조 변경에 따른 영향도 확인 필요

응답 구조가 { data: ... } 형태로 변경되었습니다. 이는 기존 API를 사용하는 코드에 영향을 줄 수 있습니다.

✅ Verification successful

Let me gather more information about the response types and their handling to verify the impact.


API 응답 구조 변경은 안전합니다

기존 API 소비자들이 이미 { data: ... } 구조를 예상하고 있음을 확인했습니다:

  • WritableGatheringCardInformResponse, MyCrewListResponse, ReviewInformResponse 등의 타입들이 이미 data 필드를 포함하고 있습니다
  • API 호출 부분에서도 fetchApi<{ data: GatheringType[] }>, fetchApi<{ data: CrewDetail }> 등과 같이 data 필드를 포함한 타입을 명시적으로 사용하고 있습니다

따라서 이 변경사항은 기존 코드와 일관성이 있으며 호환됩니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find potential affected API consumers

# Search for fetchApi usage
echo "Checking for fetchApi usage:"
ast-grep --pattern 'fetchApi<$_>($_)'

# Search for direct response handling
echo -e "\nChecking for potential response handling:"
rg "await.*fetchApi.*" -A 2

Length of output: 1453


Script:

#!/bin/bash
# Check response type definitions and handling
echo "Checking response type definitions:"
rg "type.*Response" -A 3

echo -e "\nChecking interface definitions:"
rg "interface.*Response" -A 3

echo -e "\nChecking actual response handling in components:"
rg "const.*=.*response" -A 2

Length of output: 2680

src/components/gathering-list/gathering-carousel.stories.tsx (2)

2-2: React Query 설정이 적절히 구현되었습니다.

QueryClient의 설정이 올바르게 되어있으며, 필요한 import문도 정확하게 추가되었습니다.

Also applies to: 42-43


67-67: crewId prop 추가에 대한 검증이 필요합니다.

crewId가 추가되었지만, 이 값이 실제로 어떻게 사용되는지 확인이 필요합니다.

✅ Verification successful

Let me check how the crewId is used in the GatheringCard component.


Let me try to find the GatheringCard component in the codebase first.


Let me check how the crewId is used in the GatheringCard container component.


Let me check for any API calls or hooks that might be using the crewId.


crewId prop이 적절하게 사용되고 있음을 확인했습니다.

crewId는 다음과 같이 올바르게 사용되고 있습니다:

  • GatheringCard 컴포넌트에서 모임 상세 정보를 조회하는 useGetGatheringDetailQuery에 필요한 파라미터로 사용
  • API 엔드포인트 /api/crews/${crewId}/gatherings/${gatheringId}에서 특정 크루의 모임 정보를 조회하는데 사용
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: crewId 사용 방식 확인

# GatheringCardCarousel 컴포넌트에서 crewId prop 사용 확인
ast-grep --pattern 'interface GatheringCardCarouselProps {
  $$$
  crewId: $_
  $$$
}'

# crewId 사용 패턴 검색
rg -A 3 'crewId' src/components/gathering-list/

Length of output: 1757


Script:

#!/bin/bash
# GatheringCard 컴포넌트에서 crewId prop 사용 확인
ast-grep --pattern 'interface GatheringCardProps {
  $$$
  crewId: $_
  $$$
}'

# GatheringCard 컴포넌트 내에서 crewId 사용 패턴 검색
rg -A 3 'crewId' src/components/gathering-card/

Length of output: 199


Script:

#!/bin/bash
# Find GatheringCard component file
fd GatheringCard

# Search for GatheringCard interface and crewId usage
rg -A 3 "interface.*GatheringCard"
rg -A 3 "type.*GatheringCard"

Length of output: 6525


Script:

#!/bin/bash
# Check GatheringCard container implementation
rg -A 10 "GatheringCardContainer" src/components/common/gathering-card/container.tsx

# Check if crewId is used in any API calls or important logic
rg -A 5 "crewId.*=" src/components/common/gathering-card/
rg -A 5 "useQuery.*crewId" src/components/common/gathering-card/

Length of output: 719


Script:

#!/bin/bash
# Search for API calls or hooks using crewId
rg -A 5 "api.*crewId" 
rg -A 5 "mutation.*crewId"
rg -A 5 "useGathering.*crewId"

# Check the GatheringCard implementation file content
cat src/components/common/gathering-card/container.tsx

Length of output: 3296

src/components/common/gathering-card/gathering-card.stories.tsx (1)

28-34: 데코레이터 구현이 잘 되었습니다.

QueryClientProvider를 데코레이터로 구현한 방식이 적절합니다. 모든 스토리에서 일관된 Query 컨텍스트를 사용할 수 있게 되었습니다.

src/components/gathering-list/gathering-card-carousel.tsx (3)

12-12: Props 인터페이스 변경이 적절히 구현되었습니다.

crewId prop이 인터페이스에 추가되고 컴포넌트에서 올바르게 구조분해되어 사용되고 있습니다.

Also applies to: 15-18


63-63: 반응형 레이아웃 동작을 확인해주세요.

레이아웃 관련 변경사항들이 있어 다음 사항들을 확인해주시면 좋겠습니다:

  1. 모바일에서 카드가 전체 너비를 차지하는지
  2. lg 브레이크포인트에서 최소 너비 제한이 잘 적용되는지
  3. 여백이 디자인과 일치하는지

추가로, 브레이크포인트별 레이아웃 값들을 상수로 분리하는 것을 고려해보세요. 예:

const LAYOUT_CONFIG = {
  mobile: {
    slidesToShow: 1,
    slideSize: 'w-full'
  },
  tablet: {
    slidesToShow: 2,
    slideSize: 'w-[calc(50%-8px)]'
  },
  desktop: {
    slidesToShow: 3,
    slideSize: 'w-[calc(33.33%-12px)]'
  }
} as const;

Also applies to: 77-78


109-109: 인디케이터 여백이 디자인 명세와 일치하는지 확인해주세요.

인디케이터의 상단 여백이 mt-4에서 mt-2로 변경되었습니다. 이 변경이 디자인 명세와 일치하는지 확인이 필요합니다.

src/components/common/gathering-card/presenter.tsx (1)

4-4: import 경로 변경이 적절합니다.

유틸리티 함수를 utils 디렉토리로 이동한 것은 코드 구조화 측면에서 좋은 변경입니다.

src/components/common/crew-list/detail-crew-card.tsx (2)

14-25: 인터페이스 구조 개선이 잘 되었습니다!

데이터를 하나의 객체로 묶어서 관리하는 방식이 props 전달을 더 깔끔하게 만들었습니다.


28-40: 데이터 구조 분해가 깔끔하게 되었습니다!

객체 구조 분해를 통해 코드의 가독성이 향상되었습니다.

Comment on lines +7 to +13
const response = await fetchApi<{ data: CrewDetail }>(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});

return { data: response[0] };
return response.data;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

에러 처리 로직 추가 검토 필요

API 호출 실패 시의 에러 처리가 명시적으로 구현되어 있지 않습니다. 사용자 경험 향상을 위해 에러 처리 로직 추가를 고려해 주세요.

다음과 같은 구현을 제안드립니다:

 export async function getCrewDetail(id: number): Promise<CrewDetail> {
   const url = `/api/crews/${id}`;

-  const response = await fetchApi<{ data: CrewDetail }>(url, {
-    method: 'GET',
-    headers: {
-      'Content-Type': 'application/json',
-    },
-  });
-  return response.data;
+  try {
+    const response = await fetchApi<{ data: CrewDetail }>(url, {
+      method: 'GET',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+    });
+    return response.data;
+  } catch (error) {
+    console.error('크루 상세 정보를 가져오는데 실패했습니다:', error);
+    throw new Error('크루 상세 정보를 불러올 수 없습니다.');
+  }
 }
📝 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 response = await fetchApi<{ data: CrewDetail }>(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
return { data: response[0] };
return response.data;
try {
const response = await fetchApi<{ data: CrewDetail }>(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
return response.data;
} catch (error) {
console.error('크루 상세 정보를 가져오는데 실패했습니다:', error);
throw new Error('크루 상세 정보를 불러올 수 없습니다.');
}

Comment on lines +5 to +13
const url = `/api/crews/${id}/gatherings`;

const response = await fetchApi<{ data: GatheringType[] }>(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
return response.data;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

API 응답 처리 개선이 필요합니다.

API 응답 처리에서 몇 가지 개선이 필요합니다:

  1. 오류 처리가 누락되어 있습니다.
  2. API 응답의 유효성 검사가 없습니다.

다음과 같이 개선하는 것을 제안드립니다:

 export async function getGatheringList(id: number): Promise<GatheringType[]> {
   const url = `/api/crews/${id}/gatherings`;

+  try {
     const response = await fetchApi<{ data: GatheringType[] }>(url, {
       method: 'GET',
       headers: {
         'Content-Type': 'application/json',
       },
     });
+    
+    if (!response.data) {
+      throw new Error('데이터가 존재하지 않습니다');
+    }
+
     return response.data;
+  } catch (error) {
+    console.error('모임 목록을 가져오는데 실패했습니다:', error);
+    throw error;
+  }
 }

또한 API 응답의 타입 안전성을 위해 zod와 같은 런타임 타입 검증 라이브러리의 사용을 고려해보시는 것을 추천드립니다.

📝 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 url = `/api/crews/${id}/gatherings`;
const response = await fetchApi<{ data: GatheringType[] }>(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
return response.data;
export async function getGatheringList(id: number): Promise<GatheringType[]> {
const url = `/api/crews/${id}/gatherings`;
try {
const response = await fetchApi<{ data: GatheringType[] }>(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (!response.data) {
throw new Error('데이터가 존재하지 않습니다');
}
return response.data;
} catch (error) {
console.error('모임 목록을 가져오는데 실패했습니다:', error);
throw error;
}
}

Comment on lines +4 to +7
export async function GetGatheringDetail(
crewId: number,
gatheringId: number,
): Promise<GatheringDetailType> {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

함수 이름이 컨벤션을 따르지 않습니다

함수 이름이 파스칼 케이스(PascalCase)로 작성되어 있습니다. JavaScript/TypeScript에서 함수는 일반적으로 카멜 케이스(camelCase)를 사용합니다.

다음과 같이 수정하는 것을 제안합니다:

-export async function GetGatheringDetail(
+export async function getGatheringDetail(
   crewId: number,
   gatheringId: number,
 ): Promise<GatheringDetailType>
📝 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
export async function GetGatheringDetail(
crewId: number,
gatheringId: number,
): Promise<GatheringDetailType> {
export async function getGatheringDetail(
crewId: number,
gatheringId: number,
): Promise<GatheringDetailType> {

Comment on lines +10 to +15
const response = await fetchApi<{ data: GatheringDetailType }>(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

에러 처리 로직이 필요합니다

API 호출 시 발생할 수 있는 다양한 에러 상황(네트워크 오류, 서버 오류 등)에 대한 처리가 없습니다.

다음과 같은 에러 처리를 추가하는 것을 제안합니다:

-  const response = await fetchApi<{ data: GatheringDetailType }>(url, {
-    method: 'GET',
-    headers: {
-      'Content-Type': 'application/json',
-    },
-  });
+  try {
+    const response = await fetchApi<{ data: GatheringDetailType }>(url, {
+      method: 'GET',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+    });
+    return response.data;
+  } catch (error) {
+    if (error instanceof Error) {
+      throw new Error(`모임 상세 정보를 가져오는데 실패했습니다: ${error.message}`);
+    }
+    throw new Error('모임 상세 정보를 가져오는데 실패했습니다');
+  }
📝 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 response = await fetchApi<{ data: GatheringDetailType }>(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
try {
const response = await fetchApi<{ data: GatheringDetailType }>(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
return response.data;
} catch (error) {
if (error instanceof Error) {
throw new Error(`모임 상세 정보를 가져오는데 실패했습니다: ${error.message}`);
}
throw new Error('모임 상세 정보를 가져오는데 실패했습니다');
}

Comment on lines +17 to +30
if (error) {
if (error instanceof ApiError) {
try {
const errorData = JSON.parse(error.message);

if (errorData.status === 'NOT_FOUND') {
return <p>크루 정보를 찾을 수 없습니다</p>;
}
} catch {
return <p>{`Error ${error.status}: ${error.message}`}</p>;
}
}
return <p>데이터 통신에 실패했습니다.</p>;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

에러 처리 로직 개선 필요

현재 에러 처리 로직이 복잡하고 중첩된 조건문을 사용하고 있어 유지보수가 어려울 수 있습니다.

다음과 같이 에러 처리를 단순화하는 것을 제안합니다:

-  if (error) {
-    if (error instanceof ApiError) {
-      try {
-        const errorData = JSON.parse(error.message);
-
-        if (errorData.status === 'NOT_FOUND') {
-          return <p>크루 정보를 찾을 수 없습니다</p>;
-        }
-      } catch {
-        return <p>{`Error ${error.status}: ${error.message}`}</p>;
-      }
-    }
-    return <p>데이터 통신에 실패했습니다.</p>;
-  }
+  if (error) {
+    const getErrorMessage = () => {
+      if (!(error instanceof ApiError)) {
+        return '데이터 통신에 실패했습니다.';
+      }
+      try {
+        const errorData = JSON.parse(error.message);
+        return errorData.status === 'NOT_FOUND'
+          ? '크루 정보를 찾을 수 없습니다'
+          : `Error ${error.status}: ${error.message}`;
+      } catch {
+        return `Error ${error.status}: ${error.message}`;
+      }
+    };
+    return <p>{getErrorMessage()}</p>;
+  }
📝 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
if (error) {
if (error instanceof ApiError) {
try {
const errorData = JSON.parse(error.message);
if (errorData.status === 'NOT_FOUND') {
return <p>크루 정보를 찾을 수 없습니다</p>;
}
} catch {
return <p>{`Error ${error.status}: ${error.message}`}</p>;
}
}
return <p>데이터 통신에 실패했습니다.</p>;
}
if (error) {
const getErrorMessage = () => {
if (!(error instanceof ApiError)) {
return '데이터 통신에 실패했습니다.';
}
try {
const errorData = JSON.parse(error.message);
return errorData.status === 'NOT_FOUND'
? '크루 정보를 찾을 수 없습니다'
: `Error ${error.status}: ${error.message}`;
} catch {
return `Error ${error.status}: ${error.message}`;
}
};
return <p>{getErrorMessage()}</p>;
}

Comment on lines +11 to +12
export default async function CrewDetailPage({ params }: CrewDetailPageProps) {
const id = Number(params.id);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

params.id의 타입 변환 처리를 개선해 주세요.

Number() 함수를 직접 사용하면 잘못된 id 형식에 대한 처리가 누락될 수 있습니다.

다음과 같이 개선하는 것을 추천드립니다:

-  const id = Number(params.id);
+  const id = parseInt(params.id, 10);
+  if (isNaN(id)) {
+    throw new Error('Invalid ID format');
+  }
📝 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
export default async function CrewDetailPage({ params }: CrewDetailPageProps) {
const id = Number(params.id);
export default async function CrewDetailPage({ params }: CrewDetailPageProps) {
const id = parseInt(params.id, 10);
if (isNaN(id)) {
throw new Error('Invalid ID format');
}

participantCount: 10,
totalCount: 20,
confirmed: true,
imageUrl: 'https://i.pinimg.com/564x/f8/8d/c5/f88dc5b857caf6c303ae5ef9dd12e7fb.jpg',
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

이미지 URL을 상수로 분리하세요

하드코딩된 이미지 URL들이 여러 곳에서 반복되고 있습니다. 이는 유지보수를 어렵게 만들 수 있습니다.

스토리북 설정 파일에 상수로 분리하는 것을 제안합니다:

const MOCK_IMAGES = {
  CREW_DEFAULT: 'https://i.pinimg.com/564x/f8/8d/c5/f88dc5b857caf6c303ae5ef9dd12e7fb.jpg',
  PROFILE_DEFAULT: 'https://i.pinimg.com/564x/e2/25/bb/e225bb492dc7a20a549f3c0abec28eb8.jpg'
} as const;

Also applies to: 29-30, 35-36, 56-56, 73-73

Comment on lines +58 to +60
{/* {currentPageData.map((card, id) => (
<GatheringCard key={id} {...card} className={cardClassName} />
))}
))} */}
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

⚠️ Potential issue

주석 처리된 코드로 인한 심각한 기능 문제 확인됨

코드베이스 분석 결과, 현재 gathering-list.tsx에서 핵심 기능인 GatheringCard 렌더링이 주석 처리되어 있으며, 이는 다음과 같은 실제 문제를 야기합니다:

  • 모임 데이터가 전혀 표시되지 않음
  • 페이지네이션은 존재하지만 실제 데이터를 보여주지 않음
  • 빈 카드만 표시되어 사용자 경험이 심각하게 저하됨

다음과 같이 수정하시기를 강력히 권장드립니다:

        {currentPageData.length > 0 ? (
          currentPageData.map((card, id) => (
            <GatheringCard key={id} {...card} className={cardClassName} />
          ))
        ) : (
          <div className="col-span-full text-center py-8">
            현재 표시할 모임이 없습니다.
          </div>
        )}
🔗 Analysis chain

주석 처리된 코드로 인한 잠재적 문제

현재 주요 기능인 GatheringCard 렌더링이 주석 처리되어 있습니다. 이로 인해 다음과 같은 문제가 발생할 수 있습니다:

  1. 사용자에게 데이터가 표시되지 않음
  2. 페이지네이션은 작동하지만 실제 데이터를 볼 수 없음
  3. 빈 카드만 표시되어 사용자 경험 저하

다음 중 하나의 방안을 선택하시기를 권장드립니다:

  1. 주석을 제거하고 기능을 복원
  2. 임시 UI나 로딩 상태를 표시
  3. 기능이 준비되지 않았다면 사용자에게 알림 메시지 표시
-        {/* {currentPageData.map((card, id) => (
-          <GatheringCard key={id} {...card} className={cardClassName} />
-        ))} */}
+        {currentPageData.length > 0 ? (
+          currentPageData.map((card, id) => (
+            <GatheringCard key={id} {...card} className={cardClassName} />
+          ))
+        ) : (
+          <div className="col-span-full text-center py-8">
+            현재 표시할 모임이 없습니다.
+          </div>
+        )}

페이지네이션 기능이 여전히 올바르게 작동하는지 확인이 필요합니다:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 페이지네이션 관련 로직이 다른 컴포넌트에서도 사용되는지 확인
rg -l "Pagination.*total={Math\.ceil\(" 

Length of output: 174


Script:

#!/bin/bash
# 페이지네이션 관련 코드 검색
rg -l "Pagination.*total"

# GatheringCard 컴포넌트 사용 현황 확인
rg -l "GatheringCard"

# gathering-list.tsx 전체 내용 확인
cat src/components/gathering-list/gathering-list.tsx

Length of output: 4481

Comment on lines +53 to +69
if (error) {
if (error instanceof ApiError) {
try {
const errorData = JSON.parse(error.message);

if (opened) {
fetchGatheringDetail();
if (errorData.status === 'NOT_FOUND') {
Toast({ message: '모임 정보를 찾을 수 없습니다.', type: 'error' });
}
} catch {
Toast({ message: `Error ${error.status}: ${error.message}`, type: 'error' });
}
} else {
Toast({ message: '데이터 통신에 실패했습니다.', type: 'error' });
}
}
}, [opened]);
}, [error]);

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

에러 처리 로직 개선 제안

error.message를 JSON으로 파싱하는 대신, error.response?.data 또는 error.data를 사용하여 에러 정보를 처리하는 것이 더 안전하고 정확합니다. 이는 서버에서 전달된 실제 에러 데이터를 직접 활용하여 파싱 에러를 방지할 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

 useEffect(() => {
   if (error) {
     if (error instanceof ApiError) {
-      try {
-        const errorData = JSON.parse(error.message);
+      const errorData = error.response?.data;

         if (errorData.status === 'NOT_FOUND') {
           Toast({ message: '모임 정보를 찾을 수 없습니다.', type: 'error' });
         }
-      } catch {
-        Toast({ message: `Error ${error.status}: ${error.message}`, type: 'error' });
-      }
     } else {
       Toast({ message: '데이터 통신에 실패했습니다.', type: 'error' });
     }
   }
 }, [error]);

Committable suggestion skipped: line range outside the PR's diff.

@HaeJungg HaeJungg changed the title DetailPage DetailPage api 연결 Nov 13, 2024
@HaeJungg HaeJungg linked an issue Nov 13, 2024 that may be closed by this pull request
3 tasks
Copy link
Contributor

@minkyung5x5 minkyung5x5 left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!!!

Copy link
Contributor

@ChoYenii ChoYenii left a comment

Choose a reason for hiding this comment

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

수고많으셨습니다!

Copy link
Contributor

@yulrang yulrang left a comment

Choose a reason for hiding this comment

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

수고하셨습니다~!~! 고생하셨어용

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

디테일 페이지 조회 API 연결

6 participants