Skip to content

Conversation

@LeeCh0129
Copy link
Contributor

@LeeCh0129 LeeCh0129 commented Aug 2, 2025

📌 변경 사항 개요

내 체험 관리 페이질르 구현했습니다. 사용자가 등록한 체험 목록 조회 + 수정 및 삭제 연동, myactivity 프로필 섹션 레이아웃까지 추가 완료했습니다.

📝 상세 내용

체험 목록

  • 체험 목록의 경우 무한 스크롤을 이용하여 최신순 정렬로 10개씩 로딩
  • 체험 등록/수정/삭제 기존 페이지와 연동(라우팅)

🔗 관련 이슈

🖼️ 스크린샷(선택사항)

image image image image

💡 참고 사항

  • 모달 zIndex, backdropClassName props를 추가하여 모달 배경이 헤더에 가려지도록 수정

Summary by CodeRabbit

  • 신규 기능

    • 내 활동 관리 페이지에 활동 목록 조회, 무한 스크롤, 삭제 기능이 추가되었습니다.
    • 활동 카드, 삭제 확인 모달, 빈 목록 안내 등 다양한 컴포넌트가 도입되었습니다.
    • 활동 목록이 없을 때 안내 메시지가 표시됩니다.
    • 활동 삭제 시 확인 모달이 나타나며, 삭제 진행 중 상태를 표시합니다.
    • 내 활동 관련 API와 React Query 훅이 추가되어 데이터 관리가 개선되었습니다.
    • 사용자 프로필 기반 레이아웃이 도입되어 로딩 및 오류 상태 UI가 향상되었습니다.
    • 더보기 옵션 아이콘 컴포넌트가 새로 추가되었습니다.
  • 스타일

    • 일부 버튼 및 모달의 크기 단위 클래스가 수정되고, 모달의 z-index 및 배경 스타일이 개선되었습니다.

@LeeCh0129 LeeCh0129 self-assigned this Aug 2, 2025
@LeeCh0129 LeeCh0129 added the ✨ Feature 기능구현 label Aug 2, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 2, 2025

Walkthrough

내 체험 관리 페이지가 새로 구현되었습니다. 레이아웃, 활동 카드, 삭제 모달, 비어있는 상태 컴포넌트가 추가되었고, API 연동 및 무한 스크롤, 삭제 기능이 적용되었습니다. 관련 커스텀 훅과 API 모듈도 새로 도입되었습니다. 일부 스타일 클래스가 수정되었습니다.

Changes

Cohort / File(s) Change Summary
내 체험 관리 UI 컴포넌트
src/app/(with-header)/mypage/activities/components/ActivityCard.tsx, src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx, src/app/(with-header)/mypage/activities/components/EmptyActivities.tsx
활동 카드, 삭제 확인 모달, 비어있는 상태 UI 컴포넌트 신규 추가
내 체험 관리 페이지 및 레이아웃
src/app/(with-header)/mypage/activities/page.tsx, src/app/(with-header)/myactivity/layout.tsx
내 체험 관리 페이지 전체 구현 및 레이아웃 컴포넌트 추가, 무한 스크롤 및 삭제 로직 포함
API 연동 및 커스텀 훅
src/apis/myActivities.ts, src/hooks/useMyActivitiesQueries.ts
내 체험 목록 조회/삭제 API 모듈 및 React Query 기반 커스텀 훅 추가
공통/스타일/아이콘
public/assets/svg/moreOptionsIcon.tsx, src/app/(with-header)/mypage/reservations/components/CancelReservationModal.tsx, src/components/Modal/Content.tsx
더보기 아이콘 SVG 컴포넌트 신규 추가, 일부 스타일 클래스명(px 단위 제거) 변경 및 모달 z-index 옵션 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MyActivitiesPage
    participant useMyActivitiesInfinite
    participant useDeleteMyActivity
    participant API

    User->>MyActivitiesPage: 페이지 접속
    MyActivitiesPage->>useMyActivitiesInfinite: 활동 목록 요청
    useMyActivitiesInfinite->>API: GET /my-activities (cursorId, size)
    API-->>useMyActivitiesInfinite: 활동 목록 반환
    useMyActivitiesInfinite-->>MyActivitiesPage: 데이터 전달
    MyActivitiesPage-->>User: 활동 목록/비어있는 상태/로딩/에러 UI 표시

    User->>MyActivitiesPage: 삭제 버튼 클릭
    MyActivitiesPage->>DeleteActivityModal: 삭제 확인 모달 표시
    User->>DeleteActivityModal: 삭제 확정 클릭
    DeleteActivityModal->>useDeleteMyActivity: 삭제 요청
    useDeleteMyActivity->>API: DELETE /deleteActivity/{id}
    API-->>useDeleteMyActivity: 성공/실패 응답
    useDeleteMyActivity-->>MyActivitiesPage: 쿼리 무효화 및 알림
    MyActivitiesPage-->>User: 갱신된 목록/알림 표시
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Assessment against linked issues

Objective Addressed Explanation
내 체험 관리 페이지 레이아웃 (#100)
내 체험 관리 API 연동 (#100)

Assessment against linked issues: Out-of-scope changes

해당 이슈의 목적 외 변경사항은 발견되지 않았습니다.

Suggested reviewers

  • minimo-9
  • BokyungCodes

Poem

🐰
체험 관리 페이지가 새로 태어났네,
무한 스크롤, 삭제도 척척 잘 되네!
비어있을 땐 토끼처럼 귀엽게,
카드와 모달, 아이콘까지 반짝이네.
리뷰어님, 오늘도 힘내세요!
🥕✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/100

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.

❤️ 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.
    • 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 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 for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for 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 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.

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 86ccfd7 and fe6f07c.

📒 Files selected for processing (9)
  • public/assets/svg/moreOptionsIcon.tsx (1 hunks)
  • src/apis/myActivities.ts (1 hunks)
  • src/app/(with-header)/myactivity/layout.tsx (1 hunks)
  • src/app/(with-header)/mypage/activities/components/ActivityCard.tsx (1 hunks)
  • src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx (1 hunks)
  • src/app/(with-header)/mypage/activities/components/EmptyActivities.tsx (1 hunks)
  • src/app/(with-header)/mypage/activities/page.tsx (1 hunks)
  • src/app/(with-header)/mypage/reservations/components/CancelReservationModal.tsx (2 hunks)
  • src/hooks/useMyActivitiesQueries.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/app/(with-header)/mypage/activities/components/EmptyActivities.tsx (2)
src/app/(with-header)/mypage/dashboard/components/EmptyDashboard.tsx (1)
  • EmptyDashboard (3-17)
src/app/(with-header)/mypage/reservations/components/EmptyReservations.tsx (1)
  • EmptyReservations (3-17)
src/app/(with-header)/mypage/reservations/components/CancelReservationModal.tsx (3)
src/types/modalTypes.ts (1)
  • ModalProps (9-13)
src/components/Button.tsx (1)
  • Button (18-49)
src/components/Modal/Content.tsx (1)
  • ModalContent (19-45)
🪛 Biome (2.1.2)
public/assets/svg/moreOptionsIcon.tsx

[error] 4-11: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)

src/app/(with-header)/mypage/activities/components/ActivityCard.tsx

[error] 76-81: Static Elements should not be interactive.

To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.

(lint/a11y/noStaticElementInteractions)


[error] 76-81: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


[error] 67-71: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 84-88: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 90-94: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

🔇 Additional comments (6)
src/app/(with-header)/mypage/reservations/components/CancelReservationModal.tsx (2)

22-22: Tailwind CSS 클래스 일관성 개선을 승인합니다

px 단위를 제거하여 Tailwind의 표준 유틸리티 클래스 명명 규칙과 일치시킨 것은 좋은 변경사항입니다.


46-46: 클래스명 일관성 개선을 승인합니다

버튼의 크기 클래스에서 px 단위를 제거한 것이 일관성 있는 개선사항입니다.

src/app/(with-header)/mypage/activities/components/EmptyActivities.tsx (1)

3-17: 일관된 빈 상태 컴포넌트 구현을 승인합니다

기존 EmptyReservationsEmptyDashboard 컴포넌트와 동일한 패턴을 따라 일관성을 유지하고 있습니다. 구조와 스타일링이 적절합니다.

src/apis/myActivities.ts (1)

26-28: 삭제 API 함수 구현을 승인합니다

간단하고 명확한 삭제 API 구현입니다.

src/hooks/useMyActivitiesQueries.ts (1)

19-30: 무한 스크롤 구현을 승인합니다

React Query의 useInfiniteQuery를 적절히 활용한 무한 스크롤 구현입니다. 커서 기반 페이지네이션과 적절한 캐싱 전략을 사용하고 있습니다.

src/app/(with-header)/myactivity/layout.tsx (1)

1-74: 레이아웃 구현이 잘 되어있습니다

로딩 상태, 에러 처리, 반응형 디자인이 적절히 구현되었습니다. 스켈레톤 UI가 실제 UI와 일치하여 사용자 경험이 향상됩니다.

@@ -0,0 +1,18 @@
import React from 'react';

const MoreOptionsIcon = ({ size = 24, ...props }) => (
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

TypeScript 타입 정의와 접근성 개선이 필요합니다

컴포넌트에 적절한 타입 정의가 없고, 접근성을 위한 속성이 누락되어 있습니다.

다음과 같이 개선하세요:

+interface MoreOptionsIconProps extends React.SVGProps<SVGSVGElement> {
+  size?: number;
+}
+
-const MoreOptionsIcon = ({ size = 24, ...props }) => (
+const MoreOptionsIcon = ({ size = 24, ...props }: MoreOptionsIconProps) => (
   <svg
     xmlns='http://www.w3.org/2000/svg'
     width={size}
     height={size}
     fill='none'
     viewBox='0 0 40 40'
+    role='img'
+    aria-label='더보기 옵션'
     {...props}
   >
📝 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 MoreOptionsIcon = ({ size = 24, ...props }) => (
interface MoreOptionsIconProps extends React.SVGProps<SVGSVGElement> {
size?: number;
}
const MoreOptionsIcon = ({ size = 24, ...props }: MoreOptionsIconProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={size}
height={size}
fill="none"
viewBox="0 0 40 40"
role="img"
aria-label="더보기 옵션"
{...props}
>
{/* existing icon paths/circles */}
</svg>
);
🤖 Prompt for AI Agents
In public/assets/svg/moreOptionsIcon.tsx at line 3, the MoreOptionsIcon
component lacks TypeScript type definitions and accessibility attributes. Define
proper TypeScript types for the component props, including size and any other
SVG attributes. Add accessibility attributes such as role="img" and an
appropriate aria-label or title to improve screen reader support.

Comment on lines +8 to +20
export const getMyActivitiesWithPagination = async (params?: {
cursorId?: number;
size?: number;
}): Promise<MyActivitiesResponse> => {
const queryParams = new URLSearchParams();
if (params?.cursorId)
queryParams.append('cursorId', params.cursorId.toString());
if (params?.size) queryParams.append('size', params.size.toString());

const url = `/my-activities${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
const response = await privateInstance.get(url);
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.

🧹 Nitpick (assertive)

API 함수 구현을 승인하며 쿼리 파라미터 처리 개선을 제안합니다

전반적인 구현이 잘 되어 있습니다. 쿼리 파라미터 생성 부분을 약간 개선할 수 있습니다.

더 간결한 구현을 위해 다음과 같이 개선할 수 있습니다:

 export const getMyActivitiesWithPagination = async (params?: {
   cursorId?: number;
   size?: number;
 }): Promise<MyActivitiesResponse> => {
-  const queryParams = new URLSearchParams();
-  if (params?.cursorId)
-    queryParams.append('cursorId', params.cursorId.toString());
-  if (params?.size) queryParams.append('size', params.size.toString());
-
-  const url = `/my-activities${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
+  const queryParams = new URLSearchParams();
+  if (params?.cursorId !== undefined) {
+    queryParams.append('cursorId', params.cursorId.toString());
+  }
+  if (params?.size !== undefined) {
+    queryParams.append('size', params.size.toString());
+  }
+  
+  const queryString = queryParams.toString();
+  const url = `/my-activities${queryString ? `?${queryString}` : ''}`;
   const response = await privateInstance.get(url);
   return response.data;
 };
📝 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 const getMyActivitiesWithPagination = async (params?: {
cursorId?: number;
size?: number;
}): Promise<MyActivitiesResponse> => {
const queryParams = new URLSearchParams();
if (params?.cursorId)
queryParams.append('cursorId', params.cursorId.toString());
if (params?.size) queryParams.append('size', params.size.toString());
const url = `/my-activities${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
const response = await privateInstance.get(url);
return response.data;
};
export const getMyActivitiesWithPagination = async (params?: {
cursorId?: number;
size?: number;
}): Promise<MyActivitiesResponse> => {
const queryParams = new URLSearchParams();
if (params?.cursorId !== undefined) {
queryParams.append('cursorId', params.cursorId.toString());
}
if (params?.size !== undefined) {
queryParams.append('size', params.size.toString());
}
const queryString = queryParams.toString();
const url = `/my-activities${queryString ? `?${queryString}` : ''}`;
const response = await privateInstance.get(url);
return response.data;
};
🤖 Prompt for AI Agents
In src/apis/myActivities.ts around lines 8 to 20, the current query parameter
construction manually appends each parameter, which can be simplified. Refactor
the code to build the URLSearchParams object more concisely by conditionally
adding parameters in a cleaner way or by using a helper function to filter and
append only defined parameters. This will make the code more readable and
maintainable without changing its behavior.

Comment on lines +67 to +71
onClick={() => setIsMenuOpen(!isMenuOpen)}
className='flex h-40 w-40 items-center justify-center rounded-full hover:bg-gray-100'
>
<MoreOptionsIcon size={40} />
</button>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

버튼에 명시적인 type 속성을 추가하세요

모든 버튼에 type="button" 속성을 추가하여 의도하지 않은 폼 제출을 방지하세요.

             <button
+              type="button"
               onClick={() => setIsMenuOpen(!isMenuOpen)}
               className='flex h-40 w-40 items-center justify-center rounded-full hover:bg-gray-100'
             >

                   <button
+                    type="button"
                     onClick={handleEdit}
                     className='flex h-62 w-full items-center justify-center border-b border-gray-300 px-46 py-18 text-center text-lg font-medium text-gray-900 hover:bg-gray-50'
                   >

                   <button
+                    type="button"
                     onClick={handleDelete}
                     className='flex h-62 w-full items-center justify-center px-46 py-18 text-center text-lg font-medium text-gray-900 hover:bg-gray-50'
                   >

Also applies to: 83-87, 89-93

🧰 Tools
🪛 Biome (2.1.2)

[error] 67-71: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

🤖 Prompt for AI Agents
In src/app/(with-header)/mypage/activities/components/ActivityCard.tsx around
lines 67 to 71, 83 to 87, and 89 to 93, the button elements lack an explicit
type attribute, which can cause unintended form submissions. Add type="button"
to each button element in these line ranges to clearly specify their behavior
and prevent accidental form submissions.

Comment on lines +73 to +96
{isMenuOpen && (
<>
<div
className='fixed inset-0 z-40'
onClick={() => setIsMenuOpen(false)}
/>

{/* 드롭다운 메뉴 */}
<div className='absolute top-full right-0 z-50 w-160 rounded-md border border-gray-300 bg-white shadow-lg'>
<button
onClick={handleEdit}
className='flex h-62 w-full items-center justify-center border-b border-gray-300 px-46 py-18 text-center text-lg font-medium text-gray-900 hover:bg-gray-50'
>
수정하기
</button>
<button
onClick={handleDelete}
className='flex h-62 w-full items-center justify-center px-46 py-18 text-center text-lg font-medium text-gray-900 hover:bg-gray-50'
>
삭제하기
</button>
</div>
</>
)}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

🛠️ Refactor suggestion

드롭다운 메뉴의 접근성을 개선하세요

현재 구현은 키보드 네비게이션을 지원하지 않습니다. 접근성을 위해 다음을 고려하세요:

  1. ESC 키로 메뉴 닫기
  2. 포커스 트랩 구현
  3. 적절한 ARIA 속성 추가

Headless UI의 Menu 컴포넌트나 Radix UI의 DropdownMenu를 사용하는 것을 추천합니다. 이미 구현된 접근성 기능을 활용할 수 있습니다.

🧰 Tools
🪛 Biome (2.1.2)

[error] 76-81: Static Elements should not be interactive.

To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.

(lint/a11y/noStaticElementInteractions)


[error] 76-81: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.

Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.

(lint/a11y/useKeyWithClickEvents)


[error] 84-88: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 90-94: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

🤖 Prompt for AI Agents
In src/app/(with-header)/mypage/activities/components/ActivityCard.tsx around
lines 73 to 96, the dropdown menu lacks keyboard accessibility features such as
closing with the ESC key, focus trapping, and ARIA attributes. To fix this,
replace the current custom dropdown implementation with a well-supported
accessible component like Headless UI's Menu or Radix UI's DropdownMenu, which
provide built-in keyboard navigation, focus management, and ARIA roles. This
will ensure the dropdown is fully accessible without manually implementing these
features.

}: DeleteActivityModalProps) {
return (
<Modal isOpen={isOpen} onOpenChange={(open) => !open && onCancel()}>
<Modal.Content className='!h-184 !w-298 !max-w-none !min-w-0 !rounded-xl !p-0'>
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

🛠️ Refactor suggestion

!important 사용을 최소화하세요

Modal.Content의 className에 많은 !important가 사용되고 있습니다. 이는 CSS 우선순위 문제를 나타내며, Modal 컴포넌트의 기본 스타일과 충돌이 있을 수 있습니다. Modal 컴포넌트의 기본 스타일을 수정하거나 더 구체적인 CSS 선택자를 사용하는 것이 좋습니다.

🤖 Prompt for AI Agents
In src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx at
line 22, the className for Modal.Content uses multiple !important flags, which
indicates CSS specificity conflicts. To fix this, remove the !important
declarations and instead adjust the CSS by either modifying the Modal
component's base styles or applying more specific CSS selectors to override
styles without using !important.

Comment on lines 22 to 30
<Modal.Content className='!h-184 !w-298 !max-w-none !min-w-0 !rounded-xl !p-0'>
<div
className='flex h-full w-full flex-col items-center justify-center gap-24 bg-white p-16'
style={{
borderRadius: '12px',
background: '#FFFFFF',
boxShadow: '0px 4px 16px 0px rgba(17, 34, 17, 0.05)',
overflow: 'hidden',
}}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

인라인 스타일과 className을 혼용하지 마세요

classNamestyle 속성을 함께 사용하는 것은 유지보수성을 저하시킵니다. Tailwind CSS 클래스로 통일하거나 CSS 모듈을 사용하세요.

       <Modal.Content className='!h-184 !w-298 !max-w-none !min-w-0 !rounded-xl !p-0'>
         <div
-          className='flex h-full w-full flex-col items-center justify-center gap-24 bg-white p-16'
-          style={{
-            borderRadius: '12px',
-            background: '#FFFFFF',
-            boxShadow: '0px 4px 16px 0px rgba(17, 34, 17, 0.05)',
-            overflow: 'hidden',
-          }}
+          className='flex h-full w-full flex-col items-center justify-center gap-24 bg-white p-16 rounded-xl shadow-[0px_4px_16px_0px_rgba(17,34,17,0.05)] overflow-hidden'
         >
📝 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
<Modal.Content className='!h-184 !w-298 !max-w-none !min-w-0 !rounded-xl !p-0'>
<div
className='flex h-full w-full flex-col items-center justify-center gap-24 bg-white p-16'
style={{
borderRadius: '12px',
background: '#FFFFFF',
boxShadow: '0px 4px 16px 0px rgba(17, 34, 17, 0.05)',
overflow: 'hidden',
}}
<Modal.Content className='!h-184 !w-298 !max-w-none !min-w-0 !rounded-xl !p-0'>
<div
className='flex h-full w-full flex-col items-center justify-center gap-24 bg-white p-16 rounded-xl shadow-[0px_4px_16px_0px_rgba(17,34,17,0.05)] overflow-hidden'
>
🤖 Prompt for AI Agents
In src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx
around lines 22 to 30, avoid mixing inline styles with className attributes.
Replace the inline style object with equivalent Tailwind CSS utility classes or
move the styles to a CSS module and apply them via className to improve
maintainability and consistency.

Comment on lines +75 to +87
<div className='w-full max-w-none lg:max-w-792'>
<div className='mb-24 flex items-center justify-between'>
<h1 className='text-nomad text-3xl leading-42 font-bold'>
내 체험 관리
</h1>
<Button
variant='primary'
onClick={handleCreateActivity}
className='h-48 w-120 rounded-sm px-16 py-8 text-base font-bold whitespace-nowrap'
>
체험 등록하기
</Button>
</div>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

중복된 헤더 섹션을 컴포넌트로 추출하세요

헤더 섹션(제목과 버튼)이 로딩, 에러, 성공 상태에서 반복됩니다. 별도의 컴포넌트로 추출하여 코드 중복을 줄이세요.

+const ActivityHeader = ({ onCreateActivity }: { onCreateActivity: () => void }) => (
+  <div className='mb-24 flex items-center justify-between'>
+    <h1 className='text-nomad text-3xl leading-42 font-bold'>
+      내 체험 관리
+    </h1>
+    <Button
+      variant='primary'
+      onClick={onCreateActivity}
+      className='h-48 w-120 rounded-sm px-16 py-8 text-base font-bold whitespace-nowrap'
+    >
+      체험 등록하기
+    </Button>
+  </div>
+);

 export default function MyActivitiesPage() {
   // ... existing code ...

   if (isLoading) {
     return (
       <div className='w-full max-w-none lg:max-w-792'>
-        <div className='mb-24 flex items-center justify-between'>
-          <h1 className='text-nomad text-3xl leading-42 font-bold'>
-            내 체험 관리
-          </h1>
-          <Button
-            variant='primary'
-            onClick={handleCreateActivity}
-            className='h-48 w-120 rounded-sm px-16 py-8 text-base font-bold whitespace-nowrap'
-          >
-            체험 등록하기
-          </Button>
-        </div>
+        <ActivityHeader onCreateActivity={handleCreateActivity} />
         // ... rest of loading state

Also applies to: 104-115, 128-139

🤖 Prompt for AI Agents
In src/app/(with-header)/mypage/activities/page.tsx around lines 75 to 87, 104
to 115, and 128 to 139, the header section containing the title and button is
duplicated across loading, error, and success states. Extract this header
section into a separate reusable component that accepts necessary props like the
button click handler. Replace the repeated header code in all these sections
with this new component to reduce duplication and improve maintainability.

</div>
<div className='w-full max-w-none lg:max-w-792'>
{/* 제목 */}
<div className='mb-48 flex items-center justify-between'>
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

헤더 하단 여백이 일관되지 않습니다

성공 상태에서 헤더의 하단 여백이 mb-48로 설정되어 있지만, 로딩과 에러 상태에서는 mb-24입니다. 의도적인 것이 아니라면 일관성을 위해 통일하세요.

-        <div className='mb-48 flex items-center justify-between'>
+        <div className='mb-24 flex items-center justify-between'>
🤖 Prompt for AI Agents
In src/app/(with-header)/mypage/activities/page.tsx at line 128, the bottom
margin class on the header container is set to mb-48 for the success state but
mb-24 for loading and error states, causing inconsistent spacing. Update the
margin class in the loading and error state containers to mb-48 to match the
success state, ensuring consistent bottom margin across all states.

Comment on lines +167 to +172
<DeleteActivityModal
isOpen={deleteModal.isOpen}
onCancel={handleDeleteClose}
onConfirm={handleDeleteConfirm}
isLoading={deleteActivityMutation.isPending}
/>
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

모달과 헤더 간의 z-index 충돌을 확인하세요

PR 설명에서 언급된 z-index 충돌 문제를 해결해야 합니다. 모달이 헤더 위에 제대로 표시되는지 확인하세요.


🏁 Script executed:

#!/bin/bash
# 헤더와 모달 관련 z-index 값 확인
echo "=== Header z-index values ==="
rg -A 2 "z-" --glob "**/*header*" --glob "**/*Header*"

echo -e "\n=== Modal z-index values ==="
rg -A 2 "z-" --glob "**/Modal*" --glob "**/modal*"

echo -e "\n=== DeleteActivityModal의 부모 컴포넌트들 확인 ==="
fd -e tsx -e jsx | xargs rg "DeleteActivityModal" -l

Length of output: 794


🏁 Script executed:

#!/bin/bash
# DeleteActivityModal 컴포넌트 내 z-index 정의 및 className 확인

MODAL_FILE=$(fd 'DeleteActivityModal.tsx')
echo "DeleteActivityModal 파일 위치: $MODAL_FILE"

echo "=== z-index 정의 확인 ==="
rg -n "z-" -A3 "$MODAL_FILE" || echo "→ z-index 클래스 없음"

echo -e "\n=== className 사용 라인 ==="
rg -n "className" -A2 "$MODAL_FILE"

Length of output: 1623


🏁 Script executed:

#!/bin/bash
# DeleteActivityModal 파일 상단의 import 문 확인
FILE='src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx'
echo "=== ${FILE} 상단 1-60줄 ==="
sed -n '1,60p' "$FILE"

Length of output: 2158


🏁 Script executed:

#!/bin/bash
# Modal 컴포넌트 파일 위치 확인 및 z-index 정의 점검
MODAL_FILE=$(fd 'Modal.tsx' 2>/dev/null | head -n 1)
echo "Modal 파일 위치: $MODAL_FILE"

echo -e "\n=== 상단 1-200줄 확인 ==="
sed -n '1,200p' "$MODAL_FILE"

echo -e "\n=== z-index 클래스 및 style 내 z-index 검색 ==="
rg -n "z-" "$MODAL_FILE" || echo "→ z-index 클래스 없음"
rg -n "zIndex" "$MODAL_FILE" || echo "→ style 속성 내 zIndex 없음"

Length of output: 2676


🏁 Script executed:

#!/bin/bash
# Modal 컴포넌트 파일 위치 및 내용 확인
echo "== Modal.tsx 위치 찾기 =="
find src/components -type f -name "Modal.tsx"

echo -e "\n== Modal.tsx 상단 1-200줄 확인 =="
find src/components -type f -name "Modal.tsx" | head -n1 | xargs sed -n '1,200p'

echo -e "\n== Modal.tsx에서 z-index 클래스 및 style 내 zIndex 검색 =="
find src/components -type f -name "Modal.tsx" | head -n1 | xargs rg -n "z-" || echo "→ z-index 클래스 없음"
find src/components -type f -name "Modal.tsx" | head -n1 | xargs rg -n "zIndex" || echo "→ style 속성 내 zIndex 없음"

Length of output: 4230


모달이 헤더(z-100) 위에 제대로 표시되도록 z-index 설정 추가 필요
헤더 컴포넌트(fixed z-100) 위에 모달이 렌더링되려면, 현재 Modal.Content에 z-index가 없어 헤더 뒤로 가려질 수 있습니다.

수정 위치:

  • src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx
    • 22행(\<Modal.Content>): 클래스에 헤더보다 높은 z-index 유틸리티(예: !z-[200])를 추가해주세요.
- <Modal.Content className='!h-184 !w-298 !max-w-none !min-w-0 !rounded-xl !p-0'>
+ <Modal.Content className='!z-[200] !h-184 !w-298 !max-w-none !min-w-0 !rounded-xl !p-0'>

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

🤖 Prompt for AI Agents
In src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx at
line 22, the Modal.Content element lacks a z-index, causing the modal to appear
behind the header which has z-100. To fix this, add a Tailwind CSS class with a
higher z-index such as !z-[200] to the Modal.Content's className to ensure the
modal displays above the header.

Comment on lines +33 to +49
export const useDeleteMyActivity = () => {
const queryClient = useQueryClient();

return useMutation({
mutationFn: deleteMyActivity,
onSuccess: () => {
// 내 체험 관련 쿼리들 무효화
queryClient.invalidateQueries({
queryKey: MY_ACTIVITIES_QUERY_KEYS.ALL,
});
alert('체험이 삭제되었습니다.');
},
onError: (error) => {
alert(`체험 삭제 실패: ${error.message}`);
},
});
};
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

삭제 기능 구현을 승인하며 사용자 피드백 개선을 제안합니다

뮤테이션 로직과 쿼리 무효화 처리가 적절합니다. 하지만 사용자 경험 개선을 위해 alert() 대신 토스트 알림 시스템 사용을 권장합니다.

더 나은 사용자 경험을 위해 다음과 같이 개선하는 것을 고려해보세요:

     onSuccess: () => {
       queryClient.invalidateQueries({
         queryKey: MY_ACTIVITIES_QUERY_KEYS.ALL,
       });
-      alert('체험이 삭제되었습니다.');
+      // Toast 알림 시스템 사용 권장
+      // toast.success('체험이 삭제되었습니다.');
     },
     onError: (error) => {
-      alert(`체험 삭제 실패: ${error.message}`);
+      // Toast 알림 시스템 사용 권장
+      // toast.error(`체험 삭제 실패: ${error.message}`);
     },
📝 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 const useDeleteMyActivity = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: deleteMyActivity,
onSuccess: () => {
// 내 체험 관련 쿼리들 무효화
queryClient.invalidateQueries({
queryKey: MY_ACTIVITIES_QUERY_KEYS.ALL,
});
alert('체험이 삭제되었습니다.');
},
onError: (error) => {
alert(`체험 삭제 실패: ${error.message}`);
},
});
};
export const useDeleteMyActivity = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: deleteMyActivity,
onSuccess: () => {
// 내 체험 관련 쿼리들 무효화
queryClient.invalidateQueries({
queryKey: MY_ACTIVITIES_QUERY_KEYS.ALL,
});
// Toast 알림 시스템 사용 권장
// toast.success('체험이 삭제되었습니다.');
},
onError: (error) => {
// Toast 알림 시스템 사용 권장
// toast.error(`체험 삭제 실패: ${error.message}`);
},
});
};
🤖 Prompt for AI Agents
In src/hooks/useMyActivitiesQueries.ts around lines 33 to 49, replace the
alert() calls in onSuccess and onError handlers with a toast notification system
to improve user experience. Import and use a toast library (e.g., react-toastify
or similar) to show non-blocking, styled notifications instead of blocking alert
dialogs. This change will provide smoother feedback without interrupting user
interaction.

Copy link
Contributor

@BokyungCodes BokyungCodes left a comment

Choose a reason for hiding this comment

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

이제 마이페이지 거의 다 완성됐네요! 수고하셨습니다🤲

@evaain706
Copy link
Contributor

구현 수고하셨습니다!

Copy link
Contributor

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

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx (1)

23-23: !important 사용을 최소화하세요

Modal.Content의 className에 많은 !important가 사용되고 있습니다. 이는 CSS 우선순위 문제를 나타내며, Modal 컴포넌트의 기본 스타일과 충돌이 있을 수 있습니다. Modal 컴포넌트의 기본 스타일을 수정하거나 더 구체적인 CSS 선택자를 사용하는 것이 좋습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fe6f07c and 9879658.

📒 Files selected for processing (3)
  • src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx (1 hunks)
  • src/app/(with-header)/mypage/reservations/components/CancelReservationModal.tsx (2 hunks)
  • src/components/Modal/Content.tsx (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/components/Modal/Content.tsx (3)
src/types/modalTypes.ts (1)
  • ModalProps (9-13)
src/contexts/ModalContext.tsx (1)
  • useModalContext (20-26)
src/lib/utils.ts (1)
  • cn (4-6)
🔇 Additional comments (6)
src/app/(with-header)/mypage/reservations/components/CancelReservationModal.tsx (3)

27-27: 인라인 스타일을 Tailwind CSS로 잘 변환했습니다

rounded-xl, bg-white, shadow-[0px_4px_16px_0px_rgba(17,34,17,0.05)] 등으로 인라인 스타일을 Tailwind 클래스로 깔끔하게 변환했습니다. 일관된 스타일링 방식으로 유지보수성이 향상되었습니다.


42-42: !important 제거가 적절합니다

버튼 클래스에서 불필요한 !important를 제거하여 CSS 특이성 문제를 방지했습니다. 깔끔한 개선입니다.


22-26: CancelReservationModal의 z-index 설정은 올바르게 적용됩니다

CancelReservationModal에서 사용된 backdropClassName='!z-[999]'는 Tailwind CSS의 arbitrary value 문법에 맞으므로 문제없이 작동합니다.
추가로, DeleteActivityModal에서는 !z-999 대신 !z-[999] 형태로 통일하시면 일관성을 유지할 수 있습니다.

src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx (1)

27-27: 스타일링이 일관되게 잘 적용되었습니다

인라인 스타일 대신 Tailwind CSS 클래스를 사용하여 일관된 스타일링을 구현했습니다. 이는 유지보수성 향상에 도움이 됩니다.

src/components/Modal/Content.tsx (2)

20-23: 인터페이스 확장이 적절합니다

ExtendedModalContentProps로 기존 ModalProps를 확장하여 zIndexbackdropClassName 지원을 추가한 것이 좋습니다. 타입 안전성을 유지하면서 기능을 확장했습니다.


46-52: 백드롭 스타일링 개선이 잘 구현되었습니다

cn 유틸리티를 사용하여 백드롭의 기본 클래스, z-index 클래스, 커스텀 클래스를 적절히 조합했습니다. 조건부 클래스 적용이 깔끔하게 처리되었습니다.

Comment on lines +14 to +61
export default function DeleteActivityModal({
isOpen,
onCancel,
onConfirm,
isLoading = false,
}: DeleteActivityModalProps) {
return (
<Modal isOpen={isOpen} onOpenChange={(open) => !open && onCancel()}>
<Modal.Content
className='!h-184 !w-298 !max-w-none !min-w-0 !rounded-xl !p-0'
zIndex={999}
backdropClassName='!z-999'
>
<div className='flex h-full w-full flex-col items-center justify-center gap-24 rounded-xl bg-white p-16 shadow-[0px_4px_16px_0px_rgba(17,34,17,0.05)]'>
{/* 체크 아이콘 */}
<div className='flex justify-center'>
<CheckIcon size={24} />
</div>

{/* 메시지 */}
<p className='text-nomad text-center text-lg font-medium'>
체험을 삭제하시겠어요?
</p>

{/* 버튼 */}
<div className='flex gap-12'>
<Button
variant='secondary'
className='text-md h-38 w-80 rounded-lg border border-gray-300 font-medium'
onClick={onCancel}
disabled={isLoading}
>
아니오
</Button>
<Button
variant='primary'
className='text-md bg-nomad h-38 w-80 rounded-lg font-medium text-white'
onClick={onConfirm}
disabled={isLoading}
>
{isLoading ? '삭제 중...' : '삭제하기'}
</Button>
</div>
</div>
</Modal.Content>
</Modal>
);
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

코드 중복을 줄이기 위한 공통 컴포넌트 고려

DeleteActivityModalCancelReservationModal이 거의 동일한 구조를 가지고 있습니다. 메시지와 버튼 텍스트만 다를 뿐입니다. 공통 ConfirmationModal 컴포넌트를 만들어 재사용성을 높이는 것을 고려해보세요.

공통 컴포넌트 예시:

interface ConfirmationModalProps {
  isOpen: boolean;
  onCancel: () => void;
  onConfirm: () => void;
  isLoading?: boolean;
  message: string;
  confirmText: string;
  cancelText?: string;
  loadingText?: string;
}
🤖 Prompt for AI Agents
In src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx
from lines 14 to 61, the DeleteActivityModal component shares almost identical
structure with CancelReservationModal except for message and button texts. To
reduce code duplication, create a reusable ConfirmationModal component that
accepts props for isOpen, onCancel, onConfirm, isLoading, message, confirmText,
cancelText, and loadingText. Replace DeleteActivityModal and
CancelReservationModal with this common component by passing the appropriate
texts as props.

<Modal.Content
className='!h-184 !w-298 !max-w-none !min-w-0 !rounded-xl !p-0'
zIndex={999}
backdropClassName='!z-999'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

잘못된 Tailwind 클래스명을 수정하세요

backdropClassName='!z-999'는 올바르지 않은 Tailwind 클래스명입니다. 대괄호 표기법을 사용해야 합니다.

다음과 같이 수정하세요:

-        backdropClassName='!z-999'
+        backdropClassName='!z-[999]'
📝 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
backdropClassName='!z-999'
backdropClassName='!z-[999]'
🤖 Prompt for AI Agents
In src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx at
line 25, the Tailwind class 'backdropClassName="!z-999"' is invalid. Replace it
with the correct bracket notation for arbitrary values by changing it to
'backdropClassName="!z-[999]"' to ensure proper styling.

const { isOpen } = useModalContext();
const [isMounted, setIsMounted] = useState(false);

const zIndexClass = zIndex ? `z-[${zIndex}]` : 'z-50';
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

동적 z-index 클래스 생성의 잠재적 문제

z-[${zIndex}] 형태의 동적 클래스 생성은 Tailwind CSS의 JIT 컴파일러가 해당 클래스를 인식하지 못할 수 있습니다. 런타임에 생성되는 클래스는 CSS에 포함되지 않을 위험이 있습니다.

다음 스크립트로 사용되는 z-index 값들을 확인하고 safelist에 추가하거나 미리 정의된 클래스를 사용하는 것을 고려해보세요:

미리 정의된 z-index 클래스를 사용하는 방향으로 개선:

-  const zIndexClass = zIndex ? `z-[${zIndex}]` : 'z-50';
+  const getZIndexClass = (z?: number) => {
+    switch (z) {
+      case 999: return 'z-[999]';
+      case 50: return 'z-50';
+      default: return 'z-50';
+    }
+  };
+  const zIndexClass = getZIndexClass(zIndex);

🏁 Script executed:

#!/bin/bash
# 코드베이스에서 사용되는 zIndex 값들 찾기
rg "zIndex=\{[0-9]+\}" --type tsx -o

Length of output: 66


현재 rg --type tsx 옵션이 지원되지 않아 스크립트가 실패했습니다. .tsx 파일 내에서 실제로 zIndex={숫자} 형태로 사용된 곳이 있는지 아래 스크립트로 재확인해 주세요.

이 후 사용되는 zIndex 값 목록에 따라 safelist 추가 여부나 미리 정의된 클래스 사용으로 전환할지 결정합시다.


🏁 Script executed:

#!/bin/bash
# .tsx 파일 전체에서 zIndex={숫자} 사용 위치 찾기
rg --glob '*.tsx' "zIndex\s*=\s*{[0-9]+}" -n .

Length of output: 166


아래 스크립트로 다시 한 번 .tsx 파일 전체에서 zIndex prop 사용 위치를 확인해 주세요.

만약 위 결과에 숫자 리터럴이 포함되어 있다면, 다음 스크립트로 순수 숫자 리터럴만 추출해 보세요.

이후 실제로 사용되는 zIndex 값 목록을 기반으로 Tailwind safelist 추가 또는 미리 정의된 클래스 전환 여부를 결정합시다.


🏁 Script executed:

#!/bin/bash
# .tsx 파일 전체에서 zIndex prop 사용 위치 확인
rg --glob '*.tsx' -n 'zIndex\s*=\s*{'

Length of output: 131


🏁 Script executed:

#!/bin/bash
# zIndex={숫자} 형태 리터럴 사용 위치 확인
grep -RPn --include="*.tsx" 'zIndex\s*=\s*\{\d+\}' .

Length of output: 261


Tailwind JIT에서 ‘z-[${zIndex}]’ 동적 클래스가 누락되지 않도록 설정 필요

현재 코드에서 사용된 zIndex는 다음 두 곳에서 숫자 리터럴로만 사용되고 있습니다:

  • src/app/(with-header)/mypage/activities/components/DeleteActivityModal.tsx:24 (zIndex={999})
  • src/app/(with-header)/mypage/reservations/components/CancelReservationModal.tsx:24 (zIndex={999})

제안 방안:

  • tailwind.config.js에 safelist에 해당 클래스를 추가
    // tailwind.config.js
    module.exports = {
      // …
      safelist: ['z-[999]'],
    }
  • 또는 theme.extend로 zIndex 스케일을 확장하고, 코드에서 브라켓 문법이 아닌 ‘z-999’ 형태를 사용
    // tailwind.config.js
    module.exports = {
      theme: {
        extend: {
          zIndex: {
            999: '999',
          },
        },
      },
    }
    // src/components/Modal/Content.tsx
  • const zIndexClass = zIndex ? z-[${zIndex}] : 'z-50';
  • const zIndexClass = zIndex ? z-${zIndex} : 'z-50';
    
    

위 중 하나를 적용해 JIT가 해당 클래스를 누락 없이 컴파일하도록 보장해주세요.

🤖 Prompt for AI Agents
In src/components/Modal/Content.tsx at line 34, the dynamic Tailwind class
`z-[${zIndex}]` may be omitted by Tailwind JIT compiler. To fix this, update
tailwind.config.js by either adding 'z-[999]' to the safelist array to ensure
the class is always included, or extend the theme's zIndex scale with a key
'999' and use the class 'z-999' in the code instead of bracket notation. Apply
one of these approaches to guarantee the zIndex class is compiled correctly.

@LeeCh0129 LeeCh0129 merged commit b9bbdeb into develop Aug 2, 2025
2 checks passed
@LeeCh0129 LeeCh0129 deleted the feat/100 branch August 2, 2025 09:41
@minimo-9 minimo-9 linked an issue Aug 4, 2025 that may be closed by this pull request
@minimo-9 minimo-9 removed a link to an issue Aug 4, 2025
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.

5 participants