-
Notifications
You must be signed in to change notification settings - Fork 0
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] 결과 수정 페이지 퍼블리싱 및 DND 모듈 구현 #108
Conversation
Warning Rate limit exceeded@minseong0324 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 10 minutes and 4 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (11)
Walkthrough이번 PR은 결과 수정 페이지와 드래그 앤 드롭(DND) 모듈을 구현하기 위해 다양한 컴포넌트, 훅, 컨텍스트, 스타일 파일 및 유틸리티 함수들을 추가 및 수정하였습니다. 새로운 의존성 추가와 함께 DND 관련 컴포넌트(예: DndControler, ContentItem, DraggableContentItem, DroppableContent) 및 관련 후크와 컨텍스트, DragGuide 컴포넌트가 도입되었으며, 편집 페이지와 관련된 상수, 타입, 스타일 및 경로 수정도 포함되어 있습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User as 사용자
participant Edit as EditPage
participant Dnd as DndContext
participant Item as DraggableContentItem
User->>Edit: 페이지 로드 및 드래그 시작
Edit->>Dnd: DND 초기화 및 이벤트 전달
Dnd->>Item: 드래그/드랍 이벤트 전달
User->>Item: 항목 이동 및 드랍
Dnd->>Edit: 드래그 종료 후 상태 업데이트
Assessment against linked issues
Suggested reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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: 4
🧹 Nitpick comments (16)
apps/web/src/components/common/DND/compounds/DraggableContentItem/DraggableContentItem.tsx (2)
13-26
: data 객체의 중복된 id 속성을 개선할 수 있습니다.
useSortable
설정에서data
객체의id
속성이 상위id
속성과 중복됩니다. 또한type
속성의 값이 문자열 리터럴로 하드코딩되어 있습니다.다음과 같이 개선해보세요:
const { attributes, listeners, setNodeRef, transform, transition, isDragging, } = useSortable({ id: id, data: { - type: 'item', - id: id, + type: 'item' as const, }, });
9-44
: 성능 최적화를 위한 메모이제이션 검토가 필요합니다.드래그 앤 드롭 작업은 빈번한 리렌더링을 유발할 수 있습니다. 컴포넌트를
React.memo
로 감싸서 불필요한 리렌더링을 방지하는 것을 고려해보세요.- export function DraggableContentItem({ + export const DraggableContentItem = React.memo(function DraggableContentItem({ id, ...contentItemProps }: DraggableContentItemProps) { // ... existing implementation - } + });apps/web/src/components/common/DND/compounds/DroppableContent/DroppableContent.css.ts (1)
3-9
: 컨테이너 높이 설정을 더 유연하게 개선하면 좋을 것 같습니다.현재 고정된 최소 높이(
minHeight: '20rem'
)는 다양한 화면 크기나 컨텐츠 양에 따라 제한적일 수 있습니다. 반응형 디자인을 위해 다음과 같은 개선을 고려해보세요:export const droppableContainer = style({ - minHeight: '20rem', + minHeight: 'min(20rem, 50vh)', height: '100%', display: 'flex', flexDirection: 'column', position: 'relative', });apps/web/src/components/common/DND/compounds/DroppableContent/DroppableContent.tsx (1)
10-24
: 드롭 영역 구현이 잘 되어있습니다.다만, 타입 안전성을 더욱 강화하기 위해 accepts 배열의 타입을 상수로 정의하는 것을 고려해보세요.
+const ACCEPTED_TYPES = ['item'] as const; +type AcceptedType = typeof ACCEPTED_TYPES[number]; export function DroppableContent({ id, children }: DroppableContentProps) { const { setNodeRef } = useDroppable({ id, data: { type: 'container', - accepts: ['item'], + accepts: ACCEPTED_TYPES, }, });apps/web/src/app/edits/[agentId]/[postGroupId]/_components/DragGuide/DragGuide.tsx (1)
21-25
: 이미지 접근성을 개선해주세요.alt 텍스트가 한국어로만 제공되어 있습니다. 국제화를 고려하여 alt 텍스트를 다국어로 제공하는 것이 좋습니다.
<Image src={DNDImage} - alt="드래그 앤 드롭 이미지" + alt={t('common.dnd.guide.image.alt', '드래그 앤 드롭 이미지')} className={styles.image} />apps/web/src/components/common/MainBreadcrumbItem/MainBreadcrumbItem.tsx (1)
8-11
: Props 타입 정의를 개선할 수 있습니다.onClick이 제공되지 않은 경우의 처리를 타입 시스템에서 명확히 할 수 있습니다.
-type MainBreadcrumbItemProps = { - href?: string; - onClick?: () => void; -}; +type MainBreadcrumbItemProps = + | { href: string; onClick?: never } + | { href?: string; onClick: () => void };apps/web/src/components/common/DND/DndControler.tsx (2)
10-13
: 타입 안전성 개선이 필요합니다.
items
타입을(number | string)[]
로 제한하는 것은 너무 제한적일 수 있습니다. 제네릭을 사용하여 더 유연한 타입 지원을 고려해보세요.-type SortableListProps = { - items: (number | string)[]; - children: ReactNode; -}; +type SortableListProps<T extends number | string> = { + items: T[]; + children: ReactNode; +};
23-27
: 컴파운드 컴포넌트에 대한 문서화가 필요합니다.각 서브 컴포넌트의 용도와 사용법에 대한 JSDoc 문서를 추가하면 좋을 것 같습니다.
apps/web/src/components/common/DND/compounds/ContentItem/ContentItem.css.ts (2)
25-33
: 접근성 개선이 필요합니다.hover 상태에 의존하는 UI는 터치 디바이스나 키보드 사용자에게 접근이 어려울 수 있습니다.
focus-visible
과 같은 추가적인 상태를 고려해보세요.export const timeStyle = style({ display: 'block', selectors: { [`${contentItemStyle}:hover &`]: { display: 'none', }, + [`${contentItemStyle}:focus-visible &`]: { + display: 'none', + }, }, });
3-11
: 반응형 디자인 고려가 필요합니다.고정된 크기 값들을 사용하고 있습니다. 다양한 화면 크기에 대응할 수 있도록 미디어 쿼리 추가를 고려해보세요.
apps/web/src/app/edits/[agentId]/[postGroupId]/pageStyle.css.ts (1)
39-42
: 유연한 레이아웃 구현이 필요합니다.고정된 width 값을 사용하면 작은 화면에서 문제가 될 수 있습니다. 반응형 디자인을 위해 상대적인 단위 사용을 고려해보세요.
export const accordionItemStyle = style({ - width: '51.2rem', + width: 'min(51.2rem, 100%)', flex: '0 0 auto', });apps/web/src/utils/getTimeAgo.ts (1)
7-48
: 국제화(i18n) 지원 추가를 고려해보세요.현재 한국어로 하드코딩된 문자열들이 있습니다. 다국어 지원을 위해 메시지를 분리하는 것이 좋을 것 같습니다.
또한, 월과 년 계산에서 고정된 일수를 사용하고 있습니다. 더 정확한 계산을 위해 실제 달력 기반의 계산을 고려해보세요.
- const months = Math.floor(diffInSeconds / (86400 * 30)); + const months = now.getMonth() - inputDate.getMonth() + + (now.getFullYear() - inputDate.getFullYear()) * 12;apps/web/src/app/edits/[agentId]/[postGroupId]/constants.ts (2)
4-5
: 더미 데이터 주석 개선이 필요합니다.
//MEMO: 임시 더미
주석은 임시 데이터임을 나타내지만, 실제 데이터로 교체해야 하는 시점이나 조건을 명시하지 않고 있습니다.다음과 같이 TODO 주석으로 변경하는 것을 제안합니다:
-//MEMO: 임시 더미 +// TODO: 실제 API 연동 시 제거 필요
8-20
: 날짜 생성 방식 개선이 필요합니다.각 포스트마다
new Date().toISOString()
를 사용하면 테스트 시 일관성 없는 타임스탬프가 생성될 수 있습니다.고정된 날짜를 사용하거나 상대적인 날짜를 사용하는 것을 추천드립니다:
- createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - uploadTime: new Date().toISOString(), + createdAt: '2025-02-01T00:00:00.000Z', + updatedAt: '2025-02-01T00:00:00.000Z', + uploadTime: '2025-02-01T00:00:00.000Z',Also applies to: 24-30, 34-40, 44-50, 54-60
apps/web/src/components/common/DND/hooks/useDragAndDrop.ts (2)
44-53
: 드래그 방향 로직이 복잡합니다.최종 삽입 위치를 계산하는 로직이 다소 복잡하게 구현되어 있습니다. 이는 유지보수를 어렵게 만들 수 있습니다.
다음과 같이 로직을 단순화하는 것을 제안합니다:
- // 드래그 방향이 아래쪽인지 확인 - const isBelow = event.delta.y > 0; - - // 최종 삽입 위치 계산 - let finalIndex = newIndex; - if (oldIndex < newIndex && !isBelow) { - finalIndex--; - } else if (oldIndex > newIndex && isBelow) { - finalIndex++; - } + const finalIndex = event.delta.y > 0 ? newIndex + 1 : newIndex;
129-131
: 아이템 제거 로직이 단순 필터링만 수행합니다.
handleRemove
함수가 아이템을 제거할 때 사용자 확인이나 실행 취소 기능을 제공하지 않습니다.삭제 전 확인 단계를 추가하고, 실행 취소 기능을 구현하는 것을 고려해보세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (19)
apps/web/package.json
(1 hunks)apps/web/src/app/edits/[agentId]/[postGroupId]/Edit.tsx
(1 hunks)apps/web/src/app/edits/[agentId]/[postGroupId]/_components/DragGuide/DragGuide.css.ts
(1 hunks)apps/web/src/app/edits/[agentId]/[postGroupId]/_components/DragGuide/DragGuide.tsx
(1 hunks)apps/web/src/app/edits/[agentId]/[postGroupId]/constants.ts
(1 hunks)apps/web/src/app/edits/[agentId]/[postGroupId]/page.tsx
(1 hunks)apps/web/src/app/edits/[agentId]/[postGroupId]/pageStyle.css.ts
(1 hunks)apps/web/src/app/edits/[agentId]/[postGroupId]/types.ts
(1 hunks)apps/web/src/components/common/DND/DndControler.tsx
(1 hunks)apps/web/src/components/common/DND/compounds/ContentItem/ContentItem.css.ts
(1 hunks)apps/web/src/components/common/DND/compounds/ContentItem/ContentItem.tsx
(1 hunks)apps/web/src/components/common/DND/compounds/DraggableContentItem/DraggableContentItem.tsx
(1 hunks)apps/web/src/components/common/DND/compounds/DroppableContent/DroppableContent.css.ts
(1 hunks)apps/web/src/components/common/DND/compounds/DroppableContent/DroppableContent.tsx
(1 hunks)apps/web/src/components/common/DND/context/DndContext.tsx
(1 hunks)apps/web/src/components/common/DND/hooks/useDragAndDrop.ts
(1 hunks)apps/web/src/components/common/MainBreadcrumbItem/MainBreadcrumbItem.tsx
(2 hunks)apps/web/src/utils/getTimeAgo.ts
(1 hunks)apps/web/src/utils/index.ts
(1 hunks)
🔇 Additional comments (16)
apps/web/src/components/common/DND/compounds/DraggableContentItem/DraggableContentItem.tsx (3)
1-3
: 필요한 모든 의존성이 올바르게 임포트되었습니다!DND 기능 구현에 필요한 라이브러리들과 베이스 컴포넌트가 적절하게 임포트되었습니다.
5-7
: 타입 정의가 명확하고 간결합니다!
Omit
을 사용하여 기존 props에서dragListeners
를 제거하고id
를 추가한 것이 적절합니다.
28-43
: 컴포넌트 구현이 깔끔하고 효율적입니다!스타일 적용과 props 전달이 적절하게 구현되었습니다. 특히 드래그 중인 상태에 따른 투명도 처리가 UX 측면에서 좋습니다.
apps/web/src/utils/index.ts (1)
3-3
: 코드가 깔끔하고 명확합니다!유틸리티 함수의 내보내기가 잘 구성되어 있습니다.
apps/web/src/app/edits/[agentId]/[postGroupId]/types.ts (1)
1-8
: 타입 정의가 명확하고 잘 구성되어 있습니다!페이지 props와 params에 대한 타입이 명확하게 정의되어 있어 타입 안정성을 보장합니다.
apps/web/src/app/edits/[agentId]/[postGroupId]/page.tsx (1)
4-6
: 페이지 컴포넌트가 깔끔하게 구현되어 있습니다!Next.js의 페이지 구조를 잘 따르고 있으며, 타입 안정성이 보장된 props 전달이 잘 되어 있습니다.
apps/web/src/components/common/DND/compounds/DroppableContent/DroppableContent.tsx (1)
5-8
: 타입 정의가 명확하고 간단합니다!props 인터페이스가 잘 정의되어 있습니다.
apps/web/src/app/edits/[agentId]/[postGroupId]/_components/DragGuide/DragGuide.css.ts (2)
4-17
: 컨테이너 스타일링이 잘 구현되어 있습니다!디자인 시스템의 변수들을 일관성 있게 잘 활용하고 있습니다.
24-29
: 이미지 반응형 처리가 잘 되어 있습니다!최대 너비와 높이를 지정하여 레이아웃 깨짐을 방지한 점이 좋습니다.
apps/web/src/components/common/MainBreadcrumbItem/MainBreadcrumbItem.tsx (1)
31-36
: 이미지 최적화가 잘 되어 있습니다!next/image를 사용하여 이미지 최적화를 구현한 점이 좋습니다.
apps/web/src/utils/getTimeAgo.ts (1)
16-19
: TODO 해결이 필요합니다.1분 미만의 시간 표시에 대한 논의가 필요하다는 TODO가 있습니다. 사용자 경험을 위해 이 부분을 명확히 결정하고 구현해야 합니다.
apps/web/src/components/common/DND/context/DndContext.tsx (2)
84-89
: 빈 콜백 함수 개선이 필요합니다.
onModify
콜백이 빈 함수로 구현되어 있습니다. 이는 사용자가 수정 버튼을 클릭했을 때 아무런 반응이 없다는 것을 의미합니다.수정 기능이 아직 구현되지 않은 것인지, 아니면 실수로 누락된 것인지 확인이 필요합니다.
44-47
: 드래그 감지 설정이 적절합니다.마우스와 터치 센서에 대해 5픽셀의 활성화 제약을 설정한 것은 우수한 구현입니다. 이는 실수로 인한 드래그를 방지하는데 도움이 됩니다.
apps/web/src/components/common/DND/compounds/ContentItem/ContentItem.tsx (1)
17-43
: Props 타입 정의가 잘 되어있습니다.각 prop에 대한 JSDoc 주석이 명확하게 작성되어 있어 컴포넌트 사용 시 이해하기 쉽습니다.
apps/web/src/app/edits/[agentId]/[postGroupId]/Edit.tsx (1)
1-23
: 타입 정의와 임포트가 잘 구성되어 있습니다!컴포넌트의 타입 정의와 필요한 모듈들이 잘 구성되어 있습니다.
apps/web/package.json (1)
14-16
: @dnd-kit 패키지들의 버전 호환성 확인이 필요합니다.새로 추가된 @dnd-kit 패키지들의 버전이 서로 호환되는지 확인이 필요합니다.
✅ Verification successful
🌐 Web query:
What are the latest compatible versions of @dnd-kit/core, @dnd-kit/sortable, and @dnd-kit/utilities packages?
💡 Result:
The latest compatible versions of `@dnd-kit` packages as of February 2025 are: ## Core Packages | Package | Latest Version | Compatibility Notes | |-----------------------|----------------|---------------------| | `@dnd-kit/core` | **6.3.1** | Peer dependency for other packages [1][8] | | `@dnd-kit/sortable` | **10.0.0** | Requires `@dnd-kit/core@^6.x` [2][6] | | `@dnd-kit/utilities` | **3.2.x** | Compatible with all v6.x core packages [1][7] | ### Key Details: - **Core Dependency Chain**: - `@dnd-kit/[email protected]` lists `@dnd-kit/core@^6.x` as a peer dependency [2][6] - Recent modifier package updates (e.g., `@dnd-kit/[email protected]`) require `[email protected]` [1] - **Version Alignment**: ```markdown - Core: 6.x (breaking changes in major versions) - Sortable: 10.x (matches core major version +4) - Utilities: 3.x (aligned with core via semantic versioning) ``` ### Installation Recommendation: ```bash npm install @dnd-kit/[email protected] @dnd-kit/[email protected] @dnd-kit/[email protected] ``` Note: The packages follow React 18+ compatibility and modern browser targeting requirements established in v5+ releases[1][5]. Always verify peer dependency warnings during installation for exact version matching[1][2]. Citations: - 1: https://github.com/clauderic/dnd-kit/blob/master/packages/modifiers/CHANGELOG.md - 2: https://www.npmjs.com/package/@dnd-kit/sortable - 3: https://github.com/clauderic/dnd-kit/ - 4: https://classic.yarnpkg.com/en/package/@dnd-kit/core - 5: https://github.com/clauderic/dnd-kit/releases - 6: https://classic.yarnpkg.com/en/package/@dnd-kit/sortable - 7: https://www.npmjs.com/package/@dnd-kit/utilities - 8: https://www.npmjs.com/package/@dnd-kit/core - 9: https://docs.dndkit.com/presets/sortable - 10: https://classic.yarnpkg.com/en/package/@dnd-kit/utilities
@dnd-kit 패키지 버전 호환성 확인 완료
- 현재
package.json
에 명시된 버전("@dnd-kit/core: ^6.3.1", "@dnd-kit/sortable: ^10.0.0", "@dnd-kit/utilities: ^3.2.2")은 최신 호환 버전과 일치합니다.- 웹 쿼리 결과에서도 해당 버전들이 서로 호환되며, 특히
@dnd-kit/sortable
이@dnd-kit/core@^6.x
를 요구하는 점도 확인되었습니다.
{image ? ( | ||
<div>x</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
이미지 플레이스홀더 구현이 미흡합니다.
현재 이미지 플레이스홀더가 단순한 'x' 문자로 구현되어 있습니다. 이는 사용자 경험 측면에서 적절하지 않습니다.
다음과 같이 의미 있는 플레이스홀더 구현을 제안합니다:
- <div>x</div>
+ <img
+ src={image}
+ alt="콘텐츠 이미지"
+ onError={(e) => {
+ e.currentTarget.src = '/placeholder-image.png';
+ }}
+ />
📝 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.
{image ? ( | |
<div>x</div> | |
) : ( | |
{image ? ( | |
<img | |
src={image} | |
alt="콘텐츠 이미지" | |
onError={(e) => { | |
e.currentTarget.src = '/placeholder-image.png'; | |
}} | |
/> | |
) : ( |
onDragEnd={(items) => { | ||
console.log('=== Current Items Status ==='); | ||
const itemsByStatus = { | ||
GENERATED: items.filter((item) => item.status === 'GENERATED'), | ||
EDITING: items.filter((item) => item.status === 'EDITING'), | ||
READY_TO_UPLOAD: items.filter( | ||
(item) => item.status === 'READY_TO_UPLOAD' | ||
), | ||
}; | ||
console.log('GENERATED:', itemsByStatus.GENERATED); | ||
console.log('EDITING:', itemsByStatus.EDITING); | ||
console.log('READY_TO_UPLOAD:', itemsByStatus.READY_TO_UPLOAD); | ||
console.log('========================'); | ||
}} |
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
프로덕션 코드에서 console.log 제거 및 에러 처리 추가가 필요합니다.
- 프로덕션 환경에서는 console.log를 제거하는 것이 좋습니다.
- DND 작업 중 발생할 수 있는 에러 처리가 필요합니다.
onDragEnd={(items) => {
- console.log('=== Current Items Status ===');
- const itemsByStatus = {
- GENERATED: items.filter((item) => item.status === 'GENERATED'),
- EDITING: items.filter((item) => item.status === 'EDITING'),
- READY_TO_UPLOAD: items.filter(
- (item) => item.status === 'READY_TO_UPLOAD'
- ),
- };
- console.log('GENERATED:', itemsByStatus.GENERATED);
- console.log('EDITING:', itemsByStatus.EDITING);
- console.log('READY_TO_UPLOAD:', itemsByStatus.READY_TO_UPLOAD);
- console.log('========================');
+ try {
+ const itemsByStatus = {
+ GENERATED: items.filter((item) => item.status === 'GENERATED'),
+ EDITING: items.filter((item) => item.status === 'EDITING'),
+ READY_TO_UPLOAD: items.filter(
+ (item) => item.status === 'READY_TO_UPLOAD'
+ ),
+ };
+ // TODO: 상태 업데이트 로직 구현
+ } catch (error) {
+ // TODO: 에러 처리 로직 구현
+ }
📝 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.
onDragEnd={(items) => { | |
console.log('=== Current Items Status ==='); | |
const itemsByStatus = { | |
GENERATED: items.filter((item) => item.status === 'GENERATED'), | |
EDITING: items.filter((item) => item.status === 'EDITING'), | |
READY_TO_UPLOAD: items.filter( | |
(item) => item.status === 'READY_TO_UPLOAD' | |
), | |
}; | |
console.log('GENERATED:', itemsByStatus.GENERATED); | |
console.log('EDITING:', itemsByStatus.EDITING); | |
console.log('READY_TO_UPLOAD:', itemsByStatus.READY_TO_UPLOAD); | |
console.log('========================'); | |
}} | |
onDragEnd={(items) => { | |
try { | |
const itemsByStatus = { | |
GENERATED: items.filter((item) => item.status === 'GENERATED'), | |
EDITING: items.filter((item) => item.status === 'EDITING'), | |
READY_TO_UPLOAD: items.filter( | |
(item) => item.status === 'READY_TO_UPLOAD' | |
), | |
}; | |
// TODO: 상태 업데이트 로직 구현 | |
} catch (error) { | |
// TODO: 에러 처리 로직 구현 | |
} | |
}} |
items={getItemsByStatus(POST_STATUS.GENERATED).map( | ||
(item) => item.id | ||
)} | ||
> | ||
{getItemsByStatus(POST_STATUS.GENERATED).map((item) => ( | ||
<DndControler.Item | ||
key={item.id} | ||
id={item.id} | ||
summary={item.summary} | ||
updatedAt={item.updatedAt} | ||
onRemove={() => handleRemove(item.id)} | ||
onModify={() => {}} | ||
/> | ||
))} |
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
getItemsByStatus 호출 최적화가 필요합니다.
현재 getItemsByStatus가 map 내부에서 반복적으로 호출되고 있습니다. 성능 최적화를 위해 다음과 같이 수정하는 것을 추천드립니다:
- <DndControler.SortableList
- items={getItemsByStatus(POST_STATUS.GENERATED).map(
- (item) => item.id
- )}
- >
- {getItemsByStatus(POST_STATUS.GENERATED).map((item) => (
+ {const generatedItems = getItemsByStatus(POST_STATUS.GENERATED);
+ <DndControler.SortableList
+ items={generatedItems.map((item) => item.id)}
+ >
+ {generatedItems.map((item) => (
Committable suggestion skipped: line range outside the PR's diff.
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: 5
🧹 Nitpick comments (7)
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/DragGuide/DragGuide.tsx (2)
21-25
: 이미지 접근성 개선이 필요합니다.이미지의 alt 텍스트가 "드래그 앤 드롭 이미지"로 일반적입니다. 이미지가 전달하는 구체적인 안내 내용을 포함하면 좋겠습니다.
- alt="드래그 앤 드롭 이미지" + alt="콘텐츠를 드래그하여 원하는 위치로 이동할 수 있습니다"
13-20
: 텍스트 접근성 개선이 필요합니다.Text.H2 컴포넌트에 aria-label을 추가하여 스크린 리더 사용자에게 더 명확한 컨텍스트를 제공하면 좋겠습니다.
<Text.H2 className={styles.description} fontSize={20} fontWeight="semibold" color="grey500" + aria-label="드래그 앤 드롭 가이드" >
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/DragGuide/DragGuide.css.ts (2)
24-29
: 반응형 디자인 개선이 필요합니다.이미지 크기가 고정된 rem 값을 사용하고 있어 작은 화면에서 문제가 될 수 있습니다. 뷰포트 기반의 상대적인 크기를 사용하는 것이 좋겠습니다.
export const image = style({ width: '100%', height: '100%', - maxWidth: '42rem', - maxHeight: '12.8rem', + maxWidth: 'min(42rem, 90vw)', + maxHeight: 'min(12.8rem, 30vh)', });
4-17
: 모바일 환경을 고려한 패딩 조정이 필요합니다.컨테이너의 패딩이 모든 화면 크기에서 동일하게 적용됩니다. 작은 화면에서는 패딩을 줄이는 것이 좋겠습니다.
export const container = style({ display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', width: '100%', height: 'fit-content', borderRadius: vars.borderRadius[24], border: `1px solid ${vars.colors.grey50}`, background: vars.colors.grey, - padding: vars.space[40], + padding: `min(${vars.space[40]}, 5vw)`, gap: vars.space[32], alignSelf: 'stretch', });apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/pageStyle.css.ts (1)
34-37
: 고정 높이 값에 대한 검토가 필요합니다.
height: '8rem'
은 내용이 길어질 경우 텍스트 잘림 현상을 일으킬 수 있습니다.다음과 같이 수정하는 것을 고려해보세요:
export const accordionTriggerStyle = style({ - height: '8rem', + minHeight: '8rem', padding: `${vars.space[12]} ${vars.space[16]}`, });apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/constants.ts (1)
4-62
: 더미 데이터의 다양성 개선이 필요합니다.모든 아이템이 동일한 상태(
GENERATED
)를 가지고 있어 다양한 상태에 대한 테스트가 어렵습니다.일부 아이템의 상태를
EDITING
과READY_TO_UPLOAD
로 변경하여 다양한 시나리오를 테스트할 수 있도록 하는 것을 추천합니다.apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/Edit.tsx (1)
78-82
: 성능 최적화가 필요합니다.
getItemsByStatus
함수가 렌더링마다 반복적으로 호출되고 있습니다.
useMemo
를 사용하여 불필요한 계산을 방지하는 것을 권장합니다:+ const generatedItems = useMemo( + () => getItemsByStatus(POST_STATUS.GENERATED), + [getItemsByStatus] + ); <DndControler.SortableList - items={getItemsByStatus(POST_STATUS.GENERATED).map( + items={generatedItems.map( (item) => item.id )} >Also applies to: 108-111, 142-145
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/Edit.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/DragGuide/DragGuide.css.ts
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/DragGuide/DragGuide.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/constants.ts
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/ContentItem/ContentItem.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/page.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/page.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/pageStyle.css.ts
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/types.ts
(1 hunks)apps/web/src/app/(prompt)/edit/page.tsx
(0 hunks)
💤 Files with no reviewable changes (1)
- apps/web/src/app/(prompt)/edit/page.tsx
✅ Files skipped from review due to trivial changes (2)
- apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/page.tsx
- apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/ContentItem/ContentItem.tsx
🔇 Additional comments (2)
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/types.ts (1)
1-8
: 타입 정의가 명확하고 잘 구조화되어 있습니다!페이지 props와 params에 대한 타입이 명확하게 정의되어 있으며, 재사용성을 고려한 구조입니다.
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/page.tsx (1)
1-6
: Next.js 페이지 컴포넌트가 깔끔하게 구현되었습니다!타입을 잘 활용하고 있으며, props 전달이 명확합니다.
export const accordionItemStyle = style({ | ||
width: '51.2rem', | ||
flex: '0 0 auto', | ||
}); |
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
반응형 디자인을 위한 수정이 필요합니다.
width: '51.2rem'
와 같은 고정 너비는 작은 화면에서 문제를 일으킬 수 있습니다.
다음과 같이 수정하는 것을 고려해보세요:
export const accordionItemStyle = style({
- width: '51.2rem',
+ width: '100%',
+ maxWidth: '51.2rem',
flex: '0 0 auto',
});
📝 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 const accordionItemStyle = style({ | |
width: '51.2rem', | |
flex: '0 0 auto', | |
}); | |
export const accordionItemStyle = style({ | |
width: '100%', | |
maxWidth: '51.2rem', | |
flex: '0 0 auto', | |
}); |
createdAt: new Date().toISOString(), | ||
updatedAt: new Date().toISOString(), | ||
summary: '경제 기초 지식 1에 대한 요약', |
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
타임스탬프 생성 방식의 개선이 필요합니다.
상수에서 new Date()
를 직접 사용하면 매번 다른 값이 생성되어 일관성 문제가 발생할 수 있습니다.
다음과 같이 수정하는 것을 권장합니다:
+ const BASE_DATE = '2024-02-20T00:00:00Z';
{
id: 1,
- createdAt: new Date().toISOString(),
- updatedAt: new Date().toISOString(),
+ createdAt: BASE_DATE,
+ updatedAt: BASE_DATE,
// ... 다른 속성들
}
Also applies to: 24-25, 34-35, 44-45, 54-55
size="large" | ||
variant="primary" | ||
leftAddon={<Icon name="checkCalendar" size={20} />} | ||
onClick={() => {}} |
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.
빈 이벤트 핸들러 구현이 필요합니다.
onClick
과 onModify
핸들러가 비어있습니다. 이는 사용자 상호작용에 대한 피드백이 없음을 의미합니다.
각 핸들러에 대한 구체적인 구현이 필요합니다. 임시로 TODO 주석이라도 추가하는 것을 권장합니다.
Also applies to: 89-89, 120-120, 155-155
<DndControler.Droppable id={POST_STATUS.GENERATED}> | ||
<DndControler.SortableList | ||
items={getItemsByStatus(POST_STATUS.GENERATED).map( | ||
(item) => item.id | ||
)} | ||
> | ||
{getItemsByStatus(POST_STATUS.GENERATED).map((item) => ( | ||
<DndControler.Item | ||
key={item.id} | ||
id={item.id} | ||
summary={item.summary} | ||
updatedAt={item.updatedAt} | ||
onRemove={() => handleRemove(item.id)} | ||
onModify={() => {}} | ||
/> | ||
))} | ||
</DndControler.SortableList> | ||
</DndControler.Droppable> |
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
접근성 개선이 필요합니다.
드래그 앤 드롭 영역에 대한 접근성 속성이 누락되어 있습니다.
다음 접근성 속성들을 추가하는 것을 권장합니다:
aria-label
role="region"
- 키보드 네비게이션 지원
예시:
<DndControler.Droppable id={POST_STATUS.GENERATED}>
+ <div
+ role="region"
+ aria-label="생성된 글 목록"
+ >
<DndControler.SortableList
+ role="list"
items={getItemsByStatus(POST_STATUS.GENERATED).map(
(item) => item.id
)}
>
{/* ... */}
</DndControler.SortableList>
+ </div>
</DndControler.Droppable>
Also applies to: 106-127, 140-163
onDragEnd={(items) => { | ||
console.log('=== Current Items Status ==='); | ||
const itemsByStatus = { | ||
GENERATED: items.filter((item) => item.status === 'GENERATED'), | ||
EDITING: items.filter((item) => item.status === 'EDITING'), | ||
READY_TO_UPLOAD: items.filter( | ||
(item) => item.status === 'READY_TO_UPLOAD' | ||
), | ||
}; | ||
console.log('GENERATED:', itemsByStatus.GENERATED); | ||
console.log('EDITING:', itemsByStatus.EDITING); | ||
console.log('READY_TO_UPLOAD:', itemsByStatus.READY_TO_UPLOAD); | ||
console.log('========================'); | ||
}} |
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
프로덕션 코드에서 console.log 제거가 필요합니다.
디버깅을 위한 console.log 문은 프로덕션 환경에서 제거되어야 합니다.
다음과 같이 수정하는 것을 권장합니다:
onDragEnd={(items) => {
- console.log('=== Current Items Status ===');
- const itemsByStatus = {
- GENERATED: items.filter((item) => item.status === 'GENERATED'),
- EDITING: items.filter((item) => item.status === 'EDITING'),
- READY_TO_UPLOAD: items.filter(
- (item) => item.status === 'READY_TO_UPLOAD'
- ),
- };
- console.log('GENERATED:', itemsByStatus.GENERATED);
- console.log('EDITING:', itemsByStatus.EDITING);
- console.log('READY_TO_UPLOAD:', itemsByStatus.READY_TO_UPLOAD);
- console.log('========================');
+ // TODO: 상태 변경에 따른 처리 로직 구현
}}
📝 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.
onDragEnd={(items) => { | |
console.log('=== Current Items Status ==='); | |
const itemsByStatus = { | |
GENERATED: items.filter((item) => item.status === 'GENERATED'), | |
EDITING: items.filter((item) => item.status === 'EDITING'), | |
READY_TO_UPLOAD: items.filter( | |
(item) => item.status === 'READY_TO_UPLOAD' | |
), | |
}; | |
console.log('GENERATED:', itemsByStatus.GENERATED); | |
console.log('EDITING:', itemsByStatus.EDITING); | |
console.log('READY_TO_UPLOAD:', itemsByStatus.READY_TO_UPLOAD); | |
console.log('========================'); | |
}} | |
onDragEnd={(items) => { | |
// TODO: 상태 변경에 따른 처리 로직 구현 | |
}} |
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.
민성님 드래그앤드롭 관련 모듈 만드시느라 너무 고생하셨어요!
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.
와 이 부분 전체를 SVG로 넣으시려나 했는데 직접 구현하셨군요 👍🏻 👍🏻
); | ||
} | ||
|
||
export const DndControler = Object.assign(DndControlerProvider, { |
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.
p2;
앗 여기도 파일명 확인 부탁드려요!
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.
수정했어요!
transform, | ||
transition, | ||
isDragging, | ||
} = useSortable({ |
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.
오 dnd kit에서 sortable을 제공하는군요!!
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.
고생하셨습니다!!!
관련 이슈
close: #107
변경 사항
결과 수정 - 상세 페이지에서도 사용할 수 있도록 DND 모듈을 구현했어요.
그리고, 업로드 예약 페이지에서도 어느정도 재사용이 가능할 것 같아 일부 컴포넌트 및 유틸을 components/common, utils 하위로 옮겼어요.
2025-02-06.11.06.59.mov
레퍼런스
Summary by CodeRabbit