Skip to content

feat: 이벤트 삭제 구현#145

Merged
Yejiin21 merged 11 commits intodevelopfrom
feat/#144/event-delete
May 27, 2025
Merged

feat: 이벤트 삭제 구현#145
Yejiin21 merged 11 commits intodevelopfrom
feat/#144/event-delete

Conversation

@Yejiin21
Copy link
Copy Markdown
Contributor

@Yejiin21 Yejiin21 commented May 26, 2025

이벤트 삭제 퍼블리싱

스크린샷 2025-05-26 오후 5 27 38 스크린샷 2025-05-26 오후 5 27 42

Summary by CodeRabbit

  • New Features

    • 이벤트 카드에 삭제 모드 및 삭제 확인 모달이 추가되어, 사용자가 이벤트를 삭제할 수 있습니다.
    • 파일 업로드 및 이벤트 정보 페이지에 유효성 검사 상태 콜백 기능이 도입되었습니다.
    • 티켓 호스트 레이아웃 및 대시보드 레이아웃에 홈 이동 버튼이 추가되었습니다.
    • 이벤트 등록 단계에서 입력 유효성 검사가 강화되었습니다.
  • Bug Fixes

    • 이벤트 상세 페이지 및 관련 훅, 컴포넌트의 import 경로 및 방식이 올바르게 수정되었습니다.
  • Refactor

    • 이벤트 삭제 API 및 관련 훅 구조가 개선되어, 삭제 기능이 별도 훅으로 분리되었습니다.
    • 일부 컴포넌트의 props 타입이 유연하게 개선되었습니다.
  • Style

    • 버튼, 레이아웃, 텍스트 크기 등 일부 UI 요소의 스타일이 조정되었습니다.

@Yejiin21 Yejiin21 requested review from hyeeuncho and xaexunxang May 26, 2025 08:29
@Yejiin21 Yejiin21 self-assigned this May 26, 2025
@Yejiin21 Yejiin21 added the 🔧 Feature 기능 구현 label May 26, 2025
@Yejiin21 Yejiin21 linked an issue May 26, 2025 that may be closed by this pull request
2 tasks
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented May 26, 2025

Walkthrough

이 변경 사항은 이벤트 삭제 기능을 추가하고, 관련 API 및 훅을 정비하며, UI 컴포넌트에 삭제 모드와 검증 콜백을 도입합니다. 이벤트 카드에서 삭제 버튼과 확인 모달이 제공되고, 삭제 성공 시 카드가 즉시 사라집니다. 여러 컴포넌트와 훅의 import 경로와 타입도 일관성 있게 수정되었습니다.

Changes

파일/경로 요약 변경 내용 요약
design-system/ui/Header.tsx leftButtonLabel 타입을 string에서 ReactNode로 변경, import에 ReactNode 추가
design-system/ui/buttons/TertiaryButton.tsx small 사이즈의 폰트 크기를 text-11에서 text-10으로 변경
src/entities/event/api/event.ts 삭제 함수명 deleteEventeventDeletion으로 변경, 타입 명시 제거, 내부 타입 추론 사용
src/entities/event/hook/useEventHook.ts useEventDeletion 훅 추가, useEventDetail을 named export로 변경, import 경로 정비
src/entities/event/hook/useEventListHook.ts
src/features/event/ui/EventList.tsx
src/features/home/hooks/useEventHook.ts
이벤트 관련 API import 경로를 eventDetail에서 event로 변경
src/features/event/ui/EventFunnel.tsx EventInfo 스텝의 레이아웃에 requireValidation={true} prop 추가
src/features/event/ui/FileUpload.tsx onValidationChange 콜백 prop 추가, 이미지 유효성 변경시 외부로 알림
src/pages/dashboard/ui/EventDetailPage.tsx
src/pages/dashboard/ui/EventInfoPage.tsx
src/pages/event/ui/EventDetailsPage.tsx
useEventDetail 훅 import 방식 및 위치 정비 (default → named import 등)
src/pages/event/ui/create-event/EventInfoPage.tsx onValidationChange prop 추가 및 전달, 인터페이스와 시그니처 수정
src/pages/menu/ui/myHost/MyHostPage.tsx 삭제 모드 토글 버튼 및 삭제된 이벤트 카드 즉시 제거 로직 추가, 상태 관리 개선
src/shared/ui/EventCard.tsx isDelete, onDeleteSuccess prop 추가, 삭제 아이콘 및 확인 모달 연동, 삭제 성공시 콜백 호출
src/shared/ui/backgrounds/DashboardLayout.tsx 현재 경로에 따라 홈 버튼(이미지) 또는 뒤로가기 문자열 렌더링, 이동 로직 분기
src/shared/ui/backgrounds/TicketHostLayout.tsx 헤더에 홈 이동 아이콘 버튼 추가, 레이아웃 및 텍스트 사이즈 조정
src/widgets/host/DeleteConfirmModal.tsx 삭제 확인 모달 신규 컴포넌트 추가, 취소/삭제 버튼 및 안내 문구 포함

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MyHostPage
    participant EventCard
    participant DeleteConfirmModal
    participant useEventDeletion(API)
    User->>MyHostPage: "삭제" 버튼 클릭(삭제 모드 진입)
    MyHostPage->>EventCard: isDelete=true로 렌더링
    User->>EventCard: 삭제 아이콘 클릭
    EventCard->>DeleteConfirmModal: 모달 오픈
    User->>DeleteConfirmModal: "삭제" 버튼 클릭
    DeleteConfirmModal->>EventCard: onConfirm 호출
    EventCard->>useEventDeletion: mutate(eventId)
    useEventDeletion-->>EventCard: 삭제 성공 콜백
    EventCard->>MyHostPage: onDeleteSuccess(eventId)
    MyHostPage->>MyHostPage: deletedEventIds에 추가, UI에서 카드 제거
Loading

Suggested reviewers

  • hyeeuncho

Poem

🐇
삭제 버튼이 깡총깡총,
이벤트 카드가 사라져요!
확인 모달로 한 번 더,
실수 방지 잊지 마요.
새 훅과 콜백이 힘을 합쳐,
깔끔한 관리, 토끼도 감탄!
🗑️✨


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 144bd35 and e09bb88.

📒 Files selected for processing (2)
  • src/pages/menu/ui/myHost/MyHostPage.tsx (2 hunks)
  • src/shared/ui/EventCard.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/menu/ui/myHost/MyHostPage.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/shared/ui/EventCard.tsx (1)
src/entities/event/hook/useEventHook.ts (1)
  • useEventDeletion (22-28)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: storybook
🔇 Additional comments (3)
src/shared/ui/EventCard.tsx (3)

7-11: Import 구문이 올바르게 추가되었습니다.

삭제 기능에 필요한 모든 컴포넌트와 훅들이 적절한 경로에서 import되었습니다.


24-25: 인터페이스 변경사항이 적절합니다.

새로운 props들이 옵셔널로 정의되어 기존 컴포넌트 사용에 영향을 주지 않으며, 타입 정의가 명확합니다.


39-40: Props 처리 및 상태 관리가 적절합니다.

기본값 설정과 훅 사용이 올바르게 구현되었으며, 모달 상태 관리도 적절합니다.

Also applies to: 44-45

✨ Finishing Touches
  • 📝 Generate Docstrings

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 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.

@github-actions
Copy link
Copy Markdown

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

🧹 Nitpick comments (4)
src/features/event/ui/FileUpload.tsx (1)

24-28: useEffect를 통한 validation 콜백 구현이 올바릅니다.

previewUrl 변경 시 부모 컴포넌트에 validation 상태를 알리는 로직이 적절하게 구현되었습니다.

성능 최적화를 위해 dependency array에서 onValidationChange를 제거하는 것을 고려해보세요:

  useEffect(() => {
    if (onValidationChange) {
      onValidationChange(!!previewUrl);
    }
-  }, [previewUrl, onValidationChange]);
+  }, [previewUrl]);

onValidationChange는 보통 부모 컴포넌트에서 안정적인 함수 참조로 제공되지만, dependency에서 제거하면 불필요한 재실행을 방지할 수 있습니다.

src/entities/event/hook/useEventHook.ts (1)

22-28: 이벤트 삭제 훅이 잘 구현되었습니다!

React Query의 useMutation 패턴을 올바르게 따르고 있으며, 타입 정의도 적절합니다.

추가 제안: 에러 처리나 성공 후 캐시 무효화를 위해 onSuccessonError 옵션을 고려해보세요.

예시:

 export const useEventDeletion = () => {
-  return useMutation<ApiResponse<null>, Error, number>({
+  const queryClient = useQueryClient();
+  return useMutation<ApiResponse<null>, Error, number>({
     mutationFn: async (eventId: number) => {
       return await eventDeletion(eventId);
     },
+    onSuccess: (_, eventId) => {
+      // 이벤트 목록과 상세 정보 캐시 무효화
+      queryClient.invalidateQueries({ queryKey: ['eventList'] });
+      queryClient.invalidateQueries({ queryKey: ['eventDetail', eventId] });
+    },
   });
 };
src/widgets/host/DeleteConfirmModal.tsx (1)

9-27: 모달 UX 및 접근성 개선을 고려해보세요.

현재 구현은 기본적인 기능을 제공하지만, 다음과 같은 개선사항을 추가하면 더 나은 사용자 경험을 제공할 수 있습니다:

  1. ESC 키로 모달 닫기
  2. 모달 외부 클릭 시 닫기
  3. 접근성 속성 추가 (role, aria-label 등)
  4. 모달이 열릴 때 body 스크롤 방지

다음과 같이 개선할 수 있습니다:

+import { useEffect } from 'react';
 import TertiaryButton from '../../../design-system/ui/buttons/TertiaryButton';

 const DeleteConfirmModal = ({ isOpen, onClose, onConfirm }: DeleteConfirmModalProps) => {
+  useEffect(() => {
+    if (isOpen) {
+      const handleEsc = (e: KeyboardEvent) => {
+        if (e.key === 'Escape') onClose();
+      };
+      document.addEventListener('keydown', handleEsc);
+      document.body.style.overflow = 'hidden';
+
+      return () => {
+        document.removeEventListener('keydown', handleEsc);
+        document.body.style.overflow = '';
+      };
+    }
+  }, [isOpen, onClose]);

   if (!isOpen) return null;

   return (
-    <div className="fixed inset-0 w-full max-w-lg z-50 flex items-center justify-center mx-auto bg-black bg-opacity-60">
-      <div className="bg-white rounded-lg p-6 w-[90%] max-w-md shadow-lg">
+    <div 
+      className="fixed inset-0 w-full max-w-lg z-50 flex items-center justify-center mx-auto bg-black bg-opacity-60"
+      onClick={onClose}
+      role="dialog"
+      aria-modal="true"
+      aria-labelledby="delete-modal-title"
+    >
+      <div 
+        className="bg-white rounded-lg p-6 w-[90%] max-w-md shadow-lg"
+        onClick={(e) => e.stopPropagation()}
+      >
-        <h2 className="text-base md:text-lg font-semibold text-black mb-3">이벤트를 삭제하시겠습니까?</h2>
+        <h2 id="delete-modal-title" className="text-base md:text-lg font-semibold text-black mb-3">이벤트를 삭제하시겠습니까?</h2>
src/shared/ui/EventCard.tsx (1)

119-134: 모달 렌더링 최적화를 고려하세요.

각 EventCard 내부에 DeleteConfirmModal을 렌더링하는 것은 카드가 많을 때 비효율적일 수 있습니다.

모달을 상위 컴포넌트로 이동하고 필요한 정보만 전달하는 방식을 고려해보세요. 또한 에러 처리에 alert 대신 토스트 알림을 사용하면 더 나은 UX를 제공할 수 있습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between dd233a7 and 144bd35.

⛔ Files ignored due to path filters (2)
  • public/assets/menu/Delete.svg is excluded by !**/*.svg
  • public/assets/menu/HomeButton.svg is excluded by !**/*.svg
📒 Files selected for processing (18)
  • design-system/ui/Header.tsx (2 hunks)
  • design-system/ui/buttons/TertiaryButton.tsx (1 hunks)
  • src/entities/event/api/event.ts (1 hunks)
  • src/entities/event/hook/useEventHook.ts (2 hunks)
  • src/entities/event/hook/useEventListHook.ts (1 hunks)
  • src/features/event/ui/EventFunnel.tsx (1 hunks)
  • src/features/event/ui/EventList.tsx (1 hunks)
  • src/features/event/ui/FileUpload.tsx (2 hunks)
  • src/features/home/hooks/useEventHook.ts (1 hunks)
  • src/pages/dashboard/ui/EventDetailPage.tsx (1 hunks)
  • src/pages/dashboard/ui/EventInfoPage.tsx (1 hunks)
  • src/pages/event/ui/EventDetailsPage.tsx (1 hunks)
  • src/pages/event/ui/create-event/EventInfoPage.tsx (1 hunks)
  • src/pages/menu/ui/myHost/MyHostPage.tsx (2 hunks)
  • src/shared/ui/EventCard.tsx (4 hunks)
  • src/shared/ui/backgrounds/DashboardLayout.tsx (3 hunks)
  • src/shared/ui/backgrounds/TicketHostLayout.tsx (3 hunks)
  • src/widgets/host/DeleteConfirmModal.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: storybook
🔇 Additional comments (24)
design-system/ui/buttons/TertiaryButton.tsx (1)

14-14: 폰트 크기 변경의 의도를 확인해주세요.

small 사이즈에서 text-11text-10으로 변경하셨는데, 이벤트 삭제 기능과 관련해서 폰트 크기를 줄일 특별한 이유가 있는지 확인이 필요합니다. 디자인 시스템의 일관성을 위해 다른 버튼 컴포넌트들과 동일한 기준을 적용하고 있는지 검토해주세요.

src/entities/event/hook/useEventListHook.ts (1)

3-3:

Details

✅ Verification successful

import 경로 변경이 올바른지 확인해주세요.

getAllEventsInfinite 함수의 import 경로가 '../api/eventDetail'에서 '../api/event'로 변경되었습니다. 이 변경이 API 모듈 재구성의 일부인지 확인하고, 새 경로에서 함수가 정상적으로 export되고 있는지 검증이 필요합니다.

다음 스크립트로 함수의 존재 여부를 확인해보겠습니다:


🏁 Script executed:

#!/bin/bash
# getAllEventsInfinite 함수가 새 경로에 올바르게 존재하는지 확인
echo "=== event.ts 파일에서 getAllEventsInfinite 함수 확인 ==="
rg -A 5 "export.*getAllEventsInfinite" src/entities/event/api/event.ts

echo "=== useEventListHook에서 사용되는 함수 확인 ==="
rg -A 2 -B 2 "getAllEventsInfinite" src/entities/event/hook/useEventListHook.ts

Length of output: 988


import 경로 및 함수 존재 확인 완료

  • src/entities/event/api/event.ts에서 getAllEventsInfinite가 정상적으로 export되고 있습니다.
  • useEventListHook.ts에서 올바른 경로(../api/event)로 import되고 있습니다.

해당 변경사항은 정확하므로 추가 검증이나 수정이 필요 없습니다.

design-system/ui/Header.tsx (1)

1-1:

Details

✅ Verification successful

타입 변경으로 인한 호환성을 검증해주세요.

leftButtonLabel의 타입을 string에서 ReactNode로 변경하여 더 유연한 콘텐츠를 지원할 수 있게 되었습니다. 하지만 이 변경이 기존 사용처들과 호환되는지, 그리고 TextButton 컴포넌트가 ReactNode 타입의 label을 올바르게 처리할 수 있는지 확인이 필요합니다.

다음 스크립트로 호환성을 확인해보겠습니다:

Also applies to: 10-10


🏁 Script executed:

#!/bin/bash
# TextButton 컴포넌트의 label prop 타입 확인
echo "=== TextButton 컴포넌트의 label prop 타입 확인 ==="
rg -A 10 "interface.*Props" design-system/ui/buttons/TextButton.tsx

echo "=== Header 컴포넌트 사용처에서 leftButtonLabel 사용 현황 ==="
rg -B 3 -A 3 "leftButtonLabel" --type tsx --type ts

Length of output: 655


🏁 Script executed:

#!/bin/bash
# TextButton 컴포넌트의 label Prop 타입 재확인
echo "=== TextButton 컴포넌트의 label Prop 타입 확인 ==="
rg -A 10 "interface TextButtonProps" design-system/ui/buttons/TextButton.tsx

# leftButtonLabel 사용처 탐색
echo "=== 전체 코드베이스에서 leftButtonLabel 사용처 검색 ==="
rg -n "leftButtonLabel" .

Length of output: 2748


leftButtonLabel 타입 변경 호환성 확인 완료

TextButton 컴포넌트의 label Prop이 ReactNode로 정의되어 있어, 문자열뿐 아니라 JSX 요소(예: <img />)도 모두 올바르게 처리합니다. 전체 코드베이스에서 leftButtonLabel에 문자열과 ReactNode가 혼용된 사용 사례를 검토한 결과, 호환성 문제가 없음을 확인했습니다.

  • TextButtonProps.label: ReactNode로 선언 (string, JSX 등 모두 허용)
  • 기존 사용처: 문자열("<" 등) 및 JSX(<img src=… />) 모두 정상 렌더링 확인

해당 타입 변경에 따른 추가 조치는 필요하지 않습니다.

src/features/event/ui/EventList.tsx (1)

3-3:

Details

✅ Verification successful

API 함수들의 import 경로 변경이 적절합니다.

getAllEventsInfinitegetCategoryEventsInfinite 함수들을 eventDetail 모듈에서 event 모듈로 이동한 것은 API 함수들을 통합하는 리팩토링으로 보입니다.

다른 파일들에서도 동일한 함수들의 import 경로가 일관성 있게 업데이트되었는지 확인해보겠습니다:


🏁 Script executed:

#!/bin/bash
# Description: 코드베이스에서 getAllEventsInfinite와 getCategoryEventsInfinite 함수의 import 경로 확인

echo "=== getAllEventsInfinite 함수 import 확인 ==="
rg -A 2 -B 2 "getAllEventsInfinite"

echo "=== getCategoryEventsInfinite 함수 import 확인 ==="
rg -A 2 -B 2 "getCategoryEventsInfinite"

echo "=== 기존 eventDetail 모듈에서의 import 잔재 확인 ==="
rg "from.*eventDetail.*event"

Length of output: 3563


✔️ API 함수 import 경로 통합 확인 완료

  • getAllEventsInfinitegetCategoryEventsInfinitesrc/entities/event/api/event.ts에서 정상적으로 export됨
  • EventList.tsxuseEventListHook.ts에서 모두 일관되게 새 경로(../api/event)를 사용
  • eventDetail 모듈 관련 잔여 import 없음

해당 리팩토링을 승인합니다.

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

20-20: useEventDetail 훅의 import 경로 정리가 적절합니다.

다른 파일들과 일관성 있게 훅의 import 경로가 정리되어 모듈 구조가 개선되었습니다.

src/pages/dashboard/ui/EventInfoPage.tsx (1)

13-13: import 경로 정리가 일관성 있게 적용되었습니다.

다른 파일들과 동일한 패턴으로 useEventDetail 훅의 import 경로가 정리되어 코드베이스의 일관성이 향상되었습니다.

src/features/event/ui/FileUpload.tsx (2)

4-4: useEffect import 추가가 적절합니다.

새로운 validation 콜백 기능을 위해 필요한 import입니다.


11-11: validation 콜백 prop 추가가 잘 설계되었습니다.

onValidationChange prop을 선택적으로 추가하여 기존 컴포넌트와의 호환성을 유지하면서도 새로운 기능을 제공합니다.

src/pages/event/ui/create-event/EventInfoPage.tsx (3)

6-8: 검증 콜백 인터페이스 추가 승인

검증 상태 변경을 외부로 알릴 수 있는 선택적 콜백 prop이 적절히 추가되었습니다. TypeScript 타입 정의도 명확합니다.


10-10: 함수 시그니처 업데이트 승인

새로운 prop을 구조분해할당으로 받도록 함수 시그니처가 올바르게 업데이트되었습니다.


14-14:

Details

✅ Verification successful

검증 콜백 전파 확인

FileUpload 컴포넌트에 onValidationChange 콜백이 올바르게 전달되었습니다. 이를 통해 검증 상태를 상위 컴포넌트로 전파할 수 있습니다.

FileUpload 컴포넌트가 이 콜백을 올바르게 처리하는지 확인해주세요:


🏁 Script executed:

#!/bin/bash
# FileUpload 컴포넌트에서 onValidationChange prop 사용 확인
ast-grep --pattern $'interface $_Props {
  $$$
  onValidationChange?: (isValid: boolean) => void;
  $$$
}'

# FileUpload 컴포넌트에서 콜백 호출 확인
rg -A 5 "onValidationChange" --type tsx

Length of output: 175


추가 검증을 위해 FileUpload 컴포넌트 파일 위치를 찾고, onValidationChange prop 정의 및 호출 여부를 확인하는 스크립트를 실행해주세요.


🏁 Script executed:

#!/bin/bash
# 1. FileUpload 컴포넌트가 정의된 .tsx 파일 찾기
rg -l "FileUpload" -g '*.tsx'

# 2. 찾은 파일들에서 Props 인터페이스에 onValidationChange 정의 확인
rg -C3 "interface .*Props" -g '*.tsx' | sed -n '1,20p'
rg -C3 "onValidationChange" -g '*.tsx'

# 3. FileUpload 내부에서 콜백이 실제로 호출되는지 확인
rg -C5 "onValidationChange" -g '*.tsx'

Length of output: 24592


검증 콜백 전파 확인 완료

src/features/event/ui/FileUpload.tsx에서

  • FileUploadPropsonValidationChange?: (isValid: boolean) => void가 정의되어 있으며
  • useEffect 훅에서 previewUrl 변경 시 onValidationChange(!!previewUrl)를 호출하도록 구현되어 있습니다.

따라서 상위 컴포넌트로 검증 상태가 정상 전파됩니다.

src/features/home/hooks/useEventHook.ts (1)

2-2:

Details

✅ Verification successful

Import 경로 리팩토링 승인 및 검증 요청

getEventByTag 함수의 import 경로가 eventDetail에서 event 모듈로 변경되었습니다. 이는 API 모듈 구조 개선의 일환으로 보입니다.

다른 파일들과의 일관성과 새 경로의 유효성을 확인해주세요:


🏁 Script executed:

#!/bin/bash
# getEventByTag 함수가 새 경로에 존재하는지 확인
ast-grep --pattern $'export $_ getEventByTag'

# 다른 파일들에서 eventDetail에서 event로의 import 경로 변경 확인
rg "from.*event/api/event" --type ts --type tsx
rg "from.*event/api/eventDetail" --type ts --type tsx

Length of output: 208


아래 스크립트를 실행해 getEventByTag의 새 경로 존재 여부와 전체 import 일관성을 다시 확인해주세요:


🏁 Script executed:

#!/bin/bash
# 1) getEventByTag 함수가 새 모듈에서 올바르게 export 되었는지 확인
grep -R "export .*getEventByTag" -n src/entities/event/api/event*

# 2) 코드베이스 전반에서 event 모듈 import 현황 확인
grep -R "entities/event/api/event" -n src
grep -R "entities/event/api/eventDetail" -n src

Length of output: 521


Import 경로 리팩토링 승인 및 일관성 확인 완료

  • src/entities/event/api/event.ts에서 getEventByTag가 정상적으로 export됨(59번째 줄).
  • useEventHook.tsEventList.tsx에서 ../../../entities/event/api/event로 import가 적용되었으며, 더 이상 eventDetail 경로를 참조하는 import가 없습니다.

이상 없습니다.

src/shared/ui/backgrounds/DashboardLayout.tsx (5)

1-2: Import 구문 정리 승인

중복된 useState import가 제거되고 useLocation 훅이 추가되었습니다. Import 구문이 깔끔하게 정리되었습니다.


6-6: 홈 버튼 이미지 Import 추가

조건부 버튼 표시를 위한 홈 버튼 이미지가 적절히 import되었습니다.


21-27: 조건부 네비게이션 로직 승인

홈 페이지에서는 루트('/')로, 다른 페이지에서는 이전 페이지(-1)로 이동하는 로직이 명확하고 직관적입니다.


42-42: 조건부 버튼 표시 구현

라우트에 따라 홈 버튼 이미지 또는 '<' 텍스트를 표시하는 로직이 적절히 구현되었습니다.


16-19:

Details

✅ Verification successful

라우트 기반 조건부 로직 구현

현재 경로를 확인하여 대시보드 홈 여부를 판단하는 로직이 잘 구현되었습니다.

정규식 패턴이 의도한 라우트를 정확히 매칭하는지 확인해주세요:


🏁 Script executed:

#!/bin/bash
# 대시보드 관련 라우트 패턴 확인
rg "/dashboard/" --type ts --type tsx -A 2 -B 2

# 라우팅 설정에서 대시보드 경로 확인
fd "route" --type f | xargs rg "dashboard" -A 3 -B 3

Length of output: 5344


정규식 패턴 검증 완료: 대시보드 홈(/dashboard/:id)만 정확히 매칭합니다
라우팅 설정(src/app/routes/routes.ts, Router.tsx)상 /dashboard/:id 외에는 동일한 수준의 경로가 없으므로,

const home = /^\/dashboard\/[^/]+$/.test(location.pathname);

은 의도한 대로 첫 번째 레벨 대시보드 홈 경로만 일치시킵니다. 추가 검증 및 수정이 필요하지 않습니다.

src/features/event/ui/EventFunnel.tsx (1)

101-101: EventInfo 단계 검증 요구사항 추가 승인

EventInfo 단계에 requireValidation={true}가 추가되어 다른 정보 입력 단계들과 일관성이 맞춰졌습니다. 이벤트 정보 입력은 필수 검증이 필요한 단계이므로 적절한 변경입니다.

src/entities/event/hook/useEventHook.ts (2)

1-5: Import 변경사항이 적절합니다!

새로운 이벤트 삭제 기능을 위한 useMutationApiResponse 타입이 올바르게 추가되었고, API 모듈 리팩토링에 따른 import 경로 변경도 일관성 있게 적용되었습니다.


7-7:

Details

✅ Verification successful

Export 방식 변경에 대한 확인이 필요합니다.

useEventDetail이 default export에서 named export로 변경되었습니다. 이는 breaking change이므로 모든 사용처가 업데이트되었는지 확인이 필요합니다.

다음 스크립트를 실행하여 모든 사용처가 업데이트되었는지 확인하세요:


🏁 Script executed:

#!/bin/bash
# Description: useEventDetail의 모든 import가 named import로 변경되었는지 확인

# Test: default import 사용 검색. 기대값: 결과 없음
rg -A 2 "import\s+useEventDetail\s+from.*useEventHook"

# Test: named import 사용 검색. 기대값: 모든 사용처가 표시됨
rg -A 2 "import\s+\{.*useEventDetail.*\}\s+from.*useEventHook"

Length of output: 825


useEventDetail 명명형(named) export 적용 완료 확인

default import 구문이 더 이상 존재하지 않음
– 모든 사용처가 아래와 같이 import { useEventDetail } from '…/useEventHook'로 업데이트됨
• src/pages/dashboard/ui/EventInfoPage.tsx
• src/pages/dashboard/ui/EventDetailPage.tsx
• src/pages/event/ui/EventDetailsPage.tsx

src/shared/ui/backgrounds/TicketHostLayout.tsx (1)

3-4: UI 개선사항이 잘 적용되었습니다!

홈 버튼 추가로 사용자 네비게이션이 개선되었고, 반응형 텍스트 크기 조정으로 모바일 사용성이 향상되었습니다. w-full 클래스 추가도 적절합니다.

Also applies to: 20-20, 27-33, 54-54

src/pages/dashboard/ui/EventDetailPage.tsx (1)

11-11: Import 구문이 올바르게 수정되었습니다!

useEventDetail의 export 방식 변경에 맞춰 import 구문이 적절히 업데이트되었습니다.

src/pages/menu/ui/myHost/MyHostPage.tsx (2)

42-52: 삭제 버튼의 조건부 렌더링이 적절합니다.

이벤트가 있을 때만 삭제 버튼을 표시하는 것은 좋은 UX 결정입니다.


57-58: 삭제된 이벤트의 로컬 필터링 동작을 확인하세요.

현재 구현은 삭제된 이벤트를 로컬 상태로만 관리하여 UI에서 숨깁니다. 페이지 새로고침 시 삭제된 이벤트가 다시 나타날 수 있습니다.

이것이 의도된 동작인지 확인하고, 필요하다면 삭제 성공 후 서버에서 데이터를 다시 가져오는 것을 고려해보세요.

Comment on lines +76 to 79
export const eventDeletion = async (eventId: number) => {
const response = await axiosClient.delete(`/events/${eventId}`);
return response.data;
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

함수 리팩토링의 일관성과 타입 안전성을 검토해주세요.

이벤트 삭제 함수가 deleteEvent에서 eventDeletion으로 이름이 변경되고, 타입 어노테이션이 제거되었습니다. 몇 가지 확인이 필요합니다:

  1. 명명 일관성: 다른 API 함수들과 네이밍 컨벤션이 일치하는지 확인
  2. 타입 안전성: 명시적인 반환 타입 제거로 인한 타입 추론 문제 가능성
  3. 사용처 업데이트: 이 함수를 사용하는 모든 곳에서 새 함수명으로 업데이트되었는지 확인

다음 스크립트로 함수 사용처와 일관성을 확인해보겠습니다:

타입 안전성을 위해 명시적인 반환 타입을 유지하는 것을 권장합니다:

-export const eventDeletion = async (eventId: number) => {
-  const response = await axiosClient.delete(`/events/${eventId}`);
+export const eventDeletion = async (eventId: number): Promise<ApiResponse<string>> => {
+  const response = await axiosClient.delete<ApiResponse<string>>(`/events/${eventId}`);
   return response.data;
 };

🏁 Script executed:

#!/bin/bash
# 기존 deleteEvent 함수 사용처가 남아있는지 확인
echo "=== 기존 deleteEvent 함수 사용처 확인 ==="
rg -i "deleteEvent" --type ts --type tsx

echo "=== 새로운 eventDeletion 함수 사용처 확인 ==="
rg -i "eventDeletion" --type ts --type tsx

echo "=== API 함수들의 네이밍 패턴 확인 ==="
rg -A 1 "export const.*=" src/entities/event/api/event.ts

Length of output: 1097


API 함수 eventDeletion에 명시적 반환 타입 및 제네릭 타입 추가 필요

src/entities/event/api/event.ts 내 다른 API 함수들과 비교했을 때, 반환 타입 어노테이션과 axiosClient.delete 제네릭 타입이 빠져 있어 타입 안전성이 떨어집니다.

확인 및 조치 사항:

  • 반환 타입을 명시적으로 선언 (Promise<ApiResponse<…>>)
  • axiosClient.delete<…> 제네릭 타입을 추가
  • 이 함수를 호출하는 모든 곳이 eventDeletion으로 변경되었는지 재검토

예시 변경안:

-export const eventDeletion = async (eventId: number) => {
-  const response = await axiosClient.delete(`/events/${eventId}`);
+export const eventDeletion = async (eventId: number): Promise<ApiResponse<void>> => {
+  const response = await axiosClient.delete<ApiResponse<void>>(`/events/${eventId}`);
   return response.data;
};

추가로, API 함수 네이밍 컨벤션을 일관되게 유지하고 싶다면

  • 동사+주체(예: deleteEvent, getEventDetail)
  • 또는 모두 noun+action(예: eventDeletion, eventDetail)
    중 하나로 통일하는 방안을 검토해주세요.
📝 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 eventDeletion = async (eventId: number) => {
const response = await axiosClient.delete(`/events/${eventId}`);
return response.data;
};
export const eventDeletion = async (eventId: number): Promise<ApiResponse<void>> => {
const response = await axiosClient.delete<ApiResponse<void>>(`/events/${eventId}`);
return response.data;
};
🤖 Prompt for AI Agents
In src/entities/event/api/event.ts around lines 76 to 79, the function
eventDeletion lacks explicit return type annotation and does not specify a
generic type for axiosClient.delete, which reduces type safety. Add a specific
return type, such as Promise<ApiResponse<YourType>>, and include the appropriate
generic type parameter in the delete call. Also, verify that all usage sites
have been updated to use eventDeletion instead of previous function names, and
consider standardizing the naming convention across API functions for
consistency.

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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 3

🧹 Nitpick comments (4)
src/features/event/ui/FileUpload.tsx (1)

24-28: useEffect를 통한 validation 콜백 구현이 올바릅니다.

previewUrl 변경 시 부모 컴포넌트에 validation 상태를 알리는 로직이 적절하게 구현되었습니다.

성능 최적화를 위해 dependency array에서 onValidationChange를 제거하는 것을 고려해보세요:

  useEffect(() => {
    if (onValidationChange) {
      onValidationChange(!!previewUrl);
    }
-  }, [previewUrl, onValidationChange]);
+  }, [previewUrl]);

onValidationChange는 보통 부모 컴포넌트에서 안정적인 함수 참조로 제공되지만, dependency에서 제거하면 불필요한 재실행을 방지할 수 있습니다.

src/entities/event/hook/useEventHook.ts (1)

22-28: 이벤트 삭제 훅이 잘 구현되었습니다!

React Query의 useMutation 패턴을 올바르게 따르고 있으며, 타입 정의도 적절합니다.

추가 제안: 에러 처리나 성공 후 캐시 무효화를 위해 onSuccessonError 옵션을 고려해보세요.

예시:

 export const useEventDeletion = () => {
-  return useMutation<ApiResponse<null>, Error, number>({
+  const queryClient = useQueryClient();
+  return useMutation<ApiResponse<null>, Error, number>({
     mutationFn: async (eventId: number) => {
       return await eventDeletion(eventId);
     },
+    onSuccess: (_, eventId) => {
+      // 이벤트 목록과 상세 정보 캐시 무효화
+      queryClient.invalidateQueries({ queryKey: ['eventList'] });
+      queryClient.invalidateQueries({ queryKey: ['eventDetail', eventId] });
+    },
   });
 };
src/widgets/host/DeleteConfirmModal.tsx (1)

9-27: 모달 UX 및 접근성 개선을 고려해보세요.

현재 구현은 기본적인 기능을 제공하지만, 다음과 같은 개선사항을 추가하면 더 나은 사용자 경험을 제공할 수 있습니다:

  1. ESC 키로 모달 닫기
  2. 모달 외부 클릭 시 닫기
  3. 접근성 속성 추가 (role, aria-label 등)
  4. 모달이 열릴 때 body 스크롤 방지

다음과 같이 개선할 수 있습니다:

+import { useEffect } from 'react';
 import TertiaryButton from '../../../design-system/ui/buttons/TertiaryButton';

 const DeleteConfirmModal = ({ isOpen, onClose, onConfirm }: DeleteConfirmModalProps) => {
+  useEffect(() => {
+    if (isOpen) {
+      const handleEsc = (e: KeyboardEvent) => {
+        if (e.key === 'Escape') onClose();
+      };
+      document.addEventListener('keydown', handleEsc);
+      document.body.style.overflow = 'hidden';
+
+      return () => {
+        document.removeEventListener('keydown', handleEsc);
+        document.body.style.overflow = '';
+      };
+    }
+  }, [isOpen, onClose]);

   if (!isOpen) return null;

   return (
-    <div className="fixed inset-0 w-full max-w-lg z-50 flex items-center justify-center mx-auto bg-black bg-opacity-60">
-      <div className="bg-white rounded-lg p-6 w-[90%] max-w-md shadow-lg">
+    <div 
+      className="fixed inset-0 w-full max-w-lg z-50 flex items-center justify-center mx-auto bg-black bg-opacity-60"
+      onClick={onClose}
+      role="dialog"
+      aria-modal="true"
+      aria-labelledby="delete-modal-title"
+    >
+      <div 
+        className="bg-white rounded-lg p-6 w-[90%] max-w-md shadow-lg"
+        onClick={(e) => e.stopPropagation()}
+      >
-        <h2 className="text-base md:text-lg font-semibold text-black mb-3">이벤트를 삭제하시겠습니까?</h2>
+        <h2 id="delete-modal-title" className="text-base md:text-lg font-semibold text-black mb-3">이벤트를 삭제하시겠습니까?</h2>
src/shared/ui/EventCard.tsx (1)

119-134: 모달 렌더링 최적화를 고려하세요.

각 EventCard 내부에 DeleteConfirmModal을 렌더링하는 것은 카드가 많을 때 비효율적일 수 있습니다.

모달을 상위 컴포넌트로 이동하고 필요한 정보만 전달하는 방식을 고려해보세요. 또한 에러 처리에 alert 대신 토스트 알림을 사용하면 더 나은 UX를 제공할 수 있습니다.

🛑 Comments failed to post (3)
src/entities/event/api/event.ts (1)

76-79: 💡 Verification agent

🧩 Analysis chain

함수 리팩토링의 일관성과 타입 안전성을 검토해주세요.

이벤트 삭제 함수가 deleteEvent에서 eventDeletion으로 이름이 변경되고, 타입 어노테이션이 제거되었습니다. 몇 가지 확인이 필요합니다:

  1. 명명 일관성: 다른 API 함수들과 네이밍 컨벤션이 일치하는지 확인
  2. 타입 안전성: 명시적인 반환 타입 제거로 인한 타입 추론 문제 가능성
  3. 사용처 업데이트: 이 함수를 사용하는 모든 곳에서 새 함수명으로 업데이트되었는지 확인

다음 스크립트로 함수 사용처와 일관성을 확인해보겠습니다:

타입 안전성을 위해 명시적인 반환 타입을 유지하는 것을 권장합니다:

-export const eventDeletion = async (eventId: number) => {
-  const response = await axiosClient.delete(`/events/${eventId}`);
+export const eventDeletion = async (eventId: number): Promise<ApiResponse<string>> => {
+  const response = await axiosClient.delete<ApiResponse<string>>(`/events/${eventId}`);
   return response.data;
 };

🏁 Script executed:

#!/bin/bash
# 기존 deleteEvent 함수 사용처가 남아있는지 확인
echo "=== 기존 deleteEvent 함수 사용처 확인 ==="
rg -i "deleteEvent" --type ts --type tsx

echo "=== 새로운 eventDeletion 함수 사용처 확인 ==="
rg -i "eventDeletion" --type ts --type tsx

echo "=== API 함수들의 네이밍 패턴 확인 ==="
rg -A 1 "export const.*=" src/entities/event/api/event.ts

Length of output: 1097


API 함수 eventDeletion에 명시적 반환 타입 및 제네릭 타입 추가 필요

src/entities/event/api/event.ts 내 다른 API 함수들과 비교했을 때, 반환 타입 어노테이션과 axiosClient.delete 제네릭 타입이 빠져 있어 타입 안전성이 떨어집니다.

확인 및 조치 사항:

  • 반환 타입을 명시적으로 선언 (Promise<ApiResponse<…>>)
  • axiosClient.delete<…> 제네릭 타입을 추가
  • 이 함수를 호출하는 모든 곳이 eventDeletion으로 변경되었는지 재검토

예시 변경안:

-export const eventDeletion = async (eventId: number) => {
-  const response = await axiosClient.delete(`/events/${eventId}`);
+export const eventDeletion = async (eventId: number): Promise<ApiResponse<void>> => {
+  const response = await axiosClient.delete<ApiResponse<void>>(`/events/${eventId}`);
   return response.data;
};

추가로, API 함수 네이밍 컨벤션을 일관되게 유지하고 싶다면

  • 동사+주체(예: deleteEvent, getEventDetail)
  • 또는 모두 noun+action(예: eventDeletion, eventDetail)
    중 하나로 통일하는 방안을 검토해주세요.
📝 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.

export const eventDeletion = async (eventId: number): Promise<ApiResponse<void>> => {
  const response = await axiosClient.delete<ApiResponse<void>>(`/events/${eventId}`);
  return response.data;
};
🤖 Prompt for AI Agents
In src/entities/event/api/event.ts around lines 76 to 79, the function
eventDeletion lacks explicit return type annotation and does not specify a
generic type for axiosClient.delete, which reduces type safety. Add a specific
return type, such as Promise<ApiResponse<YourType>>, and include the appropriate
generic type parameter in the delete call. Also, verify that all usage sites
have been updated to use eventDeletion instead of previous function names, and
consider standardizing the naming convention across API functions for
consistency.
src/pages/menu/ui/myHost/MyHostPage.tsx (1)

70-72: ⚠️ Potential issue

매개변수 이름을 단수형으로 수정하세요.

onDeleteSuccess 콜백의 매개변수 이름이 혼란을 야기할 수 있습니다. 실제로는 단일 ID를 받으므로 복수형 대신 단수형을 사용해야 합니다.

-onDeleteSuccess={(deletedEventIds: number) => {
-  setDeletedEventIds(prev => [...prev, deletedEventIds]);
+onDeleteSuccess={(deletedEventId: number) => {
+  setDeletedEventIds(prev => [...prev, deletedEventId]);
 }}
📝 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.

              onDeleteSuccess={(deletedEventId: number) => {
                setDeletedEventIds(prev => [...prev, deletedEventId]);
              }}
🤖 Prompt for AI Agents
In src/pages/menu/ui/myHost/MyHostPage.tsx around lines 70 to 72, the parameter
name 'deletedEventIds' suggests it is an array, but the comment indicates it
should be a single ID. Rename the parameter to a singular form, such as
'deletedEventId', to accurately reflect that it is a single value, and update
its usage accordingly.
src/shared/ui/EventCard.tsx (1)

114-114: ⚠️ Potential issue

삭제 버튼 클릭 시 이벤트 전파를 중지하세요.

삭제 버튼을 클릭할 때 카드의 onClick 이벤트가 실행되지 않도록 이벤트 전파를 중지해야 합니다.

 onClick={() => setIsModalOpen(true)}
+onClick={(e) => {
+  e.stopPropagation();
+  setIsModalOpen(true);
+}}

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

🤖 Prompt for AI Agents
In src/shared/ui/EventCard.tsx at line 114, the onClick handler opens a modal
but does not prevent event propagation when clicking the delete button. To fix
this, add an event parameter to the delete button's onClick handler and call
event.stopPropagation() within it to prevent the click from bubbling up and
triggering the card's onClick event.

@github-actions
Copy link
Copy Markdown

Copy link
Copy Markdown
Member

@hyeeuncho hyeeuncho left a comment

Choose a reason for hiding this comment

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

수고하셨습니다

@Yejiin21 Yejiin21 merged commit b85c540 into develop May 27, 2025
2 checks passed
@Yejiin21 Yejiin21 deleted the feat/#144/event-delete branch May 27, 2025 05:08
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] 이벤트 삭제 구현

2 participants