Feat/#122 페이지 진입 시 이벤트 소개 모달 추가 및 이벤트 소개 페이지 디자인 수정#123
Feat/#122 페이지 진입 시 이벤트 소개 모달 추가 및 이벤트 소개 페이지 디자인 수정#123leeleeleeleejun merged 8 commits intodevelopfrom
Conversation
…자인 변경 - EventStats 컴포넌트 삭제
- EventResultClient에서 참여자 수 및 사용된 티켓 수를 표시하는 UI를 직접 드러냄
- FirstViewEventModal 컴포넌트 생성 - API에서 이벤트 정보 가져와 EventPrizeCard로 표시 - sessionStorage로 세션별 한 번만 표시 (새로고침 시 미표시) - 0.5초 딜레이 후 자연스럽게 모달 표시 - '자세히 보기' 버튼 클릭 시 이벤트 페이지로 이동 및 모달 닫기 - layout.tsx에 Suspense로 감싸서 전역 적용
Walkthrough이 PR은 이벤트 관련 UI를 리팩토링하여 PrizeInfo/EventStats/ParticipationStatus를 제거하고 새로운 EventPrizeCard로 통합하며, 첫 방문 시 이벤트 소개를 표시하는 FirstViewEventModal을 추가하고 소수의 스타일 조정을 포함합니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client (Browser)
participant Layout as RootLayout
participant Modal as FirstViewEventModal
participant Session as SessionStorage
participant API as GraphQL (useSuspenseQuery)
participant Server as API Server
Client->>Layout: 페이지 요청
Layout->>Modal: Suspense 내에서 마운트
Modal->>Session: has_seen 플래그 확인
alt 플래그 없음
Modal->>Session: has_seen=true 설정
Modal->>Modal: 500ms 후 모달 오픈 예약
Modal->>API: byPublic() 쿼리 호출
API->>Server: 이벤트 데이터 요청
Server-->>API: 이벤트 데이터 응답
API-->>Modal: 데이터 제공
Modal->>Client: EventPrizeCard 포함 모달 렌더 및 표시
else 플래그 존재
Modal-->>Client: 렌더 없음
end
Client->>Modal: 모달 닫기 또는 이동
Modal->>Modal: onClose 처리
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan
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: 1
🧹 Nitpick comments (5)
apps/web/app/events/lucky-draw/_components/Pages/MemberView/InProgressEvent/EventCountdown.tsx (1)
7-7: 함수에 명시적 반환 타입 추가를 권장합니다.코딩 가이드라인에 따르면 함수에 반환 타입이 필요합니다. 이번 변경 범위는 아니지만, 향후 유지보수를 위해 추가하는 것을 고려해 주세요.
♻️ 제안된 수정 사항
-export const EventCountdown = ({ eventEndDate }: { eventEndDate: string }) => { +export const EventCountdown = ({ eventEndDate }: { eventEndDate: string }): JSX.Element => {As per coding guidelines, "return types required on functions".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/app/events/lucky-draw/_components/Pages/MemberView/InProgressEvent/EventCountdown.tsx` at line 7, The EventCountdown component currently has no explicit return type; update the function signature for EventCountdown (which takes { eventEndDate: string }) to include an explicit React return type such as JSX.Element or React.ReactElement so the component's return is typed according to the coding guideline requiring return types on functions; locate the EventCountdown declaration and add the chosen return type to the function signature.apps/web/app/layout.tsx (1)
124-126: ErrorBoundary 추가 권장
FirstViewEventModal은useSuspenseQuery를 사용하며, API 호출 실패 시 에러를 throw합니다. 현재Suspense만 있고ErrorBoundary가 없어서 네트워크 오류나 API 장애 시 전체 앱이 크래시될 수 있습니다.이벤트 모달은 부가 기능이므로, 실패해도 앱 전체에 영향을 주지 않도록 ErrorBoundary로 감싸는 것을 권장합니다.
♻️ ErrorBoundary 추가 예시
+import { ErrorBoundary } from 'react-error-boundary' + +const SilentFallback = () => null + // layout.tsx 내부 -<Suspense fallback={null}> - <FirstViewEventModal /> -</Suspense> +<ErrorBoundary fallback={<SilentFallback />}> + <Suspense fallback={null}> + <FirstViewEventModal /> + </Suspense> +</ErrorBoundary>또는 Next.js의
error.tsx패턴을 사용할 수도 있습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/app/layout.tsx` around lines 124 - 126, Wrap the Suspense-wrapped component to prevent app-wide crashes by adding an ErrorBoundary around the Suspense + FirstViewEventModal (i.e., change the fragment containing <Suspense fallback={null}><FirstViewEventModal /></Suspense> to be nested inside an ErrorBoundary component); implement or reuse an ErrorBoundary component that catches render errors from FirstViewEventModal (which uses useSuspenseQuery), renders a safe fallback UI or null, and logs the error so API/network failures do not crash the whole app.apps/web/app/events/lucky-draw/_components/EventPrizeCard/EventPrizeCard.tsx (1)
13-18: 함수에 명시적 반환 타입 추가 권장코딩 가이드라인에 따라 함수에 반환 타입을 명시하는 것이 좋습니다.
♻️ 반환 타입 추가 제안
export const EventPrizeCard = ({ imageUrl, description, totalWinnersCount, participantsCount, -}: Props) => { +}: Props): React.ReactElement => { return (🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/app/events/lucky-draw/_components/EventPrizeCard/EventPrizeCard.tsx` around lines 13 - 18, The EventPrizeCard functional component lacks an explicit return type; update its signature to declare a TypeScript return type (e.g., JSX.Element or React.FC<Props>) so the component's return value is typed. Locate the EventPrizeCard declaration and add the return type after the parameter list (keeping Props as the param type) and ensure any imported React types are available (JSX.Element or React.FC) to satisfy the compiler and coding guidelines.apps/web/app/events/lucky-draw/_components/Pages/MemberView/InProgressEvent/InProgressEvent.tsx (2)
15-15: 함수에 명시적 반환 타입이 누락되었습니다.코딩 가이드라인에 따르면 함수에 반환 타입을 명시해야 합니다.
♻️ 반환 타입 추가
-export const InProgressEvent = () => { +export const InProgressEvent = (): React.ReactElement => {코딩 가이드라인에 따르면: "return types required on functions"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/app/events/lucky-draw/_components/Pages/MemberView/InProgressEvent/InProgressEvent.tsx` at line 15, 함수 InProgressEvent에 명시적 반환 타입이 빠져 있으니 해당 컴포넌트 선언(Export const InProgressEvent) 에 JSX.Element 또는 React.ReactElement 같은 명시적 반환 타입을 추가하여 타입 검사를 통과하도록 수정하세요; 파일에서 InProgressEvent 함수 시그니처를 찾아 현재 화살표 함수 선언에 반환 타입을 붙이고 필요한 경우 React 타입을 임포트하세요.
3-13: import 순서가 코딩 가이드라인을 따르지 않습니다.가이드라인에 따르면 import 순서는 다음과 같아야 합니다: Node/built-in, external packages, absolute imports, relative imports.
현재 코드에서는 external packages(
next/link,@tanstack/react-query,@repo/ui/*)와 absolute imports(@/_constants/path,@/_apis/queries/event,@/events/...)가 혼합되어 있고, relative imports(./EventCountdown,../../EmptyEventState)도 중간에 위치해 있습니다.♻️ 권장되는 import 순서
'use client' +import Link from 'next/link' +import { useSuspenseQuery } from '@tanstack/react-query' +import { Flex, Column } from '@repo/ui/components/Layout' +import { Icon } from '@repo/ui/components/Icon' +import { Text } from '@repo/ui/components/Text' +import { Button } from '@repo/ui/components/Button' + +import { CLIENT_PATH } from '@/_constants/path' +import { useEventQueries } from '@/_apis/queries/event' +import { EventPrizeCard } from '@/events/lucky-draw/_components/EventPrizeCard' + +import { EventCountdown } from './EventCountdown' +import { EmptyEventState } from '../../EmptyEventState' -import Link from 'next/link' -import { CLIENT_PATH } from '@/_constants/path' -import { useSuspenseQuery } from '@tanstack/react-query' -import { useEventQueries } from '@/_apis/queries/event' -import { Flex, Column } from '@repo/ui/components/Layout' -import { Icon } from '@repo/ui/components/Icon' -import { Text } from '@repo/ui/components/Text' -import { EventCountdown } from './EventCountdown' -import { EventPrizeCard } from '@/events/lucky-draw/_components/EventPrizeCard' -import { EmptyEventState } from '../../EmptyEventState' -import { Button } from '@repo/ui/components/Button'코딩 가이드라인에 따르면: "Organize imports in the following order: Node/built-in, external packages, absolute imports, relative imports"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/app/events/lucky-draw/_components/Pages/MemberView/InProgressEvent/InProgressEvent.tsx` around lines 3 - 13, The imports in InProgressEvent.tsx are out of order; reorder them to follow the project's guideline: external packages first (e.g., next/link, `@tanstack/react-query`), then absolute imports (e.g., `@/_constants/path`, `@/_apis/queries/event`, `@repo/ui/`*, `@/events/lucky-draw/_components/EventPrizeCard`), and finally relative imports (./EventCountdown, ../../EmptyEventState); ensure related UI imports (Flex, Column, Icon, Text, Button) are grouped together under absolute imports and move all relative imports to the bottom so the import list for Link, CLIENT_PATH, useSuspenseQuery, useEventQueries, EventPrizeCard, EventCountdown, and EmptyEventState matches the required order.
🤖 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/web/app/_components/FirstViewEventModal.tsx`:
- Around line 27-41: The sessionStorage is being set regardless of whether an
active event exists, causing the modal never to show later; update the useEffect
so it first checks `data` (return early if falsy) before reading/setting
`sessionStorage` and starting the `setTimeout` that calls `onOpen`, and ensure
the cleanup still clears the `timer` with `clearTimeout(timer)`; specifically
modify the `useEffect` that references `STORAGE_KEY`, `onOpen`,
`sessionStorage.setItem`, and `timer` so storage is only written when `data` is
present.
---
Nitpick comments:
In
`@apps/web/app/events/lucky-draw/_components/EventPrizeCard/EventPrizeCard.tsx`:
- Around line 13-18: The EventPrizeCard functional component lacks an explicit
return type; update its signature to declare a TypeScript return type (e.g.,
JSX.Element or React.FC<Props>) so the component's return value is typed. Locate
the EventPrizeCard declaration and add the return type after the parameter list
(keeping Props as the param type) and ensure any imported React types are
available (JSX.Element or React.FC) to satisfy the compiler and coding
guidelines.
In
`@apps/web/app/events/lucky-draw/_components/Pages/MemberView/InProgressEvent/EventCountdown.tsx`:
- Line 7: The EventCountdown component currently has no explicit return type;
update the function signature for EventCountdown (which takes { eventEndDate:
string }) to include an explicit React return type such as JSX.Element or
React.ReactElement so the component's return is typed according to the coding
guideline requiring return types on functions; locate the EventCountdown
declaration and add the chosen return type to the function signature.
In
`@apps/web/app/events/lucky-draw/_components/Pages/MemberView/InProgressEvent/InProgressEvent.tsx`:
- Line 15: 함수 InProgressEvent에 명시적 반환 타입이 빠져 있으니 해당 컴포넌트 선언(Export const
InProgressEvent) 에 JSX.Element 또는 React.ReactElement 같은 명시적 반환 타입을 추가하여 타입 검사를
통과하도록 수정하세요; 파일에서 InProgressEvent 함수 시그니처를 찾아 현재 화살표 함수 선언에 반환 타입을 붙이고 필요한 경우
React 타입을 임포트하세요.
- Around line 3-13: The imports in InProgressEvent.tsx are out of order; reorder
them to follow the project's guideline: external packages first (e.g.,
next/link, `@tanstack/react-query`), then absolute imports (e.g.,
`@/_constants/path`, `@/_apis/queries/event`, `@repo/ui/`*,
`@/events/lucky-draw/_components/EventPrizeCard`), and finally relative imports
(./EventCountdown, ../../EmptyEventState); ensure related UI imports (Flex,
Column, Icon, Text, Button) are grouped together under absolute imports and move
all relative imports to the bottom so the import list for Link, CLIENT_PATH,
useSuspenseQuery, useEventQueries, EventPrizeCard, EventCountdown, and
EmptyEventState matches the required order.
In `@apps/web/app/layout.tsx`:
- Around line 124-126: Wrap the Suspense-wrapped component to prevent app-wide
crashes by adding an ErrorBoundary around the Suspense + FirstViewEventModal
(i.e., change the fragment containing <Suspense
fallback={null}><FirstViewEventModal /></Suspense> to be nested inside an
ErrorBoundary component); implement or reuse an ErrorBoundary component that
catches render errors from FirstViewEventModal (which uses useSuspenseQuery),
renders a safe fallback UI or null, and logs the error so API/network failures
do not crash the whole app.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1807af44-448d-425b-a40e-e76b7bc0cb29
📒 Files selected for processing (16)
apps/web/app/_components/BottomNavigation/BottomNavigation.tsxapps/web/app/_components/FirstViewEventModal.tsxapps/web/app/events/lucky-draw/_components/EventPrizeCard/EventPrizeCard.tsxapps/web/app/events/lucky-draw/_components/EventPrizeCard/index.tsapps/web/app/events/lucky-draw/_components/EventStats/EventStats.tsxapps/web/app/events/lucky-draw/_components/EventStats/index.tsapps/web/app/events/lucky-draw/_components/Pages/GuestView/GuestView.tsxapps/web/app/events/lucky-draw/_components/Pages/MemberView/InProgressEvent/EventCountdown.tsxapps/web/app/events/lucky-draw/_components/Pages/MemberView/InProgressEvent/InProgressEvent.tsxapps/web/app/events/lucky-draw/_components/ParticipationStatus/ParticipationStatus.tsxapps/web/app/events/lucky-draw/_components/ParticipationStatus/index.tsxapps/web/app/events/lucky-draw/_components/PrizeInfo/PrizeInfo.tsxapps/web/app/events/lucky-draw/_components/PrizeInfo/index.tsapps/web/app/events/lucky-draw/result/[id]/EventResultClient.tsxapps/web/app/layout.tsxapps/web/app/places/new/_components/Step/EventWelcome/EventWelcome.tsx
💤 Files with no reviewable changes (6)
- apps/web/app/events/lucky-draw/_components/EventStats/index.ts
- apps/web/app/events/lucky-draw/_components/ParticipationStatus/index.tsx
- apps/web/app/events/lucky-draw/_components/EventStats/EventStats.tsx
- apps/web/app/events/lucky-draw/_components/PrizeInfo/index.ts
- apps/web/app/events/lucky-draw/_components/PrizeInfo/PrizeInfo.tsx
- apps/web/app/events/lucky-draw/_components/ParticipationStatus/ParticipationStatus.tsx
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/web/app/_components/FirstViewEventModal.tsx (1)
23-23: 컴포넌트 반환 타입 명시 권장 (선택 사항)코딩 가이드라인에 따라 함수에 반환 타입을 명시하는 것이 권장됩니다. TypeScript가 올바르게 추론하지만, 명시적 타입은 코드 문서화에 도움이 됩니다.
💡 반환 타입 추가 제안
-export const FirstViewEventModal = () => { +export const FirstViewEventModal = (): React.ReactNode => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/app/_components/FirstViewEventModal.tsx` at line 23, Add an explicit return type to the FirstViewEventModal component declaration to follow the TypeScript coding guideline: change the signature of FirstViewEventModal to include a return type (for example use (): JSX.Element or (): React.ReactElement or React.FC) so the component reads like `export const FirstViewEventModal = (): JSX.Element => { ... }`; update any related imports if you choose React.FC and ensure the component implementation remains unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@apps/web/app/_components/FirstViewEventModal.tsx`:
- Line 23: Add an explicit return type to the FirstViewEventModal component
declaration to follow the TypeScript coding guideline: change the signature of
FirstViewEventModal to include a return type (for example use (): JSX.Element or
(): React.ReactElement or React.FC) so the component reads like `export const
FirstViewEventModal = (): JSX.Element => { ... }`; update any related imports if
you choose React.FC and ensure the component implementation remains unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 44286c73-832c-422d-8d1c-a7bc964fa226
📒 Files selected for processing (1)
apps/web/app/_components/FirstViewEventModal.tsx
#️⃣연관된 이슈
📝작업 내용
페이지 첫 방문 시 이벤트 참여를 유도하는 모달을 추가하고, 이벤트 페이지 UI를 개선했습니다
1. EventPrizeCard 컴포넌트 개선
2. 방문 이벤트 모달 구현 (FirstViewEventModal)
3. 기타 UI 개선
스크린샷 (선택)
첫 방문 시 자동으로 표시되는 이벤트 모달

💬리뷰 요구사항(선택)
Summary by CodeRabbit
릴리스 노트
새로운 기능
스타일 개선
기타