Conversation
Walkthrough새로운 로그인 어르신 프로모션 코드 입력 화면이 추가됩니다. 화면 UI, ViewModel, 상태 관리, 그리고 내비게이션 통합이 포함되어 있습니다. 사용자는 8자 대문자/숫자 형식의 코드를 입력하고, 확인 버튼 클릭 시 다이얼로그가 표시됩니다. Changes
Sequence DiagramsequenceDiagram
participant User
participant Screen as LoginElderPromotionScreen
participant ViewModel as LoginElderPromotionViewModel
participant Navigation
User->>Screen: 프로모션 코드 입력
Screen->>ViewModel: onPromotionCodeChange(code)
ViewModel->>ViewModel: inputValue 업데이트
User->>Screen: 확인 버튼 클릭
Screen->>ViewModel: onConfirm()
ViewModel->>ViewModel: showDialog = true
ViewModel-->>Screen: uiState 업데이트
Screen->>Screen: Dialog 표시
User->>Screen: 확인 버튼 클릭 (Dialog)
Screen->>ViewModel: onDismissRequest()
ViewModel->>ViewModel: showDialog = false
Screen->>Navigation: navigateToElderRegister()
Navigation->>Navigation: 어르신 등록 화면으로 이동
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/navigation/Route.kt (1)
35-36: 포맷팅 일관성 확인 필요다른 Route들은
Splash : Route처럼 콜론 앞뒤에 공백이 있는데,LoginPromotion: Route는 콜론 뒤에만 공백이 없습니다. 기존 스타일과 일관성을 맞추는 것이 좋겠습니다.♻️ 제안된 수정
`@Serializable` - data object LoginPromotion: Route + data object LoginPromotion : Route🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/navigation/Route.kt` around lines 35 - 36, The declaration for the serializable route is inconsistent with the project's spacing style; update the data object declaration for LoginPromotion so the colon has spaces on both sides like the other routes (change "LoginPromotion: Route" to "LoginPromotion : Route") while preserving the `@Serializable` annotation and the data object keyword to match the style used by other Route declarations.composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/viewmodel/LoginElderPromotionViewModel.kt (2)
14-16: 입력값 검증 고려UI에서는
^[A-Z0-9]{8}$정규식으로 버튼 활성화를 제어하지만, ViewModel에서는 입력값에 대한 검증이 없습니다.입력을 대문자로 변환하거나 최대 길이를 제한하는 로직을 ViewModel에서 처리하면 UI와 비즈니스 로직의 분리가 더 명확해집니다.
♻️ 선택적 개선안
fun onPromotionCodeChange(value: String) { - _uiState.update { it.copy(inputValue = value) } + val sanitized = value.uppercase().take(8) + _uiState.update { it.copy(inputValue = sanitized) } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/viewmodel/LoginElderPromotionViewModel.kt` around lines 14 - 16, onPromotionCodeChange currently just stores raw input; update it in LoginElderPromotionViewModel to normalize and validate input: convert value to uppercase, trim and cap to 8 characters, then update _uiState with the processed inputValue and a validity flag computed against the regex ^[A-Z0-9]{8}$ (or set isValid true only when it matches); keep normalization/validation inside onPromotionCodeChange so UI stays presentation-only and business rules live in the ViewModel.
18-21: 프로모션 검증 로직 누락TODO 주석에서 언급된 대로 프로모션 검증 로직이 없습니다. 현재
onConfirm()은 실제 검증 없이 바로 성공 다이얼로그를 표시합니다.실제 프로모션 코드 검증(API 호출 등)이 추가될 때까지 사용자에게 잘못된 피드백을 줄 수 있습니다. 검증 실패 케이스에 대한 UI 처리도 고려해 주세요.
프로모션 검증 로직 구현을 위한 이슈를 생성해 드릴까요?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/viewmodel/LoginElderPromotionViewModel.kt` around lines 18 - 21, onConfirm currently skips promotion validation and immediately sets _uiState to showDialog=true; implement actual validation: call or create a validation method (e.g., verifyPromotionCode or validatePromotion) from onConfirm (handle as suspend if using coroutines), set a loading flag on _uiState while awaiting the result, and on success update _uiState.copy(showDialog=true) but on failure update _uiState to reflect the error (e.g., showDialog=false plus errorMessage or showError flag) so the UI can display failure feedback; remove the TODO and ensure error and loading state fields exist/are used in the same ViewModel (referencing onConfirm, _uiState and showDialog).composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/screen/LoginElderPromotionScreen.kt (1)
105-110: Regex 객체 재생성 최적화
"^[A-Z0-9]{8}\$".toRegex()가 매 recomposition마다 새로 생성됩니다.remember를 사용하거나 companion object에 정의하여 불필요한 객체 생성을 방지하는 것이 좋습니다.♻️ 제안된 수정
Layout 함수 상단에 추가:
val promotionCodePattern = remember { "^[A-Z0-9]{8}$".toRegex() }그리고 사용처에서:
CTAButton( - if (uiState.inputValue.matches("^[A-Z0-9]{8}\$".toRegex())) CTAButtonType.GREEN + if (uiState.inputValue.matches(promotionCodePattern)) CTAButtonType.GREEN else CTAButtonType.DISABLED, text = "확인", onClick = { onConfirm() }, )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/screen/LoginElderPromotionScreen.kt` around lines 105 - 110, The inline regex "^[A-Z0-9]{8}\$".toRegex() is recreated on every recomposition; inside the LoginElderPromotionScreen composable define a single reusable Regex (e.g., val promotionCodePattern = remember { "^[A-Z0-9]{8}$".toRegex() } at the top of the composable) and replace the inline call in the CTAButton condition with promotionCodePattern.matches(uiState.inputValue); alternatively, if you need a static/global instance, move the Regex into a companion object or top-level constant and reference that instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/screen/LoginElderPromotionScreen.kt`:
- Around line 141-152: The "확인" button only calls navigateToElderRegister(),
leaving the dialog state open; update the click handler on the Box in
LoginElderPromotionScreen (the clickable that currently invokes
navigateToElderRegister()) to first call onDismissRequest() to set showDialog =
false and then call navigateToElderRegister(), ensuring the dialog is closed
before navigation to avoid backstack issues.
In
`@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/navigation/LoginNavigation.kt`:
- Line 69: The parameter navigateToPromotion is declared on the loginNavGraph
function signature but never used inside loginNavGraph and is not passed to
LoginElderPromotionScreen; remove the unused parameter from the loginNavGraph
signature and any corresponding callers, and update any references to the
navigateToPromotion symbol so callers no longer supply it (ensure
LoginElderPromotionScreen usages remain unchanged).
---
Nitpick comments:
In
`@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/screen/LoginElderPromotionScreen.kt`:
- Around line 105-110: The inline regex "^[A-Z0-9]{8}\$".toRegex() is recreated
on every recomposition; inside the LoginElderPromotionScreen composable define a
single reusable Regex (e.g., val promotionCodePattern = remember {
"^[A-Z0-9]{8}$".toRegex() } at the top of the composable) and replace the inline
call in the CTAButton condition with
promotionCodePattern.matches(uiState.inputValue); alternatively, if you need a
static/global instance, move the Regex into a companion object or top-level
constant and reference that instead.
In
`@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/viewmodel/LoginElderPromotionViewModel.kt`:
- Around line 14-16: onPromotionCodeChange currently just stores raw input;
update it in LoginElderPromotionViewModel to normalize and validate input:
convert value to uppercase, trim and cap to 8 characters, then update _uiState
with the processed inputValue and a validity flag computed against the regex
^[A-Z0-9]{8}$ (or set isValid true only when it matches); keep
normalization/validation inside onPromotionCodeChange so UI stays
presentation-only and business rules live in the ViewModel.
- Around line 18-21: onConfirm currently skips promotion validation and
immediately sets _uiState to showDialog=true; implement actual validation: call
or create a validation method (e.g., verifyPromotionCode or validatePromotion)
from onConfirm (handle as suspend if using coroutines), set a loading flag on
_uiState while awaiting the result, and on success update
_uiState.copy(showDialog=true) but on failure update _uiState to reflect the
error (e.g., showDialog=false plus errorMessage or showError flag) so the UI can
display failure feedback; remove the TODO and ensure error and loading state
fields exist/are used in the same ViewModel (referencing onConfirm, _uiState and
showDialog).
In
`@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/navigation/Route.kt`:
- Around line 35-36: The declaration for the serializable route is inconsistent
with the project's spacing style; update the data object declaration for
LoginPromotion so the colon has spaces on both sides like the other routes
(change "LoginPromotion: Route" to "LoginPromotion : Route") while preserving
the `@Serializable` annotation and the data object keyword to match the style used
by other Route declarations.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3a7dd488-ae7b-4957-8912-0c24fca04ac4
📒 Files selected for processing (8)
composeApp/src/commonMain/composeResources/drawable/ic_check_green.xmlcomposeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/screen/LoginElderPromotionScreen.ktcomposeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/viewmodel/LoginElderPromotionUiState.ktcomposeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/viewmodel/LoginElderPromotionViewModel.ktcomposeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/navigation/LoginNavigation.ktcomposeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/navigation/MainNavigator.ktcomposeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/navigation/NavGraph.ktcomposeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/navigation/Route.kt
| Box( | ||
| Modifier.fillMaxWidth() | ||
| .clip(RoundedCornerShape(14.dp)) | ||
| .background(G500) | ||
| .clickable { navigateToElderRegister() }, | ||
| contentAlignment = Alignment.Center, | ||
| ) { | ||
| Text( | ||
| "확인", color = White, style = MediCareCallTheme.typography.B_17, | ||
| modifier = Modifier.padding(vertical = 14.dp), | ||
| ) | ||
| } |
There was a problem hiding this comment.
다이얼로그 닫기 후 네비게이션 처리
다이얼로그의 "확인" 버튼 클릭 시 navigateToElderRegister()만 호출하고 onDismissRequest()를 호출하지 않습니다. 네비게이션 후에도 showDialog가 true로 남아있어 백스택 관련 이슈가 발생할 수 있습니다.
🐛 제안된 수정
Box(
Modifier.fillMaxWidth()
.clip(RoundedCornerShape(14.dp))
.background(G500)
- .clickable { navigateToElderRegister() },
+ .clickable {
+ onDismissRequest()
+ navigateToElderRegister()
+ },
contentAlignment = Alignment.Center,
)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/elder/screen/LoginElderPromotionScreen.kt`
around lines 141 - 152, The "확인" button only calls navigateToElderRegister(),
leaving the dialog state open; update the click handler on the Box in
LoginElderPromotionScreen (the clickable that currently invokes
navigateToElderRegister()) to first call onDismissRequest() to set showDialog =
false and then call navigateToElderRegister(), ensuring the dialog is closed
before navigation to avoid backstack issues.
| navigateToRegisterElderHealth: () -> Unit, | ||
| navigateToCareCallSetting: () -> Unit, | ||
| navigateToCareCallSettingWithPopUpTo: () -> Unit, | ||
| navigateToPromotion: () -> Unit, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: navigateToPromotion이 실제로 사용되는 곳이 있는지 확인
rg -n "navigateToPromotion" --type=kotlinRepository: Medicare-Call/Medicare-Call-KMP
Length of output: 376
🏁 Script executed:
cat -n composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/navigation/LoginNavigation.kt | sed -n '50,160p'Repository: Medicare-Call/Medicare-Call-KMP
Length of output: 4604
🏁 Script executed:
cat -n composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/navigation/NavGraph.kt | sed -n '120,140p'Repository: Medicare-Call/Medicare-Call-KMP
Length of output: 1477
사용되지 않는 파라미터 제거
navigateToPromotion 파라미터가 함수 시그니처에는 있지만 loginNavGraph 본문에서 전혀 사용되지 않습니다. LoginElderPromotionScreen 호출 시에도 전달되지 않고 있으니, 필요 없다면 파라미터를 제거해 주세요.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/navigation/LoginNavigation.kt`
at line 69, The parameter navigateToPromotion is declared on the loginNavGraph
function signature but never used inside loginNavGraph and is not passed to
LoginElderPromotionScreen; remove the unused parameter from the loginNavGraph
signature and any corresponding callers, and update any references to the
navigateToPromotion symbol so callers no longer supply it (ensure
LoginElderPromotionScreen usages remain unchanged).
🔗 관련 이슈
📙 작업 설명
📸 스크린샷 또는 시연 영상 (선택)
Summary by CodeRabbit
릴리스 노트