Skip to content

Conversation

@dkslel1225
Copy link
Contributor

@dkslel1225 dkslel1225 commented Jun 21, 2025

📌 변경 사항 개요

✅ 디벨롭 브랜치에 병합은 작업 마무리되면 하겠습니다(아직 테스트API사용하고 있어서)

  • 카드 상세 모달 상단 - UI
  • 카드 상세 모달 하단 - 댓글 생성,수정,삭제
  • 카드 삭제 기능 추가
  • 모달 반응형 완성
  • 공통 컴포넌트 수정
    • Avatar에 flex-0클래스 추가: 모바일에서 플렉스박스 내에서 아바타가 찌그러지는 현상이 발생해서 추가함
    • useIsMobile 함수 추가
      • 화면 사이즈를 감지하여 불리언 값을 반환함
      • 모바일에서 프로필 아바타의 사이즈가 작아져야 하는 경우가 있어서, 화면 너비에 따라 다른 값을 아바타 컴포넌트에 전달하기 위해 만들었음

남은 작업 (필수)

  • 대시보드 상세 페이지 반응형
  • 무한스크롤
  • 🐛 수정 모달 - 변경한 컬럼 값이 폼이랑 연결 안되어있는듯
  • 🐛 카드 수정 모달에서, 드롭다운 선택지의 UI가 이상해졌음.. 수정 예정
  • 🐛 수정 모달 - 담당자 드롭다운의 placeholder에 조건 걸기. 그리고 다크모드일때 배경색 안맞음
  • 생성모달 - disabled상태에 대한 버튼 컬러 적용
  • 수정/생성모달-이미지수정 UI 적용(어둡게+연필)

남은 작업 (선택)

  • 카드 드래그 시 스크롤 방지, 드래그에 따라 자동 스크롤
  • 🐛 수정 모달 - 태그삭제만으로는 isDirtty로 안잡힘
  • 🐛 태그 - 특수문자 입력 제한하기
  • 🐛 태그 - 태그에 한글 입력시 글자 분리 현상. 영어만 허용하거나, 어떻게 해결해보기
  • 🐛 카드 본문 입력:250자까지 받기. 그 이상은 서버 에러남)

✨ 요약

📝 상세 내용

🔗 관련 이슈

🖼️ 스크린샷

카드 상세 모달

image

댓글

image

댓글 수정

image

✅ 체크리스트

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

💡 참고 사항

Summary by CodeRabbit

  • New Features

    • 카드 상세 모달에서 댓글 작성, 수정, 삭제 기능이 추가되었습니다.
    • 카드 상세 모달 내에서 카드 수정 및 삭제가 가능합니다.
    • 댓글 목록 조회 및 실시간 반영 기능이 추가되었습니다.
  • Bug Fixes

    • 카드 수정 폼에서 담당자가 없는 경우에도 오류 없이 동작하도록 개선되었습니다.
  • Style

    • 컬럼 제목이 한 줄로 표시되도록 스타일이 개선되었습니다.
    • 아바타 컴포넌트가 flex 컨테이너에서 크기가 줄어들지 않도록 수정되었습니다.
    • 다크 모드에서 구분선(border) 색상이 개선되었습니다.
    • 카드 상세 모달 레이아웃 및 반응형 스타일이 향상되었습니다.
  • Documentation

    • 댓글 및 카드 관련 타입 정의가 추가되었습니다.
  • Chores

    • 내부 API 타입 및 훅 구조가 개선되어 유지보수가 용이해졌습니다.

@coderabbitai
Copy link

coderabbitai bot commented Jun 21, 2025

"""

Walkthrough

이번 변경은 카드 상세 모달에 댓글(코멘트) 기능을 추가하고, 카드 수정/삭제 및 댓글 CRUD를 위한 API와 UI를 구현합니다. 카드 상세 모달 내에서 댓글 작성, 수정, 삭제가 가능해졌으며, 카드 수정 모달 호출 방식과 스타일, 타입 정의, 공통 훅 등이 추가 및 개선되었습니다.

Changes

파일/경로 그룹 변경 요약
Card.tsx, cardModal/CardContent.tsx, cardModal/CardModal.tsx, ColumnTitle.tsx 카드 상세 모달에 카드 수정 모달 연동, 댓글 컴포넌트 추가, 스타일 개선, 이벤트 핸들링 강화
cardFormModals/ModifyCardForm.tsx 카드 수정 폼의 초기값 안전성 보강, assignee 조건부 렌더링, 이벤트 전파 제어
cardModal/Comment.tsx, CommentForm.tsx, CommentModifyForm.tsx, Comments.tsx 댓글 목록, 작성, 수정, 삭제 컴포넌트 신설 및 연결
api/deleteCard.ts, api/deleteComment.ts, api/fetchComments.ts, api/postComment.ts, api/putComment.ts 카드/댓글 삭제, 댓글 목록 조회, 댓글 작성/수정 API 함수 신설
api/useCommentsQuery.ts, api/useDeleteCardMutation.ts, api/useDeleteCommentMutation.ts, api/usePostCommentMutation.ts, api/usePutCommentsMutation.ts 댓글 및 카드 관련 React Query 커스텀 훅 신설
api/putCard.ts, api/usePutCardMutation.ts ApiResponse 타입 외부 정의로 변경, 쿼리 무효화 키 수정
type/ApiResponse.ts, type/Comment.type.ts, type/CommentFormData.type.ts ApiResponse, 댓글, 댓글 폼 등 타입 정의 신설
shared/components/common/Avatar.tsx Avatar 컴포넌트 flexbox shrink 방지 클래스 추가
shared/hooks/useIsmobile.ts 모바일 환경 감지 커스텀 훅 신설
shared/hooks/useLockBodyScroll.ts 모달 활성 시 배경 스크롤 잠금 훅 신설
globals.css 다크 모드 테두리 색상 변경

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CardModal
    participant API
    participant Comments
    participant CommentForm
    participant Comment

    User->>CardModal: 카드 상세 모달 오픈
    CardModal->>Comments: 카드 ID로 댓글 목록 조회
    Comments->>API: fetchComments(cardId)
    API-->>Comments: 댓글 목록 반환
    Comments-->>CardModal: 댓글 목록 렌더링

    User->>CommentForm: 댓글 작성 입력 및 제출
    CommentForm->>API: postComment(payload)
    API-->>CommentForm: 작성 결과 반환
    CommentForm->>Comments: 쿼리 무효화 및 목록 갱신

    User->>Comment: 댓글 수정/삭제 버튼 클릭
    Comment->>API: putComment/deleteComment
    API-->>Comment: 결과 반환
    Comment->>Comments: 쿼리 무효화 및 목록 갱신
Loading

Possibly related PRs

  • CoPlay-FE/coplan#91: Card 컴포넌트와 CardContent에서 카드 수정 모달을 지원하도록 확장한 PR로, 본 PR의 카드 수정 모달 연동과 직접적으로 연결됩니다.
  • CoPlay-FE/coplan#95: Card 및 관련 모달 컴포넌트에서 카드 상세 및 수정 모달 상태 관리와 column 객체 전달 구조를 개선한 PR로, 본 PR과 강한 코드 레벨 연관성이 있습니다.

Suggested labels

🐛Fix, 🎨Style

Suggested reviewers

  • LeeCh0129
  • Insung-Jo

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-21T15_04_19_830Z-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 self-assigned this Jun 21, 2025
@dkslel1225 dkslel1225 added the ✨Feat 기능 개발 label Jun 21, 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: 15

🔭 Outside diff range comments (1)
src/app/features/dashboard_Id/Card/cardModal/CardContentCopy.tsx (1)

1-111: 사용하지 않는 파일 삭제 권장

이 파일은 전체가 주석 처리되어 있어 실제로 사용되지 않습니다. 코드베이스의 깔끔한 관리를 위해 이 파일을 삭제하는 것을 권장합니다. 필요시 git 히스토리에서 복원할 수 있습니다.

🧹 Nitpick comments (17)
src/app/features/dashboard_Id/type/ApiResponse.ts (1)

1-3: API 응답 타입 정의가 적절하게 구현되었습니다.

공통 타입 정의로 코드 재사용성이 향상됩니다. 향후 다양한 응답 구조가 필요한 경우 제네릭 타입 사용을 고려해보세요.

+export interface ApiResponse<T = string> {
+  message: T
+}
src/app/features/dashboard_Id/api/deleteComment.ts (1)

6-11: 에러 처리 추가를 고려해보세요.

API 함수에 적절한 에러 처리를 추가하면 더 견고한 코드가 됩니다.

export async function deleteComment(commentId: number): Promise<ApiResponse> {
+  try {
    const res = await api.delete(
      `/${process.env.NEXT_PUBLIC_TEAM_ID}/comments/${commentId}`,
    )
    return res.data
+  } catch (error) {
+    console.error('댓글 삭제 중 오류 발생:', error)
+    throw error
+  }
}
src/app/features/dashboard_Id/api/usePutCardMutation.ts (1)

8-8: 주석이 부정확합니다.

주석에서 CreateCardForm.tsx를 언급하고 있지만, 이 훅은 카드 수정용이므로 ModifyCardForm.tsx가 더 정확할 것 같습니다.

-// ✅ 카드 수정 모달에서 사용 (CreateCardForm.tsx)
+// ✅ 카드 수정 모달에서 사용 (ModifyCardForm.tsx)
src/app/features/dashboard_Id/api/deleteCard.ts (1)

6-11: 매개변수 유효성 검사 및 에러 처리 추가 권장

cardId 매개변수에 대한 유효성 검사와 API 호출 실패 시 에러 처리를 추가하는 것을 권장합니다.

export async function deleteCard(cardId: number): Promise<ApiResponse> {
+  if (!cardId || cardId <= 0) {
+    throw new Error('유효하지 않은 cardId입니다.')
+  }
+
+  try {
    const res = await api.delete(
      `/${process.env.NEXT_PUBLIC_TEAM_ID}/cards/${cardId}`,
    )
    return res.data
+  } catch (error) {
+    console.error('카드 삭제 실패:', error)
+    throw error
+  }
}
src/app/features/dashboard_Id/api/usePutCommentsMutation.ts (1)

12-12: 잘못된 주석 수정 필요

주석이 실제 사용처와 일치하지 않습니다. 이 훅은 댓글 수정에 사용되는 것으로 보입니다.

-// ✅ 카드 생성 모달에서 사용 (CreateCardForm.tsx)
+// ✅ 댓글 수정 시 사용 (CommentModifyForm.tsx)
src/app/features/dashboard_Id/api/fetchComments.ts (1)

11-13: 페이지 크기를 매개변수로 분리하고 에러 처리 추가 권장

하드코딩된 size=10을 매개변수로 분리하고 에러 처리를 추가하는 것을 권장합니다.

-export async function fetchComments(cardId: number): Promise<CommentsResponse> {
+export async function fetchComments(
+  cardId: number, 
+  size: number = 10
+): Promise<CommentsResponse> {
  if (!cardId || cardId <= 0) {
    throw new Error('cardId가 유효하지 않습니다.')
  }

+  try {
    const res = await api.get<CommentsResponse>(
-     `/${process.env.NEXT_PUBLIC_TEAM_ID}/comments?size=10&cardId=${cardId}`,
+     `/${process.env.NEXT_PUBLIC_TEAM_ID}/comments?size=${size}&cardId=${cardId}`,
    )
    return res.data
+  } catch (error) {
+    console.error('댓글 조회 실패:', error)
+    throw error
+  }
}
src/app/features/dashboard_Id/Card/cardModal/CardModal.tsx (1)

12-12: 반응형 스타일링 개선사항과 잠재적 문제점

반응형 디자인 추가는 좋은 개선이지만 몇 가지 문제점이 있습니다:

  1. max-h-764 min-h-764는 고정 높이를 만들어 반응형 디자인에 적합하지 않을 수 있습니다
  2. overflow-auto overflow-y-scroll는 중복입니다 - overflow-auto만으로 충분합니다
  3. mask-image 속성이 모달에 필요한지 확인이 필요합니다

다음과 같이 개선을 고려해보세요:

-<div className="BG-white relative max-h-764 min-h-764 w-730 overflow-auto overflow-y-scroll rounded-16 px-18 py-30 shadow-lg [mask-image:radial-gradient(white_100%,transparent_100%)] mobile:w-327 mobile:p-16 tablet:w-678 tablet:px-32 tablet:py-24">
+<div className="BG-white relative max-h-[90vh] w-730 overflow-auto rounded-16 px-18 py-30 shadow-lg mobile:w-327 mobile:p-16 tablet:w-678 tablet:px-32 tablet:py-24">
src/app/features/dashboard_Id/Card/cardModal/Comments.tsx (3)

1-2: 사용되지 않는 import 제거 필요

formatuseState가 import되었지만 실제로는 사용되지 않습니다.

-import { format } from 'date-fns'
-import { useState } from 'react'

4-4: 사용되지 않는 Avatar import 제거

Avatar 컴포넌트가 import되었지만 사용되지 않습니다.

-import { Avatar } from '@/app/shared/components/common/Avatar'

18-18: 반응형 디자인 고려

고정 너비 (w-450) 대신 반응형 너비를 사용하는 것을 고려해보세요.

-    <div className="flex w-450 flex-col gap-20">
+    <div className="flex w-full max-w-450 flex-col gap-20">
src/app/features/dashboard_Id/Card/Card.tsx (1)

99-109: 주석 처리된 코드를 제거해주세요.

104번 줄의 주석 처리된 columnId={column.id} 코드는 더 이상 필요하지 않다면 제거하는 것이 좋습니다.

-            // columnId={column.id}
src/app/features/dashboard_Id/Card/cardModal/CommentForm.tsx (1)

27-37: console.log 구문을 제거해주세요.

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

   function onSubmit(data: CommentFormData) {
     const payload = {
       ...data,
       cardId,
       columnId,
       dashboardId,
     }
-    console.log(payload)
     createComment(payload)
     reset()
   }
src/app/features/dashboard_Id/Card/cardModal/Comment.tsx (1)

17-17: 불필요한 key prop을 제거해주세요.

이 div는 배열에서 렌더링되는 것이 아니므로 key prop이 불필요합니다. key는 상위 컴포넌트에서 Comment 컴포넌트를 렌더링할 때 추가해야 합니다.

-    <div key={comment.id} className="flex gap-10 mobile:gap-8 tablet:gap-12">
+    <div className="flex gap-10 mobile:gap-8 tablet:gap-12">
src/app/features/dashboard_Id/Card/cardModal/CommentModifyForm.tsx (2)

29-34: console.log 구문들을 제거해주세요.

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

   function onSubmit(data: PutCommentForm) {
-    console.log(data)
-    console.log(commentId)
     createComment({ payload: data, commentId })
     onClose()
   }

47-47: placeholder 로직을 단순화할 수 있습니다.

content가 이미 defaultValues로 설정되어 있으므로 placeholder 조건부 로직이 불필요합니다.

-        placeholder={content ? content : '댓글 작성하기'}
+        placeholder="댓글 작성하기"
src/app/features/dashboard_Id/Card/cardModal/CardContent.tsx (2)

29-32: 사용하지 않는 코드 제거

주석 처리된 코드와 사용하지 않는 openModifyCard 상태를 제거해주세요:

-// const { id, imageUrl, title, tags, dueDate, assignee, description } = card
-const [openModifyCard, setOpenModifyCard] = useState(false)
-// const { title: columnTitle, id: columnId } = column
-// const currentColumn = { columnTitle, columnId }

174-174: 빈 div 태그 제거

의미 없는 빈 div 태그를 제거해주세요.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0c2a7fc and 1363449.

📒 Files selected for processing (28)
  • src/app/features/dashboard_Id/Card/Card.tsx (3 hunks)
  • src/app/features/dashboard_Id/Card/ColumnTitle.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardFormModals/ModifyCardForm.tsx (3 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/CardContent.tsx (2 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/CardContentCopy.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/CardModal.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/Comment.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/CommentForm.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/CommentModifyForm.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/Comments.tsx (1 hunks)
  • src/app/features/dashboard_Id/api/deleteCard.ts (1 hunks)
  • src/app/features/dashboard_Id/api/deleteComment.ts (1 hunks)
  • src/app/features/dashboard_Id/api/fetchComments.ts (1 hunks)
  • src/app/features/dashboard_Id/api/postComment.ts (1 hunks)
  • src/app/features/dashboard_Id/api/putCard.ts (1 hunks)
  • src/app/features/dashboard_Id/api/putComment.ts (1 hunks)
  • src/app/features/dashboard_Id/api/useCommentsQuery.ts (1 hunks)
  • src/app/features/dashboard_Id/api/useDeleteCardMutation.ts (1 hunks)
  • src/app/features/dashboard_Id/api/useDeleteCommentMutation.ts (1 hunks)
  • src/app/features/dashboard_Id/api/usePostCommentMutation.ts (1 hunks)
  • src/app/features/dashboard_Id/api/usePutCardMutation.ts (2 hunks)
  • src/app/features/dashboard_Id/api/usePutCommentsMutation.ts (1 hunks)
  • src/app/features/dashboard_Id/type/ApiResponse.ts (1 hunks)
  • src/app/features/dashboard_Id/type/Comment.type.ts (1 hunks)
  • src/app/features/dashboard_Id/type/CommentFormData.type.ts (1 hunks)
  • src/app/globals.css (1 hunks)
  • src/app/shared/components/common/Avatar.tsx (2 hunks)
  • src/app/shared/hooks/useIsmobile.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (15)
src/app/features/dashboard_Id/api/useDeleteCardMutation.ts (1)
src/app/features/dashboard_Id/api/deleteCard.ts (1)
  • deleteCard (6-11)
src/app/features/dashboard_Id/api/postComment.ts (1)
src/app/features/dashboard_Id/type/CommentFormData.type.ts (2)
  • PutCommentForm (18-20)
  • CommentResponse (9-16)
src/app/features/dashboard_Id/api/deleteComment.ts (1)
src/app/features/dashboard_Id/type/ApiResponse.ts (1)
  • ApiResponse (1-3)
src/app/features/dashboard_Id/api/usePutCommentsMutation.ts (2)
src/app/features/dashboard_Id/type/CommentFormData.type.ts (2)
  • PutCommentForm (18-20)
  • CommentResponse (9-16)
src/app/features/dashboard_Id/api/putComment.ts (1)
  • putComment (6-15)
src/app/features/dashboard_Id/api/usePostCommentMutation.ts (1)
src/app/features/dashboard_Id/api/postComment.ts (1)
  • postComment (6-14)
src/app/features/dashboard_Id/api/deleteCard.ts (1)
src/app/features/dashboard_Id/type/ApiResponse.ts (1)
  • ApiResponse (1-3)
src/app/features/dashboard_Id/api/useDeleteCommentMutation.ts (1)
src/app/features/dashboard_Id/api/deleteComment.ts (1)
  • deleteComment (6-11)
src/app/features/dashboard_Id/Card/cardFormModals/ModifyCardForm.tsx (1)
src/app/features/dashboard_Id/Card/MyAssignee.tsx (1)
  • MyAssignee (5-18)
src/app/features/dashboard_Id/api/useCommentsQuery.ts (2)
src/app/features/dashboard_Id/type/Comment.type.ts (1)
  • CommentsResponse (14-17)
src/app/features/dashboard_Id/api/fetchComments.ts (1)
  • fetchComments (6-16)
src/app/features/dashboard_Id/Card/cardModal/CommentForm.tsx (2)
src/app/features/dashboard_Id/type/CommentFormData.type.ts (1)
  • CommentFormData (3-8)
src/app/features/dashboard_Id/api/usePostCommentMutation.ts (1)
  • usePostCommentMutation (7-24)
src/app/features/dashboard_Id/api/fetchComments.ts (1)
src/app/features/dashboard_Id/type/Comment.type.ts (1)
  • CommentsResponse (14-17)
src/app/features/dashboard_Id/Card/Card.tsx (3)
src/app/features/dashboard_Id/Card/cardModal/CardModal.tsx (1)
  • CardModal (6-18)
src/app/features/dashboard_Id/Card/cardFormModals/CreateCardModal.tsx (1)
  • CreateCardModal (6-18)
src/app/features/dashboard_Id/Card/cardFormModals/ModifyCardForm.tsx (1)
  • ModifyCardForm (29-371)
src/app/features/dashboard_Id/type/Comment.type.ts (1)
src/app/features/dashboard_Id/Card/cardModal/Comment.tsx (1)
  • Comment (11-58)
src/app/features/dashboard_Id/api/putComment.ts (1)
src/app/features/dashboard_Id/type/CommentFormData.type.ts (2)
  • PutCommentForm (18-20)
  • CommentResponse (9-16)
src/app/features/dashboard_Id/type/CommentFormData.type.ts (1)
src/app/features/dashboard_Id/type/Comment.type.ts (1)
  • Auth (1-5)
🔇 Additional comments (26)
src/app/features/dashboard_Id/Card/ColumnTitle.tsx (1)

5-5: 모달 레이아웃 개선을 위한 적절한 스타일링 변경입니다.

whitespace-nowrap 클래스 추가로 카드 모달 내에서 컬럼 제목이 한 줄로 유지되어 UI 일관성이 향상됩니다.

src/app/globals.css (1)

73-73: 다크모드 UI 개선을 위한 적절한 색상 조정입니다.

순수 검정색에서 중간 회색(#454545)으로 변경하여 다크모드에서 더 나은 시각적 경험과 접근성을 제공합니다.

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

1-3: 테스트용 Axios 인스턴스 사용을 확인해주세요.

현재 testAxios를 사용하고 프로덕션용 axios는 주석 처리되어 있습니다. 의도적인 변경인지 확인이 필요합니다.

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

21-21: 쿼리 키 변경이 적절합니다.

['cardId']에서 ['columnId']로 변경한 것은 다른 카드 관련 뮤테이션 훅들과의 일관성을 위해 좋은 개선입니다. 카드 수정 후 해당 컬럼의 전체 카드 목록을 갱신하는 것이 올바른 접근입니다.

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

54-54: flex 레이아웃 안정성 개선이 좋습니다.

두 렌더링 분기 모두에 shrink-0 클래스를 추가한 것은 flex 컨테이너 내에서 아바타가 축소되는 것을 방지하여 레이아웃 안정성을 크게 개선합니다. 반응형 디자인과 카드 모달의 UI 일관성에 도움이 될 것입니다.

Also applies to: 66-66

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

5-17: 카드 삭제 뮤테이션 훅 구현이 적절합니다.

React Query의 표준 패턴을 잘 따르고 있으며, 성공 시 ['columnId'] 캐시를 무효화하는 것이 다른 카드 관련 뮤테이션 훅들과 일관성을 유지합니다. 에러 핸들링도 간단하고 명확합니다.

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

5-17: 댓글 삭제 뮤테이션 훅 구현이 일관성 있습니다.

카드 삭제 훅과 동일한 패턴을 따르고 있어 코드베이스의 일관성을 유지합니다. ['comments'] 캐시 무효화를 통해 댓글 목록이 즉시 업데이트되도록 하는 것이 적절합니다.

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

7-24: 댓글 생성 뮤테이션 훅이 잘 구현되었습니다.

다른 뮤테이션 훅들보다 더 상세한 에러 핸들링을 제공하여 Axios 에러와 일반 에러를 구분해서 처리하는 것이 좋습니다. postComment를 직접 mutationFn으로 사용하는 것도 간결하고 효율적입니다.

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

18-29: 에러 처리 및 캐시 무효화 로직 승인

성공 시 comments 쿼리 캐시 무효화와 Axios 에러 처리 로직이 잘 구현되어 있습니다.

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

4-4: 타입 이름 일관성 확인 필요

POST 요청에 PutCommentForm 타입을 사용하고 있습니다. 댓글 생성과 수정에 동일한 구조를 사용하는 것이 의도된 것인지 확인이 필요합니다. 명확성을 위해 더 일반적인 이름을 고려해보세요.

다음 스크립트로 타입 사용 현황을 확인해보겠습니다:

#!/bin/bash
# 댓글 관련 타입 사용 현황 확인
echo "=== PutCommentForm 타입 사용 현황 ==="
rg -A 3 -B 3 "PutCommentForm"

echo -e "\n=== 댓글 관련 다른 타입들 ==="
rg -A 3 -B 3 "CommentForm|PostComment"

6-14: ```shell
#!/bin/bash

전체 리포지토리에서 PutCommentForm 타입 정의 검색

echo "=== Searching for PutCommentForm across repo ==="
rg -n "PutCommentForm"

echo -e "\n=== CommentFormData.type.ts 파일 내용 확인 ==="
fd "CommentFormData.type.ts" --type f --exec sed -n '1,200p' {}


</details>
<details>
<summary>src/app/features/dashboard_Id/api/putComment.ts (1)</summary>

`6-15`: **API 함수 구조 승인**

함수의 매개변수 구조와 API 호출 방식이 명확하고 올바르게 구현되어 있습니다. PUT 요청에 적합한 구조입니다.

</details>
<details>
<summary>src/app/features/dashboard_Id/api/putCard.ts (1)</summary>

`3-3`: **타입 중앙화 개선사항 승인**

`ApiResponse` 타입을 외부 모듈로 분리하여 타입 일관성을 향상시킨 좋은 리팩토링입니다. 코드 중복을 줄이고 타입 관리를 개선합니다.

</details>
<details>
<summary>src/app/features/dashboard_Id/api/useCommentsQuery.ts (1)</summary>

`6-11`: **React Query 훅 구현 승인**

댓글 데이터를 가져오는 커스텀 훅이 올바르게 구현되었습니다:
- 적절한 쿼리 키 구조 (`['comments', cardId]`)
- 타입 안전성 보장
- React Query 모범 사례 준수

</details>
<details>
<summary>src/app/features/dashboard_Id/Card/cardFormModals/ModifyCardForm.tsx (4)</summary>

`66-66`: **안전한 속성 접근 개선 승인**

`card.assignee?.id`로 옵셔널 체이닝을 사용하여 undefined 에러를 방지하는 좋은 개선입니다.

---

`71-73`: **폼 필드 기본값 처리 개선**

falsy 값에 대한 적절한 fallback 처리로 폼 초기화를 개선했습니다.

---

`127-131`: **이벤트 전파 방지 처리 승인**

`stopPropagation`을 통한 이벤트 버블링 방지로 모달 외부 클릭 동작을 올바르게 처리했습니다.

---

`194-198`: **조건부 렌더링 개선 승인**

`selectedAssignee`가 존재할 때만 `MyAssignee` 컴포넌트를 렌더링하는 안전한 조건부 렌더링입니다.

</details>
<details>
<summary>src/app/features/dashboard_Id/Card/Card.tsx (3)</summary>

`9-10`: **새로운 import 구문이 올바르게 추가되었습니다.**

모달과 폼 컴포넌트 import가 적절하게 구성되어 있습니다.

---

`25-27`: **새로운 state와 currentColumn 객체 생성이 적절합니다.**

카드 수정 모달의 상태 관리와 컬럼 정보 추출이 올바르게 구현되었습니다.

---

`92-92`: **CardContent에 openModifyModal prop 추가가 올바릅니다.**

모달 열기 콜백이 적절하게 전달되고 있습니다.

</details>
<details>
<summary>src/app/features/dashboard_Id/type/Comment.type.ts (1)</summary>

`14-17`: **CommentsResponse 인터페이스가 올바르게 정의되었습니다.**

페이지네이션을 위한 구조가 적절하게 구성되어 있습니다.

</details>
<details>
<summary>src/app/features/dashboard_Id/Card/cardModal/CommentForm.tsx (1)</summary>

`40-68`: **폼 UI와 검증 로직이 잘 구현되었습니다.**

반응형 스타일링과 폼 검증이 적절하게 구성되어 있습니다.

</details>
<details>
<summary>src/app/features/dashboard_Id/Card/cardModal/Comment.tsx (2)</summary>

`18-30`: **반응형 아바타 크기 조정이 잘 구현되었습니다.**

모바일과 데스크톱에서 다른 아바타 크기를 적용하는 로직이 적절합니다.

---

`40-54`: **댓글 수정/삭제 기능이 올바르게 구현되었습니다.**

조건부 렌더링과 상태 관리가 적절하게 구성되어 있습니다.

</details>
<details>
<summary>src/app/features/dashboard_Id/type/CommentFormData.type.ts (1)</summary>

`12-13`: **타임스탬프 타입 확인 필요**

`createdAt`과 `updatedAt`이 `number` 타입으로 정의되어 있습니다. 일반적으로 타임스탬프는 ISO 문자열이나 Date 타입을 사용합니다. Unix 타임스탬프를 사용하는 것이 의도된 것인지 확인이 필요합니다.


```shell
#!/bin/bash
# Description: API 응답에서 타임스탬프 필드의 실제 타입 확인

# postComment, putComment API 파일에서 응답 타입 확인
rg -A 10 "createdAt|updatedAt" --glob "*.ts" --glob "*.tsx"

@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 2025
@CoPlay-FE CoPlay-FE deleted a comment from coderabbitai bot Jun 21, 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: 2

🧹 Nitpick comments (3)
src/app/shared/hooks/useLockBodyScroll.ts (1)

7-16: 모달 스크롤 잠금 훅 구현이 잘 되었습니다만, 몇 가지 개선사항을 제안합니다.

현재 구현은 기본적으로 올바르게 작동하지만 다음과 같은 개선이 필요합니다:

  1. getComputedStyle보다는 직접 document.body.style.overflow 값을 저장하는 것이 더 안전합니다.
  2. 여러 모달이 동시에 열릴 때를 대비한 참조 카운팅이 필요할 수 있습니다.

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

export function useLockBodyScroll() {
  useEffect(() => {
-   const originalStyle = window.getComputedStyle(document.body).overflow
+   const originalStyle = document.body.style.overflow
    document.body.style.overflow = 'hidden'

    return () => {
      document.body.style.overflow = originalStyle
    }
  }, [])
}
src/app/features/dashboard_Id/api/useUploadCardImage.ts (1)

16-19: 사용되지 않는 코드를 제거해주세요.

message 변수가 더 이상 사용되지 않으므로 제거하는 것이 좋겠습니다.

다음과 같이 수정하세요:

    onError: (error: AxiosError<{ message: string }>) => {
      toast.error(
        '이미지 업로드 중 오류가 발생했습니다. 크기가 작은 파일을 시도해주세요.',
      )
-     const message =
-       error?.response?.data?.message ?? // 서버가 준 에러메세지
-       '이미지 업로드 중 오류가 발생했습니다. 크기가 작은 파일을 시도해주세요.' // 없으면 이 내용으로
    },
src/app/features/dashboard_Id/Card/cardModal/Comments.tsx (1)

1-2: 사용하지 않는 임포트를 제거하세요.

formatuseState가 임포트되었지만 이 컴포넌트에서 사용되지 않습니다.

-import { format } from 'date-fns'
-import { useState } from 'react'
import { toast } from 'sonner'
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1363449 and 1e0becf.

📒 Files selected for processing (14)
  • src/app/features/dashboard_Id/Card/cardFormModals/CreateCardModal.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/CardContent.tsx (2 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/CardModal.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/CommentModifyForm.tsx (1 hunks)
  • src/app/features/dashboard_Id/Card/cardModal/Comments.tsx (1 hunks)
  • src/app/features/dashboard_Id/api/fetchComments.ts (1 hunks)
  • src/app/features/dashboard_Id/api/useDeleteCardMutation.ts (1 hunks)
  • src/app/features/dashboard_Id/api/usePostCard.ts (2 hunks)
  • src/app/features/dashboard_Id/api/usePutCardMutation.ts (2 hunks)
  • src/app/features/dashboard_Id/api/usePutCommentsMutation.ts (1 hunks)
  • src/app/features/dashboard_Id/api/useUploadCardImage.ts (1 hunks)
  • src/app/features/dashboard_Id/type/Comment.type.ts (1 hunks)
  • src/app/shared/hooks/useIsmobile.ts (1 hunks)
  • src/app/shared/hooks/useLockBodyScroll.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/app/features/dashboard_Id/api/usePutCommentsMutation.ts
  • src/app/features/dashboard_Id/api/fetchComments.ts
  • src/app/features/dashboard_Id/api/useDeleteCardMutation.ts
  • src/app/shared/hooks/useIsmobile.ts
  • src/app/features/dashboard_Id/Card/cardModal/CardModal.tsx
  • src/app/features/dashboard_Id/api/usePutCardMutation.ts
  • src/app/features/dashboard_Id/type/Comment.type.ts
  • src/app/features/dashboard_Id/Card/cardModal/CommentModifyForm.tsx
  • src/app/features/dashboard_Id/Card/cardModal/CardContent.tsx
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/app/features/dashboard_Id/Card/cardFormModals/CreateCardModal.tsx (1)
src/app/shared/hooks/useLockBodyScroll.ts (1)
  • useLockBodyScroll (7-16)
src/app/features/dashboard_Id/Card/cardModal/Comments.tsx (3)
src/app/features/dashboard_Id/api/useCommentsQuery.ts (1)
  • useCommentsQuery (6-11)
src/app/features/dashboard_Id/type/Comment.type.ts (1)
  • Comment (6-13)
src/app/features/dashboard_Id/Card/cardModal/Comment.tsx (1)
  • Comment (11-58)
🔇 Additional comments (6)
src/app/features/dashboard_Id/api/usePostCard.ts (3)

3-3: 토스트 알림 추가가 잘 구현되었습니다.

사용자 피드백을 위한 토스트 알림이 적절히 추가되었습니다.


14-14: 성공 메시지가 명확하고 적절합니다.

"할 일이 추가되었습니다." 메시지는 사용자에게 명확한 피드백을 제공합니다.


18-19: 에러 처리 개선이 잘 되었습니다.

기존 에러 로깅 로직을 유지하면서 사용자에게 즉각적인 피드백을 제공하도록 개선되었습니다.

src/app/features/dashboard_Id/Card/cardFormModals/CreateCardModal.tsx (2)

3-3: 스크롤 잠금 훅 import가 올바르게 추가되었습니다.

새로 생성된 useLockBodyScroll 훅을 적절히 import했습니다.


11-11: 훅 사용법이 정확합니다.

모달 컴포넌트에서 useLockBodyScroll()을 무조건적으로 호출하는 것이 올바른 사용법입니다.

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

13-15: 사용자 친화적인 에러 메시지로 개선되었습니다.

고정된 에러 메시지가 사용자에게 더 명확한 안내를 제공합니다.

Comment on lines +12 to +17
const { data, isLoading, error } = useCommentsQuery(cardId)
const comments = data?.comments

if (error) {
toast.error(error?.message || '문제가 발생했습니다.')
}
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. isLoading 상태를 추출했지만 로딩 UI를 제공하지 않습니다
  2. 에러가 발생했을 때도 컴포넌트가 계속 렌더링되어 혼란을 줄 수 있습니다
export default function Comments({ cardId }: { cardId: number }) {
  const { data, isLoading, error } = useCommentsQuery(cardId)
  const comments = data?.comments

  if (error) {
    toast.error(error?.message || '문제가 발생했습니다.')
+    return <div className="Text-gray-light text-14">댓글을 불러올 수 없습니다.</div>
  }
+
+  if (isLoading) {
+    return <div className="Text-gray-light text-14">댓글을 불러오는 중...</div>
+  }
+
  return (
📝 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 { data, isLoading, error } = useCommentsQuery(cardId)
const comments = data?.comments
if (error) {
toast.error(error?.message || '문제가 발생했습니다.')
}
export default function Comments({ cardId }: { cardId: number }) {
const { data, isLoading, error } = useCommentsQuery(cardId)
const comments = data?.comments
if (error) {
toast.error(error?.message || '문제가 발생했습니다.')
return <div className="Text-gray-light text-14">댓글을 불러올 수 없습니다.</div>
}
if (isLoading) {
return <div className="Text-gray-light text-14">댓글을 불러오는 중...</div>
}
return (
// …rest of your rendering logic
)
}
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/Card/cardModal/Comments.tsx around lines 12 to
17, the component extracts isLoading but does not show any loading UI, and it
continues rendering even when there is an error, which can confuse users. To fix
this, add a conditional rendering block that displays a loading indicator when
isLoading is true, and render an error message or return null to prevent the
rest of the component from rendering when error exists after showing the toast
notification.

Comment on lines +19 to +24
<div className="flex w-450 flex-col gap-20">
{comments?.map((comment: CommentType) => (
<Comment key={comment.id} comment={comment} />
))}
</div>
)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

반응형 디자인과 빈 상태 처리를 개선하세요.

현재 구현의 개선점:

  1. w-450 고정 너비가 모바일에서 문제가 될 수 있습니다
  2. 댓글이 없을 때의 상태를 처리하지 않습니다
  return (
-    <div className="flex w-450 flex-col gap-20">
+    <div className="flex w-full max-w-450 flex-col gap-20">
      {comments?.map((comment: CommentType) => (
        <Comment key={comment.id} comment={comment} />
      ))}
+      {comments?.length === 0 && (
+        <div className="Text-gray-light text-14">첫 번째 댓글을 작성해보세요!</div>
+      )}
    </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
<div className="flex w-450 flex-col gap-20">
{comments?.map((comment: CommentType) => (
<Comment key={comment.id} comment={comment} />
))}
</div>
)
return (
<div className="flex w-full max-w-450 flex-col gap-20">
{comments?.map((comment: CommentType) => (
<Comment key={comment.id} comment={comment} />
))}
{comments?.length === 0 && (
<div className="Text-gray-light text-14">첫 번째 댓글을 작성해보세요!</div>
)}
</div>
)
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/Card/cardModal/Comments.tsx around lines 19 to
24, the fixed width class 'w-450' can cause layout issues on mobile devices and
there is no handling for the empty comments state. Replace the fixed width with
a responsive width class or use relative sizing to improve mobile compatibility.
Additionally, add conditional rendering to display a user-friendly message or
placeholder when the comments array is empty or undefined.

@dkslel1225 dkslel1225 merged commit 1f2b585 into feature/dashboard_id Jun 21, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨Feat 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants