Skip to content

[Feature/#282] 타임라인 수정/삭제/AI 요약 API 연동#283

Merged
jjjsun merged 9 commits into
developfrom
feature/#282
Jul 7, 2026
Merged

[Feature/#282] 타임라인 수정/삭제/AI 요약 API 연동#283
jjjsun merged 9 commits into
developfrom
feature/#282

Conversation

@jjjsun

@jjjsun jjjsun commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

🚨 관련 이슈

Closed #282

✨ 변경사항

  • 🐞 BugFix Something isn't working
  • 💻 CrossBrowsing Browser compatibility
  • 🌏 Deploy Deploy
  • 🎨 Design Markup & styling
  • 📃 Docs Documentation writing and editing (README.md, etc.)
  • ✨ Feature Feature
  • 🔨 Refactor Code refactoring
  • ⚙️ Setting Development environment setup
  • ✅ Test Test related (storybook, jest, etc.)

✏️ 작업 내용

  • 타임라인 수정/삭제/AI요약 요청 API 함수 및 mutation 훅 추가
  • useTimelineDetail에 query options 전달 지원 -> AI 요약 요청 후 summary 갱신까지 타임라인 상세 내용 GET 폴링(1.5초 간격으로 진행되고, 90초 타임아웃 걸어둠)
  • TimelineCreateModal edit 모드 지원 및 생성/수정 모달 분리
  • Timeline.tsx 바/패널 수정/삭제 연동, 삭제 확인 Modal, AI 요약 버튼 연동
  • TimelinePerformancePanel mock setTimeout 제거, onRequestsummary /loading props 연동

😅 미완성 작업

  • 일별 변화 추이 차트 - ApexChart 연동 예정

📢 논의 사항 및 참고 사항

  • 타임라인 바 Sort/Filter은 UI만 있는 상태입니다. 사전에 BE와 협의되지 않은 추가 기능이기에 전체 기능 구현후 추가 시간이 부여된다면 진행할 예정입니다.

💬 리뷰어 가이드 (P-Rules)
P1: 필수 반영 (Critical) - 버그 가능성, 컨벤션 위반. 해결 전 머지 불가.
P2: 적극 권장 (Recommended) - 더 나은 대안 제시. 가급적 반영 권장.
P3: 제안 (Suggestion) - 아이디어 공유. 반영 여부는 드라이버 자율.
P4: 단순 확인/칭찬 (Nit) - 사소한 오타, 칭찬 등 피드백.

Summary by CodeRabbit

  • New Features
    • 타임라인 생성/수정 공용 모달로 전환되어 편집 시 초기값 기반 저장 기능이 추가되었습니다.
    • 타임라인 수정/삭제와 AI 요약 요청 플로우가 상세/성과 패널 및 페이지 동작에 연결되었습니다.
  • Bug Fixes
    • AI 요약 생성 대기/로딩 표시가 요청 상태에 맞게 정확히 동작하며, 폴링 타임아웃 및 오류 토스트 처리도 개선되었습니다.
    • 수정/삭제 후 관련 목록·상세 정보가 자동으로 갱신됩니다.
  • Refactor
    • 타임라인 관련 요청/조회 로직이 훅과 상태 주입 방식으로 정리되었습니다.

@jjjsun jjjsun requested review from Seojegyeong and YermIm July 6, 2026 12:40
@jjjsun jjjsun self-assigned this Jul 6, 2026
@jjjsun jjjsun added ✨ Feature 기능 개발 📬 API 서버 API 통신 labels Jul 6, 2026
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f2b05478-ee7b-4ddd-8fec-3aa31b6e58cf

📥 Commits

Reviewing files that changed from the base of the PR and between 22e3c92 and 5357e42.

📒 Files selected for processing (1)
  • src/pages/dashboard/timeline/Timeline.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/dashboard/timeline/Timeline.tsx

📝 Walkthrough

Walkthrough

타임라인 수정·삭제·AI 요약 요청 API와 훅을 추가하고, 생성 모달을 수정 모드까지 확장했다. TimelinePerformancePanel은 외부 요청 상태를 받도록 바뀌었고, Timeline 페이지는 수정·삭제 모달과 요약 폴링 흐름을 실제 동작에 연결했다.

Changes

타임라인 CRUD/요약 연동

Layer / File(s) Summary
API 함수 및 타입 추가
src/api/timeline/timeline.ts, src/types/timeline/api.ts
updateTimeline, deleteTimeline, requestTimelineSummary가 axios 호출로 구현되고, 업데이트 변수 타입이 추가됐다.
mutation/query 훅 구현
src/hooks/timeline/useUpdateTimeline.ts, src/hooks/timeline/useDeleteTimeline.ts, src/hooks/timeline/useRequestTimelineSummary.ts, src/hooks/timeline/useTimelineDetail.ts
수정·삭제·요약 요청 훅이 추가되고, 상세 조회 훅이 옵션을 받도록 확장됐다.
TimelineCreateModal 생성/수정 공용화
src/components/timeline/TimelineCreateModal.tsx
timelineId와 initialValues로 생성/수정 모드를 구분하고, 제출·문구·초기화를 모드에 맞게 분기한다.
TimelinePerformancePanel 외부 요약 상태 연동
src/components/timeline/TimelinePerformancePanel.tsx
내부 타이머 기반 요약 상태를 제거하고 onRequestSummary, isSummaryPending, isSummaryLoading props 기반으로 동작한다.
Timeline 페이지 상태·요청 흐름
src/pages/dashboard/timeline/Timeline.tsx
편집/삭제/요약 상태, 폴링, 요청 핸들러를 추가하고 상세 조회 및 삭제 처리 흐름을 연결한다.
Timeline 페이지 렌더링 연결
src/pages/dashboard/timeline/Timeline.tsx
수정 모달, 삭제 확인 모달, 성능 패널의 요청·로딩 상태가 실제 값에 연결된다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: Seojegyeong, YermIm

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning CRUD·AI 요약·훅/UI 연동은 충족했지만, 이슈 범위의 목록 정렬/필터 기능은 아직 구현되지 않았습니다. 목록 정렬/필터를 실제 동작으로 연결하거나, 이번 PR 범위에서 제외했다면 이슈와 설명에 명확히 표시해 주세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 타임라인 수정/삭제 및 AI 요약 API 연동이라는 핵심 변경을 정확히 요약합니다.
Description check ✅ Passed 관련 이슈, 변경사항, 미완성 작업, 참고 사항이 포함되어 템플릿을 대부분 충족합니다.
Out of Scope Changes check ✅ Passed 추가된 변경은 모두 타임라인 수정/삭제/AI 요약 연동 범위에 맞아 보이며, 무관한 변경은 보이지 않습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#282

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

📚 Storybook 배포 완료

항목 링크
📖 Storybook https://69a147b60a56365d9e2185ef-ymzzkszsjm.chromatic.com/
🔍 Chromatic https://www.chromatic.com/build?appId=69a147b60a56365d9e2185ef&number=395

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (4)
src/hooks/timeline/useUpdateTimeline.ts (1)

35-40: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

세 훅에서 중복되는 에러 메시지 추출 로직 헬퍼로 뽑아내면 좋겠어요

useUpdateTimeline, useDeleteTimeline, useRequestTimelineSummary 모두 (error as IApiErrorResponse).message ?? fallback 패턴을 그대로 복붙해서 쓰고 있어요. 공용 함수로 추출하면 나중에 에러 응답 형태가 바뀌었을 때 한 곳만 수정하면 됩니다.

♻️ 제안하는 헬퍼 추출
// src/utils/getErrorMessage.ts
import type { IApiErrorResponse } from "`@/types/common/common`";

export function getErrorMessage(error: unknown, fallback: string): string {
  return (error as IApiErrorResponse)?.message ?? fallback;
}
-      userOnError: (error) => {
-        const message =
-          (error as IApiErrorResponse).message ??
-          "타임라인 수정에 실패했습니다. 다시 시도해주세요";
-        toast.error(message);
-      },
+      userOnError: (error) => {
+        toast.error(getErrorMessage(error, "타임라인 수정에 실패했습니다. 다시 시도해주세요"));
+      },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks/timeline/useUpdateTimeline.ts` around lines 35 - 40, The repeated
`(error as IApiErrorResponse).message ?? fallback` logic in useUpdateTimeline,
useDeleteTimeline, and useRequestTimelineSummary should be extracted into a
shared helper. Create a reusable function like getErrorMessage that accepts
unknown error input and a fallback string, returns the API message when present,
and update each hook’s userOnError handler to call it instead of duplicating the
cast-and-fallback pattern.

Source: Path instructions

src/hooks/timeline/useTimelineDetail.ts (1)

10-20: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

options.enabled로 null 가드가 무력화될 수 있어요

지금 스프레드 순서상 optionsenabled가 포함되면 우리가 강제한 orgId != null && timelineId != null 체크를 덮어써버립니다. 그러면 getTimelineDetail(orgId!, timelineId!)의 non-null assertion 때문에 실제로 null인 상태에서 호출되어 런타임 에러로 이어질 수 있어요. 지금 당장 Timeline.tsx 호출부는 enabled를 안 넘기니 문제 없지만, 향후 다른 곳에서 사용할 때 터질 수 있는 구조입니다.

🛡️ 제안하는 수정
   return useCoreQuery(
     QUERY_KEYS.timeline.detail(orgId, timelineId),
     () => getTimelineDetail(orgId!, timelineId!),
-    { enabled: orgId != null && timelineId != null, ...options },
+    {
+      ...options,
+      enabled:
+        orgId != null &&
+        timelineId != null &&
+        (options?.enabled ?? true),
+    },
   );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks/timeline/useTimelineDetail.ts` around lines 10 - 20,
`useTimelineDetail`에서 `options.enabled`가 내부 null 가드를 덮어쓰는 문제가 있습니다.
`useCoreQuery`로 넘기는 옵션을 구성할 때 `orgId != null && timelineId != null` 조건을 항상 최종
`enabled` 값에 반영하도록 `useTimelineDetail`의 옵션 병합 순서를 바꾸거나, `options.enabled`와 논리적으로
결합하세요. 특히 `QUERY_KEYS.timeline.detail`와 `getTimelineDetail` 호출부가 `orgId!`,
`timelineId!`에 의존하므로, `enabled`가 null 상태를 절대 통과하지 못하게 고정해야 합니다.

Source: Path instructions

src/components/timeline/TimelineCreateModal.tsx (1)

108-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

reset 이펙트가 initialValues 참조 동일성에 의존

현재는 호출부(Timeline.tsx)에서 useMemoeditInitialValues를 메모이제이션해서 안전하게 동작하지만, 이 컴포넌트 자체는 initialValues가 매 렌더마다 새 객체로 전달되면(향후 다른 호출부 추가 시) 폼이 계속 리셋되어 사용자가 입력한 값이 사라지는 문제가 생길 수 있습니다. isOpentrue로 바뀌는 시점(최초 오픈)에만 리셋하도록 이전 isOpen 값을 ref로 추적하는 방식이 더 안전합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/timeline/TimelineCreateModal.tsx` around lines 108 - 114, The
reset effect in TimelineCreateModal is tied to initialValues identity, so the
form can be reset on every render if a new object is passed. Update the effect
to reset only when isOpen transitions from false to true, using a ref to track
the previous isOpen state, and keep the existing reset logic for closing and
first-open initialization. Reference the TimelineCreateModal component and its
useEffect/reset behavior when making the change.
src/pages/dashboard/timeline/Timeline.tsx (1)

58-113: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

페이지 컴포넌트에 편집/삭제/요약 폴링 비즈니스 로직이 과도하게 집중되어 있습니다.

수정/삭제/요약 요청 상태 관리와 폴링 로직(약 40여 줄)이 Timeline.tsx 페이지 컴포넌트 안에 그대로 구현되어 있어 가독성과 재사용성이 떨어집니다. useTimelineSummaryPolling, useTimelineDeleteFlow 같은 커스텀 훅으로 분리하면 페이지 컴포넌트는 조합/렌더링에만 집중할 수 있습니다. As per path instructions, "페이지에 비즈니스 로직이 과도하지 않은지 확인. 커스텀 훅으로의 분리 여부 검토."

Also applies to: 172-211

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/dashboard/timeline/Timeline.tsx` around lines 58 - 113, The
Timeline page is carrying too much edit/delete/summary polling state and logic
inside the component, making it hard to read and reuse. Move the summary polling
and timeout behavior from Timeline into a dedicated hook like
useTimelineSummaryPolling, and extract delete/edit flow state and handlers into
hooks such as useTimelineDeleteFlow or a similar dedicated hook. Keep Timeline
focused on composing useTimelineList, useTimelineDetail, and the UI, and make
sure the extracted hooks own the related state setters, mutation callbacks, and
polling lifecycle.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/dashboard/timeline/Timeline.tsx`:
- Line 78: The edit modal flow in Timeline.tsx only reads data from
useTimelineDetail(editTimelineId), so loading/error states are ignored and a
failed fetch leaves editInitialValues unset forever. Update the
editTimelineId-driven logic around useTimelineDetail and the modal open
condition so you handle isLoading/isError explicitly, show a toast on failure,
and reset editTimelineId via setEditTimelineId(null) when the fetch fails or
cannot complete. Keep the fix centered on the edit flow symbols
useTimelineDetail, editTimelineId, editInitialValues, and the isOpen condition
so users get visible feedback and can retry.
- Around line 358-364: `Timeline`의 `onDelete`는 `onEdit`과 달리 `selectedBarId!`를
사용해 null을 단언하고 있어 처리 방식이 불일치합니다. `onDelete`가 호출되는 시점에도 안전하도록 `onEdit`과 동일하게
`selectedBarId != null` 체크를 먼저 하고, `openDeleteModal`은 유효한 id가 있을 때만 실행되도록
`selectedBarId`를 명시적으로 가드하는 방식으로 통일하세요. `openEditModal`, `openDeleteModal`,
`selectedBarId`를 기준으로 수정 위치를 찾으면 됩니다.
- Around line 75-102: `useTimelineDetail`의 `refetchInterval` 콜백에서 상태 변경과
`toast.error`를 수행하는 부분을 분리하세요. `Timeline` 컴포넌트에서 `setIsAwaitingSummary`,
`setSummaryPollStartedAt` 및 타임아웃 토스트 처리는 `useEffect`로 옮기고, `refetchInterval`은
간격(또는 중단 여부)만 반환하도록 바꾸세요. 특히 `isAwaitingSummary`, `summaryPollStartedAt`,
`selectedBarId`와 `detail`의 summary 상태를 기준으로 완료/타임아웃 판정을 별도 훅/이펙트에서 처리하도록 정리하세요.
- Around line 104-113: The edit form in Timeline currently hardcodes
comparisonPeriodType to LAST_WEEK in editInitialValues, which can overwrite an
existing timeline’s comparison period on save. Update Timeline and the
ITimelineDetail model so the edit flow restores the original
comparisonPeriodType from editDetail when available, or otherwise excludes this
field from the update payload before calling useUpdateTimeline in
TimelineCreateModal.

---

Nitpick comments:
In `@src/components/timeline/TimelineCreateModal.tsx`:
- Around line 108-114: The reset effect in TimelineCreateModal is tied to
initialValues identity, so the form can be reset on every render if a new object
is passed. Update the effect to reset only when isOpen transitions from false to
true, using a ref to track the previous isOpen state, and keep the existing
reset logic for closing and first-open initialization. Reference the
TimelineCreateModal component and its useEffect/reset behavior when making the
change.

In `@src/hooks/timeline/useTimelineDetail.ts`:
- Around line 10-20: `useTimelineDetail`에서 `options.enabled`가 내부 null 가드를 덮어쓰는
문제가 있습니다. `useCoreQuery`로 넘기는 옵션을 구성할 때 `orgId != null && timelineId != null`
조건을 항상 최종 `enabled` 값에 반영하도록 `useTimelineDetail`의 옵션 병합 순서를 바꾸거나,
`options.enabled`와 논리적으로 결합하세요. 특히 `QUERY_KEYS.timeline.detail`와
`getTimelineDetail` 호출부가 `orgId!`, `timelineId!`에 의존하므로, `enabled`가 null 상태를 절대
통과하지 못하게 고정해야 합니다.

In `@src/hooks/timeline/useUpdateTimeline.ts`:
- Around line 35-40: The repeated `(error as IApiErrorResponse).message ??
fallback` logic in useUpdateTimeline, useDeleteTimeline, and
useRequestTimelineSummary should be extracted into a shared helper. Create a
reusable function like getErrorMessage that accepts unknown error input and a
fallback string, returns the API message when present, and update each hook’s
userOnError handler to call it instead of duplicating the cast-and-fallback
pattern.

In `@src/pages/dashboard/timeline/Timeline.tsx`:
- Around line 58-113: The Timeline page is carrying too much edit/delete/summary
polling state and logic inside the component, making it hard to read and reuse.
Move the summary polling and timeout behavior from Timeline into a dedicated
hook like useTimelineSummaryPolling, and extract delete/edit flow state and
handlers into hooks such as useTimelineDeleteFlow or a similar dedicated hook.
Keep Timeline focused on composing useTimelineList, useTimelineDetail, and the
UI, and make sure the extracted hooks own the related state setters, mutation
callbacks, and polling lifecycle.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 35253e2e-049d-4bce-8cc1-f4d2b7e4bd22

📥 Commits

Reviewing files that changed from the base of the PR and between 0e51f7b and 22e3c92.

📒 Files selected for processing (9)
  • src/api/timeline/timeline.ts
  • src/components/timeline/TimelineCreateModal.tsx
  • src/components/timeline/TimelinePerformancePanel.tsx
  • src/hooks/timeline/useDeleteTimeline.ts
  • src/hooks/timeline/useRequestTimelineSummary.ts
  • src/hooks/timeline/useTimelineDetail.ts
  • src/hooks/timeline/useUpdateTimeline.ts
  • src/pages/dashboard/timeline/Timeline.tsx
  • src/types/timeline/api.ts

Comment thread src/pages/dashboard/timeline/Timeline.tsx
Comment thread src/pages/dashboard/timeline/Timeline.tsx Outdated
Comment thread src/pages/dashboard/timeline/Timeline.tsx
Comment thread src/pages/dashboard/timeline/Timeline.tsx

@Seojegyeong Seojegyeong left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P4: 확인했습니다!

@jjjsun jjjsun merged commit 574e52c into develop Jul 7, 2026
3 checks passed
@jjjsun jjjsun deleted the feature/#282 branch July 7, 2026 01:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📬 API 서버 API 통신 ✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ [Feature] 타임라인 수정/삭제/AI요약연동

2 participants