-
Notifications
You must be signed in to change notification settings - Fork 2
develop <-- feature/dashboard_id #84
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
Conversation
- UI, 기능 적용. 완성도 80% - 폴더 구조 변경
-폼데이터의 디폴트값을 빈 문자열로 설정 - onSubmit함수에서는 해당 란을 제외한 데이터를 보냄. (빈 문자열로 디폴트값 설정 안하면, 기본 파일리스트 객체가 전달되기 때문에 이미지 URL이 있는지 참,거짓 측정이 불가함)
…Modal ✨ Feat: create card modal 카드 생성 모달 구현
Walkthrough카드와 컬럼 관련 API 훅 및 타입이 기존의 공통 폴더에서 Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant DashboardPage
participant CreateCardModal
participant CreateCardForm
participant usePostCard
participant API
User->>DashboardPage: "카드 생성" 버튼 클릭
DashboardPage->>CreateCardModal: 모달 열기
CreateCardModal->>CreateCardForm: 폼 렌더링
User->>CreateCardForm: 카드 정보 입력 및 제출
CreateCardForm->>usePostCard: 카드 생성 요청
usePostCard->>API: POST /cards
API-->>usePostCard: 카드 생성 결과 반환
usePostCard-->>CreateCardForm: 성공/실패 콜백
CreateCardForm-->>CreateCardModal: onClose 호출(성공시)
CreateCardModal-->>DashboardPage: 모달 닫기, 목록 갱신
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: 8
🔭 Outside diff range comments (1)
src/app/features/dashboardId/Card/cardFormModals/AssigneeList.tsx (1)
1-30: 파일 경로 일관성 확인 필요현재 파일 경로가
dashboardId인데, 다른 파일들은dashboard_Id를 사용하고 있습니다. 이는 일관성 문제를 야기할 수 있습니다.폴더 구조의 일관성을 위해 다음 중 하나를 선택해야 합니다:
- 이 파일을
src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx로 이동- 또는 다른 파일들을
dashboardId구조로 통일파일 경로 불일치로 인한 임포트 오류가 발생할 수 있습니다.
♻️ Duplicate comments (1)
src/app/features/dashboard_Id/api/fetchCards.ts (1)
1-3: testAxios 사용에 대한 일관성 확인
fetchColumns.ts와 동일하게 테스트용 axios 인스턴스를 사용하고 있습니다. 프로덕션 환경에서의 사용 의도를 확인해주세요.
🧹 Nitpick comments (16)
src/app/features/dashboard_Id/api/useMembers.ts (1)
9-9: 쿼리 키를 더 구체적으로 변경하는 것을 권장합니다.현재
['dashboardId', dashboardId]키는 너무 일반적이어서 다른 대시보드 관련 쿼리와 충돌할 가능성이 있습니다.다음과 같이 변경하는 것을 권장합니다:
- queryKey: ['dashboardId', dashboardId], + queryKey: ['members', dashboardId],src/app/features/dashboard_Id/api/usePostCard.ts (1)
15-22: 사용자 피드백 일관성 개선 필요다른 훅(
useUploadCardImage)에서는 토스트 알림으로 에러를 표시하지만, 여기서는 콘솔 로그만 출력합니다. 사용자 경험 일관성을 위해 토스트 알림 추가를 고려해보세요.toast 추가 예시:
import { useMutation, useQueryClient } from '@tanstack/react-query' import axios from 'axios' +import { toast } from 'sonner' import { postCard } from './postCard' export function usePostCard() { const queryClient = useQueryClient() return useMutation({ mutationFn: postCard, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['columnId'] }) + toast.success('카드가 성공적으로 생성되었습니다.') }, onError: (error) => { if (axios.isAxiosError(error)) { const message = error.response?.data?.message - console.error('카드 생성 실패:', message ?? '알 수 없는 에러') + toast.error(message ?? '카드 생성에 실패했습니다.') } else { - console.error('카드 생성 실패:', error) + toast.error('카드 생성에 실패했습니다.') } }, }) }src/app/features/dashboard_Id/api/fetchCards.ts (1)
6-14: 기본 구현은 적절하지만 입력 검증 추가 고려
fetchColumns와 달리columnId유효성 검사가 없습니다. 일관성을 위해 추가를 고려해보세요.입력 검증 추가 예시:
export async function fetchCards( columnId: number, size: number = 10, ): Promise<CardResponse> { + if (!columnId) { + throw new Error('columnId가 유효하지 않습니다.') + } + const res = await api.get<CardResponse>( `/${process.env.NEXT_PUBLIC_TEAM_ID}/cards?size=${size}&columnId=${columnId}`, ) return res.data }src/app/features/dashboard_Id/api/postCard.ts (1)
6-8: ApiResponse 인터페이스를 공통 타입으로 분리하세요.ApiResponse 인터페이스가 다른 API 함수들에서도 재사용될 가능성이 높습니다.
공통 타입 파일로 분리하여 재사용성을 높이세요:
// src/app/features/dashboard_Id/type/ApiResponse.type.ts export interface ApiResponse { message: string }src/app/features/dashboard_Id/api/postCardImage.ts (1)
15-15: 주석에 오타가 있습니다.주석 끝부분의 's'를 제거하세요.
- 'Content-Type': 'multipart/form-data', // multipart/form-data 방식으로 파일 전송: 모든 문자를 인코딩하지 않음s + 'Content-Type': 'multipart/form-data', // multipart/form-data 방식으로 파일 전송: 모든 문자를 인코딩하지 않음src/app/features/dashboard_Id/Card/Tags.tsx (2)
6-7: 색상 배열을 상수로 분리하세요.하드코딩된 색상 배열을 상수로 분리하여 재사용성과 유지보수성을 높이세요.
+const TAG_COLORS = { + backgrounds: ['#F9EEE3', '#E7F7DB', '#F7DBF0', '#DBE6F7'], + texts: ['#D58D49', '#86D549', '#D549B6', '#4981D5'], +} as const export default function Tags({ tags }: { tags: string[] }) { //태그 컬러 - 랜덤 배정 //카드 생성 시 - 동일 태그 입력 불가하도록 - const bgColors = ['#F9EEE3', '#E7F7DB', '#F7DBF0', '#DBE6F7'] - const textColors = ['#D58D49', '#86D549', '#D549B6', '#4981D5'] + const bgColors = TAG_COLORS.backgrounds + const textColors = TAG_COLORS.texts
14-25: 접근성을 개선하세요.태그 요소에 의미론적 역할을 추가하여 스크린 리더 사용자에게 더 나은 경험을 제공하세요.
<span key={tag} className="inline-block whitespace-nowrap rounded-4 px-9 pb-3 pt-5" + role="button" + tabIndex={0} + aria-label={`태그: ${tag}`} style={{ backgroundColor: bgColors[colorIndex], color: textColors[colorIndex], }} > {tag} </span>src/app/features/dashboard_Id/Card/cardFormModals/input/DateInput.tsx (1)
9-18: 접근성 속성을 추가하세요.날짜 입력 필드에 접근성 속성을 추가하여 사용자 경험을 개선하세요.
<input ref={ref} {...restProps} inputMode="none" readOnly className="Input-readOnly" id={id} placeholder="날짜와 시간을 선택하세요" + aria-label="마감일 선택" + aria-describedby="dueDate-description" />src/app/features/dashboard_Id/Card/cardFormModals/input/Input.tsx (1)
2-7: 인터페이스 네이밍 개선이 필요합니다.인터페이스 이름이 컴포넌트 이름과 동일하여 충돌할 수 있습니다. 더 명확한 이름으로 변경하는 것이 좋겠습니다.
-interface Input { +interface InputProps { children: React.ReactNode labelName: string labelFor: string accent?: boolean }src/app/features/dashboard_Id/api/useColumns.ts (1)
6-11: 에러 처리 개선을 고려해보세요.현재
fetchColumns함수에서 에러 처리를 하고 있지만, 이 훅에서도 추가적인 에러 처리나 로딩 상태 관리가 필요한지 검토해보시기 바랍니다.필요하다면 다음과 같이 추가 옵션을 고려할 수 있습니다:
export default function useColumns(dashboardId: number) { return useQuery<Column[]>({ queryKey: ['columns', dashboardId], queryFn: () => fetchColumns(dashboardId), + enabled: Boolean(dashboardId), + staleTime: 1000 * 60 * 5, // 5분 }) }src/app/features/dashboard_Id/api/fetchMembers.ts (1)
6-11: API 호출에 에러 핸들링 추가 권장현재 함수에는 에러 핸들링이 없어 네트워크 오류나 API 응답 오류 시 처리가 어려울 수 있습니다.
다음과 같이 에러 핸들링을 추가하는 것을 고려해보세요:
export async function fetchMembers(dashboardId: number): Promise<Member[]> { - const res = await api.get<MembersResponse>( - `/${process.env.NEXT_PUBLIC_TEAM_ID}/members?&dashboardId=${dashboardId}`, - ) - return res.data.members + try { + const res = await api.get<MembersResponse>( + `/${process.env.NEXT_PUBLIC_TEAM_ID}/members?&dashboardId=${dashboardId}`, + ) + return res.data.members + } catch (error) { + console.error('Failed to fetch members:', error) + throw error + } }src/app/dashboard/[id]/layout.tsx (2)
3-3: 사용하지 않는 Sidebar 임포트 제거Sidebar를 임포트했지만 주석 처리되어 실제로 사용하지 않고 있습니다.
사용하지 않는 임포트를 제거하는 것을 권장합니다:
-import Sidebar from '@/app/shared/components/common/sidebar/Sidebar'Also applies to: 12-12
5-5: 컴포넌트 이름이 용도와 일치하지 않음컴포넌트 이름이
AboutLayout이지만 실제로는 대시보드 레이아웃에 사용되고 있습니다.컴포넌트 이름을 용도에 맞게 변경하는 것을 고려해보세요:
-export default function AboutLayout({ +export default function DashboardLayout({src/app/features/dashboardId/Card/cardFormModals/AssigneeList.tsx (1)
21-21: 개발용 console.log 제거 필요프로덕션 코드에서 디버깅용 console.log를 제거해야 합니다.
다음과 같이 console.log를 제거하세요:
onClick={() => { setSelectedAssignee(Assignee) - console.log(Assignee) }}src/app/dashboard/[id]/page.tsx (1)
17-17: 주석 처리된 코드를 제거해주세요.사용하지 않는 주석 처리된 코드는 코드 가독성을 해치므로 제거하는 것이 좋습니다.
- // const { data: columns, isLoading, error } = useColumns(id)src/app/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx (1)
92-94: 디버그 코드를 제거해주세요.프로덕션 코드에서
console.log는 제거하는 것이 좋습니다.- console.log('submitted', payload)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/images/plus.svgis 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 (19)
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/fetchCards.ts (1)
src/app/features/dashboard_Id/type/Card.type.ts (1)
CardResponse(21-25)
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/postCard.ts (1)
src/app/features/dashboard_Id/type/CardFormData.type.ts (1)
CardFormData(1-10)
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/usePostCard.ts (1)
src/app/features/dashboard_Id/api/postCard.ts (1)
postCard(10-16)
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/dashboard_Id/api/useUploadCardImage.ts (1)
src/app/features/dashboard_Id/api/postCardImage.ts (1)
postCardImages(4-21)
src/app/dashboard/[id]/layout.tsx (1)
src/app/shared/components/common/header/Header.tsx (1)
Header(12-66)
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/useColumns.ts (2)
src/app/features/dashboard_Id/type/Column.type.ts (1)
Column(1-8)src/app/features/dashboard_Id/api/fetchColumns.ts (1)
fetchColumns(6-16)
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/type/Column.type.ts (1)
src/app/features/dashboard_Id/Column/Column.tsx (1)
Column(13-105)
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/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/dashboard/[id]/page.tsx (1)
src/app/features/dashboard_Id/api/useColumns.ts (1)
useColumns(6-11)
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/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx (7)
src/app/features/dashboard_Id/api/useUploadCardImage.ts (1)
useUploadCardImage(8-19)src/app/features/dashboard_Id/api/useMembers.ts (1)
useMembers(7-12)src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx (2)
Assignee(9-12)AssigneeList(24-50)src/app/features/dashboard_Id/type/CardFormData.type.ts (1)
CardFormData(1-10)src/app/features/dashboard_Id/api/usePostCard.ts (1)
usePostCard(7-24)src/app/features/dashboard_Id/Card/cardFormModals/input/Input.tsx (1)
Input(9-28)src/app/features/dashboard_Id/Card/Tags.tsx (1)
Tags(3-29)
🪛 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 (39)
src/app/layout.tsx (1)
28-28: 모달 Portal 컨테이너 추가가 적절합니다.React Portal을 위한
modal-rootdiv가 올바른 위치에 추가되었습니다. Providers 외부에 배치하여 모달이 전역 스타일과 독립적으로 렌더링될 수 있도록 했습니다.package.json (1)
16-16: lockfile이 없어npm audit가 실패했습니다. 아래 스크립트로package-lock.json을 생성한 뒤 보안 검사를 다시 실행해주세요.#!/bin/bash # package-lock.json 생성 npm install --package-lock-only # 보안 취약점 검사 npm audit --audit-level=moderatesrc/app/shared/lib/testAxios.ts (2)
10-10: 인터셉터와 export 업데이트가 일관성 있습니다.변경된 인스턴스 이름에 맞춰 인터셉터 설정과 export문이 올바르게 업데이트되었습니다.
Also applies to: 18-18
3-5: ```shell
#!/bin/bash.ts 및 .tsx 파일에서 api 인스턴스(import api from testAxios) 사용처 검색
rg -n "import\s.*api\s.from\s.testAxios" -g '.ts' -g '.tsx'
이전 axiosClient 사용처가 남아있는지 확인
rg -n "axiosClient" -g '.ts' -g '.tsx'
</details> <details> <summary>src/app/shared/lib/getColor.ts (1)</summary> `1-5`: 아래 명령어로 `getColor` 호출처를 다시 검색해주세요. 이번에는 glob 옵션을 사용해 `.ts`·`.tsx` 파일을 모두 탐색합니다. ```shell #!/bin/bash # Description: ts/tsx 파일에서 getColor 함수 사용처를 찾아 올바른 인자가 전달되는지 확인합니다. rg -n -C 2 "getColor\(" --glob "*.ts" --glob "*.tsx"src/app/globals.css (3)
45-47: 텍스트 입력 스타일이 일관성 있게 추가되었습니다.
.Text-Input클래스가 기존 텍스트 스타일 패턴과 일관성 있게 다크 모드 지원과 함께 추가되었습니다.
84-86: 입력 요소 호버 효과가 적절히 구현되었습니다.
.BG-Input-hovered클래스가 라이트/다크 모드 모두에서 적절한 호버 효과를 제공합니다.
91-96: 입력 요소 스타일이 포괄적으로 정의되었습니다.
.Input과.Input-readOnly클래스가 폼 요소의 다양한 상태(포커스, 읽기 전용)를 잘 다루고 있으며, 다크 모드 지원도 완벽합니다.src/app/features/dashboardId/Card/Tags.tsx (1)
12-12: getColor 함수 시그니처 변경에 맞는 올바른 수정입니다.새로운 getColor 함수가 배열 길이를 매개변수로 받도록 변경된 것에 맞춰 적절하게 수정되었습니다.
src/app/shared/components/common/Avatar.tsx (1)
34-34: getColor 함수 사용법이 올바르게 업데이트되었습니다.Tags 컴포넌트와 일관된 방식으로 getColor 함수의 새로운 시그니처에 맞게 수정되었습니다.
src/app/features/dashboard_Id/type/Card.type.ts (1)
21-25: 표준적인 페이지네이션 응답 인터페이스가 잘 정의되었습니다.카드 목록 조회 API의 응답 구조를 명확하게 타입으로 정의하여 타입 안전성을 보장합니다.
src/app/features/dashboard_Id/api/useCardMutation.ts (1)
4-4: 리팩토링에 맞는 올바른 임포트 경로 변경입니다.기존 API 모듈에서 새로운 feature-specific 타입 정의로 임포트 경로가 적절하게 변경되었습니다.
src/app/features/dashboard_Id/api/useUploadCardImage.ts (1)
7-19: 이미지 업로드 훅 구현이 적절합니다.에러 핸들링과 사용자 피드백이 잘 구현되어 있습니다. 서버 에러 메시지를 우선적으로 사용하고, 대체 메시지로 폴백하는 로직이 적절합니다.
src/app/features/dashboard_Id/api/useCards.ts (1)
7-12: 카드 조회 훅이 올바르게 구현되었습니다.쿼리 키 구조
['columnId', columnId]가 적절하며, 향후 무한 스크롤 구현 계획에 대한 주석도 유용합니다.src/app/features/dashboard_Id/api/fetchColumns.ts (2)
6-9: 입력 검증 로직이 적절합니다.
dashboardId유효성 검사와 명확한 에러 메시지가 잘 구현되어 있습니다.
1-3: 테스트 axios 인스턴스 사용 확인 필요현재
testAxios를 사용하고 있고 프로덕션용 axios가 주석 처리되어 있습니다. 의도적인 것인지 확인이 필요합니다.다음 스크립트로 프로젝트 전체에서 어떤 axios 인스턴스가 사용되고 있는지 확인해보세요:
#!/bin/bash # 프로젝트에서 axios 인스턴스 사용 현황 확인 echo "=== testAxios 사용 현황 ===" rg "from.*testAxios" --type ts --type tsx -A 2 echo -e "\n=== 일반 axios 사용 현황 ===" rg "from.*lib/axios" --type ts --type tsx -A 2 echo -e "\n=== axios 설정 파일들 ===" fd "axios" --type fsrc/app/features/dashboard_Id/api/updateCardColumn.ts (1)
1-2: 프로덕션 환경에서 testAxios 사용 여부를 검증하세요.현재 testAxios를 사용하고 있고 프로덕션용 axios는 주석 처리되어 있습니다. 프로덕션 배포 시 올바른 API 클라이언트가 사용되는지 확인이 필요합니다.
src/app/features/dashboard_Id/api/postCard.ts (1)
1-1: testAxios 사용에 대한 검증이 필요합니다.다른 API 함수들과 동일하게 testAxios를 사용하고 있습니다. 프로덕션 환경에서의 사용 여부를 확인하세요.
src/app/features/dashboard_Id/Card/Tags.tsx (1)
3-29: 전반적으로 잘 구현된 컴포넌트입니다.getColor 함수를 적절히 사용하여 일관된 색상 할당을 구현했고, 적절한 스타일링과 키 속성을 사용했습니다.
src/app/features/dashboard_Id/Card/cardFormModals/input/DateInput.tsx (1)
4-22: forwardRef 구현이 잘 되어 있습니다.forwardRef를 적절히 사용하여 ref 전달을 지원하고, displayName을 설정하여 디버깅에 도움이 되도록 구현했습니다.
src/app/features/dashboard_Id/type/CardFormData.type.ts (1)
1-10: 인터페이스 정의가 깔끔하고 적절합니다.카드 폼 데이터를 위한 타입 정의가 명확하고 필요한 필드들이 적절히 구성되어 있습니다. 필수 필드와 선택적 필드(
dueDate,imageUrl)의 구분도 적절합니다.src/app/features/dashboard_Id/lib/getDashboardMembers.ts (1)
10-18: 함수 구현이 깔끔하고 안전합니다.undefined 처리와 타입 변환 로직이 적절하게 구현되어 있습니다. 한국어 주석도 코드의 의도를 명확히 설명하고 있습니다.
src/app/features/dashboard_Id/Card/cardFormModals/input/Input.tsx (1)
9-28: 컴포넌트 구현이 적절하고 접근성을 고려했습니다.label과 input 요소의 연결(
htmlFor)이 적절히 구현되어 있고, 필수 필드 표시(accent)도 좋은 UX 패턴입니다. 스타일링도 일관성 있게 적용되어 있습니다.src/app/features/dashboard_Id/Card/Card.tsx (3)
6-6: import 경로 업데이트가 적절합니다.타입 정의를 feature-specific 폴더로 이동한 리팩터링에 맞춰 import 경로가 올바르게 업데이트되었습니다.
20-20: props 구조분해를 통한 코드 개선이 좋습니다.
card.id대신 구조분해된id를 사용하여 코드가 더 간결해졌습니다.
50-73: 조건부 렌더링 개선이 훌륭합니다.마감일과 담당자 섹션을 각각 조건부로 렌더링하도록 개선하여 불필요한 빈 요소 렌더링을 방지했습니다. 코드 가독성도 향상되었습니다.
src/app/features/dashboard_Id/api/useColumns.ts (1)
6-11: React Query 훅 구현이 표준 패턴을 잘 따르고 있습니다.dashboardId를 쿼리 키에 포함하여 대시보드별 캐시 분리가 적절히 구현되었고, 타입 정의도 명확합니다. 간결하고 재사용 가능한 훅 구조입니다.
src/app/features/dashboard_Id/api/fetchMembers.ts (1)
1-1: 프로덕션용 Axios 설정 확인다음 스크립트를 실행해
src/app/shared/lib/axios.ts(또는 유사 파일)의 설정을 확인하고,testAxios와 비교해주세요.#!/bin/bash # shared/lib 디렉터리 파일 목록 확인 echo "=== src/app/shared/lib 파일 목록 ===" ls src/app/shared/lib echo "" # 프로덕션용 axios 설정 확인 if [ -f src/app/shared/lib/axios.ts ]; then echo "=== src/app/shared/lib/axios.ts 내용 ===" cat src/app/shared/lib/axios.ts elif [ -f src/app/shared/lib/axios.js ]; then echo "=== src/app/shared/lib/axios.js 내용 ===" cat src/app/shared/lib/axios.js else echo "프로덕션 axios 파일(axios.ts/.js)을 찾을 수 없습니다." fisrc/app/features/dashboard_Id/type/Column.type.ts (1)
1-11: 타입 정의가 올바르게 구성되었습니다Column 인터페이스와 ColumnsResponse 인터페이스가 적절하게 정의되어 있습니다. 필드 타입들이 일관성 있게 설정되어 있고 API 응답 구조도 표준적입니다.
src/app/features/dashboard_Id/Card/cardFormModals/CreateCardModal.tsx (1)
8-9: modal-root 요소가 없을 때의 처리가 적절합니다
document.getElementById('modal-root')가 null일 경우 적절히 처리하고 있습니다.src/app/features/dashboardId/Card/cardFormModals/AssigneeList.tsx (1)
2-2: 사용 중인AssigneeList컴포넌트가 어느 경로의 파일인지 확인하기 위해 아래 스크립트를 실행해주세요:#!/bin/bash echo "=== AssigneeList 사용처 검색 ===" rg "AssigneeList" -n . echo -e "\n=== dashboardId 폴더 참조 검색 ===" rg "src/app/features/dashboardId" -n . echo -e "\n=== dashboard_Id 폴더 참조 검색 ===" rg "src/app/features/dashboard_Id" -n .src/app/features/dashboard_Id/type/Member.type.ts (1)
1-14: 타입 정의가 깔끔하고 잘 구조화되어 있습니다.Member와 MembersResponse 인터페이스가 명확하게 정의되어 있고, 필드 타입들이 적절히 설정되어 있습니다. profileImageUrl의 nullable 처리도 올바르게 되어 있습니다.
src/app/dashboard/[id]/page.tsx (1)
14-16: 동적 대시보드 ID 구현이 올바르게 되어 있습니다.
useParams를 사용하여 URL에서 동적으로 대시보드 ID를 가져오고 있으며, 새로운useColumns훅에 올바르게 전달하고 있습니다.src/app/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx (2)
26-48: 폼 상태 관리가 잘 구현되어 있습니다.
react-hook-form을 사용한 폼 상태 관리가 적절히 구현되어 있고, 이미지 업로드, 태그 관리, 담당자 선택 등의 기능이 잘 구조화되어 있습니다.
193-196: 태그 중복 처리 로직이 올바르게 구현되어 있습니다.태그 중복을 체크하고
trim()을 사용하여 공백을 제거하는 로직이 적절히 구현되어 있습니다.src/app/features/dashboard_Id/Column/Column.tsx (2)
9-11: 모달 컴포넌트 통합이 잘 되어 있습니다.
CreateCardForm과CreateCardModal을 적절히 import하고 있으며, 새로운 피처 구조에 맞게 경로가 업데이트되었습니다.
95-102: 카드 생성 모달 구현이 적절합니다.조건부 렌더링으로 모달을 표시하고, 필요한 props들(onClose, columnId)을 올바르게 전달하고 있습니다.
src/app/features/dashboard_Id/Card/cardFormModals/AssigneeList.tsx (2)
9-17: 타입 정의가 명확하고 잘 구조화되어 있습니다.
Assignee인터페이스와AssigneeListProps가 명확하게 정의되어 있으며, react-hook-form과의 통합을 위한ControllerRenderProps타입 사용이 적절합니다.
40-43: 담당자 선택 로직이 올바르게 구현되어 있습니다.UI 상태(
setAssignee)와 폼 상태(controlField.onChange) 업데이트를 분리하여 처리하는 것이 적절합니다. 주석으로 설명된 로직도 명확합니다.
| onSuccess: () => { | ||
| queryClient.invalidateQueries({ queryKey: ['columnId'] }) //'columnId' 쿼리 invalidate - 카드 리스트가 stale 상태임을 알리고 다시 fetch 하도록 유도함 | ||
| }, |
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.
쿼리 키 불일치로 인한 캐시 무효화 문제
useCards 훅에서는 ['columnId', columnId] 키를 사용하지만, 여기서는 ['columnId']만 무효화하고 있습니다. 이로 인해 카드 생성 후 목록이 자동으로 업데이트되지 않을 수 있습니다.
다음과 같이 수정하세요:
- queryClient.invalidateQueries({ queryKey: ['columnId'] })
+ queryClient.invalidateQueries({ queryKey: ['columnId'] })Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/api/usePostCard.ts around lines 12 to 14, the
query key used in queryClient.invalidateQueries is inconsistent with the key
used in the useCards hook. The hook uses ['columnId', columnId] but the
invalidateQueries call only uses ['columnId'], causing cache invalidation to
fail. Fix this by including the columnId variable in the invalidateQueries call
to match the full query key, ensuring the card list updates correctly after
creation.
| export async function updateCardColumn( | ||
| cardId: number, | ||
| columnId: number, | ||
| ): Promise<{ success: boolean }> { | ||
| const res = await api.put<{ success: boolean }>( | ||
| `/${process.env.NEXT_PUBLIC_TEAM_ID}/cards/${cardId}`, | ||
| { | ||
| columnId: columnId, | ||
| }, | ||
| ) | ||
| return res.data | ||
| } |
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
환경변수 검증과 에러 처리를 추가하세요.
현재 구현에서 다음 사항들을 개선할 수 있습니다:
process.env.NEXT_PUBLIC_TEAM_ID가 undefined일 경우 처리- API 요청 실패 시 에러 처리
- 카드 ID와 컬럼 ID 유효성 검증
다음과 같은 개선사항을 적용하세요:
export async function updateCardColumn(
cardId: number,
columnId: number,
): Promise<{ success: boolean }> {
+ if (!process.env.NEXT_PUBLIC_TEAM_ID) {
+ throw new Error('NEXT_PUBLIC_TEAM_ID is not defined')
+ }
+
+ if (cardId <= 0 || columnId <= 0) {
+ throw new Error('Invalid cardId or columnId')
+ }
+
+ try {
const res = await api.put<{ success: boolean }>(
`/${process.env.NEXT_PUBLIC_TEAM_ID}/cards/${cardId}`,
{
columnId: columnId,
},
)
return res.data
+ } catch (error) {
+ console.error('Failed to update card column:', 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.
| export async function updateCardColumn( | |
| cardId: number, | |
| columnId: number, | |
| ): Promise<{ success: boolean }> { | |
| const res = await api.put<{ success: boolean }>( | |
| `/${process.env.NEXT_PUBLIC_TEAM_ID}/cards/${cardId}`, | |
| { | |
| columnId: columnId, | |
| }, | |
| ) | |
| return res.data | |
| } | |
| export async function updateCardColumn( | |
| cardId: number, | |
| columnId: number, | |
| ): Promise<{ success: boolean }> { | |
| if (!process.env.NEXT_PUBLIC_TEAM_ID) { | |
| throw new Error('NEXT_PUBLIC_TEAM_ID is not defined') | |
| } | |
| if (cardId <= 0 || columnId <= 0) { | |
| throw new Error('Invalid cardId or columnId') | |
| } | |
| try { | |
| const res = await api.put<{ success: boolean }>( | |
| `/${process.env.NEXT_PUBLIC_TEAM_ID}/cards/${cardId}`, | |
| { | |
| columnId: columnId, | |
| }, | |
| ) | |
| return res.data | |
| } catch (error) { | |
| console.error('Failed to update card column:', error) | |
| throw error | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/api/updateCardColumn.ts lines 5 to 16, add
validation to check if process.env.NEXT_PUBLIC_TEAM_ID is defined before using
it, validate that cardId and columnId are valid numbers, and wrap the API call
in a try-catch block to handle and propagate errors properly. Return or throw
meaningful errors if validations fail or the API request encounters an error.
| export async function postCard(payload: CardFormData): Promise<ApiResponse> { | ||
| const res = await api.post( | ||
| `/${process.env.NEXT_PUBLIC_TEAM_ID}/cards`, | ||
| payload, | ||
| ) | ||
| return res.data | ||
| } |
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
환경변수 검증과 에러 처리를 추가하세요.
updateCardColumn 함수와 동일한 문제점들이 있습니다. 환경변수 검증과 에러 처리를 추가하세요.
export async function postCard(payload: CardFormData): Promise<ApiResponse> {
+ if (!process.env.NEXT_PUBLIC_TEAM_ID) {
+ throw new Error('NEXT_PUBLIC_TEAM_ID is not defined')
+ }
+
+ try {
const res = await api.post(
`/${process.env.NEXT_PUBLIC_TEAM_ID}/cards`,
payload,
)
return res.data
+ } catch (error) {
+ console.error('Failed to create card:', 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.
| 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> { | |
| if (!process.env.NEXT_PUBLIC_TEAM_ID) { | |
| throw new Error('NEXT_PUBLIC_TEAM_ID is not defined') | |
| } | |
| try { | |
| const res = await api.post( | |
| `/${process.env.NEXT_PUBLIC_TEAM_ID}/cards`, | |
| payload, | |
| ) | |
| return res.data | |
| } catch (error) { | |
| console.error('Failed to create card:', error) | |
| throw error | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/api/postCard.ts between lines 10 and 16, the
function postCard lacks environment variable validation and error handling
similar to updateCardColumn. Add a check to ensure
process.env.NEXT_PUBLIC_TEAM_ID is defined before making the API call, and
implement try-catch to handle potential errors, returning or logging appropriate
error information.
| export async function postCardImages( | ||
| columnId: number, | ||
| file: File, | ||
| ): Promise<{ imageUrl: string }> { | ||
| const formData = new FormData() | ||
| formData.append('image', file) | ||
| const res = await api.post( | ||
| `/${process.env.NEXT_PUBLIC_TEAM_ID}/columns/${columnId}/card-image`, | ||
| formData, | ||
| { | ||
| headers: { | ||
| 'Content-Type': 'multipart/form-data', // multipart/form-data 방식으로 파일 전송: 모든 문자를 인코딩하지 않음s | ||
| }, | ||
| }, | ||
| ) | ||
|
|
||
| return res.data | ||
| } |
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
파일 유효성 검증과 에러 처리를 추가하세요.
파일 업로드 함수에 다음 개선사항들을 적용하세요:
- 파일 크기 제한 검증
- 파일 타입 검증
- 환경변수 검증
- 에러 처리 개선
export async function postCardImages(
columnId: number,
file: File,
): Promise<{ imageUrl: string }> {
+ if (!process.env.NEXT_PUBLIC_TEAM_ID) {
+ throw new Error('NEXT_PUBLIC_TEAM_ID is not defined')
+ }
+
+ // 파일 크기 제한 (예: 10MB)
+ const maxSize = 10 * 1024 * 1024
+ if (file.size > maxSize) {
+ throw new Error('파일 크기가 10MB를 초과합니다')
+ }
+
+ // 이미지 파일 타입 검증
+ const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
+ if (!allowedTypes.includes(file.type)) {
+ throw new Error('지원하지 않는 이미지 파일 형식입니다')
+ }
+
+ try {
const formData = new FormData()
formData.append('image', file)
const res = await api.post(
`/${process.env.NEXT_PUBLIC_TEAM_ID}/columns/${columnId}/card-image`,
formData,
{
headers: {
- 'Content-Type': 'multipart/form-data', // multipart/form-data 방식으로 파일 전송: 모든 문자를 인코딩하지 않음s
+ 'Content-Type': 'multipart/form-data', // multipart/form-data 방식으로 파일 전송: 모든 문자를 인코딩하지 않음
},
},
)
return res.data
+ } catch (error) {
+ console.error('Failed to upload card image:', 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.
| export async function postCardImages( | |
| columnId: number, | |
| file: File, | |
| ): Promise<{ imageUrl: string }> { | |
| const formData = new FormData() | |
| formData.append('image', file) | |
| const res = await api.post( | |
| `/${process.env.NEXT_PUBLIC_TEAM_ID}/columns/${columnId}/card-image`, | |
| formData, | |
| { | |
| headers: { | |
| 'Content-Type': 'multipart/form-data', // multipart/form-data 방식으로 파일 전송: 모든 문자를 인코딩하지 않음s | |
| }, | |
| }, | |
| ) | |
| return res.data | |
| } | |
| export async function postCardImages( | |
| columnId: number, | |
| file: File, | |
| ): Promise<{ imageUrl: string }> { | |
| if (!process.env.NEXT_PUBLIC_TEAM_ID) { | |
| throw new Error('NEXT_PUBLIC_TEAM_ID is not defined') | |
| } | |
| // 파일 크기 제한 (예: 10MB) | |
| const maxSize = 10 * 1024 * 1024 | |
| if (file.size > maxSize) { | |
| throw new Error('파일 크기가 10MB를 초과합니다') | |
| } | |
| // 이미지 파일 타입 검증 | |
| const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'] | |
| if (!allowedTypes.includes(file.type)) { | |
| throw new Error('지원하지 않는 이미지 파일 형식입니다') | |
| } | |
| try { | |
| const formData = new FormData() | |
| formData.append('image', file) | |
| const res = await api.post( | |
| `/${process.env.NEXT_PUBLIC_TEAM_ID}/columns/${columnId}/card-image`, | |
| formData, | |
| { | |
| headers: { | |
| 'Content-Type': 'multipart/form-data', // multipart/form-data 방식으로 파일 전송: 모든 문자를 인코딩하지 않음 | |
| }, | |
| }, | |
| ) | |
| return res.data | |
| } catch (error) { | |
| console.error('Failed to upload card image:', error) | |
| throw error | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/api/postCardImage.ts between lines 4 and 21,
add validation to check the file size and type before uploading, verify that the
environment variable NEXT_PUBLIC_TEAM_ID is defined and valid, and wrap the API
call in a try-catch block to handle errors gracefully by returning or logging
meaningful error messages.
| inputMode="none" | ||
| readOnly | ||
| className="Input-readOnly" | ||
| id="dueDate" |
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
하드코딩된 id 속성을 개선하세요.
고정된 id="dueDate"는 동일한 컴포넌트의 여러 인스턴스가 존재할 때 문제가 될 수 있습니다.
props로 id를 전달받거나 고유한 id를 생성하도록 개선하세요:
const DateInput = forwardRef<
HTMLInputElement,
- React.InputHTMLAttributes<HTMLInputElement>
+ React.InputHTMLAttributes<HTMLInputElement> & { id?: string }
>((props, ref) => {
+ const { id = 'dueDate', ...restProps } = props
return (
<input
ref={ref}
- {...props}
+ {...restProps}
inputMode="none"
readOnly
className="Input-readOnly"
- id="dueDate"
+ id={id}
placeholder="날짜와 시간을 선택하세요"
/>
)
})📝 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.
| id="dueDate" | |
| const DateInput = forwardRef< | |
| HTMLInputElement, | |
| - React.InputHTMLAttributes<HTMLInputElement> | |
| + React.InputHTMLAttributes<HTMLInputElement> & { id?: string } | |
| >((props, ref) => { | |
| + const { id = 'dueDate', ...restProps } = props | |
| return ( | |
| <input | |
| ref={ref} | |
| - {...props} | |
| + {...restProps} | |
| inputMode="none" | |
| readOnly | |
| className="Input-readOnly" | |
| - id="dueDate" | |
| + id={id} | |
| placeholder="날짜와 시간을 선택하세요" | |
| /> | |
| ) | |
| }) |
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/Card/cardFormModals/input/DateInput.tsx at line
15, the id attribute is hardcoded as "dueDate", which can cause conflicts if
multiple instances of this component are rendered. Modify the component to
accept an id as a prop or generate a unique id internally, then replace the
hardcoded id with this dynamic value to ensure uniqueness across instances.
| export interface Assignee { | ||
| userId: number | ||
| nickname: string | ||
| } |
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
타입 정의 중복을 피해주세요.
Assignee 인터페이스가 AssigneeList.tsx에서도 동일하게 정의되어 있습니다. 타입 정의를 별도 파일로 분리하거나 한 곳에서만 정의하고 다른 곳에서 import하도록 리팩터링하는 것이 좋겠습니다.
-export interface Assignee {
- userId: number
- nickname: string
-}별도의 타입 파일 (예: src/app/features/dashboard_Id/type/Assignee.type.ts)을 생성하고 해당 타입을 export하여 사용하세요.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/lib/getDashboardMembers.ts around lines 3 to 6,
the Assignee interface is duplicated in AssigneeList.tsx. To fix this, create a
separate type definition file such as
src/app/features/dashboard_Id/type/Assignee.type.ts, move the Assignee interface
there, export it, and then import and use this shared type in both
getDashboardMembers.ts and AssigneeList.tsx to avoid duplication.
|
|
||
| interface ModalProps { | ||
| children: React.ReactNode | ||
| onClose: () => void |
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
onClose 콜백 props가 사용되지 않음
onClose props가 정의되어 있지만 모달 내에서 실제로 사용되지 않고 있습니다. 사용자가 모달 외부를 클릭하거나 ESC 키를 눌렀을 때 모달을 닫을 수 있도록 기능을 추가하는 것을 고려해보세요.
다음과 같이 onClose 기능을 추가할 수 있습니다:
return createPortal(
- <div className="fixed inset-0 flex items-center justify-center bg-black/40">
+ <div
+ className="fixed inset-0 flex items-center justify-center bg-black/40"
+ onClick={onClose}
+ >
<div className="BG-white h-970 w-584 overflow-y-scroll rounded-16 p-32 shadow-lg [mask-image:radial-gradient(white_100%,transparent_100%)]">
{children}
</div>
</div>,추가로 ESC 키 처리를 위한 useEffect 훅도 고려해볼 수 있습니다.
Also applies to: 7-7
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/Card/cardFormModals/CreateCardModal.tsx around
lines 5 to 7, the onClose callback prop is defined but not used. To fix this,
integrate the onClose function to close the modal when the user clicks outside
the modal area or presses the ESC key. Implement an event listener using a
useEffect hook to detect the ESC key press and call onClose accordingly, and
ensure clicking outside the modal triggers onClose as well.
| if (!data.dueDate) delete payload.dueDate | ||
| if (!data.imageUrl || !preview) delete payload.imageUrl // delete로 아예 필드의 해당 key를 지워야, 서버가 "없음"으로 인식함.. | ||
| console.log('🌀', data.imageUrl) |
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.
성능 이슈: delete 연산자 사용을 피하고 디버그 코드를 제거해주세요.
정적 분석 도구에서 지적한 대로 delete 연산자는 성능에 영향을 줄 수 있습니다. 또한 프로덕션 코드에서 console.log는 제거해야 합니다.
- if (!data.dueDate) delete payload.dueDate
- if (!data.imageUrl || !preview) delete payload.imageUrl // delete로 아예 필드의 해당 key를 지워야, 서버가 "없음"으로 인식함..
- console.log('🌀', data.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.
| if (!data.dueDate) delete payload.dueDate | |
| if (!data.imageUrl || !preview) delete payload.imageUrl // delete로 아예 필드의 해당 key를 지워야, 서버가 "없음"으로 인식함.. | |
| console.log('🌀', data.imageUrl) | |
| if (!data.dueDate) payload.dueDate = undefined | |
| if (!data.imageUrl || !preview) payload.imageUrl = undefined |
🤖 Prompt for AI Agents
In src/app/features/dashboard_Id/Card/cardFormModals/CreateCardForm.tsx around
lines 89 to 91, avoid using the delete operator on payload keys due to
performance concerns and remove the console.log debug statement. Instead of
deleting keys, set payload.dueDate and payload.imageUrl to undefined or null
when their corresponding data values are falsy, and remove the console.log line
entirely to clean up production code.
📌 변경 사항 개요
✨ 요약
📝 상세 내용
🔗 관련 이슈
🖼️ 스크린샷
✅ 체크리스트
💡 참고 사항
Summary by CodeRabbit
신규 기능
버그 수정
스타일
리팩터링
문서화
기타