-
Notifications
You must be signed in to change notification settings - Fork 2
✨ Feat: 카드 상세 모달 구현 #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ Feat: 카드 상세 모달 구현 #99
Conversation
📝 TODO: - 담당자 옆 아바타에 반응형 사이즈 적용 필요 - 카드 수정 모달의 컬럼 선택 값을 form 데이터와 연결 필요
…board_id-CardModal
|
""" Walkthrough이번 변경은 카드 상세 모달에 댓글(코멘트) 기능을 추가하고, 카드 수정/삭제 및 댓글 CRUD를 위한 API와 UI를 구현합니다. 카드 상세 모달 내에서 댓글 작성, 수정, 삭제가 가능해졌으며, 카드 수정 모달 호출 방식과 스타일, 타입 정의, 공통 훅 등이 추가 및 개선되었습니다. Changes
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: 쿼리 무효화 및 목록 갱신
Possibly related PRs
Suggested labels
Suggested reviewers
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
npm error Exit handler never called! ✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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: 반응형 스타일링 개선사항과 잠재적 문제점반응형 디자인 추가는 좋은 개선이지만 몇 가지 문제점이 있습니다:
max-h-764 min-h-764는 고정 높이를 만들어 반응형 디자인에 적합하지 않을 수 있습니다overflow-auto overflow-y-scroll는 중복입니다 -overflow-auto만으로 충분합니다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 제거 필요
format과useState가 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
📒 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"
There was a problem hiding this 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: 모달 스크롤 잠금 훅 구현이 잘 되었습니다만, 몇 가지 개선사항을 제안합니다.현재 구현은 기본적으로 올바르게 작동하지만 다음과 같은 개선이 필요합니다:
getComputedStyle보다는 직접document.body.style.overflow값을 저장하는 것이 더 안전합니다.- 여러 모달이 동시에 열릴 때를 대비한 참조 카운팅이 필요할 수 있습니다.
다음과 같이 개선할 수 있습니다:
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: 사용하지 않는 임포트를 제거하세요.
format과useState가 임포트되었지만 이 컴포넌트에서 사용되지 않습니다.-import { format } from 'date-fns' -import { useState } from 'react' import { toast } from 'sonner'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 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: 사용자 친화적인 에러 메시지로 개선되었습니다.고정된 에러 메시지가 사용자에게 더 명확한 안내를 제공합니다.
| const { data, isLoading, error } = useCommentsQuery(cardId) | ||
| const comments = data?.comments | ||
|
|
||
| if (error) { | ||
| toast.error(error?.message || '문제가 발생했습니다.') | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
로딩 상태 처리와 에러 처리 개선이 필요합니다.
현재 구현에는 다음 문제들이 있습니다:
isLoading상태를 추출했지만 로딩 UI를 제공하지 않습니다- 에러가 발생했을 때도 컴포넌트가 계속 렌더링되어 혼란을 줄 수 있습니다
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.
| 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.
| <div className="flex w-450 flex-col gap-20"> | ||
| {comments?.map((comment: CommentType) => ( | ||
| <Comment key={comment.id} comment={comment} /> | ||
| ))} | ||
| </div> | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
반응형 디자인과 빈 상태 처리를 개선하세요.
현재 구현의 개선점:
w-450고정 너비가 모바일에서 문제가 될 수 있습니다- 댓글이 없을 때의 상태를 처리하지 않습니다
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.
| <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.
📌 변경 사항 개요
✅ 디벨롭 브랜치에 병합은 작업 마무리되면 하겠습니다(아직 테스트API사용하고 있어서)
남은 작업 (필수)
남은 작업 (선택)
✨ 요약
📝 상세 내용
🔗 관련 이슈
🖼️ 스크린샷
카드 상세 모달
댓글
댓글 수정
✅ 체크리스트
💡 참고 사항
Summary by CodeRabbit
New Features
Bug Fixes
Style
Documentation
Chores