Skip to content

feat: 카테고리 페이지 구현 및 카테고리에 따른 이벤트 무한 스크롤 API 연동#125

Merged
xaexunxang merged 3 commits intodevelopfrom
feat/#107/event-category-api
May 13, 2025
Merged

feat: 카테고리 페이지 구현 및 카테고리에 따른 이벤트 무한 스크롤 API 연동#125
xaexunxang merged 3 commits intodevelopfrom
feat/#107/event-category-api

Conversation

@xaexunxang
Copy link
Copy Markdown
Contributor

@xaexunxang xaexunxang commented May 13, 2025

개발/스터디 이벤트 페이지

image

네트워킹 이벤트 페이지

image

해커톤 이벤트 페이지

image

컨퍼런스 이벤트 페이지

image

작업 방식

  1. mainCardButtonType.ts/cardButtons 에 category객체 추가
  2. 카테고리 이벤트를 불러오는 호출 URL에 관한 API 구현
  3. AllEventPage에서 사용하는 EventList 컴포넌트의 filter안에 category 필터 객체 추가
  4. AllEventPage에서는 current 태그에 해당하는 이벤트만 렌더링
  5. CategoryPage에서는 cardButtons에서 제공하는 category에 따른 이벤트만 렌더링

Summary by CodeRabbit

  • 신규 기능

    • 카테고리별 이벤트 목록 페이지가 추가되었습니다.
    • 메인 페이지에서 카테고리 버튼 클릭 시 해당 카테고리 이벤트 목록으로 이동할 수 있습니다.
    • 로그인 상태에 따라 헤더 우측 버튼이 사용자 이름 또는 로그인으로 표시되며, 로그인 모달이 애니메이션과 함께 표시됩니다.
  • 기능 개선

    • 이벤트 목록에서 카테고리 또는 태그별 필터링 기능이 추가되어 원하는 이벤트를 쉽게 찾을 수 있습니다.
    • 전체 이벤트 페이지에서 "current" 태그로 필터링된 이벤트만 표시됩니다.
    • 이벤트 API 호출 방식과 무한 스크롤 로직이 개선되어 안정성과 가독성이 향상되었습니다.
  • 기타

    • 개발 도구용 패키지가 추가되었습니다.
    • 내부 코드 가독성과 구조가 일부 개선되었습니다.

@xaexunxang xaexunxang self-assigned this May 13, 2025
@xaexunxang xaexunxang added the 🔧 Feature 기능 구현 label May 13, 2025
@xaexunxang xaexunxang linked an issue May 13, 2025 that may be closed by this pull request
2 tasks
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented May 13, 2025

## Walkthrough

이 변경사항은 카테고리별 이벤트 목록 페이지를 추가하고, 이벤트 목록 컴포넌트와 API를 카테고리 및 태그 기반 필터링을 지원하도록 확장합니다. 라우터, 메인 페이지, 타입 정의, 패키지 의존성, 그리고 관련 API 함수들이 이에 맞게 수정 및 추가되었습니다.

## Changes

| 파일/경로 요약                                                                 | 변경 요약                                                                                   |
|-------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|
| package.json                                                                  | `@tanstack/react-query-devtools` 패키지 의존성 추가                                        |
| src/app/routes/Router.tsx, src/app/routes/routes.ts                           | 카테고리 페이지 라우트 추가, `MAIN_ROUTES``/category` 경로 및 관련 설정 추가             |
| src/entities/event/api/event.ts                                               | 카테고리 기반 무한 스크롤 이벤트 조회 함수 추가, 기존 무한 스크롤 함수 리팩토링 및 반환값 구조화 |
| src/features/event-manage/event-list/ui/EventList.tsx                         | `category`, `tag` prop 지원, 관련 타입 및 쿼리 로직 확장                                    |
| src/pages/event/ui/AllEventsPage.tsx                                          | `EventList``tag="current"` prop 추가                                                    |
| src/pages/event/ui/CategoryPage.tsx                                           | 카테고리별 이벤트 페이지 컴포넌트 신설, 라우터 연동 및 레이아웃 구성                        |
| src/pages/home/ui/MainPage.tsx                                                | 메인 카드 버튼 클릭 시 각 카테고리로 이동하도록 네비게이션 로직 변경                        |
| src/shared/types/mainCardButtonType.ts                                        | 각 메인 카드 버튼에 `category` 속성 추가                                                    |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant MainPage
    participant Router
    participant CategoryPage
    participant EventList
    participant EventAPI

    User->>MainPage: 카테고리 카드 버튼 클릭
    MainPage->>Router: '/category' 경로로 category state 전달
    Router->>CategoryPage: CategoryPage 렌더링
    CategoryPage->>EventList: category prop 전달
    EventList->>EventAPI: getCategoryEventsInfinite(category, page, size)
    EventAPI-->>EventList: { items, hasNextPage }
    EventList-->>CategoryPage: 이벤트 목록 렌더링

Possibly related PRs

Suggested reviewers

  • Yejiin21

Poem

🐇
카테고리 따라 폴짝폴짝,
이벤트 목록도 새로워졌지!
버튼을 누르면 길이 열리고,
토끼는 즐겁게 코드를 뛰놀아.
새로운 경로, 새로운 이야기,
우리 모두 함께 고고!
🥕✨


<!-- walkthrough_end -->

<!-- announcements_start -->

> [!TIP]
> <details>
> <summary>⚡️ Faster reviews with caching</summary>
> 
> - CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure `Review - Disable Cache` at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the `Data Retention` setting under your Organization Settings.
> 
> Enjoy the performance boost—your workflow just got faster.
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

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

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 6716c248c2e75cc3f554aae5b92d32d8d2447c84 and 38439df85ebd8f7f7bde1298137b987b2b048aa8.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `yarn.lock` is excluded by `!**/yarn.lock`, `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (9)</summary>

* `package.json` (1 hunks)
* `src/app/routes/Router.tsx` (2 hunks)
* `src/app/routes/routes.ts` (1 hunks)
* `src/entities/event/api/event.ts` (1 hunks)
* `src/features/event-manage/event-list/ui/EventList.tsx` (2 hunks)
* `src/pages/event/ui/AllEventsPage.tsx` (2 hunks)
* `src/pages/event/ui/CategoryPage.tsx` (1 hunks)
* `src/pages/home/ui/MainPage.tsx` (1 hunks)
* `src/shared/types/mainCardButtonType.ts` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (9)</summary>

* package.json
* src/pages/event/ui/AllEventsPage.tsx
* src/pages/home/ui/MainPage.tsx
* src/shared/types/mainCardButtonType.ts
* src/app/routes/routes.ts
* src/entities/event/api/event.ts
* src/app/routes/Router.tsx
* src/features/event-manage/event-list/ui/EventList.tsx
* src/pages/event/ui/CategoryPage.tsx

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: storybook

</details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=GoTogether-Inc/frontend&utm_content=125):

- 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](https://www.coderabbit.ai/contact-us/support) 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](https://docs.coderabbit.ai/finishing-touches/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](https://docs.coderabbit.ai/guides/configure-coderabbit) 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](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

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 (6)
src/shared/types/mainCardButtonType.ts (1)

5-5: 카테고리 속성이 추가되었으며 타입 안전성을 향상시킬 수 있습니다.

카테고리 속성이 각 카드 버튼에 문자열로 추가되었습니다. 이는 기능적으로는 정확하지만, 타입 안전성을 높이기 위해 CategoryType을 명시적으로 사용하는 것이 좋을 것 같습니다.

다음과 같이 수정해 보세요:

+import { CategoryType } from '../types/baseEventType';

 export const cardButtons = [
   {
     iconPath: '/assets/main/DevStudy.svg',
     label: '개발/스터디',
-    category: 'DEVELOPMENT_STUDY',
+    category: 'DEVELOPMENT_STUDY' as CategoryType,
     onClick: () => console.log('DevStudy clicked'),
   },
   // 다른 버튼들도 동일하게 수정

또는 전체 객체에 타입을 적용하는 방법도 있습니다:

+import { CategoryType } from '../types/baseEventType';

+interface CardButton {
+  iconPath: string;
+  label: string;
+  category: CategoryType;
+  onClick: () => void;
+}

-export const cardButtons = [
+export const cardButtons: CardButton[] = [
   // ...

Also applies to: 11-11, 17-17, 23-23

src/pages/event/ui/CategoryPage.tsx (1)

10-10: 변수명 오타 수정이 필요합니다.

navigater는 오타입니다. 올바른 변수명은 navigate입니다.

-  const navigater = useNavigate();
+  const navigate = useNavigate();

그리고 이 변수의 모든 사용처도 수정해야 합니다:

-            onClick={() => navigater('/search')}
+            onClick={() => navigate('/search')}

-        leftButtonClick={() => navigater('/')}
+        leftButtonClick={() => navigate('/')}
src/features/event-manage/event-list/ui/EventList.tsx (2)

21-21: 쿼리 키 최적화 필요

현재 queryKey는 category나 tag가 undefined일 때 빈 문자열('')을 사용합니다. 이는 불필요한 리페칭을 발생시킬 수 있습니다.

-    queryKey: ['events', 'infinite', category ?? '', tag ?? ''],
+    queryKey: ['events', 'infinite', category || null, tag || null],

또는 더 명확하게:

-    queryKey: ['events', 'infinite', category ?? '', tag ?? ''],
+    queryKey: ['events', 'infinite', { category, tag }],

35-35: 프로덕션 코드에서 console.log 제거 필요

디버깅을 위한 console.log가 남아있습니다. 프로덕션 코드에서는 제거하는 것이 좋습니다.

-  console.log('EventList data.pages:', data?.pages);
src/entities/event/api/event.ts (2)

74-78: 일관성을 위해 getEventByTag 함수도 URLSearchParams를 사용하도록 수정을 고려해보세요.

getEventByTag 함수는 여전히 문자열 보간법을 사용하여 URL을 구성하고 있습니다. 코드베이스의 일관성을 위해 이 함수도 URLSearchParams를 사용하도록 리팩토링하는 것을 고려해보세요.

export const getEventByTag = async (tag: TagType, { page, size }: PaginationParams): Promise<EventItem[]> => {
-  const response = await axiosClient.get<{ result: EventItem[] }>(`/events?tags=${tag}&page=${page}&size=${size}`);
+  const params = new URLSearchParams();
+  
+  params.append('tags', tag);
+  params.append('page', page.toString());
+  params.append('size', size.toString());
+  
+  const response = await axiosClient.get<ApiResponse<EventItem[]>>(`/events?${params.toString()}`);
  return response.data.result || [];
};

80-89: getEventByCategory 함수도 URLSearchParams 패턴과 일관된 타입 사용을 고려해 보세요.

이 함수도 문자열 보간법 대신 URLSearchParams를 사용하도록 업데이트하는 것이 좋습니다. 또한 다른 API 함수들과 달리 응답 타입이 ApiResponse<EventItem[]> 대신 EventItem[]로 되어 있어 일관성이 떨어집니다. 응답 처리 방식을 표준화하는 것을 고려해보세요.

export const getEventByCategory = async (
  category: CategoryType,
  { page, size }: PaginationParams
): Promise<EventItem[]> => {
-  const response = await axiosClient.get<EventItem[]>(
-    `/events/category?category=${category}&page=${page}&size=${size}`
-  );
-  return response.data;
+  const params = new URLSearchParams();
+  
+  params.append('category', category);
+  params.append('page', page.toString());
+  params.append('size', size.toString());
+  
+  const response = await axiosClient.get<ApiResponse<EventItem[]>>(`/events/category?${params.toString()}`);
+  return response.data.result || [];
};
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 328a3bf and f9a9c76.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (9)
  • package.json (1 hunks)
  • src/app/routes/Router.tsx (2 hunks)
  • src/app/routes/routes.ts (1 hunks)
  • src/entities/event/api/event.ts (2 hunks)
  • src/features/event-manage/event-list/ui/EventList.tsx (1 hunks)
  • src/pages/event/ui/AllEventsPage.tsx (1 hunks)
  • src/pages/event/ui/CategoryPage.tsx (1 hunks)
  • src/pages/home/ui/MainPage.tsx (1 hunks)
  • src/shared/types/mainCardButtonType.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/app/routes/Router.tsx (1)
src/app/routes/routes.ts (1)
  • MAIN_ROUTES (1-12)
src/entities/event/api/event.ts (4)
src/entities/event/model/event.ts (2)
  • PaginationParams (19-22)
  • EventItem (30-34)
src/shared/types/api/apiResponse.ts (1)
  • ApiResponse (1-5)
src/shared/types/api/http-client.ts (1)
  • axiosClient (6-13)
src/shared/types/baseEventType.ts (1)
  • CategoryType (2-2)
src/features/event-manage/event-list/ui/EventList.tsx (3)
src/shared/types/baseEventType.ts (3)
  • BaseEvent (5-24)
  • CategoryType (2-2)
  • TagType (3-3)
src/shared/hooks/useInfiniteScroll.ts (1)
  • useInfiniteScroll (14-21)
src/entities/event/api/event.ts (2)
  • getCategoryEventsInfinite (53-72)
  • getAllEventsInfinite (31-50)
🔇 Additional comments (12)
package.json (1)

19-19: React Query DevTools 패키지 추가가 적절합니다.

React Query 상태를 디버깅하기 위한 DevTools 패키지를 추가한 것은 개발 과정에서 큰 도움이 될 것입니다. 선택한 버전이 기존 React Query 버전(^5.61.3)과 호환됩니다.

src/app/routes/routes.ts (1)

10-11: 카테고리 라우트 추가가 적절합니다.

카테고리 페이지를 위한 새로운 라우트 추가는 PR 목표와 일치합니다. 트레일링 콤마를 추가한 것도 향후 새로운 라우트를 추가할 때 Git diff를 깔끔하게 유지하는 좋은 관행입니다.

src/pages/event/ui/AllEventsPage.tsx (1)

29-29: EventList 컴포넌트에 태그 속성 추가가 적절합니다.

이벤트 목록에 "current" 태그를 명시적으로 전달하여 현재 이벤트만 표시하도록 한 것은 좋은 변경사항입니다. 이는 카테고리 필터링 구현이라는 PR 목표와 일치합니다.

src/pages/home/ui/MainPage.tsx (2)

62-62: 카테고리 페이지로 네비게이션 처리가 적절합니다.

카테고리 버튼 클릭 시 해당 카테고리 정보를 state로 전달하며 '/category' 경로로 이동하도록 구현한 것은 PR 목표에 부합하는 좋은 접근 방식입니다. React Router의 state 기능을 활용하여 데이터를 전달하는 방식도 적절합니다.


80-80: React Query DevTools 사용이 개발 경험을 향상시킬 것입니다.

React Query DevTools를 추가한 것은 package.json에 추가된 새로운, 의존성과 일치하며, 데이터 패칭 및 캐싱 상태를 디버깅하는 데 유용하게 사용될 것입니다.

src/app/routes/Router.tsx (1)

39-39: 카테고리 페이지 라우트가 올바르게 추가되었습니다.

새로운 CategoryPage 컴포넌트를 위한 라우트가 적절하게 추가되었습니다. 카테고리 정보는 URL 파라미터가 아닌 location state를 통해 전달되는 것으로 보입니다.

Also applies to: 50-50

src/pages/event/ui/CategoryPage.tsx (1)

18-24: 검색 기능이 완전히 구현되지 않았습니다.

현재 SearchTextField가 있지만 onChange 핸들러가 비어있고 실제 검색 기능이 구현되지 않았습니다.

검색 기능을 제대로 구현하거나, 현재 단계에서 필요하지 않다면 주석으로 TODO를 추가하는 것이 좋습니다.

        centerContent={
          <SearchTextField
            iconPath={<img src={searchIcon} alt="searchIcon" />}
            onClick={() => navigater('/search')}
-            onChange={() => {}}
+            onChange={(e) => {
+              // TODO: 검색 기능 구현 예정
+              console.log('Search input:', e.target.value);
+            }}
            placeholder="입력해주세요"
          />
        }
src/features/event-manage/event-list/ui/EventList.tsx (2)

22-27: API 호출 로직이 명확하고 잘 구현되었습니다.

카테고리 기반 이벤트 가져오기와 태그 기반 이벤트 가져오기를 구분하여 조건부로 처리하는 로직이 깔끔합니다.


29-29:

Details

✅ Verification successful

필터에 undefined 값 전달 여부 검토 필요

현재 tagcategory가 undefined인 경우에도 filters에 포함됩니다. API 호출 시 이러한 undefined 값이 어떻게 처리되는지 확인이 필요합니다.


🏁 Script executed:

#!/bin/bash
# entities/event/api/event.ts 파일에서 undefined 매개변수 처리 방식 확인

# getAllEventsInfinite 및 getCategoryEventsInfinite 함수에서 undefined 매개변수 처리 확인
rg -A 5 "if \(tag\)" src/entities/event/api/event.ts
rg -A 5 "if \(category\)" src/entities/event/api/event.ts

Length of output: 339


🏁 Script executed:

#!/bin/bash
# category 필터 처리 여부 확인
rg -A5 "params.append('category'" src/entities/event/api/event.ts
rg -A5 "getCategoryEventsInfinite" src/entities/event/api/event.ts

Length of output: 457


🏁 Script executed:

#!/bin/bash
# getAllEventsInfinite 함수 전체 확인
rg -n "export const getAllEventsInfinite" -A10 src/entities/event/api/event.ts

# getCategoryEventsInfinite 함수 전체 확인
rg -n "export const getCategoryEventsInfinite" -A10 src/entities/event/api/event.ts

# 모든 params.append 호출 확인
rg -n "params\.append" src/entities/event/api/event.ts

Length of output: 1370


필터 undefined 처리 검토 결과

  • getAllEventsInfinite 함수에서는 tag가 falsy(undefined 등)인 경우 if (tag) 조건에 의해 tags 파라미터를 추가하지 않습니다.
  • getCategoryEventsInfinite 함수의 시그니처에는 category: CategoryType가 필수로 정의되어 있어, 컴파일 시 undefined 전달이 차단되며 항상 올바른 category 파라미터가 포함됩니다.

결론적으로, UI에서 filters: { tag, category }를 전달해도 API 호출 시 의도치 않은 undefined 파라미터가 전송되지 않으므로 추가 조치가 필요 없습니다.

src/entities/event/api/event.ts (3)

15-26: searchEvents 함수의 가독성이 개선되었습니다.

함수 시그니처와 구현이 더 명확하게 포맷팅되어 가독성이 향상되었습니다. 파라미터를 URLSearchParams를 사용하여 구성하는 것은 URL 인코딩을 올바르게 처리하는 좋은 방법입니다.


31-50: URLSearchParams를 사용한 개선된 파라미터 처리 방식입니다.

문자열 보간법 대신 URLSearchParams를 사용하여 쿼리 파라미터를 구성하는 방식으로 개선되었습니다. 이 접근 방식은 다음과 같은 이점이 있습니다:

  1. 특수 문자의 자동 인코딩
  2. 코드 가독성 향상
  3. 파라미터 구성의 일관성

또한 response.data.result ?? []와 같은 nullish 병합 연산자를 사용하여 결과가 없을 경우를 적절히 처리하고 있습니다.


52-72: 카테고리별 이벤트 목록을 무한 스크롤로 조회하는 함수가 잘 구현되었습니다.

새로 추가된 getCategoryEventsInfinite 함수는 카테고리 기반 이벤트 필터링을 위한 API를 잘 구현하고 있습니다. URLSearchParams를 사용한 파라미터 구성 방식과 반환 구조가 getAllEventsInfinite 함수와 일관성 있게 구현되어 있습니다.

다만 이미 존재하는 getEventByCategory 함수(80-89줄)와의 관계를 고려해볼 필요가 있습니다:

  1. getEventByCategory/events/category 엔드포인트를 사용하지만, 새 함수는 /events/categories를 사용합니다.
  2. 두 함수의 역할이 유사하므로 기존 함수를 대체하거나 통합할 계획이 있는지 확인해보세요.

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/event/ui/CategoryPage.tsx (2)

15-15: 카테고리가 undefined일 경우에 대한 처리가 필요합니다.

현재 코드에서는 사용자가 직접 URL을 통해 /category로 접근할 경우 category 값이 undefined가 될 수 있습니다. 이 경우에 대한 처리가 없어 오류가 발생할 수 있습니다.

카테고리가 없을 경우에 대한 처리를 추가하세요:

  const category = location.state?.category;

+  // 카테고리가 없을 경우 메인 페이지로 리다이렉트
+  useEffect(() => {
+    if (!category) {
+      navigater('/', { replace: true });
+    }
+  }, [category, navigater]);

43-43: 🛠️ Refactor suggestion

카테고리가 없을 경우 EventList 렌더링에 대한 처리가 필요합니다.

category 값이 undefined일 경우, EventList 컴포넌트가 오류를 발생시킬 수 있습니다.

조건부 렌더링을 추가하여 category 값이 있는 경우에만 해당 카테고리의 이벤트를 표시하도록 수정하세요:

-      <EventList category={category} />
+      {category ? (
+        <EventList category={category} />
+      ) : (
+        <div className="mt-8 text-center text-gray-500">
+          카테고리를 선택해 주세요.
+        </div>
+      )}
🧹 Nitpick comments (2)
src/pages/event/ui/CategoryPage.tsx (1)

12-14: navigater 변수명 오타를 수정하세요.

navigater 변수명은 일반적으로 navigator로 작성하는 것이 관례입니다. 또는 React Router의 경우 navigate로 작성하는 것이 일반적입니다.

-  const navigater = useNavigate();
+  const navigate = useNavigate();

이 변경에 따라 다른 부분도 navigate로 변경해야 합니다:

-            onClick={() => navigater('/search')}
+            onClick={() => navigate('/search')}

-        leftButtonClick={() => navigater('/')}
+        leftButtonClick={() => navigate('/')}
src/pages/event/ui/AllEventsPage.tsx (1)

13-13: navigater 변수명 오타를 수정하세요.

navigater 변수명은 일반적으로 navigator로 작성하는 것이 관례입니다. 또는 React Router의 경우 navigate로 작성하는 것이 일반적입니다.

-  const navigater = useNavigate();
+  const navigate = useNavigate();

이 변경에 따라 다른 부분도 navigate로 변경해야 합니다:

-            onClick={() => navigater('/search')}
+            onClick={() => navigate('/search')}

-        leftButtonClick={() => navigater('/')}
+        leftButtonClick={() => navigate('/')}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 62340ff and 6716c24.

📒 Files selected for processing (2)
  • src/pages/event/ui/AllEventsPage.tsx (2 hunks)
  • src/pages/event/ui/CategoryPage.tsx (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/pages/event/ui/AllEventsPage.tsx (1)
src/app/provider/authStore.ts (1)
  • useAuthStore (17-33)
src/pages/event/ui/CategoryPage.tsx (1)
src/app/provider/authStore.ts (1)
  • useAuthStore (17-33)
🔇 Additional comments (5)
src/pages/event/ui/AllEventsPage.tsx (5)

8-10: 인증 관련 기능 추가에 대한 구현이 적절합니다.

인증 상태 관리와 로그인 모달 기능을 위한 필요한 임포트가 추가되었습니다.


14-14: 인증 스토어 활용이 적절하게 구현되었습니다.

useAuthStore에서 필요한 상태와 함수들을 적절하게 구조 분해 할당하여 사용하고 있습니다.


30-37: 로그인 버튼 구현이 적절합니다.

사용자의 로그인 상태에 따라 버튼 텍스트와 동작을 다르게 설정하는 것이 잘 구현되었습니다.


39-39: 로그인 모달 구현이 적절합니다.

framer-motion의 AnimatePresence를 사용하여 모달이 자연스럽게 나타나고 사라지도록 구현하였습니다.


41-41: EventList에 tag 속성 추가가 적절합니다.

현재 이벤트 목록만 표시하도록 tag="current" 속성을 추가한 것이 적절합니다. 이는 CategoryPage와의 일관성을 유지하면서 필터링 기능을 구현한 좋은 방식입니다.

@xaexunxang xaexunxang force-pushed the feat/#107/event-category-api branch from 6716c24 to 38439df Compare May 13, 2025 13:24
@github-actions
Copy link
Copy Markdown

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.

수고하셨습니당

@xaexunxang xaexunxang merged commit 411ea9b into develop May 13, 2025
2 checks passed
@xaexunxang xaexunxang deleted the feat/#107/event-category-api branch May 13, 2025 16:40
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