Skip to content

Conversation

@dkslel1225
Copy link
Contributor

@dkslel1225 dkslel1225 commented Jun 19, 2025

📌 변경 사항 개요

  • feature/하위 폴더로 파일 이동
  • 카드 생성 모달 구현
  • shared/lip/textAxios.ts 는 제가 테스트로 사용중인 파일입니다. (나중에 삭제 예정)

변경 파일이 많이 뜰거같은데,
이번 작업은 CreateCardForm 파일 중심으로 진행되었고,
관련 파일은 아래 사진에 보이는, feature/dashboard_id경로 내에서 확인 가능합니다.

image

큰 틀은 CreateCardForm에 집중되어 있으니 이 파일 위주로 검토해주시면 됩니다.

✨ 요약

  • CreateCardForm: 카드생성 폼
  • CreateCardModal: 모달 껍데기

  • 타이틀, 설명만 필수 입력.

  • 마감일, 이미지는 미입력 시 필드에서 해당 키 자체를 제거하고 post요청에 전달하면 에러 안 남..

2025-06-19.4.38.37.mov

thub.com/user-attachments/assets/918e9fc4-628b-4cfa-8363-06cdedc660a9

📝 상세 내용

🔗 관련 이슈

🖼️ 스크린샷

✅ 체크리스트

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

💡 참고 사항

Summary by CodeRabbit

  • 신규 기능

    • 카드 생성, 이미지 업로드, 담당자 지정, 태그 및 마감일 설정 등 카드 작성 폼 추가
    • 대시보드별 컬럼 및 카드 목록, 멤버 목록 조회 기능 추가
    • 모달 및 입력 UI 컴포넌트, 드래그 앤 드롭 상태 관리 기능 도입
  • 버그 수정

    • 태그 및 아바타 색상 계산 로직 오류 수정
  • 스타일

    • 인풋, 텍스트, 호버 등 신규 CSS 유틸리티 클래스 추가
  • 리팩터링

    • 내부 API 및 타입 정의 분리 및 경로 구조 개선
  • 기타

    • 신규 라이브러리(date-fns, react-datepicker) 도입
    • 모달 렌더링을 위한 DOM 노드 추가

jyn added 6 commits June 18, 2025 18:11
- UI, 기능 적용. 완성도 80%
- 폴더 구조 변경
-폼데이터의 디폴트값을 빈 문자열로 설정
- onSubmit함수에서는 해당 란을 제외한 데이터를 보냄.

(빈 문자열로 디폴트값 설정 안하면, 기본 파일리스트 객체가 전달되기 때문에 이미지 URL이 있는지 참,거짓 측정이 불가함)
@coderabbitai
Copy link

coderabbitai bot commented Jun 19, 2025

Walkthrough

이 변경사항은 대시보드 상세 페이지의 카드 및 컬럼 관리 기능을 대폭 확장하고, 관련 API 훅, 타입, 저장소, 컴포넌트들을 features/dashboard_Id 폴더로 이동 및 리팩토링합니다. 카드 생성, 이미지 업로드, 담당자 선택, 드래그 앤 드롭, 모달 표시 등 다양한 신규 기능과 유틸리티가 추가되었습니다.

Changes

파일/그룹 변경 요약
package.json date-fns, react-datepicker 의존성 추가
src/app/globals.css 입력 및 호버 관련 유틸리티 CSS 클래스 추가
src/app/layout.tsx <div id="modal-root"> 추가로 모달 렌더링용 DOM 노드 제공
src/app/shared/lib/getColor.ts, .../Avatar.tsx, .../Card/Tags.tsx getColor 함수 시그니처 및 사용법 수정(배열 → 길이)
src/app/shared/lib/testAxios.ts Axios 인스턴스명 및 baseURL 변경, export명 변경
src/app/dashboard/[id]/layout.tsx AboutLayout 레이아웃 컴포넌트 신규 도입, 헤더 렌더링, 사이드바 주석 처리
src/app/dashboard/[id]/page.tsx URL 파라미터로 대시보드 ID 동적 획득, 컬럼 훅 호출, 레이아웃 및 import 경로 수정
src/app/features/dashboardId/Card/Tags.tsx getColor 호출 방식 수정(배열 → 길이)
src/app/features/dashboardId/Card/cardFormModals/AssigneeList.tsx 하드코딩된 담당자 리스트 드롭다운 컴포넌트 신규 추가
src/app/features/dashboard_Id/Card/Card.tsx 타입 import 경로 수정, 카드 id 참조 방식 변경, 마감일/담당자 조건부 렌더링
src/app/features/dashboard_Id/Card/Tags.tsx 태그 리스트 컴포넌트 신규 추가, 색상 일관성 보장
src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx 대시보드 멤버 기반 담당자 선택 드롭다운 컴포넌트 신규 추가
src/app/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx 카드 생성 폼(담당자, 제목, 설명, 마감일, 태그, 이미지 업로드) 신규 구현
src/app/features/dashboard_Id/Card/cardFormModals/CreateCardModal.tsx 모달 포탈 컴포넌트 신규 구현
src/app/features/dashboard_Id/Card/cardFormModals/input/DateInput.tsx 날짜 입력용 커스텀 인풋 컴포넌트 신규 구현
src/app/features/dashboard_Id/Card/cardFormModals/input/Input.tsx 라벨+입력 필드 래퍼 컴포넌트 신규 구현
src/app/features/dashboard_Id/Column/Column.tsx 카드 생성 모달 추가, 드래그 오버/드롭 로직 개선, import 경로 수정
src/app/features/dashboard_Id/api/fetchCards.ts 카드 목록 조회 API 함수 신규 추가
src/app/features/dashboard_Id/api/fetchColumns.ts 컬럼 목록 조회 API 함수 신규 추가
src/app/features/dashboard_Id/api/fetchMembers.ts 멤버 목록 조회 API 함수 신규 추가
src/app/features/dashboard_Id/api/postCard.ts 카드 생성 API 함수 신규 추가
src/app/features/dashboard_Id/api/postCardImage.ts 카드 이미지 업로드 API 함수 신규 추가
src/app/features/dashboard_Id/api/updateCardColumn.ts 카드 컬럼 이동 API 함수 신규 추가
src/app/features/dashboard_Id/api/useCardMutation.ts 타입 import 경로 수정 및 공백 정리
src/app/features/dashboard_Id/api/useCards.ts 카드 목록 조회용 React Query 훅 신규 추가
src/app/features/dashboard_Id/api/useColumns.ts 컬럼 목록 조회용 React Query 훅 신규 추가
src/app/features/dashboard_Id/api/useMembers.ts 멤버 목록 조회용 React Query 훅 신규 추가
src/app/features/dashboard_Id/api/usePostCard.ts 카드 생성용 React Query mutation 훅 신규 추가
src/app/features/dashboard_Id/api/useUploadCardImage.ts 카드 이미지 업로드용 React Query mutation 훅 신규 추가
src/app/features/dashboard_Id/lib/getDashboardMembers.ts 멤버 → 담당자 변환 유틸리티 함수 및 타입 추가
src/app/features/dashboard_Id/store/useDragStore.ts 카드 드래그 상태 관리용 Zustand store 신규 추가
src/app/features/dashboard_Id/type/Card.type.ts 카드, 카드 응답 타입 추가
src/app/features/dashboard_Id/type/CardFormData.type.ts 카드 폼 데이터 타입 추가
src/app/features/dashboard_Id/type/Column.type.ts 컬럼, 컬럼 응답 타입 추가
src/app/features/dashboard_Id/type/Member.type.ts 멤버, 멤버 응답 타입 추가
src/app/api/useCards.ts, src/app/api/useColumns.ts, src/app/dashboard/[id]/api/updateCardColumn.ts 기존 API 훅/타입/함수 파일 삭제 및 기능 이전/확장

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DashboardPage
    participant Column
    participant CreateCardModal
    participant CreateCardForm
    participant API

    User->>DashboardPage: 대시보드 상세 진입
    DashboardPage->>Column: 컬럼/카드 데이터 로드
    User->>Column: "카드 추가" 클릭
    Column->>CreateCardModal: 모달 오픈
    CreateCardModal->>CreateCardForm: 카드 생성 폼 렌더
    User->>CreateCardForm: 폼 입력/담당자/태그/이미지 선택
    CreateCardForm->>API: 이미지 업로드 (선택 시)
    API-->>CreateCardForm: 이미지 URL 반환
    User->>CreateCardForm: 제출 클릭
    CreateCardForm->>API: 카드 생성 요청
    API-->>CreateCardForm: 생성 성공 응답
    CreateCardForm->>Column: 모달 닫기, 카드 목록 갱신
Loading
sequenceDiagram
    participant User
    participant Column
    participant Card
    participant useDragStore
    participant API

    User->>Card: 카드 드래그 시작
    Card->>useDragStore: draggingCard 상태 저장
    User->>Column: 카드 드롭
    Column->>useDragStore: draggingCard 상태 확인
    Column->>API: 카드 컬럼 이동 요청
    API-->>Column: 이동 성공 응답
    Column->>useDragStore: draggingCard 상태 초기화
    Column->>Column: 카드 목록 갱신
Loading

Possibly related PRs

  • CoPlay-FE/coplan#42: Sidebar 컴포넌트 및 대시보드 관련 UI를 도입하여 본 PR의 레이아웃 변경과 직접적으로 연관됨.
  • CoPlay-FE/coplan#37: 카드/컬럼 관련 API 훅과 타입을 최초로 도입한 PR로, 본 PR의 리팩토링 및 확장과 코드 레벨에서 밀접하게 연결됨.
  • CoPlay-FE/coplan#55: 카드 드래그 앤 드롭 및 상태 관리 로직을 구현한 PR로, 본 PR의 drag store 및 컬럼 이동 로직과 직접 관련됨.

Suggested labels

✨Feat

Poem

🐇
새 폴더 속에 토끼가 뛰어,
카드와 컬럼, 담당자도 모여.
드래그엔 드롭, 모달엔 폼,
이미지 첨부도 이제는 척척!
대시보드가 더 똑똑해진 오늘,
토끼는 기뻐 귀를 쫑긋 세우네.

✨🥕✨

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-19T08_06_28_021Z-debug-0.log

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

@dkslel1225 dkslel1225 changed the base branch from main to feature/dashboard_id June 19, 2025 07:47
@dkslel1225 dkslel1225 self-assigned this Jun 19, 2025
@dkslel1225 dkslel1225 added ✨Feat 기능 개발 🐛Fix 버그 수정 📁Chore 폴더 변경 또는 디렉토리 작업 labels Jun 19, 2025
@dkslel1225 dkslel1225 added this to the 2차 구현 기간 milestone Jun 19, 2025
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: 19

🔭 Outside diff range comments (1)
src/app/dashboard/[id]/page.tsx (1)

26-124: 드래그 앤 드롭 로직이 복잡하므로 별도 훅으로 분리를 고려해주세요.

터치 이벤트 핸들링 로직이 매우 복잡하고 컴포넌트를 무겁게 만들고 있습니다. useDragAndDrop 같은 커스텀 훅으로 분리하는 것을 고려해보세요. 또한 한국어 주석들을 영어로 통일해주세요.

주석 언어 통일 예시:

-    // 1. 터치 대상 찾기
+    // 1. Find touch target
-    // 2. 카드 영역 내 터치 좌표 계산 (저장)
+    // 2. Calculate and store touch coordinates within card area
🧹 Nitpick comments (17)
src/app/shared/lib/testAxios.ts (1)

3-5: 임시 파일의 정리 계획을 확인해주세요.

변수명 변경과 URL 업데이트는 적절하지만, PR 목표에서 언급한 대로 이 파일이 임시 테스트용이라면 향후 정리 계획을 추적하는 것이 좋겠습니다.

Also applies to: 10-10, 18-18

src/app/features/dashboard_Id/api/fetchColumns.ts (1)

7-9: 환경 변수 유효성 검사 추가를 고려해보세요.

dashboardId는 검증하지만 process.env.NEXT_PUBLIC_TEAM_ID에 대한 검증은 없습니다. 환경 변수가 설정되지 않았을 경우 런타임 에러가 발생할 수 있습니다.

export async function fetchColumns(dashboardId: number): Promise<Column[]> {
  if (!dashboardId) {
    throw new Error('dashboardId가 유효하지 않습니다.')
  }
+
+  if (!process.env.NEXT_PUBLIC_TEAM_ID) {
+    throw new Error('NEXT_PUBLIC_TEAM_ID가 설정되지 않았습니다.')
+  }
src/app/features/dashboard_Id/api/usePostCard.ts (1)

13-13: 쿼리 키를 더 구체적으로 만드는 것을 고려해보세요.

현재 ['columnId']로 모든 컬럼 관련 쿼리를 무효화하고 있습니다. 특정 대시보드의 카드만 무효화하도록 더 구체적인 키를 사용하는 것이 좋을 것 같습니다.

-    queryClient.invalidateQueries({ queryKey: ['columnId'] })
+    queryClient.invalidateQueries({ queryKey: ['cards', dashboardId] })

이렇게 하려면 dashboardId를 훅의 매개변수로 받아야 합니다.

src/app/features/dashboard_Id/api/useColumns.ts (1)

6-6: export 방식의 일관성을 고려해보세요.

다른 API 함수들은 named export를 사용하고 있는데, 이 훅만 default export를 사용하고 있습니다. 프로젝트의 일관성을 위해 named export 사용을 고려해보세요.

-export default function useColumns(dashboardId: number) {
+export function useColumns(dashboardId: number) {
src/app/features/dashboard_Id/api/fetchMembers.ts (1)

6-11: 입력 검증 추가를 고려해보세요.

fetchColumns 함수와 달리 이 함수는 dashboardId 검증이 없습니다. 일관성을 위해 동일한 검증 로직을 추가하는 것이 좋겠습니다.

export async function fetchMembers(dashboardId: number): Promise<Member[]> {
+  if (!dashboardId) {
+    throw new Error('dashboardId가 유효하지 않습니다.')
+  }
+
  const res = await api.get<MembersResponse>(
src/app/features/dashboard_Id/api/postCardImage.ts (1)

4-7: 함수명이 복수형이지만 단일 파일을 처리합니다.

함수명 postCardImages는 복수형이지만 실제로는 하나의 파일만 처리합니다. 일관성을 위해 단수형으로 변경하는 것이 좋습니다.

-export async function postCardImages(
+export async function postCardImage(
src/app/features/dashboard_Id/api/updateCardColumn.ts (1)

11-13: 객체 프로퍼티 축약형을 사용하세요.

columnId: columnId는 중복입니다. ES6 축약형을 사용할 수 있습니다.

    `/${process.env.NEXT_PUBLIC_TEAM_ID}/cards/${cardId}`,
    {
-     columnId: columnId,
+     columnId,
    },
src/app/features/dashboard_Id/api/useCards.ts (1)

1-1: 주석 언어 일관성을 맞춰주세요.

영문 코드베이스에서는 주석도 영어로 작성하는 것이 일관성 측면에서 좋습니다.

-//size일단 10으로 하고, 나중에 커서아이디 받아서 무한 스크롤 구현해야 함.
+// TODO: Implement infinite scrolling with cursor ID, currently using fixed size of 10
src/app/features/dashboard_Id/lib/getDashboardMembers.ts (1)

8-10: 주석 언어 일관성과 반환 타입 명시를 개선해주세요.

영문 코드베이스에서는 주석도 영어로 작성하고, 함수의 반환 타입을 명시하는 것이 좋습니다.

-// 서버에서 받아온 Member 객체 배열을 Assignee 배열로 가공
-// → 불필요한 필드는 제거하고 필요한 userId, nickname만 추출
-export default function getDashboardMembers(data: Member[] | undefined) {
+// Transform Member array to Assignee array, extracting only required fields
+export default function getDashboardMembers(data: Member[] | undefined): Assignee[] {
src/app/dashboard/[id]/page.tsx (1)

130-132: 하드코딩된 마진 값을 개선해주세요.

ml-300 같은 하드코딩된 값들은 사이드바 상태에 따라 동적으로 조정되어야 합니다.

-      <div className="ml-300 select-none">
+      <div className={`${isSidebarOpen ? 'ml-300' : 'ml-0'} select-none transition-all duration-300`}>
src/app/features/dashboardId/Card/cardFormModals/AssigneeList.tsx (1)

21-21: 디버깅 코드 제거 필요

프로덕션 코드에서 console.log 문을 제거해야 합니다.

src/app/features/dashboard_Id/Card/cardFormModals/input/Input.tsx (1)

2-7: 인터페이스명을 더 구체적으로 변경 권장

Input이라는 인터페이스명이 너무 일반적입니다. InputProps 또는 LabeledInputProps와 같이 더 구체적인 이름을 사용하는 것이 좋습니다.

-interface Input {
+interface InputProps {
   children: React.ReactNode
   labelName: string
   labelFor: string
   accent?: boolean
 }

 export default function Input({
   children,
   labelName,
   labelFor,
   accent,
-}: Input) {
+}: InputProps) {
src/app/features/dashboard_Id/Card/Tags.tsx (1)

4-5: 중복 태그 방지 기능 구현 고려

주석에 언급된 "동일 태그 입력 불가하도록" 기능을 카드 생성 폼에서 구현하는 것을 고려해보세요.

중복 태그 방지 로직 구현에 도움이 필요하시면 알려주세요.

src/app/dashboard/[id]/layout.tsx (1)

12-12: 주석 처리된 Sidebar 정리 필요

Sidebar가 주석 처리되어 있는데, 사용할 계획이 없다면 import와 함께 제거하거나, 향후 사용 예정이라면 TODO 주석을 추가하는 것이 좋습니다.

-import Sidebar from '@/app/shared/components/common/sidebar/Sidebar'

또는

-      {/* <Sidebar /> */}
+      {/* TODO: Sidebar 기능 구현 예정 */}
+      {/* <Sidebar /> */}
src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx (1)

9-12: 중복 인터페이스 정의를 확인해주세요.

Assignee 인터페이스가 getDashboardMembers.ts 파일에도 정의되어 있는 것 같습니다. 중복을 피하기 위해 한 곳에서 export하여 재사용하는 것을 고려해보세요.

getDashboardMembers.ts에서 Assignee를 export하고 여기서 import하도록 수정:

-export interface Assignee {
-  userId: number
-  nickname: string
-}
+import { Assignee } from '../../lib/getDashboardMembers'
src/app/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx (2)

91-92: console.log 제거가 필요합니다.

프로덕션 코드에서 디버깅용 console.log는 제거해야 합니다.

-    console.log('🌀', data.imageUrl)
-    console.log('submitted', payload)

204-204: TODO 주석을 해결해주세요.

태그 클릭으로 삭제 기능 구현이 필요해 보입니다. 사용자 경험 개선을 위해 이 기능을 추가하는 것을 고려해보세요.

태그 삭제 기능 구현을 도와드릴까요? 클릭 핸들러와 UI 개선 코드를 생성해드릴 수 있습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3a4833c and 38a70ca.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • public/images/plus.svg is excluded by !**/*.svg
📒 Files selected for processing (38)
  • package.json (1 hunks)
  • src/app/api/useCards.ts (0 hunks)
  • src/app/api/useColumns.ts (0 hunks)
  • src/app/dashboard/[id]/api/updateCardColumn.ts (0 hunks)
  • src/app/dashboard/[id]/layout.tsx (1 hunks)
  • src/app/dashboard/[id]/page.tsx (2 hunks)
  • src/app/features/dashboardId/Card/Tags.tsx (1 hunks)
  • src/app/features/dashboardId/Card/cardFormModals/AssigneeList.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/Card.tsx (3 hunks)
  • src/app/features/dashboard_Id/Card/Tags.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardFormModals/CreateCardModal.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardFormModals/input/DateInput.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardFormModals/input/Input.tsx (1 hunks)
  • src/app/features/dashboard_Id/Column/Column.tsx (6 hunks)
  • src/app/features/dashboard_Id/api/fetchCards.ts (1 hunks)
  • src/app/features/dashboard_Id/api/fetchColumns.ts (1 hunks)
  • src/app/features/dashboard_Id/api/fetchMembers.ts (1 hunks)
  • src/app/features/dashboard_Id/api/postCard.ts (1 hunks)
  • src/app/features/dashboard_Id/api/postCardImage.ts (1 hunks)
  • src/app/features/dashboard_Id/api/updateCardColumn.ts (1 hunks)
  • src/app/features/dashboard_Id/api/useCardMutation.ts (2 hunks)
  • src/app/features/dashboard_Id/api/useCards.ts (1 hunks)
  • src/app/features/dashboard_Id/api/useColumns.ts (1 hunks)
  • src/app/features/dashboard_Id/api/useMembers.ts (1 hunks)
  • src/app/features/dashboard_Id/api/usePostCard.ts (1 hunks)
  • src/app/features/dashboard_Id/api/useUploadCardImage.ts (1 hunks)
  • src/app/features/dashboard_Id/lib/getDashboardMembers.ts (1 hunks)
  • src/app/features/dashboard_Id/type/Card.type.ts (1 hunks)
  • src/app/features/dashboard_Id/type/CardFormData.type.ts (1 hunks)
  • src/app/features/dashboard_Id/type/Column.type.ts (1 hunks)
  • src/app/features/dashboard_Id/type/Member.type.ts (1 hunks)
  • src/app/globals.css (2 hunks)
  • src/app/layout.tsx (1 hunks)
  • src/app/shared/components/common/Avatar.tsx (1 hunks)
  • src/app/shared/lib/getColor.ts (1 hunks)
  • src/app/shared/lib/testAxios.ts (1 hunks)
💤 Files with no reviewable changes (3)
  • src/app/dashboard/[id]/api/updateCardColumn.ts
  • src/app/api/useColumns.ts
  • src/app/api/useCards.ts
🧰 Additional context used
🧬 Code Graph Analysis (18)
src/app/features/dashboardId/Card/Tags.tsx (1)
src/app/shared/lib/getColor.ts (1)
  • getColor (1-5)
src/app/shared/components/common/Avatar.tsx (1)
src/app/shared/lib/getColor.ts (1)
  • getColor (1-5)
src/app/features/dashboard_Id/api/useMembers.ts (2)
src/app/features/dashboard_Id/type/Member.type.ts (1)
  • Member (1-10)
src/app/features/dashboard_Id/api/fetchMembers.ts (1)
  • fetchMembers (6-11)
src/app/features/dashboard_Id/api/fetchColumns.ts (1)
src/app/features/dashboard_Id/type/Column.type.ts (2)
  • Column (1-8)
  • ColumnsResponse (9-11)
src/app/features/dashboard_Id/api/fetchMembers.ts (1)
src/app/features/dashboard_Id/type/Member.type.ts (2)
  • Member (1-10)
  • MembersResponse (11-14)
src/app/features/dashboard_Id/api/postCard.ts (1)
src/app/features/dashboard_Id/type/CardFormData.type.ts (1)
  • CardFormData (1-10)
src/app/features/dashboard_Id/api/usePostCard.ts (1)
src/app/features/dashboard_Id/api/postCard.ts (1)
  • postCard (10-16)
src/app/features/dashboard_Id/api/useUploadCardImage.ts (1)
src/app/features/dashboard_Id/api/postCardImage.ts (1)
  • postCardImages (4-21)
src/app/features/dashboard_Id/api/fetchCards.ts (1)
src/app/features/dashboard_Id/type/Card.type.ts (1)
  • CardResponse (21-25)
src/app/features/dashboard_Id/lib/getDashboardMembers.ts (2)
src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx (1)
  • Assignee (9-12)
src/app/features/dashboard_Id/type/Member.type.ts (1)
  • Member (1-10)
src/app/dashboard/[id]/page.tsx (1)
src/app/features/dashboard_Id/api/useColumns.ts (1)
  • useColumns (6-11)
src/app/dashboard/[id]/layout.tsx (1)
src/app/shared/components/common/header/Header.tsx (1)
  • Header (12-66)
src/app/features/dashboard_Id/Card/Card.tsx (2)
src/app/features/dashboard_Id/Card/Tags.tsx (1)
  • Tags (3-29)
src/app/shared/components/common/Avatar.tsx (1)
  • Avatar (32-61)
src/app/features/dashboard_Id/Card/Tags.tsx (1)
src/app/shared/lib/getColor.ts (1)
  • getColor (1-5)
src/app/features/dashboard_Id/api/useCards.ts (2)
src/app/features/dashboard_Id/type/Card.type.ts (1)
  • CardResponse (21-25)
src/app/features/dashboard_Id/api/fetchCards.ts (1)
  • fetchCards (6-14)
src/app/features/dashboardId/Card/cardFormModals/AssigneeList.tsx (3)
src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx (2)
  • AssigneeList (24-50)
  • Assignee (9-12)
src/app/features/dashboard_Id/type/Card.type.ts (1)
  • Assignee (1-5)
src/app/shared/lib/cn.ts (1)
  • cn (4-6)
src/app/features/dashboard_Id/Column/Column.tsx (5)
src/app/features/dashboard_Id/type/Column.type.ts (1)
  • Column (1-8)
src/app/features/dashboard_Id/api/useCards.ts (1)
  • useCards (7-12)
src/app/features/dashboard_Id/store/useDragStore.ts (1)
  • useDragStore (13-17)
src/app/features/dashboard_Id/Card/cardFormModals/CreateCardModal.tsx (1)
  • CreateCardModal (7-19)
src/app/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx (1)
  • CreateCardForm (19-281)
src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx (5)
src/app/features/dashboard_Id/lib/getDashboardMembers.ts (2)
  • Assignee (3-6)
  • getDashboardMembers (10-18)
src/app/features/dashboard_Id/type/Member.type.ts (1)
  • Member (1-10)
src/app/features/dashboard_Id/type/CardFormData.type.ts (1)
  • CardFormData (1-10)
src/app/features/dashboardId/Card/cardFormModals/AssigneeList.tsx (1)
  • AssigneeList (7-29)
src/app/shared/lib/cn.ts (1)
  • cn (4-6)
🪛 Biome (1.9.4)
src/app/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx

[error] 92-92: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 94-97: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

🔇 Additional comments (35)
package.json (1)

16-16: 새로운 의존성 추가가 적절합니다.

카드 생성 모달의 날짜 선택 기능을 위한 date-fnsreact-datepicker 라이브러리 추가가 기능 요구사항과 잘 맞습니다.

Also applies to: 20-20

src/app/layout.tsx (1)

28-28: 모달 포털을 위한 DOM 노드 추가가 적절합니다.

React 포털을 통한 모달 렌더링을 위한 modal-root div 추가는 표준적인 구현 방식입니다.

src/app/shared/lib/getColor.ts (1)

1-5: 함수 시그니처 개선이 우수합니다.

배열 전체 대신 배열 길이만 받도록 변경한 것은 성능상 효율적이고 함수의 의도를 더 명확하게 만듭니다.

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

34-34: getColor 함수 호출 업데이트가 일관성 있게 적용되었습니다.

함수 시그니처 변경에 맞춰 customColors.length를 전달하도록 수정한 것이 올바릅니다.

src/app/features/dashboardId/Card/Tags.tsx (1)

12-12: 타입 안전성 개선을 위한 올바른 수정입니다.

getColor 함수가 배열 길이를 숫자로 받도록 업데이트됨에 따라, bgColors 배열 대신 bgColors.length를 전달하는 것이 올바릅니다. 이는 함수 시그니처와 일치하며 타입 안전성을 보장합니다.

src/app/features/dashboard_Id/type/Card.type.ts (1)

21-25: 페이지네이션을 위한 잘 구조화된 응답 타입입니다.

CardResponse 인터페이스는 카드 데이터와 페이지네이션 메타데이터를 포함한 표준적인 API 응답 구조를 제공합니다. cursorId를 통한 커서 기반 페이지네이션 지원이 적절합니다.

src/app/features/dashboard_Id/api/useCardMutation.ts (2)

4-4: feature 폴더 구조로의 리팩토링이 적절합니다.

전역 API 훅에서 feature별 로컬 타입으로 임포트 경로를 변경한 것은 모듈화와 코드 구조 개선에 도움이 됩니다.


78-79: 포맷팅 개선이 코드 가독성을 향상시킵니다.

clearDraggingCard() 호출 후 빈 줄 추가로 코드 블록 구분이 더 명확해졌습니다.

src/app/features/dashboard_Id/api/useMembers.ts (1)

7-12: 표준적인 React Query 패턴을 잘 따르는 훅입니다.

useMembers 훅은 적절한 쿼리 키 구조와 타입 안전성을 제공하며, fetchMembers 함수와의 통합이 올바르게 구현되었습니다.

src/app/features/dashboard_Id/api/useUploadCardImage.ts (1)

8-19: 포괄적인 에러 처리를 갖춘 잘 구현된 뮤테이션 훅입니다.

이미지 업로드 뮤테이션이 적절히 구현되었습니다:

  • 서버 에러 메시지 우선 사용 후 폴백 메시지 제공
  • toast를 통한 사용자 친화적 에러 피드백
  • postCardImages 함수와의 올바른 통합
src/app/features/dashboard_Id/api/fetchColumns.ts (1)

1-3: testAxios 사용 확인이 필요합니다.

실제 axios 대신 testAxios를 사용하고 있습니다. PR 목적에 따르면 testAxios.ts는 테스트용으로 나중에 삭제될 예정이라고 하는데, 프로덕션 코드에서 사용하는 것이 적절한지 확인이 필요합니다.

src/app/features/dashboard_Id/api/usePostCard.ts (1)

15-22: 에러 처리 로직이 잘 구현되었습니다.

axios 에러와 일반 에러를 구분하여 처리하고 있으며, 서버 응답 메시지를 적절히 추출하고 있습니다.

src/app/features/dashboard_Id/api/useColumns.ts (1)

7-10: 쿼리 구성이 적절합니다.

dashboardId를 포함한 쿼리 키 구성과 타입 정의가 올바르게 되어 있습니다.

src/app/features/dashboard_Id/type/Column.type.ts (1)

1-11: 타입 정의가 명확하고 잘 구조화되어 있습니다.

Column 인터페이스와 ColumnsResponse 인터페이스가 적절히 정의되어 있으며, API 응답 구조와 잘 매칭됩니다.

src/app/features/dashboard_Id/type/CardFormData.type.ts (1)

1-10: 타입 정의가 잘 되어 있습니다.

인터페이스 구조가 명확하고 옵셔널 필드들이 적절히 표시되어 있습니다. 다만 assigneeUserId가 필수 필드인데, 담당자를 지정하지 않는 경우는 어떻게 처리할 계획인지 확인이 필요합니다.

담당자 미지정 케이스 처리 방식 확인이 필요합니다.

src/app/features/dashboard_Id/Card/cardFormModals/input/Input.tsx (1)

15-28: 컴포넌트 구조 양호

입력 필드 래퍼로서 잘 구성되어 있습니다. accent 프롭을 통한 필수 필드 표시 기능도 유용합니다.

src/app/globals.css (2)

45-47: 새로운 텍스트 유틸리티 클래스 추가 양호

입력 필드를 위한 .Text-Input 클래스가 다크 모드를 포함하여 잘 구현되었습니다.


84-96: 입력 관련 유틸리티 클래스들 잘 구성됨

.BG-Input-hovered, .Input, .Input-readOnly 클래스들이 일관된 스타일링을 제공하며 다크 모드도 적절히 지원합니다. 읽기 전용 입력에서 캐럿을 숨기는 caret-transparent 설정도 좋습니다.

src/app/features/dashboard_Id/Card/Tags.tsx (2)

3-8: 색상 할당 로직 잘 구현됨

getColor 함수를 활용한 일관된 색상 할당이 잘 구현되었습니다. 배경색과 텍스트 색상 배열의 인덱스 매칭도 적절합니다.


9-29: 태그 렌더링 로직 양호

태그들이 적절한 스타일링과 함께 깔끔하게 렌더링됩니다. whitespace-nowrap을 통한 텍스트 줄바꿈 방지도 좋은 선택입니다.

src/app/dashboard/[id]/layout.tsx (1)

5-17: 기본 레이아웃 구조 양호

Header와 children을 포함한 기본적인 레이아웃 구조가 적절합니다. 향후 필요에 따라 브레드크럼이나 추가 네비게이션을 고려할 수 있습니다.

src/app/features/dashboard_Id/Card/Card.tsx (3)

6-6: 상대 import 경로로 변경이 적절합니다.

기존 절대 import 경로에서 상대 경로로 변경하여 feature-scoped 구조에 맞게 잘 리팩토링되었습니다.


20-20: data 속성 최적화가 좋습니다.

구조분해할당된 id 변수를 사용하여 card.id 대신 직접 참조하는 것이 더 효율적입니다.


50-73: 조건부 렌더링으로 UI 개선이 잘 되었습니다.

dueDateassignee가 존재할 때만 해당 섹션을 렌더링하도록 개선하여 빈 데이터로 인한 UI 문제를 방지했습니다. 한국어 주석도 코드 이해에 도움이 됩니다.

src/app/features/dashboard_Id/type/Member.type.ts (1)

1-14: 타입 정의가 명확하고 완전합니다.

MemberMembersResponse 인터페이스가 멤버 관리에 필요한 모든 필드를 포함하고 있으며, 명명 규칙도 일관성 있게 잘 정의되었습니다. profileImageUrlnull 가능하도록 정의된 것도 적절합니다.

src/app/features/dashboard_Id/Column/Column.tsx (5)

7-12: import 경로 리팩토링이 적절합니다.

절대 경로에서 상대 경로로 변경하여 feature-scoped 아키텍처에 맞게 잘 정리되었습니다.


31-32: 드래그 오버 성능 최적화가 우수합니다.

같은 컬럼 내에서의 드래그를 체크하여 불필요한 상태 업데이트를 방지하는 로직이 성능상 좋습니다.


41-44: 드롭 로직의 조기 반환이 효율적입니다.

드래그 중인 카드가 없거나 같은 컬럼에 드롭하는 경우 조기 반환하여 불필요한 API 호출을 방지하는 것이 좋습니다.


95-102: 모달 통합이 깔끔합니다.

CreateCardModalCreateCardForm 컴포넌트를 조건부로 렌더링하는 구조가 깔끔하고 명확합니다.


50-52: 스크립트에서 ts 타입만 지정되어 tsx 파일이 검색되지 않았습니다. .tsx 파일을 glob 패턴으로 지정해 드래그 이벤트 핸들링 패턴을 다시 확인해주세요.

#!/bin/bash
# .tsx 파일에서 onMouseUp, onDragEnd, onDrop 핸들러 패턴 재검색
rg -g '*.tsx' -A 10 -B 5 "onMouseUp|onDragEnd|onDrop"
src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx (2)

19-23: 컴포넌트 설명 주석이 유용합니다.

컴포넌트의 역할과 상태 관리 방식을 명확히 설명하는 주석이 코드 이해에 도움이 됩니다.


40-43: 이중 상태 관리가 적절합니다.

UI 표시용 assignee 객체와 form 제출용 userId를 분리하여 관리하는 방식이 명확하고 적절합니다.

src/app/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx (3)

189-198: 태그 입력 로직이 우수합니다.

Enter 키로 태그를 추가하고 중복을 방지하는 로직이 잘 구현되었습니다. trimEnd()trim() 사용으로 공백 처리도 적절합니다.


162-177: 날짜 선택기 통합이 깔끔합니다.

react-datepickerreact-hook-form의 Controller를 사용한 날짜 입력 구현이 잘 되어 있습니다. 시간 선택 기능도 포함되어 사용자 경험이 좋습니다.


63-76: 이미지 업로드 처리가 적절합니다.

비동기 이미지 업로드와 미리보기 기능이 잘 구현되었습니다. 성공 콜백에서 form state와 preview state를 모두 업데이트하는 것이 좋습니다.


export async function fetchMembers(dashboardId: number): Promise<Member[]> {
const res = await api.get<MembersResponse>(
`/${process.env.NEXT_PUBLIC_TEAM_ID}/members?&dashboardId=${dashboardId}`,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

쿼리 파라미터 형식을 수정해주세요.

URL에 불필요한 &가 있습니다. 첫 번째 파라미터이므로 ? 바로 다음에 파라미터 이름이 와야 합니다.

-    `/${process.env.NEXT_PUBLIC_TEAM_ID}/members?&dashboardId=${dashboardId}`,
+    `/${process.env.NEXT_PUBLIC_TEAM_ID}/members?dashboardId=${dashboardId}`,
📝 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
`/${process.env.NEXT_PUBLIC_TEAM_ID}/members?&dashboardId=${dashboardId}`,
`/${process.env.NEXT_PUBLIC_TEAM_ID}/members?dashboardId=${dashboardId}`,
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/api/fetchMembers.ts at line 8, remove the
unnecessary '&' character immediately following the '?' in the URL query string.
The query parameters should start directly after the '?' without an '&' since
this is the first parameter. Update the URL string to have the format
`?dashboardId=${dashboardId}` without the extra '&'.

Comment on lines +9 to +17
<input
ref={ref}
{...props}
inputMode="none"
readOnly
className="Input-readOnly"
id="dueDate"
placeholder="날짜와 시간을 선택하세요"
/>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

props 순서와 id 중복 문제를 해결해야 합니다.

현재 구현에서 두 가지 문제가 있습니다:

  1. {...props} 스프레드가 특정 props보다 먼저 오면서 중요한 속성들이 덮어쓰일 수 있습니다
  2. 하드코딩된 id="dueDate"로 인해 컴포넌트를 여러 번 사용할 때 DOM id 중복이 발생할 수 있습니다

다음과 같이 수정하는 것을 권장합니다:

-    <input
-      ref={ref}
-      {...props}
-      inputMode="none"
-      readOnly
-      className="Input-readOnly"
-      id="dueDate"
-      placeholder="날짜와 시간을 선택하세요"
-    />
+    <input
+      {...props}
+      ref={ref}
+      inputMode="none"
+      readOnly
+      className="Input-readOnly"
+      placeholder="날짜와 시간을 선택하세요"
+    />

id는 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
<input
ref={ref}
{...props}
inputMode="none"
readOnly
className="Input-readOnly"
id="dueDate"
placeholder="날짜와 시간을 선택하세요"
/>
<input
{...props}
ref={ref}
inputMode="none"
readOnly
className="Input-readOnly"
placeholder="날짜와 시간을 선택하세요"
/>
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/Card/cardFormModals/input/DateInput.tsx around
lines 9 to 17, the spread operator {...props} is placed before specific
attributes, which can cause important props to be overwritten, and the hardcoded
id="dueDate" can lead to duplicate DOM ids when the component is used multiple
times. To fix this, move {...props} after the specific attributes so that passed
props can override defaults, and remove the hardcoded id, instead accepting id
as a prop or managing it from the parent component.

Comment on lines +1 to +3
import api from '@/app/shared/lib/testAxios'

// import api from '@/app/shared/lib/axios'
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

프로덕션 환경에서 테스트용 axios 클라이언트를 사용하고 있습니다.

현재 testAxios를 사용하고 있는데, 이는 임시 파일로 명시되어 있습니다. 프로덕션 코드에서는 정식 axios 클라이언트를 사용해야 합니다.

주석 처리된 정식 axios import를 사용하는 것을 권장합니다:

-import api from '@/app/shared/lib/testAxios'
-
-// import api from '@/app/shared/lib/axios'
+import api from '@/app/shared/lib/axios'
📝 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
import api from '@/app/shared/lib/testAxios'
// import api from '@/app/shared/lib/axios'
import api from '@/app/shared/lib/axios'
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/api/postCard.ts at lines 1 to 3, replace the
import of the testAxios client with the production-ready axios client by
uncommenting the line importing from '@/app/shared/lib/axios' and commenting out
or removing the import from '@/app/shared/lib/testAxios'. This ensures the
production environment uses the correct axios instance.

Comment on lines +10 to +16
export async function postCard(payload: CardFormData): Promise<ApiResponse> {
const res = await api.post(
`/${process.env.NEXT_PUBLIC_TEAM_ID}/cards`,
payload,
)
return res.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. NEXT_PUBLIC_TEAM_ID 환경 변수의 존재 여부 검증
  2. API 요청 실패 시 에러 처리
  3. 응답 데이터 유효성 검증

다음과 같은 개선을 권장합니다:

export async function postCard(payload: CardFormData): Promise<ApiResponse> {
+  const teamId = process.env.NEXT_PUBLIC_TEAM_ID
+  if (!teamId) {
+    throw new Error('NEXT_PUBLIC_TEAM_ID 환경 변수가 설정되지 않았습니다.')
+  }
+  
+  try {
    const res = await api.post(
-     `/${process.env.NEXT_PUBLIC_TEAM_ID}/cards`,
+     `/${teamId}/cards`,
      payload,
    )
    return res.data
+  } catch (error) {
+    console.error('카드 생성 실패:', error)
+    throw error
+  }
}
📝 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 async function postCard(payload: CardFormData): Promise<ApiResponse> {
const res = await api.post(
`/${process.env.NEXT_PUBLIC_TEAM_ID}/cards`,
payload,
)
return res.data
}
export async function postCard(payload: CardFormData): Promise<ApiResponse> {
const teamId = process.env.NEXT_PUBLIC_TEAM_ID
if (!teamId) {
throw new Error('NEXT_PUBLIC_TEAM_ID 환경 변수가 설정되지 않았습니다.')
}
try {
const res = await api.post(
`/${teamId}/cards`,
payload,
)
return res.data
} catch (error) {
console.error('카드 생성 실패:', error)
throw error
}
}
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/api/postCard.ts around lines 10 to 16, the code
lacks validation for the NEXT_PUBLIC_TEAM_ID environment variable, error
handling for the API request, and response data validation. To fix this, first
check if NEXT_PUBLIC_TEAM_ID is defined and throw an error if not. Then, wrap
the API call in a try-catch block to handle request failures gracefully.
Finally, validate the structure or presence of expected fields in res.data
before returning it, throwing an error if validation fails.

Comment on lines +1 to +4
import api from '@/app/shared/lib/testAxios'

// import api from '@/app/shared/lib/axios'
import { CardResponse } from '../type/Card.type'
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

프로덕션 환경에서 테스트용 axios 클라이언트를 사용하고 있습니다.

postCard.ts와 동일한 문제로, 테스트용 axios 클라이언트 대신 정식 클라이언트를 사용해야 합니다.

-import api from '@/app/shared/lib/testAxios'
-
-// import api from '@/app/shared/lib/axios'
+import api from '@/app/shared/lib/axios'
📝 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
import api from '@/app/shared/lib/testAxios'
// import api from '@/app/shared/lib/axios'
import { CardResponse } from '../type/Card.type'
import api from '@/app/shared/lib/axios'
import { CardResponse } from '../type/Card.type'
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/api/fetchCards.ts at lines 1 to 4, the code
imports a test axios client instead of the production axios client. Replace the
import statement to use the official axios client by uncommenting the production
import line and removing the test client import to ensure the correct client is
used in production.

Comment on lines +14 to +16
const params = useParams()
const dashboardId = Number(params.id)
const { data: columns, isLoading, error } = useColumns(dashboardId)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

타입 안전성을 개선해주세요.

params.id가 undefined일 수 있고, Number() 변환 결과가 NaN일 수 있습니다. 타입 안전성을 위해 검증 로직을 추가해주세요.

  const params = useParams()
-  const dashboardId = Number(params.id)
+  const dashboardId = params.id ? Number(params.id) : null
+  
+  if (!dashboardId || isNaN(dashboardId)) {
+    return <div>잘못된 대시보드 ID입니다.</div>
+  }
+
  const { data: columns, isLoading, error } = useColumns(dashboardId)
📝 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 params = useParams()
const dashboardId = Number(params.id)
const { data: columns, isLoading, error } = useColumns(dashboardId)
const params = useParams()
const dashboardId = params.id ? Number(params.id) : null
if (!dashboardId || isNaN(dashboardId)) {
return <div>잘못된 대시보드 ID입니다.</div>
}
const { data: columns, isLoading, error } = useColumns(dashboardId)
🤖 Prompt for AI Agents
In src/app/dashboard/[id]/page.tsx around lines 14 to 16, the code directly
converts params.id to a number without checking if params.id is undefined or if
the conversion results in NaN, which can cause runtime errors. Add validation to
ensure params.id exists and is a valid number before using it; if invalid,
handle the case appropriately, such as showing an error or returning early to
maintain type safety.

@@ -0,0 +1,29 @@
import { cn } from '@/app/shared/lib/cn'
const mockData = ['aaa', 'bbb', 'ccc']
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

목 데이터를 실제 데이터로 교체 필요

하드코딩된 목 데이터 대신 실제 멤버 데이터를 사용해야 합니다. src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx에 있는 완전한 구현체를 참고하세요.

🤖 Prompt for AI Agents
In src/app/features/dashboardId/Card/cardFormModals/AssigneeList.tsx at line 2,
replace the hardcoded mockData array with the actual member data source. Refer
to the full implementation in
src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx to correctly
fetch and use real member data instead of static mock values.

Comment on lines +12 to +18
{mockData.map((Assignee, index) => (
<div
className={cn(
'BG-Input-hovered w-full cursor-pointer px-16 py-11 pt-14 placeholder-gray-400 caret-transparent',
index !== 0 && 'border-t',
)}
key={index}
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. 변수명 Assignee가 타입명과 혼동될 수 있습니다 (소문자 assignee 권장)
  2. 배열 인덱스를 키로 사용하는 것은 React 모범 사례에 어긋납니다
-      {mockData.map((Assignee, index) => (
+      {mockData.map((assignee, index) => (
         <div
           className={cn(
             'BG-Input-hovered w-full cursor-pointer px-16 py-11 pt-14 placeholder-gray-400 caret-transparent',
             index !== 0 && 'border-t',
           )}
-          key={index}
+          key={assignee}
           onClick={() => {
-            setSelectedAssignee(Assignee)
-            console.log(Assignee)
+            setSelectedAssignee(assignee)
           }}
         >
-          {Assignee}
+          {assignee}
         </div>
       ))}
📝 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
{mockData.map((Assignee, index) => (
<div
className={cn(
'BG-Input-hovered w-full cursor-pointer px-16 py-11 pt-14 placeholder-gray-400 caret-transparent',
index !== 0 && 'border-t',
)}
key={index}
{mockData.map((assignee, index) => (
<div
className={cn(
'BG-Input-hovered w-full cursor-pointer px-16 py-11 pt-14 placeholder-gray-400 caret-transparent',
index !== 0 && 'border-t',
)}
key={assignee}
onClick={() => {
setSelectedAssignee(assignee)
}}
>
{assignee}
</div>
))}
🤖 Prompt for AI Agents
In src/app/features/dashboardId/Card/cardFormModals/AssigneeList.tsx around
lines 12 to 18, rename the variable from `Assignee` to `assignee` to avoid
confusion with type names, and replace the use of the array index as the React
key with a unique and stable identifier from the `assignee` object, such as an
`id` property, to follow React best practices for list rendering.

Comment on lines +1 to +3
import Header from '@components/common/header/Header'

import Sidebar from '@/app/shared/components/common/sidebar/Sidebar'
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

import 경로 일관성 개선 필요

Header와 Sidebar의 import 경로가 일관되지 않습니다. 둘 다 같은 패턴을 사용하는 것이 좋습니다.

-import Header from '@components/common/header/Header'
-
-import Sidebar from '@/app/shared/components/common/sidebar/Sidebar'
+import Header from '@/app/shared/components/common/header/Header'
+import Sidebar from '@/app/shared/components/common/sidebar/Sidebar'
📝 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
import Header from '@components/common/header/Header'
import Sidebar from '@/app/shared/components/common/sidebar/Sidebar'
import Header from '@/app/shared/components/common/header/Header'
import Sidebar from '@/app/shared/components/common/sidebar/Sidebar'
🤖 Prompt for AI Agents
In src/app/dashboard/[id]/layout.tsx at lines 1 to 3, the import paths for
Header and Sidebar are inconsistent. Update the import statements so both use
the same path pattern, either both using '@components' or both using
'@/app/shared/components', to maintain consistency across the codebase.

Comment on lines +89 to +93
if (!data.dueDate) delete payload.dueDate
if (!data.imageUrl || !preview) delete payload.imageUrl // delete로 아예 필드의 해당 key를 지워야, 서버가 "없음"으로 인식함..
console.log('🌀', data.imageUrl)
console.log('submitted', payload)
createCard(payload)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

delete 연산자 성능 최적화가 필요합니다.

정적 분석 도구에서 지적한 대로 delete 연산자는 성능에 영향을 줄 수 있습니다. undefined 할당을 사용하는 것이 더 좋습니다.

다음과 같이 수정하세요:

-    if (!data.dueDate) delete payload.dueDate
-    if (!data.imageUrl || !preview) delete payload.imageUrl
+    if (!data.dueDate) payload.dueDate = undefined
+    if (!data.imageUrl || !preview) payload.imageUrl = undefined
📝 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
if (!data.dueDate) delete payload.dueDate
if (!data.imageUrl || !preview) delete payload.imageUrl // delete로 아예 필드의 해당 key를 지워야, 서버가 "없음"으로 인식함..
console.log('🌀', data.imageUrl)
console.log('submitted', payload)
createCard(payload)
if (!data.dueDate) payload.dueDate = undefined
if (!data.imageUrl || !preview) payload.imageUrl = undefined
console.log('🌀', data.imageUrl)
console.log('submitted', payload)
createCard(payload)
🧰 Tools
🪛 Biome (1.9.4)

[error] 92-92: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx around
lines 89 to 93, replace the delete operations on payload.dueDate and
payload.imageUrl with assignments to undefined to improve performance. Instead
of using 'delete payload.dueDate' and 'delete payload.imageUrl', set these
properties to undefined when the conditions are met, ensuring the server still
interprets the absence correctly while avoiding the performance cost of delete.

Copy link

@Insung-Jo Insung-Jo left a comment

Choose a reason for hiding this comment

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

모달 구현 수고 많으셨습니다!

Comment on lines +10 to +11
ref={ref}
{...props}
Copy link

@Insung-Jo Insung-Jo Jun 19, 2025

Choose a reason for hiding this comment

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

ref가 위에 있으면 아래에 있는 ...props 때문에 ref 값이 바뀔 수도 있으니 아래 처럼 배치해 주세요!

{...props}
ref={ref}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

앗 수정하겠습니다, 감사합니다!

Copy link
Contributor

Choose a reason for hiding this comment

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

저도 배워갑니당

Copy link

@LeeCh0129 LeeCh0129 left a comment

Choose a reason for hiding this comment

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

모달 구현 고생많으셨습니다~👍

@dkslel1225 dkslel1225 merged commit b9c5436 into feature/dashboard_id Jun 19, 2025
1 check passed
@coderabbitai coderabbitai bot mentioned this pull request Jun 19, 2025
3 tasks
Copy link
Contributor

@yuj2n yuj2n left a comment

Choose a reason for hiding this comment

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

지윤님 카드 생성 모달 구현 수고많으셨고 가능하면 중복되는 코드의 경우 공용으로 사용하면 좋을 것 같아용!!

"next": "14.2.25",
"next-themes": "^0.4.6",
"react": "18.2.0",
"react-datepicker": "^8.4.0",
Copy link
Contributor

Choose a reason for hiding this comment

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

date-picker 사용해주셨군용!

Comment on lines +10 to +11
ref={ref}
{...props}
Copy link
Contributor

Choose a reason for hiding this comment

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

저도 배워갑니당

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📁Chore 폴더 변경 또는 디렉토리 작업 ✨Feat 기능 개발 🐛Fix 버그 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants