[FEAT/#35] 챌린지 뷰 컴포넌트 구현#41
Conversation
- 카테고리 enum으로 적용 - Column -> Grid로 변경 - Viewmodel로 받을 수 있게 주입 변경 - 파라미터명 표시
Walkthrough챌린지 루틴 온보딩 기능을 위한 새로운 Compose UI 컴포넌트와 데이터 모델을 추가합니다. 2열 그리드 레이아웃으로 루틴과 미션 항목을 렌더링하며, 기존 컴포넌트의 형식을 일부 수정합니다. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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: 5
🤖 Fix all issues with AI agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeChecklist.kt:
- Line 53: The RoundedCornerShape call in ChallengeChecklist's shape parameter
uses inconsistent spacing ("size= 10.dp"); update the argument to use standard
spacing ("size = 10.dp") by editing the shape = RoundedCornerShape(...)
expression (look for RoundedCornerShape and the size argument) to ensure the
code reads size = 10.dp.
In
@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineBottom.kt:
- Around line 8-15: The ChallengeRoutineBottom composable currently hardcodes
CherrishButton's onClick and enabled state; update ChallengeRoutineBottom to
accept onClick: () -> Unit and enabled: Boolean (with sensible defaults) as
parameters and pass them through to CherrishButton (retain modifier param), so
the parent can control button enablement and click handling; reference the
ChallengeRoutineBottom function and CherrishButton's enabled and onClick
parameters when making the change.
In
@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineHeader.kt:
- Around line 9-16: ChallengeRoutineHeader ignores its modifier and hardcodes
empty click handlers; update the function signature to accept and forward the
modifier and expose onBackClick and onCloseClick as parameters (e.g., fun
ChallengeRoutineHeader(modifier: Modifier = Modifier, onBackClick: () -> Unit,
onCloseClick: () -> Unit)) and then pass the received modifier and handlers into
BackAndCloseTopAppBar (replace Modifier with the incoming modifier and replace
{} with onBackClick/onCloseClick) so parent composables and the ViewModel can
supply behavior.
In
@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt:
- Around line 48-61: ChallengeRoutineCategoryChip declares a modifier parameter
but never passes it down, preventing parent composables from applying layout
modifiers; update ChallengeRoutineCategoryChip so the modifier is forwarded into
the CherrishSelectionChip call (e.g., pass modifier = modifier to
CherrishSelectionChip) while keeping the existing onClick and isSelected
behavior.
In
@app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineCategory.kt:
- Around line 3-8: The enum ChallengeRoutineCategory has a trailing space in the
BODY label and inconsistent spacing before the opening brace; remove the
trailing whitespace from the BODY label value ("체형 관리 ") and normalize the enum
declaration spacing so the brace follows the enum header consistently (look for
ChallengeRoutineCategory and the BODY entry to update).
🧹 Nitpick comments (3)
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineBottom.kt (1)
9-9: 코드 스타일 일관성 개선함수 선언부의 공백이 일관되지 않습니다. Kotlin 컨벤션에 맞게 수정하는 것을 권장합니다.
♻️ 포맷팅 수정
-fun ChallengeRoutineBottom (modifier :Modifier = Modifier){ +fun ChallengeRoutineBottom(modifier: Modifier = Modifier) {app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt (2)
25-46: 상태 호이스팅 패턴이 잘 적용되었습니다.
selectedCategory와onCategoryClick을 파라미터로 받아 stateless 컴포저블로 구현한 점이 좋습니다. 단방향 데이터 흐름 패턴을 잘 따르고 있습니다.다만, 하드코딩된 문자열(line 33)은 향후 다국어 지원을 위해
strings.xml리소스로 분리하는 것을 권장합니다.
70-86:items에key파라미터 추가를 권장합니다.
LazyVerticalGrid의items에key를 지정하면 아이템 순서 변경이나 추가/삭제 시 불필요한 recomposition을 방지할 수 있습니다.ChallengeRoutineCategory가 enum이므로 안정적인 key를 제공할 수 있습니다.♻️ 수정 제안
LazyVerticalGrid( columns = GridCells.Fixed(count = 2), horizontalArrangement = Arrangement.spacedBy(space = 12.dp), verticalArrangement = Arrangement.spacedBy(space = 12.dp), modifier = modifier ) { - items(items = categories) { category -> - + items( + items = categories, + key = { it.name } + ) { category -> ChallengeRoutineCategoryChip( category = category, isSelected = selectedCategory == category, onClick = onCategoryClick ) - } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
.kotlin/sessions/kotlin-compiler-2012687974255034637.saliveapp/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionChip.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeChecklist.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineBottom.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineHeader.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineCategory.kt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
⚙️ CodeRabbit configuration file
**/*.kt: - Jetpack Compose 구조, 상태 관리, recomposition 최적화에 집중
- ViewModel, UiState, 단방향 데이터 흐름 패턴 검토
- 불필요한 recomposition 가능성, remember/derivedStateOf 적절한 사용 확인
- 네이밍 컨벤션, 가독성, Google 권장 Android 아키텍처 준수 여부
Files:
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineHeader.ktapp/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionChip.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineBottom.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineCategory.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeChecklist.kt
🧠 Learnings (1)
📚 Learning: 2026-01-09T08:25:52.533Z
Learnt from: nhyeonii
Repo: TEAM-Cherrish/Cherrish-Android PR: 14
File: app/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelction.kt:1-1
Timestamp: 2026-01-09T08:25:52.533Z
Learning: Enforce that the Kotlin file name under the design system chip package matches the main Jetpack Compose function name defined in that file. For example, CherrishBasicChip.kt should declare a top-level composable function named CherrishBasicChip. If the file name and main composable name do not align, flag for refactor. This improves consistency and discovery across the Android codebase (TEAM-Cherrish/Cherrish-Android).
Applied to files:
app/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionChip.kt
🧬 Code graph analysis (3)
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineHeader.kt (1)
app/src/main/java/com/cherrish/android/core/designsystem/component/topappbar/BackAndCloseTopAppBar.kt (1)
BackAndCloseTopAppBar(15-46)
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineBottom.kt (1)
app/src/main/java/com/cherrish/android/core/designsystem/component/button/CherrishButton.kt (1)
CherrishButton(27-79)
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt (2)
app/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionChip.kt (1)
CherrishSelectionChip(18-42)app/src/main/java/com/cherrish/android/core/designsystem/theme/Theme.kt (1)
CherrishTheme(38-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: PR Lint Check
- GitHub Check: PR Build Check
🔇 Additional comments (3)
app/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionChip.kt (1)
44-57: LGTM!포맷팅 변경만 포함되어 있으며, 기능적 변경 없이 코드 가독성이 유지됩니다. 파일명과 주요 Composable 함수명(CherrishSelectionChip)이 일치하여 명명 규칙을 잘 준수하고 있습니다.
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeChecklist.kt (1)
46-57: 명명된 파라미터 사용 개선
RoundedCornerShape,spacedBy,mutableStateOf에 명명된 파라미터를 사용하여 코드 가독성이 향상되었습니다.Also applies to: 78-81, 103-106
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt (1)
88-117: 프리뷰 구현이 적절합니다.
CherrishTheme으로 감싸고remember+mutableStateOf를 사용하여 인터랙티브한 프리뷰를 제공하는 패턴이 잘 적용되었습니다.
| @Composable | ||
| fun ChallengeRoutineBottom (modifier :Modifier = Modifier){ | ||
| CherrishButton( | ||
| text = "다음", | ||
| onClick = {}, | ||
| modifier = modifier | ||
| ) | ||
| } |
There was a problem hiding this comment.
버튼 활성화 상태와 클릭 핸들러를 외부에서 제어할 수 있도록 파라미터를 노출해야 합니다.
PR 목표에 따르면 "선택 상태에 따라 다음 버튼이 활성화"되어야 합니다. 현재 구현에서는 enabled와 onClick이 하드코딩되어 있어 상위 컴포저블에서 버튼 상태를 제어할 수 없습니다.
CherrishButton은 enabled 파라미터를 지원하므로(관련 코드 스니펫 참조), 이를 노출하는 것이 좋습니다.
🔧 수정 제안
@Composable
-fun ChallengeRoutineBottom (modifier :Modifier = Modifier){
+fun ChallengeRoutineBottom(
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true
+) {
CherrishButton(
text = "다음",
- onClick = {},
- modifier = modifier
+ onClick = onClick,
+ modifier = modifier,
+ enabled = enabled
)
}🤖 Prompt for AI Agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineBottom.kt
around lines 8 - 15, The ChallengeRoutineBottom composable currently hardcodes
CherrishButton's onClick and enabled state; update ChallengeRoutineBottom to
accept onClick: () -> Unit and enabled: Boolean (with sensible defaults) as
parameters and pass them through to CherrishButton (retain modifier param), so
the parent can control button enablement and click handling; reference the
ChallengeRoutineBottom function and CherrishButton's enabled and onClick
parameters when making the change.
| fun ChallengeRoutineHeader(modifier: Modifier = Modifier) { | ||
| BackAndCloseTopAppBar( | ||
| title = "루틴 챌린지 선택", | ||
| onBackClick = {}, | ||
| onCloseClick = {}, | ||
| modifier = Modifier | ||
|
|
||
| ) |
There was a problem hiding this comment.
전달받은 modifier 파라미터가 사용되지 않습니다.
modifier 파라미터를 받지만, BackAndCloseTopAppBar에 새로운 Modifier를 전달하고 있습니다. 이는 상위 컴포저블에서 레이아웃 수정자를 적용할 수 없게 만듭니다. Compose의 modifier 체이닝 컨벤션을 위반합니다.
또한, onBackClick과 onCloseClick이 빈 람다로 되어 있어 실제 사용 시 상위에서 주입받아야 합니다. PR 설명에 따르면 ViewModel 통합 후 구성될 예정이므로, 이 핸들러들을 파라미터로 노출하는 것을 권장합니다.
🔧 수정 제안
@Composable
-fun ChallengeRoutineHeader(modifier: Modifier = Modifier) {
+fun ChallengeRoutineHeader(
+ onBackClick: () -> Unit,
+ onCloseClick: () -> Unit,
+ modifier: Modifier = Modifier
+) {
BackAndCloseTopAppBar(
title = "루틴 챌린지 선택",
- onBackClick = {},
- onCloseClick = {},
- modifier = Modifier
-
+ onBackClick = onBackClick,
+ onCloseClick = onCloseClick,
+ modifier = modifier
)
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fun ChallengeRoutineHeader(modifier: Modifier = Modifier) { | |
| BackAndCloseTopAppBar( | |
| title = "루틴 챌린지 선택", | |
| onBackClick = {}, | |
| onCloseClick = {}, | |
| modifier = Modifier | |
| ) | |
| @Composable | |
| fun ChallengeRoutineHeader( | |
| onBackClick: () -> Unit, | |
| onCloseClick: () -> Unit, | |
| modifier: Modifier = Modifier | |
| ) { | |
| BackAndCloseTopAppBar( | |
| title = "루틴 챌린지 선택", | |
| onBackClick = onBackClick, | |
| onCloseClick = onCloseClick, | |
| modifier = modifier | |
| ) | |
| } |
🤖 Prompt for AI Agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineHeader.kt
around lines 9 - 16, ChallengeRoutineHeader ignores its modifier and hardcodes
empty click handlers; update the function signature to accept and forward the
modifier and expose onBackClick and onCloseClick as parameters (e.g., fun
ChallengeRoutineHeader(modifier: Modifier = Modifier, onBackClick: () -> Unit,
onCloseClick: () -> Unit)) and then pass the received modifier and handlers into
BackAndCloseTopAppBar (replace Modifier with the incoming modifier and replace
{} with onBackClick/onCloseClick) so parent composables and the ViewModel can
supply behavior.
| @Composable | ||
| private fun ChallengeRoutineCategoryChip( | ||
| category: ChallengeRoutineCategory, | ||
| isSelected: Boolean, | ||
| onClick: (ChallengeRoutineCategory) -> Unit, | ||
| modifier: Modifier = Modifier | ||
| ) { | ||
| CherrishSelectionChip( | ||
| text = category.label, | ||
| onClick = { onClick(category) }, | ||
| isSelected = isSelected | ||
| ) | ||
|
|
||
| } |
There was a problem hiding this comment.
modifier 파라미터가 사용되지 않고 있습니다.
modifier 파라미터를 선언했지만 CherrishSelectionChip에 전달하지 않아 부모 컴포저블에서 레이아웃 수정자를 적용할 수 없습니다.
🔧 수정 제안
@Composable
private fun ChallengeRoutineCategoryChip(
category: ChallengeRoutineCategory,
isSelected: Boolean,
onClick: (ChallengeRoutineCategory) -> Unit,
modifier: Modifier = Modifier
) {
CherrishSelectionChip(
text = category.label,
onClick = { onClick(category) },
- isSelected = isSelected
+ isSelected = isSelected,
+ modifier = modifier
)
-
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Composable | |
| private fun ChallengeRoutineCategoryChip( | |
| category: ChallengeRoutineCategory, | |
| isSelected: Boolean, | |
| onClick: (ChallengeRoutineCategory) -> Unit, | |
| modifier: Modifier = Modifier | |
| ) { | |
| CherrishSelectionChip( | |
| text = category.label, | |
| onClick = { onClick(category) }, | |
| isSelected = isSelected | |
| ) | |
| } | |
| @Composable | |
| private fun ChallengeRoutineCategoryChip( | |
| category: ChallengeRoutineCategory, | |
| isSelected: Boolean, | |
| onClick: (ChallengeRoutineCategory) -> Unit, | |
| modifier: Modifier = Modifier | |
| ) { | |
| CherrishSelectionChip( | |
| text = category.label, | |
| onClick = { onClick(category) }, | |
| isSelected = isSelected, | |
| modifier = modifier | |
| ) | |
| } |
🤖 Prompt for AI Agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt
around lines 48 - 61, ChallengeRoutineCategoryChip declares a modifier parameter
but never passes it down, preventing parent composables from applying layout
modifiers; update ChallengeRoutineCategoryChip so the modifier is forwarded into
the CherrishSelectionChip call (e.g., pass modifier = modifier to
CherrishSelectionChip) while keeping the existing onClick and isSelected
behavior.
| enum class ChallengeRoutineCategory(val label: String){ | ||
| SKIN (label = "피부 컨디션"), | ||
| LIFE (label = "생활 습관"), | ||
| BODY (label = "체형 관리 "), | ||
| WELLNESS (label = "웰니스 ∙ 마음 챙김"), | ||
| } |
There was a problem hiding this comment.
레이블에 불필요한 공백이 포함되어 있습니다.
BODY의 레이블 "체형 관리 "에 후행 공백이 있습니다. UI에서 정렬 문제나 비교 로직에서 예상치 못한 동작을 유발할 수 있습니다. 또한 클래스 선언부에 중괄호 앞 공백을 추가하면 코드 스타일 일관성이 향상됩니다.
🔧 수정 제안
-enum class ChallengeRoutineCategory(val label: String){
- SKIN (label = "피부 컨디션"),
- LIFE (label = "생활 습관"),
- BODY (label = "체형 관리 "),
- WELLNESS (label = "웰니스 ∙ 마음 챙김"),
+enum class ChallengeRoutineCategory(val label: String) {
+ SKIN(label = "피부 컨디션"),
+ LIFE(label = "생활 습관"),
+ BODY(label = "체형 관리"),
+ WELLNESS(label = "웰니스 ∙ 마음 챙김"),
}🤖 Prompt for AI Agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineCategory.kt
around lines 3 - 8, The enum ChallengeRoutineCategory has a trailing space in
the BODY label and inconsistent spacing before the opening brace; remove the
trailing whitespace from the BODY label value ("체형 관리 ") and normalize the enum
declaration spacing so the brace follows the enum header consistently (look for
ChallengeRoutineCategory and the BODY entry to update).
There was a problem hiding this comment.
@hyeminililo 감사합니다! 😊 수정이 필요하실 때 언제든지 적용해 주시면 됩니다.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineCategory.kt:
- Line 6: Remove the trailing space from the enum label for BODY in
ChallengeRoutineCategory: locate the BODY entry (symbol: BODY) in the
ChallengeRoutineCategory enum and change its label string from "체형 관리 " to "체형
관리" so the stored/displayed label has no trailing whitespace.
🧹 Nitpick comments (1)
app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineCategory.kt (1)
3-8: 하드코딩된 문자열 대신 문자열 리소스 사용을 고려해 보세요.현재 한국어 레이블이 직접 하드코딩되어 있습니다. 향후 다국어 지원이나 유지보수를 고려한다면,
strings.xml리소스를 활용하는 것이 Android 권장 패턴입니다.단, 한국어 전용 앱으로 유지할 예정이라면 현재 구조도 무방합니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
app/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionChip.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeChecklist.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineBottom.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineCategory.kt
🚧 Files skipped from review as they are similar to previous changes (3)
- app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeChecklist.kt
- app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineBottom.kt
- app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
⚙️ CodeRabbit configuration file
**/*.kt: - Jetpack Compose 구조, 상태 관리, recomposition 최적화에 집중
- ViewModel, UiState, 단방향 데이터 흐름 패턴 검토
- 불필요한 recomposition 가능성, remember/derivedStateOf 적절한 사용 확인
- 네이밍 컨벤션, 가독성, Google 권장 Android 아키텍처 준수 여부
Files:
app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineCategory.ktapp/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionChip.kt
🧠 Learnings (1)
📚 Learning: 2026-01-09T08:25:52.533Z
Learnt from: nhyeonii
Repo: TEAM-Cherrish/Cherrish-Android PR: 14
File: app/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelction.kt:1-1
Timestamp: 2026-01-09T08:25:52.533Z
Learning: Enforce that the Kotlin file name under the design system chip package matches the main Jetpack Compose function name defined in that file. For example, CherrishBasicChip.kt should declare a top-level composable function named CherrishBasicChip. If the file name and main composable name do not align, flag for refactor. This improves consistency and discovery across the Android codebase (TEAM-Cherrish/Cherrish-Android).
Applied to files:
app/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionChip.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: PR Lint Check
- GitHub Check: PR Build Check
🔇 Additional comments (1)
app/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionChip.kt (1)
44-57: LGTM!Preview 함수에서 modifier 파라미터를 한 줄로 정리한 포맷팅 변경입니다. 컴포넌트가 stateless하게 잘 설계되어 있고, 파일명(
CherrishSelectionChip.kt)과 메인 Composable 함수명(CherrishSelectionChip)이 일치하여 컨벤션을 잘 따르고 있습니다. 학습된 내용 기반으로 확인했습니다.
ChallengeRoutinBottom 내에 있는 컴포넌트와 CherrishButton을 바로 사용하도록 리팩토링
ChallengeRoutinHeader 내에 있는 컴포넌트와 CherrishTopAppbar를 바로 사용하도록 리팩토링
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt (1)
21-26: ViewModel 미사용 및 paddingValues 미적용
ChallengeRouteViewModel이 이미 구현되어 있지만ChallengeRoute에서 사용되지 않고 있습니다. 또한paddingValues가 전달되지만ChallengeScreen에서 적용되지 않습니다.PR 설명에 따르면 단방향 데이터 흐름을 위해 ViewModel로 상태 관리를 위임한다고 했으므로, ViewModel 연동을 권장합니다.
♻️ ViewModel 연동 및 paddingValues 적용 예시
+import androidx.lifecycle.viewmodel.compose.viewModel + @Composable fun ChallengeRoute( - paddingValues: PaddingValues + paddingValues: PaddingValues, + viewModel: ChallengeRouteViewModel = viewModel() ) { - ChallengeScreen(paddingValues = paddingValues) + val selectedCategory by viewModel.selectedCategory.collectAsStateWithLifecycle() + + ChallengeScreen( + paddingValues = paddingValues, + selectedCategory = selectedCategory, + onCategoryClick = viewModel::onCategoryClick + ) }
🤖 Fix all issues with AI agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt:
- Around line 52-55: The "Next" CherrishButton isn't wired to the selection
state: make the button's enabled property depend on the selection (e.g., use
selectedCategory or selectedCategories state) so it is disabled when nothing is
selected and enabled when a selection exists; update the CherrishButton
invocation in ChallengeScreen (reference CherrishButton and
selectedCategory/selectedCategories) to pass enabled = (selectedCategory != null
/ selectedCategories.isNotEmpty()) and keep the existing onClick behavior only
when enabled (or guard the click handler by the same condition).
🧹 Nitpick comments (3)
app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeViewModel.kt (1)
8-11: 파일명과 클래스명 불일치 및asStateFlow()사용 권장파일명
ChallengeViewModel.kt와 클래스명ChallengeRouteViewModel이 일치하지 않습니다. 일관성을 위해 둘 중 하나를 수정하는 것이 좋습니다.또한,
_selectedCategory를StateFlow로 노출할 때asStateFlow()를 사용하면 실수로 캐스팅하여 수정하는 것을 방지할 수 있습니다.♻️ 권장 수정안
+import kotlinx.coroutines.flow.asStateFlow + class ChallengeRouteViewModel : ViewModel() { private val _selectedCategory = MutableStateFlow<ChallengeRoutineCategory?>(null) - val selectedCategory: StateFlow<ChallengeRoutineCategory?> = _selectedCategory + val selectedCategory: StateFlow<ChallengeRoutineCategory?> = _selectedCategory.asStateFlow()app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt (2)
33-35: 로컬 상태 대신 상태 호이스팅 패턴 적용 권장현재
ChallengeScreen내부에서 로컬 상태를 관리하고 있습니다. Stateless 컴포넌트 원칙에 따라 상태를 파라미터로 받아 처리하면 테스트 용이성과 재사용성이 향상됩니다.♻️ 상태 호이스팅 적용 예시
@Composable private fun ChallengeScreen( paddingValues: PaddingValues, + selectedCategory: ChallengeRoutineCategory?, + onCategoryClick: (ChallengeRoutineCategory) -> Unit, modifier: Modifier = Modifier ) { - var selectedCategory by remember { - mutableStateOf<ChallengeRoutineCategory?>(value = null) - }
59-63: Preview에 테마 래퍼 추가 권장
CherrishTheme으로 감싸지 않으면 Preview에서 커스텀 테마 색상과 타이포그래피가 적용되지 않을 수 있습니다.♻️ 테마 래퍼 추가
@Preview @Composable private fun ChallengeScreenPreview() { - ChallengeScreen(paddingValues = PaddingValues(26.dp)) + CherrishTheme { + ChallengeScreen(paddingValues = PaddingValues(26.dp)) + } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.ktapp/src/main/java/com/cherrish/android/presentation/challenge/ChallengeViewModel.kt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
⚙️ CodeRabbit configuration file
**/*.kt: - Jetpack Compose 구조, 상태 관리, recomposition 최적화에 집중
- ViewModel, UiState, 단방향 데이터 흐름 패턴 검토
- 불필요한 recomposition 가능성, remember/derivedStateOf 적절한 사용 확인
- 네이밍 컨벤션, 가독성, Google 권장 Android 아키텍처 준수 여부
Files:
app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeViewModel.ktapp/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt (3)
app/src/main/java/com/cherrish/android/core/designsystem/component/topappbar/CherrishBasicTopAppBar.kt (1)
CherrishBasicTopAppBar(17-54)app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt (1)
ChallengeRoutineOnboardingBody(24-45)app/src/main/java/com/cherrish/android/core/designsystem/component/button/CherrishButton.kt (1)
CherrishButton(27-79)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: PR Build Check
- GitHub Check: PR Lint Check
🔇 Additional comments (1)
app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeViewModel.kt (1)
13-15: 토글 선택 해제 기능 고려현재 동일한 카테고리를 다시 클릭해도 선택이 해제되지 않습니다. UX 요구사항에 따라 선택 해제 기능이 필요할 수 있습니다.
선택 해제 기능이 필요하다면 다음과 같이 수정할 수 있습니다:
♻️ 토글 기능 추가 예시
fun onCategoryClick(category: ChallengeRoutineCategory) { - _selectedCategory.value = category + _selectedCategory.value = if (_selectedCategory.value == category) null else category }
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt:
- Around line 52-55: The Next button in ChallengeScreen is not tied to the
selection state; update the CherrishButton call so its enabled parameter
reflects the current selection (e.g., use selectedCategory or whatever selection
state variable is used in ChallengeScreen), e.g., enabled = selectedCategory !=
null (or selectedCategory.isNotEmpty() for strings, or
selectedItems.isNotEmpty() for collections) and keep the existing onClick logic;
ensure you reference the selectedCategory state variable in ChallengeScreen to
drive the button enabled/disabled state.
- Around line 30-39: The ChallengeScreen composable currently ignores the
paddingValues parameter causing layout overlap with system bars; update the root
container Modifier (the Column using modifier) to incorporate paddingValues
(e.g., combine or chain the existing .padding(start = 26.dp, bottom = 64.dp, end
= 26.dp) with paddingValues) so the incoming Scaffold inner padding is applied;
locate the ChallengeScreen function and modify the Column's modifier (and any
parent modifier passed in) to include paddingValues before/alongside the
existing paddings.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineCategory.kt
🚧 Files skipped from review as they are similar to previous changes (1)
- app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineCategory.kt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
⚙️ CodeRabbit configuration file
**/*.kt: - Jetpack Compose 구조, 상태 관리, recomposition 최적화에 집중
- ViewModel, UiState, 단방향 데이터 흐름 패턴 검토
- 불필요한 recomposition 가능성, remember/derivedStateOf 적절한 사용 확인
- 네이밍 컨벤션, 가독성, Google 권장 Android 아키텍처 준수 여부
Files:
app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt (3)
app/src/main/java/com/cherrish/android/core/designsystem/component/topappbar/CherrishBasicTopAppBar.kt (1)
CherrishBasicTopAppBar(17-54)app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt (1)
ChallengeRoutineOnboardingBody(24-45)app/src/main/java/com/cherrish/android/core/designsystem/component/button/CherrishButton.kt (1)
CherrishButton(27-79)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: PR Build Check
- GitHub Check: PR Lint Check
🔇 Additional comments (1)
app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt (1)
59-63: Preview 구현 확인Preview 함수가 추가되어 컴포넌트를 시각적으로 확인할 수 있습니다. 위의
paddingValues적용 문제가 수정되면 Preview도 정상적으로 동작할 것입니다.
| paddingValues: PaddingValues, | ||
| modifier: Modifier = Modifier | ||
| ) { | ||
| Text( | ||
| "Challenge", | ||
| modifier = modifier.padding(paddingValues) | ||
| ) | ||
| var selectedCategory by remember { | ||
| mutableStateOf<ChallengeRoutineCategory?>(value = null) | ||
| } | ||
|
|
||
| Column( | ||
| modifier = modifier | ||
| .padding(start = 26.dp, bottom = 64.dp, end = 26.dp) |
There was a problem hiding this comment.
paddingValues 파라미터가 사용되지 않음
paddingValues가 함수 파라미터로 전달되지만 실제로 적용되지 않고 있습니다. Scaffold와 함께 사용될 때 시스템 바(상태바, 네비게이션 바)와의 레이아웃 충돌이 발생할 수 있습니다.
🐛 paddingValues 적용 수정 제안
@Composable
private fun ChallengeScreen(
paddingValues: PaddingValues,
modifier: Modifier = Modifier
) {
var selectedCategory by remember {
mutableStateOf<ChallengeRoutineCategory?>(value = null)
}
Column(
modifier = modifier
+ .padding(paddingValues)
.padding(start = 26.dp, bottom = 64.dp, end = 26.dp)
) {🤖 Prompt for AI Agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt
around lines 30 - 39, The ChallengeScreen composable currently ignores the
paddingValues parameter causing layout overlap with system bars; update the root
container Modifier (the Column using modifier) to incorporate paddingValues
(e.g., combine or chain the existing .padding(start = 26.dp, bottom = 64.dp, end
= 26.dp) with paddingValues) so the incoming Scaffold inner padding is applied;
locate the ChallengeScreen function and modify the Column's modifier (and any
parent modifier passed in) to include paddingValues before/alongside the
existing paddings.
There was a problem hiding this comment.
이거 #27 요기 pr에도 질문 나왓던거죠 ~~ !! 래빗이도 잘 짚어줫네요 ㅎㅎㅎ 반영해서 수정해주세요 ~~
There was a problem hiding this comment.
@nhyeonii 감사합니다! 네, 동일한 이슈가 이전 PR에서도 발견되었군요. paddingValues를 적용하지 않으면 Scaffold의 시스템 바와 겹칠 수 있으니 꼭 반영이 필요합니다.
제안드린 대로 Column의 modifier에 .padding(paddingValues)를 먼저 추가하고, 그 다음에 추가 패딩을 적용하면 됩니다. 🙂
✏️ Learnings added
Learnt from: nhyeonii
Repo: TEAM-Cherrish/Cherrish-Android PR: 41
File: app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt:30-39
Timestamp: 2026-01-12T19:49:27.085Z
Learning: In the Cherrish-Android codebase, Screen composables that receive a `paddingValues: PaddingValues` parameter from Scaffold must apply it to their root container's modifier (e.g., `.padding(paddingValues)`) before applying additional padding, to avoid layout overlap with system bars.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
| CherrishButton( | ||
| text = "다음", | ||
| onClick = {} | ||
| ) |
There was a problem hiding this comment.
버튼 활성화 상태가 선택 상태와 연동되지 않음
PR 목표에 "다음 버튼이 선택 상태에 따라 활성화될 수 있도록 구조 설계"라고 명시되어 있습니다. CherrishButton의 enabled 파라미터를 selectedCategory에 따라 설정해야 합니다.
🐛 버튼 활성화 로직 추가 제안
CherrishButton(
text = "다음",
- onClick = {}
+ onClick = {},
+ enabled = selectedCategory != null
)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CherrishButton( | |
| text = "다음", | |
| onClick = {} | |
| ) | |
| CherrishButton( | |
| text = "다음", | |
| onClick = {}, | |
| enabled = selectedCategory != null | |
| ) |
🤖 Prompt for AI Agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt
around lines 52 - 55, The Next button in ChallengeScreen is not tied to the
selection state; update the CherrishButton call so its enabled parameter
reflects the current selection (e.g., use selectedCategory or whatever selection
state variable is used in ChallengeScreen), e.g., enabled = selectedCategory !=
null (or selectedCategory.isNotEmpty() for strings, or
selectedItems.isNotEmpty() for collections) and keep the existing onClick logic;
ensure you reference the selectedCategory state variable in ChallengeScreen to
drive the button enabled/disabled state.
nhyeonii
left a comment
There was a problem hiding this comment.
직접 이야기하면서 나누어보앗던 얘기들 기억하면서 리팩토링 해보면 참 좋을 거 가트요 ㅎㅎㅎ 너무 잘해주고 잇고 질문도 열심히 해주는 모습 기특합니다 🫳🫳🫳🫳 좀만 더 화이팅 ~ !!!!
| "Challenge", | ||
| modifier = modifier.padding(paddingValues) | ||
| ) | ||
| var selectedCategory by remember { |
There was a problem hiding this comment.
P1 : 이거 UiState로 상태관리 올려주세용옹 ~~ 이렇게 스크린에 작성해주면 요 선택된 아이들의 관리가 힘들답니다 ㅎㅎㅎ
There was a problem hiding this comment.
넵넵 기반으로 리팩토링 진행해보도록 하겠습니다 ~!!
| paddingValues: PaddingValues, | ||
| modifier: Modifier = Modifier | ||
| ) { | ||
| Text( | ||
| "Challenge", | ||
| modifier = modifier.padding(paddingValues) | ||
| ) | ||
| var selectedCategory by remember { | ||
| mutableStateOf<ChallengeRoutineCategory?>(value = null) | ||
| } | ||
|
|
||
| Column( | ||
| modifier = modifier | ||
| .padding(start = 26.dp, bottom = 64.dp, end = 26.dp) |
There was a problem hiding this comment.
이거 #27 요기 pr에도 질문 나왓던거죠 ~~ !! 래빗이도 잘 짚어줫네요 ㅎㅎㅎ 반영해서 수정해주세요 ~~
|
|
||
| ChallengeRoutineOnboardingBody( | ||
| selectedCategory = selectedCategory, | ||
| onCategoryClick = { selectedCategory = it } |
There was a problem hiding this comment.
P1 : 얘도 상태 호이스팅 필요하겟죠잉 ?!
There was a problem hiding this comment.
넵 끌어올리겠습니당 ~~!!
There was a problem hiding this comment.
오호.. 스크린 구현할 때 상태 호이스팅에 유의해야겟군요? ㅎ호호이
|
|
||
| CherrishButton( | ||
| text = "다음", | ||
| onClick = {} |
There was a problem hiding this comment.
P1 : onClick 상태 호이스팅 해주세요 ~~ 그리고 버튼이 활성화 되는 시기가 언제인지도 처리해줘야하겟죵 !?
There was a problem hiding this comment.
앗 네네 !! 리팩토링 진행할게요 !!
| SKIN(label = "피부 컨디션"), | ||
| LIFE(label = "생활 습관"), | ||
| BODY(label = "체형 관리"), | ||
| WELLNESS(label = "웰니스 ∙ 마음 챙김") |
There was a problem hiding this comment.
좋습니당 !!! 서버 API 꼭 확인하겠습니다아 ,,, 🤭
| onCategoryClick: (ChallengeRoutineCategory) -> Unit, | ||
| modifier: Modifier = Modifier | ||
| ) { | ||
| Column(modifier = modifier) { |
There was a problem hiding this comment.
P1 : 요거 .fillMaxWidth() 속성 줘야할거 가트요 ~~
| Text( | ||
| text = "지금 나에게 가장 필요한 \n관리 루틴을 선택해주세요.", | ||
| color = CherrishTheme.colors.gray1000, | ||
| style = CherrishTheme.typography.title1SB18 | ||
| ) | ||
|
|
||
| Spacer(modifier = Modifier.height(height = 40.dp)) | ||
|
|
||
| ChallengeRoutineSelectionChipGroup( | ||
| categories = ChallengeRoutineCategory.entries, | ||
| selectedCategory = selectedCategory, | ||
| onCategoryClick = onCategoryClick | ||
| ) | ||
| } |
There was a problem hiding this comment.
오 좋을 것 같아요 ~!~~!!@
|
|
||
| @Composable | ||
| private fun ChallengeRoutineSelectionChipGroup( | ||
| categories: List<ChallengeRoutineCategory>, |
There was a problem hiding this comment.
| categories: List<ChallengeRoutineCategory>, | |
| categories: immutableList<ChallengeRoutineCategory>, |
P1 : 요거 List 보다는 immutableList 사용해주세요!! immutableLIst의 장점은 무엇일까용ㅇ이 ~?!!?!
There was a problem hiding this comment.
immutableList는 한 번 정하면 값이 변하지 않는 불변 값이니 타입 안정성이 보장된다 ,,! ! 그리고 리소스를 보장할 수 있다가 맞을까요 ??
| verticalArrangement = Arrangement.spacedBy(space = 12.dp), | ||
| modifier = modifier | ||
| ) { | ||
| items(items = categories) { category -> |
There was a problem hiding this comment.
P1 : key 값 지정해주는거 어떨까용 ?!?!?
|
|
||
| ChallengeRoutineOnboardingBody( | ||
| selectedCategory = selectedCategory, | ||
| onCategoryClick = { selectedCategory = it } |
There was a problem hiding this comment.
오호.. 스크린 구현할 때 상태 호이스팅에 유의해야겟군요? ㅎ호호이
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt:
- Around line 119-127: The compile error comes from calling item.copy(...) on
ChallengeRoutineItem (an interface) inside the ChallengeRoutineOnboardingBody
onItemClick handler; replace that call with a polymorphic copy method on the
interface (e.g., add fun copyWithSelection(isSelected: Boolean):
ChallengeRoutineItem to the ChallengeRoutineItem interface and implement it in
concrete classes) and then update the mapping to use
item.copyWithSelection(item.id == clickedItem.id); alternatively, if all items
are concrete data classes, cast to the concrete type before using copy, but the
preferred fix is to add and call copyWithSelection on ChallengeRoutineItem and
implement it in the implementations.
🧹 Nitpick comments (4)
app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineItem.kt (1)
3-8: 인터페이스 설계가 적절합니다.다형성을 활용한
ChallengeRoutineItem인터페이스 설계가 잘 되어 있습니다.ChallengeRoutineModel과ChallengeRoutineMissionModel이 공통 인터페이스를 구현하여ChallengeRoutineOnboardingBody에서 유연하게 처리할 수 있습니다.선택 사항:
category타입을String대신ChallengeRoutineCategoryenum으로 변경하면 타입 안전성을 높일 수 있습니다.♻️ 타입 안전성 개선 제안
+import com.cherrish.android.presentation.challenge.model.ChallengeRoutineCategory + interface ChallengeRoutineItem { val id : Int val title : String - val category: String + val category: ChallengeRoutineCategory val isSelected: Boolean }app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineMissionModel.kt (1)
3-9: 들여쓰기가 일관되지 않습니다.
subTitle프로퍼티의 들여쓰기가 다른 프로퍼티들과 일치하지 않습니다.♻️ 들여쓰기 수정
data class ChallengeRoutineMissionModel( - override val id: Int, - override val title : String, - val subTitle: String, - override val category : String, - override val isSelected: Boolean = false + override val id: Int, + override val title: String, + val subTitle: String, + override val category: String, + override val isSelected: Boolean = false ) : ChallengeRoutineItemapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt (2)
51-70:when표현식에else분기 누락새로운
ChallengeRoutineItem구현체가 추가될 경우를 대비해else분기를 추가하는 것이 좋습니다. 또한ChallengeRoutineMissionModel의subTitle이 UI에 표시되지 않습니다.♻️ else 분기 및 subTitle 활용 제안
items(items) { item -> when (item) { is ChallengeRoutineModel -> { CherrishSelectionChip( text = item.title, isSelected = item.isSelected, onClick = { onItemClick(item) } ) } is ChallengeRoutineMissionModel -> { CherrishMissionCard( - text = item.title, + text = "${item.subTitle}\n${item.title}", isSelected = item.isSelected, onClick = { onItemClick(item) } ) } + + else -> { + // 알 수 없는 아이템 타입 처리 + } } }
45-51:items()에key파라미터 추가 권장리스트 아이템 변경 시 효율적인 recomposition을 위해
key파라미터를 추가하세요. 코딩 가이드라인에서 불필요한 recomposition 최적화를 권장합니다.♻️ key 파라미터 추가
LazyVerticalGrid( columns = GridCells.Fixed(2), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(12.dp), modifier = Modifier.fillMaxHeight() ) { - items(items) { item -> + items(items, key = { it.id }) { item -> when (item) {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.kotlin/sessions/kotlin-compiler-2276212971756165281.saliveapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineItem.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineMissionModel.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineModel.kt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
⚙️ CodeRabbit configuration file
**/*.kt: - Jetpack Compose 구조, 상태 관리, recomposition 최적화에 집중
- ViewModel, UiState, 단방향 데이터 흐름 패턴 검토
- 불필요한 recomposition 가능성, remember/derivedStateOf 적절한 사용 확인
- 네이밍 컨벤션, 가독성, Google 권장 Android 아키텍처 준수 여부
Files:
app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineModel.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineItem.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineMissionModel.kt
🧠 Learnings (1)
📚 Learning: 2026-01-12T19:49:27.085Z
Learnt from: nhyeonii
Repo: TEAM-Cherrish/Cherrish-Android PR: 41
File: app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt:30-39
Timestamp: 2026-01-12T19:49:27.085Z
Learning: When a Jetpack Compose screen composable receives a Scaffold paddingValues: PaddingValues parameter (commonly from Scaffold), apply it to the root container's modifier first (e.g., .padding(paddingValues)) before applying any additional padding. This ensures content respects system bars (status/navigation) and avoids layout overlap. This pattern should be followed across presentation screens under app/src/main/java/com/cherrish/android/presentation/ to maintain consistent insets handling.
Applied to files:
app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineModel.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineItem.ktapp/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.ktapp/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineMissionModel.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt (3)
app/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionChip.kt (1)
CherrishSelectionChip(18-42)app/src/main/java/com/cherrish/android/core/designsystem/component/chip/CherrishSelectionMissionChip.kt (1)
CherrishMissionCard(27-70)app/src/main/java/com/cherrish/android/core/designsystem/theme/Theme.kt (1)
CherrishTheme(38-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: PR Lint Check
- GitHub Check: PR Build Check
🔇 Additional comments (2)
app/src/main/java/com/cherrish/android/presentation/challenge/model/ChallengeRoutineModel.kt (1)
3-8: LGTM!
data class구현이 적절하며,copy()함수를 통해 Compose에서 불변 상태 업데이트가 가능합니다.isSelected의 기본값 설정도 적절합니다.app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt (1)
30-35: Stateless 컴포넌트 설계가 좋습니다.PR 설명에 언급된 대로 컴포넌트가 상태를 직접 관리하지 않고
items와onItemClick을 통해 외부에서 상태를 제어할 수 있도록 설계되어 있습니다. 단방향 데이터 흐름 패턴을 잘 따르고 있습니다.
| ChallengeRoutineOnboardingBody( | ||
| items = routineItems, | ||
| onItemClick = { clickedItem -> | ||
| routineItems = routineItems.map { item -> | ||
| item.copy( | ||
| isSelected = item.id == clickedItem.id | ||
| ) | ||
| } | ||
| }, |
There was a problem hiding this comment.
컴파일 오류: ChallengeRoutineItem 인터페이스에서 copy() 호출 불가
ChallengeRoutineItem은 인터페이스이므로 copy() 메서드가 없습니다. Preview에서 item.copy()를 호출하면 컴파일 오류가 발생합니다.
🐛 수정 제안
ChallengeRoutineOnboardingBody(
items = routineItems,
onItemClick = { clickedItem ->
routineItems = routineItems.map { item ->
- item.copy(
- isSelected = item.id == clickedItem.id
- )
+ if (item is ChallengeRoutineModel) {
+ item.copy(isSelected = item.id == clickedItem.id)
+ } else {
+ item
+ }
}
},
modifier = Modifier.padding(26.dp)
)또는 ChallengeRoutineItem 인터페이스에 copyWithSelection 메서드를 추가하는 방법도 있습니다:
interface ChallengeRoutineItem {
// ... existing properties
fun copyWithSelection(isSelected: Boolean): ChallengeRoutineItem
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ChallengeRoutineOnboardingBody( | |
| items = routineItems, | |
| onItemClick = { clickedItem -> | |
| routineItems = routineItems.map { item -> | |
| item.copy( | |
| isSelected = item.id == clickedItem.id | |
| ) | |
| } | |
| }, | |
| ChallengeRoutineOnboardingBody( | |
| items = routineItems, | |
| onItemClick = { clickedItem -> | |
| routineItems = routineItems.map { item -> | |
| if (item is ChallengeRoutineModel) { | |
| item.copy(isSelected = item.id == clickedItem.id) | |
| } else { | |
| item | |
| } | |
| } | |
| }, |
🤖 Prompt for AI Agents
In
@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt
around lines 119 - 127, The compile error comes from calling item.copy(...) on
ChallengeRoutineItem (an interface) inside the ChallengeRoutineOnboardingBody
onItemClick handler; replace that call with a polymorphic copy method on the
interface (e.g., add fun copyWithSelection(isSelected: Boolean):
ChallengeRoutineItem to the ChallengeRoutineItem interface and implement it in
concrete classes) and then update the mapping to use
item.copyWithSelection(item.id == clickedItem.id); alternatively, if all items
are concrete data classes, cast to the concrete type before using copy, but the
preferred fix is to add and call copyWithSelection on ChallengeRoutineItem and
implement it in the implementations.



Related issue 🛠
Work Description ✏️
Screenshot 📸
Uncompleted Tasks 😅
To Reviewers 📢
ViewModel은 컴포넌트 PR 완료 후, 조립과 함께 ViewModel을 같이 구현할 예정입니당 3개의 컴폰넌트 모두 다 프리뷰 있으니까, 편히 봐주세용 !! 피드백도 조하요 ~~ ! !
Summary by CodeRabbit
릴리스 노트
새로운 기능
스타일
✏️ Tip: You can customize this high-level summary in your review settings.