Conversation
- `withErrorHandling()` 함수에 대한 설명을 문서에서 제거하여 일관성 유지
- 응답에 유효한 데이터베이스 ID가 있는 경우 선택한 Notion 데이터베이스 ID를 설정
- Google Calendar 관련 쿼리 키 및 훅 추가 - Google Calendar 캘린더 및 이벤트 조회 기능 구현 - 선택된 캘린더 관리 및 연결 해제 기능 추가 - 기존 코드 리팩토링 및 상태 관리 개선
- 요청 ID를 사용하여 이전 요청의 응답을 무효화하는 로직 추가 - 페이지 로드 및 데이터베이스 페이지 적용 시 요청 ID 확인 추가
- useRef를 사용하여 초기화 상태를 추적하는 로직 추가 - notionCalendarEvents가 비어있거나 초기화가 완료된 경우 useEffect에서 조기 반환하도록 수정
- 오류 발생 시 사용자에게 명확한 메시지 제공 - 세션 스토리지에서 상태 키 제거 및 URL에서 OAuth 매개변수 정리 로직 추가
- useRef를 사용하여 초기화 상태를 추적하는 로직 추가 - allUnifiedEvents가 비어있거나 초기화가 완료된 경우 useEffect에서 조기 반환하도록 수정
- activeTab 상태를 useMemo를 사용하여 계산하도록 변경 - SCHEDULE 탭에서 캘린더 이벤트가 없을 경우 기본 탭으로 돌아가는 useEffect 추가 - 코드 가독성을 높이기 위해 불필요한 초기화 로직 제거
- useRef를 사용하여 초기화 상태를 추적하는 로직 추가 - parsedEvents가 비어있거나 초기화가 완료된 경우 useEffect에서 조기 반환하도록 수정 - 캘린더의 첫 번째 이벤트에 따라 기본 선택 날짜 및 표시 월 설정 로직 추가
- 클럽 이름을 URL에 안전하게 포함하기 위해 encodeURIComponent 사용
- articles 배열에서 유효한 timestamp를 필터링하여 최대값을 반환하도록 수정 - 빈 timestamps 배열에 대한 처리를 추가하여 0을 반환하도록 변경
- globalThis.crypto.randomUUID가 지원되지 않는 경우를 대비하여 대체 로직 추가 - Uint8Array를 사용하여 안전한 난수 문자열 생성 방식으로 변경
- 날짜 배열 생성을 위한 로직을 addDays 함수를 사용하여 간결하게 변경 - 코드 가독성을 높이기 위해 불필요한 변수 제거
- 유효하지 않은 날짜 문자열에 대한 처리를 추가하여 NaN 반환 시 빈 문자열을 반환하도록 수정
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning
|
| Cohort / File(s) | Summary |
|---|---|
ESLint 및 MSW frontend/.eslintignore, frontend/public/mockServiceWorker.js |
mockServiceWorker.js를 eslint 무시 목록에 추가하고 파일 상단에 /* eslint-disable */ 지시문 삽입. |
쿼리 키 frontend/src/constants/queryKeys.ts |
queryKeys에 googleCalendar 네임스페이스(all, calendars, events) 추가. |
Google Calendar 훅 frontend/src/hooks/Queries/useGoogleCalendar.ts |
캘린더/이벤트 조회와 선택·연결해제를 위한 4개 React Query 훅 추가(에러 분기·캐싱·invalidate 처리 포함). |
CalendarSyncTab 훅 리팩토링 frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useGoogleCalendarData.ts |
직접 API 호출에서 React Query 훅으로 마이그레이션; 로드 함수 제거, 로딩/선택 로직을 쿼리/뮤테이션 기반으로 재정의. |
Notion 관련 훅들 개선 frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useNotionCalendarData.ts, .../useNotionCalendarUiState.ts, .../useUnifiedCalendarUiState.ts |
요청 ID로 오래된 응답 무시 로직 추가 및 visibleMonth 초기화에 useRef 가드 도입(한 번만 초기화). |
OAuth 처리 개선 frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useNotionOAuth.ts |
OAuth 콜백 검증 시 명확한 오류 처리, sessionStorage/URL 정리 동작 조정. |
스타일 변경 frontend/src/pages/AdminPage/tabs/CalendarSyncTab/CalendarSyncTab.styles.ts |
하드코드 색상·미디어쿼리를 테마(colors, media)로 대체. |
UI 초기화 안정화 frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx, frontend/src/pages/ClubDetailPage/components/ClubScheduleCalendar/ClubScheduleCalendar.tsx |
activeTab 로직 보강(스케줄 탭 비활성화 조건 포함) 및 캘린더 초기화에 useRef 가드 추가. |
유틸 개선 frontend/src/utils/calendarSyncUtils.ts, frontend/src/utils/formatKSTDateTime.ts |
createState에서 crypto 기반 난수/UUID 사용, buildMonthCalendarDays를 Date 커서 기반으로 변경, formatKSTDateTime에 invalid Date 검증 추가. |
프로모션 관련 수정 frontend/src/pages/PromotionPage/utils/promotionNotification.ts, frontend/src/pages/PromotionPage/components/detail/PromotionClubCTA/PromotionClubCTA.tsx |
타임스탬프 배열에서 NaN 필터링 및 빈 배열 처리 추가, 클럽명 URL 인코딩 적용. |
타입 변경 frontend/src/types/club.ts |
ClubDetail 필드명 hasCalendarEvents → hasCalendarConnection으로 변경. |
문서 frontend/CLAUDE.md |
API 헬퍼 설명에서 withErrorHandling() 항목 삭제(문서만 변경). |
Sequence Diagram(s)
sequenceDiagram
participant UI as "UI Component"
participant Hook as "useGetGoogleCalendars / useGetGoogleCalendarEvents"
participant Query as "React Query"
participant API as "Backend API"
UI->>Hook: 마운트 또는 사용자 액션으로 호출
Hook->>Query: useQuery/useMutation 실행 (키: googleCalendar...)
Query->>API: HTTP 요청 (GET /google/calendars or /events / POST select/disconnect)
API-->>Query: 응답 반환
Query-->>Hook: 캐시 업데이트 및 데이터/상태 제공
Hook-->>UI: 데이터 · 로딩 · 에러 전달
Note right of Hook: 뮤테이션 성공 시 Query.invalidateQueries("googleCalendar") 호출로 캐시 갱신
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
- [feature] Google 캘린더 이벤트 조회 API 추가 #1375: Google Calendar events 엔드포인트 관련 변경과 직접 연결(쿼리 훅/키 사용).
- [feature] Google Calendar 이벤트와 Notion 캘린더 페이지 통합 #1376: Google Calendar·Notion 통합 관련 기능 추가/수정과 범위가 겹침.
- [feature] 관리자 캘린더 연동 탭에 Notion DB 선택/캘린더 표시 기능 추가 #1352: Calendar Sync 유틸·훅·쿼리키 변경과 중복되는 코드영역 존재.
Suggested reviewers
- lepitaaar
- oesnuj
- suhyun113
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Title check | ❓ Inconclusive | 제목은 '[Fix] pr review 1386'으로 구체적인 변경사항을 명확히 설명하지 못하고 있습니다. | Google Calendar 통합 및 캘린더 연결 로직 개선을 반영하는 더 구체적인 제목으로 변경하세요. 예: '[Fix] Refactor Google Calendar integration and improve calendar connection logic' |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ 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
fix/pr-review-1386
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
🎨 UI 변경사항을 확인해주세요
2개 스토리 변경 · 전체 56개 스토리 · 22개 컴포넌트 |
- 기본 정렬 로직을 수정하여 aStart와 bStart의 차이를 반환하도록 변경하여 정렬 정확도 향상
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useGoogleCalendarData.ts (1)
33-39: 시간 범위가 컴포넌트 마운트 시점에 고정됩니다.
useMemo의 의존성 배열이 비어있어new Date()가 마운트 시점에만 평가됩니다. 사용자가 페이지를 오래 열어두면 시간 범위가 현재와 맞지 않을 수 있습니다. 7개월 범위라 큰 문제는 아니지만, 필요시 주기적 갱신을 고려해볼 수 있습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useGoogleCalendarData.ts` around lines 33 - 39, The eventTimeRange computed with useMemo is fixed at mount because its dependency array is empty; update eventTimeRange (in useGoogleCalendarData) so it recalculates over time by either removing useMemo (compute on each render), adding a time-based dependency (e.g., currentDate or currentMonth derived from Date.now()) or implementing a timer/state that updates periodically (e.g., daily) to trigger recomputation, ensuring the timeMin/timeMax reflect the current date rather than only the mount time.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useGoogleCalendarData.ts`:
- Line 152: The current isInitialChecking uses calendarsQuery.isPending which
becomes true on background refetches and causes UI flicker; update
useGoogleCalendarData to set isInitialChecking based on the initial load only
(e.g., use calendarsQuery.isLoading or the combination calendarsQuery.status ===
'pending' && calendarsQuery.fetchStatus === 'fetching', or implement a useRef
flag to mark first load completion) and ensure the exported symbol
isInitialChecking (from useGoogleCalendarData) is adjusted so
CalendarSyncTab.tsx reads a value that stays false after the initial load rather
than toggling on background refetches.
In
`@frontend/src/pages/ClubDetailPage/components/ClubScheduleCalendar/ClubScheduleCalendar.tsx`:
- Around line 76-77: The didInitFromEventsRef guard (didInitFromEventsRef) can
persist across club switches because the parent reuses ClubScheduleCalendar
without a key; update the component to reset that ref when the active club
changes by adding the club identifier (e.g., clubId or clubName) to the relevant
useEffect dependency or adding a useEffect that sets
didInitFromEventsRef.current = false when clubId/clubName changes, so
visibleMonth and selectedDateKey will reinitialize for the new club;
alternatively ensure the parent passes a key (key={clubId || clubName}) when
rendering ClubScheduleCalendar.
In `@frontend/src/utils/calendarSyncUtils.ts`:
- Around line 29-35: createState returns inconsistent formats:
crypto.randomUUID() yields a hyphenated UUID while the fallback returns a
32-char hex string; normalize both to the same format. Update createState so the
fallback (the Uint8Array path) produces a hyphenated UUID string (8-4-4-4-12) to
match randomUUID(), or alternatively strip hyphens from randomUUID() so both
paths return the same non-hyphenated 32-char hex; modify the logic in
createState (and ensure any comparisons in useGoogleCalendarData.ts where state
is validated) to use the chosen unified format.
---
Nitpick comments:
In
`@frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useGoogleCalendarData.ts`:
- Around line 33-39: The eventTimeRange computed with useMemo is fixed at mount
because its dependency array is empty; update eventTimeRange (in
useGoogleCalendarData) so it recalculates over time by either removing useMemo
(compute on each render), adding a time-based dependency (e.g., currentDate or
currentMonth derived from Date.now()) or implementing a timer/state that updates
periodically (e.g., daily) to trigger recomputation, ensuring the
timeMin/timeMax reflect the current date rather than only the mount time.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b0481af8-d680-4f8a-b16e-873be5688d6d
📒 Files selected for processing (17)
frontend/.eslintignorefrontend/CLAUDE.mdfrontend/public/mockServiceWorker.jsfrontend/src/constants/queryKeys.tsfrontend/src/hooks/Queries/useGoogleCalendar.tsfrontend/src/pages/AdminPage/tabs/CalendarSyncTab/CalendarSyncTab.styles.tsfrontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useGoogleCalendarData.tsfrontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useNotionCalendarData.tsfrontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useNotionCalendarUiState.tsfrontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useNotionOAuth.tsfrontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useUnifiedCalendarUiState.tsfrontend/src/pages/ClubDetailPage/ClubDetailPage.tsxfrontend/src/pages/ClubDetailPage/components/ClubScheduleCalendar/ClubScheduleCalendar.tsxfrontend/src/pages/PromotionPage/components/detail/PromotionClubCTA/PromotionClubCTA.tsxfrontend/src/pages/PromotionPage/utils/promotionNotification.tsfrontend/src/utils/calendarSyncUtils.tsfrontend/src/utils/formatKSTDateTime.ts
💤 Files with no reviewable changes (1)
- frontend/CLAUDE.md
frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useGoogleCalendarData.ts
Outdated
Show resolved
Hide resolved
frontend/src/pages/ClubDetailPage/components/ClubScheduleCalendar/ClubScheduleCalendar.tsx
Show resolved
Hide resolved
- hasCalendarEvents를 hasCalendarConnection으로 변경하여 클럽의 캘린더 연결 상태를 정확하게 반영
There was a problem hiding this comment.
🧹 Nitpick comments (1)
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx (1)
75-97:tabs와topBarTabs배열의 중복을 고려해볼 수 있습니다.두 배열이 거의 동일하며 첫 번째 탭 레이블만 다릅니다 ('소개 내용' vs '소개내용'). 향후 유지보수성을 위해 공통 로직을 추출하는 것을 고려해볼 수 있습니다.
♻️ 중복 제거를 위한 선택적 리팩토링 제안
+ const createTabs = (introLabel: string) => + [ + { key: TAB_TYPE.INTRO, label: introLabel }, + { key: TAB_TYPE.PHOTOS, label: '활동사진' }, + hasCalendarConnection + ? { key: TAB_TYPE.SCHEDULE, label: '일정 보기' } + : null, + ].filter(Boolean) as Array<{ key: TabType; label: string }>; - const tabs = useMemo( - () => - [ - { key: TAB_TYPE.INTRO, label: '소개 내용' }, - { key: TAB_TYPE.PHOTOS, label: '활동사진' }, - hasCalendarConnection - ? { key: TAB_TYPE.SCHEDULE, label: '일정 보기' } - : null, - ].filter(Boolean) as Array<{ key: TabType; label: string }>, - [hasCalendarConnection], - ); + const tabs = useMemo(() => createTabs('소개 내용'), [hasCalendarConnection]); - const topBarTabs = useMemo( - () => - [ - { key: TAB_TYPE.INTRO, label: '소개내용' }, - { key: TAB_TYPE.PHOTOS, label: '활동사진' }, - hasCalendarConnection - ? { key: TAB_TYPE.SCHEDULE, label: '일정 보기' } - : null, - ].filter(Boolean) as Array<{ key: TabType; label: string }>, - [hasCalendarConnection], - ); + const topBarTabs = useMemo(() => createTabs('소개내용'), [hasCalendarConnection]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx` around lines 75 - 97, The tabs and topBarTabs arrays are duplicated; extract a small helper (e.g., createTabs or buildTabList) that accepts the first intro label or a flag and returns Array<{ key: TabType; label: string }>, then replace both useMemo calls to call this helper with the appropriate intro label ('소개 내용' vs '소개내용') and the hasCalendarConnection boolean so the logic for adding TAB_TYPE.SCHEDULE is centralized; keep the useMemo wrappers and their dependency on hasCalendarConnection and ensure the helper preserves the same types and keys (TAB_TYPE.INTRO, TAB_TYPE.PHOTOS, TAB_TYPE.SCHEDULE).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx`:
- Around line 75-97: The tabs and topBarTabs arrays are duplicated; extract a
small helper (e.g., createTabs or buildTabList) that accepts the first intro
label or a flag and returns Array<{ key: TabType; label: string }>, then replace
both useMemo calls to call this helper with the appropriate intro label ('소개 내용'
vs '소개내용') and the hasCalendarConnection boolean so the logic for adding
TAB_TYPE.SCHEDULE is centralized; keep the useMemo wrappers and their dependency
on hasCalendarConnection and ensure the helper preserves the same types and keys
(TAB_TYPE.INTRO, TAB_TYPE.PHOTOS, TAB_TYPE.SCHEDULE).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a2286cee-fbe3-4df6-9bea-74b91caaf0dd
📒 Files selected for processing (2)
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsxfrontend/src/types/club.ts
- useRef를 사용하여 캘린더 데이터 로딩 상태를 추적하는 hasLoadedOnce 추가 - isInitialChecking 상태를 개선하여 초기 로딩 후에만 true로 설정되도록 수정
- clubId 또는 clubName을 key prop으로 사용하여 컴포넌트의 재렌더링 최적화
#️⃣연관된 이슈
📝작업 내용
PR에 대한 fix작업입니다.
중점적으로 리뷰받고 싶은 부분(선택)
논의하고 싶은 부분(선택)
🫡 참고사항
Summary by CodeRabbit
New Features
Bug Fixes
Style
Documentation
Chores