Skip to content

[Feature/#271] 타임라인 조회/생성 API 연동 및 mock 데이터 교체 - #281

Merged
jjjsun merged 16 commits into
developfrom
feature/#271
Jul 6, 2026
Merged

[Feature/#271] 타임라인 조회/생성 API 연동 및 mock 데이터 교체#281
jjjsun merged 16 commits into
developfrom
feature/#271

Conversation

@jjjsun

@jjjsun jjjsun commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

🚨 관련 이슈

Closed #271

✨ 변경사항

  • 🐞 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.)

✏️ 작업 내용

  • 타임라인 목록/상세/생성 API 함수 추가
  • QUERY_KEYS.timelineuseTimelineList / useTimelineDetail / useCreateTimeline 커스텀 훅 추가
  • API 응답시 UI 데이터 변환하는 유틸 추가
  • Timeline.tsx 에서 mock데이터 제거, 목록 API + 기간(viewUnit,periodIndex) 기반 그리드 랜더링
  • TimelineCreateModal mock 제출 → createTimeline mutation + 목록 invalidate
  • 로딩 TimelineSkeleton 추가, 목록 조회나 실패시 에러 UI 추가

😅 미완성 작업

다음 이슈 작업 - 타임라인 수정, 삭제, AI 요약, Sort/Filter

📢 논의 사항 및 참고 사항

  • Chromatic: Storybook prod 빌드에서 API URL 미설정 crash 방지를 위해 .storybook/main.ts에 dummy VITE_API_BASE_URL 설정. Storybook은 mock/UI 전용이라 실제 API 호출 목적 아닙니다

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

Summary by CodeRabbit

Summary (ko-KR)

  • New Features
    • 타임라인이 실제 데이터 기반으로 목록/상세 조회 및 생성을 지원하도록 개선되었습니다.
    • 기간별 타임라인 그리드와 성과 요약 패널을 새로 제공해 확인 흐름이 직관적이졌습니다.
    • 타임라인 생성 모달의 로딩/비활성화 상태가 더 일관되게 반영됩니다.
  • Bug Fixes
    • 로딩 시 스켈레톤 노출, 오류 시 안내 메시지 표기가 추가되었습니다.
    • 기간 이동 및 바 선택 시 요약 패널 갱신 흐름이 안정화되었습니다.
  • Alterations
    • 비교 기간 옵션이 “작년 동기간 대비”로 업데이트되었습니다.

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

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jjjsun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0bf44917-ac40-48c4-960f-63adefb9b6e0

📥 Commits

Reviewing files that changed from the base of the PR and between bd4c78b and c19861f.

📒 Files selected for processing (1)
  • src/types/timeline/api.ts
📝 Walkthrough

Walkthrough

타임라인 조회·생성 API와 React Query 훅이 추가되고, 페이지는 mock 데이터 대신 실제 조회 결과와 상세 데이터를 사용하도록 바뀌었다. 기간 계산·그리드·요약 패널 유틸이 신설됐고, 생성 모달은 isPending 기반 제출 흐름으로 전환됐다. 비교 기간 타입과 옵션도 함께 갱신됐다.

Changes

타임라인 API 연동 및 UI 전환

Layer / File(s) Summary
타임라인 API 및 쿼리 키 정의
src/api/timeline/timeline.ts, src/lib/queryKeys.ts
타임라인 상세/목록 조회와 생성 API 함수가 추가되고, QUERY_KEYS.timeline 키 생성 함수가 정의됨.
타임라인 조회/생성 훅
src/hooks/timeline/useTimelineList.ts, src/hooks/timeline/useTimelineDetail.ts, src/hooks/timeline/useCreateTimeline.ts
목록/상세 조회와 생성 뮤테이션이 useCoreQuery/useCoreMutation로 연결되고, 생성 성공 시 캐시 무효화와 토스트 처리가 추가됨.
기간 계산 및 그리드 빌드 유틸
src/utils/timeline/period.ts, src/utils/timeline/buildTimelineGrid.ts, src/utils/timeline/buildTimelineSummaryPanel.ts
표시 기간, 컬럼/바 배치, 상세 요약 패널 변환 로직이 새 유틸로 분리됨.
Timeline 페이지 mock 제거 및 API 연동
src/pages/dashboard/timeline/Timeline.tsx, src/components/timeline/skeleton/TimelineSkeleton.tsx
페이지가 목록/상세 훅과 유틸로 렌더링되며, 로딩 스켈레톤·에러 UI·빈 상태·기간 이동 로직이 갱신됨.
생성 모달과 비교 기간 옵션 전환
src/components/timeline/TimelineCreateModal.tsx, src/constants/timeline/formOptions.ts, src/types/timeline/api.ts
생성 모달이 useCreateTimeline 기반으로 바뀌고, 비교 기간 옵션/타입이 LAST_YEAR 중심으로 변경됨.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested labels: 🎨 Html&css

Suggested reviewers: Seojegyeong, YermIm

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning 목록 훅이 orgId만 키로 쓰고 period 변경을 쿼리나 API 파라미터에 반영하지 않아 #271의 기간 갱신 요구를 충족하지 못합니다. useTimelineList/getTimelineList에 viewUnit·periodIndex를 반영하고, 기간 변경 시 queryKey와 재조회가 일어나도록 수정하세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed 변경점이 타임라인 API, 훅, 그리드·패널 유틸, 로딩·생성 흐름에 집중돼 있어 이슈 범위를 벗어난 코드는 보이지 않습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed 타임라인 조회/생성 API 연동과 mock 데이터 교체라는 핵심 변경사항을 명확히 요약하고 있습니다.
Description check ✅ Passed 필수 섹션인 관련 이슈, 변경사항, 작업 내용, 미완성 작업, 참고 사항이 모두 포함되어 있어 템플릿을 대부분 충족합니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#271

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.

@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: 3

🧹 Nitpick comments (2)
src/api/timeline/timeline.ts (1)

37-44: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

validateStatus 조건 중복 정리 필요.

status === 201은 이미 status >= 200 && status < 300 조건에 포함되기 때문에 실질적으로 아무 효과가 없는 중복 체크입니다. axios의 기본 validateStatus도 2xx는 전부 성공으로 처리하므로, 이 커스텀 옵션 자체가 불필요해 보입니다. 향후 유지보수자가 "201만 특별 취급한다"고 오해할 소지가 있어 정리하는 게 좋습니다.

♻️ 제안
   const { data } = await axiosInstance.post<
     ICommonResponse<ITimelineMutationResponse>
-  >(`/api/org/${orgId}/timeline`, body, {
-    validateStatus: (status) =>
-      status === 201 || (status >= 200 && status < 300),
-  });
+  >(`/api/org/${orgId}/timeline`, body);
🤖 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/api/timeline/timeline.ts` around lines 37 - 44, The custom validateStatus
in timeline mutation request is redundant because status === 201 is already
covered by the 2xx range and axios defaults to treating 2xx as success. Remove
the unnecessary validateStatus override from the axiosInstance.post call in
timeline.ts, keeping the request behavior aligned with the default success
handling in the timeline API function.
src/hooks/timeline/useCreateTimeline.ts (1)

15-34: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

로컬 reject 값과 IApiErrorResponse 타입 불일치.

orgId가 없을 때 Promise.reject(new Error("워크스페이스를 선택해주세요"))로 거부하는데, useCoreMutationTError 기본 타입은 IApiErrorResponse(status, code, method, requestURI 포함)입니다. 지금은 ErrorIApiErrorResponse 둘 다 message 필드를 가지고 있어서 userOnError(error as IApiErrorResponse).message가 우연히 정상 동작하지만, 타입상으로는 error.code/error.status 등이 항상 존재하는 것처럼 보여 실제로는 undefined인 위험한 불일치가 있습니다. 추후 에러 코드 기반 분기나 로깅을 추가하면 조용히 깨질 수 있습니다.

로컬 검증 실패는 IApiErrorResponse와 별개의 유니온 타입으로 다루거나, 최소한 로컬 전용 에러 클래스를 만들어 명시적으로 구분하는 걸 권장합니다.

As per path instructions, "타입 안정성: TypeScript 타입의 명확성 확인. any 사용 지양, 제네릭 활용 검토."

🤖 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/useCreateTimeline.ts` around lines 15 - 34,
`useCreateTimeline`의 로컬 검증 실패가 `IApiErrorResponse`와 타입이 섞여 있어 `userOnError`에서 실제
API 에러처럼 취급되는 불일치가 있습니다. `orgId == null`일 때의 reject를 `IApiErrorResponse`와 구분되는
별도 로컬 에러로 처리하거나 `useCoreMutation`의 에러 타입을 유니온으로 명시해, `userOnError`와
`createTimeline` 경로에서 `message` 외의 필드(`status`, `code`, `method`, `requestURI`)를
안전하게 다루도록 정리하세요.

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`:
- Around line 79-82: `Timeline`의 `handleBarClick`에서 `selectedBarId`만 바꾸고
`panelData`를 유지해서 이전 요약이 잠깐 보이는 상태입니다. 새 막대를 클릭할 때 즉시 `panelData`를 null로 초기화해
`TimelinePerformancePanel`이 기존 내용을 렌더링하지 않도록 하고, `useEffect`의
`buildTimelineSummaryPanel(detail)`로 새 `detail`이 도착하면 다시 채우도록 수정하세요.
`selectedBarId`, `panelData`, `handleBarClick`, `useTimelineDetail`,
`buildTimelineSummaryPanel`을 기준으로 고치면 됩니다.
- Around line 55-70: The current isEmpty check in Timeline is based on bars from
buildTimelineGrid, but bars only reflect items in the selected
viewUnit/periodIndex and can incorrectly show TimelineEmptyState when data
exists outside the current period. Update the Timeline component to distinguish
between an empty overall timelineList and an empty current-period result, using
the existing useTimelineList, buildTimelineGrid, and isEmpty logic so the UI can
show “no timeline data” only when timelineList is truly empty and a separate
state when nothing matches the current period.
- Around line 130-144: Update the error UI in Timeline so the container rendered
from the isError branch exposes accessibility feedback with role="alert" and
aria-live="assertive". In the Timeline component, remove the unnecessary
IApiErrorResponse cast around error and read the message directly via
error?.message. Also fix the Korean copy in the fallback string to correct the
typos in “못했습니다” and “잠시 후”.

---

Nitpick comments:
In `@src/api/timeline/timeline.ts`:
- Around line 37-44: The custom validateStatus in timeline mutation request is
redundant because status === 201 is already covered by the 2xx range and axios
defaults to treating 2xx as success. Remove the unnecessary validateStatus
override from the axiosInstance.post call in timeline.ts, keeping the request
behavior aligned with the default success handling in the timeline API function.

In `@src/hooks/timeline/useCreateTimeline.ts`:
- Around line 15-34: `useCreateTimeline`의 로컬 검증 실패가 `IApiErrorResponse`와 타입이 섞여
있어 `userOnError`에서 실제 API 에러처럼 취급되는 불일치가 있습니다. `orgId == null`일 때의 reject를
`IApiErrorResponse`와 구분되는 별도 로컬 에러로 처리하거나 `useCoreMutation`의 에러 타입을 유니온으로 명시해,
`userOnError`와 `createTimeline` 경로에서 `message` 외의 필드(`status`, `code`, `method`,
`requestURI`)를 안전하게 다루도록 정리하세요.
🪄 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: 43ce660c-33d9-441a-8e52-927afe4e0ecf

📥 Commits

Reviewing files that changed from the base of the PR and between 3ec0887 and d788c08.

📒 Files selected for processing (11)
  • src/api/timeline/timeline.ts
  • src/components/timeline/TimelineCreateModal.tsx
  • src/components/timeline/skeleton/TimelineSkeleton.tsx
  • src/hooks/timeline/useCreateTimeline.ts
  • src/hooks/timeline/useTimelineDetail.ts
  • src/hooks/timeline/useTimelineList.ts
  • src/lib/queryKeys.ts
  • src/pages/dashboard/timeline/Timeline.tsx
  • src/utils/timeline/buildTimelineGrid.ts
  • src/utils/timeline/buildTimelineSummaryPanel.ts
  • src/utils/timeline/period.ts

Comment thread src/pages/dashboard/timeline/Timeline.tsx
Comment thread src/pages/dashboard/timeline/Timeline.tsx
Comment thread src/pages/dashboard/timeline/Timeline.tsx
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

📚 Storybook 배포 완료

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

@jjjsun jjjsun changed the title [Feature/#271] 타임라인 API 연동 및 mock 데이터 교체 [Feature/#271] 타임라인 조회/생성 API 연동 및 mock 데이터 교체 Jul 4, 2026

@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: 2

🤖 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/constants/timeline/formOptions.ts`:
- Line 24: The `LAST_YEAR` option in the timeline form is failing type-check
because `TTimelineComparisonPeriodType` is defined with the misspelled value
from `TIMELINE_COMPARISON_PERIOD_TYPES`. Fix the source of truth in
`src/types/timeline/api.ts` by correcting the array entry from the typo to
`LAST_YEAR`, so `formOptions.ts` can use the matching
`TTimelineComparisonPeriodType` value without a compile error.

In `@src/types/timeline/api.ts`:
- Around line 26-30: `TIMELINE_COMPARISON_PERIOD_TYPES` contains a typo that
propagates into `TTimelineComparisonPeriodType` and `timelineCreateSchema`, so
update the array entry in `TIMELINE_COMPARISON_PERIOD_TYPES` from the misspelled
year value to the correct `LAST_YEAR` literal. Use the existing symbols
`TIMELINE_COMPARISON_PERIOD_TYPES`, `TIMELINE_COMPARISON_PERIOD_VALUES`, and
`TTimelineComparisonPeriodType` to verify the type union and enum validation now
match the `LAST_YEAR` usage in `formOptions`.
🪄 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: db4a4e69-e8b1-4184-8735-ea9d070c6e0f

📥 Commits

Reviewing files that changed from the base of the PR and between d788c08 and bd4c78b.

⛔ Files ignored due to path filters (2)
  • .storybook/main.ts is excluded by none and included by none
  • .storybook/preview.tsx is excluded by none and included by none
📒 Files selected for processing (3)
  • src/constants/timeline/formOptions.ts
  • src/pages/dashboard/timeline/Timeline.tsx
  • src/types/timeline/api.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/dashboard/timeline/Timeline.tsx

Comment thread src/constants/timeline/formOptions.ts
Comment thread src/types/timeline/api.ts

@YermIm YermIm 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 0e51f7b into develop Jul 6, 2026
3 checks passed
@jjjsun
jjjsun deleted the feature/#271 branch July 6, 2026 01:14
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] 타임라인 조회/생성 API 및 상태 연동

2 participants