Skip to content
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 관련 모듈 수정 #117

Merged
merged 9 commits into from
Feb 10, 2025

Conversation

minseong0324
Copy link
Contributor

@minseong0324 minseong0324 commented Feb 9, 2025

관련 이슈

close: #116

변경 사항

업로드 예약 페이지 일부 퍼블리싱 및 dnd 관련 모듈 수정을 진행했어요.

dnd 의 Item 컴포넌트에 자식으로 자유롭게 컴포넌트를 넣고, dnd overlay에도 이에 맞게 자유롭게 컴포넌트를 넣을 수 있도록 기존 ContentItem과의 결합을 분리했어요. (+ 결과 수정 > 상세 페이지에서도 반영해두었습니다!)

그리고, @kongnayeon 님께서 진행해주실 Dropdown 컴포넌트를 넣는 것을 제외한 퍼블리싱을 진행했어요.

image

레퍼런스

Summary by CodeRabbit

  • 새로운 기능
    • 드래그 앤 드롭 인터페이스가 강화되어, 아이템 드래그 시 요약 정보와 업데이트 날짜가 오버레이로 표시됩니다.
    • 새로운 스케줄 관리 페이지가 추가되어, 포스트 재정렬 및 업로드 일정을 쉽게 관리할 수 있습니다.
    • 사이드바와 일정표 등 추가 구성 요소로 편리한 일정 관리가 지원됩니다.
    • 제목과 설명을 표시하는 새로운 구성 요소가 추가되었습니다.
  • 스타일
    • 콘텐츠 항목에 ‘grab’ 커서 효과가 적용되어 사용자 인터랙션이 개선되었습니다.
    • 네비게이션 바, 테이블 행 및 제목/설명 등 UI 요소의 외관이 업데이트되었습니다.
    • 사이드바와 일정표의 스타일이 새롭게 정의되었습니다.

Copy link

coderabbitai bot commented Feb 9, 2025

Walkthrough

이번 풀 리퀘스트에서는 업로드 예약 페이지 퍼블리싱 작업과 드래그 앤 드롭(DnD) 모듈 전반의 수정이 이루어졌습니다. 기존의 인라인 DND 아이템 렌더링을 ContentItem 등 재사용 가능한 컴포넌트들을 이용하도록 개선하였고, drag overlay 렌더링 방식을 동적 처리하도록 업데이트하였습니다. 또한, 예약 기능 관련 컴포넌트(Schedule, ScheduleTable, SideBar, TableRow, TitleWithDescription 등)와 관련 스타일, 타입 정의가 추가되었으며, NavBar와 DnD 모듈 내 일부 컴포넌트 및 로직도 명칭 변경 및 리팩토링되었습니다.

Changes

File Change Summary
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/{Edit.tsx, _components/ContentItem/ContentItem.tsx, _components/ContentItem/ContentItem.css.ts, EditContent.tsx, detail/_components/EditSidebar/EditSidebar.tsx} ContentItem 컴포넌트 도입 및 DndController에 renderDragOverlay prop 추가, dragListeners 제거, 기본값 타입 업데이트 등 DND 관련 렌더링 방식 개선
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/pageStyle.css.ts 아코디언 관련 스타일(export) 삭제
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/{Schedule.tsx, _components/ScheduleTable/, _components/SideBar/, _components/TableRow/, _components/TitleWithDescription/, page.tsx, pageStyle.css.ts, type.ts} 업로드 예약 인터페이스 및 관련 테이블, 사이드바, 제목/설명 컴포넌트 등 신규 컴포넌트, 스타일, 타입 정의 추가
apps/web/src/components/common/DNDController/{DndController.tsx, compounds/*, context/DndContext.tsx, hooks/useDragAndDrop.ts} DND 모듈 리팩토링: DraggableContentItem → DraggableItem 변경, 충돌 감지 전략 변경(closestCorners), renderDragOverlay prop 추가
apps/web/src/components/common/NavBar/{NavBar.css.ts, NavBar.tsx} leftAddon, rightAddon을 새 wrapper(div with addonStyle)로 감싸 레이아웃 및 스타일 개선

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant SP as SchedulePage
    participant S as Schedule
    participant TC as DndController
    U->>SP: 페이지 접근 및 예약 데이터 요청
    SP->>S: 서버 사이드 토큰 및 데이터 페치
    S->>TC: 드래그 시작 및 항목 이동 처리
    TC->>S: 업데이트된 순서 반환
    U->>S: 포스트 수정/삭제 요청
    S->>SP: UI 갱신 후 결과 반영
Loading

Assessment against linked issues

Objective Addressed Explanation
업로드 예약 페이지 퍼블리싱 (#116)
dnd 관련 모듈 수정 (#116)

Possibly related PRs

Suggested reviewers

  • kongnayeon

Poem

나는 귀여운 토끼, 코드 숲을 뛰네
드래그와 드랍, 마법처럼 흐르고
예약 페이지는 당근처럼 반짝이며
ContentItem과 DnD, 함께 춤추네
내 귀가 쫑긋, 모두 즐거운 코드의 날!


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4c91a3c and 41d70f2.

📒 Files selected for processing (1)
  • apps/web/src/store/query/useGetAllPostsQuery.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • apps/web/src/store/query/useGetAllPostsQuery.ts

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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🔭 Outside diff range comments (3)
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/EditContent/EditContent.tsx (1)

73-83: 에러 처리 로직 추가가 필요합니다.

onSubmit 함수에 에러 처리 로직이 누락되어 있습니다. API 호출 실패 시 사용자에게 적절한 피드백을 제공하고, 입력된 프롬프트 값을 유지하는 것이 좋습니다.

  const onSubmit = (data: PromptForm) => {
    const editingPostIds = getItemsByStatus(POST_STATUS.EDITING).map(
      (item) => item.id
    );

    updatePrompt({
      prompt: data.prompt,
      postsId: editingPostIds,
+     onError: (error) => {
+       modal.alert({
+         title: '업데이트 실패',
+         description: '프롬프트 업데이트 중 오류가 발생했습니다.',
+         icon: <Modal.Icon name="notice" color="warning500" />,
+       });
+     },
+     onSuccess: () => {
+       setValue('prompt', '');
+     },
    });
-   setValue('prompt', '');
  };
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditSidebar/EditSidebar.tsx (1)

215-215: 드래그 가이드 메시지가 불완전합니다.

"수정하고 싶은 글을"이라는 메시지가 불완전해 보입니다. 다른 DragGuide 컴포넌트들처럼 완전한 문장으로 수정이 필요합니다.

-<DragGuide description="수정하고 싶은 글을" />
+<DragGuide description="수정하고 싶은 글을 끌어서 여기에 놓아주세요" />
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/ContentItem/ContentItem.tsx (1)

71-73: 이미지 플레이스홀더를 개선하세요.

현재 이미지 플레이스홀더가 의미 없는 'x' 문자를 사용하고 있습니다.

-        {image ? (
-          <div>x</div>
+        {image ? (
+          <img
+            src={image}
+            alt="콘텐츠 썸네일"
+            className={noShrinkStyle}
+            width={32}
+            height={32}
+          />
         ) : (
🧹 Nitpick comments (20)
apps/web/src/components/common/NavBar/NavBar.tsx (1)

23-24: addon 래퍼 구현이 개선되었습니다만, null 처리가 필요합니다.

addon 요소들을 스타일된 div로 래핑하여 구조가 개선되었습니다. 하지만 leftAddon이나 rightAddon이 없을 경우에도 빈 div가 렌더링됩니다.

다음과 같이 조건부 렌더링을 적용하는 것을 고려해보세요:

-      <div className={styles.addonStyle}>{leftAddon}</div>
-      <div className={styles.addonStyle}>{rightAddon}</div>
+      {leftAddon && <div className={styles.addonStyle}>{leftAddon}</div>}
+      {rightAddon && <div className={styles.addonStyle}>{rightAddon}</div>}
apps/web/src/components/common/DNDController/context/DndContext.tsx (2)

59-61: activeItem 로직이 개선되었습니다.

드래그 중인 아이템을 찾는 로직이 명확하게 구현되었습니다. 하지만 성능 최적화의 여지가 있습니다.

useMemo를 사용하여 activeItem 계산을 최적화하는 것을 고려해보세요:

-  const activeItem = dnd.activeId
-    ? dnd.items.find((item) => item.id === dnd.activeId)
-    : null;
+  const activeItem = useMemo(() => {
+    return dnd.activeId
+      ? dnd.items.find((item) => item.id === dnd.activeId)
+      : null;
+  }, [dnd.activeId, dnd.items]);

90-90: 드래그 오버레이 렌더링 로직이 개선되었습니다.

조건부 렌더링을 통해 커스텀 오버레이 구현이 가능해졌습니다. 하지만 fallback UI가 없는 경우를 고려해야 합니다.

기본 오버레이 컴포넌트를 제공하는 것을 고려해보세요:

-        {activeItem && renderDragOverlay && renderDragOverlay(activeItem)}
+        {activeItem && (renderDragOverlay
+          ? renderDragOverlay(activeItem)
+          : <DefaultDragOverlay item={activeItem} />
+        )}
apps/web/src/components/common/DNDController/hooks/useDragAndDrop.ts (2)

153-178: 동일 상태 내 재정렬 로직 최적화 제안

현재 구현은 정상적으로 작동하지만, 다음과 같은 개선사항을 고려해보시면 좋을 것 같습니다:

  1. 불필요한 상태 업데이트를 방지하기 위해 oldIndexnewIndex가 동일한 경우를 체크
  2. 재사용 가능한 정렬 로직을 별도 함수로 추출

다음과 같이 코드를 개선해보세요:

 setItems((prev) => {
   const itemsByStatus = createItemsByStatus(prev);
   const statusItems = itemsByStatus[draggedItem.status];
   const oldIndex = statusItems.findIndex(
     (item) => item.id === draggedItemId
   );
   const newIndex = statusItems.findIndex((item) => item.id === overId);
+  if (oldIndex === newIndex) return prev;
   const reorderedItems = arrayMove(statusItems, oldIndex, newIndex);

   reorderedItems.forEach((item, index) => {
     item.displayOrder = index + 1;
   });

   itemsByStatus[draggedItem.status] = reorderedItems;
   const newItems = updateDisplayOrders(
     Object.values(itemsByStatus).flat()
   );
   onDragEnd?.(newItems);
   return newItems;
 });

44-46: 타입 안전성 개선 제안

드래그된 아이템을 찾는 로직에 타입 가드를 추가하면 런타임 안전성이 향상될 것 같습니다.

다음과 같이 타입 가드를 추가해보세요:

-const draggedItemId = Number(active.id);
-const draggedItem = items.find((item) => item.id === draggedItemId);
-if (!draggedItem) return;
+const draggedItemId = Number(active.id);
+if (isNaN(draggedItemId)) return;
+const draggedItem = items.find((item) => item.id === draggedItemId);
+if (!draggedItem || typeof draggedItem.status !== 'string') return;

Also applies to: 118-120

apps/web/src/components/common/DNDController/compounds/DraggableItem/DraggableItem.tsx (1)

9-45: 컴포넌트 구현 개선사항 검토

컴포넌트가 더 범용적이고 재사용 가능하도록 개선되었습니다:

  • children prop을 통해 유연한 콘텐츠 렌더링이 가능해졌습니다
  • 기본 스타일링과 이벤트 처리가 잘 구현되어 있습니다

하나의 개선 제안이 있습니다:

className에 대한 타입 안전성을 높이기 위해 CSS 모듈이나 styled-components 사용을 고려해보세요.

apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/Edit.tsx (2)

77-82: 드래그 오버레이 구현 검토

드래그 중인 아이템에 대한 시각적 피드백이 잘 구현되었습니다. 다만 몇 가지 개선사항을 제안드립니다:

  1. 성능 최적화를 위해 renderDragOverlay를 useCallback으로 메모이제이션하는 것을 고려해보세요.
  2. activeItem이 undefined일 경우에 대한 처리가 필요할 수 있습니다.

예시 코드:

+ const renderDragOverlay = useCallback((activeItem) => {
+   if (!activeItem) return null;
    return (
      <ContentItem
        summary={activeItem.summary}
        updatedAt={activeItem.updatedAt}
      />
    );
+ }, []);

65-65: 키 생성 로직 검토

posts 배열의 id를 이용한 key 생성이 적절히 구현되었습니다. 다만, 성능상의 이점을 위해 다음과 같은 개선을 고려해보세요:

- key={posts.data.posts.map((p) => p.id).join(',')}
+ key={posts.data.posts.map((p) => p.id).join('_')}

문자열 연결 시 쉼표 대신 언더스코어를 사용하면 URL 인코딩이 필요한 경우에 더 안전할 수 있습니다.

apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/SideBar/SideBar.tsx (1)

10-12: 접근성 개선을 위한 제안

사이드바의 의미를 스크린 리더에 전달하기 위해 ARIA 속성을 추가하는 것이 좋습니다.

-  return <div className={style.sidebarStyle}>{children}</div>;
+  return <div className={style.sidebarStyle} role="complementary" aria-label="사이드바">{children}</div>;
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/SideBar/SideBar.css.ts (1)

4-14: 반응형 디자인 개선 제안

현재 구현은 고정된 너비와 절대 위치를 사용하고 있어 다양한 화면 크기에서 문제가 발생할 수 있습니다.

 export const sidebarStyle = style({
-  width: '44rem',
+  width: 'min(44rem, 100%)',
   height: '100%',
   backgroundColor: 'transparent',
   padding: `0 ${vars.space[40]}`,
-  position: 'absolute',
+  position: 'relative',
   top: 0,
   left: 0,
   borderRight: `1px solid ${vars.colors.grey200}`,
   paddingTop: '8rem',
 });
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/ScheduleTable/types.ts (2)

10-14: 타입 안정성 개선 제안

onDragEnd 콜백 함수의 에러 처리를 위한 타입 개선이 필요합니다.

 export type ScheduleTableProps = {
   columns: Column[];
   items: Post[];
-  onDragEnd?: (items: Post[]) => void;
+  onDragEnd?: (items: Post[]) => Promise<void> | void;
 };

4-8: Column 타입 개선 제안

width 속성의 타입을 더 구체적으로 정의하면 좋을 것 같습니다.

 export type Column = {
   id: string;
   label: string;
-  width: string;
+  width: `${number}${'px' | 'rem' | '%'}`;
 };
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TableRow/TableRow.css.ts (1)

4-10: 테이블 행 스타일이 잘 정의되어 있습니다.

cursor: grab 스타일은 드래그 앤 드롭 기능을 직관적으로 나타내며, 플렉스 레이아웃과 테두리 스타일이 적절하게 적용되어 있습니다.

드래그 중일 때의 커서 스타일도 고려해보세요:

 export const tableRowStyle = style({
   display: 'flex',
   alignItems: 'center',
   width: '100%',
   cursor: 'grab',
+  ':active': {
+    cursor: 'grabbing',
+  },
   borderBottom: `1px solid ${vars.colors.grey200}`,
 });
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TitleWithDescription/TitleWithDescription.tsx (1)

4-23: 제목과 설명을 위한 컴포넌트가 깔끔하게 구현되어 있습니다.

Text 컴포넌트를 활용한 타이포그래피 스타일링이 일관성 있게 적용되어 있습니다.

접근성 향상을 위해 시맨틱 마크업을 고려해보세요:

 export function TitleWithDescription({
   title,
   description,
 }: TitleWithDescriptionProps) {
   return (
-    <div className={style.textWrapperStyle}>
+    <section className={style.textWrapperStyle} aria-label={title}>
       <Text.H2 fontSize={28} fontWeight="bold" color="grey1000">
         {title}
       </Text.H2>
       <Text.P fontSize={18} fontWeight="medium" color="grey500">
         {description}
       </Text.P>
-    </div>
+    </section>
   );
 }
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/ScheduleTable/ScheduleTable.css.ts (1)

12-20: 테이블 스타일이 체계적으로 구성되어 있습니다.

테이블 레이아웃과 여백 처리가 잘 되어 있으나, 테두리 처리를 개선할 수 있습니다.

테이블 테두리 스타일을 더 일관성 있게 적용해보세요:

 export const table = style({
   width: '100%',
   borderCollapse: 'separate',
   borderSpacing: 0,
   backgroundColor: 'transparent',
   borderRadius: vars.borderRadius[8],
+  border: `1px solid ${vars.colors.grey200}`,
   overflow: 'hidden',
   tableLayout: 'fixed',
 });
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TableRow/TableRow.tsx (1)

20-20: 하드코딩된 텍스트를 상수로 분리하세요.

"드롭다운" 텍스트가 여러 번 반복되어 있습니다. 이를 상수로 분리하여 관리하면 유지보수가 용이해집니다.

+const DROPDOWN_TEXT = '드롭다운';

 export function TableRow({ columns, ...contentItemProps }: TableRowProps) {
   return (
     <div className={style.tableRowStyle}>
-      <div className={style.tableRowCellStyle}>
-        드롭다운
+      <div className={style.tableRowCellStyle}>
+        {DROPDOWN_TEXT}
       </div>
       // ... 다른 셀들도 동일하게 수정

Also applies to: 26-26, 32-32

apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/pageStyle.css.ts (2)

6-6: 하드코딩된 값을 테마 변수로 이동하세요.

144rem과 같은 하드코딩된 값은 테마 시스템을 통해 관리되어야 합니다.

+// theme.ts에 추가
+export const sizes = {
+  sidebar: '44rem',
+  content: '100rem',
+  mainWidth: 'calc(var(--content) + var(--sidebar))',
+} as const;

 export const mainStyle = style({
   position: 'relative',
-  minWidth: '144rem', // 100rem + 44rem
+  minWidth: vars.sizes.mainWidth,
   minHeight: '100vh',
   // ...
 });

44-54: 유사한 스타일 패턴을 재사용 가능한 믹스인으로 분리하세요.

sideBarContentWrapperStyledropdownWrapperStyle이 유사한 flexbox 패턴을 사용하고 있습니다.

+const flexColumnMixin = style({
+  display: 'flex',
+  flexDirection: 'column',
+});

 export const sideBarContentWrapperStyle = style([
+  flexColumnMixin,
   {
-    display: 'flex',
-    flexDirection: 'column',
     gap: vars.space[40],
   },
 ]);

 export const dropdownWrapperStyle = style([
+  flexColumnMixin,
   {
-    display: 'flex',
-    flexDirection: 'column',
     gap: vars.space[16],
   },
 ]);
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/ScheduleTable/ScheduleTable.tsx (1)

68-79: 데이터 매핑 최적화가 필요합니다.

data.map이 두 번 호출되어 불필요한 반복이 발생하고 있습니다.

-          <DndController.SortableList items={data.map((item) => item.id)}>
-            {data.map((item) => (
+          <DndController.SortableList
+            items={data.map((item) => ({
+              id: item.id,
+              element: (
               <DndController.Item id={item.id} key={item.id}>
                 <TableRow
                   columns={columns}
                   onModify={() => handleModify(item.id)}
                   onRemove={() => handleDeletePost(item.id)}
                   {...item}
                 />
               </DndController.Item>
+              ),
+            }))}
+          >
+            {(item) => item.element}
-            ))}
           </DndController.SortableList>
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/Schedule.tsx (1)

29-50: 칼럼 설정을 상수 파일로 분리 권장

칼럼 설정이 컴포넌트 내부에 하드코딩되어 있어 유지보수가 어려울 수 있습니다.

constants.ts 파일을 생성하여 다음과 같이 분리하는 것을 제안드립니다:

// constants.ts
export const SCHEDULE_TABLE_COLUMNS: Column[] = [
  {
    id: 'date',
    label: '날짜 변경',
    width: '16.6rem',
  },
  // ... 나머지 칼럼 설정
];

// Schedule.tsx에서는 다음과 같이 사용
import { SCHEDULE_TABLE_COLUMNS } from './constants';
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2ac4e66 and 4c91a3c.

📒 Files selected for processing (26)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/Edit.tsx (3 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/ContentItem/ContentItem.css.ts (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/ContentItem/ContentItem.tsx (3 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/EditContent/EditContent.tsx (4 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditSidebar/EditSidebar.tsx (5 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/pageStyle.css.ts (0 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/Schedule.tsx (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/ScheduleTable/ScheduleTable.css.ts (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/ScheduleTable/ScheduleTable.tsx (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/ScheduleTable/types.ts (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/SideBar/SideBar.css.ts (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/SideBar/SideBar.tsx (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TableRow/TableRow.css.ts (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TableRow/TableRow.tsx (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TitleWithDescription/TitleWithDescription.css.ts (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TitleWithDescription/TitleWithDescription.tsx (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/page.tsx (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/pageStyle.css.ts (1 hunks)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/type.ts (1 hunks)
  • apps/web/src/components/common/DNDController/DndController.tsx (2 hunks)
  • apps/web/src/components/common/DNDController/compounds/DraggableItem/DraggableItem.tsx (2 hunks)
  • apps/web/src/components/common/DNDController/compounds/index.ts (1 hunks)
  • apps/web/src/components/common/DNDController/context/DndContext.tsx (5 hunks)
  • apps/web/src/components/common/DNDController/hooks/useDragAndDrop.ts (3 hunks)
  • apps/web/src/components/common/NavBar/NavBar.css.ts (1 hunks)
  • apps/web/src/components/common/NavBar/NavBar.tsx (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/pageStyle.css.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/type.ts
🔇 Additional comments (20)
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/ContentItem/ContentItem.css.ts (2)

11-11: 드래그 가능한 요소임을 시각적으로 표시하는 커서 스타일이 추가되었습니다.

사용자 경험 향상을 위해 드래그 가능한 요소임을 직관적으로 알 수 있도록 'grab' 커서가 적용되었습니다.


3-46: 스타일 구조가 잘 정리되어 있습니다.

각 스타일이 명확한 목적을 가지고 분리되어 있으며, 선택자를 활용한 호버 효과도 깔끔하게 구현되어 있습니다. 특히:

  • contentItemStyle: 기본 레이아웃과 드래그 인터랙션
  • summaryStyle: 텍스트 오버플로우 처리
  • timeStyle & iconHoverStyle: 호버 시 동작하는 UI 전환
apps/web/src/components/common/NavBar/NavBar.css.ts (1)

31-34: 새로운 addon 스타일이 적절하게 구현되었습니다.

flex 컨테이너를 사용하여 addon 요소들을 중앙 정렬하는 스타일이 깔끔하게 구현되었습니다.

apps/web/src/components/common/DNDController/context/DndContext.tsx (3)

10-10: 충돌 감지 전략이 변경되었습니다.

closestCenter에서 closestCorners로 변경되었습니다. 이는 드래그 앤 드롭 시 아이템 위치 결정 방식에 영향을 미칩니다.

드래그 앤 드롭 동작이 의도한 대로 작동하는지 확인해 주세요. 특히 아이템이 많은 경우나 아이템 크기가 다양한 경우에 대해 테스트가 필요합니다.


23-23: 커스텀 드래그 오버레이 렌더링 기능이 추가되었습니다.

renderDragOverlay 옵션 prop이 추가되어 드래그 중인 아이템의 시각적 표현을 커스터마이즈할 수 있게 되었습니다.


82-84: 드롭 영역 측정 전략이 적절합니다.

MeasuringStrategy.Always를 사용하여 드롭 영역을 지속적으로 측정하는 것은 정확한 드래그 앤 드롭을 위해 좋은 선택입니다.

apps/web/src/components/common/DNDController/hooks/useDragAndDrop.ts (1)

88-88: 상태 업데이트 로직이 개선되었습니다!

상태 업데이트 후 바로 정렬된 아이템을 반환하도록 수정된 것이 좋습니다. 이는 코드의 일관성과 예측 가능성을 높여줍니다.

Also applies to: 110-110

apps/web/src/components/common/DNDController/compounds/index.ts (1)

1-2: 컴포넌트 구조 변경 검토

ContentItem의 경로가 더 구체적인 위치로 이동되었고, DraggableContentItem이 DraggableItem으로 대체되었습니다. 이러한 변경은 컴포넌트의 재사용성과 유지보수성을 향상시킬 것으로 보입니다.

apps/web/src/components/common/DNDController/DndController.tsx (1)

6-6: DndController 컴포넌트 업데이트 확인

DraggableContentItem에서 DraggableItem으로의 변경이 일관되게 적용되었습니다. 이는 compounds 디렉토리의 변경사항과 잘 동기화되어 있습니다.

Also applies to: 25-25

apps/web/src/components/common/DNDController/compounds/DraggableItem/DraggableItem.tsx (1)

5-7: 타입 정의 개선사항 검토

Props 타입이 더 유연하게 개선되었습니다:

  • id 타입이 number | string으로 확장되어 더 다양한 사용 사례를 지원합니다
  • ComponentPropsWithoutRef를 활용하여 HTML div 요소의 props를 적절히 상속받습니다
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/_components/EditContent/EditContent.tsx (1)

19-19: 컴포넌트 재사용성 개선이 잘 이루어졌습니다!

ContentItem 컴포넌트를 도입하여 중복 코드를 제거하고 일관된 UI를 제공하도록 개선되었습니다.

Also applies to: 127-135, 193-201, 228-235

apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditSidebar/EditSidebar.tsx (2)

48-48: TODO 주석들을 이슈로 트래킹해야 합니다.

여러 TODO 주석들이 있습니다:

  1. param 주입 방식 수정
  2. 스켈레톤 데이터 관련
  3. 중복되는 로직 컴포넌트화
  4. 제어 컴포넌트 수정

이러한 개선 사항들을 이슈로 생성하여 체계적으로 관리하면 좋겠습니다.

이슈들을 생성해드릴까요?

Also applies to: 96-96, 106-106, 122-122


320-325: 드래그 오버레이 구현이 잘 되었습니다!

ContentItem을 활용하여 드래그 중인 아이템의 시각적 피드백을 일관성 있게 제공하고 있습니다.

apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TitleWithDescription/TitleWithDescription.css.ts (1)

4-9: 스타일 구현이 깔끔합니다!

flex 레이아웃을 사용한 구현이 적절하며, 테마 변수를 일관되게 활용하고 있습니다.

apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TableRow/TableRow.css.ts (1)

12-44: 테이블 셀과 헤더 스타일이 적절히 구성되어 있습니다.

플렉스 레이아웃을 사용한 정렬과 flexShrink: 0을 통한 크기 유지가 잘 되어 있습니다.

apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/page.tsx (1)

7-20: 서버 사이드 데이터 페칭이 적절하게 구현되어 있습니다.

ServerFetchBoundary를 활용한 데이터 페칭 처리와 토큰 관리가 잘 되어 있습니다.

apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/ScheduleTable/ScheduleTable.css.ts (1)

27-44: 헤더 셀 스타일이 상세하게 정의되어 있습니다.

텍스트 스타일과 패딩 처리가 디자인 시스템을 잘 따르고 있습니다.

apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TableRow/TableRow.tsx (1)

9-11: 타입 정의에 필수 컬럼 개수를 명시하세요.

columns 배열의 최소 길이가 명시되어 있지 않아 런타임 에러가 발생할 수 있습니다.

 type TableRowProps = Omit<ContentItemProps, 'dragListeners'> & {
-  columns: Column[];
+  columns: [Column, Column, Column, Column];  // 정확히 4개의 컬럼이 필요함을 명시
 } & Post;
✅ Verification successful

컬럼 길이 정의 필요성 검증 완료

현재 코드에서는 columns가 임의 길이의 배열로 정의되어 있어, 4개의 컬럼이 반드시 필요할 경우 런타임 에러의 위험이 존재합니다. 제안하신 수정안처럼 columns 타입을 튜플 [Column, Column, Column, Column]으로 변경하면, 4개의 컬럼만이 허용되어 보다 안전한 타입 검증을 할 수 있습니다.

• 파일 위치: apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/_components/TableRow/TableRow.tsx
• 변경 제안은 columns의 타입을 배열(Column[])에서 4개의 Column으로 구성된 튜플로 명시하여, 런타임 에러 가능성을 줄이는데 효과적입니다.

apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/schedule/Schedule.tsx (2)

1-18: LGTM! 임포트 구성이 잘 되어있습니다.

필요한 모든 컴포넌트와 훅이 적절하게 임포트되어 있습니다.


88-89: TODO 주석 처리 필요

드롭다운 컴포넌트 구현이 필요한 상태입니다.

@kongnayeon님이 구현하실 예정이라고 PR 설명에 명시되어 있습니다. 해당 작업이 완료될 때까지 이 PR의 머지를 보류해야 할지 확인이 필요합니다.

Comment on lines +16 to +33
<div
className={style.tableRowCellStyle}
style={{ width: columns?.[0]?.width ?? 'auto' }}
>
드롭다운
</div>
<div
className={style.tableRowCellStyle}
style={{ width: columns?.[1]?.width ?? 'auto' }}
>
드롭다운
</div>
<div
className={style.tableRowCellStyle}
style={{ width: columns?.[2]?.width ?? 'auto' }}
>
드롭다운
</div>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

반복되는 셀 렌더링 로직을 리팩토링하세요.

동일한 패턴의 셀이 3번 반복되고 있습니다. 이를 map 함수를 사용하여 리팩토링하면 코드의 중복을 줄일 수 있습니다.

+const DROPDOWN_CELLS_COUNT = 3;

 export function TableRow({ columns, ...contentItemProps }: TableRowProps) {
   return (
     <div className={style.tableRowStyle}>
-      <div
-        className={style.tableRowCellStyle}
-        style={{ width: columns?.[0]?.width ?? 'auto' }}
-      >
-        드롭다운
-      </div>
-      // ... 반복되는 셀들
+      {Array.from({ length: DROPDOWN_CELLS_COUNT }).map((_, index) => (
+        <div
+          key={index}
+          className={style.tableRowCellStyle}
+          style={{ width: columns?.[index]?.width ?? 'auto' }}
+        >
+          드롭다운
+        </div>
+      ))}
       <div className={style.contentItemWrapper}>
         <ContentItem {...contentItemProps} />
       </div>
     </div>
   );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
className={style.tableRowCellStyle}
style={{ width: columns?.[0]?.width ?? 'auto' }}
>
드롭다운
</div>
<div
className={style.tableRowCellStyle}
style={{ width: columns?.[1]?.width ?? 'auto' }}
>
드롭다운
</div>
<div
className={style.tableRowCellStyle}
style={{ width: columns?.[2]?.width ?? 'auto' }}
>
드롭다운
</div>
const DROPDOWN_CELLS_COUNT = 3;
export function TableRow({ columns, ...contentItemProps }: TableRowProps) {
return (
<div className={style.tableRowStyle}>
{Array.from({ length: DROPDOWN_CELLS_COUNT }).map((_, index) => (
<div
key={index}
className={style.tableRowCellStyle}
style={{ width: columns?.[index]?.width ?? 'auto' }}
>
드롭다운
</div>
))}
<div className={style.contentItemWrapper}>
<ContentItem {...contentItemProps} />
</div>
</div>
);
}

Comment on lines +34 to +46
modal.confirm({
title: '정말 삭제하시겠어요?',
description: '삭제된 글은 복구할 수 없어요',
icon: <Modal.Icon name="notice" color="warning500" />,
confirmButton: '삭제하기',
cancelButton: '취소',
confirmButtonProps: {
onClick: () => {
deletePost(postId);
},
},
});
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

모달 텍스트를 상수로 분리하고 에러 처리를 추가하세요.

모달의 텍스트가 하드코딩되어 있으며, 삭제 작업의 에러 처리가 누락되어 있습니다.

+const DELETE_MODAL_TEXTS = {
+  title: '정말 삭제하시겠어요?',
+  description: '삭제된 글은 복구할 수 없어요',
+  confirm: '삭제하기',
+  cancel: '취소',
+} as const;

 const handleDeletePost = (postId: Post['id']) => {
   modal.confirm({
-    title: '정말 삭제하시겠어요?',
-    description: '삭제된 글은 복구할 수 없어요',
+    title: DELETE_MODAL_TEXTS.title,
+    description: DELETE_MODAL_TEXTS.description,
     icon: <Modal.Icon name="notice" color="warning500" />,
-    confirmButton: '삭제하기',
-    cancelButton: '취소',
+    confirmButton: DELETE_MODAL_TEXTS.confirm,
+    cancelButton: DELETE_MODAL_TEXTS.cancel,
     confirmButtonProps: {
       onClick: () => {
-        deletePost(postId);
+        deletePost(postId, {
+          onError: (error) => {
+            modal.alert({
+              title: '삭제 실패',
+              description: '게시글 삭제 중 오류가 발생했습니다.',
+            });
+          },
+        });
       },
     },
   });
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
modal.confirm({
title: '정말 삭제하시겠어요?',
description: '삭제된 글은 복구할 수 없어요',
icon: <Modal.Icon name="notice" color="warning500" />,
confirmButton: '삭제하기',
cancelButton: '취소',
confirmButtonProps: {
onClick: () => {
deletePost(postId);
},
},
});
};
const DELETE_MODAL_TEXTS = {
title: '정말 삭제하시겠어요?',
description: '삭제된 글은 복구할 수 없어요',
confirm: '삭제하기',
cancel: '취소',
} as const;
const handleDeletePost = (postId: Post['id']) => {
modal.confirm({
title: DELETE_MODAL_TEXTS.title,
description: DELETE_MODAL_TEXTS.description,
icon: <Modal.Icon name="notice" color="warning500" />,
confirmButton: DELETE_MODAL_TEXTS.confirm,
cancelButton: DELETE_MODAL_TEXTS.cancel,
confirmButtonProps: {
onClick: () => {
deletePost(postId, {
onError: (error) => {
modal.alert({
title: '삭제 실패',
description: '게시글 삭제 중 오류가 발생했습니다.',
});
},
});
},
},
});
};

Comment on lines 107 to +109
{onRemove && <IconButton icon="trash" onClick={onRemove} />}
{onModify && <IconButton icon="pencil" onClick={onModify} />}
{dragListeners && (
<IconButton
className={cursorGrabStyle}
icon="sixDots"
{...dragListeners}
/>
)}
<IconButton icon="sixDots" />
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

접근성을 위한 aria-label을 추가하세요.

IconButton들에 aria-label이 누락되어 있어 스크린 리더 사용자의 접근성이 저하됩니다.

-            {onRemove && <IconButton icon="trash" onClick={onRemove} />}
-            {onModify && <IconButton icon="pencil" onClick={onModify} />}
-            <IconButton icon="sixDots" />
+            {onRemove && <IconButton icon="trash" onClick={onRemove} aria-label="콘텐츠 삭제" />}
+            {onModify && <IconButton icon="pencil" onClick={onModify} aria-label="콘텐츠 수정" />}
+            <IconButton icon="sixDots" aria-label="드래그 핸들" />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{onRemove && <IconButton icon="trash" onClick={onRemove} />}
{onModify && <IconButton icon="pencil" onClick={onModify} />}
{dragListeners && (
<IconButton
className={cursorGrabStyle}
icon="sixDots"
{...dragListeners}
/>
)}
<IconButton icon="sixDots" />
{onRemove && <IconButton icon="trash" onClick={onRemove} aria-label="콘텐츠 삭제" />}
{onModify && <IconButton icon="pencil" onClick={onModify} aria-label="콘텐츠 수정" />}
<IconButton icon="sixDots" aria-label="드래그 핸들" />

Comment on lines +57 to +59
<MainBreadcrumbItem href="/" />
<Breadcrumb.Item active>기초 경제 지식</Breadcrumb.Item>
</Breadcrumb>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

브레드크럼 텍스트 동적 처리 필요

브레드크럼의 텍스트가 하드코딩되어 있습니다.

다음과 같이 동적으로 처리하는 것을 제안드립니다:

- <Breadcrumb.Item active>기초 경제 지식</Breadcrumb.Item>
+ <Breadcrumb.Item active>{posts.data.title}</Breadcrumb.Item>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<MainBreadcrumbItem href="/" />
<Breadcrumb.Item active>기초 경제 지식</Breadcrumb.Item>
</Breadcrumb>
<MainBreadcrumbItem href="/" />
<Breadcrumb.Item active>{posts.data.title}</Breadcrumb.Item>
</Breadcrumb>

Comment on lines +73 to +82
<Button
type="submit"
size="large"
variant="primary"
leftAddon={<Icon name="check" size={20} />}
onClick={() => {}}
className={style.submitButtonStyle}
>
예약 완료
</Button>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

제출 버튼 핸들러 구현 필요

예약 완료 버튼의 onClick 핸들러가 비어있습니다.

다음과 같이 핸들러를 구현하는 것을 제안드립니다:

- onClick={() => {}}
+ onClick={() => {
+   // TODO: 예약 완료 로직 구현
+   // 1. 현재 상태 유효성 검증
+   // 2. API 호출
+   // 3. 성공/실패 처리
+   // 4. 적절한 페이지로 리다이렉션
+ }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Button
type="submit"
size="large"
variant="primary"
leftAddon={<Icon name="check" size={20} />}
onClick={() => {}}
className={style.submitButtonStyle}
>
예약 완료
</Button>
<Button
type="submit"
size="large"
variant="primary"
leftAddon={<Icon name="check" size={20} />}
onClick={() => {
// TODO: 예약 완료 로직 구현
// 1. 현재 상태 유효성 검증
// 2. API 호출
// 3. 성공/실패 처리
// 4. 적절한 페이지로 리다이렉션
}}
className={style.submitButtonStyle}
>
예약 완료
</Button>

Comment on lines +19 to +28
export default function Schedule({ params }: SchedulePageProps) {
const [scrollRef, isScrolled] = useScroll<HTMLDivElement>({ threshold: 100 });
const { data: posts } = useGetAllPostsQuery(params);
const { mutate: updatePosts } = useUpdatePostsMutation(params);
const router = useRouter();

const readyToUploadPosts = posts.data.posts.filter(
(post) => post.status === POST_STATUS.READY_TO_UPLOAD
);

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

데이터 페칭 에러 처리 추가 필요

데이터 페칭 과정에서 발생할 수 있는 에러 상황에 대한 처리가 누락되어 있습니다.

다음과 같이 에러 처리를 추가하는 것을 제안드립니다:

- const { data: posts } = useGetAllPostsQuery(params);
+ const { data: posts, error } = useGetAllPostsQuery(params);
+ 
+ if (error) {
+   return <ErrorComponent message="포스트를 불러오는 중 오류가 발생했습니다" />;
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export default function Schedule({ params }: SchedulePageProps) {
const [scrollRef, isScrolled] = useScroll<HTMLDivElement>({ threshold: 100 });
const { data: posts } = useGetAllPostsQuery(params);
const { mutate: updatePosts } = useUpdatePostsMutation(params);
const router = useRouter();
const readyToUploadPosts = posts.data.posts.filter(
(post) => post.status === POST_STATUS.READY_TO_UPLOAD
);
export default function Schedule({ params }: SchedulePageProps) {
const [scrollRef, isScrolled] = useScroll<HTMLDivElement>({ threshold: 100 });
const { data: posts, error } = useGetAllPostsQuery(params);
if (error) {
return <ErrorComponent message="포스트를 불러오는 중 오류가 발생했습니다" />;
}
const { mutate: updatePosts } = useUpdatePostsMutation(params);
const router = useRouter();
const readyToUploadPosts = posts.data.posts.filter(
(post) => post.status === POST_STATUS.READY_TO_UPLOAD
);
// ... (rest of the component code)
}

Copy link
Member

@kongnayeon kongnayeon left a comment

Choose a reason for hiding this comment

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

코드 동작 제대로 하는 것 확인했고 다른 페이지들에서도 이상 없는 것 같아요! dnd 모듈 처음 만들어 주실 때도 잘 만들어 주셔서 수정 사항이 별로 없었던 것 같습니다! 깔끔하게 수정해 주셔서 감사해요! 너무 고생하셨습니다 ㅠㅠ!

Copy link
Member

Choose a reason for hiding this comment

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

p4;
디자인 시안에 있는 16px gap이 덜 반영된 것 같아요!
추후 dropdown 넣을 때 반영해도 될 것 같습니다!
image
image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

드롭다운 넣으면서 반영하겠습니다!

Copy link
Member

Choose a reason for hiding this comment

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

이 부분 생각보다 코드 수정이 많이 필요없었군요 굿... 👍🏻

@minseong0324 minseong0324 merged commit 6adea35 into develop Feb 10, 2025
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature] 업로드 예약 페이지 일부 퍼블리싱 및 dnd 관련 모듈 수정
2 participants