Skip to content

Conversation

@yuj2n
Copy link
Contributor

@yuj2n yuj2n commented Jun 21, 2025

📌 변경 사항 개요

대시보드 수정 페이지 API 연동

✨ 요약

대시보드 수정 페이지 API 연동

📝 상세 내용

🫧modify:

  • 함수명 네이밍 컨벤션 일치
  • 매직 넘버명 구체화
  • 미사용 토스트 구현 삭제
  • 이전 멤버 컴포넌트 수정
  • pathname 미사용 및 cn 적용
  • 활성화된 경우 폰트 굵기 적용한 부분 삭제
  • 돌아가기 버튼 사이즈 수정
  • 조건부 스타일링 삭제에도 cn 사용 이유 주석 추가
  • 모달타입 수정 적용
  • 이메일 초대 토스트 적용
  • 헤더 버튼 다크모드 반영을 위한 색 추가
  • getColor 커스텀 훅 적용

✨feat:

  • 대시보드 이름 및 색상 변경 폼 공용화
  • 페이지네이션 커스텀 훅 구현
  • 페이지네이션 컴포넌트 작성
  • 페이지네이션 훅 및 컴포넌트 적용
  • useMutation 적용으로 수동 setState 간소화하여 자동 상태 관리
  • 초대 후 초대 내역 새로고침을 위한 캐시 무효화 구현
  • 초대 내역 불러오기 API 구현 및 툴팁 표시 구현
  • 대시보드 멤버 목록 가져오는 훅 구현
  • 대시보드 구성원 수정 컴포넌트 구현
  • 로그인된 사용자 및 공동 사용자 정보를 가져오기 위한 데이터 반영
  • 공동 작업자 프로필 api 적용 및 수정
  • 로그인된 사용자 정보 불러오기 및 로그아웃 시 로그인 화면으로 이동

🎨style:

  • 동일 이미지 삭제 및 반영

🐛fix: 사이드바에 대시보드 명 적용안되던 문제 캐시 무효화 및 페이지 강제 갱신으로 해결

🔗 관련 이슈

🖼️ 스크린샷

  • 대시보드 생성자
20250622_081151.mp4
  • 대시보드 멤버
20250622_080834.mp4

✅ 체크리스트

  • 브랜치 네이밍 컨벤션을 준수했습니다
  • 커밋 컨벤션을 준수했습니다
  • 코드가 프로젝트의 스타일 가이드라인을 준수합니다

💡 참고 사항

  • createDashboardModal과 EditInfo의 경우 동일하게 대시보드 이름 및 색상 변경 폼을 불러오기 때문에 api 부분을 useDashboardFrom으로 옮겨서 공통 부분과 각 컴포넌트에서 사용하는 부분을 사용할 수 있도록 작성하였습니다

Summary by CodeRabbit

Summary by CodeRabbit

  • 신규 기능

    • 대시보드 생성/수정 폼을 위한 재사용 가능한 컴포넌트와 커스텀 훅이 추가되었습니다.
    • 멤버, 초대 목록 등에서 동적 데이터 페칭 및 페이지네이션 기능이 도입되었습니다.
    • 초대, 멤버 관리 등에서 API 연동 및 React Query 기반 상태 관리가 적용되었습니다.
    • 대시보드 삭제 시 토스트 기반 확인 및 상태 관리가 개선되었습니다.
    • 페이지네이션 헤더 컴포넌트가 새로 추가되어 UI가 간결해졌습니다.
    • 사용자 아바타 컴포넌트가 닉네임과 프로필 이미지 URL을 직접 받아 렌더링하도록 변경되었습니다.
    • 환경변수에서 팀 ID를 안전하게 가져오는 유틸 함수가 추가되었습니다.
  • 버그 수정

    • 멤버, 초대 목록 등에서 잘못된 이미지 URL 및 닉네임 처리 로직이 개선되었습니다.
    • 권한 오류 및 데이터 로딩 실패 시 명확한 에러 메시지가 표시되도록 개선되었습니다.
  • 리팩터

    • 여러 컴포넌트에서 내부 상태 관리 및 API 호출 로직이 커스텀 훅과 공통 컴포넌트로 분리되어 코드가 간결해졌습니다.
    • 모달, 네비게이션 등에서 props 및 상태 관리 방식이 개선되었습니다.
    • 대시보드 편집 페이지와 관련 컴포넌트들이 불필요한 상태 및 API 호출을 제거하고 재사용 컴포넌트로 대체되었습니다.
    • 글로벌 상태 관리에서 모달 타입 초기값이 null에서 'none'으로 변경되었습니다.
    • 정적 mock 데이터가 삭제되고 실제 API 기반 데이터 페칭으로 전환되었습니다.
    • 네비게이션 아이템의 활성 상태 관련 props 및 로직이 제거되어 단순화되었습니다.
  • 스타일

    • 버튼, 폼, 네비게이션 등 UI 요소의 스타일 및 레이아웃이 일부 조정되었습니다.
    • 뒤로가기 버튼의 아이콘 크기 및 텍스트 폰트 크기가 조정되었습니다.
  • 문서화

    • 일부 컴포넌트와 훅에 타입 및 props 설명이 추가되었습니다.

yuj2n added 28 commits June 20, 2025 20:21
@yuj2n yuj2n added this to the 2차 구현 기간 milestone Jun 21, 2025
@yuj2n yuj2n requested a review from dkslel1225 June 21, 2025 16:26
@yuj2n yuj2n requested review from Insung-Jo and LeeCh0129 June 21, 2025 16:26
@yuj2n yuj2n self-assigned this Jun 21, 2025
@yuj2n yuj2n added ✨Feat 기능 개발 🐛Fix 버그 수정 💄Modify 자잘한 수정 labels Jun 21, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jun 21, 2025

"""

Walkthrough

이 변경사항은 대시보드 및 협업 관련 컴포넌트의 상태 관리와 데이터 흐름을 리팩토링하고, 여러 기능을 커스텀 훅과 재사용 가능한 컴포넌트로 분리하였습니다. 또한, 정적 목업 데이터를 동적 API 기반 데이터로 대체하고, 토스트 알림 및 스타일링 일부를 수정하였습니다.

Changes

파일/경로 그룹 변경 요약
src/app/dashboard/[id]/edit/page.tsx 토스트 알림 관련 코드와 핸들러 제거, 뒤로가기 버튼 스타일 수정
src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx 삭제 로직을 React Query useMutation으로 리팩토링, 상태 관리 단순화
src/app/features/dashboard/components/edit/EditInfo.tsx 내부 상태 및 API 호출 제거, useDashboardForm 훅과 DashboardForm 컴포넌트로 대체
src/app/features/dashboard/components/edit/EditInvitation.tsx, EditMember.tsx 목업 데이터 제거, React Query 기반 동적 데이터 및 뮤테이션 적용, 페이지네이션 로직 개선, UI 컴포넌트 개선
src/app/features/dashboard/components/edit/PaginationHeader.tsx 페이지네이션 헤더 컴포넌트 신규 추가
src/app/shared/components/common/Avatar.tsx getColor import 경로 변경, 렌더링 시 getInitial 직접 호출로 수정
src/app/shared/components/common/CollaboratorItem.tsx Avatar에 전달하는 이미지 prop 타입 확장 및 prop명 변경
src/app/shared/components/common/UserInfo.tsx nickname optional 처리 및 imageUrl prop 추가, 유저 정보 렌더링 로직 개선
src/app/shared/components/common/header/Collaborator/CollaboratorList.tsx 목업 대신 동적 멤버 데이터 fetch, prop 제거, 키 및 이미지 prop명 변경, 프로필 이미지 크기 축소
src/app/shared/components/common/header/NavItem.tsx, RightHeaderNav.tsx active prop 및 관련 로직 제거, 아이콘 경로 변경, 스타일 수정
src/app/shared/components/common/header/UserDropdown.tsx 로그아웃 후 이동 경로 변경, UserInfo에 nickname prop 제거
src/app/shared/components/common/modal/CreateDashboardModal.tsx 폼 로직을 useDashboardFormDashboardForm으로 위임, 내부 상태 제거
src/app/shared/components/common/modal/CreateInvitationModal.tsx 초대 후 React Query 캐시 무효화 추가, 모달 렌더 조건 명시적 변경, 함수 선언 방식 변경
src/app/shared/components/dashboard/DashboardForm.tsx 대시보드 생성/수정 폼 컴포넌트 신규 추가
src/app/shared/hooks/useDashboardForm.ts 대시보드 폼 상태 및 로직 관리 커스텀 훅 신규 추가
src/app/shared/hooks/useMembers.ts 멤버 데이터 fetch 훅 신규 추가 및 Member 타입 정의
src/app/shared/hooks/usePagination.ts 페이지네이션 관리 커스텀 훅 신규 추가
src/app/shared/store/useModalStore.ts 모달 상태의 초기값 및 닫기 동작을 'none' 문자열로 변경
src/app/features/dashboard/components/edit/mockMember.js 정적 목업 멤버 데이터 파일 삭제
src/app/shared/hooks/useDashboard.ts 일부 import 경로 수정

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant EditInvitation
  participant ReactQuery
  participant API

  User->>EditInvitation: 페이지 진입 및 초대 취소 요청
  EditInvitation->>ReactQuery: invitations 데이터 fetch 및 mutate 요청
  ReactQuery->>API: GET/DELETE /invitations API 호출
  API-->>ReactQuery: 응답 반환 (초대 목록 또는 삭제 결과)
  ReactQuery-->>EditInvitation: 상태 및 데이터 업데이트
  EditInvitation-->>User: UI 갱신 및 토스트 알림 표시
Loading
sequenceDiagram
  participant User
  participant DashboardForm
  participant useDashboardForm
  participant API
  participant ReactQuery
  participant Router

  User->>DashboardForm: 폼 입력 및 제출
  DashboardForm->>useDashboardForm: onChange, onSubmit 이벤트 전달
  useDashboardForm->>API: POST/PUT /dashboard API 호출
  API-->>useDashboardForm: 성공/실패 응답
  useDashboardForm->>ReactQuery: 캐시 무효화 요청
  useDashboardForm->>Router: 페이지 이동 및 새로고침
  useDashboardForm-->>DashboardForm: 상태 및 에러 전달
  DashboardForm-->>User: UI 갱신 및 알림 표시
Loading

Possibly related PRs

  • CoPlay-FE/coplan#63: 대시보드 수정 페이지에 토스트 알림 기능을 추가했던 PR로, 본 PR에서 해당 기능이 제거됨.
  • CoPlay-FE/coplan#85: 대시보드 수정 페이지의 네비게이션 및 삭제 버튼 관련 UI와 로직을 개선했던 PR로, 본 PR에서 동일 파일과 UI 영역이 추가로 변경됨.
  • CoPlay-FE/coplan#75: EditInfo 컴포넌트를 초기 구현한 PR로, 본 PR에서 해당 컴포넌트를 커스텀 훅과 재사용 컴포넌트로 리팩토링함.

Suggested labels

♻️Refactor, 🎨Style

Suggested reviewers

  • Insung-Jo
  • LeeCh0129

Poem

🐇
새싹처럼 자라난 훅과 폼,
목업은 안녕, API가 온다네.
협업의 이름, 동적으로 빛나고,
페이지네이션도 똑똑하게 변했지.
리팩토링 한 번에,
토스트는 사라지고,
토끼는 기쁘게 깡총깡총!

"""

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-21T20_28_36_205Z-debug-0.log


📜 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 ecebc70 and 0c78d1d.

📒 Files selected for processing (3)
  • src/app/shared/components/common/Avatar.tsx (2 hunks)
  • src/app/shared/components/common/CollaboratorItem.tsx (2 hunks)
  • src/app/shared/components/common/UserInfo.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/app/shared/components/common/Avatar.tsx
  • src/app/shared/components/common/CollaboratorItem.tsx
  • src/app/shared/components/common/UserInfo.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: eslint-check
✨ Finishing Touches
  • 📝 Generate Docstrings

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

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

🔭 Outside diff range comments (1)
src/app/shared/components/common/header/NavItem.tsx (1)

13-13: 사용되지 않는 active prop을 타입 정의에서 제거 필요

컴포넌트 로직에서 active prop이 더 이상 사용되지 않으므로 타입 정의에서도 제거해야 합니다.

type NavItemProps = {
  as?: 'link' | 'button'
  href?: string
  onClick?: () => void
  iconSrc: string
  label: string
-  active?: boolean
  className?: string
}
🧹 Nitpick comments (8)
src/app/features/dashboard/components/edit/PaginationHeader.tsx (2)

31-42: 이전 버튼의 접근성과 상태 처리를 개선해주세요.

버튼의 disabled 상태 처리는 올바르지만, 접근성을 위해 aria-disabled 속성과 시각적 피드백을 개선할 수 있습니다.

-        <button onClick={onPrev} disabled={currentPage === 1}>
+        <button 
+          onClick={onPrev} 
+          disabled={currentPage === 1}
+          aria-disabled={currentPage === 1}
+          className={currentPage === 1 ? 'cursor-not-allowed opacity-50' : 'hover:opacity-80'}
+        >

43-54: 다음 버튼도 동일한 접근성 개선이 필요합니다.

이전 버튼과 마찬가지로 접근성과 시각적 피드백을 개선해주세요.

-        <button onClick={onNext} disabled={currentPage === totalPages}>
+        <button 
+          onClick={onNext} 
+          disabled={currentPage === totalPages}
+          aria-disabled={currentPage === totalPages}
+          className={currentPage === totalPages ? 'cursor-not-allowed opacity-50' : 'hover:opacity-80'}
+        >
src/app/shared/components/dashboard/DashboardForm.tsx (1)

85-96: 폼 제출 버튼의 비활성화 로직을 개선해주세요.

현재 로직은 올바르지만, 코드 가독성을 위해 조건을 별도 변수로 분리하는 것을 제안합니다.

+  const isFormInvalid = !formData.title || !formData.color || isSubmitting
+
   <button
     type="submit"
-    disabled={!formData.title || !formData.color || isSubmitting}
-    className={`BG-violet h-48 ${submitButtonWidth} rounded-8 px-16 py-10 text-16 font-semibold text-white transition-opacity ${
-      !formData.title || !formData.color || isSubmitting
-        ? 'cursor-not-allowed opacity-50'
-        : 'hover:opacity-90'
-    }`}
+    disabled={isFormInvalid}
+    className={`BG-violet h-48 ${submitButtonWidth} rounded-8 px-16 py-10 text-16 font-semibold text-white transition-opacity ${
+      isFormInvalid
+        ? 'cursor-not-allowed opacity-50'
+        : 'hover:opacity-90'
+    }`}
   >
src/app/shared/components/common/UserInfo.tsx (1)

19-19: 빈 문자열 체크 로직을 강화해보세요.

현재 빈 문자열만 체크하고 있는데, 공백만 있는 문자열도 고려해볼 수 있습니다.

-  if (!displayNickname) return null // 사용자 정보가 없는 경우 렌더링하지 않음
+  if (!displayNickname || !displayNickname.trim()) return null // 사용자 정보가 없거나 공백만 있는 경우 렌더링하지 않음
src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx (1)

35-35: 사용자 경험을 위해 alert 대신 toast 알림 사용을 고려해보세요.

현재 alert을 사용하고 있는데, 다른 컴포넌트에서 사용하는 toast 알림과 일관성을 위해 변경을 제안합니다.

+import { showError } from '@/app/shared/lib/toast'

// onError 콜백에서
-        alert(message)
+        showError(message)
        
-        alert('알 수 없는 오류가 발생했습니다.')
+        showError('알 수 없는 오류가 발생했습니다.')

Also applies to: 39-39

src/app/features/dashboard/components/edit/EditMember.tsx (1)

99-99: 불필요한 nullish coalescing 연산자 사용

profileImageUrl이 null/undefined일 때 빈 문자열로 대체하고 있지만, UserInfo 컴포넌트가 null 값을 처리할 수 있다면 이는 불필요할 수 있습니다.

-imageUrl={member.profileImageUrl ?? ''}
+imageUrl={member.profileImageUrl}
src/app/shared/components/common/header/Collaborator/CollaboratorList.tsx (2)

51-51: 툴팁 내용이 혼란스러울 수 있습니다.

추가 인원 표시의 툴팁에서 첫 번째 협업자의 이름을 사용하는 것은 직관적이지 않습니다. 전체 협업자 목록이나 더 명확한 메시지를 표시하는 것이 좋습니다.

-content={`${visibleCollaborators[0].nickname} 외 ${extraCount}명`}
+content={`${extraCount}명의 추가 협업자`}

31-33: 주석이 코드와 일치하지 않습니다.

주석은 "프로필 이미지 및 닉네임만 필요한 경우"라고 되어 있지만, 실제로는 전체 멤버 객체를 슬라이싱하고 있습니다. 주석을 수정하거나 제거하세요.

-// 프로필 이미지 및 닉네임만 필요한 경우
+// 표시할 협업자 목록 (최대 4명)
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 945f7ad and d06b980.

⛔ Files ignored due to path filters (1)
  • public/images/management.png is excluded by !**/*.png
📒 Files selected for processing (20)
  • src/app/dashboard/[id]/edit/page.tsx (1 hunks)
  • src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx (2 hunks)
  • src/app/features/dashboard/components/edit/EditInfo.tsx (1 hunks)
  • src/app/features/dashboard/components/edit/EditInvitation.tsx (1 hunks)
  • src/app/features/dashboard/components/edit/EditMember.tsx (1 hunks)
  • src/app/features/dashboard/components/edit/PaginationHeader.tsx (1 hunks)
  • src/app/shared/components/common/Avatar.tsx (2 hunks)
  • src/app/shared/components/common/CollaboratorItem.tsx (1 hunks)
  • src/app/shared/components/common/UserInfo.tsx (1 hunks)
  • src/app/shared/components/common/header/Collaborator/CollaboratorList.tsx (1 hunks)
  • src/app/shared/components/common/header/NavItem.tsx (1 hunks)
  • src/app/shared/components/common/header/RightHeaderNav.tsx (1 hunks)
  • src/app/shared/components/common/header/UserDropdown.tsx (1 hunks)
  • src/app/shared/components/common/modal/CreateDashboardModal.tsx (1 hunks)
  • src/app/shared/components/common/modal/CreateInvitationModal.tsx (3 hunks)
  • src/app/shared/components/dashboard/DashboardForm.tsx (1 hunks)
  • src/app/shared/hooks/useDashboardForm.ts (1 hunks)
  • src/app/shared/hooks/useMembers.ts (1 hunks)
  • src/app/shared/hooks/usePagination.ts (1 hunks)
  • src/app/shared/store/useModalStore.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (12)
src/app/shared/components/common/CollaboratorItem.tsx (1)
src/app/shared/components/common/Avatar.tsx (1)
  • Avatar (31-68)
src/app/shared/components/common/header/UserDropdown.tsx (2)
src/app/shared/components/common/Dropdown/Dropdown.tsx (1)
  • Dropdown (14-140)
src/app/shared/components/common/UserInfo.tsx (1)
  • UserInfo (13-32)
src/app/shared/components/common/header/RightHeaderNav.tsx (3)
src/app/shared/store/useModalStore.ts (1)
  • useModalStore (6-10)
src/app/shared/store/useSelectedDashboardStore.ts (1)
  • useSelectedDashboardStore (10-15)
src/app/shared/components/common/header/NavItem.tsx (1)
  • NavItem (17-57)
src/app/shared/hooks/useDashboardForm.ts (3)
src/app/shared/store/useSelectedDashboardStore.ts (1)
  • useSelectedDashboardStore (10-15)
src/app/shared/types/dashboard.ts (1)
  • CreateDashboardRequest (31-34)
src/app/shared/constants/colors.ts (1)
  • DASHBOARD_COLORS (3-9)
src/app/shared/components/common/UserInfo.tsx (2)
src/app/features/auth/store/useAuthStore.ts (1)
  • useAuthStore (6-21)
src/app/shared/components/common/Avatar.tsx (1)
  • Avatar (31-68)
src/app/shared/components/common/Avatar.tsx (1)
src/app/shared/lib/getColor.ts (1)
  • getColor (1-5)
src/app/shared/components/common/modal/CreateInvitationModal.tsx (2)
src/app/features/dashboard/api/invitation.ts (1)
  • inviteUser (9-17)
src/app/shared/lib/toast.ts (2)
  • showSuccess (3-3)
  • showError (4-4)
src/app/shared/components/common/header/Collaborator/CollaboratorList.tsx (2)
src/app/shared/components/common/header/Collaborator/Tooltip.tsx (1)
  • Tooltip (12-70)
src/app/shared/components/common/CollaboratorItem.tsx (1)
  • CollaboratorItem (15-27)
src/app/features/dashboard/components/edit/EditMember.tsx (4)
src/app/shared/lib/toast.ts (2)
  • showSuccess (3-3)
  • showError (4-4)
src/app/features/dashboard/components/edit/PaginationHeader.tsx (1)
  • PaginationHeader (15-59)
src/app/shared/lib/cn.ts (1)
  • cn (4-6)
src/app/shared/components/common/UserInfo.tsx (1)
  • UserInfo (13-32)
src/app/shared/components/common/header/NavItem.tsx (1)
src/app/shared/lib/cn.ts (1)
  • cn (4-6)
src/app/shared/components/dashboard/DashboardForm.tsx (2)
src/app/features/dashboard_Id/Card/cardFormModals/input/Input.tsx (1)
  • Input (9-28)
src/app/shared/constants/colors.ts (1)
  • DASHBOARD_COLORS (3-9)
src/app/features/dashboard/components/edit/EditInfo.tsx (2)
src/app/shared/hooks/useDashboardForm.ts (1)
  • useDashboardForm (14-111)
src/app/shared/components/dashboard/DashboardForm.tsx (1)
  • DashboardForm (22-99)
🔇 Additional comments (32)
src/app/shared/store/useModalStore.ts (1)

7-9: 타입 안정성 개선을 위한 좋은 변경사항입니다.

null 대신 문자열 센티널 값 'none'을 사용하여 타입 시스템의 일관성을 향상시켰습니다. 이는 null 체크를 피하고 더 명확한 상태 관리를 가능하게 합니다.

src/app/shared/hooks/useMembers.ts (1)

10-10: isOwner 타입을 명확히 해주세요.

isOwner: boolean | string 타입이 혼재되어 있습니다. API 응답에서 문자열로 받아오는 경우가 있는지 확인하고, 가능하다면 boolean으로 통일하는 것이 좋겠습니다.

다음 스크립트로 API 응답 형태를 확인해보세요:

#!/bin/bash
# isOwner 필드의 사용법을 확인합니다
rg -A 3 -B 3 "isOwner" --type ts
src/app/shared/hooks/usePagination.ts (1)

3-33: 잘 구현된 재사용 가능한 페이지네이션 훅입니다.

  • 제네릭 타입 지원으로 유연성 확보
  • useMemo를 사용한 성능 최적화
  • 페이지 경계 조건 처리가 적절함
  • 깔끔한 API 설계

재사용성이 높은 좋은 구현입니다.

src/app/shared/components/common/Avatar.tsx (1)

31-68: 전역 상태 의존성 제거를 통한 우수한 리팩토링입니다.

  • 전역 스토어 의존성 제거로 컴포넌트 재사용성 향상
  • Props 기반 설계로 더 예측 가능한 동작
  • getColor 유틸리티 활용으로 일관된 색상 생성
  • 이미지 로딩 실패 시 적절한 폴백 처리

컴포넌트 아키텍처가 크게 개선되었습니다.

src/app/shared/components/common/CollaboratorItem.tsx (1)

24-24: Avatar 컴포넌트 인터페이스와 일치하는 올바른 prop 이름 변경

Avatar 컴포넌트의 업데이트된 인터페이스에 맞춰 prop 이름을 imageUrl에서 profileImageUrl로 변경한 것이 적절합니다.

src/app/shared/components/common/header/NavItem.tsx (1)

26-31: cn 유틸리티 사용에 대한 유용한 주석 추가

외부에서 className을 받을 때 cn 유틸리티 사용을 권장하는 주석이 개발자에게 도움이 됩니다.

src/app/shared/components/common/header/UserDropdown.tsx (3)

14-21: 로그아웃 후 로그인 페이지로 리디렉션하는 개선된 사용자 경험

로그아웃 후 메인 페이지('/') 대신 로그인 페이지('/login')로 리디렉션하는 것이 더 직관적이고 사용자 친화적입니다.


27-28: 하드코딩된 사용자 정보 제거로 동적 데이터 흐름 개선

UserInfo 컴포넌트에서 하드코딩된 nickname prop을 제거하고 자동으로 로그인된 사용자 정보를 불러오도록 변경한 것이 더 유연하고 유지보수하기 좋은 구조입니다.


14-16: 함수 선언 스타일 일관성 확인을 위해 --type 대신 -g 옵션으로 확장자를 지정하여 다시 검색해 보겠습니다.

#!/bin/bash
echo "=== 화살표 함수 패턴 검색 ==="
rg -g '*.ts' -g '*.tsx' -A 2 "const [A-Za-z0-9_]\+ *= *\(" .

echo -e "\n=== 함수 선언 패턴 검색 ==="
rg -g '*.ts' -g '*.tsx' -A 2 "^\s*function [A-Za-z0-9_]\+" .
src/app/dashboard/[id]/edit/page.tsx (1)

19-25: 뒤로가기 버튼 스타일링 개선

패딩 조정, 이미지 크기 명시, 그리고 일관된 폰트 크기 클래스 추가로 뒤로가기 버튼의 UI가 개선되었습니다.

src/app/shared/components/common/header/RightHeaderNav.tsx (2)

9-9: 불필요한 modalType 상태 추적 제거로 컴포넌트 단순화

NavItem에서 active 상태 관리가 제거됨에 따라 modalType 추적도 제거한 것이 일관성 있는 변경입니다.


17-17: 아이콘 파일 형식 변경 및 존재 여부 확인 필요

아이콘이 PNG에서 SVG로 변경되었습니다. 새로운 아이콘 파일이 올바른 경로에 존재하는지 확인해 주세요.

#!/bin/bash
# Description: 새로운 아이콘 파일 존재 여부 확인
# Expected: config.svg 파일이 public/images/ 경로에 존재해야 함

echo "=== 새로운 아이콘 파일 존재 여부 확인 ==="
if [ -f "public/images/config.svg" ]; then
  echo "✅ config.svg 파일이 존재합니다."
  ls -la "public/images/config.svg"
else
  echo "❌ config.svg 파일이 존재하지 않습니다."
fi

echo -e "\n=== 기존 management.png 파일 확인 ==="
if [ -f "public/images/management.png" ]; then
  echo "⚠️  기존 management.png 파일이 여전히 존재합니다."
  ls -la "public/images/management.png"
else
  echo "ℹ️  기존 management.png 파일이 제거되었습니다."
fi
src/app/features/dashboard/components/edit/PaginationHeader.tsx (2)

6-13: 타입 정의가 잘 구조화되어 있습니다.

컴포넌트의 props 타입이 명확하게 정의되어 있고, optional children prop을 통해 확장성을 제공하는 것이 좋습니다.


28-30: 페이지 표시 순서 확인이 필요합니다.

한국어 맥락에서 "총 페이지 중 현재 페이지" 순서가 더 자연스러울 수 있습니다.

현재 표시: "5 페이지 중 1"
제안 표시: "1 / 5 페이지" 또는 "1페이지 (총 5페이지)"

UI/UX 팀과 표시 형식을 확인해보시겠어요?

src/app/shared/components/dashboard/DashboardForm.tsx (3)

10-20: props 타입 정의가 잘 구조화되어 있습니다.

폼 데이터, 이벤트 핸들러, 옵션들이 명확하게 타입이 정의되어 있고, 기본값과 optional props 처리가 적절합니다.


50-71: 색상 선택 UI가 잘 구현되어 있습니다.

DASHBOARD_COLORS 상수를 사용하여 색상 버튼을 렌더링하고, 선택된 색상에 체크마크를 표시하는 로직이 올바릅니다. aria-label을 통한 접근성 고려도 좋습니다.


37-45: Input 컴포넌트의 실제 Props 정의를 확인하기 위해 아래 스크립트를 실행해주세요.

#!/bin/bash
# 1. Input.tsx 상단 200줄 출력
echo "=== src/app/shared/components/Input.tsx (1~200줄) ==="
sed -n '1,200p' src/app/shared/components/Input.tsx || true

# 2. Props 인터페이스/타입 검색
echo -e "\n=== Props 정의 검색 ==="
rg -n "type InputProps" src/app/shared/components/Input.tsx || true
rg -n "interface InputProps" src/app/shared/components/Input.tsx || true
src/app/shared/components/common/UserInfo.tsx (3)

8-8: nickname을 optional로 만든 변경이 좋습니다.

이전 필수 prop에서 optional로 변경하여 컴포넌트의 재사용성이 향상되었습니다.


16-19: fallback 로직과 early return 처리가 잘 구현되어 있습니다.

props와 사용자 스토어 데이터 간의 우선순위가 명확하고, 표시할 정보가 없을 때의 early return 처리가 적절합니다.


24-28: Avatar 컴포넌트에 props 전달이 올바릅니다.

relevant code snippets에서 확인한 Avatar 컴포넌트의 새로운 인터페이스에 맞게 nicknameprofileImageUrl을 정확히 전달하고 있습니다.

src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx (4)

18-26: React Query mutation 설정이 잘 구현되어 있습니다.

환경변수 검증과 API 호출 로직이 올바르게 mutationFn에 구현되어 있습니다.


27-42: 성공/에러 핸들링이 체계적으로 구현되어 있습니다.

onSuccess에서 라우터 리다이렉션, onError에서 axios 에러 타입 체크와 사용자 피드백이 잘 처리되어 있습니다.


44-50: 사용자 확인 처리가 적절합니다.

삭제 전 확인 다이얼로그와 조건부 실행 로직이 올바르게 구현되어 있습니다.


56-56: isPending 사용으로 정확히 수정되었습니다.

React Query v4+에서 isLoading이 isPending으로 변경된 것을 올바르게 반영했습니다.

src/app/shared/components/common/modal/CreateInvitationModal.tsx (5)

5-5: React Query 클라이언트 추가가 적절합니다.

캐시 관리를 위한 useQueryClient 훅 사용이 올바르게 추가되었습니다.

Also applies to: 17-17


36-40: 캐시 무효화 전략이 잘 구현되어 있습니다.

초대 성공 후 해당 대시보드의 초대 내역을 새로고침하는 캐시 무효화가 적절히 구현되어 있습니다.


19-23: 인라인 함수를 명명 함수로 리팩토링한 것이 좋습니다.

handleBackdropClick과 handleSubmit 함수로 분리하여 코드 가독성이 향상되었습니다.

Also applies to: 25-47


49-49: 모달 조건부 렌더링이 명확해졌습니다.

modalType 체크 로직이 명시적으로 변경되어 코드 의도가 더 명확해졌습니다.


37-39: 쿼리 키 검색 시 파일 타입 인식 오류가 발생한 것으로 보입니다. ts와 tsx 파일을 모두 포함하도록 glob 패턴을 사용해 재검증해보세요.

#!/bin/bash
# ts, tsx 파일에서 invitations 쿼리 키 패턴 검색
rg -A 3 -B 3 "queryKey.*invitations" -g '*.ts' -g '*.tsx'
src/app/shared/components/common/modal/CreateDashboardModal.tsx (1)

1-61: 깔끔한 리팩토링입니다!

커스텀 훅(useDashboardForm)과 재사용 가능한 컴포넌트(DashboardForm)를 활용하여 관심사를 잘 분리했습니다. 모달이 닫힐 때 폼을 초기화하는 처리도 적절합니다.

src/app/features/dashboard/components/edit/EditInvitation.tsx (1)

122-159: 초대 목록 UI 구현이 잘 되어있습니다.

빈 상태 처리, 툴팁을 통한 닉네임 표시, 취소 버튼의 로딩 상태 등이 적절히 구현되었습니다.

src/app/features/dashboard/components/edit/EditInfo.tsx (1)

1-37: 완벽한 컴포넌트 리팩토링입니다!

useDashboardForm 훅과 DashboardForm 컴포넌트를 활용하여 로직과 UI를 완전히 분리했습니다. 이는 재사용성과 유지보수성을 크게 향상시킵니다.

Comment on lines 14 to 24
const teamId = process.env.NEXT_PUBLIC_TEAM_ID

export async function fetchMembers(dashboardId: string): Promise<Member[]> {
const { data } = await authHttpClient.get(`/${teamId}/members`, {
params: {
page: 1,
size: 100,
dashboardId,
},
})
return data.members ?? data
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

환경 변수 에러 처리 및 데이터 구조 명확화가 필요합니다.

  1. teamIdundefined일 수 있는 경우에 대한 에러 처리가 필요합니다.
  2. data.members ?? data 폴백 로직의 의도를 명확히 해주세요.

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

+const teamId = process.env.NEXT_PUBLIC_TEAM_ID
+if (!teamId) {
+  throw new Error('NEXT_PUBLIC_TEAM_ID 환경변수가 설정되지 않았습니다.')
+}

 export async function fetchMembers(dashboardId: string): Promise<Member[]> {
   const { data } = await authHttpClient.get(`/${teamId}/members`, {
     params: {
       page: 1,
       size: 100,
       dashboardId,
     },
   })
+  // API 응답 구조에 따라 members 배열 또는 전체 데이터 반환
   return data.members ?? data
 }

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

🤖 Prompt for AI Agents
In src/app/shared/hooks/useMembers.ts around lines 14 to 24, add a check to
throw an explicit error if the environment variable teamId is undefined before
making the API call. Also, clarify the fallback logic by explicitly checking if
data.members exists and returning it; otherwise, handle or throw an error if the
data structure is unexpected, instead of using a fallback that may mask issues.

Comment on lines 91 to 96
const message = axios.isAxiosError(error)
? error.response?.data?.message ||
'대시보드 요청 중 오류가 발생했습니다.'
: '알 수 없는 오류가 발생했습니다.'
alert(message)
console.error('대시보드 오류:', error)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

사용자 경험을 위해 에러 처리 방식을 개선해주세요.

alert()를 사용한 에러 표시는 사용자 경험에 좋지 않습니다. 토스트 알림이나 인라인 에러 메시지를 사용하는 것을 고려해보세요.

에러 상태를 훅에서 관리하고 컴포넌트에서 적절히 표시하도록 개선할 수 있습니다:

+const [error, setError] = useState<string | null>(null)

 const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
   // ...
   try {
+    setError(null)
     setIsSubmitting(true)
     // ... API 호출
   } catch (error) {
     const message = axios.isAxiosError(error)
       ? error.response?.data?.message ||
         '대시보드 요청 중 오류가 발생했습니다.'
       : '알 수 없는 오류가 발생했습니다.'
-    alert(message)
+    setError(message)
     console.error('대시보드 오류:', error)
   }
 }

 return {
   // ... 다른 값들
+  error,
+  clearError: () => setError(null),
 }
📝 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 message = axios.isAxiosError(error)
? error.response?.data?.message ||
'대시보드 요청 중 오류가 발생했습니다.'
: '알 수 없는 오류가 발생했습니다.'
alert(message)
console.error('대시보드 오류:', error)
// ───────────────────────────────────────────────────────────────────────────────
// at the top of your hook (above handleSubmit)
const [error, setError] = useState<string | null>(null)
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
+ setError(null)
setIsSubmitting(true)
try {
// ... API 호출
} catch (error) {
const message = axios.isAxiosError(error)
? error.response?.data?.message ||
'대시보드 요청 중 오류가 발생했습니다.'
: '알 수 없는 오류가 발생했습니다.'
- alert(message)
+ setError(message)
console.error('대시보드 오류:', error)
} finally {
setIsSubmitting(false)
}
}
return {
// ... 다른 값들
error,
clearError: () => setError(null),
}
🤖 Prompt for AI Agents
In src/app/shared/hooks/useDashboardForm.ts around lines 91 to 96, replace the
alert-based error notification with state management for the error message
inside the hook. Create a state variable to hold the error message, set it when
an error occurs, and return this state from the hook so the component can
display the error using a toast notification or inline message instead of
alert().


import { mockMembers } from './mockMember'
const PAGE_SIZE = 4
const teamId = process.env.NEXT_PUBLIC_TEAM_ID
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

환경 변수가 정의되지 않았을 때를 대비한 처리가 필요합니다.

process.env.NEXT_PUBLIC_TEAM_ID가 undefined일 경우를 처리해야 합니다.

-const teamId = process.env.NEXT_PUBLIC_TEAM_ID
+const teamId = process.env.NEXT_PUBLIC_TEAM_ID
+
+if (!teamId) {
+  throw new Error('NEXT_PUBLIC_TEAM_ID가 환경 변수에 설정되지 않았습니다.')
+}
📝 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 teamId = process.env.NEXT_PUBLIC_TEAM_ID
const teamId = process.env.NEXT_PUBLIC_TEAM_ID
if (!teamId) {
throw new Error('NEXT_PUBLIC_TEAM_ID가 환경 변수에 설정되지 않았습니다.')
}
🤖 Prompt for AI Agents
In src/app/features/dashboard/components/edit/EditMember.tsx at line 16, the
code assigns process.env.NEXT_PUBLIC_TEAM_ID directly to teamId without handling
the case when this environment variable is undefined. Add a check to verify if
process.env.NEXT_PUBLIC_TEAM_ID is defined; if not, handle the situation
appropriately, such as setting a default value or throwing a clear error to
prevent runtime issues.

Comment on lines 30 to 40
// ✅ dashboardId 안전 처리
const rawDashboardId = params.id
const dashboardId: string =
typeof rawDashboardId === 'string'
? rawDashboardId
: (rawDashboardId?.[0] ?? '')

// ✅ teamId는 환경변수에서 가져오며 string으로 강제 처리
const rawTeamId = process.env.NEXT_PUBLIC_TEAM_ID
const teamId: string =
typeof rawTeamId === 'string' ? rawTeamId : (rawTeamId?.[0] ?? '')
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

파라미터 처리가 지나치게 복잡합니다.

useParams의 반환값과 환경 변수 처리가 과도하게 방어적입니다. Next.js의 useParams는 일반적으로 문자열을 반환하므로 이러한 복잡한 처리는 불필요할 수 있습니다.

-// ✅ dashboardId 안전 처리
-const rawDashboardId = params.id
-const dashboardId: string =
-  typeof rawDashboardId === 'string'
-    ? rawDashboardId
-    : (rawDashboardId?.[0] ?? '')
-
-// ✅ teamId는 환경변수에서 가져오며 string으로 강제 처리
-const rawTeamId = process.env.NEXT_PUBLIC_TEAM_ID
-const teamId: string =
-  typeof rawTeamId === 'string' ? rawTeamId : (rawTeamId?.[0] ?? '')
+const dashboardId = params.id as string
+const teamId = process.env.NEXT_PUBLIC_TEAM_ID as string
+
+if (!teamId) {
+  throw new Error('NEXT_PUBLIC_TEAM_ID가 설정되지 않았습니다.')
+}
📝 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
// ✅ dashboardId 안전 처리
const rawDashboardId = params.id
const dashboardId: string =
typeof rawDashboardId === 'string'
? rawDashboardId
: (rawDashboardId?.[0] ?? '')
// ✅ teamId는 환경변수에서 가져오며 string으로 강제 처리
const rawTeamId = process.env.NEXT_PUBLIC_TEAM_ID
const teamId: string =
typeof rawTeamId === 'string' ? rawTeamId : (rawTeamId?.[0] ?? '')
const dashboardId = params.id as string
const teamId = process.env.NEXT_PUBLIC_TEAM_ID as string
if (!teamId) {
throw new Error('NEXT_PUBLIC_TEAM_ID가 설정되지 않았습니다.')
}
🤖 Prompt for AI Agents
In src/app/features/dashboard/components/edit/EditInvitation.tsx around lines 30
to 40, the code overcomplicates extracting dashboardId and teamId by defensively
handling types that are unlikely given Next.js guarantees. Simplify by directly
assigning params.id and process.env.NEXT_PUBLIC_TEAM_ID to dashboardId and
teamId as strings without conditional checks, assuming they are strings as
expected.

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

🧹 Nitpick comments (2)
src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx (1)

20-43: React Query mutation으로의 리팩토링이 우수합니다.

블로킹 대화상자에서 토스트 기반 확인으로 변경하여 UX를 개선하고, React Query의 mutation lifecycle을 잘 활용한 점이 좋습니다.

환경변수 접근의 일관성을 위해 getTeamId 함수 사용을 권장합니다.

22-24줄에서 직접 process.env.NEXT_PUBLIC_TEAM_ID를 확인하는 대신, 새로 도입된 getTeamId 유틸리티 함수를 사용하면 더 일관된 코드가 됩니다.

+import { getTeamId } from '@/app/shared/lib/getTeamId'

  const mutation = useMutation<void, Error, void>({
    mutationFn: async () => {
-     if (!process.env.NEXT_PUBLIC_TEAM_ID) {
-       throw new Error('NEXT_PUBLIC_TEAM_ID 환경변수가 설정되지 않았습니다.')
-     }
+     const teamId = getTeamId()
      await api.delete(
-       `/${process.env.NEXT_PUBLIC_TEAM_ID}/dashboards/${dashboardId}`,
+       `/${teamId}/dashboards/${dashboardId}`,
      )
    },
src/app/features/dashboard/components/edit/EditInvitation.tsx (1)

89-97: 에러 메시지 처리 로직을 단순화할 수 있습니다.

현재 에러 처리 로직이 불필요하게 복잡합니다. 더 간단하고 읽기 쉽게 개선할 수 있습니다.

-// 에러 메시지 정리
-const errorMessage =
-  isError && axios.isAxiosError(error)
-    ? error.response?.status === 403
-      ? '초대 권한이 없습니다.'
-      : '초대 정보를 불러오는 데 실패했습니다.'
-    : isError
-      ? '초대 정보를 불러오는 데 실패했습니다.'
-      : null
+const getErrorMessage = () => {
+  if (!isError) return null
+  if (axios.isAxiosError(error) && error.response?.status === 403) {
+    return '초대 권한이 없습니다.'
+  }
+  return '초대 정보를 불러오는 데 실패했습니다.'
+}
+
+const errorMessage = getErrorMessage()
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d06b980 and ecebc70.

📒 Files selected for processing (13)
  • src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx (2 hunks)
  • src/app/features/dashboard/components/edit/EditInfo.tsx (1 hunks)
  • src/app/features/dashboard/components/edit/EditInvitation.tsx (1 hunks)
  • src/app/features/dashboard/components/edit/EditMember.tsx (1 hunks)
  • src/app/features/dashboard/components/edit/mockMember.js (0 hunks)
  • src/app/shared/components/common/UserInfo.tsx (1 hunks)
  • src/app/shared/components/common/header/Collaborator/CollaboratorList.tsx (1 hunks)
  • src/app/shared/components/common/header/NavItem.tsx (1 hunks)
  • src/app/shared/components/common/header/RightHeaderNav.tsx (1 hunks)
  • src/app/shared/hooks/useDashboard.ts (1 hunks)
  • src/app/shared/hooks/useDashboardForm.ts (1 hunks)
  • src/app/shared/hooks/useMembers.ts (1 hunks)
  • src/app/shared/lib/getTeamId.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • src/app/features/dashboard/components/edit/mockMember.js
✅ Files skipped from review due to trivial changes (1)
  • src/app/shared/hooks/useDashboard.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/app/shared/components/common/header/NavItem.tsx
  • src/app/shared/components/common/header/RightHeaderNav.tsx
  • src/app/shared/hooks/useMembers.ts
  • src/app/shared/hooks/useDashboardForm.ts
  • src/app/shared/components/common/UserInfo.tsx
  • src/app/shared/components/common/header/Collaborator/CollaboratorList.tsx
  • src/app/features/dashboard/components/edit/EditMember.tsx
  • src/app/features/dashboard/components/edit/EditInfo.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx (1)
src/app/shared/lib/toast.ts (2)
  • showSuccess (3-3)
  • showError (4-4)
🔇 Additional comments (6)
src/app/shared/lib/getTeamId.ts (1)

1-7: 환경변수 접근을 중앙화한 좋은 접근 방식입니다.

getTeamId 함수를 통해 환경변수 접근을 중앙화하고 적절한 에러 처리를 구현한 점이 우수합니다. 이는 코드의 일관성과 유지보수성을 향상시킵니다.

src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx (1)

45-54: 토스트 기반 삭제 확인 구현이 훌륭합니다.

사용자 경험을 향상시키는 비블로킹 확인 방식이며, 명확한 설명과 액션 버튼을 제공하는 점이 우수합니다.

src/app/features/dashboard/components/edit/EditInvitation.tsx (4)

33-33: 파라미터 처리가 개선되었습니다.

과거 리뷰에서 지적된 복잡한 파라미터 처리가 간단하고 명확하게 개선되었습니다.


38-54: React Query를 활용한 데이터 페칭이 우수합니다.

적절한 쿼리 키 설정, 에러 재시도 비활성화, enabled 조건 등 React Query 모범 사례를 잘 따르고 있습니다.


67-84: mutation을 통한 초대 취소 기능이 잘 구현되었습니다.

적절한 에러 처리, 성공 시 캐시 무효화, 토스트 피드백 등이 잘 구현되어 있습니다.


125-176: 로딩, 에러, 빈 상태 처리가 잘 구현되었습니다.

다양한 UI 상태에 대한 적절한 처리와 사용자 피드백이 잘 구현되어 있습니다. Tooltip을 활용한 닉네임 표시와 mutation 상태에 따른 버튼 비활성화도 우수합니다.

Comment on lines +18 to +19
const INVITATION_SIZE = 5
const teamId = getTeamId()
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

모듈 레벨에서의 getTeamId() 호출을 컴포넌트 내부로 이동하세요.

모듈 레벨에서 getTeamId()를 호출하면 환경변수가 설정되지 않았을 때 모듈 초기화 시점에 에러가 발생할 수 있습니다. 컴포넌트 내부로 이동하는 것이 안전합니다.

-const INVITATION_SIZE = 5
-const teamId = getTeamId()

+const INVITATION_SIZE = 5

 export default function EditInvitation() {
   const params = useParams()
   const { openModal } = useModalStore()
 
   const dashboardId = params.id as string
+  const teamId = getTeamId()
   const queryClient = useQueryClient()
📝 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 INVITATION_SIZE = 5
const teamId = getTeamId()
// at top of file, only the constant remains
const INVITATION_SIZE = 5
export default function EditInvitation() {
const params = useParams()
const { openModal } = useModalStore()
const dashboardId = params.id as string
const teamId = getTeamId()
const queryClient = useQueryClient()
// …rest of the component
}
🤖 Prompt for AI Agents
In src/app/features/dashboard/components/edit/EditInvitation.tsx at lines 18-19,
move the call to getTeamId() from the module level into the component function
body to avoid errors during module initialization when environment variables are
not set. This means declaring and assigning teamId inside the React component
instead of at the top-level scope.

@yuj2n yuj2n merged commit 9169f13 into develop Jun 21, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨Feat 기능 개발 🐛Fix 버그 수정 💄Modify 자잘한 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants