Skip to content

[NDGL-100] 장소 상세보기 관련 UI/UX 수정#29

Merged
mj010504 merged 4 commits into
developfrom
feature/NDGL-100
Feb 19, 2026
Merged

[NDGL-100] 장소 상세보기 관련 UI/UX 수정#29
mj010504 merged 4 commits into
developfrom
feature/NDGL-100

Conversation

@mj010504
Copy link
Copy Markdown
Contributor

@mj010504 mj010504 commented Feb 19, 2026

개요

  • 장소 상세보기 관련 UI/UX 수정

변경사항

  • 공통되는 PlaceInfo, ContentInfo 하나의 모델로 묶기
  • 공통되는 컴포넌트 정리 - AlternativePlaceContent, PlaceDetallTabRow, PlaceInfoTab, PlacePhotoTab, PlaceTipCard
  • PlaceBottomSheet 장소 이름 옆 버튼 위치 조정
  • PlanB 장소를 눌렀을 때 PlaceDetailScreen으로 화면 전환
  • PlaceDetailTabRow 활성화/비활성화 버튼/텍스트 색상 변경

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 장소 상세 정보 화면에서 대체 장소 선택 및 탐색 기능을 추가했습니다.
    • 여행 일정 추가 시 장소 검색 및 선택 기능을 개선했습니다.
  • 개선 사항

    • 장소 정보 표시 레이아웃을 재구성하여 더욱 일관되게 표현했습니다.
    • 장소 상세, 팁, 사진 탭 구성을 통합하여 사용자 경험을 개선했습니다.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 19, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

PlaceInfo 데이터 클래스를 공유 모델로 중앙화하고 id를 googlePlaceId로 변경합니다. AddItinerary, AddPlace, FollowTravel, PlaceDetail 등 여러 기능에서 PlaceInfo를 사용하도록 업데이트하며, 네비게이션 파라미터를 placeId에서 googlePlaceId로 변경합니다. UI 컴포넌트를 공유 버전으로 통합하고 TravelPlace 데이터 모델을 리팩토링합니다.

Changes

Cohort / File(s) Summary
PlaceInfo 모델 중앙화
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/model/PlaceInfo.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/model/ContentInfo.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/model/TipContent.kt, navigation/src/main/java/com/yapp/ndgl/navigation/Route.kt
PlaceInfo를 공유 모델로 생성하고 id를 googlePlaceId로 변경. ContentInfo, VideoInfo, Budget 데이터 클래스 추가. Route.PlaceDetail 및 Route.FollowPlaceDetail에서 placeId를 googlePlaceId로 변경.
AddItinerary 기능 업데이트
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/AddItineraryContract.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/AddItineraryScreen.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/AddItineraryViewModel.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/component/SearchPlaceMap.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/component/SearchedPlaceBottomSheet.kt
PlaceInfo를 새로운 위치에서 임포트하고, id에서 googlePlaceId를 사용하도록 변경. response.toPlaceInfo()를 사용하여 PlaceInfo 생성 로직 간소화. 공유 UI 컴포넌트(PlaceDetailTabRow, PlaceInfoTab, PlacePhotoTab) 사용.
AddPlace 기능 제거 및 통합
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/addplace/AddPlaceContract.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/addplace/AddPlaceScreen.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/addplace/AddPlaceViewModel.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/addplace/component/AddPlace*.kt
AddPlaceInfo를 제거하고 PlaceInfo를 사용. 기존 AddPlace 컴포넌트 삭제(AddPlaceTabRow, AddPlaceInfoTab, AddPlacePhotoTab). PlaceDetailTabRow, PlaceInfoTab, PlacePhotoTab으로 대체.
공유 UI 컴포넌트 생성
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlaceDetailTabRow.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlaceInfoTab.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlacePhotoTab.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlaceTipCard.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/AlternativePlaceContent.kt
PlaceInfo 모델을 기반으로 새로운 공유 UI 컴포넌트 생성. 탭 행, 정보 탭, 사진 탭, 팁 카드 등의 재사용 가능한 컴포넌트 구현.
FollowTravel 리팩토링
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/FollowTravelContract.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/FollowTravelViewModel.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/component/PlaceItem.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/component/TravelMap.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/component/ContentCard.kt
TravelPlace 모델을 PlaceInfo를 중첩하도록 재구성. ContentInfo, VideoInfo, Budget을 모델 패키지로 이동. 기존 OpeningHours 제거. 좌표 및 장소 정보 접근을 placeInfo로 통합.
FollowPlaceDetail 컴포넌트 교체
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/placedetail/FollowPlaceDetailContract.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/placedetail/FollowPlaceDetailScreen.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/placedetail/FollowPlaceDetailViewModel.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/placedetail/component/Follow*.kt
FollowPlaceInfo를 PlaceInfo로 교체. FollowPlaceDetailTabRow, FollowPlaceInfoTab, FollowPlacePhotoTab 제거. placeId를 googlePlaceId로 변경. 대체 장소 선택 네비게이션 추가.
PlaceDetail 리팩토링
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/placedetail/PlaceDetailContract.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/placedetail/PlaceDetailScreen.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/placedetail/PlaceDetailViewModel.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/placedetail/component/Place*.kt
PlaceDetailContract에서 PlaceInfo 제거 후 공유 모델 임포트. 공유 컴포넌트 사용. placeId를 googlePlaceId로 변경. 대체 장소 네비게이션 추가.
TravelDetail 리팩토링
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailContract.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailScreen.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailViewModel.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/PlaceItem.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/TravelMap.kt, feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/PlaceBottomSheet.kt
TravelPlace를 placeInfo 중첩 구조로 변경. selectedPlaceIds를 Set<Int>에서 Set<Long>으로 변경. 모든 좌표 및 장소 정보 접근을 placeInfo를 통해 수행. googlePlaceId 네비게이션 적용.
네비게이션 통합
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/navigation/TravelEntry.kt
placeId를 googlePlaceId로 변경. navigateToAlternativePlaceDetail 콜백 추가. 기존 레거시 OpeningHours 제거. 네비게이션 파라미터 통일.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

이 PR은 매우 광범위한 리팩토링으로 여러 기능에 걸쳐 PlaceInfo 모델을 중앙화하고, 데이터 구조를 재설계하며, 네비게이션 파라미터를 변경합니다. 26개 이상의 파일이 영향을 받으며, 각 변경은 데이터 접근 패턴, UI 컴포넌트 구성, 네비게이션 플로우 변경을 포함합니다. 복합적인 리팩토링으로 인해 자세한 검토와 통합 테스트가 필요합니다.

Possibly related PRs

Suggested reviewers

  • jihee-dev
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 PR의 주요 변경사항인 장소 상세보기 관련 UI/UX 수정을 명확하게 설명하고 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/NDGL-100

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.

Copy link
Copy Markdown

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
navigation/src/main/java/com/yapp/ndgl/navigation/Route.kt (1)

52-52: 🛠️ Refactor suggestion | 🟠 Major

AddPlace.placeIdgooglePlaceId로 변경하세요

PlaceDetail, FollowPlaceDetailgooglePlaceId로 변경되었으나 AddPlace는 여전히 placeId를 사용합니다. 네이밍 일관성을 위해 변경이 필요합니다.

♻️ 변경 사항
-    data class AddPlace(val placeId: String) : Route
+    data class AddPlace(val googlePlaceId: String) : Route

TravelEntry.kt (line 156):

-                factory.create(placeId = route.placeId)
+                factory.create(placeId = route.googlePlaceId)

AddPlaceViewModel.kt (constructor parameter 이름은 유지 가능):

-class AddPlaceViewModel `@AssistedInject` constructor(
-    `@Assisted` private val placeId: String,
+class AddPlaceViewModel `@AssistedInject` constructor(
+    `@Assisted` private val googlePlaceId: String,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@navigation/src/main/java/com/yapp/ndgl/navigation/Route.kt` at line 52,
AddPlace 데이터클래스의 프로퍼티명 placeId를 googlePlaceId로 변경하고, 이 변경에 따라 AddPlace를 생성하거나
매칭하는 모든 호출부와 패턴(예: when, nav args, serialization/deserialization),
TravelEntry에서의 사용 부분 그리고 관련 네비게이션 생성 지점들을 함께 업데이트하세요; AddPlaceViewModel의 생성자
파라미터 이름은 유지해도 되지만 내부에서 참조하는 필드명도 googlePlaceId로 맞추어 오류가 생기지 않도록 확인하세요.
🧹 Nitpick comments (13)
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/component/SearchedPlaceBottomSheet.kt (1)

162-165: navBarSectionHeight 변수명이 실제 역할과 맞지 않습니다.

이 48dp 값은 PlaceDetailTabRow(탭 바)의 높이를 의미하는데, 변수명 navBarSectionHeightNDGLNavigationBar로 오해하기 쉽습니다. NDGLNavigationBar는 스크롤 영역 바깥(상단 Box)에 위치하므로 여기서의 48dp는 탭 바와 관계있습니다.

♻️ 변수명 개선 제안
-val navBarSectionHeight = 48.dp
-val thumbnailHeightPx = with(density) { thumbnailHeight.toPx() }
-val navBarSectionHeightPx = with(density) { navBarSectionHeight.toPx() }
-val maxCollapseHeightPx = navBarSectionHeightPx + thumbnailHeightPx
+val tabRowHeight = 48.dp
+val thumbnailHeightPx = with(density) { thumbnailHeight.toPx() }
+val tabRowHeightPx = with(density) { tabRowHeight.toPx() }
+val maxCollapseHeightPx = tabRowHeightPx + thumbnailHeightPx

thumbnailProgress 계산식도 동일하게 변경 필요:

-val thumbnailProgress = (1f - (collapseOffset - navBarSectionHeightPx).coerceAtLeast(0f) / thumbnailHeightPx).coerceIn(0f, 1f)
+val thumbnailProgress = (1f - (collapseOffset - tabRowHeightPx).coerceAtLeast(0f) / thumbnailHeightPx).coerceIn(0f, 1f)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/component/SearchedPlaceBottomSheet.kt`
around lines 162 - 165, 현재 navBarSectionHeight라는 이름이 실제로는 PlaceDetailTabRow(탭
바)의 높이(48.dp)를 가리켜 오해의 소지가 있습니다; navBarSectionHeight를 placeDetailTabRowHeight 또는
tabBarHeight 같은 명확한 이름으로 변경하고 thumbnailProgress를 계산하는 식(참조: thumbnailHeight,
thumbnailHeightPx, maxCollapseHeightPx 등)이 새 이름을 사용하도록 모두 업데이트하세요; 또한
NDGLNavigationBar와 혼동되지 않도록 관련 주석도 갱신해 주세요.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/PlaceItem.kt (1)

220-298: 세 프리뷰의 PlaceInfo 생성 코드 중복 — 공유 상수 추출 권장

PlaceItemPreview, EditablePlaceItemUncheckedPreview, EditablePlaceItemCheckedPreview가 동일한 PlaceInfoTravelPlace.UserData 인스턴스를 반복 생성합니다. 프리뷰 전용 상수 하나로 추출하면 유지보수가 용이해집니다.

♻️ 리팩토링 제안
+private val previewTravelPlace = TravelPlace(
+    id = 1,
+    placeInfo = PlaceInfo(
+        day = 1,
+        sequence = 1,
+        googlePlaceId = "",
+        thumbnail = "",
+        latitude = 35.6585805,
+        longitude = 139.7454329,
+        name = "도쿄 타워",
+        googleMapsUri = "",
+        placeType = PlaceType.ATTRACTION,
+    ),
+    userData = TravelPlace.UserData(estimatedDuration = 60.minutes),
+    startTime = 10.hours,
+)

 `@Preview`
 `@Composable`
 private fun PlaceItemPreview() {
     NDGLTheme {
         PlaceItem(
-            place = TravelPlace(
-                id = 1,
-                placeInfo = PlaceInfo(
-                    day = 1,
-                    sequence = 1,
-                    googlePlaceId = "",
-                    thumbnail = "",
-                    latitude = 35.6585805,
-                    longitude = 139.7454329,
-                    name = "도쿄 타워",
-                    googleMapsUri = "",
-                    placeType = PlaceType.ATTRACTION,
-                ),
-                userData = TravelPlace.UserData(estimatedDuration = 60.minutes),
-                startTime = 10.hours,
-            ),
+            place = previewTravelPlace,
             onClick = {},
             onLongClick = {},
         )
     }
 }

EditablePlaceItemUncheckedPreview / EditablePlaceItemCheckedPreview도 동일하게 previewTravelPlace를 재사용하되, startTime이 다른 경우 copy(startTime = 12.hours)를 활용합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/PlaceItem.kt`
around lines 220 - 298, Extract a shared preview TravelPlace instance (e.g.,
previewTravelPlace) containing the common PlaceInfo and TravelPlace.UserData
used in PlaceItemPreview, EditablePlaceItemUncheckedPreview, and
EditablePlaceItemCheckedPreview, then reuse it in each preview and adjust
differing fields with copy(startTime = 12.hours) where needed; update
PlaceItemPreview, EditablePlaceItemUncheckedPreview, and
EditablePlaceItemCheckedPreview to reference previewTravelPlace (and call
copy(...) to change startTime for the editable previews) to remove duplication
while keeping existing onClick/onLongClick/onCheck parameters.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlacePhotoTab.kt (1)

23-23: 불필요한 kotlin.collections.forEach import 제거 권장

forEach는 Kotlin 표준 라이브러리에서 자동으로 사용 가능한 확장 함수로, 명시적 import가 필요 없습니다.

♻️ 제안된 수정
-import kotlin.collections.forEach
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlacePhotoTab.kt`
at line 23, Remove the unnecessary explicit import of kotlin.collections.forEach
in PlacePhotoTab (the import line "import kotlin.collections.forEach"); forEach
is a Kotlin stdlib extension and does not require an explicit import, so delete
that import statement to clean up unused imports in the PlacePhotoTab
file/class.
navigation/src/main/java/com/yapp/ndgl/navigation/Route.kt (1)

29-40: alternativePlaces 기본값 타입 불일치에 대한 설계 의도 명시 필요

PlaceDetail.alternativePlacesList<RouteAlternativePlace>? = null이고, FollowPlaceDetail.alternativePlacesList<RouteAlternativePlace> = emptyList()로 정의되어 있습니다. 현재 코드는 TravelEntry.kt에서 이 차이를 명시적으로 처리하고 있습니다 (FollowPlaceDetail 생성 시 null을 emptyList()로 변환). 이러한 설계 선택이 의도적이라면, 각 타입에 주석을 추가하여 왜 다른 기본값을 사용하는지 명시하는 것이 좋습니다. PlaceDetail은 개인 여행용(nullable 허용), FollowPlaceDetail은 팔로우 여행용(항상 비어있는 리스트)이라는 의도를 코드 레벨에서 명확히 하면 향후 유지보수가 용이해집니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@navigation/src/main/java/com/yapp/ndgl/navigation/Route.kt` around lines 29 -
40, Add clear KDoc comments above the data classes PlaceDetail and
FollowPlaceDetail explaining the design intent for alternativePlaces: state that
PlaceDetail.alternativePlaces is nullable (List<RouteAlternativePlace>? = null)
to represent optional personal-travel alternatives, while
FollowPlaceDetail.alternativePlaces uses a non-null empty list
(List<RouteAlternativePlace> = emptyList()) because follow-trips always
normalize null to empty and consumers expect a non-null collection; also
reference in the comment that TravelEntry.kt explicitly converts null to
emptyList() when constructing FollowPlaceDetail so readers know where the
normalization occurs.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/AddItineraryContract.kt (1)

85-92: placeIdgooglePlaceId 이름 변경 누락

SelectablePlace, SearchResult, CheckSelectablePlace, ClickSelectablePlace 등 AddItinerary의 대부분의 클래스와 PlaceInfo 모델에서는 googlePlaceId를 사용하지만, BookMarkPlaceNavigateToAddPlace는 여전히 placeId를 사용하고 있어 일관성이 떨어집니다. 특히 AddItineraryViewModel.kt:271에서 googlePlaceIdNavigateToAddPlace(placeId)로 전달하고 있으므로, 의미론적 일관성을 위해 이 두 클래스의 파라미터명을 googlePlaceId로 변경하는 것을 권장합니다.

♻️ 제안된 수정
-    data class BookMarkPlace(val placeId: String) : AddItineraryIntent
+    data class BookMarkPlace(val googlePlaceId: String) : AddItineraryIntent

-    data class NavigateToAddPlace(val placeId: String) : AddItinerarySideEffect
+    data class NavigateToAddPlace(val googlePlaceId: String) : AddItinerarySideEffect
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/AddItineraryContract.kt`
around lines 85 - 92, The parameter name inconsistency: change the BookMarkPlace
data class and the NavigateToAddPlace side-effect to use googlePlaceId instead
of placeId (i.e., BookMarkPlace(val googlePlaceId: String) and
NavigateToAddPlace(val googlePlaceId: String)), and update all call sites (for
example the place where NavigateToAddPlace(placeId) is constructed and any
BookMarkPlace(...) usages) to pass and reference googlePlaceId so names are
consistent with SelectablePlace, SearchResult, CheckSelectablePlace,
ClickSelectablePlace and PlaceInfo.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailContract.kt (1)

105-105: Intent와 SideEffect 간 파라미터 네이밍 불일치

TravelDetailIntent.NavigateToTravelPlaceDetailplaceId: String(Line 105)을 사용하지만, TravelDetailSideEffect.NavigateToTravelPlaceDetailgooglePlaceId: String(Line 117)을 사용합니다. 이 PR에서 placeIdgooglePlaceId로 전환하고 있으므로, Intent 쪽도 googlePlaceId로 통일하는 것이 일관성 있습니다.

♻️ 네이밍 통일 제안
-    data class NavigateToTravelPlaceDetail(val placeId: String) : TravelDetailIntent
+    data class NavigateToTravelPlaceDetail(val googlePlaceId: String) : TravelDetailIntent

Also applies to: 116-117

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailContract.kt`
at line 105, Update the parameter name in
TravelDetailIntent.NavigateToTravelPlaceDetail from placeId: String to
googlePlaceId: String so it matches
TravelDetailSideEffect.NavigateToTravelPlaceDetail; update all
usages/constructor calls and any pattern matching or when branches that
reference NavigateToTravelPlaceDetail to use googlePlaceId to keep naming
consistent across intent and side-effect handling.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/FollowTravelContract.kt (1)

38-44: NavigateToFollowPlaceDetail의 파라미터명이 placeId로 남아있습니다.

TravelDetailSideEffect.NavigateToTravelPlaceDetail에서는 googlePlaceId로 변경되었지만, 이 파일의 NavigateToFollowPlaceDetail은 여전히 placeId를 사용합니다. 일관성을 위해 googlePlaceId로 통일하는 것을 권장합니다.

♻️ 네이밍 통일 제안
 sealed interface FollowTravelSideEffect : UiSideEffect {
     data class NavigateToFollowPlaceDetail(
-        val placeId: String,
+        val googlePlaceId: String,
         val tipContent: TipContent?,
         val alternativePlaces: List<AlternativePlace>?,
     ) :
         FollowTravelSideEffect
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/FollowTravelContract.kt`
around lines 38 - 44, Rename the NavigateToFollowPlaceDetail data class
parameter from placeId to googlePlaceId in FollowTravelSideEffect (key symbol:
NavigateToFollowPlaceDetail) and update all usages/signatures accordingly
(references in constructors, callers, and any mapping to TipContent or
AlternativePlace). Ensure the property name change is reflected in
serialization/parcelization and in any code that constructs or deconstructs
NavigateToFollowPlaceDetail so the type remains consistent with
TravelDetailSideEffect.NavigateToTravelPlaceDetail.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/addplace/AddPlaceViewModel.kt (1)

19-19: AddPlaceViewModel의 파라미터명을 googlePlaceId로 통일 필요

PlaceDetailViewModel과 FollowPlaceDetailViewModel은 이미 googlePlaceId로 통일되어 있으나, AddPlaceViewModel만 placeId를 사용 중입니다. 코드베이스 전체의 일관성을 위해 여기도 함께 변경하는 것을 권장합니다.

변경 대상:

  • 생성자 파라미터 (19행)
  • Factory 메서드 시그니처 (92-95행)
  • 내부 사용처: loadPlaceDetail() (30행), loadPlacePhotos() (44행)
  • 호출 지점: TravelEntry.kt의 factory.create(placeId = ...) 도 함께 변경 필요
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/addplace/AddPlaceViewModel.kt`
at line 19, AddPlaceViewModel의 생성자 파라미터명 placeId를 googlePlaceId로 바꿔 일관성 유지하세요:
생성자 선언(현재 `@Assisted` private val placeId)과 Factory 메서드 시그니처를 googlePlaceId로 변경하고,
내부에서 참조되는 loadPlaceDetail()와 loadPlacePhotos() 호출부도 모두 새 이름으로 전달되도록 수정하며, 이 뷰모델을
생성하는 호출(예: TravelEntry.kt의 factory.create(placeId = ...))도
factory.create(googlePlaceId = ...)로 함께 업데이트하세요.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/model/TipContent.kt (1)

3-6: tips 를 nullable로 변경 + PlaceTipCardrequire() 조합 — 런타임 크래시 위험

tips: List<String>? = null로 변경하면서 PlaceTipCard 내부에서 require(tips != null)로 null 여부를 강제 검증하는 패턴이 됩니다. Composable이 예외를 던질 경우 어떻게 전파될지 명확히 정의되어 있지 않으며, 현재 호출부인 PlaceInfoTabisNullOrEmpty() 가드로 보호하고 있지만, 다른 곳에서 PlaceTipCard를 직접 호출하면 IllegalArgumentException으로 앱이 크래시됩니다.

API 계약을 컴파일 타임에 보장하려면 tips를 non-nullable로 유지하거나, PlaceTipCard 내부에서 null/empty 조건을 graceful하게 처리하는 것을 권장합니다.

♻️ 대안: `tips`를 non-nullable로 유지
 data class TipContent(
     val creatorName: String = "",
-    val tips: List<String>? = null,
+    val tips: List<String> = emptyList(),
 )

그에 맞춰 PlaceTipCard.kt도 수정:

-    require(tips != null)
-    val pagerState = rememberPagerState(pageCount = { tips.size })
+    if (tips.isEmpty()) return
+    val pagerState = rememberPagerState(pageCount = { tips.size })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/model/TipContent.kt`
around lines 3 - 6, The TipContent.tips field was made nullable which forces
callers like PlaceTipCard to use require(tips != null) and risks runtime
IllegalArgumentException; revert tips to a non-nullable list (e.g., change
TipContent.tips to val tips: List<String> = emptyList()) and update PlaceTipCard
to stop using require(...) and instead work with the non-null list (or
alternatively, if you prefer nullable, remove the require and handle null/empty
gracefully inside PlaceTipCard). Update any callers (e.g., PlaceInfoTab) to
pass/expect a non-null list and remove redundant null checks like
isNullOrEmpty() where appropriate so the API contract is enforced at compile
time.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/component/TravelMap.kt (1)

122-124: key {} 블록 누락 — traveldetail 버전과 불일치

traveldetail/component/TravelMap.ktkey(place.id, place.placeInfo.sequence) { PlaceMarker(...) } 블록을 사용하지만, 이 파일의 forEach에는 key {} 블록이 없습니다. 리스트가 재정렬되거나 중간 항목이 삭제될 경우 Compose가 위치 기반으로 composition slot을 재사용하려 할 수 있어 비효율적인 recomposition이 발생할 수 있습니다.

♻️ key 블록 추가 제안
+import androidx.compose.runtime.key

 places.forEach { place ->
-    PlaceMarker(place = place)
+    key(place.id, place.placeInfo.sequence) {
+        PlaceMarker(place = place)
+    }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/component/TravelMap.kt`
around lines 122 - 124, The places.forEach loop in TravelMap.kt lacks a key
block which can cause wrong composition reuse; wrap the PlaceMarker composable
inside a stable key using the place identifiers (e.g., place.id and
place.placeInfo.sequence) so Compose can track items across reorders/deletions;
locate the loop that calls PlaceMarker(place = place) and replace it with a
key(...) { PlaceMarker(...) } using those unique symbols to prevent
position-based slot reuse.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlaceTipCard.kt (1)

39-43: Composable 내부 require() — null일 경우 앱 크래시

require(tips != null)이 실패하면 IllegalArgumentException이 발생하며, Composable이 예외를 던질 때의 동작이 명확히 정의되어 있지 않습니다. 현재는 PlaceInfoTabisNullOrEmpty() 가드로 보호하고 있지만, 이 컴포넌트를 다른 곳에서 재사용할 경우 크래시 위험이 있습니다.

TipContent.tips를 non-nullable로 변경하거나(TipContent.kt 코멘트 참고), null/empty 시 gracefully 렌더링하지 않는 방식으로 수정하는 것을 권장합니다.

♻️ 제안된 수정 (null guard early return)
 `@Composable`
 internal fun PlaceTipCard(tipContent: TipContent) {
     val creatorName = tipContent.creatorName
     val tips = tipContent.tips
-    require(tips != null)
+    if (tips.isNullOrEmpty()) return
     val pagerState = rememberPagerState(pageCount = { tips.size })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlaceTipCard.kt`
around lines 39 - 43, Replace the unsafe require(tips != null) in the
PlaceTipCard composable with a graceful null/empty guard: check TipContent.tips
via if (tips.isNullOrEmpty()) return (or render an empty placeholder) so the
composable exits early instead of throwing; then only call
rememberPagerState(pageCount = { tips.size }) after the guard so pagerState
never receives a null/zero source. Update references in PlaceTipCard (tips,
pagerState, rememberPagerState) to rely on the early-return guard; alternatively
consider making TipContent.tips non-nullable in TipContent if you prefer
model-level enforcement.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/component/PlaceItem.kt (1)

90-91: PlaceCard의 가시성이 public으로 설정됨

PlaceIteminternal이고 PlaceNumberprivate인 반면, PlaceCardpublic으로 선언되어 있습니다. 모듈 외부에서 사용하지 않는다면 internal로 변경하는 것이 좋습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/component/PlaceItem.kt`
around lines 90 - 91, PlaceCard is declared public while PlaceItem is internal
and PlaceNumber is private; make PlaceCard internal to match module visibility
and avoid exposing it outside the module. Change the function declaration of
PlaceCard to internal (i.e., update the modifier on fun PlaceCard) and run a
quick project-wide search for usages of PlaceCard to confirm no external modules
depend on it; if any external use exists, either keep it public with
justification or refactor callers into the same module.
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/placedetail/FollowPlaceDetailScreen.kt (1)

89-274: FollowPlaceDetailScreenPlaceDetailScreen의 레이아웃 코드 중복

두 화면의 레이아웃 구조(collapsible header, nested scroll, thumbnail, tab row, lazy column)가 거의 동일합니다. PlaceDetailScreen과의 차이점은 모달/변경 기능 유무 정도입니다. 이번 PR에서 컴포넌트 통합이 잘 진행되고 있으므로, 추후 공통 레이아웃을 별도 컴포저블로 추출하면 유지보수성이 더 향상될 것입니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/placedetail/FollowPlaceDetailScreen.kt`
around lines 89 - 274, The FollowPlaceDetailScreen duplicates most of the
collapsible header + nested scroll layout from PlaceDetailScreen; extract the
common structure (nestedScrollConnection, collapseOffset logic,
navBarProgress/thumbnailProgress calculations, thumbnail rendering,
PlaceDetailTabRow and LazyColumn container) into a shared composable (e.g.,
CollapsiblePlaceDetailLayout or PlaceDetailLayout) that accepts
parameters/callbacks for placeInfo, selectedTab, clickBackButton, selectTab,
clickAddress, clickMenu, clickAlternativePlace and slot lambdas for the
tab-specific content (INFO vs PHOTO) and optional modal/modify UI; then refactor
FollowPlaceDetailScreen and PlaceDetailScreen to call that shared composable and
pass only their differing behavior (modal flags, extra actions, and the tab
content) so layout logic lives in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/component/SearchedPlaceBottomSheet.kt`:
- Around line 219-220: PlaceDetailTabRow already renders a HorizontalDivider
internally, so remove the extra HorizontalDivider call in
SearchedPlaceBottomSheet (the line immediately after
PlaceDetailTabRow(selectedTab = selectedTab, onTabSelected = { selectedTab = it
})) to avoid double dividers; keep only the PlaceDetailTabRow invocation (or, if
you prefer the external divider, remove the divider inside PlaceDetailTabRow) so
only one divider is rendered.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/AlternativePlaceContent.kt`:
- Line 50: AlternativePlace.id is hardcoded to an empty string when creating
AlternativePlace in FollowTravelViewModel (where AlternativePlace is constructed
with id = "") which causes onClick(alternativePlace.id) in
AlternativePlaceContent to pass an empty googlePlaceId; update the model/mapping
so the alternative place has the real Google Place ID—either add a googlePlaceId
field to PlanBPlace (and populate it when creating AlternativePlace) or change
the mapping logic in FollowTravelViewModel (the AlternativePlace creation code)
to supply the actual ID instead of "". Ensure AlternativePlaceContent continues
to call onClick(alternativePlace.id) and
FollowTravelViewModel/FollowPlaceDetailIntent receives the real ID.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlaceInfoTab.kt`:
- Around line 99-111: The divider currently shows when placeInfo.tipContent !=
null || placeInfo.alternativePlaces != null which can render a divider without
any content; change the divider condition to the same checks used for rendering
content so it only shows when there is actual content: use the same null/empty
checks as the PlaceTipCard and the alternative-places rendering (e.g.,
!placeInfo.tipContent?.tips.isNullOrEmpty() ||
!placeInfo.alternativePlaces.isNullOrEmpty()), updating the condition near the
divider and keeping PlaceTipCard(tipContent = placeInfo.tipContent) and the
alternative places block unchanged.
- Around line 108-111: placeInfo.tipContent is nullable but PlaceTipCard expects
a non-null TipContent; change the null-check logic so you first obtain a
non-null TipContent reference and only then call PlaceTipCard. For example,
guard using a local val or use Kotlin's let/takeIf to ensure tipContent is
non-null and its tips list is not empty, then call PlaceTipCard with that
non-null TipContent (referencing placeInfo.tipContent, TipContent, tips, and
PlaceTipCard).

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/FollowTravelViewModel.kt`:
- Around line 113-116: The code has a race: toItinerary() reads
state.value.contentInfo.videoInfo.creatorName while
loadTravelTemplateItinerary() and loadTravelTemplateContentInfo() run
concurrently, causing creatorName to be empty if itinerary arrives first; fix by
making contentInfo load before mapping or by deferring injection of
creatorName—either sequence loadTravelTemplateContentInfo() and on its success
call loadTravelTemplateItinerary(), or change toItinerary()/TipContent
construction to omit reading state.value.contentInfo.videoInfo.creatorName
(leave creatorName empty or null) and then, when loadTravelTemplateContentInfo()
completes, update the mapped itinerary/TipContent with the actual creatorName.
- Around line 117-124: The mapping for alternativePlaces is incorrectly using
the parent item's category (item.place.category.toPlaceType()) because
PlanBPlace currently lacks a category; update the PlanBPlace data model to
include a category field, populate it where PlanBPlace instances are created,
and change the mapper in FollowTravelViewModel (the item.planB.map block that
constructs AlternativePlace) to use planB.category.toPlaceType() for placeType
(keep other fields like name and feature as-is and set id appropriately if
needed).

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/model/ContentInfo.kt`:
- Line 4: The ContentInfo data model declares travelId as Int which is
inconsistent with the rest of the codebase and the server model
(TravelTemplateContentInfo.travelId: Long) and can lead to overflow/data loss;
change the travelId property in ContentInfo to Long (use 0L as the default) and
then update any constructors, mappers or usages that instantiate ContentInfo
(e.g., mapping functions from TravelTemplateContentInfo, places referencing
ContentInfo.travelId) to accept/propagate Longs so the type is uniform across
Route/ViewModel/Contract and matches the server model.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/navigation/TravelEntry.kt`:
- Around line 56-60: The nested null-safe lets around tipContent drop
creatorName when content.tips is null; update the mapping that builds
RouteTipContent so it preserves creatorName and supplies a non-null tips
fallback (e.g., use content.tips ?: emptyList()) like: tipContent?.let { content
-> RouteTipContent(creatorName = content.creatorName, tips = content.tips ?:
emptyList()) }, and apply the same fix to the other occurrence; if the original
intent was to allow null result when tips is null, instead add a clarifying
comment near the tipContent -> RouteTipContent mapping explaining that behavior.

---

Outside diff comments:
In `@navigation/src/main/java/com/yapp/ndgl/navigation/Route.kt`:
- Line 52: AddPlace 데이터클래스의 프로퍼티명 placeId를 googlePlaceId로 변경하고, 이 변경에 따라
AddPlace를 생성하거나 매칭하는 모든 호출부와 패턴(예: when, nav args,
serialization/deserialization), TravelEntry에서의 사용 부분 그리고 관련 네비게이션 생성 지점들을 함께
업데이트하세요; AddPlaceViewModel의 생성자 파라미터 이름은 유지해도 되지만 내부에서 참조하는 필드명도 googlePlaceId로
맞추어 오류가 생기지 않도록 확인하세요.

---

Nitpick comments:
In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/AddItineraryContract.kt`:
- Around line 85-92: The parameter name inconsistency: change the BookMarkPlace
data class and the NavigateToAddPlace side-effect to use googlePlaceId instead
of placeId (i.e., BookMarkPlace(val googlePlaceId: String) and
NavigateToAddPlace(val googlePlaceId: String)), and update all call sites (for
example the place where NavigateToAddPlace(placeId) is constructed and any
BookMarkPlace(...) usages) to pass and reference googlePlaceId so names are
consistent with SelectablePlace, SearchResult, CheckSelectablePlace,
ClickSelectablePlace and PlaceInfo.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/additinerary/component/SearchedPlaceBottomSheet.kt`:
- Around line 162-165: 현재 navBarSectionHeight라는 이름이 실제로는 PlaceDetailTabRow(탭 바)의
높이(48.dp)를 가리켜 오해의 소지가 있습니다; navBarSectionHeight를 placeDetailTabRowHeight 또는
tabBarHeight 같은 명확한 이름으로 변경하고 thumbnailProgress를 계산하는 식(참조: thumbnailHeight,
thumbnailHeightPx, maxCollapseHeightPx 등)이 새 이름을 사용하도록 모두 업데이트하세요; 또한
NDGLNavigationBar와 혼동되지 않도록 관련 주석도 갱신해 주세요.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/addplace/AddPlaceViewModel.kt`:
- Line 19: AddPlaceViewModel의 생성자 파라미터명 placeId를 googlePlaceId로 바꿔 일관성 유지하세요:
생성자 선언(현재 `@Assisted` private val placeId)과 Factory 메서드 시그니처를 googlePlaceId로 변경하고,
내부에서 참조되는 loadPlaceDetail()와 loadPlacePhotos() 호출부도 모두 새 이름으로 전달되도록 수정하며, 이 뷰모델을
생성하는 호출(예: TravelEntry.kt의 factory.create(placeId = ...))도
factory.create(googlePlaceId = ...)로 함께 업데이트하세요.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlacePhotoTab.kt`:
- Line 23: Remove the unnecessary explicit import of kotlin.collections.forEach
in PlacePhotoTab (the import line "import kotlin.collections.forEach"); forEach
is a Kotlin stdlib extension and does not require an explicit import, so delete
that import statement to clean up unused imports in the PlacePhotoTab
file/class.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/component/PlaceTipCard.kt`:
- Around line 39-43: Replace the unsafe require(tips != null) in the
PlaceTipCard composable with a graceful null/empty guard: check TipContent.tips
via if (tips.isNullOrEmpty()) return (or render an empty placeholder) so the
composable exits early instead of throwing; then only call
rememberPagerState(pageCount = { tips.size }) after the guard so pagerState
never receives a null/zero source. Update references in PlaceTipCard (tips,
pagerState, rememberPagerState) to rely on the early-return guard; alternatively
consider making TipContent.tips non-nullable in TipContent if you prefer
model-level enforcement.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/component/PlaceItem.kt`:
- Around line 90-91: PlaceCard is declared public while PlaceItem is internal
and PlaceNumber is private; make PlaceCard internal to match module visibility
and avoid exposing it outside the module. Change the function declaration of
PlaceCard to internal (i.e., update the modifier on fun PlaceCard) and run a
quick project-wide search for usages of PlaceCard to confirm no external modules
depend on it; if any external use exists, either keep it public with
justification or refactor callers into the same module.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/component/TravelMap.kt`:
- Around line 122-124: The places.forEach loop in TravelMap.kt lacks a key block
which can cause wrong composition reuse; wrap the PlaceMarker composable inside
a stable key using the place identifiers (e.g., place.id and
place.placeInfo.sequence) so Compose can track items across reorders/deletions;
locate the loop that calls PlaceMarker(place = place) and replace it with a
key(...) { PlaceMarker(...) } using those unique symbols to prevent
position-based slot reuse.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/FollowTravelContract.kt`:
- Around line 38-44: Rename the NavigateToFollowPlaceDetail data class parameter
from placeId to googlePlaceId in FollowTravelSideEffect (key symbol:
NavigateToFollowPlaceDetail) and update all usages/signatures accordingly
(references in constructors, callers, and any mapping to TipContent or
AlternativePlace). Ensure the property name change is reflected in
serialization/parcelization and in any code that constructs or deconstructs
NavigateToFollowPlaceDetail so the type remains consistent with
TravelDetailSideEffect.NavigateToTravelPlaceDetail.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/followtravel/placedetail/FollowPlaceDetailScreen.kt`:
- Around line 89-274: The FollowPlaceDetailScreen duplicates most of the
collapsible header + nested scroll layout from PlaceDetailScreen; extract the
common structure (nestedScrollConnection, collapseOffset logic,
navBarProgress/thumbnailProgress calculations, thumbnail rendering,
PlaceDetailTabRow and LazyColumn container) into a shared composable (e.g.,
CollapsiblePlaceDetailLayout or PlaceDetailLayout) that accepts
parameters/callbacks for placeInfo, selectedTab, clickBackButton, selectTab,
clickAddress, clickMenu, clickAlternativePlace and slot lambdas for the
tab-specific content (INFO vs PHOTO) and optional modal/modify UI; then refactor
FollowPlaceDetailScreen and PlaceDetailScreen to call that shared composable and
pass only their differing behavior (modal flags, extra actions, and the tab
content) so layout logic lives in one place.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/model/TipContent.kt`:
- Around line 3-6: The TipContent.tips field was made nullable which forces
callers like PlaceTipCard to use require(tips != null) and risks runtime
IllegalArgumentException; revert tips to a non-nullable list (e.g., change
TipContent.tips to val tips: List<String> = emptyList()) and update PlaceTipCard
to stop using require(...) and instead work with the non-null list (or
alternatively, if you prefer nullable, remove the require and handle null/empty
gracefully inside PlaceTipCard). Update any callers (e.g., PlaceInfoTab) to
pass/expect a non-null list and remove redundant null checks like
isNullOrEmpty() where appropriate so the API contract is enforced at compile
time.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/PlaceItem.kt`:
- Around line 220-298: Extract a shared preview TravelPlace instance (e.g.,
previewTravelPlace) containing the common PlaceInfo and TravelPlace.UserData
used in PlaceItemPreview, EditablePlaceItemUncheckedPreview, and
EditablePlaceItemCheckedPreview, then reuse it in each preview and adjust
differing fields with copy(startTime = 12.hours) where needed; update
PlaceItemPreview, EditablePlaceItemUncheckedPreview, and
EditablePlaceItemCheckedPreview to reference previewTravelPlace (and call
copy(...) to change startTime for the editable previews) to remove duplication
while keeping existing onClick/onLongClick/onCheck parameters.

In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailContract.kt`:
- Line 105: Update the parameter name in
TravelDetailIntent.NavigateToTravelPlaceDetail from placeId: String to
googlePlaceId: String so it matches
TravelDetailSideEffect.NavigateToTravelPlaceDetail; update all
usages/constructor calls and any pattern matching or when branches that
reference NavigateToTravelPlaceDetail to use googlePlaceId to keep naming
consistent across intent and side-effect handling.

In `@navigation/src/main/java/com/yapp/ndgl/navigation/Route.kt`:
- Around line 29-40: Add clear KDoc comments above the data classes PlaceDetail
and FollowPlaceDetail explaining the design intent for alternativePlaces: state
that PlaceDetail.alternativePlaces is nullable (List<RouteAlternativePlace>? =
null) to represent optional personal-travel alternatives, while
FollowPlaceDetail.alternativePlaces uses a non-null empty list
(List<RouteAlternativePlace> = emptyList()) because follow-trips always
normalize null to empty and consumers expect a non-null collection; also
reference in the comment that TravelEntry.kt explicitly converts null to
emptyList() when constructing FollowPlaceDetail so readers know where the
normalization occurs.

Comment thread feature/travel/src/main/java/com/yapp/ndgl/feature/travel/model/ContentInfo.kt Outdated
@mj010504 mj010504 merged commit e4f080e into develop Feb 19, 2026
2 checks passed
@mj010504 mj010504 deleted the feature/NDGL-100 branch February 19, 2026 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant