Skip to content

[Fix] pr review 1386#1387

Merged
seongwon030 merged 22 commits intodevelop-fefrom
fix/pr-review-1386
Apr 5, 2026
Merged

[Fix] pr review 1386#1387
seongwon030 merged 22 commits intodevelop-fefrom
fix/pr-review-1386

Conversation

@seongwon030
Copy link
Copy Markdown
Member

@seongwon030 seongwon030 commented Apr 5, 2026

🚀 릴리즈 PR인 경우 릴리즈 템플릿으로 전환해 주세요. (Preview 탭에서 클릭)

#️⃣연관된 이슈

ex) #이슈번호, #이슈번호

📝작업 내용

PR에 대한 fix작업입니다.

중점적으로 리뷰받고 싶은 부분(선택)

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요

ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요?

논의하고 싶은 부분(선택)

논의하고 싶은 부분이 있다면 작성해주세요.

🫡 참고사항

Summary by CodeRabbit

  • New Features

    • Google Calendar 동기화(캘린더/이벤트 조회, 선택, 연결 해제) 기능 추가
  • Bug Fixes

    • 날짜/시간 파싱 및 타임스탬프 안정성 개선
    • 캘린더 UI 초기화 재실행 방지 및 상태 동기화 안정화
    • OAuth 처리 및 오류 메시지 개선
    • 프로모션 링크 URL 인코딩 및 정렬 우선순위 개선
    • 암호학적 식별자 생성 방식 개선
  • Style

    • 테마 기반 색상 및 반응형 레이아웃 적용
  • Documentation

    • API 레이어 문서 항목 일부 정비(사용 안내 항목 축소)
  • Chores

    • 개발용 서비스 워커 파일 린트 무시 항목 추가

- `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 반환 시 빈 문자열을 반환하도록 수정
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
moadong Ready Ready Preview, Comment Apr 5, 2026 0:12am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 5, 2026

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid regex pattern for base branch. Received: "**" at "reviews.auto_review.base_branches[0]"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

React Query 기반 Google Calendar 훅과 쿼리 키를 추가하고, 캘린더 동기화·Notion·UI 훅들에 요청 취소·초기화 가드 도입, 날짜·난수 유틸 개선 및 스타일·문서·라우팅·lint 예외 소소한 변경을 적용했습니다.

Changes

Cohort / File(s) Summary
ESLint 및 MSW
frontend/.eslintignore, frontend/public/mockServiceWorker.js
mockServiceWorker.js를 eslint 무시 목록에 추가하고 파일 상단에 /* eslint-disable */ 지시문 삽입.
쿼리 키
frontend/src/constants/queryKeys.ts
queryKeysgoogleCalendar 네임스페이스(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 필드명 hasCalendarEventshasCalendarConnection으로 변경.
문서
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") 호출로 캐시 갱신
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

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.

❤️ Share

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

@seongwon030 seongwon030 added 💻 FE Frontend 🛠Fix 기능이 의도한 대로 동작하지 않는 버그를 수정 labels Apr 5, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 5, 2026

🎨 UI 변경사항을 확인해주세요

변경된 스토리를 Chromatic에서 확인해주세요.

구분 링크
🔍 변경사항 리뷰 https://www.chromatic.com/build?appId=67904e61c16daa99a63b44a7&number=146
📖 Storybook https://67904e61c16daa99a63b44a7-pvagqjsysc.chromatic.com/

2개 스토리 변경 · 전체 56개 스토리 · 22개 컴포넌트

- 기본 정렬 로직을 수정하여 aStart와 bStart의 차이를 반환하도록 변경하여 정렬 정확도 향상
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

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 (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

📥 Commits

Reviewing files that changed from the base of the PR and between 5527141 and 6f89739.

📒 Files selected for processing (17)
  • frontend/.eslintignore
  • frontend/CLAUDE.md
  • frontend/public/mockServiceWorker.js
  • frontend/src/constants/queryKeys.ts
  • frontend/src/hooks/Queries/useGoogleCalendar.ts
  • frontend/src/pages/AdminPage/tabs/CalendarSyncTab/CalendarSyncTab.styles.ts
  • frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useGoogleCalendarData.ts
  • frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useNotionCalendarData.ts
  • frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useNotionCalendarUiState.ts
  • frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useNotionOAuth.ts
  • frontend/src/pages/AdminPage/tabs/CalendarSyncTab/hooks/useUnifiedCalendarUiState.ts
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubScheduleCalendar/ClubScheduleCalendar.tsx
  • frontend/src/pages/PromotionPage/components/detail/PromotionClubCTA/PromotionClubCTA.tsx
  • frontend/src/pages/PromotionPage/utils/promotionNotification.ts
  • frontend/src/utils/calendarSyncUtils.ts
  • frontend/src/utils/formatKSTDateTime.ts
💤 Files with no reviewable changes (1)
  • frontend/CLAUDE.md

- hasCalendarEvents를 hasCalendarConnection으로 변경하여 클럽의 캘린더 연결 상태를 정확하게 반영
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx (1)

75-97: tabstopBarTabs 배열의 중복을 고려해볼 수 있습니다.

두 배열이 거의 동일하며 첫 번째 탭 레이블만 다릅니다 ('소개 내용' 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5e545ce and ca2a297.

📒 Files selected for processing (2)
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/types/club.ts

- useRef를 사용하여 캘린더 데이터 로딩 상태를 추적하는 hasLoadedOnce 추가
- isInitialChecking 상태를 개선하여 초기 로딩 후에만 true로 설정되도록 수정
- clubId 또는 clubName을 key prop으로 사용하여 컴포넌트의 재렌더링 최적화
@seongwon030 seongwon030 changed the title Fix/pr review 1386 [Fix] pr review 1386 Apr 5, 2026
Copy link
Copy Markdown
Collaborator

@suhyun113 suhyun113 left a comment

Choose a reason for hiding this comment

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

빠른 수정 좋아요! 수고하셨습니다~

@seongwon030 seongwon030 merged commit 3adb2fc into develop-fe Apr 5, 2026
5 checks passed
@seongwon030 seongwon030 deleted the fix/pr-review-1386 branch April 5, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend 🛠Fix 기능이 의도한 대로 동작하지 않는 버그를 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants