Skip to content

[FEAT/#73] 챌린지 미션 프로그래스 바 컴포넌트 구현 #75

Merged
hyeminililo merged 45 commits intodevelopfrom
feat/#73-challenge-missionprogress-component
Jan 18, 2026
Merged

[FEAT/#73] 챌린지 미션 프로그래스 바 컴포넌트 구현 #75
hyeminililo merged 45 commits intodevelopfrom
feat/#73-challenge-missionprogress-component

Conversation

@hyeminililo
Copy link
Copy Markdown
Contributor

@hyeminililo hyeminililo commented Jan 16, 2026

Related issue 🛠

Work Description ✏️

  • 현재 본인 상태에 따라 다른 피부 상태 및 체리 분기처리 구현
  • 정해진 날짜의 Todo 미션 리스트 나오도록 구현
  • 그라데이션 적용
  • 버튼 활성화/비활성화 적용
  • ktLint 실행

Screenshot 📸

- Todo
https://github.com/user-attachments/assets/e125b1bd-24e0-41a5-82a2-b69e8db199cb

- 체리
https://github.com/user-attachments/assets/7340f89b-80d2-45d6-a7cc-32f955649abd

Uncompleted Tasks 😅

N/A

To Reviewers 📢

uiState와 model을 이용해서 구현했습니다! 뷰모델은 컴포넌트를 조립할 때 viewModel을 구현하려고 합니다!! 피드백해주세용 ,,~~~ 제가 놓친 패딩 부분이 있다면 ,,,,,, 바로 수정하겠습니다아,,,

Summary by CodeRabbit

  • 새로운 기능

    • 체리 성장 진행 카드 추가 — 레벨·단계 비주얼, 남은 루틴 안내와 달성률 게이지 제공
    • 일일 TO-DO 섹션 추가 — 루틴 체크리스트와 항목 터치, “오늘 미션 종료하기” 버튼 제공
    • 미션 온보딩 및 루틴 선택 UI 추가 — 카드·셀렉션 그리드로 미션/루틴 선택 지원
  • 내부(데이터)

    • 미션/루틴 관련 UI 상태와 모델 추가로 화면 데이터 표현 지원
  • Style

    • 게이지·체리 이미지 리소스 및 기본 챌린지 이미지 변경(시각적 업데이트)

✏️ Tip: You can customize this high-level summary in your review settings.

@hyeminililo hyeminililo self-assigned this Jan 16, 2026
@hyeminililo hyeminililo requested a review from a team as a code owner January 16, 2026 20:16
@hyeminililo hyeminililo added FEAT✨ 새로운 기능 구현 혜민🍒 혜민 담당 labels Jan 16, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 16, 2026

Walkthrough

챌린지 관련 여러 Compose UI 컴포저블(체리 성장 프로그레스, TO‑DO 섹션, 온보딩/루틴 선택)과 이를 지원하는 UI 상태·열거형·데이터 모델들이 추가되었고, 일부 디자인시스템 게이지 이미지 기본 참조가 업데이트되었습니다.

Changes

코호트 / 파일(s) 변경 요약
UI 컴포넌트 — 프로그레스 / TO‑DO
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionProgressCherrygrowth.kt, app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt
새 Compose 컴포저블 2종 추가. ChallengeMissionProgressCherrygrowth(체리 성장 카드, 서브컴포저블·Preview 포함). ChallengeMissionTodoSection(일일 루틴 목록, 항목 클릭 콜백, 완료 버튼, 내부 리스트/제목 컴포저블·Preview 포함).
온보딩 / 루틴 선택 UI
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionOnboardingBody.kt, app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt
온보딩용 컴포저블 2종 추가: 미션 카드 목록 및 루틴 그리드 선택 UI(각각 Preview 포함, 클릭 콜백 수신).
UI 상태 / 열거형
app/src/main/java/com/cherrish/android/presentation/challenge/missionprogress/ChallengeMissionProgressUiState.kt, app/src/main/java/com/cherrish/android/presentation/challenge/missionprogress/CherryType.kt, app/src/main/java/com/cherrish/android/presentation/challenge/mission/ChallengeMissionUiState.kt, app/src/main/java/com/cherrish/android/presentation/challenge/routine/ChallengeRoutineUiState.kt
새 데이터형/열거형 추가: ChallengeMissionProgressUiState(challenge, currentDay, cherryType, remainingCount, routines), CherryType enum(4종, step/level/stageName/imageRes), ChallengeMissionUiState(missions 리스트), ChallengeRoutineUiState(routine/isSelected 및 FakeRoutine).
데이터 모델
app/src/main/java/com/cherrish/android/presentation/challenge/mission/model/ChallengeMissionModel.kt, app/src/main/java/com/cherrish/android/presentation/challenge/missionprogress/model/ChallengeInfoModel.kt, app/src/main/java/com/cherrish/android/presentation/challenge/missionprogress/model/DailyTodoRoutineModel.kt, app/src/main/java/com/cherrish/android/presentation/challenge/routine/model/ChallengeRoutineModel.kt
불변 데이터 클래스 추가: ChallengeMissionModel(id, missionContent, isSelected), ChallengeInfoModel(id, challengeTitle, challengeTotalDays), DailyTodoRoutineModel(id, routine, isCompleted), ChallengeRoutineModel(id, routine, isSelected).
디자인시스템 및 홈 섹션 변경
app/src/main/java/com/cherrish/android/core/designsystem/component/type/CherrishGaugeType.kt, app/src/main/java/com/cherrish/android/presentation/home/component/ChallengeSection.kt
게이지 타입의 drawable 참조를 img_lvNimg_challenge_lvN로 교체. ChallengeSection 기본 imageRes 기본값을 R.drawable.img_challenge_lv2로 변경.
사소한 UI 조정 / 프리뷰 수정
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionCardChip.kt, ...
Chip 내부 간격 조정(6.dp → 8.dp) 및 Preview 상태 변수명 변경 등 경미한 UI/프리뷰 수정.

Sequence Diagram(s)

(생성 조건 미충족 — 변경은 주로 UI 컴포저블 및 데이터 모델 추가로, 다중 컴포넌트 연속 흐름 시각화가 필요하지 않음)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • sohee6989
  • usuuhyn
🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 PR의 주요 변경사항인 챌린지 미션 프로그래스 바 컴포넌트 구현을 명확하게 반영하고 있습니다.
Description check ✅ Passed PR 설명이 템플릿 구조를 따르고 있으며, 관련 이슈, 작업 내용, 스크린샷, 검토자 피드백이 포함되어 있습니다.
Linked Issues check ✅ Passed PR에서 구현한 변경사항들이 이슈 #73의 모든 주요 요구사항(체리 성장 프로그래스 컴포넌트, 체리 Todo 컴포넌트, 그라데이션 적용, 성장에 따른 체리 분기 처리, ktLint 실행)을 충족합니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 이슈 #73의 범위 내에 있으며, 챌린지 미션 프로그래스 컴포넌트 구현 관련 파일들만 포함되어 있습니다.

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

✨ Finishing touches
  • 📝 Generate docstrings

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: 2

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt`:
- Line 53: ChallengeMissionTodoSection의 onRoutineClick 파라미터 타입이 Int로 선언되어 있는데
DailyTodoRoutineModel.id가 Long이므로 시그니처 및 모든 호출부를 Long으로 변경해야 합니다;
ChallengeMissionTodoSection 컴포저블 선언부의 onRoutineClick: (Int) -> Unit을
onRoutineClick: (Long) -> Unit으로 바꾸고, 해당 콜백을 전달하는 곳/람다(예: 호출자에서 routine.id를 넘기는
코드)들도 Int가 아닌 Long을 받도록 수정하여 타입 불일치를 제거하세요.
- Line 43: The code is converting item.id (a Long) to Int via item.id.toInt()
when invoking onRoutineClick, risking data loss; update the onRoutineClick
callback signature to accept a Long instead of Int and pass item.id directly
(i.e., remove .toInt()), then update any implementations/usages of
onRoutineClick to accept Long as well so types remain consistent across
ChallengeMissionTodoSection, the onChecklistClick mapping, and all callers.
🧹 Nitpick comments (7)
app/src/main/java/com/cherrish/android/presentation/challenge/missionprogress/CherryType.kt (2)

6-12: steplevel 속성이 중복됩니다.

현재 모든 enum 상수에서 steplevel 값이 동일합니다. 향후 다르게 사용될 계획이 아니라면 하나로 통합하는 것을 고려해 주세요.

또한, enum은 본질적으로 불변이므로 @Immutable 어노테이션은 선택적입니다. 유지해도 무방하지만 참고 사항입니다.


5-6: 코드 포맷팅: import와 어노테이션 사이에 빈 줄 추가를 권장합니다.

가독성을 위해 import 문과 클래스 선언 사이에 빈 줄을 추가하는 것이 좋습니다.

🔧 제안된 수정
 import com.cherrish.android.R
+
 `@Immutable`
 enum class CherryType(
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionProgressCherrygrowth.kt (3)

85-85: 파일명과 함수명의 대소문자 일관성을 확인하세요.

파일명 ChallengeMissionProgressCherrygrowth.kt에서 "Cherrygrowth"의 대소문자가 일반적인 CamelCase 컨벤션(CherryGrowth)과 다릅니다. 프로젝트 학습 내용에 따르면 파일명과 메인 컴포저블 함수명이 일치해야 합니다.

ChallengeMissionProgressCherryGrowth로 통일하는 것을 권장합니다.


91-91: 불필요한 recomposition 방지를 위해 remember 사용을 권장합니다.

colors 리스트가 매 recomposition마다 새로 생성됩니다. remember로 감싸서 불필요한 객체 생성을 방지하세요.

♻️ 제안된 수정
-    val colors = listOf(CherrishTheme.colors.red200, CherrishTheme.colors.gray0)
+    val colors = remember { listOf(CherrishTheme.colors.red200, CherrishTheme.colors.gray0) }

CherrishTheme.colors가 CompositionLocal로 제공되어 테마 변경 시 업데이트가 필요한 경우, remember 대신 현재 구현을 유지하거나 키를 사용해야 할 수 있습니다.


107-111: 그라데이션 종료 오프셋이 하드코딩되어 있습니다.

end = Offset(x = 0f, y = 230f)가 고정값으로 설정되어 있어, 컨텐츠 높이가 달라질 경우 그라데이션이 의도대로 표시되지 않을 수 있습니다. 동적 높이 계산 또는 비율 기반 그라데이션(Brush.verticalGradient)을 고려해 주세요.

app/src/main/java/com/cherrish/android/presentation/challenge/missionprogress/ChallengeMissionProgressUiState.kt (1)

7-14: routines 필드에 ImmutableList 사용을 권장합니다.

@Immutable 어노테이션이 클래스 전체를 안정적으로 표시하지만, List<DailyTodoRoutineModel>은 가변 컬렉션입니다. Compose 최적화를 위해 kotlinx.collections.immutable.ImmutableList를 사용하면 더 명확한 불변성 보장이 가능합니다.

현재 구현도 동작하지만, 다른 파일(ChallengeMissionProgressCherrygrowth.kt)에서 이미 kotlinx.collections.immutable을 사용하고 있으므로 일관성을 위해 권장드립니다.

♻️ 제안된 수정
 import androidx.compose.runtime.Immutable
 import com.cherrish.android.presentation.challenge.missionprogress.model.ChallengeInfoModel
 import com.cherrish.android.presentation.challenge.missionprogress.model.DailyTodoRoutineModel
+import kotlinx.collections.immutable.ImmutableList

 `@Immutable`
 data class ChallengeMissionProgressUiState(
     val challenge: ChallengeInfoModel,
     val currentDay: Int,
     val cherryType: CherryType,
     val remainingCount: Int,
-    val routines: List<DailyTodoRoutineModel>
+    val routines: ImmutableList<DailyTodoRoutineModel>
 )
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt (1)

66-72: modifier 체인 내 불필요한 빈 줄이 있습니다.

코드 포맷팅을 위해 modifier 체인 내의 빈 줄을 제거하는 것이 좋습니다.

🔧 제안된 수정
             .dropShadow(
                 shape = RoundedCornerShape(size = 10.dp),
                 blur = 10.dp,
                 offsetX = 0.dp,
                 offsetY = 0.dp,
                 spread = 0.dp,
                 color = CherrishTheme.colors.shadow
-
             )
             .clip(shape = RoundedCornerShape(size = 10.dp))
             .background(color = CherrishTheme.colors.gray0)
             .padding(all = 18.dp)
-
     ) {

Copy link
Copy Markdown
Contributor

@sohee6989 sohee6989 left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!!

val currentDay: Int,
val cherryType: CherryType,
val remainingCount: Int,
val routines: List<DailyTodoRoutineModel>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p1: immutableList?!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

로 변경할게요오 ~!!

@Immutable
data class DailyTodoRoutineModel(
val id: Long,
val name: String,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p3: 이거 변수명 name 대신 routine 이렇게 좀 더 관련된거 어떠신가요?!
name으로 하면 변수명만 보고 뭐인지 바로 알기 어려워서요..!!ㅎㅎ

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

넵 알겠습니다아 ! 좋아요

Comment on lines +8 to +9
val title: String,
val totalDays: Int
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p3: 이런것도 파라미터명을 challengeTitle, challengeTotalDays 이런 식으로 작성하시느거 어떠신가요?!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

넵 이것도 반영하겠습니다 ~!


@Composable
private fun ChallengeMissionTodoList(
routines: List<DailyTodoRoutineModel>,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p1: immutableList?!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

넵넵 얘두 반영할게용 !!


@Composable
fun ChallengeMissionTodoSection(
uiState: ChallengeMissionProgressUiState,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p1: ChallengeMissionProgressUiState는 화면 단 상태라 Screen까지만 전달하고
하위 Section에는 currentDay, routines처럼 필요한 값만 내려주는 형태가 컴포넌트 결합도를 낮추고 재사용/테스트/프리뷰 측면에서도 더 적합해 보입니다!ㅎㅎ

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

오 좋아요 !! 감사합니다 ~!!

import kotlinx.collections.immutable.toImmutableList

@Composable
private fun CherryGrowthSection(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p1: Lv0. OO체리 이 부분 뒤에 배경을 한 번더 설정한 것 같아서 체크해주셔야 될 것 같습니다!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

넵 color가 두 개 적용된 것 말하시는 것 맞죠 ??

.background(CherrishTheme.colors.gray0)
.background(
brush = Brush.linearGradient(
colors = colors, // red200 -> gray0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p2: 주석 지워주자요오~~

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

허거덩 네네 ~~!!

text = "체리가 크려면 ${remainingRoutines}개의 미션을 수행해야 해요!",
color = CherrishTheme.colors.gray800,
style = CherrishTheme.typography.body2R13,
textAlign = TextAlign.Center
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p2: 이거 fillMaxWith 먹여야 textAlign = TextAlign.Center 가 잘 작동하는거 아닌가여?!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

오오 그러네요 !! 상위 Column에 modifier로 센터를 줬으니 이 코드는 지우겠습니다 !!

end = Offset(x = 0f, y = 230f)
)
)
.padding(18.dp),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1: padding 각자 먹여야 할 것 같아요!!
지금 해당 컴포넌트에서 HorizontalDivider에는 패딩이 안 먹고 가로영역을 다 차지하고 있어서요!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

앗 넵 그럼 따로 먹일겡요용 ~~!


) {
Text(
text = "${uiState.currentDay}일차 TO-DO 미션",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

image

P1 : 이거 일차랑 todo 사이에 패딩값이 있어서 텍스트 컴포저블 따로 만들어줘야할 것 같아요!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

넵 나눠서 리팩토링 했습니다 !

import androidx.annotation.DrawableRes
import androidx.compose.runtime.Immutable
import com.cherrish.android.R
@Immutable
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 : 줄바꿈 해주시와용 ~~

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

넵~!!

Copy link
Copy Markdown
Contributor

@nhyeonii nhyeonii left a comment

Choose a reason for hiding this comment

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

수고햇서용 ~~ !! 소희 언니 리뷰도 반영해주시고 제 리뷰도 확인해보셔서 수정 부탁드립니둥 !! 거의 끈낫다 ~~

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: 1

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionProgressCherrygrowth.kt`:
- Around line 79-83: The call to modifier.padding() in the
ChallengeMissionProgressCherrygrowth composable is invalid because padding
requires parameters; in the CherrishGaugeBar invocation replace
modifier.padding() either by providing an explicit padding value (e.g.,
modifier.padding(dp)) or by passing the modifier as-is (modifier) depending on
intended spacing; update the CherrishGaugeBar call site so the modifier argument
is a valid Modifier expression (reference CherrishGaugeBar,
ChallengeMissionProgressCherrygrowth, and the modifier.padding() call).
🧹 Nitpick comments (1)
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt (1)

73-112: 완료 버튼 활성/비활성 경로를 확인해주세요.
Line 107-111에서 CherrishButton이 항상 enabled 상태입니다. 요구사항에 “버튼 enable/disable”이 포함되어 있다면 enabled 파라미터를 노출하거나 routines 기반으로 계산해 전달하는 흐름이 필요합니다.

예시 수정(옵션)
 fun ChallengeMissionTodoSection(
     routines: ImmutableList<DailyTodoRoutineModel>,
     currentDay: Int,
     onRoutineClick: (Long) -> Unit,
     onCompleteClick: () -> Unit,
-    modifier: Modifier = Modifier
+    modifier: Modifier = Modifier,
+    isCompleteEnabled: Boolean = true
 ) {
     Column( /* ... */ ) {
         /* ... */
         CherrishButton(
             text = "오늘 미션 종료하기",
             onClick = onCompleteClick,
-            modifier = Modifier.padding(top = 10.dp)
+            modifier = Modifier.padding(top = 10.dp),
+            enabled = isCompleteEnabled
         )
     }
 }

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: 1

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt`:
- Around line 93-112: Replace hardcoded Korean strings in the
ChallengeMissionTodoTitle composable with string resources: add entries in
strings.xml for a day-format (e.g. "%1$d일차"), the "TO-DO 미션" label, and the "오늘
미션 종료하기" text, then import androidx.compose.ui.res.stringResource and use
stringResource(R.string.<name>, currentDay) for the day text and
stringResource(R.string.<name>) for the other two Text calls in
ChallengeMissionTodoTitle (and update the other occurrence at line 65 to use
stringResource as well).
🧹 Nitpick comments (2)
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionProgressCherrygrowth.kt (1)

72-76: 하드코딩된 문구는 stringResource로 분리해 주세요.

사용자 노출 문구가 문자열 리터럴로 고정돼 있어 로컬라이징/문구 관리가 어렵습니다. 리소스로 이동하는 편이 안전합니다(동시에 strings.xml에 키 추가 필요).

♻️ 제안 변경
+import androidx.compose.ui.res.stringResource
...
-            text = "체리가 크려면 ${remainingRoutines}개의 미션을 수행해야 해요!",
+            text = stringResource(
+                R.string.challenge_mission_remaining,
+                remainingRoutines
+            ),
...
-            text = "챌린지 달성률",
+            text = stringResource(R.string.challenge_progress_label),
...
-            text = "$challengeProgress%",
+            text = stringResource(
+                R.string.challenge_progress_percent,
+                challengeProgress
+            ),

Also applies to: 135-142

app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt (1)

72-90: 스크롤 컨테이너 중첩 가능성 확인 필요.
이 섹션이 상위에서 스크롤(예: LazyColumn/verticalScroll) 안에 들어가면 LazyColumn 중첩으로 측정/스크롤 충돌이 날 수 있습니다. 리스트가 소량이라면 Column으로 단순화하거나, LazyColumn을 유지한다면 높이 제약/스크롤 비활성화를 고려해 주세요.

♻️ 대안(소량 리스트 가정)
-    LazyColumn(
-        verticalArrangement = Arrangement.spacedBy(8.dp)
-    ) {
-        items(
-            items = routines,
-            key = { it.id }
-        ) { item ->
-            ChallengeChecklist(
-                isChecked = item.isCompleted,
-                onChecklistClick = { onRoutineClick(item.id) },
-                checklistContent = item.routine
-            )
-        }
-    }
+    Column(
+        verticalArrangement = Arrangement.spacedBy(8.dp)
+    ) {
+        routines.forEach { item ->
+            ChallengeChecklist(
+                isChecked = item.isCompleted,
+                onChecklistClick = { onRoutineClick(item.id) },
+                checklistContent = item.routine
+            )
+        }
+    }

Comment on lines +93 to +112
@Composable
private fun ChallengeMissionTodoTitle(
currentDay: Int,
modifier: Modifier = Modifier
) {
Row(
modifier = modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = "${currentDay}일차",
color = CherrishTheme.colors.gray1000,
style = CherrishTheme.typography.body1SB14
)

Text(
text = "TO-DO 미션",
color = CherrishTheme.colors.gray1000,
style = CherrishTheme.typography.body1SB14
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, check the actual file content at the specified lines
cd app/src/main/java/com/cherrish/android/presentation/challenge/component
if [ -f ChallengeMissionTodoSection.kt ]; then
  echo "=== File content at lines 93-112 ==="
  wc -l ChallengeMissionTodoSection.kt
  echo ""
  sed -n '93,112p' ChallengeMissionTodoSection.kt
fi

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 706


🏁 Script executed:

# Search for strings.xml files in the project
find . -name "strings.xml" -type f

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 111


🏁 Script executed:

# Check the resource structure in the project
find . -path "*/res/values*" -type d

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 99


🏁 Script executed:

# Check if there are any string resources already defined
if find . -name "strings.xml" -type f | head -1 | xargs cat 2>/dev/null | head -20; then
  echo "=== Sample strings.xml content ==="
fi

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 178


🏁 Script executed:

# Look for existing localization patterns in the file
grep -n "stringResource\|R.string" app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


🏁 Script executed:

# Check if similar challenge-related strings are already extracted
grep -r "challenge.*day\|challenge.*mission\|일차\|미션" --include="*.xml" . 2>/dev/null | head -10

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


🏁 Script executed:

# Check if other Compose files use stringResource pattern
find . -name "*.kt" -type f | xargs grep -l "stringResource" | head -5

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


🏁 Script executed:

# Look for R.string usage in the project
grep -r "R\.string\." --include="*.kt" . 2>/dev/null | head -10

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


🏁 Script executed:

# Check the complete ChallengeMissionTodoSection.kt file to understand structure
cat -n app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 6103


🏁 Script executed:

# Check if androidx.compose.ui.res is imported anywhere
grep -r "androidx.compose.ui.res" --include="*.kt" . 2>/dev/null | head -5

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 795


🏁 Script executed:

# Check for other hardcoded Korean strings in the file
grep -n "문자\|미션\|일차\|하기\|\".*\"" app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt | grep -E "text\s*=|onclick"

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 186


🏁 Script executed:

# Check if stringResource is imported and used in other files
grep -r "stringResource" --include="*.kt" . 2>/dev/null

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


🏁 Script executed:

# Check how other Compose files handle hardcoded text
find . -name "*.kt" -path "*/presentation/*" -type f | xargs grep -l "Text(" | head -3 | xargs grep -B2 -A2 "text = \"" | head -30

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 1369


🏁 Script executed:

# Verify if R.string can be accessed (build structure)
find . -name "R.kt" -o -name "R.java" | head -5

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


문자열 하드코딩 대신 stringResource 사용 권장.

Line 103, 109, 65의 "일차", "TO-DO 미션", "오늘 미션 종료하기"은 리소스로 분리하는 편이 로컬라이징에 안전합니다. 프로젝트에서 stringResource 패턴이 아직 도입되지 않았으므로, 이를 적용하려면 androidx.compose.ui.res.stringResource import 추가 및 strings.xml에 해당 리소스를 등록해야 합니다.

🔧 예시
+import androidx.compose.ui.res.stringResource
@@
         Text(
-            text = "${currentDay}일차",
+            text = stringResource(R.string.challenge_day, currentDay),
             color = CherrishTheme.colors.gray1000,
             style = CherrishTheme.typography.body1SB14
         )
@@
         Text(
-            text = "TO-DO 미션",
+            text = stringResource(R.string.challenge_todo_mission),
             color = CherrishTheme.colors.gray1000,
             style = CherrishTheme.typography.body1SB14
         )
@@
         Text(
-            text = "오늘 미션 종료하기",
+            text = stringResource(R.string.challenge_complete_today_mission),

strings.xml에 리소스 추가가 필요합니다.

🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt`
around lines 93 - 112, Replace hardcoded Korean strings in the
ChallengeMissionTodoTitle composable with string resources: add entries in
strings.xml for a day-format (e.g. "%1$d일차"), the "TO-DO 미션" label, and the "오늘
미션 종료하기" text, then import androidx.compose.ui.res.stringResource and use
stringResource(R.string.<name>, currentDay) for the day text and
stringResource(R.string.<name>) for the other two Text calls in
ChallengeMissionTodoTitle (and update the other occurrence at line 65 to use
stringResource as well).

Copy link
Copy Markdown
Contributor

@nhyeonii nhyeonii left a comment

Choose a reason for hiding this comment

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

굿굿

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: 2

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionOnboardingBody.kt`:
- Around line 67-69: Rename the preview composable function
ChallengeRoutineOnboardingMissionPreview to
ChallengeMissionOnboardingBodyPreview so its name matches the composable it
previews (ChallengeMissionOnboardingBody); update the function declaration (the
`@Composable` `@Preview` annotated private fun) and any references to the old
preview name to the new name to keep naming consistent.

In
`@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt`:
- Around line 35-38: Hardcoded UI string in the Text composable inside
ChallengeRoutineOnboardingBody.kt should be moved to resources for i18n; replace
the literal "지금 나에게 가장 필요한 \n관리 루틴을 선택해주세요." in the Text call with
stringResource(R.string.challenge_routine_onboarding_title) and add the
corresponding entry (<string name="challenge_routine_onboarding_title">지금 나에게 가장
필요한 \n관리 루틴을 선택해주세요.</string>) to strings.xml; ensure you import
androidx.compose.ui.res.stringResource and update any previews or tests that
reference the composable if they relied on the literal.
♻️ Duplicate comments (2)
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionTodoSection.kt (2)

30-71: 하드코딩된 문자열을 stringResource로 분리 권장.

Line 66의 "오늘 미션 종료하기" 문자열이 하드코딩되어 있습니다. 로컬라이제이션 지원 및 유지보수를 위해 strings.xml에 리소스로 등록하고 stringResource()를 사용하는 것이 좋습니다.

🔧 제안된 수정
+import androidx.compose.ui.res.stringResource
 
         CherrishButton(
-            text = "오늘 미션 종료하기",
+            text = stringResource(R.string.challenge_complete_today_mission),
             onClick = onCompleteClick,
             modifier = Modifier.padding(top = 10.dp)
         )

strings.xml<string name="challenge_complete_today_mission">오늘 미션 종료하기</string> 추가 필요


94-115: 하드코딩된 문자열을 stringResource로 분리 권장.

Line 104의 "${currentDay}일차"와 Line 110의 "TO-DO 미션" 문자열이 하드코딩되어 있습니다. 로컬라이제이션을 위해 리소스로 분리하는 것이 좋습니다.

🔧 제안된 수정
         Text(
-            text = "${currentDay}일차",
+            text = stringResource(R.string.challenge_day_format, currentDay),
             color = CherrishTheme.colors.gray1000,
             style = CherrishTheme.typography.body1SB14
         )

         Text(
-            text = "TO-DO 미션",
+            text = stringResource(R.string.challenge_todo_mission),
             color = CherrishTheme.colors.gray1000,
             style = CherrishTheme.typography.body1SB14
         )

strings.xml 추가 필요:

  • <string name="challenge_day_format">%1$d일차</string>
  • <string name="challenge_todo_mission">TO-DO 미션</string>
🧹 Nitpick comments (2)
app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionProgressCherrygrowth.kt (2)

73-77: 문구는 문자열 리소스로 분리해 주세요.

하드코딩된 문구는 다국어/카피 수정 시 유지보수가 어렵습니다. Line 73–77은 stringResource로 분리하는 편이 좋아요.

🔧 제안 수정
+import androidx.compose.ui.res.stringResource
...
-        Text(
-            text = "체리가 크려면 ${remainingRoutines}개의 미션을 수행해야 해요!",
+        Text(
+            text = stringResource(
+                R.string.challenge_cherry_growth_message,
+                remainingRoutines
+            ),
             color = CherrishTheme.colors.gray800,
             style = CherrishTheme.typography.body2R13
         )
<!-- res/values/strings.xml -->
<string name="challenge_cherry_growth_message">체리가 크려면 %1$d개의 미션을 수행해야 해요!</string>

149-151: 게이지 리스트는 remember로 고정해 재컴포지션 비용을 줄이세요.

CherrishGaugeType.entries.toImmutableList()가 매번 새 리스트를 만들어 CherrishGaugeBar 내부 remember(gauges) 캐시가 무효화될 수 있습니다. remember나 상수로 고정하는 편이 안전합니다. 코딩 가이드라인에 따라, 불필요한 recomposition을 줄이는 방향을 권장합니다.

🔧 제안 수정
 `@Composable`
 private fun CherryGrowthProgressSection(
     challengeProgress: Int,
     cherryType: CherryType,
     modifier: Modifier = Modifier
 ) {
+    val gauges = remember { CherrishGaugeType.entries.toImmutableList() }
     Column(
         modifier = modifier
             .fillMaxWidth(),
         verticalArrangement = Arrangement.spacedBy(12.dp)
     ) {
@@
         CherrishGaugeBar(
             currentStep = cherryType.step,
-            gauges = CherrishGaugeType.entries.toImmutableList()
+            gauges = gauges
         )
     }
 }

Comment on lines +67 to +69
@Preview(showBackground = true)
@Composable
private fun ChallengeRoutineOnboardingMissionPreview() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Preview 함수 이름 불일치

Preview 함수명이 ChallengeRoutineOnboardingMissionPreview로 되어 있으나, 실제 프리뷰 대상 컴포저블은 ChallengeMissionOnboardingBody입니다. 일관성을 위해 ChallengeMissionOnboardingBodyPreview로 변경하는 것이 좋겠습니다.

🔧 제안하는 수정
 `@Preview`(showBackground = true)
 `@Composable`
-private fun ChallengeRoutineOnboardingMissionPreview() {
+private fun ChallengeMissionOnboardingBodyPreview() {
📝 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.

Suggested change
@Preview(showBackground = true)
@Composable
private fun ChallengeRoutineOnboardingMissionPreview() {
`@Preview`(showBackground = true)
`@Composable`
private fun ChallengeMissionOnboardingBodyPreview() {
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeMissionOnboardingBody.kt`
around lines 67 - 69, Rename the preview composable function
ChallengeRoutineOnboardingMissionPreview to
ChallengeMissionOnboardingBodyPreview so its name matches the composable it
previews (ChallengeMissionOnboardingBody); update the function declaration (the
`@Composable` `@Preview` annotated private fun) and any references to the old
preview name to the new name to keep naming consistent.

Comment on lines +35 to +38
Text(
text = "지금 나에게 가장 필요한 \n관리 루틴을 선택해주세요.",
color = CherrishTheme.colors.gray1000,
style = CherrishTheme.typography.title1SB18
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

문자열 리소스로 분리 필요 (i18n/유지보수)

Line 35-38의 사용자 노출 문구가 하드코딩되어 있어 лок라이징/문구 관리에 취약합니다. stringResource로 분리해주세요.

💡 제안 변경
+import androidx.compose.ui.res.stringResource
@@
-        Text(
-            text = "지금 나에게 가장 필요한 \n관리 루틴을 선택해주세요.",
+        Text(
+            text = stringResource(R.string.challenge_routine_onboarding_title),
             color = CherrishTheme.colors.gray1000,
             style = CherrishTheme.typography.title1SB18
         )
<!-- strings.xml -->
<string name="challenge_routine_onboarding_title">지금 나에게 가장 필요한 \n관리 루틴을 선택해주세요.</string>
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/presentation/challenge/component/ChallengeRoutineOnboardingBody.kt`
around lines 35 - 38, Hardcoded UI string in the Text composable inside
ChallengeRoutineOnboardingBody.kt should be moved to resources for i18n; replace
the literal "지금 나에게 가장 필요한 \n관리 루틴을 선택해주세요." in the Text call with
stringResource(R.string.challenge_routine_onboarding_title) and add the
corresponding entry (<string name="challenge_routine_onboarding_title">지금 나에게 가장
필요한 \n관리 루틴을 선택해주세요.</string>) to strings.xml; ensure you import
androidx.compose.ui.res.stringResource and update any previews or tests that
reference the composable if they relied on the literal.

Copy link
Copy Markdown
Contributor

@usuuhyn usuuhyn left a comment

Choose a reason for hiding this comment

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

수고하샷슴둥 혜미니 짱
화이팅 ~~~!!

.padding(vertical = 14.dp)
.padding(start = 14.dp, end = 44.dp)
.noRippleClickable(onClick = onClick),
horizontalArrangement = Arrangement.spacedBy(space = 6.dp),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: 이거 6.dp가 맞지 않나요ㅇ오옹...? 8.dp로 수정한 이유가 있다면 미리 지송합니다

image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

오오오 아 6맞아요 !!! 감사ㅎ해요 진짜 짱이다
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FEAT✨ 새로운 기능 구현 혜민🍒 혜민 담당

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 챌린지 미션프로그래스 뷰 컴포넌트 구현

4 participants