Feat(audience): 내 관람 공연 카드 클릭 시 공연 상세 페이지로 이동 구현#306
Feat(audience): 내 관람 공연 카드 클릭 시 공연 상세 페이지로 이동 구현#306jin-evergreen wants to merge 14 commits intodevelopfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughFestival 및 Pagination 타입을 중앙화하고 관련 응답 타입을 Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~28 minutes Suggested labels
Suggested reviewers
검토 포인트 Must
Suggest
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/audience/src/shared/types/home-response.ts`:
- Line 10: The types use inconsistent naming for the same field:
UpcomingFestivalItem defines dday while Festival defines dDay, and
use-home-festivals.ts currently maps upcomingFestivalData.dday → dDay; align
these by choosing one canonical field name (prefer camelCase dDay) and update
the type declaration (UpcomingFestivalItem) and any places that produce/consume
the API to use dDay, or if the API returns dday, keep the type as dday and
centralize a single mapping in use-home-festivals.ts; ensure the mapping and the
types (UpcomingFestivalItem, Festival) and usages (upcomingFestivalData.dday,
references to dDay) are consistently updated together.
- Line 1: The import currently brings in only type definitions (Festival,
PaginationResponse) from './festival'; change it to a type-only import by using
"import type" for Festival and PaginationResponse so the compiler/tree-shaking
knows these are types (update the import statement that references Festival and
PaginationResponse in home-response.ts).
In `@apps/audience/src/shared/types/my-events-response.ts`:
- Line 1: Change the plain import of Festival and PaginationResponse to a
type-only import: replace "import { Festival, PaginationResponse } from
'./festival';" with a type import so only types are imported (e.g., "import type
{ Festival, PaginationResponse } from './festival';") to match the pattern used
in viewed-festival.ts and avoid bundling runtime imports.
In `@apps/audience/src/shared/types/viewed-festival.ts`:
- Line 1: The import in viewed-festival.ts currently brings in Festival and
PaginationResponse as values; change it to a type-only import by using "import
type" for Festival and PaginationResponse so they are erased at runtime and
remove the runtime dependency on './festival'—update the statement that imports
Festival and PaginationResponse to use type-only imports (referencing Festival
and PaginationResponse) so bundlers/tree-shaking and runtime remain optimal.
In `@apps/audience/src/widgets/home/components/festival-card/festival-card.tsx`:
- Line 9: The import currently brings in the Festival symbol as a value; since
Festival is only used as a TypeScript type, change the import to a type-only
import to avoid residual runtime import and satisfy ESLint: replace the existing
import of Festival with a type import (import type { Festival } from
'@shared/types/festival') wherever Festival is referenced in festival-card.tsx
(e.g., props, interfaces, or type annotations) and ensure no runtime usages of
Festival remain.
In
`@apps/audience/src/widgets/home/components/festival-section/festival-section.tsx`:
- Line 12: 현재 Festival 타입은 값이 아니라 타입 주석으로만 사용되므로 import를 타입 전용으로 바꿔 주세요:
Festival 심볼을 가져오는 import 문을 일반 import에서 "import type { Festival } from
'@shared/types/festival'" 형식으로 변경하고 컴포넌트 festival-section.tsx 내에서 값으로 사용되는 곳이
없는지(예: new, instanceof 등) 확인해 불필요한 런타임 의존성이 생기지 않게 해주세요.
In `@apps/audience/src/widgets/my-events/festival-list.tsx`:
- Line 6: Replace the value import with a type-only import for the Festival
type: change the existing import statement that brings in Festival to use
"import type { Festival }" (so the module only imports the type and not runtime
code); update the import line where Festival is referenced in festival-list
(e.g., the import of Festival at the top of the file) to "import type { Festival
} from '@shared/types/festival'".
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: c3da3818-e095-4d98-bf74-9c7ea78a0018
📒 Files selected for processing (8)
apps/audience/src/entities/festival/api/festival.tsapps/audience/src/shared/types/festival.tsapps/audience/src/shared/types/home-response.tsapps/audience/src/shared/types/my-events-response.tsapps/audience/src/shared/types/viewed-festival.tsapps/audience/src/widgets/home/components/festival-card/festival-card.tsxapps/audience/src/widgets/home/components/festival-section/festival-section.tsxapps/audience/src/widgets/my-events/festival-list.tsx
apps/audience/src/widgets/home/components/festival-card/festival-card.tsx
Outdated
Show resolved
Hide resolved
apps/audience/src/widgets/home/components/festival-section/festival-section.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/audience/src/widgets/home/components/festival-card/festival-card.tsx`:
- Around line 13-18: Make onCardClick optional on the FestivalCardProps
interface by changing its type to optional (onCardClick?: (festivalId: number)
=> void) and update the FestivalCard component to safely call the handler using
optional chaining (e.g., onCardClick?.(festival.id)) wherever it is invoked;
ensure any internal references to onCardClick in FestivalCard and related
handlers (props type FestivalCardProps, FestivalCard component render/click
handlers) account for the prop possibly being undefined.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: cdcf37bc-00fb-4d4e-8e43-1fa1bfa3e75b
📒 Files selected for processing (7)
apps/audience/src/entities/festival/api/festival.tsapps/audience/src/shared/types/home-response.tsapps/audience/src/shared/types/my-events-response.tsapps/audience/src/shared/types/viewed-festival.tsapps/audience/src/widgets/home/components/festival-card/festival-card.tsxapps/audience/src/widgets/home/components/festival-section/festival-section.tsxapps/audience/src/widgets/my-events/festival-list.tsx
apps/audience/src/widgets/home/components/festival-card/festival-card.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/audience/src/widgets/home/components/festival-section/festival-section.tsx (1)
66-76: 🧹 Nitpick | 🔵 TrivialSuggest:
handleCardClick을useCallback으로 감싸는 것을 고려해 주세요.현재 구현도 동작에 문제는 없지만,
FestivalCard가memo로 감싸져 있거나 리스트가 길어질 경우 불필요한 리렌더링을 방지할 수 있어요.♻️ 제안하는 수정
+import { useCallback } from 'react'; import { generatePath, useNavigate } from 'react-router'; // ... - const handleCardClick = (festivalId: number) => { + const handleCardClick = useCallback((festivalId: number) => { navigate( generatePath(ROUTE_PATH.NOTICE_LIST, { eventId: String(festivalId), }), ); - }; + }, [navigate]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/audience/src/widgets/home/components/festival-section/festival-section.tsx` around lines 66 - 76, handleCardClick이 매 렌더마다 새 함수로 생성되어 FestivalCard(memo일 경우)들의 불필요한 리렌더를 유발할 수 있으니 handleCardClick을 React의 useCallback으로 감싸서 메모이제이션하세요; FestivalSection 컴포넌트 안의 handleCardClick을 useCallback(() => { ... }, [/* 여기에 함수에서 참조하는 state/props, 예: navigate, setSelectedFestival 등 */]) 형태로 변경하고 FestivalCard로 전달되는 모든 외부 의존값들을 의존성 배열에 정확히 포함시켜 리렌더링을 최소화하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In
`@apps/audience/src/widgets/home/components/festival-section/festival-section.tsx`:
- Around line 66-76: handleCardClick이 매 렌더마다 새 함수로 생성되어 FestivalCard(memo일 경우)들의
불필요한 리렌더를 유발할 수 있으니 handleCardClick을 React의 useCallback으로 감싸서 메모이제이션하세요;
FestivalSection 컴포넌트 안의 handleCardClick을 useCallback(() => { ... }, [/* 여기에 함수에서
참조하는 state/props, 예: navigate, setSelectedFestival 등 */]) 형태로 변경하고 FestivalCard로
전달되는 모든 외부 의존값들을 의존성 배열에 정확히 포함시켜 리렌더링을 최소화하세요.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 294d8505-0737-458f-8c50-b10300b1d12c
📒 Files selected for processing (5)
apps/audience/src/entities/festival/api/festival.tsapps/audience/src/pages/home/home.tsxapps/audience/src/pages/home/model/use-home-festivals.tsapps/audience/src/shared/types/home-response.tsapps/audience/src/widgets/home/components/festival-section/festival-section.tsx
Sohyunnnn
left a comment
There was a problem hiding this comment.
수고많으셨습니다 !!! 👍
코멘트 몇 개 적어두었으니, 한 번 확인 부탁드립니다 :)
apps/audience/src/widgets/home/components/festival-section/festival-section.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/audience/src/entities/festival/api/festival.ts`:
- Around line 10-12: The FestivalsResponse and UpcomingFestivalResponse types
currently imported from `@shared/types/home-response` bleed page-specific
semantics into the festival entity API; create a festival-specific response
types file (e.g., festival-response.ts) next to the festival entity/API,
move/define FestivalsResponse and UpcomingFestivalResponse there, update imports
in functions like getAllFestivals and getWishlists to import from the new
festival-response module, and remove the dependency on
`@shared/types/home-response` so the entity layer no longer depends on a
page-scoped module.
In `@apps/audience/src/shared/constants/path.ts`:
- Around line 16-18: The ROUTE object currently only exposes ROUTE.noticeList
which builds the notices path; add an additional route builder (e.g.,
ROUTE.festivalDetail or ROUTE.eventDetail) to support navigating to the
event/festival detail page by returning `/events/${eventId}` and keep consistent
naming with noticeList, or confirm that noticeList is the intended single route
and leave as-is; update any usages to the new ROUTE.<name> function to preserve
consistency when more routes are added.
In
`@apps/audience/src/widgets/home/components/festival-section/festival-section.tsx`:
- Around line 11-12: FestivalSection currently imports ROUTE and calls navigate
(via useNavigate) inside the widget, coupling UI to routing; remove direct
routing from FestivalSection and instead accept an onFestivalClick prop (e.g.,
onFestivalClick: (festival: Festival) => void) and call that when a card is
clicked; move useNavigate, ROUTE and the navigate(ROUTE.noticeList(...)) logic
up to the parent/feature/page so the parent passes a handler that performs
navigate(ROUTE.noticeList(...)) — update all internal handlers in
FestivalSection (card click callbacks around FestivalSection,
festivalCardClickHandler, etc.) to invoke onFestivalClick and delete imports of
useNavigate and ROUTE from the widget.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: bed53fed-abfb-431e-b5eb-075ef3136dd5
📒 Files selected for processing (13)
apps/audience/src/entities/festival/api/festival.tsapps/audience/src/entities/festival/model/query-options.tsapps/audience/src/features/my-events/query.tsapps/audience/src/pages/home/home.tsxapps/audience/src/pages/home/model/use-home-festivals.tsapps/audience/src/pages/my-events/my-events.tsxapps/audience/src/shared/constants/end-point.tsapps/audience/src/shared/constants/path.tsapps/audience/src/shared/types/festival.tsapps/audience/src/shared/types/home-response.tsapps/audience/src/shared/types/my-events-response.tsapps/audience/src/widgets/home/components/festival-section/festival-section.tsxapps/audience/src/widgets/my-events/festival-list.tsx
💤 Files with no reviewable changes (3)
- apps/audience/src/shared/types/my-events-response.ts
- apps/audience/src/features/my-events/query.ts
- apps/audience/src/widgets/my-events/festival-list.tsx
| FestivalsResponse, | ||
| UpcomingFestivalResponse, | ||
| UpcomingFestivalsResponse, | ||
| } from '@shared/types/home-response'; |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Suggest: FestivalsResponse는 home-response 밖으로 분리해 주세요.
getAllFestivals와 getWishlists는 공용 festival entity API인데, 응답 타입이 @shared/types/home-response에 머물면 home이라는 페이지 의미가 entity 레이어로 스며듭니다. 이번처럼 재사용 범위가 넓어진 타입은 festival 전용 응답 타입 파일로 옮기거나 API 근처로 이동하는 편이 의존성 방향이 더 자연스럽습니다.
As per coding guidelines apps/**/src/entities/**: Entity 레이어예요. - 단일 도메인 개념을 표현해요. - 페이지/라우트 개념은 금지예요.
Also applies to: 15-18
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/audience/src/entities/festival/api/festival.ts` around lines 10 - 12,
The FestivalsResponse and UpcomingFestivalResponse types currently imported from
`@shared/types/home-response` bleed page-specific semantics into the festival
entity API; create a festival-specific response types file (e.g.,
festival-response.ts) next to the festival entity/API, move/define
FestivalsResponse and UpcomingFestivalResponse there, update imports in
functions like getAllFestivals and getWishlists to import from the new
festival-response module, and remove the dependency on
`@shared/types/home-response` so the entity layer no longer depends on a
page-scoped module.
apps/audience/src/widgets/home/components/festival-section/festival-section.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
apps/audience/src/pages/home/home.tsx (1)
32-34:⚠️ Potential issue | 🟠 MajorMust: 현재 카드 클릭 시 공연 상세가 아니라 공지 목록으로 이동합니다.
PR 목표가 “공연 상세 페이지로 이동”이라면, 여기서
ROUTE.noticeList(festivalId)로 보내는 건 목적지 자체가 다릅니다. 지금 구현은/events/{id}/notices이동이므로 상세 화면 요구사항을 충족하지 못합니다. 상세 페이지가 맞다면 전용 detail route/builder로 바꾸셔야 하고, 반대로 공지 목록이 의도라면 PR 설명과 사용자 기대를 같이 정리해 주시는 편이 좋겠습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/audience/src/pages/home/home.tsx` around lines 32 - 34, The click handler handleCardClick currently navigates to ROUTE.noticeList(festivalId) (the notices list) but the PR requires navigating to the event detail page; update the navigation target in handleCardClick to the event detail route builder (e.g., ROUTE.eventDetail(festivalId) or the app’s equivalent detail route function) so clicking a card opens the performance detail page, and, if notices was intended, update PR description to reflect that behavior instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/audience/src/shared/constants/path.ts`:
- Around line 20-21: The noticeEdit path builder (noticeEdit) is not registered
in the router (ROUTE_PATH.NOTICE_EDIT is not mapped to any route) and will lead
to NotFound; either remove or hide the noticeEdit builder from the public
constants until a corresponding edit screen exists, or add a route entry that
mounts the edit page and maps ROUTE_PATH.NOTICE_EDIT to the edit component
(ensure the route uses the same URL pattern
`/events/:eventId/notices/:noticeId/edit` and the component name used in
routes.tsx matches the intended edit screen).
---
Duplicate comments:
In `@apps/audience/src/pages/home/home.tsx`:
- Around line 32-34: The click handler handleCardClick currently navigates to
ROUTE.noticeList(festivalId) (the notices list) but the PR requires navigating
to the event detail page; update the navigation target in handleCardClick to the
event detail route builder (e.g., ROUTE.eventDetail(festivalId) or the app’s
equivalent detail route function) so clicking a card opens the performance
detail page, and, if notices was intended, update PR description to reflect that
behavior instead.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: a43d3071-a1a3-4efa-a738-061d194a0f4e
📒 Files selected for processing (3)
apps/audience/src/pages/home/home.tsxapps/audience/src/shared/constants/path.tsapps/audience/src/widgets/home/components/festival-section/festival-section.tsx
📌 Summary
내 관람 공연 카드 클릭 시 해당 공연 상세 페이지로 이동하도록 했습니다.
📚 Tasks
FestivalList,FestivalCard구조 개선🔍 Describe
내 관람 공연 카드 공연 클릭 시 공연 상세 페이지로 이동
우선,
FestivalList컴포넌트의 구조를 일부 변경했습니다. 기존 컴포넌트 내부에 있던 칩 상태 관련 로직을 모두 삭제하고,FestivalCard내부에서 기존에 분리해둔FestivalStatusGroup을 활용하여 구현했습니다. 추가로 기존에는FestivalList내부에서 컴파운드 컴포넌트를 직접 조립하여 사용하는 방식이었는데, 기존에 만들어둔FestivalCard컴포넌트를 활용하여 코드를 단순화하였습니다. 페이지 이동의 경우handleCardClick핸들러 함수를 정의하여 구현했습니다.(26.03.09 기준, 코드 리뷰를 반영하여
FestivalList를 삭제하고 해당 로직을 페이지 컴포넌트에서 처리하고 있습니다!)👀 To Reviewer
NaN으로 보이는 문제는 제외하고 확인해주세요!이번 PR 범위와 관련된 타입 정리를 진행했어요. 현재 저희는 API 별로 필요한 타입을 정의하여 사용하고 있다보니, 동일한 Festival 관련 인터페이스와 페이지네이션 관련 인터페이스가 서로 다른 이름으로 각 파일에 중복적으로 정의되어 있어요. 이를 개선하기 위해
festival.ts파일에서 핵심이 되는 타입(Festival,Pagination)을 한번에 관리하고, 각 API 파일에서는 import 해서 사용하도록 했어요.이 경우, 이제 기존 파일들에는 해당 API에 맞는 응답 형식인
~~~Response인터페이스들만 남게 되는데, 이 또한 대부분의 파일에서 중복으로 사용되고 있어요. 우선 향후 API 별로 고유한 필드가 추가되었을 때 자유롭게 확장할 수 있도록 핵심 도메인 모델은 공유하고, 응답 형식은 독립적으로 개별 인터페이스를 유지했어요. 다만 개인적인 의견일 뿐 아니라 타입의 경우 이 부분 외에도 추후에 프로젝트 전반적으로 한번 손봐야 할 것 같아서, 좋은 아이디어가 있으시다면 알려주시면 감사하겠습니다!📸 Screenshot
2026-03-07.12.49.42.mov