Skip to content

[FEAT/#44] 정보 입력 화면 구현#49

Merged
sohee6989 merged 11 commits intodevelopfrom
feat/#44-input-information-ui
Jan 15, 2026
Merged

[FEAT/#44] 정보 입력 화면 구현#49
sohee6989 merged 11 commits intodevelopfrom
feat/#44-input-information-ui

Conversation

@sohee6989
Copy link
Copy Markdown
Contributor

@sohee6989 sohee6989 commented Jan 13, 2026

Related issue 🛠

Work Description ✏️

  • 정보 입력 화면 구현

Screenshot 📸

Screen_recording_20260114_005608.mp4
Screen_recording_20260114_014229.mp4

Uncompleted Tasks 😅

  • N/A

To Reviewers 📢

이 화면은 서버에서 정보를 받아오는 화면이 아니라 로딩, 실패, 성공 화면에 대한 분기처리가 불필요하다고 생각해 처리하지 않았습니다!

Summary by CodeRabbit

  • 새로운 기능
    • 온보딩 정보 입력 화면 추가: 이름·나이 입력 필드와 "다음" 버튼 제공, 둘 다 입력되어야 버튼 활성화.
    • 나이 필드에 자동 "세" 단위 표시 변환 추가(포커스/키보드 동작 제어 포함).
    • 입력 상태를 관리하는 뷰모델 및 UI 상태 모델 추가로 입력 흐름·유효성 검사 처리.
    • 텍스트 입력 컴포넌트에 시각적 변환(visualTransformation) 지원 추가.

✏️ 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 13, 2026 16:02
@sohee6989 sohee6989 linked an issue Jan 13, 2026 that may be closed by this pull request
@sohee6989 sohee6989 self-assigned this Jan 13, 2026
@sohee6989 sohee6989 added FEAT✨ 새로운 기능 구현 소희🍒 소희 담당 labels Jan 13, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 13, 2026

Walkthrough

온보딩 정보 입력 화면(이름/나이)과 관련 상태 및 뷰모델을 추가하고, CherrishTextFieldvisualTransformation 파라미터를 도입해 내부 BasicTextField로 전달합니다. (총 다수 파일 추가/수정)

Changes

Cohort / File(s) 변경 사항
TextField 기능 확장
app/src/main/java/com/cherrish/android/core/designsystem/component/textfield/CherrishTextField.kt
visualTransformation: VisualTransformation = VisualTransformation.None 파라미터 추가 및 해당 값을 BasicTextFieldvisualTransformation로 전달
정보 입력 화면
app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt
InformationRouteInformationScreen 컴포저블 추가: 이름/나이 입력 UI, 포커스/키보드 동작, AgeSuffixTransformation 적용 및 "다음" 버튼 처리
UI 상태
app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationUiState.kt
InformationUiState 데이터 클래스 추가 (username, age, buttonEnabled 계산 프로퍼티)
뷰모델
app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationViewModel.kt
InformationViewModel 추가: uiState 노출, onNameChanged, 숫자 필터링을 수행하는 onAgeChanged, onNextClicked 핸들러
시각적 변환 확장
app/src/main/java/com/cherrish/android/presentation/onboarding/information/extension/AgeSuffixTransformation.kt
VisualTransformation 구현 추가: 입력 뒤에 " 세" 접미사 추가 및 오프셋 매핑 처리

Sequence Diagram

sequenceDiagram
    participant User
    participant InformationScreen
    participant InformationViewModel
    participant InformationUiState

    User->>InformationScreen: 이름 입력
    InformationScreen->>InformationViewModel: onNameChanged(name)
    InformationViewModel->>InformationUiState: 상태 업데이트 (username)
    InformationViewModel-->>InformationScreen: uiState 방출

    User->>InformationScreen: 나이 입력
    InformationScreen->>InformationViewModel: onAgeChanged(input)
    InformationViewModel->>InformationUiState: 숫자 필터링 후 age 업데이트
    InformationViewModel-->>InformationScreen: uiState 방출 (buttonEnabled 계산)

    User->>InformationScreen: "다음" 버튼 클릭
    InformationScreen->>InformationViewModel: onNextClicked()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • 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 PR의 변경사항은 이슈 #44 '정보입력뷰 구현'의 목표를 충족합니다. ViewModel, UiState, Screen 컴포저블, VisualTransformation 확장 및 CherrishTextField 개선을 통해 완전한 정보 입력 화면을 구현했습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 정보 입력 화면 구현이라는 링크된 이슈 목표와 직접 관련되어 있으며, 범위를 벗어난 변경사항은 없습니다.

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

✨ Finishing touches
  • 📝 Generate docstrings


📜 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 7274c2d and ec7581d.

📒 Files selected for processing (2)
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationUiState.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationUiState.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.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

✏️ 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.

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/onboarding/information/extensioin/AgeSuffixTransformation.kt:
- Line 1: The package declaration in AgeSuffixTransformation.kt uses a typo
"extensioin" instead of "extension"; update the package line to use "extension",
rename the source directory from "extensioin" to "extension", and update any
imports or references across the project that point to
com.cherrish.android.presentation.onboarding.information.extensioin to the
corrected com.cherrish.android.presentation.onboarding.information.extension so
that AgeSuffixTransformation and related classes compile correctly.
🧹 Nitpick comments (4)
app/src/main/java/com/cherrish/android/presentation/onboarding/information/extensioin/AgeSuffixTransformation.kt (1)

16-16: 불필요한 전체 경로 제거

AnnotatedString이 이미 import되어 있으므로 fully qualified name이 필요하지 않습니다.

♻️ 수정 제안
-        val transformed = androidx.compose.ui.text.AnnotatedString(text.text + suffix)
+        val transformed = AnnotatedString(text.text + suffix)
app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationViewModel.kt (1)

29-31: TODO 주석 확인

다음 화면 이동 로직이 미구현 상태입니다. 추후 네비게이션 로직 구현 시 도움이 필요하시면 말씀해주세요.

app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt (2)

96-109: AgeSuffixTransformation을 remember로 감싸는 것을 권장

현재 구현은 recomposition마다 새 AgeSuffixTransformation 인스턴스를 생성합니다. 불필요한 객체 할당을 방지하려면 remember를 사용하세요.

♻️ 수정 제안

InformationScreen 내부에서:

val ageSuffixTransformation = remember { AgeSuffixTransformation("") }

그리고 사용처에서:

         UserInfoTextField(
             ...
-            visualTransformation = AgeSuffixTransformation(" 세"),
+            visualTransformation = ageSuffixTransformation,
             ...
         )

170-191: 불필요한 Row 래퍼 검토

Row 내부에 CherrishTextField 하나만 있습니다. 향후 다른 요소(예: suffix 텍스트)를 추가할 계획이 아니라면 Row를 제거하여 불필요한 레이아웃 depth를 줄일 수 있습니다.

♻️ 수정 제안
-        Row(
-            modifier = Modifier.fillMaxWidth(),
-            verticalAlignment = Alignment.CenterVertically,
-            horizontalArrangement = Arrangement.spacedBy(8.dp)
-        ) {
-            CherrishTextField(
-                value = value,
-                onValueChange = onValueChange,
-                roundedCornerShape = RoundedCornerShape(10.dp),
-                placeholder = placeholder,
-                placeholderTextStyle = CherrishTheme.typography.body1R14,
-                inputTextStyle = CherrishTheme.typography.body1M14,
-                inputTextColor = CherrishTheme.colors.gray1000,
-                paddingValues = PaddingValues(horizontal = 16.dp, vertical = 10.dp),
-                keyboardImeAction = keyboardImeAction,
-                onNextAction = onNextAction,
-                onDoneAction = onDoneAction,
-                keyboardType = keyboardType,
-                visualTransformation = visualTransformation,
-                modifier = Modifier.fillMaxWidth()
-            )
-        }
+        CherrishTextField(
+            value = value,
+            onValueChange = onValueChange,
+            roundedCornerShape = RoundedCornerShape(10.dp),
+            placeholder = placeholder,
+            placeholderTextStyle = CherrishTheme.typography.body1R14,
+            inputTextStyle = CherrishTheme.typography.body1M14,
+            inputTextColor = CherrishTheme.colors.gray1000,
+            paddingValues = PaddingValues(horizontal = 16.dp, vertical = 10.dp),
+            keyboardImeAction = keyboardImeAction,
+            onNextAction = onNextAction,
+            onDoneAction = onDoneAction,
+            keyboardType = keyboardType,
+            visualTransformation = visualTransformation,
+            modifier = Modifier.fillMaxWidth()
+        )
📜 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 55d8c29 and 6c2e685.

📒 Files selected for processing (5)
  • app/src/main/java/com/cherrish/android/core/designsystem/component/textfield/CherrishTextField.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationUiState.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationViewModel.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/extensioin/AgeSuffixTransformation.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/component/textfield/CherrishTextField.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationViewModel.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationUiState.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/extensioin/AgeSuffixTransformation.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/onboarding/information/InformationScreen.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationViewModel.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationUiState.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/extensioin/AgeSuffixTransformation.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt (3)
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/component/textfield/CherrishTextField.kt (1)
  • CherrishTextField (30-90)
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 (6)
app/src/main/java/com/cherrish/android/core/designsystem/component/textfield/CherrishTextField.kt (1)

45-55: LGTM!

visualTransformation 파라미터 추가가 깔끔하게 구현되었습니다. 기본값으로 VisualTransformation.None을 사용하여 기존 사용처에 영향을 주지 않으면서 확장성을 제공합니다.

app/src/main/java/com/cherrish/android/presentation/onboarding/information/extensioin/AgeSuffixTransformation.kt (1)

11-24: VisualTransformation 구현 LGTM

offset mapping 로직이 올바르게 구현되었습니다. suffix가 끝에 추가되므로 originalToTransformed는 1:1 매핑, transformedToOriginal은 원본 길이로 clamp하여 커서 위치가 suffix 영역으로 이동하는 것을 방지합니다.

app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationViewModel.kt (1)

11-27: LGTM! 단방향 데이터 흐름 패턴 준수

ViewModel이 Google 권장 아키텍처를 잘 따르고 있습니다:

  • MutableStateFlow + asStateFlow()로 상태 캡슐화
  • update { } 사용으로 스레드 안전한 상태 업데이트
  • 나이 입력에 숫자만 허용하는 필터링 로직 적절
app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt (2)

36-52: LGTM! Route-Screen 분리 패턴 준수

InformationRoute가 ViewModel과 상태 수집을 담당하고, InformationScreen은 순수 UI 컴포저블로 분리되어 테스트와 Preview가 용이합니다. collectAsStateWithLifecycle() 사용도 적절합니다.


69-74: paddingValues 적용 순서 적절

Based on learnings, paddingValues가 root container에 먼저 적용되어 시스템 바(status/navigation bar)와의 레이아웃 겹침을 올바르게 처리합니다.

app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationUiState.kt (1)

5-12: LGTM! @immutable 어노테이션과 data class 조합 적절

@Immutable 어노테이션으로 Compose가 이 클래스를 안정적(stable)으로 인식하여 불필요한 recomposition을 방지합니다. buttonEnabled computed property는 간단한 로직이므로 현재 구현이 적절합니다.

@@ -0,0 +1,26 @@
package com.cherrish.android.presentation.onboarding.information.extensioin
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Jan 13, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

패키지명 오타 수정 필요

extensioinextension으로 수정해야 합니다.

🔧 수정 제안
-package com.cherrish.android.presentation.onboarding.information.extensioin
+package com.cherrish.android.presentation.onboarding.information.extension

디렉토리명도 함께 변경해주세요.

📝 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
package com.cherrish.android.presentation.onboarding.information.extensioin
package com.cherrish.android.presentation.onboarding.information.extension
🤖 Prompt for AI Agents
In
@app/src/main/java/com/cherrish/android/presentation/onboarding/information/extensioin/AgeSuffixTransformation.kt
at line 1, The package declaration in AgeSuffixTransformation.kt uses a typo
"extensioin" instead of "extension"; update the package line to use "extension",
rename the source directory from "extensioin" to "extension", and update any
imports or references across the project that point to
com.cherrish.android.presentation.onboarding.information.extensioin to the
corrected com.cherrish.android.presentation.onboarding.information.extension so
that AgeSuffixTransformation and related classes compile correctly.

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

Choose a reason for hiding this comment

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

@sohee6989, 감사합니다! 😊

૮ ˶ᵔ ᵕ ᵔ˶ ა

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

Choose a reason for hiding this comment

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

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!

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/onboarding/information/InformationScreen.kt:
- Around line 145-193: UserInfoTextField currently applies the incoming modifier
to the outer Column, so focusRequester passed from callers (e.g.,
ageFocusRequester) never reaches the actual focusable CherrishTextField; add a
new parameter (e.g., textFieldModifier: Modifier = Modifier) to
UserInfoTextField and use that modifier on the CherrishTextField instance
(instead of the hardcoded Modifier.fillMaxWidth()), keep the existing modifier
for the Column, and update all call sites to pass Modifier.focusRequester(...)
via the new textFieldModifier so focus requests target the TextField itself.
🧹 Nitpick comments (3)
app/src/main/java/com/cherrish/android/presentation/onboarding/information/extension/AgeSuffixTransformation.kt (1)

16-16: 불필요한 정규화된 클래스명 사용

AnnotatedString은 이미 3번 라인에서 import되어 있으므로, 정규화된 이름 대신 직접 사용할 수 있습니다.

♻️ 제안된 수정
-        val transformed = androidx.compose.ui.text.AnnotatedString(text.text + suffix)
+        val transformed = AnnotatedString(text.text + suffix)
app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt (2)

69-75: paddingValues 적용 순서 확인 필요

Retrieved learnings에 따르면, paddingValues는 시스템 바(상태바/내비게이션바)를 올바르게 처리하기 위해 root container의 modifier에 먼저 적용되어야 합니다. 현재 구현에서는 fillMaxSize(), background(), addFocusCleaner() 이후에 적용되어 있습니다.

♻️ 제안된 수정
     Column(
         modifier = modifier
+            .padding(paddingValues = paddingValues)
             .fillMaxSize()
             .background(color = CherrishTheme.colors.gray0)
             .addFocusCleaner(focusManager)
-            .padding(paddingValues = paddingValues)
     ) {

Based on learnings, paddingValues를 먼저 적용하면 Scaffold의 insets 처리가 일관되게 유지됩니다.


76-76: 매직 넘버를 상수로 추출하는 것을 고려해보세요

Spacer의 weight 값들(135f, 70f, 30f, 200f)이 여러 곳에서 사용되고 있습니다. 이러한 값들을 의미 있는 이름의 상수로 추출하면 레이아웃 의도를 더 명확하게 전달할 수 있습니다.

📜 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 380a410 and 0673a5b.

📒 Files selected for processing (2)
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/extension/AgeSuffixTransformation.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/onboarding/information/extension/AgeSuffixTransformation.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.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/onboarding/information/extension/AgeSuffixTransformation.kt
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt (3)
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/component/textfield/CherrishTextField.kt (1)
  • CherrishTextField (30-90)
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/onboarding/information/extension/AgeSuffixTransformation.kt (1)

8-25: LGTM! VisualTransformation 구현이 올바릅니다.

OffsetMapping 구현이 적절합니다. transformedToOriginal에서 coerceAtMost를 사용하여 커서가 suffix 영역으로 이동하는 것을 방지하고, 빈 텍스트 케이스도 잘 처리되어 있습니다.

app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt (4)

36-52: LGTM! Route 패턴이 올바르게 구현되었습니다.

collectAsStateWithLifecycle()을 사용한 상태 수집과 단방향 데이터 흐름 패턴이 잘 적용되어 있습니다.


65-67: LGTM! 포커스 관리 구현이 적절합니다.

FocusRequesterLocalSoftwareKeyboardController를 사용한 포커스 및 키보드 관리가 올바르게 구현되어 있습니다.


124-143: LGTM! 간결한 헤더 컴포넌트입니다.

상태가 없는 깔끔한 구현입니다. 향후 다국어 지원이 필요하다면 문자열 리소스로 추출하는 것을 고려해보세요.


195-209: LGTM! 프리뷰가 올바르게 구현되었습니다.

기본 상태의 프리뷰가 제공됩니다. 선택적으로 입력된 상태나 비활성화 상태의 프리뷰를 추가하면 디자인 검토에 도움이 될 수 있습니다.

Comment on lines +145 to +193
@Composable
private fun UserInfoTextField(
textFieldName: String,
value: String,
onValueChange: (String) -> Unit,
placeholder: String,
keyboardImeAction: ImeAction,
keyboardType: KeyboardType,
modifier: Modifier = Modifier,
onNextAction: () -> Unit = {},
onDoneAction: () -> Unit = {},
visualTransformation: VisualTransformation = VisualTransformation.None
) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = 26.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = textFieldName,
style = CherrishTheme.typography.body1SB14,
color = CherrishTheme.colors.gray1000
)

Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
CherrishTextField(
value = value,
onValueChange = onValueChange,
roundedCornerShape = RoundedCornerShape(10.dp),
placeholder = placeholder,
placeholderTextStyle = CherrishTheme.typography.body1R14,
inputTextStyle = CherrishTheme.typography.body1M14,
inputTextColor = CherrishTheme.colors.gray1000,
paddingValues = PaddingValues(horizontal = 16.dp, vertical = 10.dp),
keyboardImeAction = keyboardImeAction,
onNextAction = onNextAction,
onDoneAction = onDoneAction,
keyboardType = keyboardType,
visualTransformation = visualTransformation,
modifier = Modifier.fillMaxWidth()
)
}
}
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Jan 13, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the full UserInfoTextField function and its call sites
fd -t f "InformationScreen.kt" && cat -n "app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt" | head -250 | tail -150

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 5744


🏁 Script executed:

# Search for all UserInfoTextField calls and focusRequester usage in the file
rg -n "UserInfoTextField|focusRequester" "app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt" -C 2

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 980


🏁 Script executed:

# Check CherrishTextField implementation to understand how it handles modifiers
fd -t f "CherrishTextField" && fd -t f "CherrishTextField.kt" -x cat -n {}

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 4994


🏁 Script executed:

# Look for similar focusRequester patterns in other Compose files
rg -n "focusRequester.*modifier|modifier.*focusRequester" --type=kotlin -C 2

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 764


focusRequester가 TextField가 아닌 Column에 적용됩니다

라인 108에서 Modifier.focusRequester(ageFocusRequester)를 전달하면, UserInfoTextFieldmodifier 파라미터로 수신되어 라인 159의 외부 Column에 적용됩니다. 그러나 라인 189의 CherrishTextField는 이 modifier를 받지 않고 오직 Modifier.fillMaxWidth()만 받습니다.

CherrishTextField의 내부 구현(라인 56)을 보면, 전달받은 modifier를 BasicTextField에 직접 적용하므로, focusRequester가 실제 focusable 컴포넌트에 도달하려면 CherrishTextField에 전달되어야 합니다. 현재 구조에서는 focusRequester가 비-focusable인 Column에만 적용되어 포커스 요청이 올바르게 동작하지 않습니다.

🐛 제안된 수정

textFieldModifier 파라미터를 추가하여 TextField에 직접 포커스 modifier를 전달:

@Composable
private fun UserInfoTextField(
    textFieldName: String,
    value: String,
    onValueChange: (String) -> Unit,
    placeholder: String,
    keyboardImeAction: ImeAction,
    keyboardType: KeyboardType,
    modifier: Modifier = Modifier,
+    textFieldModifier: Modifier = Modifier,
    onNextAction: () -> Unit = {},
    onDoneAction: () -> Unit = {},
    visualTransformation: VisualTransformation = VisualTransformation.None
) {
    Column(
        modifier = modifier
             .fillMaxWidth()
             .padding(horizontal = 26.dp),
         verticalArrangement = Arrangement.spacedBy(8.dp)
     ) {
         // ...
         CherrishTextField(
             // ... other params
-            modifier = Modifier.fillMaxWidth()
+            modifier = textFieldModifier.fillMaxWidth()
         )
     }
}

그리고 호출부에서:

UserInfoTextField(
    textFieldName = "나이",
    value = age,
    onValueChange = onAgeChange,
    placeholder = "20",
    keyboardImeAction = ImeAction.Done,
    onDoneAction = {
        keyboardController?.hide()
        focusManager.clearFocus()
    },
    keyboardType = KeyboardType.Number,
    visualTransformation = AgeSuffixTransformation(" 세"),
-    modifier = Modifier.focusRequester(ageFocusRequester)
+    textFieldModifier = Modifier.focusRequester(ageFocusRequester)
)
🤖 Prompt for AI Agents
In
@app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt
around lines 145 - 193, UserInfoTextField currently applies the incoming
modifier to the outer Column, so focusRequester passed from callers (e.g.,
ageFocusRequester) never reaches the actual focusable CherrishTextField; add a
new parameter (e.g., textFieldModifier: Modifier = Modifier) to
UserInfoTextField and use that modifier on the CherrishTextField instance
(instead of the hardcoded Modifier.fillMaxWidth()), keep the existing modifier
for the Column, and update all call sites to pass Modifier.focusRequester(...)
via the new textFieldModifier so focus requests target the TextField itself.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@sohee6989, 확인해주셔서 감사합니다! 실제로 잘 작동한다면 현재 구현 그대로 유지하시면 됩니다. 👍

Compose의 포커스 시스템이 부모 컨테이너에 적용된 focusRequester를 하위의 focusable 컴포넌트까지 전달해주는 것으로 보입니다.


🧠 Learnings used
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.

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.

고생햇어요 !!! 아까 전달햇던거랑 코드리뷰 한번만 확인 부탁드릴게용 ㅎㅎㅎ 언니짱

paddingValues: PaddingValues,
username: String,
onNameChange: (String) -> Unit,
age: 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.

P1 : 요거 나이 Int가 아닌 String으로 받으실 예정인가용 ?!

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.

맞습니다! 입력 단계에서는 onValueChange 특성상 String으로 받고 나중에 서버에서 int로 받게되면 매퍼로 그 부분 처리 예정입니다!

style = CherrishTheme.typography.title1SB18,
color = CherrishTheme.colors.gray1000
)

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 : 요거 텍스트 사이 간격 4.dp 잇을거 가타유 ..!!!

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.

넵!

Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.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.

얜 오디서 나온아이지...?!?!

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.

스크린샷 2026-01-14 오전 1 45 50

이 부분이요!

Comment on lines +170 to +173
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.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 : 이 Row로 안묶어줘도 대지 않나용 !?!? Row로 묶으신 이유가 잇으실까용 ?!?!

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

@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/onboarding/information/InformationScreen.kt:
- Around line 119-124: The Column-level modifier is receiving the focusRequester
(ageFocusRequester) so focus requests target the container rather than the
actual text input; update UserInfoTextField to accept a new textFieldModifier:
Modifier parameter and pass that modifier into the internal CherrishTextField
(where BasicTextField is) instead of applying it to the Column, move the
.onFocusChanged handling to that CherrishTextField so isAgeFocused tracks the
real text field focus, and update callers (where ageFocusRequester is used) to
pass Modifier.focusRequester(ageFocusRequester) as textFieldModifier.
🧹 Nitpick comments (3)
app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt (3)

74-80: paddingValues 적용 순서를 확인하세요.

현재 background 이후에 paddingValues가 적용되어 배경색이 시스템 바 영역까지 확장됩니다. 학습된 패턴에 따르면 Scaffold의 paddingValues는 루트 컨테이너에 먼저 적용하는 것이 권장됩니다.

만약 전체 화면 배경(full-bleed)이 의도된 디자인이라면 현재 순서가 맞습니다. 그렇지 않다면 아래와 같이 순서를 조정하세요.

♻️ 시스템 바 내부에만 배경을 적용하려면
     Column(
         modifier = modifier
             .fillMaxSize()
+            .padding(paddingValues = paddingValues)
             .background(color = CherrishTheme.colors.gray0)
             .addFocusCleaner(focusManager)
-            .padding(paddingValues = paddingValues)
     ) {

Based on learnings, paddingValues should be applied to the root container first for consistent insets handling.


185-206: 불필요한 Row wrapper를 제거할 수 있습니다.

Row 내부에 CherrishTextField 하나만 존재하므로 Row wrapper가 불필요합니다. Arrangement.spacedBy(8.dp)도 단일 요소에서는 효과가 없습니다.

♻️ Row 제거 제안
-        Row(
-            modifier = Modifier.fillMaxWidth(),
-            verticalAlignment = Alignment.CenterVertically,
-            horizontalArrangement = Arrangement.spacedBy(8.dp)
-        ) {
-            CherrishTextField(
-                value = value,
-                onValueChange = onValueChange,
-                roundedCornerShape = RoundedCornerShape(10.dp),
-                placeholder = placeholder,
-                placeholderTextStyle = CherrishTheme.typography.body1R14,
-                inputTextStyle = CherrishTheme.typography.body1M14,
-                inputTextColor = CherrishTheme.colors.gray1000,
-                paddingValues = PaddingValues(horizontal = 16.dp, vertical = 10.dp),
-                keyboardImeAction = keyboardImeAction,
-                onNextAction = onNextAction,
-                onDoneAction = onDoneAction,
-                keyboardType = keyboardType,
-                visualTransformation = visualTransformation,
-                modifier = Modifier.fillMaxWidth()
-            )
-        }
+        CherrishTextField(
+            value = value,
+            onValueChange = onValueChange,
+            roundedCornerShape = RoundedCornerShape(10.dp),
+            placeholder = placeholder,
+            placeholderTextStyle = CherrishTheme.typography.body1R14,
+            inputTextStyle = CherrishTheme.typography.body1M14,
+            inputTextColor = CherrishTheme.colors.gray1000,
+            paddingValues = PaddingValues(horizontal = 16.dp, vertical = 10.dp),
+            keyboardImeAction = keyboardImeAction,
+            onNextAction = onNextAction,
+            onDoneAction = onDoneAction,
+            keyboardType = keyboardType,
+            visualTransformation = visualTransformation,
+            modifier = Modifier.fillMaxWidth()
+        )

210-224: Preview 함수 네이밍을 더 명확하게 변경하는 것을 고려하세요.

Preview()보다 InformationScreenPreview()와 같이 구체적인 이름을 사용하면 IDE에서 여러 Preview를 구분하기 쉬워집니다.

♻️ 네이밍 개선 제안
 @Preview(showBackground = true)
 @Composable
-private fun Preview() {
+private fun InformationScreenPreview() {
📜 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 0673a5b and 7274c2d.

📒 Files selected for processing (1)
  • app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.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/onboarding/information/InformationScreen.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/onboarding/information/InformationScreen.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt (3)
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/component/textfield/CherrishTextField.kt (1)
  • CherrishTextField (30-90)
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/onboarding/information/InformationScreen.kt (2)

39-55: LGTM!

hiltViewModel()collectAsStateWithLifecycle을 사용하여 단방향 데이터 흐름 패턴을 올바르게 구현했습니다. 상태와 이벤트 핸들러가 적절히 분리되어 있습니다.


139-158: LGTM!

CherrishTheme의 typography와 color를 올바르게 사용하는 깔끔한 stateless composable입니다.

Comment on lines +119 to +124
modifier = Modifier
.focusRequester(ageFocusRequester)
.onFocusChanged { state ->
isAgeFocused = state.isFocused
}
)
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 | 🟠 Major

focusRequester가 Column에 적용되어 포커스 요청이 동작하지 않을 수 있습니다.

현재 modifierUserInfoTextFieldColumn에 적용되고 있습니다 (line 174). FocusRequester는 포커스 가능한 요소(BasicTextField)에 직접 적용되어야 합니다. 이로 인해 이름 필드에서 Next 키보드 액션 시 나이 필드로 포커스가 이동하지 않을 수 있습니다.

🐛 UserInfoTextField 수정 제안

UserInfoTextFieldtextFieldModifier 파라미터를 추가하여 CherrishTextField에 직접 적용하세요:

 @Composable
 private fun UserInfoTextField(
     textFieldName: String,
     value: String,
     onValueChange: (String) -> Unit,
     placeholder: String,
     keyboardImeAction: ImeAction,
     keyboardType: KeyboardType,
     modifier: Modifier = Modifier,
+    textFieldModifier: Modifier = Modifier,
     onNextAction: () -> Unit = {},
     onDoneAction: () -> Unit = {},
     visualTransformation: VisualTransformation = VisualTransformation.None
 ) {
     // ... Column with modifier ...
             CherrishTextField(
                 // ... other params ...
-                modifier = Modifier.fillMaxWidth()
+                modifier = textFieldModifier.fillMaxWidth()
             )

호출부 수정:

         UserInfoTextField(
             textFieldName = "나이",
             // ... other params ...
-            modifier = Modifier
+            textFieldModifier = Modifier
                 .focusRequester(ageFocusRequester)
                 .onFocusChanged { state ->
                     isAgeFocused = state.isFocused
                 }
         )
🤖 Prompt for AI Agents
In
@app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt
around lines 119 - 124, The Column-level modifier is receiving the
focusRequester (ageFocusRequester) so focus requests target the container rather
than the actual text input; update UserInfoTextField to accept a new
textFieldModifier: Modifier parameter and pass that modifier into the internal
CherrishTextField (where BasicTextField is) instead of applying it to the
Column, move the .onFocusChanged handling to that CherrishTextField so
isAgeFocused tracks the real text field focus, and update callers (where
ageFocusRequester is used) to pass Modifier.focusRequester(ageFocusRequester) as
textFieldModifier.

@sohee6989 sohee6989 requested a review from nhyeonii January 13, 2026 17:05
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.

수고하셨습니다 !! 코멘트 하나만 확인해주세요용용용가리

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.

LGTM ~~ 🚀🚀🚀🚀🚀 어푸푸잉

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.

좋아요~~~~ 궁금한 것 답변해주시면 감사하겠습니다 ! !

@sohee6989 sohee6989 merged commit 284b68d into develop Jan 15, 2026
3 checks passed
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