Skip to content

Commit e0ba717

Browse files
authored
[Feat] 결과 수정 페이지 api 연동, 기능 구현 (#111)
* fix(apps/web): useScroll 버그 수정 * feat(packages/ui): TextField.Submit disabled 상태 추가 * feat(apps/web): 게시물 그룹별 게시물 목록 조회 API * feat(apps/web): 게시물 프롬프트 기반 일괄 수정 * feat(apps/web): 게시물 기타 정보 수정 API * feat(apps/web): 게시물 개별 삭제 API * feat(apps/web): 게시물 추가 생성 API * fix(apps/web): DND 버그 수정 * feat(apps/web): 타입 추가 * feat(apps/web): 결과 수정 페이지 기능 구현 완료 * remove(apps/web): 불필요 코드 삭제 * refactor(apps/web): SkeletonItems 분리 * feat(packages/ui): TextField 'white' variant 추가 * feat(packages/ui): TextField 'white' variant 추가 * fix(apps/web): 자잘한 수정 * fix(apps/web): invalidate 제거. 데이터 패칭으로 인해 버벅임 * feat(apps/web): optimistic update 추가 * remove(apps/web): SkeletonItems 삭제 * feat(apps/web): optimistic update 추가 * fix(apps/web): optimistic update 제거 * chore(apps/web): 베럴 파일 추가 및 import, export 경로 수정 * fix(apps/web): dnd, 정렬 버그 수정 * feat(apps/web): 게시글 eof 값에 따라 생성 막기 * fix(apps/web): 로딩 상태 * feat(apps/web): 생성 중에 dnd 방지, 예약하러가기 방지 * wip * fix(apps/web): 상태 업데이트 해결 및 불필요 로직 제거, 리팩토링 * fix(apps/web): 불필요 상태 반영 및 드롭 시 콜백 버그 수정 * remove(apps/web): 불필요 코드 삭제 * fix(apps/web): 불필요 스타일 제거
1 parent 77c38ca commit e0ba717

28 files changed

+855
-285
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,35 @@
11
'use client';
22

3-
import React, { RefObject } from 'react';
43
import { useScroll } from '@web/hooks';
54
import * as style from './pageStyle.css';
65
import { NavBar, MainBreadcrumbItem } from '@web/components/common';
7-
import { Breadcrumb, Button, Chip, Icon, Accordion } from '@repo/ui';
6+
import { Breadcrumb, Button, Icon } from '@repo/ui';
87
import { POST_STATUS } from '@web/types/post';
9-
import { INITIAL_CONTENT_ITEMS } from './constants';
10-
import { DndController, useDndController } from '@web/components/common';
8+
import { DndController } from '@web/components/common';
119
import { EditPageParams } from './types';
12-
import { DragGuide } from './_components/DragGuide/DragGuide';
10+
import { useGetAllPostsQuery } from '@web/store/query/useGetAllPostsQuery';
11+
import { useUpdatePostsMutation } from '@web/store/mutation/useUpdatePostsMutation';
12+
import { useRouter } from 'next/navigation';
13+
import { EditContent } from './_components/EditContent/EditContent';
1314

14-
type EditContentProps = {
15-
scrollRef: RefObject<HTMLDivElement>;
16-
isScrolled: boolean;
17-
agentId: EditPageParams['agentId'];
18-
postGroupId: EditPageParams['postGroupId'];
19-
};
15+
export default function Edit({ agentId, postGroupId }: EditPageParams) {
16+
const [scrollRef, isScrolled] = useScroll<HTMLDivElement>({ threshold: 100 });
17+
const { data: posts } = useGetAllPostsQuery({
18+
agentId,
19+
postGroupId,
20+
});
21+
const { mutate: updatePosts } = useUpdatePostsMutation({
22+
agentId,
23+
postGroupId,
24+
});
25+
const router = useRouter();
2026

21-
function EditContent({
22-
scrollRef,
23-
isScrolled,
24-
agentId,
25-
postGroupId,
26-
}: EditContentProps) {
27-
const { getItemsByStatus, handleRemove } = useDndController();
27+
/**
28+
* READY_TO_UPLOAD 상태인 게시물이 있는지 확인
29+
*/
30+
const hasReadyToUploadPosts = posts.data.posts.some(
31+
(post) => post.status === POST_STATUS.READY_TO_UPLOAD
32+
);
2833

2934
return (
3035
<div className={style.mainStyle} ref={scrollRef}>
@@ -41,158 +46,34 @@ function EditContent({
4146
size="large"
4247
variant="primary"
4348
leftAddon={<Icon name="checkCalendar" size={20} />}
44-
onClick={() => {}}
45-
disabled={false}
46-
isLoading={false}
49+
onClick={() =>
50+
router.push(`/edit/${agentId}/${postGroupId}/schedule`)
51+
}
52+
disabled={!hasReadyToUploadPosts}
4753
className={style.submitButtonStyle}
4854
>
4955
예약하러 가기
5056
</Button>
5157
}
5258
isScrolled={isScrolled}
5359
/>
54-
<div className={style.contentStyle}>
55-
<Accordion
56-
type="multiple"
57-
defaultValue={[
58-
POST_STATUS.GENERATED,
59-
POST_STATUS.EDITING,
60-
POST_STATUS.READY_TO_UPLOAD,
61-
]}
62-
className={style.accordionStyle}
63-
>
64-
{/* 생성된 글 영역 */}
65-
<Accordion.Item
66-
value={POST_STATUS.GENERATED}
67-
className={style.accordionItemStyle}
68-
>
69-
<Accordion.Trigger className={style.accordionTriggerStyle}>
70-
<Chip variant="grey">생성된 글</Chip>
71-
</Accordion.Trigger>
72-
<Accordion.Content>
73-
<DndController.Droppable id={POST_STATUS.GENERATED}>
74-
<DndController.SortableList
75-
items={getItemsByStatus(POST_STATUS.GENERATED).map(
76-
(item) => item.id
77-
)}
78-
>
79-
{getItemsByStatus(POST_STATUS.GENERATED).map((item) => (
80-
<DndController.Item
81-
key={item.id}
82-
id={item.id}
83-
summary={item.summary}
84-
updatedAt={item.updatedAt}
85-
onRemove={() => handleRemove(item.id)}
86-
onModify={() => {}}
87-
/>
88-
))}
89-
</DndController.SortableList>
90-
</DndController.Droppable>
91-
</Accordion.Content>
92-
</Accordion.Item>
93-
94-
{/* 수정 중인 글 영역 */}
95-
<Accordion.Item
96-
value={POST_STATUS.EDITING}
97-
className={style.accordionItemStyle}
98-
>
99-
<Accordion.Trigger className={style.accordionTriggerStyle}>
100-
<Chip variant="purple">수정 중인 글</Chip>
101-
</Accordion.Trigger>
102-
<Accordion.Content id={POST_STATUS.EDITING}>
103-
<DndController.Droppable id={POST_STATUS.EDITING}>
104-
<DndController.SortableList
105-
items={getItemsByStatus(POST_STATUS.EDITING).map(
106-
(item) => item.id
107-
)}
108-
>
109-
{getItemsByStatus(POST_STATUS.EDITING).length > 0 ? (
110-
getItemsByStatus(POST_STATUS.EDITING).map((item) => (
111-
<DndController.Item
112-
key={item.id}
113-
id={item.id}
114-
summary={item.summary}
115-
updatedAt={item.updatedAt}
116-
onRemove={() => handleRemove(item.id)}
117-
onModify={() => {}}
118-
/>
119-
))
120-
) : (
121-
<DragGuide description="수정 중인 글을 끌어서 여기에 놓아주세요" />
122-
)}
123-
</DndController.SortableList>
124-
</DndController.Droppable>
125-
</Accordion.Content>
126-
</Accordion.Item>
127-
128-
{/* 업로드할 글 영역 */}
129-
<Accordion.Item
130-
value={POST_STATUS.READY_TO_UPLOAD}
131-
className={style.accordionItemStyle}
132-
>
133-
<Accordion.Trigger className={style.accordionTriggerStyle}>
134-
<Chip variant="green">업로드할 글</Chip>
135-
</Accordion.Trigger>
136-
<Accordion.Content id={POST_STATUS.READY_TO_UPLOAD}>
137-
<DndController.Droppable id={POST_STATUS.READY_TO_UPLOAD}>
138-
<DndController.SortableList
139-
items={getItemsByStatus(POST_STATUS.READY_TO_UPLOAD).map(
140-
(item) => item.id
141-
)}
142-
>
143-
{getItemsByStatus(POST_STATUS.READY_TO_UPLOAD).length > 0 ? (
144-
getItemsByStatus(POST_STATUS.READY_TO_UPLOAD).map(
145-
(item) => (
146-
<DndController.Item
147-
key={item.id}
148-
id={item.id}
149-
summary={item.summary}
150-
updatedAt={item.updatedAt}
151-
onRemove={() => handleRemove(item.id)}
152-
onModify={() => {}}
153-
/>
154-
)
155-
)
156-
) : (
157-
<DragGuide description="업로드가 준비된 글을 끌어서 여기에 놓아주세요" />
158-
)}
159-
</DndController.SortableList>
160-
</DndController.Droppable>
161-
</Accordion.Content>
162-
</Accordion.Item>
163-
</Accordion>
164-
</div>
60+
<DndController
61+
key={posts.data.posts.map((p) => p.id).join(',')}
62+
initialItems={posts.data.posts}
63+
onDragEnd={(updatedItems) => {
64+
const updatePayload = {
65+
posts: updatedItems.map((item) => ({
66+
postId: item.id,
67+
status: item.status,
68+
displayOrder: item.displayOrder,
69+
uploadTime: item.uploadTime,
70+
})),
71+
};
72+
updatePosts(updatePayload);
73+
}}
74+
>
75+
<EditContent agentId={agentId} postGroupId={postGroupId} />
76+
</DndController>
16577
</div>
16678
);
16779
}
168-
169-
export default function Edit({ agentId, postGroupId }: EditPageParams) {
170-
const [scrollRef, isScrolled] = useScroll<HTMLDivElement>({ threshold: 100 });
171-
172-
return (
173-
<DndController
174-
initialItems={INITIAL_CONTENT_ITEMS}
175-
onDragEnd={(items) => {
176-
console.log('=== Current Items Status ===');
177-
const itemsByStatus = {
178-
GENERATED: items.filter((item) => item.status === 'GENERATED'),
179-
EDITING: items.filter((item) => item.status === 'EDITING'),
180-
READY_TO_UPLOAD: items.filter(
181-
(item) => item.status === 'READY_TO_UPLOAD'
182-
),
183-
};
184-
console.log('GENERATED:', itemsByStatus.GENERATED);
185-
console.log('EDITING:', itemsByStatus.EDITING);
186-
console.log('READY_TO_UPLOAD:', itemsByStatus.READY_TO_UPLOAD);
187-
console.log('========================');
188-
}}
189-
>
190-
<EditContent
191-
scrollRef={scrollRef}
192-
isScrolled={isScrolled}
193-
agentId={agentId}
194-
postGroupId={postGroupId}
195-
/>
196-
</DndController>
197-
);
198-
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { style } from '@vanilla-extract/css';
2+
import { vars } from '@repo/theme';
3+
4+
export const contentStyle = style({
5+
position: 'relative',
6+
width: '100%',
7+
padding: `${vars.space[80]} ${vars.space[24]}`,
8+
margin: '0 auto',
9+
overflowX: 'auto',
10+
});
11+
12+
export const submitButtonStyle = style({
13+
fontSize: vars.typography.fontSize[18],
14+
});
15+
16+
export const accordionStyle = style({
17+
display: 'flex',
18+
flexDirection: 'row',
19+
gap: vars.space[64],
20+
height: 'fit-content',
21+
minWidth: 'min-content',
22+
padding: `0 ${vars.space[32]}`,
23+
});
24+
25+
export const accordionTriggerStyle = style({
26+
height: '8rem',
27+
padding: `${vars.space[12]} ${vars.space[16]}`,
28+
});
29+
30+
export const accordionItemStyle = style({
31+
width: '51.2rem',
32+
flex: '0 0 auto',
33+
});
34+
35+
export const contentInnerWrapper = style({
36+
height: '100%',
37+
});
38+
39+
export const buttonWrapperStyle = style({
40+
display: 'flex',
41+
justifyContent: 'flex-end',
42+
marginTop: vars.space[10],
43+
});

0 commit comments

Comments
 (0)