[FEAT] 찜 목록 API 연동 - #252
Conversation
This reverts commit 18ab8dd.
…ature/user-likes-api
- 찜 목록 조회 API(likes.api.ts)와 useLikedItems 훅 추가 - EVENT 카테고리 쿼리 파라미터를 서버 규격(CONTENT)에 맞게 매핑 - 코스 기간을 한글 라벨(당일치기/1박 2일 등)로 변환 - Kakao Map에 Haversine 기반 현위치-장소 거리 계산 및 표시 추가
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthrough찜 목록을 실제 API와 무한 스크롤에 연결했습니다. 항목 매핑, 거리·동행 정보 표시, 좋아요 취소와 상세 이동을 추가했습니다. Google Places 영업시간 조회를 구현하고 찜 목록과 상세 화면에 당일 영업시간을 표시했습니다. Changes찜 목록 API 및 화면
Google Places 영업시간
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant LikesPage
participant useLikedItems
participant getLikedItems
participant LikesAPI
LikesPage->>useLikedItems: 필터·검색어·정렬 전달
useLikedItems->>getLikedItems: 커서와 AbortSignal 전달
getLikedItems->>LikesAPI: GET /users/me/likes
LikesAPI-->>getLikedItems: 좋아요 항목과 다음 커서 반환
getLikedItems-->>useLikedItems: 앱 형식으로 변환된 응답 반환
useLikedItems-->>LikesPage: 페이지 목록 갱신
sequenceDiagram
participant DetailPage
participant usePlaceOpeningHours
participant getPlaceHours
participant HoursHandler
participant GooglePlaces
DetailPage->>usePlaceOpeningHours: 장소 목록 전달
usePlaceOpeningHours->>getPlaceHours: 장소별 조회 요청
getPlaceHours->>HoursHandler: POST /google-places/hours
HoursHandler->>GooglePlaces: 텍스트 검색 및 장소 상세 조회
GooglePlaces-->>HoursHandler: 영업시간 데이터 반환
HoursHandler-->>getPlaceHours: 영업시간 응답 반환
getPlaceHours-->>usePlaceOpeningHours: 장소별 결과 반환
usePlaceOpeningHours-->>DetailPage: 당일 영업시간 표시
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (3 warnings)
✅ Passed checks (2 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
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/apis/likes.api.ts`:
- Around line 40-53: Extend RawLikedItemResponse with the server’s event/place
detail classification field, then map it to LikedItem.detailType in the
liked-items transformation used by filterLikedItems instead of always assigning
null. Treat a missing value as unavailable and suppress event/place
detail-filter options when the server does not provide that classification.
In `@src/components/kakaomap/utils/kakaoMap.ts`:
- Around line 56-62: 거리 계산 함수의 중간값 a가 부동소수점 오차로 1을 초과하지 않도록 1 이하로 제한하세요. 반환 계산은
Math.asin(Math.sqrt(a)) 대신 제한된 a를 사용하는 Math.atan2 기반의 안정적인 대척점 거리 계산으로 변경하고, 기존
EARTH_RADIUS_METERS 스케일링은 유지하세요.
🪄 Autofix
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 Plus
Run ID: 6c3815a7-238d-49f2-bfd4-7ea213435ab0
📒 Files selected for processing (7)
src/apis/likes.api.tssrc/components/kakaomap/utils/kakaoMap.tssrc/pages/likes/hooks/useLikedItems.tssrc/pages/likes/index.tsxsrc/pages/likes/types.tssrc/pages/likes/utils/likedItems.tssrc/utils/courseCard.ts
📜 Review details
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2026-07-26T17:09:23.387Z
Learnt from: KJun-2
Repo: yeogido/frontend PR: 125
File: src/pages/local-recommendation/course-basic-info/components/CompanionSelector.tsx:82-90
Timestamp: 2026-07-26T17:09:23.387Z
Learning: 이 프로젝트의 반응형 스케일 정책에서는 텍스트(폰트) 크기를 설계 기준 값에 전역 `scale`을 곱해 비율대로 스케일하세요. `12px`, `14px`처럼 특정 최소 하한을 강제로 적용하거나(클램프/바닥값) 임의의 픽셀 값으로 제한하지 마세요. 즉, 기준값(디자인 스펙) × `scale` 방식으로 계산해 비율이 유지되도록 구현합니다.
Applied to files:
src/pages/likes/index.tsx
📚 Learning: 2026-08-03T09:41:11.931Z
Learnt from: KJun-2
Repo: yeogido/frontend PR: 188
File: src/pages/detail/components/CourseDetailLayout.tsx:202-205
Timestamp: 2026-08-03T09:41:11.931Z
Learning: When implementing the shared back-navigation UI component in yeogido/frontend, manage all UI dimensions, including positional offsets, according to the project’s global `scale` policy so the component remains visually consistent across screens.
Applied to files:
src/pages/likes/index.tsx
📚 Learning: 2026-07-26T17:09:27.685Z
Learnt from: KJun-2
Repo: yeogido/frontend PR: 125
File: src/pages/local-recommendation/course-basic-info/components/TransportSelector.tsx:84-91
Timestamp: 2026-07-26T17:09:27.685Z
Learning: In this project’s 390px-based continuous responsive scaling, do not apply an artificial minimum lower bound to text sizes (e.g., avoid clamping via Math.max/min-font-size patterns). Instead, compute typography using proportional ratio scaling: render font sizes as `VALUE * scale` (for example, `DESCRIPTION_FONT_SIZE * scale`). During review, flag any code that enforces a hard minimum text size that breaks the intended proportional scaling.
Applied to files:
src/pages/likes/index.tsx
📚 Learning: 2026-07-26T17:09:32.991Z
Learnt from: KJun-2
Repo: yeogido/frontend PR: 125
File: src/pages/local-recommendation/tag-selection/components/KeywordSelectionSection.tsx:51-56
Timestamp: 2026-07-26T17:09:32.991Z
Learning: When implementing responsive scaling in this project, prefer direct proportional calculations (e.g., using `VALUE * scale`) without applying artificial minimum lower bounds (clamps) to text sizes or other visual dimensions. Only introduce a lower bound when there is an explicitly documented exception; the primary allowed example is enforcing a 44px minimum touch target for interactive elements. In review, flag new/minimum clamps for text/visual dimensions unless they match an explicitly documented exception.
Applied to files:
src/pages/likes/index.tsx
📚 Learning: 2026-07-26T17:09:40.303Z
Learnt from: KJun-2
Repo: yeogido/frontend PR: 125
File: src/pages/local-recommendation/tag-selection/components/RepresentativePhotoSection.tsx:107-122
Timestamp: 2026-07-26T17:09:40.303Z
Learning: yeogido/frontend의 반응형 스케일 정책에 맞춰, 텍스트를 포함한 UI 치수는 (디자인 기준값) × 전역 `scale`로 “연속적으로” 계산하고, 12px·14px 같은 최소 폰트/사이즈 하한(floor) 클램프를 적용하지 않는다. `scaleValue`를 쓰더라도 텍스트에 임의의 minimum floor를 추가하거나 `Math.max(value, 12/14)` 같은 보정을 넣지 말 것.
Applied to files:
src/pages/likes/index.tsx
🔇 Additional comments (5)
src/pages/likes/types.ts (1)
3-4: LGTM!Also applies to: 30-30
src/pages/likes/utils/likedItems.ts (1)
13-19: LGTM!Also applies to: 130-148
src/utils/courseCard.ts (1)
9-9: LGTM!src/pages/likes/hooks/useLikedItems.ts (1)
17-45: LGTM!src/components/kakaomap/utils/kakaoMap.ts (1)
41-55: LGTM!Also applies to: 65-71
- 좋아요 목록 응답의 distance를 PLACE 카테고리 카드에 "현위치와 N KM"으로 표시 - 디자인 시안에 맞춰 카드 정보 줄 레이아웃 조정 - 아이콘을 늘리지 않고 14px 슬롯 가운데 원본 크기로 배치 - 태그 없는 카드는 정보 줄 간격을 넓게(22px) 사용 - 사용하지 않는 목 데이터(mockLikedItems) 제거 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 좋아요 목록 응답에 행사/장소 분류 값이 없어 항상 0건이던 2번째 필터 옵션 제거 - 하버사인 중간값을 1로 제한하고 asin 대신 atan2를 써 대척점에서 NaN이 나지 않게 수정 - 두 동작에 대한 테스트 추가 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ature/user-likes-api # Conflicts: # src/utils/courseCard.ts
ca158fd to
8774512
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 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 `@api/google-places/hours.ts`:
- Around line 15-39: Update the handler function to enforce server-side usage
controls before lookupPlaceHours, including an IP- or user-based rate limit and
a server-side cache for repeated requests. Also restrict the GOOGLE_MAPS_API_KEY
to the required Google APIs and deployment origins, while preserving the
existing method, validation, and error responses.
In `@api/google-places/placeHours.ts`:
- Around line 93-99: Update the Place Details request in the fetch call to
include the languageCode=ko query parameter, ensuring formatTodayOpeningHours
receives Korean weekday labels while preserving the existing placeId encoding
and field mask.
- Around line 85-90: Update the place lookup flow around searchResult and
placeId so it does not blindly accept searchResult.places[0]. Request the
identifying fields needed to validate candidates, such as name, address, and
coordinates, compare the candidate with the requested place and the Place
Details response, and return null when no candidate matches; only persist and
pass along a validated Google Place ID.
In `@src/hooks/usePlaceOpeningHours.ts`:
- Around line 68-72: Update formatTodayOpeningHours to prioritize
hours.currentOpeningHours when determining today’s description, falling back to
regularWeekdayDescriptions and then currentWeekdayDescriptions only when the
current opening-hours data is unavailable. Preserve the existing return
formatting while ensuring holidays and special schedules use the current-day
values.
In `@src/pages/detail/festival/index.tsx`:
- Line 204: Update the event information card props around festivalPlaceHours so
its hours value uses the fetched same-day operating hours instead of
festivalDetail.period. Preserve the existing fallback text when no
operating-hours data is available.
In `@src/pages/likes/index.tsx`:
- Around line 275-276: Update the card rendering around handleCardClick and
ContentCard so PLACE items do not receive an onClick handler or appear
interactive. In ContentCard, add keyboard handling for Enter and Space that
invokes onClick, while preserving the existing role="button" and tabIndex
behavior for clickable COURSE and EVENT cards.
- Around line 136-142: Update the opening-hours flow around usePlaceOpeningHours
so it does not create one Google Places query for every accumulated PLACE item
in likedItems. Limit lookups to the currently visible items or route them
through a batched, concurrency-limited API, while preserving the displayed
opening-hours behavior for items that are actually shown.
🪄 Autofix
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 Plus
Run ID: 029b7d69-b6cf-4b94-a871-4d8a75af6ce6
📒 Files selected for processing (11)
.env.exampleapi/google-places/hours.tsapi/google-places/placeHours.tssrc/apis/googlePlacesHours.tssrc/components/kakaomap/utils/kakaoMap.tssrc/hooks/usePlaceOpeningHours.tssrc/pages/detail/components/CourseDetailLayout.tsxsrc/pages/detail/festival/index.tsxsrc/pages/likes/index.tsxvercel.jsonvite.config.ts
💤 Files with no reviewable changes (1)
- src/components/kakaomap/utils/kakaoMap.ts
📜 Review details
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2026-07-26T17:09:23.387Z
Learnt from: KJun-2
Repo: yeogido/frontend PR: 125
File: src/pages/local-recommendation/course-basic-info/components/CompanionSelector.tsx:82-90
Timestamp: 2026-07-26T17:09:23.387Z
Learning: 이 프로젝트의 반응형 스케일 정책에서는 텍스트(폰트) 크기를 설계 기준 값에 전역 `scale`을 곱해 비율대로 스케일하세요. `12px`, `14px`처럼 특정 최소 하한을 강제로 적용하거나(클램프/바닥값) 임의의 픽셀 값으로 제한하지 마세요. 즉, 기준값(디자인 스펙) × `scale` 방식으로 계산해 비율이 유지되도록 구현합니다.
Applied to files:
src/pages/detail/festival/index.tsxsrc/pages/detail/components/CourseDetailLayout.tsxsrc/pages/likes/index.tsx
📚 Learning: 2026-08-03T09:41:11.931Z
Learnt from: KJun-2
Repo: yeogido/frontend PR: 188
File: src/pages/detail/components/CourseDetailLayout.tsx:202-205
Timestamp: 2026-08-03T09:41:11.931Z
Learning: When implementing the shared back-navigation UI component in yeogido/frontend, manage all UI dimensions, including positional offsets, according to the project’s global `scale` policy so the component remains visually consistent across screens.
Applied to files:
src/pages/detail/festival/index.tsxsrc/pages/detail/components/CourseDetailLayout.tsxsrc/pages/likes/index.tsx
📚 Learning: 2026-07-26T17:09:27.685Z
Learnt from: KJun-2
Repo: yeogido/frontend PR: 125
File: src/pages/local-recommendation/course-basic-info/components/TransportSelector.tsx:84-91
Timestamp: 2026-07-26T17:09:27.685Z
Learning: In this project’s 390px-based continuous responsive scaling, do not apply an artificial minimum lower bound to text sizes (e.g., avoid clamping via Math.max/min-font-size patterns). Instead, compute typography using proportional ratio scaling: render font sizes as `VALUE * scale` (for example, `DESCRIPTION_FONT_SIZE * scale`). During review, flag any code that enforces a hard minimum text size that breaks the intended proportional scaling.
Applied to files:
src/pages/detail/festival/index.tsxsrc/pages/detail/components/CourseDetailLayout.tsxsrc/pages/likes/index.tsx
📚 Learning: 2026-07-26T17:09:32.991Z
Learnt from: KJun-2
Repo: yeogido/frontend PR: 125
File: src/pages/local-recommendation/tag-selection/components/KeywordSelectionSection.tsx:51-56
Timestamp: 2026-07-26T17:09:32.991Z
Learning: When implementing responsive scaling in this project, prefer direct proportional calculations (e.g., using `VALUE * scale`) without applying artificial minimum lower bounds (clamps) to text sizes or other visual dimensions. Only introduce a lower bound when there is an explicitly documented exception; the primary allowed example is enforcing a 44px minimum touch target for interactive elements. In review, flag new/minimum clamps for text/visual dimensions unless they match an explicitly documented exception.
Applied to files:
src/pages/detail/festival/index.tsxsrc/pages/detail/components/CourseDetailLayout.tsxsrc/pages/likes/index.tsx
📚 Learning: 2026-07-26T17:09:40.303Z
Learnt from: KJun-2
Repo: yeogido/frontend PR: 125
File: src/pages/local-recommendation/tag-selection/components/RepresentativePhotoSection.tsx:107-122
Timestamp: 2026-07-26T17:09:40.303Z
Learning: yeogido/frontend의 반응형 스케일 정책에 맞춰, 텍스트를 포함한 UI 치수는 (디자인 기준값) × 전역 `scale`로 “연속적으로” 계산하고, 12px·14px 같은 최소 폰트/사이즈 하한(floor) 클램프를 적용하지 않는다. `scaleValue`를 쓰더라도 텍스트에 임의의 minimum floor를 추가하거나 `Math.max(value, 12/14)` 같은 보정을 넣지 말 것.
Applied to files:
src/pages/detail/festival/index.tsxsrc/pages/detail/components/CourseDetailLayout.tsxsrc/pages/likes/index.tsx
🪛 dotenv-linter (4.0.0)
.env.example
[warning] 5-5: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
[warning] 5-5: [UnorderedKey] The GOOGLE_MAPS_API_KEY key should go before the KAKAO_REST_API_KEY key
(UnorderedKey)
🔇 Additional comments (12)
src/pages/likes/index.tsx (6)
2-27: LGTM!
65-135: LGTM!
155-184: LGTM!
214-237: LGTM!
252-274: LGTM!
283-311: LGTM!src/apis/googlePlacesHours.ts (1)
1-30: LGTM!vercel.json (1)
7-15: LGTM!.env.example (1)
5-5: LGTM!vite.config.ts (1)
1-69: LGTM!src/pages/detail/components/CourseDetailLayout.tsx (1)
28-31: LGTM!Also applies to: 129-155, 312-322
src/pages/detail/festival/index.tsx (1)
18-100: LGTM!Also applies to: 235-235


작업 내용
휴무, 정보 미제공 시영업시간 정보 없음표시변경 화면
확인 방법
영업시간 정보 없음, 정규 휴무일은휴무로 표시되는지 확인합니다.체크리스트
스크린샷
참고 사항
GOOGLE_MAPS_API_KEY환경 변수로 설정해야 합니다.관련 이슈
Closes #245
Summary by CodeRabbit
새로운 기능
개선 사항