Skip to content

[FEAT/#21] 홈 뷰 컴포넌트 구현#23

Closed
sohee6989 wants to merge 31 commits intodevelopfrom
feat/#21-home-view-component
Closed

[FEAT/#21] 홈 뷰 컴포넌트 구현#23
sohee6989 wants to merge 31 commits intodevelopfrom
feat/#21-home-view-component

Conversation

@sohee6989
Copy link
Copy Markdown
Contributor

@sohee6989 sohee6989 commented Jan 9, 2026

Related issue 🛠

Work Description ✏️

  • 홈 뷰에 있는 컴포넌트 구현
    (게이지바 섹션, 오늘의 일정 섹션, 다가오는 일정 섹션)

Screenshot 📸

스크린샷 2026-01-15 오후 10 01 45 스크린샷 2026-01-15 오후 10 01 42 스크린샷 2026-01-15 오후 10 01 55
2026-01-15.10.06.02.mov

Uncompleted Tasks 😅

  • 그림자 색상 하드코딩 해놓음 -> 디쌤들께 물어보고 변경 예정
  • 일정뷰 애니메이션 아요와 통일시키기

To Reviewers 📢

일단 홈화면 뷰가 조금 늦게 확정되어서 바뀐 디자인 반영하면서 홈 화면의 큰 단위의 섹션 별로 만들었습니다!
그래서 500줄이 넘었네요..ㅎㅎ

Summary by CodeRabbit

  • 새 기능

    • 진행 중인 일정 표시용 PlanBox 컴포넌트 추가(빈/채움 상태, 회복 일차·단계 표시)
    • 예정 일정 타임라인 및 개별 예정 항목 UI 추가(타임라인 색상, D-Day 배지, 더보기/접기, 항목 클릭)
    • 앱 로고 벡터 리소스 추가 및 우측 화살표 아이콘 추가
    • UI용 데이터 모델 및 다운타임 단계·타임라인 타입 추가
  • 스타일

    • 섀도우 색상 토큰 도입 및 드롭섀도우 기본색을 토큰으로 변경
  • 기타

    • 게이지 타입에 퍼센트 속성 추가

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

@sohee6989 sohee6989 requested a review from a team as a code owner January 9, 2026 17:28
@sohee6989 sohee6989 linked an issue Jan 9, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 9, 2026

Walkthrough

홈 화면 UI 컴포넌트(PlanBox, UpcomingPlan 등), 관련 UI 모델/타입, 벡터 아이콘 및 디자인 타입(CherrishGaugeType) 변경을 추가하고 Modifier.dropShadow의 기본 색상을 테마 색상으로 변경했습니다.

Changes

Cohort / File(s) 변경 내용
테마/확장 함수
app/src/main/java/com/cherrish/android/core/common/extension/ModifierExt.kt
Modifier.dropShadow 기본 색상 파라미터를 Color.Black.copy(0.25f)CherrishTheme.colors.shadow로 변경
홈 화면 UI 컴포넌트
app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt, app/src/main/java/com/cherrish/android/presentation/home/component/PlanBox.kt
다수의 private composable 추가(PlanBox, PlanBoxSection, UpcomingPlanSection 등), 레이아웃·애니메이션·클릭/확장 제어 로직 도입
컴포넌트 상태 및 모델
app/src/main/java/com/cherrish/android/presentation/home/component/PlanBoxState.kt, app/src/main/java/com/cherrish/android/presentation/home/model/PlanUiModel.kt, app/src/main/java/com/cherrish/android/presentation/home/model/UpcomingPlanUiModel.kt
PlanBoxState(sealed) 추가, PlanUiModel, UpcomingPlanUiModel(@Immutable) 추가
타입 및 스타일 매핑
app/src/main/java/com/cherrish/android/presentation/home/type/DowntimePhase.kt, app/src/main/java/com/cherrish/android/presentation/home/type/UpcomingPlanTimelineType.kt, app/src/main/java/com/cherrish/android/presentation/home/type/UpcomingPlanTimelineStyle.kt
DowntimePhase enum 추가, Int.toUpcomingPlanTimelineType() 확장 추가, UpcomingPlanTimelineStyle 데이터 클래스 및 style() 매핑 함수 추가
디자인 시스템 변경
app/src/main/java/com/cherrish/android/core/designsystem/component/type/CherrishGaugeType.kt
CherrishGaugeType 생성자에 percent: Int 필드 추가 및 모든 enum 상수에 percent 값 할당 (LEVEL1~LEVEL4) — 공개 API 변경
리소스(벡터 드로어블)
app/src/main/res/drawable/ic_right.xml, app/src/main/res/drawable/ic_app_logo.xml
우측 화살표(ic_right.xml) 및 앱 로고(ic_app_logo.xml) 벡터 drawable 추가

Sequence Diagram(s)

(생성 조건 미충족 — 해당 섹션 생략)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 분

Possibly related PRs

Suggested reviewers

  • hyeminililo
  • usuuhyn
  • nhyeonii
🚥 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 코드 변경사항이 이슈 #21의 요구사항인 홈 뷰 컴포넌트(게이지 섹션, 오늘의 일정, 다가오는 일정 등)를 완전히 구현하고 있습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 홈 뷰 컴포넌트 구현이라는 이슈 #21의 범위 내에 있으며, 관련 지원 타입, 모델, 드로어블 리소스도 해당 기능에 직접 필요합니다.

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

✨ Finishing touches
  • 📝 Generate docstrings

🧹 Recent nitpick comments
app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt (2)

190-192: visiblePlans 계산을 remember로 최적화 고려

visiblePlans가 매 recomposition마다 재계산됩니다. remember를 사용하면 불필요한 리스트 생성을 방지할 수 있습니다.

♻️ 제안하는 수정
     val previewCount = 3
     val hasMore = plans.size > previewCount
-    val visiblePlans = if (expanded) plans else plans.take(previewCount)
+    val visiblePlans = remember(plans, expanded) {
+        if (expanded) plans else plans.take(previewCount).toImmutableList()
+    }

561-563: Preview 함수 가시성 일관성

Preview()public이지만 다른 Preview 함수들(Preview2, Preview3, Preview4)은 private입니다. 일관성을 위해 private으로 변경하는 것이 좋습니다.

♻️ 제안하는 수정
 `@Preview`(showBackground = true)
 `@Composable`
-fun Preview() {
+private fun Preview() {

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d3c296c and 66f243f.

⛔ Files ignored due to path filters (2)
  • app/src/main/res/drawable/img_home_cherry.png is excluded by !**/*.png, !**/*.png
  • app/src/main/res/drawable/img_home_no_plan.png is excluded by !**/*.png, !**/*.png
📒 Files selected for processing (1)
  • app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.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/home/HomeScreen.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/home/HomeScreen.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt (4)
app/src/main/java/com/cherrish/android/core/designsystem/component/gaugebar/CherrishGaugeBar.kt (1)
  • CherrishGaugeBar (28-107)
app/src/main/java/com/cherrish/android/presentation/home/component/PlanBox.kt (1)
  • PlanBox (22-63)
app/src/main/java/com/cherrish/android/core/designsystem/component/button/CherrishButton.kt (1)
  • CherrishButton (27-79)
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 (5)
app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt (5)

71-87: LGTM!

paddingValues가 올바르게 적용되어 있습니다. 현재는 플레이스홀더 상태이며, 추후 다른 섹션 컴포넌트들이 통합될 예정으로 보입니다.


89-122: LGTM!

ImmutableList 사용으로 recomposition 최적화가 잘 되어 있고, 이미지 오버레이를 위한 offsetzIndex 사용이 적절합니다.


273-323: LGTM!

빈 상태와 데이터가 있는 상태를 when 표현식으로 깔끔하게 처리하고 있습니다. 그림자 색상도 shadow로 일관성 있게 적용되어 있습니다.


386-429: LGTM!

Canvas를 사용한 타임라인 그리기 구현이 정확합니다. density를 활용한 dp-to-px 변환과 스타일 적용이 적절합니다.


452-453: 날짜 표시 형식 확인 필요

upcomingDate.toString()은 ISO 형식(2026-01-15)을 반환합니다. 한국어 UI에서는 DateTimeFormatter를 사용하여 "1월 15일" 형식으로 포맷하는 것이 일반적입니다. PR 목표에서 서버 포맷이 미확정이라고 언급되어 있으니, 확정 후 수정이 필요할 수 있습니다.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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.

@sohee6989 sohee6989 self-assigned this Jan 9, 2026
@sohee6989 sohee6989 added FEAT✨ 새로운 기능 구현 소희🍒 소희 담당 labels Jan 9, 2026
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: 0

🧹 Nitpick comments (2)
app/src/main/java/com/cherrish/android/presentation/home/component/DowntimePhaseChip.kt (1)

15-32: 구현이 잘 되어 있습니다!

stateless composable로 올바르게 구현되었으며, 테마 시스템을 적절히 활용하고 있습니다. 다만 단일 Text를 감싸는 컨테이너로 Column보다는 Box가 더 의미적으로 적합할 수 있습니다.

♻️ Box 사용 제안
-    Column(
+    Box(
         modifier = modifier
             .clip(shape = RoundedCornerShape(20.dp))
             .background(color = CherrishTheme.colors.gray0)
app/src/main/java/com/cherrish/android/presentation/home/component/MonthPlanBox.kt (1)

80-97: DdayChip과 DowntimePhaseChip 간 코드 중복이 있습니다.

DdayChipDowntimePhaseChip이 거의 동일한 구조를 가지고 있습니다. 차이점:

  • DdayChip: 배경 gray300, horizontal padding 10.dp, vertical padding 없음
  • DowntimePhaseChip: 배경 gray0, horizontal padding 8.dp, vertical padding 3.dp, 텍스트 색상 gray700

향후 유지보수성을 위해 공통 Chip 컴포넌트로 추출하여 재사용하는 것을 권장합니다.

♻️ 통합 Chip 컴포넌트 제안

공통 컴포넌트 패키지에 다음과 같은 범용 Chip을 만들 수 있습니다:

@Composable
fun Chip(
    text: String,
    modifier: Modifier = Modifier,
    backgroundColor: Color = CherrishTheme.colors.gray300,
    textColor: Color = CherrishTheme.colors.gray900,
    textStyle: TextStyle = CherrishTheme.typography.body2R13,
    horizontalPadding: Dp = 10.dp,
    verticalPadding: Dp = 0.dp
) {
    Box(
        modifier = modifier
            .clip(shape = RoundedCornerShape(20.dp))
            .background(color = backgroundColor)
            .padding(horizontal = horizontalPadding, vertical = verticalPadding)
    ) {
        Text(
            text = text,
            style = textStyle,
            color = textColor
        )
    }
}

그런 다음 각 컴포넌트에서:

// DdayChip
@Composable
private fun DdayChip(dDay: String, modifier: Modifier = Modifier) {
    Chip(text = dDay, modifier = modifier)
}

// DowntimePhaseChip
@Composable
fun DowntimePhaseChip(downtimePhase: String, modifier: Modifier = Modifier) {
    Chip(
        text = downtimePhase,
        backgroundColor = CherrishTheme.colors.gray0,
        textColor = CherrishTheme.colors.gray700,
        horizontalPadding = 8.dp,
        verticalPadding = 3.dp,
        modifier = modifier
    )
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad96acb and 230f96c.

📒 Files selected for processing (2)
  • app/src/main/java/com/cherrish/android/presentation/home/component/DowntimePhaseChip.kt
  • app/src/main/java/com/cherrish/android/presentation/home/component/MonthPlanBox.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/home/component/DowntimePhaseChip.kt
  • app/src/main/java/com/cherrish/android/presentation/home/component/MonthPlanBox.kt
🧬 Code graph analysis (2)
app/src/main/java/com/cherrish/android/presentation/home/component/DowntimePhaseChip.kt (1)
app/src/main/java/com/cherrish/android/core/designsystem/theme/Theme.kt (1)
  • CherrishTheme (38-61)
app/src/main/java/com/cherrish/android/presentation/home/component/MonthPlanBox.kt (1)
app/src/main/java/com/cherrish/android/core/designsystem/theme/Theme.kt (1)
  • CherrishTheme (38-61)
🔇 Additional comments (4)
app/src/main/java/com/cherrish/android/presentation/home/component/DowntimePhaseChip.kt (1)

34-46: Preview 구현이 적절합니다.

다양한 배경에서의 가시성을 테스트할 수 있도록 어두운 배경을 사용한 점이 좋습니다.

app/src/main/java/com/cherrish/android/presentation/home/component/MonthPlanBox.kt (3)

30-50: shadow와 clip/border의 shape radius 불일치를 확인해주세요.

Line 34에서 dropShadow의 shape은 20.dp radius를 사용하고, Line 41과 45에서 clipborder는 10.dp radius를 사용합니다. 이것이 의도된 디자인인지 확인이 필요합니다.

하드코딩된 그림자 색상(Line 35)은 TODO 주석으로 잘 표시되어 있으며, PR 목표에서도 언급되어 있습니다.


51-77: Row 레이아웃 구성이 깔끔합니다.

Arrangement.spacedBy를 사용하여 일관된 간격을 유지하고 있으며, 테마 시스템을 적절히 활용하고 있습니다.


99-115: Preview 구현이 적절합니다.

실제 사용 시나리오를 반영한 데이터로 Preview를 구성하여 디자인 검증이 용이합니다.

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
Contributor

@hyeminililo hyeminililo 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/core/designsystem/theme/Color.kt:
- Line 38: Change the hex literal for the color constant shadow1 from uppercase
X to lowercase x to match file-wide style; update the value defined in the
shadow1 Color(...) initialization to use 0xFF9098A7 (i.e., replace 0XFF with
0xFF) so it is consistent with other color constants.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 230f96c and 2a87c1f.

📒 Files selected for processing (2)
  • app/src/main/java/com/cherrish/android/core/designsystem/theme/Color.kt
  • app/src/main/java/com/cherrish/android/presentation/home/component/MonthPlanBox.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/com/cherrish/android/presentation/home/component/MonthPlanBox.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/core/designsystem/theme/Color.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/core/designsystem/theme/Color.kt (1)
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 Build Check
  • GitHub Check: PR Lint Check
🔇 Additional comments (2)
app/src/main/java/com/cherrish/android/core/designsystem/theme/Color.kt (2)

66-68: LGTM!

shadow1 색상이 CherrishColors 데이터 클래스와 기본 초기화에 올바르게 추가되었습니다. 기존 패턴을 정확히 따르고 있으며, 테마 시스템을 통해 컴포넌트에서 CherrishTheme.colors.shadow1로 접근 가능합니다.

Also applies to: 96-98


242-254: LGTM!

미리보기 함수가 올바르게 구현되었습니다. 기존의 다른 색상 미리보기 함수들(CherrishRedColorsPreview, CherrishGrayColorsPreview 등)과 일관된 패턴을 따르고 있어 디자인 시스템의 일관성을 유지합니다.

Comment thread app/src/main/java/com/cherrish/android/core/designsystem/theme/Color.kt Outdated
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.

수고하셨습니다 !! ~~

downtimePhase: String,
modifier: Modifier = Modifier
) {
Column(
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.

P4 : 칩의 경우에는 단일 텍스트라서 Box 사용해도 될 것 같은데... 맞나용??

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.

맞아요!!
박스로 구현은 가능하다만 이 부분에서 Box의 속성을 사용하지 않고 있어서 Column으로도 가능해 Column으로 구현했습니다!!
개인적으로는 레이아웃에서 Box의 속성이 드러나지 않는 경우에는 Column을 사용하는 편이라 이 부분에서도 동일하게 적용했는데 단일 텍스트인 칩의 경우에는 Box로 구현해도 될 것 같네요!!

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.

제 얘기도 덧붙이자면 Box는 사용 목적이 비교적 명확한 컴포넌트라고 생각해용 !!!! 저는 보통 겹침이 필요하거나 부모 영역을 기준으로 자식의 위치를 직접 제어해야 할 때 Box를 선택하는 편이랍니닿ㅎㅎ 단순히 수직, 수평으로 나열하는 구조라면 Box의 역할이 크게 필요하지 않다고 느껴서 보토은 Column이나 Row를 더 많이 사용해욧 !!!

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.

오호 !!! 좋은 정보 얻어갑니다~

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/home/type/UpcomingPlanTimelineStyle.kt`:
- Line 6: The code imports and references the top-level gray0 instead of using
the theme colors object; update UpcomingPlanTimelineStyle to remove the direct
import of gray0 and use colors.gray0 in the THIRD case (and the similar usage
around the other occurrences noted, e.g., the block covering lines 25-28) so all
cases consistently reference colors.<symbol>gray0</symbol> via the theme
(replace direct gray0 usages with colors.gray0 and remove the import
com.cherrish.android.core.designsystem.theme.gray0).
🧹 Nitpick comments (7)
app/src/main/res/drawable/ic_right.xml (1)

10-12: 하드코딩된 색상 값 확인 필요

#9FA4A9 색상이 fillColor와 strokeColor에 직접 하드코딩되어 있습니다. PR 설명에서 디자인 시스템 반영이 아직 완료되지 않았다고 언급되어 있으나, 향후 테마 색상으로 교체하거나 아이콘 사용 시 tint를 적용하는 방식으로 개선하면 일관성 유지에 도움이 됩니다.

app/src/main/java/com/cherrish/android/presentation/home/component/PlanBoxState.kt (1)

7-11: 프로퍼티 네이밍 및 @Immutable 어노테이션 검토

  1. 네이밍 불일치: medicalProcedureNameDateInt 타입인데, 이름이 모호합니다. PlanUiModel에서는 동일한 개념을 daysSince로 표현하고 있어 일관성을 위해 네이밍 통일을 권장합니다.

  2. @Immutable 어노테이션 누락: Filled data class가 Compose UI에서 사용된다면 @Immutable 어노테이션을 추가하여 불필요한 recomposition을 방지할 수 있습니다.

♻️ 권장 수정안
 package com.cherrish.android.presentation.home.component
 
+import androidx.compose.runtime.Immutable
 import com.cherrish.android.presentation.home.type.DowntimePhase
 
 sealed interface PlanBoxState {
     data object Empty : PlanBoxState
+    `@Immutable`
     data class Filled(
         val medicalProcedureName: String,
-        val medicalProcedureNameDate: Int,
+        val daysSinceProcedure: Int,
         val downtimePhase: DowntimePhase
     ) : PlanBoxState
 }
app/src/main/java/com/cherrish/android/core/common/extension/ModifierExt.kt (1)

46-54: 기본 매개변수에서 CompositionLocal 접근 시 주의가 필요합니다.

CherrishTheme.colors.shadow1을 기본 매개변수로 사용하면, 함수 호출 시점에 CompositionLocal이 평가됩니다. CherrishTheme이 제공되지 않은 컨텍스트에서 호출될 경우 기본값(defaultCherrishColors)이 사용되어 의도한 테마 색상과 다를 수 있습니다.

안전한 패턴은 기본값을 Color.Unspecified로 설정하고 composed 블록 내부에서 테마 색상을 가져오는 것입니다.

♻️ 권장되는 수정 방안
 `@Composable`
 fun Modifier.dropShadow(
     shape: Shape,
-    color: Color = CherrishTheme.colors.shadow1,
+    color: Color = Color.Unspecified,
     blur: Dp = 1.dp,
     offsetY: Dp = 1.dp,
     offsetX: Dp = 1.dp,
     spread: Dp = 1.dp
 ) = composed {
     val density = LocalDensity.current
+    val resolvedColor = if (color == Color.Unspecified) {
+        CherrishTheme.colors.shadow1
+    } else {
+        color
+    }
 
-    val paint = remember(color, blur) {
+    val paint = remember(resolvedColor, blur) {
         Paint().apply {
-            this.color = color
+            this.color = resolvedColor
             // ...
         }
     }
     // ...
 }
app/src/main/java/com/cherrish/android/presentation/home/component/PlanBox.kt (4)

45-52: 하드코딩된 문자열을 문자열 리소스로 추출하는 것을 권장합니다.

"진행 중인 일정이 없어요"와 같은 사용자에게 표시되는 문자열은 국제화(i18n)를 위해 strings.xml 리소스로 관리하는 것이 좋습니다.


72-98: 긴 시술명에 대한 텍스트 오버플로우 처리가 필요합니다.

PR 설명에 언급된 대로 시술명이 길어질 경우 레이아웃이 깨질 수 있습니다. 기획 요구사항 확정 전까지 maxLinesoverflow 속성을 추가하여 방어적으로 처리하는 것을 권장합니다.

♻️ 권장되는 수정 방안
         Text(
             text = medicalProcedureName,
             style = CherrishTheme.typography.body1M14,
-            color = CherrishTheme.colors.gray900
+            color = CherrishTheme.colors.gray900,
+            maxLines = 1,
+            overflow = TextOverflow.Ellipsis
         )

101-123: Column 대신 Box를 사용하는 것이 더 적합합니다.

단일 Text 자식만 포함하므로 Column 대신 Box를 사용하면 더 명확하고 효율적입니다.

♻️ 제안된 수정
-    Column(
+    Box(
         modifier = modifier
             .clip(shape = RoundedCornerShape(20.dp))
             .background(color = CherrishTheme.colors.gray0)
             .border(
                 width = 1.dp,
                 color = CherrishTheme.colors.gray400,
                 shape = RoundedCornerShape(20.dp)
             )
-            .padding(horizontal = 8.dp, vertical = 2.dp)
+            .padding(horizontal = 8.dp, vertical = 2.dp),
+        contentAlignment = Alignment.Center
     ) {
         Text(
             text = downtimePhase.phaseName,
             style = CherrishTheme.typography.body2R13,
             color = CherrishTheme.colors.gray700
         )
     }

125-137: Preview 함수명을 더 구체적으로 변경하는 것을 권장합니다.

Preview()보다 PlanBoxFilledPreview() 또는 PlanBoxPreview()와 같이 파일 내 다른 프리뷰와 구분 가능한 이름을 사용하면 Android Studio Preview 창에서 식별이 용이합니다.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a87c1f and 6a19974.

📒 Files selected for processing (10)
  • app/src/main/java/com/cherrish/android/core/common/extension/ModifierExt.kt
  • app/src/main/java/com/cherrish/android/core/designsystem/theme/Color.kt
  • app/src/main/java/com/cherrish/android/presentation/home/component/PlanBox.kt
  • app/src/main/java/com/cherrish/android/presentation/home/component/PlanBoxState.kt
  • app/src/main/java/com/cherrish/android/presentation/home/model/PlanUiModel.kt
  • app/src/main/java/com/cherrish/android/presentation/home/model/UpcomingPlanUiModel.kt
  • app/src/main/java/com/cherrish/android/presentation/home/type/DowntimePhase.kt
  • app/src/main/java/com/cherrish/android/presentation/home/type/UpcomingPlanTimelineStyle.kt
  • app/src/main/java/com/cherrish/android/presentation/home/type/UpcomingPlanTimelineType.kt
  • app/src/main/res/drawable/ic_right.xml
🧰 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/home/type/UpcomingPlanTimelineType.kt
  • app/src/main/java/com/cherrish/android/presentation/home/type/UpcomingPlanTimelineStyle.kt
  • app/src/main/java/com/cherrish/android/core/common/extension/ModifierExt.kt
  • app/src/main/java/com/cherrish/android/presentation/home/model/UpcomingPlanUiModel.kt
  • app/src/main/java/com/cherrish/android/presentation/home/component/PlanBoxState.kt
  • app/src/main/java/com/cherrish/android/presentation/home/type/DowntimePhase.kt
  • app/src/main/java/com/cherrish/android/presentation/home/model/PlanUiModel.kt
  • app/src/main/java/com/cherrish/android/core/designsystem/theme/Color.kt
  • app/src/main/java/com/cherrish/android/presentation/home/component/PlanBox.kt
🧠 Learnings (2)
📚 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/home/type/UpcomingPlanTimelineType.kt
  • app/src/main/java/com/cherrish/android/presentation/home/type/UpcomingPlanTimelineStyle.kt
  • app/src/main/java/com/cherrish/android/presentation/home/model/UpcomingPlanUiModel.kt
  • app/src/main/java/com/cherrish/android/presentation/home/component/PlanBoxState.kt
  • app/src/main/java/com/cherrish/android/presentation/home/type/DowntimePhase.kt
  • app/src/main/java/com/cherrish/android/presentation/home/model/PlanUiModel.kt
  • app/src/main/java/com/cherrish/android/presentation/home/component/PlanBox.kt
📚 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: 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.

Applied to files:

  • app/src/main/java/com/cherrish/android/core/common/extension/ModifierExt.kt
  • app/src/main/java/com/cherrish/android/core/designsystem/theme/Color.kt
🧬 Code graph analysis (2)
app/src/main/java/com/cherrish/android/core/designsystem/theme/Color.kt (1)
app/src/main/java/com/cherrish/android/core/designsystem/theme/Theme.kt (1)
  • CherrishTheme (38-61)
app/src/main/java/com/cherrish/android/presentation/home/component/PlanBox.kt (1)
app/src/main/java/com/cherrish/android/core/designsystem/theme/Theme.kt (1)
  • CherrishTheme (38-61)
🔇 Additional comments (8)
app/src/main/java/com/cherrish/android/presentation/home/model/UpcomingPlanUiModel.kt (1)

6-12: LGTM!

@Immutable 어노테이션을 적절히 사용하여 Compose의 안정성(stability)을 보장하고 있습니다. LocalDate 사용과 프로퍼티 구조가 UI 모델로서 적합합니다.

app/src/main/java/com/cherrish/android/presentation/home/type/DowntimePhase.kt (1)

3-9: LGTM!

enum 구조가 깔끔하고 phaseName 프로퍼티를 통해 표시 텍스트를 제공하는 방식이 적절합니다.

향후 다국어 지원이 필요할 경우 문자열 리소스(@StringRes)로 전환하는 것을 고려해볼 수 있습니다.

app/src/main/java/com/cherrish/android/presentation/home/model/PlanUiModel.kt (1)

6-11: LGTM!

@Immutable 어노테이션과 함께 적절한 프로퍼티 구조를 갖추고 있습니다. DowntimePhase enum을 타입으로 사용하여 타입 안전성을 확보한 점이 좋습니다.

app/src/main/java/com/cherrish/android/core/designsystem/theme/Color.kt (3)

38-38: LGTM!

shadow1 색상 정의가 올바르게 구현되었습니다. copy(alpha = 0.12f)를 사용하여 알파 값을 적용하는 방식이 깔끔하고, hex 리터럴도 파일 내 다른 색상들과 일관되게 소문자 0xFF를 사용하고 있습니다.


66-69: LGTM!

CherrishColors 데이터 클래스에 shadow1 속성이 기존 패턴을 따라 올바르게 추가되었습니다.


241-254: LGTM!

CherrishShadowColorsPreview 함수가 기존 색상 미리보기 함수들과 동일한 패턴으로 구현되어 일관성이 유지됩니다.

app/src/main/java/com/cherrish/android/presentation/home/type/UpcomingPlanTimelineType.kt (1)

7-11: LGTM!

Int.toUpcomingPlanTimelineType() 확장 함수가 깔끔하게 구현되었습니다. else 분기에서 예상치 못한 값(2 이상 또는 음수)을 THIRD로 처리하는 방어적 접근이 적절합니다.

app/src/main/java/com/cherrish/android/presentation/home/type/UpcomingPlanTimelineStyle.kt (1)

8-11: LGTM!

UpcomingPlanTimelineStyle 데이터 클래스가 타임라인 스타일링에 필요한 속성들을 명확하게 캡슐화하고 있습니다.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import com.cherrish.android.core.designsystem.theme.CherrishColors
import com.cherrish.android.core.designsystem.theme.gray0
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

일관성을 위해 colors.gray0를 사용해야 합니다.

다른 케이스들은 모두 colors.redXXX를 사용하지만, THIRD 케이스에서는 최상위 gray0를 직접 참조하고 있습니다. 테마 일관성을 위해 colors.gray0를 사용하는 것이 좋습니다.

🔧 제안된 수정
-import com.cherrish.android.core.designsystem.theme.gray0
 
 // ...
 
         UpcomingPlanTimelineType.THIRD -> UpcomingPlanTimelineStyle(
             circleColor = colors.red300,
-            barBrush = Brush.linearGradient(listOf(colors.red300, gray0))
+            barBrush = Brush.linearGradient(listOf(colors.red300, colors.gray0))
         )

Also applies to: 25-28

🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/presentation/home/type/UpcomingPlanTimelineStyle.kt`
at line 6, The code imports and references the top-level gray0 instead of using
the theme colors object; update UpcomingPlanTimelineStyle to remove the direct
import of gray0 and use colors.gray0 in the THIRD case (and the similar usage
around the other occurrences noted, e.g., the block covering lines 25-28) so all
cases consistently reference colors.<symbol>gray0</symbol> via the theme
(replace direct gray0 usages with colors.gray0 and remove the import
com.cherrish.android.core.designsystem.theme.gray0).

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/home/HomeScreen.kt`:
- Around line 400-417: DDayChip currently interpolates dDay directly resulting
in "D-0" or "D--1"; inside DDayChip compute a display string first: if dDay > 0
use "D-{dDay}", if dDay == 0 use "D-Day", and if dDay < 0 use "D+{abs(dDay)}";
then pass that computed label to the Text composable (replace the current text =
"D-$dDay") so negative values and zero render correctly and avoid double minus
signs.
- Around line 96-103: In PlanBoxSection, change the dropShadow color from
CherrishTheme.colors.gray0 to CherrishTheme.colors.shadow1 so the shadow matches
UpcomingPlanSection and the design system; locate the dropShadow(...) call in
PlanBoxSection (the block with shape = RoundedCornerShape(14.dp), blur = 10.dp,
offsetX/offsetY = 0.dp) and replace the color argument accordingly.
🧹 Nitpick comments (4)
app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt (4)

133-143: keyindex 포함 시 재정렬 시 불필요한 recomposition 발생 가능

keyindex를 포함하면 항목이 재정렬될 때 동일한 항목이라도 키가 변경되어 불필요한 recomposition이 발생할 수 있습니다.

PlanUiModel에 고유 ID가 있다면 그것을 사용하는 것이 좋습니다. 현재 데이터 모델에 고유 ID가 없다면, 서버 연동 시 추가를 고려해 주세요.


430-440: LGTM!

Spacerweight를 사용한 레이아웃 구성이 적절합니다. TODO 주석으로 이미지 추가가 예정되어 있음을 확인했습니다.

TODO 항목에 대해 이슈를 생성하거나 구현을 도와드릴까요?


450-513: Preview 함수 명명 규칙 및 가시성 개선 권장

  1. Preview() 함수에 private 접근 제한자가 없습니다 (Line 452). Preview2, Preview3와 일관성을 위해 private를 추가하세요.
  2. Preview 함수 이름이 설명적이지 않습니다. 무엇을 미리보기하는지 명확한 이름을 사용하는 것이 좋습니다.
♻️ 제안하는 수정
 `@Preview`(showBackground = true)
 `@Composable`
-fun Preview() {
+private fun PlanBoxSectionPreview() {
     CherrishTheme {
         // ...
     }
 }

 `@Preview`(showBackground = true)
 `@Composable`
-private fun Preview2() {
+private fun UpcomingPlanSectionWithPlansPreview() {
     // ...
 }

 `@Preview`(showBackground = true)
 `@Composable`
-private fun Preview3() {
+private fun UpcomingPlanSectionEmptyPreview() {
     // ...
 }

373-379: procedureCount 조건 명확화 권장

procedureCount != 0 대신 procedureCount > 0을 사용하면 의도가 더 명확해집니다. 음수 값이 들어올 가능성은 낮지만, 방어적 코딩 관점에서 더 안전합니다.

♻️ 제안하는 수정
-                if (procedureCount != 0) {
+                if (procedureCount > 0) {
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a19974 and 0217f2f.

📒 Files selected for processing (1)
  • app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.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/home/HomeScreen.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/home/HomeScreen.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt (3)
app/src/main/java/com/cherrish/android/presentation/home/component/PlanBox.kt (1)
  • PlanBox (22-63)
app/src/main/java/com/cherrish/android/core/designsystem/component/button/CherrishButton.kt (1)
  • CherrishButton (27-79)
app/src/main/java/com/cherrish/android/core/designsystem/theme/Theme.kt (1)
  • CherrishTheme (38-61)
🔇 Additional comments (6)
app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt (6)

63-79: LGTM!

paddingValues가 루트 컨테이너에 올바르게 적용되어 있습니다. 학습된 패턴에 따라 시스템 바(상태바/네비게이션 바)를 올바르게 처리하고 있습니다.


171-221: LGTM!

UpcomingPlanSection의 구조가 깔끔하고, when 표현식을 사용한 조건부 렌더링이 적절합니다. shadow1 색상도 올바르게 적용되어 있습니다.


223-245: LGTM!

리스트 렌더링 구조가 적절합니다. keyindex가 포함된 부분은 PlanBoxSection과 동일한 개선 사항이 적용될 수 있습니다.


255-256: mutableIntStateOfmutableFloatStateOf 사용 - 좋습니다!

primitive 타입에 대해 최적화된 state 함수를 사용하여 불필요한 박싱을 방지하고 있습니다.


284-327: LGTM!

Canvas를 사용한 타임라인 구현이 적절합니다. density를 활용한 dp/px 변환과 조건부 라인 시작점 처리가 올바르게 구현되어 있습니다.


350-351: 날짜 포맷 확인 필요

upcomingDate.toString()은 ISO 8601 형식(2026-01-15)을 반환합니다. PR 설명에 따르면 날짜 포맷은 서버 명세에 따라 변경될 예정이지만, 디자인에 맞는 형식(예: 1월 15일)으로 포맷팅하는 것이 필요할 수 있습니다.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +96 to +103
.dropShadow(
shape = RoundedCornerShape(14.dp),
color = CherrishTheme.colors.gray0,
blur = 10.dp,
offsetX = 0.dp,
offsetY = 0.dp,
spread = 0.dp
)
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:

# Read the HomeScreen.kt file to verify the actual code
cat -n app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt | sed -n '80,190p'

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 4460


🏁 Script executed:

# Find theme/color definitions
find . -type f -name "*.kt" | xargs rg "gray0|shadow1" -A 2 -B 2 | head -100

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 9399


🏁 Script executed:

# Look for CherrishTheme color definitions
fd -t f -e kt | xargs rg "object.*Theme|val.*colors|CherrishTheme" -l | head -20

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 859


🏁 Script executed:

# Check if there are other dropShadow usages to see the pattern
rg "\.dropShadow\(" -B 2 -A 5 app/src/main/java/com/cherrish/android/presentation/

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 1770


PlanBoxSection의 그림자 색상을 shadow1로 변경 필요

PlanBoxSection의 dropShadow에서 gray0(흰색, #FFFFFF)을 사용하고 있는데, 같은 화면의 UpcomingPlanSection은 shadow1을 사용합니다. 디자인 시스템의 그림자 색상(shadow1: #9098A7 with 12% opacity)이 추가되었으므로 일관성 있게 CherrishTheme.colors.shadow1로 수정하세요.

🤖 Prompt for AI Agents
In `@app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt`
around lines 96 - 103, In PlanBoxSection, change the dropShadow color from
CherrishTheme.colors.gray0 to CherrishTheme.colors.shadow1 so the shadow matches
UpcomingPlanSection and the design system; locate the dropShadow(...) call in
PlanBoxSection (the block with shape = RoundedCornerShape(14.dp), blur = 10.dp,
offsetX/offsetY = 0.dp) and replace the color argument accordingly.

Comment on lines +400 to +417
@Composable
private fun DDayChip(
dDay: Int,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.clip(shape = RoundedCornerShape(20.dp))
.background(color = CherrishTheme.colors.gray200)
.padding(horizontal = 10.dp)
) {
Text(
text = "D-$dDay",
style = CherrishTheme.typography.body3R12,
color = CherrishTheme.colors.gray600
)
}
}
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

D-Day 엣지 케이스 처리 필요

현재 구현에서 dDay가 0 또는 음수일 때의 처리가 없습니다:

  • dDay = 0"D-0" (의도된 것인지 확인 필요, 보통 "D-Day" 표시)
  • dDay = -1"D--1" (잘못된 형식)
🔧 제안하는 수정
 `@Composable`
 private fun DDayChip(
     dDay: Int,
     modifier: Modifier = Modifier
 ) {
+    val dDayText = when {
+        dDay > 0 -> "D-$dDay"
+        dDay == 0 -> "D-Day"
+        else -> "D+${-dDay}"
+    }
+
     Column(
         modifier = modifier
             .clip(shape = RoundedCornerShape(20.dp))
             .background(color = CherrishTheme.colors.gray200)
             .padding(horizontal = 10.dp)
     ) {
         Text(
-            text = "D-$dDay",
+            text = dDayText,
             style = CherrishTheme.typography.body3R12,
             color = CherrishTheme.colors.gray600
         )
     }
 }
🤖 Prompt for AI Agents
In `@app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt`
around lines 400 - 417, DDayChip currently interpolates dDay directly resulting
in "D-0" or "D--1"; inside DDayChip compute a display string first: if dDay > 0
use "D-{dDay}", if dDay == 0 use "D-Day", and if dDay < 0 use "D+{abs(dDay)}";
then pass that computed label to the Text composable (replace the current text =
"D-$dDay") so negative values and zero render correctly and avoid double minus
signs.

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/home/HomeScreen.kt`:
- Around line 526-542: The Spacer weight calls inside the Column will not behave
correctly because the Column has no vertical constraint (it only uses
fillMaxWidth()); update the parent Column modifier to provide a bounded height
(e.g., use fillMaxSize() or a specific height()) or replace the Spacer(modifier
= Modifier.weight(...)) with fixed height Spacers (Modifier.height(...)) so the
vertical spacing behaves as intended; locate the Column block and either change
its modifier or change the two Spacer instances accordingly.
- Around line 130-132: The current computation of safeStep and accessing
gauges[safeStep - 1] can crash when gauges is empty (coerceIn(1, 0) -> 1 then
gauges[0] causes IndexOutOfBounds); fix by guarding against empty lists before
calculating safeStep/gauge: check gauges.isEmpty() and handle that case
(return/render empty-state UI or use a nullable gauge variable) and only compute
safeStep and read gauges[safeStep - 1] when gauges.isNotEmpty(); update uses of
isStart/currentStep accordingly so they account for the empty-state branch.
♻️ Duplicate comments (1)
app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt (1)

502-519: D-Day 엣지 케이스 처리 필요

이전 리뷰에서 언급된 것처럼, dDay가 0 또는 음수일 때의 처리가 필요합니다:

  • dDay = 0"D-0" (일반적으로 "D-Day" 표시)
  • dDay = -1"D--1" (잘못된 형식, "D+1" 이어야 함)
🔧 제안하는 수정
 `@Composable`
 private fun DDayChip(
     dDay: Int,
     modifier: Modifier = Modifier
 ) {
+    val dDayText = when {
+        dDay > 0 -> "D-$dDay"
+        dDay == 0 -> "D-Day"
+        else -> "D+${-dDay}"
+    }
+
     Column(
         modifier = modifier
             .clip(shape = RoundedCornerShape(20.dp))
             .background(color = CherrishTheme.colors.gray200)
             .padding(horizontal = 10.dp)
     ) {
         Text(
-            text = "D-$dDay",
+            text = dDayText,
             style = CherrishTheme.typography.body3R12,
             color = CherrishTheme.colors.gray600
         )
     }
 }
🧹 Nitpick comments (3)
app/src/main/java/com/cherrish/android/core/designsystem/component/type/CherrishGaugeType.kt (1)

3-10: LGTM! 명확한 enum 구조입니다.

named parameter 사용으로 가독성이 좋습니다. 선택적으로 percentstep에서 파생시켜 중복을 줄일 수 있습니다:

♻️ 선택적 리팩토링 제안
 enum class CherrishGaugeType(
-    val step: Int,
-    val percent: Int
+    val step: Int
 ) {
-    LEVEL1(step = 1, percent = 25),
-    LEVEL2(step = 2, percent = 50),
-    LEVEL3(step = 3, percent = 75),
-    LEVEL4(step = 4, percent = 100)
+    LEVEL1(step = 1),
+    LEVEL2(step = 2),
+    LEVEL3(step = 3),
+    LEVEL4(step = 4);
+
+    val percent: Int get() = step * 25
 }

현재 구현도 명시적이고 문제없으므로 유지해도 괜찮습니다.

app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt (2)

224-229: 애니메이션 duration이 다소 짧을 수 있음

durationMillis = 70은 expand/collapse 애니메이션이 거의 즉각적으로 느껴질 수 있습니다. 사용자 경험을 위해 150-200ms 정도가 더 자연스러울 수 있으나, 디자인 의도에 따라 현재 값을 유지해도 무방합니다.


552-554: Preview 함수 visibility 일관성

Preview()private이 누락되어 있습니다. 다른 Preview 함수들(Preview2, Preview3, Preview4)과 일관성을 위해 private을 추가하세요.

 `@Preview`(showBackground = true)
 `@Composable`
-fun Preview() {
+private fun Preview() {
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4588e29 and d3c296c.

⛔ Files ignored due to path filters (1)
  • app/src/main/res/drawable/ic_home_cherry.png is excluded by !**/*.png, !**/*.png
📒 Files selected for processing (4)
  • app/src/main/java/com/cherrish/android/core/common/extension/ModifierExt.kt
  • app/src/main/java/com/cherrish/android/core/designsystem/component/type/CherrishGaugeType.kt
  • app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt
  • app/src/main/res/drawable/ic_app_logo.xml
✅ Files skipped from review due to trivial changes (1)
  • app/src/main/res/drawable/ic_app_logo.xml
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/com/cherrish/android/core/common/extension/ModifierExt.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/home/HomeScreen.kt
  • app/src/main/java/com/cherrish/android/core/designsystem/component/type/CherrishGaugeType.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/home/HomeScreen.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt (4)
app/src/main/java/com/cherrish/android/core/designsystem/component/gaugebar/CherrishGaugeBar.kt (1)
  • CherrishGaugeBar (28-107)
app/src/main/java/com/cherrish/android/presentation/home/component/PlanBox.kt (1)
  • PlanBox (22-63)
app/src/main/java/com/cherrish/android/core/designsystem/component/button/CherrishButton.kt (1)
  • CherrishButton (27-79)
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 (6)
app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt (6)

78-87: LGTM!

paddingValues가 root modifier에 올바르게 적용되어 있습니다. Retrieved learnings에 따라 Scaffold의 paddingValues를 먼저 적용하는 패턴을 잘 따르고 있습니다.


452-453: 날짜 포맷 확인 필요

LocalDate.toString()은 ISO-8601 형식(2026-01-15)을 반환합니다. UI에 한국어 형식(예: 1월 15일 또는 2026년 1월 15일)으로 표시해야 한다면 DateTimeFormatter를 사용하여 포맷팅이 필요합니다.

♻️ 제안하는 수정 (필요시)
+import java.time.format.DateTimeFormatter
+import java.util.Locale
+
+private val dateFormatter = DateTimeFormatter.ofPattern("M월 d일", Locale.KOREAN)
+
 // UpcomingPlanBox 내부에서:
 Text(
-    text = upcomingDate.toString(),
+    text = upcomingDate.format(dateFormatter),
     style = CherrishTheme.typography.body1M14,
     color = CherrishTheme.colors.gray700,

386-429: LGTM!

Canvas를 사용한 타임라인 그리기 로직이 깔끔하게 구현되어 있습니다. LocalDensity를 활용한 px/dp 변환과 조건부 라인 시작점 처리가 적절합니다.


349-384: LGTM!

mutableIntStateOfmutableFloatStateOf를 사용하여 primitive 타입에 대한 recomposition을 최적화했습니다. 타임라인과 날짜 텍스트 위치 동기화 패턴이 잘 구현되어 있습니다.


89-122: LGTM!

zIndex를 활용한 체리 이미지 레이어링이 적절하게 구현되어 있습니다.


456-462: LGTM!

위치 변화 threshold 체크(abs(y - previousDateTextTopY) > 0.5f)로 불필요한 콜백 호출을 방지하는 최적화가 잘 적용되어 있습니다.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +130 to +132
val isStart = currentStep <= 0
val safeStep = currentStep.coerceIn(1, gauges.size)
val gauge = gauges[safeStep - 1]
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 | 🔴 Critical

gauges가 빈 리스트일 때 IndexOutOfBoundsException 발생 가능

gauges가 비어있으면 coerceIn(1, 0)1을 반환하고, gauges[0] 접근 시 크래시가 발생합니다.

🐛 제안하는 수정
 `@Composable`
 private fun Challenge(
     currentStep: Int,
     gauges: ImmutableList<CherrishGaugeType>,
     modifier: Modifier = Modifier
 ) {
+    if (gauges.isEmpty()) return
+
     val isStart = currentStep <= 0
     val safeStep = currentStep.coerceIn(1, gauges.size)
     val gauge = gauges[safeStep - 1]

또는 빈 상태에 대한 UI를 별도로 처리하세요.

📝 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
val isStart = currentStep <= 0
val safeStep = currentStep.coerceIn(1, gauges.size)
val gauge = gauges[safeStep - 1]
`@Composable`
private fun Challenge(
currentStep: Int,
gauges: ImmutableList<CherrishGaugeType>,
modifier: Modifier = Modifier
) {
if (gauges.isEmpty()) return
val isStart = currentStep <= 0
val safeStep = currentStep.coerceIn(1, gauges.size)
val gauge = gauges[safeStep - 1]
🤖 Prompt for AI Agents
In `@app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt`
around lines 130 - 132, The current computation of safeStep and accessing
gauges[safeStep - 1] can crash when gauges is empty (coerceIn(1, 0) -> 1 then
gauges[0] causes IndexOutOfBounds); fix by guarding against empty lists before
calculating safeStep/gauge: check gauges.isEmpty() and handle that case
(return/render empty-state UI or use a nullable gauge variable) and only compute
safeStep and read gauges[safeStep - 1] when gauges.isNotEmpty(); update uses of
isStart/currentStep accordingly so they account for the empty-state branch.

Comment on lines +526 to +542
Column(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.weight(70f))

// TODO: 추후 이미지 들어갈 예정

Text(
text = "아직 진행 중인 관리가 없어요.",
style = CherrishTheme.typography.body1R14,
color = CherrishTheme.colors.gray600
)

Spacer(modifier = Modifier.weight(60f))
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

weight() modifier는 부모에 높이 제약이 필요함

Spacer(modifier = Modifier.weight(...))는 부모 Column에 bounded height가 있어야 정상 동작합니다. 현재 Column은 fillMaxWidth()만 있고 높이 제약이 없어서 weight 비율이 의도대로 적용되지 않을 수 있습니다.

부모 레이아웃에서 이 섹션에 고정 높이를 주거나, 고정된 Spacer(modifier = Modifier.height(...))로 변경하는 것을 고려하세요.

🤖 Prompt for AI Agents
In `@app/src/main/java/com/cherrish/android/presentation/home/HomeScreen.kt`
around lines 526 - 542, The Spacer weight calls inside the Column will not
behave correctly because the Column has no vertical constraint (it only uses
fillMaxWidth()); update the parent Column modifier to provide a bounded height
(e.g., use fillMaxSize() or a specific height()) or replace the Spacer(modifier
= Modifier.weight(...)) with fixed height Spacers (Modifier.height(...)) so the
vertical spacing behaves as intended; locate the Column block and either change
its modifier or change the two Spacer instances accordingly.

@sohee6989 sohee6989 closed this Jan 15, 2026
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