-
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] 결과 수정 - 상세 페이지 api 연동 #112
Conversation
Walkthrough이번 PR은 Next.js 이미지 도메인 설정 추가, 새로운 의존성(@tanstack/react-query-devtools) 도입, 포스트의 정렬을 위한 displayOrder 속성 추가 등 다양한 변경사항을 포함합니다. 또한 스타일(CSS) 업데이트, 여러 React 컴포넌트(예: EditDetail, EditSidebar, EditPost, DragGuide, Log 관련 컴포넌트)와 커스텀 훅(useAdjacentPosts) 도입, 쿼리 및 mutation 관련 코드 개선, UI 컴포넌트(Accordion, IconButton, Spinner 등) 및 테마 관련 파일 업데이트가 이루어졌습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant U as 사용자
participant EP as EditDetailPage
participant SFB as ServerFetchBoundary
participant ED as EditDetail
participant ES as EditSidebar
participant EPst as EditPost
participant Q as useGroupPostsQuery / useAdjacentPosts
U->>EP: 편집 페이지 요청 (agentId, postGroupId)
EP->>SFB: 서버 토큰 및 쿼리 옵션 요청
SFB->>ED: EditDetail 컴포넌트 렌더링
ED->>Q: 포스트 정보 및 인접 포스트 조회
ED->>ES: 사이드바 렌더링 (드래그 앤 드롭 포함)
ED->>EPst: 포스트 편집 기능 제공
U->>EPst: 이전/다음 버튼 클릭 → 포스트 네비게이션
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
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/constants.tsOops! Something went wrong! :( ESLint: 9.17.0 Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@repo/eslint-config' imported from /eslint.config.mjs apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/EditDetail.css.tsOops! Something went wrong! :( ESLint: 9.17.0 Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@repo/eslint-config' imported from /eslint.config.mjs apps/web/next.config.mjsOops! Something went wrong! :( ESLint: 9.17.0 Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@repo/eslint-config' imported from /eslint.config.mjs
✨ Finishing Touches
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: 19
🔭 Outside diff range comments (2)
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/ContentItem/ContentItem.tsx (1)
72-76
: 이벤트 핸들러 누락
onRemove
,onModify
,onDrag
props가 정의되어 있지만 IconButton에 연결되지 않았습니다.다음과 같이 수정하는 것을 추천드립니다:
<div className={iconHoverStyle}> - <IconButton icon="trash" /> - <IconButton icon="pencil" /> - <IconButton className={cursorGrabStyle} icon="sixDots" /> + <IconButton icon="trash" onClick={onRemove} /> + <IconButton icon="pencil" onClick={onModify} /> + <IconButton + className={cursorGrabStyle} + icon="sixDots" + onMouseDown={onDrag} + /> </div>apps/web/src/components/common/DNDController/compounds/ContentItem/ContentItem.tsx (1)
78-80
: 이미지 렌더링 로직 개선 필요이미지가 있을 때 단순히 'x'를 표시하는 것은 적절하지 않습니다.
다음과 같이 이미지를 표시하는 것을 제안합니다:
- <div>x</div> + <img + src={image} + alt="콘텐츠 썸네일" + width={32} + height={32} + style={{ objectFit: 'cover', borderRadius: '4px' }} + />
🧹 Nitpick comments (32)
apps/web/src/store/query/usePostHistoryQuery.ts (1)
7-13
: 타입 정의 개선이 필요합니다.다음 사항들을 개선하면 좋을 것 같습니다:
createdAt
의 타입이Date | string
으로 정의되어 있어 타입 일관성이 떨어질 수 있습니다.type
필드의 'EACH'와 'ALL' 값의 의미를 설명하는 문서화가 필요합니다.다음과 같이 개선해보세요:
+/** Post history entry with type indicating if it applies to single or all posts */ export interface PostHistoryQuery { id: number; - createdAt: Date | string; + createdAt: string; // ISO 8601 format prompt: string; response: string; + /** Type of history entry: + * - EACH: Applies to individual post + * - ALL: Applies to all posts in group + */ type: 'EACH' | 'ALL'; }apps/web/src/store/mutation/useDeletePostMutation.ts (1)
8-11
: EditPageParams와 타입 중복 검토 필요
MutationDeletePost
인터페이스가EditPageParams
와 동일한 구조를 가지고 있습니다. 타입 중복을 피하기 위해EditPageParams
를 재사용하는 것을 고려해보세요.-export interface MutationDeletePost { - agentId: number; - postGroupId: number; -} +export type MutationDeletePost = EditPageParams;apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/_components/LogSidebar/LogSidebar.css.ts (1)
4-9
: 반응형 디자인 개선이 필요합니다사이드바의 고정 너비(42.3rem)와 높이(100vh)는 작은 화면에서 문제를 일으킬 수 있습니다.
다음과 같은 개선을 제안합니다:
export const sidebarWrapper = style({ - width: '42.3rem', + width: 'min(42.3rem, 100%)', height: '100vh', flexShrink: '0', backgroundColor: `${tokens.colors.grey0}`, + '@media': { + 'screen and (max-width: 768px)': { + width: '100%' + } + } });apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/_components/LogContentItem/LogContentItem.css.ts (2)
4-15
: 접근성과 다크 모드 지원이 필요합니다wrapper 컴포넌트에 다음 개선사항들이 필요합니다:
export const wrapper = style({ width: '100%', - height: '13.4rem', + minHeight: '13.4rem', padding: '1.2rem', display: 'flex', flexDirection: 'column', gap: '0.8rem', borderRadius: `${tokens.radius[10]}`, + cursor: 'pointer', + transition: 'background-color 0.2s ease', ':hover': { backgroundColor: `${tokens.colors.grey25}`, }, + '@media': { + '(prefers-color-scheme: dark)': { + backgroundColor: `${tokens.colors.grey800}`, + ':hover': { + backgroundColor: `${tokens.colors.grey700}`, + } + } + } });
17-23
: 텍스트 접근성 개선이 필요합니다promptText에 다음 접근성 관련 스타일을 추가하는 것이 좋습니다:
export const promptText = style({ width: '100%', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', marginRight: '0.8rem', + lineHeight: '1.5', + '@media': { + '(prefers-color-scheme: dark)': { + color: `${tokens.colors.grey100}` + } + } });apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/_components/LogSidebar/LogSidebar.tsx (1)
13-19
: 접근성 개선이 필요합니다IconButton에 적절한 aria 레이블을 추가해 주세요:
return ( <div className={sidebarWrapper}> <div className={closeArea}> - <IconButton icon="x" color="grey300" onClick={handleXClick} /> + <IconButton + icon="x" + color="grey300" + onClick={handleXClick} + aria-label="닫기" + /> </div> </div> );apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/_components/LogContentItem/LogContentItem.tsx (1)
41-48
: Text 컴포넌트 스타일 상수화를 제안합니다.반복되는 Text 컴포넌트의 스타일 속성을 상수로 분리하면 재사용성과 일관성을 높일 수 있습니다.
다음과 같이 스타일을 상수화하는 것을 제안합니다:
+const PROMPT_TEXT_STYLE = { + color: 'grey800' as const, + fontSize: 16, + fontWeight: 'medium' as const, +}; + <Text className={promptText} - color="grey800" - fontSize={16} - fontWeight="medium" + {...PROMPT_TEXT_STYLE} >packages/ui/src/components/Accordion/AccordionRoot.tsx (1)
17-17
: TODO 주석이 남아있습니다.
추후 유지보수를 위해 실제 수정 계획을 구체적으로 남겨둘 것을 권장합니다.apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditSidebar/EditSidebar.tsx (1)
95-102
: skeletonData 생성 로직은 간편합니다.
임시 로딩용 데이터라, 실제 API 연동 시 삭제할 계획을 명시해 두면 좋겠습니다.apps/web/src/components/common/DNDController/compounds/DroppableContent/DroppableContent.css.ts (1)
4-5
: 주석을 영문으로 변경해주세요.국제화 및 협업을 위해 코드 내 주석은 영문으로 작성하는 것을 권장드립니다.
- // NOTE minHeight를 20rem에서 fit-content로 바꿔도 사이드 이펙트가 없을까요? - // 두 페이지에서 모두 사용하려면 fit-content로 가야 할 것 같아서요! + // NOTE: Will changing minHeight from 20rem to fit-content have any side effects? + // We should use fit-content as this component is used across two pagesapps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/DragGuide/DragGuide.css.ts (2)
4-15
: container 스타일의 변수명을 더 구체적으로 지정하면 좋겠습니다.현재
container
라는 일반적인 이름보다는dragGuideContainer
와 같이 더 구체적인 이름을 사용하면 컴포넌트의 목적을 더 잘 나타낼 수 있습니다.-export const container = style({ +export const dragGuideContainer = style({
17-20
: description 스타일도 더 구체적인 이름으로 변경하면 좋겠습니다.마찬가지로
description
도dragGuideDescription
으로 변경하여 스타일의 용도를 명확히 하면 좋겠습니다.-export const description = style({ +export const dragGuideDescription = style({apps/web/next.config.mjs (1)
17-19
: 이미지 도메인을 환경 변수로 관리하면 좋겠습니다.S3 도메인을 하드코딩하는 대신 환경 변수로 관리하면 환경별로 유연하게 설정할 수 있습니다.
images: { - domains: ['instead-dev.s3.ap-northeast-2.amazonaws.com'], + domains: [process.env.NEXT_PUBLIC_S3_DOMAIN].filter(Boolean), },packages/ui/src/components/Accordion/hooks/useCallbackRef.tsx (2)
7-21
: 콜백이 undefined일 때의 처리를 개선하면 좋겠습니다.현재 구현은 콜백이 undefined일 때 조용히 실행을 건너뛰지만, 개발 모드에서는 경고를 표시하는 것이 디버깅에 도움이 될 수 있습니다.
return React.useMemo( - () => ((...args) => callbackRef.current?.(...args)) as T, + () => ((...args) => { + if (process.env.NODE_ENV === 'development' && !callbackRef.current) { + console.warn('useCallbackRef: callback is undefined'); + } + return callbackRef.current?.(...args); + }) as T, [] );
3-6
: JSDoc 주석에 예제 코드를 추가하면 좋겠습니다.사용 예시를 포함하면 다른 개발자들이 이 훅을 더 쉽게 이해하고 활용할 수 있습니다.
/** * A custom hook that converts a callback to a ref to avoid triggering re-renders when passed as a * prop or avoid re-executing effects when passed as a dependency + * + * @example + * ```tsx + * const MyComponent = () => { + * const callback = useCallbackRef((value: string) => { + * console.log(value); + * }); + * return <Child onChange={callback} />; + * }; + * ``` */apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/DragGuide/DragGuide.tsx (1)
8-29
: 접근성 및 국제화 개선이 필요합니다.
- 드래그 앤 드롭 영역에 대한 접근성 속성이 누락되어 있습니다.
- "끌어서 여기에 놓아주세요" 텍스트가 하드코딩되어 있어 국제화에 어려움이 있을 수 있습니다.
다음과 같이 개선해보세요:
export function DragGuide({ description }: DragGuideProps) { return ( - <div className={styles.container}> + <div + className={styles.container} + role="region" + aria-label="드래그 앤 드롭 가이드" + > <Text.H2 className={styles.description} fontSize={20} fontWeight="semibold" color="grey500" > {description} </Text.H2> <Text.H2 className={styles.description} fontSize={20} fontWeight="semibold" color="grey500" > - 끌어서 여기에 놓아주세요 + {t('common.dragAndDropHere')} </Text.H2> </div> ); }apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditSidebar/EditSidebar.css.ts (1)
26-29
: 스크롤 이벤트 최적화를 고려해주세요.
overflow-y: scroll
이 적용된 요소에서 스크롤 이벤트를 사용하는 경우, 성능 최적화가 필요할 수 있습니다.스크롤 이벤트를 사용하는 경우 다음과 같은 최적화를 고려해보세요:
- debounce/throttle 적용
passive: true
옵션 사용will-change
속성 활용packages/ui/src/components/IconButton/IconButton.tsx (1)
21-27
: 로딩 상태에 따른 조건부 렌더링 구현로딩 상태일 때는 Spinner를, 아닐 때는 Icon을 표시하도록 구현되었습니다. 하지만 불필요한 Fragment(
<>...</>
) 사용이 있습니다.다음과 같이 Fragment를 제거하여 코드를 간소화할 수 있습니다:
{isLoading ? ( - <> <Spinner color="icon" size="icon" /> - </> ) : ( <Icon name={icon} type={iconType} /> )}packages/ui/src/components/Spinner/Spinner.tsx (1)
9-13
: JSDoc 주석 업데이트 필요
color
와size
prop에 'icon' 옵션이 추가되었지만, JSDoc 주석에는 이 변경사항이 반영되지 않았습니다.다음과 같이 JSDoc을 업데이트해주세요:
/** * @param {SpinnerProps} props - 스피너 속성 - * @property {color} [color='white'] - 'black' | 'white' 스피너 색상 - * @property {size} [size='small'] - 'small' | 'large' 스피너 크기 + * @property {color} [color='white'] - 'black' | 'white' | 'icon' 스피너 색상 + * @property {size} [size='small'] - 'small' | 'large' | 'icon' 스피너 크기 */apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/ContentItem/ContentItem.css.ts (1)
11-11
: 중복된 cursor 스타일 속성이 발견되었습니다.
cursorPointerStyle
이 이미 정의되어 있는데contentItemStyle
에 동일한cursor: 'pointer'
속성이 추가되었습니다. 코드 중복을 피하기 위해cursorPointerStyle
을 재사용하는 것이 좋습니다.다음과 같이 수정하는 것을 제안합니다:
export const contentItemStyle = style({ display: 'inline-flex', flexDirection: 'row', alignItems: 'center', gap: '1.6rem', height: '6.4rem', width: '100%', padding: '1.6rem 0.8rem 1.2rem 1.2rem', - cursor: 'pointer', }); // contentItemStyle에 cursorPointerStyle을 조합하여 사용 export const interactiveContentItemStyle = style([contentItemStyle, cursorPointerStyle]);
apps/web/src/store/mutation/useModifyPostMutation.ts (1)
33-35
: 성공 메시지를 상수로 분리해 주세요.성공 메시지가 하드코딩되어 있어 재사용이 어렵고 일관성 유지가 어려울 수 있습니다.
다음과 같이 개선하는 것을 제안합니다:
+ const MESSAGES = { + SUCCESS: '저장되었습니다.', + ERROR: '포스트 수정 중 오류가 발생했습니다.', + } as const; onSuccess: () => { - toast.success('저장되었습니다.'); + toast.success(MESSAGES.SUCCESS); },apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/EditDetail.tsx (1)
10-10
: TODO 주석에 대한 이슈를 생성하시겠습니까?상태 관리 라이브러리 변경에 대한 TODO 주석이 있습니다. 이를 추적하고 관리하기 위해 이슈로 생성하는 것이 좋습니다.
이 작업을 추적하기 위한 이슈를 생성해드릴까요?
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/PostEditor/UploadedImages.tsx (2)
21-21
: 이벤트 처리 주석을 일관성 있게 작성해 주세요.이벤트 처리에 대한 주석이 한글과 영어가 혼용되어 있습니다. 또한 동일한 목적의 이벤트 처리가 여러 곳에서 반복되고 있습니다.
이벤트 처리 로직을 분리하고 주석을 일관성 있게 작성하는 것을 제안합니다:
+ // 이미지 관련 이벤트 처리를 위한 유틸리티 함수 + const preventImageEvent = (e: React.MouseEvent) => { + e.preventDefault(); // 기본 동작 방지 + e.stopPropagation(); // 이벤트 버블링 방지 + }; <div key={image} className={styles.imageWrapper} - onClick={(e) => e.preventDefault()} // 이미지 클릭 시 삭제 방지 + onClick={preventImageEvent} // 이미지 클릭 이벤트 방지 > // ... onClick={(e) => { - e.preventDefault(); // 기본 동작 차단 - e.stopPropagation(); // 이벤트 전파 차단 + preventImageEvent(e); onRemove(image); }}Also applies to: 34-35
25-25
: 이미지 alt 텍스트를 더 의미있게 작성해 주세요.현재 alt 텍스트가 이미지 URL을 포함하고 있어 스크린 리더 사용자에게 불필요한 정보를 제공할 수 있습니다.
<Image src={image} - alt={`업로드된 이미지 ${image}`} + alt="업로드된 콘텐츠 이미지" width={IMAGE_SIZE} height={IMAGE_SIZE} className={styles.image} />apps/web/src/store/mutation/usePatchPromptMutation.ts (1)
49-53
: 에러 처리를 개선해 주세요.현재 에러 처리가 너무 일반적입니다. 구체적인 에러 케이스별로 처리하는 것이 좋겠습니다.
- onError: (error) => { - if (error instanceof Error) { - toast.error(error.message); - } - }, + onError: (error) => { + if (error instanceof Error) { + switch(error.name) { + case 'NetworkError': + toast.error('네트워크 연결을 확인해주세요.'); + break; + case 'ValidationError': + toast.error('입력값을 확인해주세요.'); + break; + default: + toast.error('오류가 발생했습니다. 다시 시도해주세요.'); + } + } + },apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/constants.ts (1)
4-4
: 임시 데이터임을 명확히 표시해 주세요."MEMO: 임시 더미" 주석은 좋지만, TODO 주석을 추가하여 실제 데이터로 교체가 필요함을 명시하는 것이 좋겠습니다.
-//MEMO: 임시 더미 +//MEMO: 임시 더미 +//TODO: 실제 데이터로 교체 필요packages/ui/src/components/Accordion/hooks/useControllableState.tsx (2)
4-8
: 타입 정의에 JSDoc 문서 추가 필요타입 정의의 각 속성에 대한 설명이 없어 사용자가 이해하기 어려울 수 있습니다.
다음과 같이 JSDoc을 추가하는 것을 추천드립니다:
type UseControllableStateParams<T> = { + /** 제어된 상태일 때 사용되는 값 */ prop?: T | undefined; + /** 제어되지 않은 상태일 때의 초기값 */ defaultProp?: T | undefined; + /** 상태가 변경될 때 호출되는 콜백 함수 */ onChange?: (state: T) => void; };
27-38
: setValue 함수에 타입 안전성 강화 필요현재 구현에서는
nextValue
가undefined
일 때의 처리가 명시적이지 않습니다.다음과 같이 타입 가드를 추가하는 것을 추천드립니다:
(nextValue) => { + if (nextValue === undefined) { + console.warn('setValue was called with undefined value'); + return; + } if (isControlled) { const setter = nextValue as SetStateFn<T>;apps/web/src/types/post.ts (1)
18-23
: 상수 값에 대한 설명 주석 필요각 상수 값의 의미와 사용 목적을 이해하기 어렵습니다.
다음과 같이 각 값에 대한 설명을 추가하는 것을 추천드립니다:
export const POST_PURPOSE = { + /** 정보 제공 목적의 포스트 */ INFORMATION: 'INFORMATION', + /** 의견 제시 목적의 포스트 */ OPINION: 'OPINION', + /** 유머러스한 내용의 포스트 */ HUMOR: 'HUMOR', + /** 마케팅 목적의 포스트 */ MARKETING: 'MARKETING', } as const;apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/ContentItem/ContentItem.tsx (1)
26-35
: JSDoc 주석 업데이트 필요컴포넌트의 JSDoc 주석이 최신 props와 일치하지 않습니다.
다음과 같이 업데이트하는 것을 추천드립니다:
/** * ContentItem 컴포넌트의 Props 타입 * - * @property {string} [image] - 이미지 URL. 제공되지 않으면 기본 아이콘이 표시됩니다. + * @property {PostImage[]} [image] - 이미지 배열. 제공되지 않으면 기본 아이콘이 표시됩니다. * @property {string} [title] - 표시할 제목 텍스트. * @property {string} updatedAt - ISO 8601 형식의 날짜 문자열로, 마지막 업데이트 시간을 나타냅니다. + * @property {() => void} onClick - 아이템 클릭 시 호출되는 콜백 함수. * @property {() => void} onRemove - 삭제 아이콘 클릭 시 호출되는 콜백 함수. * @property {() => void} onModify - 수정 아이콘 클릭 시 호출되는 콜백 함수. * @property {() => void} onDrag - 드래그 아이콘 마우스 다운 시 호출되는 콜백 함수. + * @property {boolean} [isSelected] - 선택 상태 여부 */apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditPost/EditPost.tsx (1)
29-39
: 네비게이션 버튼의 접근성 개선 필요네비게이션 버튼에 적절한 aria-label이 누락되어 있어 스크린 리더 사용자의 접근성이 저하될 수 있습니다.
다음과 같이 aria-label을 추가하는 것을 제안합니다:
<IconButton icon="arrowLineTop" disabled={!canMoveUp} onClick={routePreviousPost} + aria-label="이전 포스트로 이동" /> <IconButton icon="arrowLineBottom" disabled={!canMoveDown} onClick={routeNextPost} + aria-label="다음 포스트로 이동" />apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditPromptField/EditPromptField.tsx (1)
44-62
: useEffect 의존성 배열 최적화 필요
isPending
상태 변경에 따른 로딩 상태 관리 로직이 불필요하게 자주 실행될 수 있습니다.다음과 같이 의존성 배열을 최적화하는 것을 제안합니다:
useEffect(() => { if (isPending) { if (isEntire) { setLoadingPosts(editingPosts); } else { setLoadingPosts([Number(postId)]); } } else { if (isEntire) { setLoadingPosts((prev) => prev.filter((id) => !editingPosts.includes(id)) ); } else { setLoadingPosts((prev) => prev.filter((id) => id !== Number(postId))); } } - }, [isPending]); + }, [isPending, isEntire, editingPosts, postId]);
📜 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 (46)
apps/web/next.config.mjs
(1 hunks)apps/web/package.json
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/constants.ts
(5 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/EditDetail.css.ts
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/EditDetail.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/ContentItem/ContentItem.css.ts
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/ContentItem/ContentItem.tsx
(3 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/DragGuide/DragGuide.css.ts
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/DragGuide/DragGuide.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditPost/EditPost.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditPromptField/EditPromptField.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditSidebar/EditSidebar.css.ts
(3 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditSidebar/EditSidebar.tsx
(2 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/PostEditor/PostEditor.tsx
(6 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/PostEditor/UploadedImages.tsx
(2 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_hooks/useAdjacentPosts.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/page.css.ts
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/page.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/Log.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/_components/LogContentItem/LogContentItem.css.ts
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/_components/LogContentItem/LogContentItem.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/_components/LogSidebar/LogSidebar.css.ts
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/_components/LogSidebar/LogSidebar.tsx
(1 hunks)apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/page.tsx
(1 hunks)apps/web/src/app/page.tsx
(1 hunks)apps/web/src/components/common/DNDController/compounds/ContentItem/ContentItem.tsx
(3 hunks)apps/web/src/components/common/DNDController/compounds/DroppableContent/DroppableContent.css.ts
(1 hunks)apps/web/src/components/common/DNDController/hooks/useDragAndDrop.ts
(1 hunks)apps/web/src/components/providers/Providers.tsx
(2 hunks)apps/web/src/store/mutation/useDeletePostMutation.ts
(3 hunks)apps/web/src/store/mutation/useModifyPostMutation.ts
(1 hunks)apps/web/src/store/mutation/useModifyPostsMutation.ts
(1 hunks)apps/web/src/store/mutation/usePatchPromptMutation.ts
(1 hunks)apps/web/src/store/query/QueryClientProvider.tsx
(1 hunks)apps/web/src/store/query/useGroupPostsQuery.ts
(1 hunks)apps/web/src/store/query/usePostHistoryQuery.ts
(1 hunks)apps/web/src/types/post.ts
(3 hunks)packages/theme/src/tokens/colors.ts
(1 hunks)packages/ui/src/components/Accordion/AccordionRoot.tsx
(1 hunks)packages/ui/src/components/Accordion/hooks/useCallbackRef.tsx
(1 hunks)packages/ui/src/components/Accordion/hooks/useControllableState.tsx
(1 hunks)packages/ui/src/components/Badge/index.ts
(1 hunks)packages/ui/src/components/IconButton/IconButton.css.ts
(1 hunks)packages/ui/src/components/IconButton/IconButton.tsx
(1 hunks)packages/ui/src/components/Spinner/Spinner.css.ts
(2 hunks)packages/ui/src/components/Spinner/Spinner.tsx
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- apps/web/src/components/common/DNDController/hooks/useDragAndDrop.ts
🔇 Additional comments (52)
apps/web/src/store/query/usePostHistoryQuery.ts (1)
22-23
: TODO 주석을 해결해주세요.코드에 TODO FIXME 주석이 남아있습니다. 이 주석이 무엇을 의미하는지 명확히 하고 해결해주세요.
이 TODO 주석과 관련된 작업을 도와드릴까요?
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/page.tsx (2)
22-24
: 컴포넌트 구조가 잘 구성되어 있습니다.ServerFetchBoundary를 사용하여 서버 사이드 데이터 페칭을 적절히 처리하고 있습니다.
15-20
: 🛠️ Refactor suggestion문자열 매개변수의 숫자 변환 검증이 필요합니다.
매개변수를 Number()로 변환할 때 잘못된 문자열이 입력되면 NaN이 될 수 있습니다. 이를 방지하기 위한 유효성 검사가 필요합니다.
다음과 같이 유효성 검사를 추가하는 것을 제안합니다:
+ const agentId = Number(params.agentId); + const postGroupId = Number(params.postGroupId); + const postId = Number(params.postId); + + if (isNaN(agentId) || isNaN(postGroupId) || isNaN(postId)) { + throw new Error('Invalid ID parameters'); + } + const serverFetchOptions = PostHistoryQueryQueryOptions( - Number(params.agentId), - Number(params.postGroupId), - Number(params.postId), + agentId, + postGroupId, + postId, tokens );apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/log/[postId]/_components/LogContentItem/LogContentItem.tsx (1)
50-50
: TODO 주석을 해결해주세요.디자인 시안과의 일치 여부를 확인하고 TODO 주석을 제거해주세요.
디자인 시안과 비교하여 필요한 스타일 조정을 진행해주시기 바랍니다.
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/page.tsx (5)
1-4
: Imports가 적절히 구성되어 있습니다.
이전 컴포넌트를 제거하고 필요한 의존성만 가져오는 부분이 가독성을 높여줍니다.
6-8
: 타입 선언이 명확합니다.
params 객체 안에 agentId, postGroupId를 문자열로 받아 사용하는 구조가 직관적입니다. 다만, Number 변환 시 예외 처리를 고려해볼 수도 있습니다.
10-10
: 컴포넌트 시그니처가 확장되었습니다.
이제 EditDetailPage가 props를 통해 URL params를 전달받아 처리하므로, 유지보수성이 향상되었습니다.
11-16
: 토큰과 쿼리 옵션 처리 시 예외 처리를 고려해보세요.
getServerSideTokens() 함수가 실패하거나 Number 변환이 올바르게 되지 않을 때를 위한 방어 로직이 있으면 안정적입니다.
18-20
: ServerFetchBoundary 구성이 적절합니다.
EditDetail 컴포넌트를 서버 페치 범위 내에서 안전하게 감싸 데이터 로딩과 에러 처리를 명확히 분리할 수 있습니다.packages/ui/src/components/Accordion/AccordionRoot.tsx (7)
3-10
: import 문과 useControllableState 의존성 추가가 적절해 보입니다.
React 관련 훅과 별도 훅을 잘 가져와 코드 가독성이 좋습니다.Also applies to: 13-13
18-38
: AccordionProps 제네릭 설계가 훌륭합니다.
단일 모드와 다중 모드를 구분하여 타입 안전성을 높인 점이 매우 인상적입니다.
40-59
: AccordionRootInner 함수 시그니처가 명확합니다.
type에 따른 defaultValue 처리 로직이 직관적이며, 제네릭을 통해 다양한 케이스를 지원할 수 있습니다.
62-76
: 기본 openValues 계산 로직이 명료합니다.
단일/다중 모드를 모두 고려한 처리로 예상치 못한 에러(예: 배열 변환)가 줄어들 것으로 보입니다.
78-101
: useControllableState 훅 사용으로 제어/비제어 상태를 일관성 있게 관리합니다.
단일/다중 모드별 onValueChange를 구분 처리하는 방식이 합리적입니다.
102-130
: 열림 상태(normalizedOpenValues), toggleValue, isValueOpen 로직이 잘 분리되어 있습니다.
단일 모드에서 중복으로 열리는 상황을 방지하는 처리가 안정적입니다.
132-139
: AccordionContext.Provider 및 forwardRef 사용이 적절합니다.
Context를 통해 상태를 공유하고, 제네릭 사용자 정의로 확장 가능성을 높여주어 재사용성이 뛰어납니다.Also applies to: 142-148, 151-159
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditSidebar/EditSidebar.tsx (18)
2-2
: 새로운 의존성과 공용 컴포넌트 import 구성이 좋아 보입니다.
Drag & Drop, Accordion 기능 등 필요한 모듈을 깔끔하게 정리했습니다.Also applies to: 5-5, 13-16
20-21
: useGroupPostsQuery, Post, POST_STATUS import는 관련 기능을 명확히 보여줍니다.
코드 가독성과 유지보수에 도움이 됩니다.Also applies to: 22-22, 23-25
28-29
: useCreateMorePostsMutation, useDeletePostMutation, DetailPageContext 사용이 자연스럽습니다.
Context를 통해 상위 컴포넌트 상태를 공유하는 방식이 일관성 있어 보입니다.Also applies to: 32-34
36-46
: EditSidebarContent 컴포넌트의 초기 상태 설정이 직관적입니다.
loadingPosts, agentId, postGroupId 등 필요한 요소들을 잘 관리하고 있습니다.
48-52
: useCreateMorePostsMutation를 통한 게시글 추가 로직이 명확합니다.
param 주입 방식에 대한 TODO 주석이 있으므로, 적절한 시점에 수정이 필요해 보입니다.
54-57
: useDeletePostMutation 설정이 적절합니다.
파라미터(agentId, postGroupId)를 명확히 지정해 특별한 문제는 없어 보입니다.
59-66
: Accordion 기본값 처리 방식이 훌륭합니다.
URL 파라미터(postParam)로부터 상태를 결정하는 로직이 사용자 경험을 개선합니다.Also applies to: 67-69
71-73
: handleClick 함수가 라우팅을 단순화합니다.
URL 쿼리로 postId를 넘기는 직관적인 접근입니다.
75-78
: handlePlusClick에서 Accordion 상태를 'EDITING'으로 전환하는 로직이 좋습니다.
새로운 글 추가 직후 편집 모드로 전환되어 사용자 경험이 매끄럽습니다.
80-93
: handleDeletePost에서 모달 로직이 안정적입니다.
확인 모달로 사용자의 실수 방지를 돕는 점이 우수합니다.
105-105
: Breadcrumb와 제목 표기가 직관적입니다.
TODO 주석대로 중복 로직을 컴포넌트화하면 재사용성이 더욱 높아질 것으로 보입니다.Also applies to: 106-106, 108-108, 114-114
122-127
: Accordion 컴포넌트로 펼침 상태를 단일 모드로 제어하는 구조가 좋습니다.
onValueChange 훅을 통해 동적으로 상태를 업데이트해주는 방식이 깔끔합니다.
128-178
: 생성된 글(GENERATED) 영역의 드래그 앤 드롭 로직이 잘 구현되었습니다.
DndController.SortableList로 UI 동작을 직관적으로 설계하고 스켈레톤 처리로 로딩 상태까지 고려했습니다.
179-218
: 수정 중인 글(EDITING) 영역도 동일한 패턴으로 구현되었습니다.
드래그 & 드롭 일관성이 유지되고, handleDeletePost나 handleClick을 재사용할 수 있어 효율적입니다.
219-261
: 업로드할 글(READY_TO_UPLOAD) 영역도 재사용 패턴을 따르고 있습니다.
DragGuide를 통해 빈 상태에 대한 안내가 한눈에 들어옵니다.
267-272
: EditSidebar에서 useModifyPostsMutation 설정이 깔끔합니다.
agentId와 postGroupId 모두 숫자로 변환해 호출 충돌 가능성을 줄였습니다.
274-277
: 게시글 정렬 로직이 displayOrder를 기준으로 명확하게 동작합니다.
기존 배열을 직접 정렬하므로, 불변성 유지가 필요한 경우에는 주의가 필요할 수 있습니다.
279-319
: DndController 상위 래핑으로 정렬 상태를 중앙에서 관리합니다.
onDragEnd에서 displayOrder를 일괄 수정하고, 서버 반영을 위해 modifyPosts를 호출하는 접근이 자연스럽습니다.Also applies to: 320-323
packages/ui/src/components/Badge/index.ts (1)
1-2
: 타입 내보내기가 적절히 확장되었습니다.Badge 컴포넌트의 타입 시스템이 BadgeVariant를 포함하도록 확장되어 타입 안정성이 향상되었습니다.
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/page.css.ts (1)
3-7
: 레이아웃 동작 검증이 필요합니다.height를 100vh로 설정하고 flexShrink: 0을 추가한 변경사항이 다음 시나리오에서 의도한 대로 동작하는지 확인해주세요:
- 콘텐츠가 뷰포트 높이를 초과하는 경우
- 모바일 브라우저에서 주소 표시줄이 사라지는 경우
- 키보드가 올라오는 경우
apps/web/src/components/common/DNDController/compounds/DroppableContent/DroppableContent.css.ts (1)
4-7
: minHeight 변경에 대한 검증이 필요합니다.fit-content로의 변경이 적절해 보이나, 다음 사항들의 검증이 필요합니다:
- 드래그 앤 드롭 영역이 너무 작아지지 않는지
- 빈 상태일 때의 시각적 표현이 적절한지
- 두 페이지 모두에서 일관된 사용자 경험을 제공하는지
apps/web/src/store/query/QueryClientProvider.tsx (1)
7-13
: queryClient를 싱글톤으로 분리한 것이 좋습니다!queryClient를 상수로 분리하여 싱글톤 패턴을 적용한 것은 애플리케이션 전반에 걸쳐 일관된 상태 관리를 가능하게 하는 좋은 개선입니다.
apps/web/src/components/providers/Providers.tsx (1)
5-5
: React Query Devtools가 올바르게 추가되었습니다.개발 도구가 기본적으로 닫힌 상태로 시작되도록 설정되어 있어 좋습니다.
프로덕션 빌드에서 devtools가 제외되는지 확인하시기 바랍니다. 다음 스크립트로 확인할 수 있습니다:
Also applies to: 19-19
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/DragGuide/DragGuide.tsx (1)
4-6
: Props 인터페이스가 잘 정의되어 있습니다.타입 정의가 명확하고 간단합니다.
packages/ui/src/components/IconButton/IconButton.css.ts (1)
21-25
: TODO 주석을 해결해주세요.디자이너와 색상에 대한 논의가 필요하다는 TODO 주석이 있습니다. PR 병합 전에 이 부분을 해결하는 것이 좋겠습니다.
디자이너와 논의 후 적절한 색상값으로 업데이트해주세요.
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/EditSidebar/EditSidebar.css.ts (1)
31-34
: 레이아웃이 잘 구성되어 있습니다.Flexbox를 활용한 레이아웃 구성이 적절합니다.
packages/ui/src/components/IconButton/IconButton.tsx (1)
4-4
: 로딩 상태 표시를 위한 타입 및 의존성 추가IconButton 컴포넌트에 로딩 상태를 표시하기 위한
isLoading
prop과 Spinner 컴포넌트가 추가되었습니다.Also applies to: 12-12
apps/web/src/store/query/useGroupPostsQuery.ts (1)
26-27
: 캐시 설정 검토 필요
staleTime
과gcTime
을Infinity
로 설정하면 데이터가 절대 만료되지 않습니다. 이는 메모리 누수나 오래된 데이터 문제를 일으킬 수 있습니다.실시간성이 필요하지 않은 데이터인지 확인이 필요합니다. 적절한 시간 값(예: 5분 또는 1시간)을 설정하는 것을 고려해보세요.
apps/web/src/store/mutation/useModifyPostsMutation.ts (2)
30-32
: TODO 주석 해결 필요성공 시 토스트 알림 표시 여부에 대한 결정이 필요합니다.
사용자 경험(UX) 관점에서 성공 알림이 필요한지 검토해주세요. 일반적으로 성공적인 저장 작업 후에는 피드백을 제공하는 것이 좋습니다.
33-37
: 에러 처리가 잘 구현되었습니다Error 인스턴스 체크를 통한 타입 안전성 확보와 사용자 친화적인 에러 메시지 표시가 잘 구현되었습니다.
packages/theme/src/tokens/colors.ts (1)
29-29
: 색상 토큰이 적절하게 추가되었습니다!purple 색상 스케일에 맞게 적절한 값이 추가되었습니다.
apps/web/src/store/mutation/usePatchPromptMutation.ts (1)
46-47
: TODO 주석을 해결해 주세요.성공 메시지가 임시로 하드코딩되어 있습니다. 메시지를 상수로 분리하거나 i18n 시스템을 사용하는 것이 좋겠습니다.
packages/ui/src/components/Spinner/Spinner.css.ts (1)
39-42
: 스피너 컴포넌트에 아이콘 변형이 잘 추가되었습니다!크기와 색상이 디자인 시스템의 토큰을 잘 활용하고 있습니다.
Also applies to: 80-82
apps/web/src/types/post.ts (1)
90-90
: newsCategory 타입 변경에 대한 마이그레이션 계획 필요
newsCategory
속성이 필수에서 선택적으로 변경되었습니다. 기존 코드에서 이 필드를 필수로 사용하는 부분이 있을 수 있습니다.다음 스크립트로
newsCategory
사용 현황을 확인해주세요:✅ Verification successful
🏁 Script executed:
#!/bin/bash # newsCategory 필드 사용 현황 확인 rg "newsCategory" -A 3 -B 3Length of output: 2364
newsCategory 필드 마이그레이션 검토 결과
- 앱 생성 관련 코드(apps/web/src/app/create/)에서는 newsCategory 필드를 조건부로 할당하는 등, 이미 선택적(optional) 사용에 맞춰 로직이 수정되었습니다.
- types 정의(apps/web/src/app/create/types.ts, apps/web/src/types/post.ts)에서도 해당 필드가 선택적으로 선언되어 있어 프론트엔드 코드 전반에서는 문제 없이 변경이 반영된 것으로 보입니다.
- 다만 백엔드 또는 다른 서비스에서 해당 필드를 무조건 기대하는 부분이 있다면 별도의 마이그레이션 검토가 필요할 수 있습니다.
apps/web/src/app/(prompt)/edit/[agentId]/[postGroupId]/detail/_components/PostEditor/PostEditor.tsx (1)
161-167
: 주석 처리된 드래그 앤 드롭 기능 정리 필요주석 처리된 드래그 앤 드롭 기능 코드가 남아있습니다. 해당 기능의 구현 여부를 명확히 결정해야 합니다.
드래그 앤 드롭 기능이 필요한지 확인이 필요합니다. 필요하다면 구현을 완료하고, 불필요하다면 관련 코드를 제거해주세요.
apps/web/src/app/page.tsx (1)
536-549
: 변경사항이 적절해 보입니다!multiple 타입의 Accordion에서 defaultValue를 제거한 것은 적절한 변경입니다. multiple 선택 모드에서는 초기 선택값이 필요하지 않기 때문입니다.
staleTime: Infinity, | ||
gcTime: Infinity, |
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
캐시 설정을 재검토해주세요.
staleTime
과 gcTime
을 Infinity
로 설정하면 메모리 문제가 발생할 수 있습니다. 적절한 시간 제한을 설정하는 것이 좋습니다.
다음과 같이 수정하는 것을 고려해보세요:
- staleTime: Infinity,
- gcTime: Infinity,
+ staleTime: 5 * 60 * 1000, // 5분
+ gcTime: 30 * 60 * 1000, // 30분
📝 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.
staleTime: Infinity, | |
gcTime: Infinity, | |
staleTime: 5 * 60 * 1000, // 5분 | |
gcTime: 30 * 60 * 1000, // 30분 |
export function useGroupPostsQuery( | ||
agentId: number, | ||
postGroupId: number, | ||
postId: number | ||
) { | ||
return useSuspenseQuery( | ||
PostHistoryQueryQueryOptions(agentId, postGroupId, postId) | ||
); | ||
} |
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
함수 이름과 에러 처리를 개선해주세요.
- 함수 이름
useGroupPostsQuery
가 실제 기능(포스트 히스토리 조회)과 일치하지 않습니다. - 에러 처리가 누락되어 있습니다.
다음과 같이 개선하는 것을 추천드립니다:
-export function useGroupPostsQuery(
+export function usePostHistoryQuery(
agentId: number,
postGroupId: number,
postId: number
) {
return useSuspenseQuery(
- PostHistoryQueryQueryOptions(agentId, postGroupId, postId)
+ PostHistoryQueryQueryOptions(agentId, postGroupId, postId),
+ {
+ retry: 3,
+ onError: (error) => {
+ console.error('Failed to fetch post history:', 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 function useGroupPostsQuery( | |
agentId: number, | |
postGroupId: number, | |
postId: number | |
) { | |
return useSuspenseQuery( | |
PostHistoryQueryQueryOptions(agentId, postGroupId, postId) | |
); | |
} | |
export function usePostHistoryQuery( | |
agentId: number, | |
postGroupId: number, | |
postId: number | |
) { | |
return useSuspenseQuery( | |
PostHistoryQueryQueryOptions(agentId, postGroupId, postId), | |
{ | |
retry: 3, | |
onError: (error) => { | |
console.error('Failed to fetch post history:', error); | |
// 에러 처리 로직 추가 | |
} | |
} | |
); | |
} |
// TODO 위 로직과 통일 예정 | ||
queryClient.invalidateQueries({ | ||
queryKey: ['postGroup', 'Agents'], | ||
}); |
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
쿼리 무효화 로직 통합 필요
현재 두 개의 invalidateQueries
호출이 있으며, TODO 주석에서 언급된 대로 이 로직들을 통합하는 것이 좋습니다. 리팩토링 시 다음 사항들을 고려해보세요:
- 관련된 모든 쿼리를 한 번에 무효화
- 쿼리 키 구조의 일관성 유지
- 불필요한 리렌더링 방지
onSuccess: () => {
toast.success('게시글이 삭제되었어요.');
- queryClient.invalidateQueries(
- getAllPostsQueryOptions({ agentId, postGroupId })
- );
- // TODO 위 로직과 통일 예정
- queryClient.invalidateQueries({
- queryKey: ['postGroup', 'Agents'],
- });
+ // 관련된 모든 쿼리 한 번에 무효화
+ queryClient.invalidateQueries({
+ queryKey: [
+ {
+ entity: 'posts',
+ agentId,
+ postGroupId,
+ },
+ ],
+ });
},
📝 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.
// TODO 위 로직과 통일 예정 | |
queryClient.invalidateQueries({ | |
queryKey: ['postGroup', 'Agents'], | |
}); | |
onSuccess: () => { | |
toast.success('게시글이 삭제되었어요.'); | |
// 관련된 모든 쿼리 한 번에 무효화 | |
queryClient.invalidateQueries({ | |
queryKey: [ | |
{ | |
entity: 'posts', | |
agentId, | |
postGroupId, | |
}, | |
], | |
}); | |
}, |
export function Log() { | ||
return <div>dd</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.
구현이 필요한 컴포넌트입니다
현재 컴포넌트가 단순히 "dd" 텍스트만 반환하고 있습니다. 로그 기능에 대한 실제 구현이 필요합니다.
다음 사항들을 고려해 주세요:
- 컴포넌트 Props 타입 정의
- 로그 데이터 표시 로직 구현
- 에러 상태 처리
- 로딩 상태 처리
export function LogSidebar() { | ||
const router = useRouter(); | ||
const { agentId, postGroupId } = useParams(); | ||
const searchParams = useSearchParams(); | ||
const postId = searchParams.get('post'); | ||
const handleXClick = () => { | ||
router.push(`/edit/${agentId}/${postGroupId}/detail?post=${postId}`); | ||
}; | ||
return ( |
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 function LogSidebar() {
const router = useRouter();
const { agentId, postGroupId } = useParams();
const searchParams = useSearchParams();
const postId = searchParams.get('post');
+
+ if (!agentId || !postGroupId || !postId) {
+ return <div>잘못된 접근입니다</div>;
+ }
+
const handleXClick = () => {
+ try {
router.push(`/edit/${agentId}/${postGroupId}/detail?post=${postId}`);
+ } catch (error) {
+ console.error('Navigation failed:', 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 function LogSidebar() { | |
const router = useRouter(); | |
const { agentId, postGroupId } = useParams(); | |
const searchParams = useSearchParams(); | |
const postId = searchParams.get('post'); | |
const handleXClick = () => { | |
router.push(`/edit/${agentId}/${postGroupId}/detail?post=${postId}`); | |
}; | |
return ( | |
export function LogSidebar() { | |
const router = useRouter(); | |
const { agentId, postGroupId } = useParams(); | |
const searchParams = useSearchParams(); | |
const postId = searchParams.get('post'); | |
if (!agentId || !postGroupId || !postId) { | |
return <div>잘못된 접근입니다</div>; | |
} | |
const handleXClick = () => { | |
try { | |
router.push(`/edit/${agentId}/${postGroupId}/detail?post=${postId}`); | |
} catch (error) { | |
console.error('Navigation failed:', error); | |
// 에러 처리 로직 추가 필요 | |
} | |
}; | |
return ( | |
// ... rest of the component JSX | |
); | |
} |
render={({ field }) => ( | ||
<Checkbox | ||
label="수정 중인 글을 모두 업그레이드하기" | ||
defaultChecked |
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.
체크박스 defaultChecked 속성 제거 필요
defaultChecked
속성과 checked
속성이 동시에 사용되고 있어 React 컴포넌트의 제어 상태가 모호해질 수 있습니다.
다음과 같이 defaultChecked
속성을 제거하는 것을 제안합니다:
<Checkbox
label="수정 중인 글을 모두 업그레이드하기"
- defaultChecked
checked={field.value}
onChange={field.onChange}
/>
@@ -63,6 +64,7 @@ export const ContentItem = forwardRef<HTMLDivElement, ContentItemProps>( | |||
dragListeners, | |||
className, | |||
isLoading, | |||
isSelected = 'false', |
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.
타입 오류 수정 필요
isSelected
의 기본값이 문자열로 설정되어 있으나, 타입은 boolean으로 정의되어 있습니다.
다음과 같이 수정하는 것을 제안합니다:
- isSelected = 'false',
+ isSelected = false,
📝 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.
isSelected = 'false', | |
isSelected = false, |
const handleFiles = async (files: FileList) => { | ||
// 최대 4개 파일만 처리 (필요에 따라 maxFiles 값을 조정하세요) | ||
const fileArray = Array.from(files).slice(0, 4); | ||
const urls = fileArray.map((file) => URL.createObjectURL(file)); | ||
setImages(urls); | ||
const uploadedUrls = await uploadImages(fileArray); | ||
setValue('imageUrls', uploadedUrls); | ||
}; |
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.
이미지 업로드 에러 처리 필요
이미지 업로드 실패 시에 대한 에러 처리가 누락되어 있습니다.
다음과 같이 에러 처리를 추가하는 것을 제안합니다:
const handleFiles = async (files: FileList) => {
const fileArray = Array.from(files).slice(0, 4);
- const uploadedUrls = await uploadImages(fileArray);
- setValue('imageUrls', uploadedUrls);
+ try {
+ const uploadedUrls = await uploadImages(fileArray);
+ setValue('imageUrls', uploadedUrls);
+ } catch (error) {
+ console.error('이미지 업로드 실패:', 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.
const handleFiles = async (files: FileList) => { | |
// 최대 4개 파일만 처리 (필요에 따라 maxFiles 값을 조정하세요) | |
const fileArray = Array.from(files).slice(0, 4); | |
const urls = fileArray.map((file) => URL.createObjectURL(file)); | |
setImages(urls); | |
const uploadedUrls = await uploadImages(fileArray); | |
setValue('imageUrls', uploadedUrls); | |
}; | |
const handleFiles = async (files: FileList) => { | |
// 최대 4개 파일만 처리 (필요에 따라 maxFiles 값을 조정하세요) | |
const fileArray = Array.from(files).slice(0, 4); | |
try { | |
const uploadedUrls = await uploadImages(fileArray); | |
setValue('imageUrls', uploadedUrls); | |
} catch (error) { | |
console.error('이미지 업로드 실패:', error); | |
// TODO: 사용자에게 에러 메시지 표시 | |
} | |
}; |
useEffect(() => { | ||
console.log('imageUrl', watch('imageUrls')); | ||
}, [watch('imageUrls')]); |
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.
불필요한 콘솔 로그 제거 필요
개발 디버깅용 콘솔 로그가 프로덕션 코드에 남아있습니다.
다음 코드를 제거해주세요:
- useEffect(() => {
- console.log('imageUrl', watch('imageUrls'));
- }, [watch('imageUrls')]);
📝 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.
useEffect(() => { | |
console.log('imageUrl', watch('imageUrls')); | |
}, [watch('imageUrls')]); |
@@ -17,6 +17,7 @@ | |||
"@repo/theme": "workspace:^", | |||
"@repo/ui": "workspace:^", | |||
"@tanstack/react-query": "^5.66.0", | |||
"@tanstack/react-query-devtools": "^5.66.0", |
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
devDependencies로 이동을 제안합니다.
@tanstack/react-query-devtools는 개발 도구이므로 dependencies가 아닌 devDependencies에 위치하는 것이 더 적절합니다. 이렇게 하면 프로덕션 빌드 크기를 줄일 수 있습니다.
다음과 같이 수정하는 것을 제안합니다:
- "@tanstack/react-query-devtools": "^5.66.0",
devDependencies 섹션에 추가:
+ "@tanstack/react-query-devtools": "^5.66.0",
관련 이슈
#103
변경 사항
UT 이슈로 아주 급하게 구현을 했습니다,, 코드가 정말 돌아"만" 갑니다... 추후 리팩토링 해야 할 부분이 많은데 UT 끝나고 최대한 빨리 반영할 수 있도록 하겠습니다!
다른 건 dependency 거의 없어서 괜찮을 것 같은데 공통 컴포넌트 변경 사항이 있어 알려드립니다!
레퍼런스
Summary by CodeRabbit
New Features
Style