[Feature/#58] 온보딩 수정 및 감정구슬 선택 후 추천 루틴 표시 부분 구현#62
Conversation
|
""" Walkthrough온보딩 플로우 수정 및 감정구슬 선택 후 추천 루틴 표시 기능이 추가되었습니다. 온보딩 라우트가 파라미터를 받을 수 있도록 변경되었고, ViewModel은 Assisted Injection으로 생성되며, 감정구슬 선택 후 추천 루틴을 보여주는 UI와 상태 관리, 관련 도메인/데이터 모델 및 유즈케이스가 구현되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant EmotionScreen
participant EmotionViewModel
participant EmotionRepository
participant OnBoardingScreen
participant OnBoardingViewModel
User->>EmotionScreen: 감정구슬 선택
EmotionScreen->>EmotionViewModel: selectEmotion(emotion)
EmotionViewModel->>EmotionRepository: registerEmotion(emotion)
EmotionRepository-->>EmotionViewModel: Result<List<EmotionRecommendRoutine>>
EmotionViewModel->>EmotionScreen: 상태 업데이트 (추천 루틴 표시)
User->>EmotionScreen: 추천 루틴 선택/등록
EmotionScreen->>EmotionViewModel: registerRecommendRoutines()
EmotionViewModel->>...: 추천 루틴 등록 처리
EmotionViewModel->>EmotionScreen: 성공 시 뒤로 이동 SideEffect
User->>OnBoardingScreen: 온보딩 진입 (isNew or reset)
OnBoardingScreen->>OnBoardingViewModel: Assisted Injection(onBoardingArg)
OnBoardingViewModel->>OnBoardingScreen: 상태 업데이트 (SetType 등)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Assessment against linked issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionViewModel.kt (1)
145-163: 추천 루틴 등록 로직 구현 양호, 에러 처리 개선 제안선택된 추천 루틴 등록 로직이 올바르게 구현되었습니다. 다만, 실패 시 사용자 피드백이 없습니다.
에러 발생 시 사용자에게 알림을 제공하는 것을 고려해보세요:
onFailure = { sendIntent(EmotionIntent.RegisterRecommendRoutinesFailure) + // TODO: 사용자에게 에러 메시지 표시를 위한 SideEffect 추가 + // postSideEffect(EmotionSideEffect.ShowError("루틴 등록에 실패했습니다")) },presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt (1)
138-217: 새로운 추천 루틴 화면이 잘 구현되었지만 성능 개선 고려해보세요.화면 구조와 상태 관리가 적절하게 구현되었습니다. 몇 가지 개선 사항을 제안합니다:
- LazyColumn 사용 고려: 현재
Column과verticalScroll을 사용하고 있는데, 추천 루틴이 많을 경우 성능 이슈가 있을 수 있습니다.- 하드코딩된 progress 값:
progress = 1f가 하드코딩되어 있어 향후 다단계 플로우 확장시 유연성이 떨어질 수 있습니다.LazyColumn 사용 예시:
- Column( - modifier = Modifier - .weight(1f) - .verticalScroll(state = scrollState), - ) { - for (recommendRoutine in state.recommendRoutines) { - BitnagilSelectButton( - title = recommendRoutine.name, - description = recommendRoutine.description, - onClick = { onClickRoutine(recommendRoutine.id) }, - selected = recommendRoutine.selected, - modifier = Modifier.padding(bottom = 12.dp), - ) - } - } + LazyColumn( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + items(state.recommendRoutines) { recommendRoutine -> + BitnagilSelectButton( + title = recommendRoutine.name, + description = recommendRoutine.description, + onClick = { onClickRoutine(recommendRoutine.id) }, + selected = recommendRoutine.selected, + ) + } + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
app/src/main/java/com/threegap/bitnagil/MainNavHost.kt(4 hunks)app/src/main/java/com/threegap/bitnagil/Route.kt(1 hunks)core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilSelectButton.kt(2 hunks)data/src/main/java/com/threegap/bitnagil/data/emotion/model/dto/EmotionRecommendedRoutineDto.kt(2 hunks)data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt(3 hunks)data/src/main/java/com/threegap/bitnagil/data/onboarding/model/dto/OnBoardingItemDto.kt(2 hunks)domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/EmotionRecommendRoutine.kt(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/RegisterEmotionUseCase.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt(4 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionViewModel.kt(4 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionRecommendRoutineUiModel.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionScreenStep.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionIntent.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionState.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/OnBoardingScreen.kt(3 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/OnBoardingViewModel.kt(3 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingSelectTemplate.kt(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/model/OnBoardingSetType.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/model/mvi/OnBoardingState.kt(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/model/navarg/OnBoardingScreenArg.kt(1 hunks)
🧰 Additional context used
🧠 Learnings (11)
presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/model/mvi/OnBoardingState.kt (3)
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.
app/src/main/java/com/threegap/bitnagil/Route.kt (2)
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
app/src/main/java/com/threegap/bitnagil/MainNavHost.kt (1)
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionRecommendRoutineUiModel.kt (2)
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilSelectButton.kt (1)
Learnt from: l5x5l
PR: #38
File: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt:30-35
Timestamp: 2025-07-21T10:38:49.104Z
Learning: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt의 TextButton 컴포넌트는 임시로 구현된 컴포넌트로, 디자인 시스템 구현시 대체 예정입니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/OnBoardingViewModel.kt (3)
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.
presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingSelectTemplate.kt (1)
Learnt from: l5x5l
PR: #38
File: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt:30-35
Timestamp: 2025-07-21T10:38:49.104Z
Learning: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt의 TextButton 컴포넌트는 임시로 구현된 컴포넌트로, 디자인 시스템 구현시 대체 예정입니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/OnBoardingScreen.kt (1)
Learnt from: l5x5l
PR: #38
File: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt:30-35
Timestamp: 2025-07-21T10:38:49.104Z
Learning: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt의 TextButton 컴포넌트는 임시로 구현된 컴포넌트로, 디자인 시스템 구현시 대체 예정입니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt (1)
Learnt from: l5x5l
PR: #38
File: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt:30-35
Timestamp: 2025-07-21T10:38:49.104Z
Learning: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt의 TextButton 컴포넌트는 임시로 구현된 컴포넌트로, 디자인 시스템 구현시 대체 예정입니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionIntent.kt (1)
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionViewModel.kt (1)
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.
🧬 Code Graph Analysis (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionViewModel.kt (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt (1)
sendIntent(30-37)
🔇 Additional comments (41)
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionScreenStep.kt (1)
3-6: 감정 화면 단계를 명확하게 정의한 enum 클래스입니다감정 선택과 추천 루틴 표시 간의 화면 전환을 관리하기 위한 enum 클래스가 잘 정의되었습니다. 네이밍이 명확하고 구조가 간단명료합니다.
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilSelectButton.kt (2)
33-33: onClick 파라미터를 nullable로 변경하여 유연성을 제공합니다온보딩 플로우에서 상호작용이 필요없는 경우를 지원하기 위한 적절한 변경입니다.
60-70: 조건부 clickable modifier 적용이 잘 구현되었습니다let 함수를 사용하여 onClick이 null이 아닐 때만 clickable modifier를 적용하는 방식이 깔끔하고 안전합니다. 기존 기능을 유지하면서 새로운 요구사항을 잘 지원합니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/model/navarg/OnBoardingScreenArg.kt (1)
3-6: 온보딩 플로우 구분을 위한 명확한 enum 클래스입니다NEW와 RESET 두 가지 온보딩 시나리오를 명확하게 구분하는 enum 클래스가 잘 정의되었습니다. 네비게이션 인자와 UI 상태를 연결하는 역할을 효과적으로 수행할 것으로 보입니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/model/mvi/OnBoardingState.kt (2)
6-6: OnBoardingSetType import 추가새로운 온보딩 타입 지원을 위한 적절한 import 추가입니다.
21-22: 온보딩 타입을 상태에 추가하여 유연성을 확보했습니다기존 progress 계산 로직을 유지하면서 onBoardingSetType 프로퍼티를 추가하여 NEW와 RESET 온보딩 플로우를 구분할 수 있도록 했습니다. MVI 아키텍처와 Parcelable 구조를 잘 유지하고 있습니다.
app/src/main/java/com/threegap/bitnagil/Route.kt (1)
32-34: OnBoarding 라우트에 상태 정보를 추가했습니다data object에서 data class로 변경하여 isNew 파라미터를 추가한 것이 적절합니다. 기본값 true로 설정하여 기존 동작을 유지하면서 하위 호환성을 보장하고, 새로운 온보딩과 리셋 온보딩을 효과적으로 구분할 수 있습니다.
domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt (2)
4-4: 새로운 도메인 모델 import가 올바르게 추가되었습니다.EmotionRecommendRoutine 도메인 모델의 import가 적절히 추가되어 변경된 메서드 시그니처를 지원합니다.
9-9: 모든 EmotionRepository 구현체 시그니처 일관 적용 확인
EmotionRepositoryImpl(data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt:30–46)에서
suspend fun registerEmotion(emotion: Emotion): Result<List<EmotionRecommendRoutine>>로 정상 반영된 것을 확인했습니다.
추가 구현체가 없어 변경사항이 일관되게 적용되었으므로 승인합니다.domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/EmotionRecommendRoutine.kt (1)
3-7: 깔끔한 도메인 모델 구현입니다.EmotionRecommendRoutine 데이터 클래스가 도메인 레이어의 모범 사례를 따라 구현되었습니다. 불변 속성들과 명확한 네이밍이 사용되었으며, 비즈니스 로직 없이 순수한 데이터 홀더 역할을 수행합니다.
data/src/main/java/com/threegap/bitnagil/data/emotion/model/dto/EmotionRecommendedRoutineDto.kt (2)
3-3: 도메인 모델 import가 올바르게 추가되었습니다.변환 함수에서 사용할 EmotionRecommendRoutine 도메인 모델의 import가 적절히 추가되었습니다.
17-25: DTO에서 도메인 모델로의 변환 함수가 올바르게 구현되었습니다.toEmotionRecommendRoutine() 함수가 데이터 레이어와 도메인 레이어 간의 깔끔한 분리를 제공합니다. Int 타입의 recommendedRoutineId를 String으로 변환하는 것도 적절히 처리되었습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingSelectTemplate.kt (2)
28-28: nullable 클릭 핸들러로의 변경이 적절합니다.onClickItem 파라미터를 nullable로 변경하여 온보딩 플로우에서 동적으로 상호작용을 제어할 수 있게 되었습니다. 이는 온보딩 타입에 따라 버튼 클릭을 비활성화해야 하는 요구사항을 지원합니다.
62-66: 조건부 클릭 핸들러 로직이 올바르게 구현되었습니다.onClickItem이 null인 경우 BitnagilSelectButton의 onClick을 null로 설정하는 조건부 로직이 안전하게 구현되었습니다. 이를 통해 버튼 클릭을 동적으로 비활성화할 수 있습니다.
domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/RegisterEmotionUseCase.kt (2)
4-4: 새로운 도메인 모델 import가 올바르게 추가되었습니다.EmotionRecommendRoutine 도메인 모델의 import가 변경된 반환 타입을 지원하기 위해 적절히 추가되었습니다.
11-11: Use Case 반환 타입 변경이 일관성 있게 구현되었습니다.RegisterEmotionUseCase의 반환 타입이 Result에서 Result<List>으로 변경되어 리포지토리 인터페이스 변경과 일치합니다. 이제 감정 등록 후 추천 루틴 목록을 프레젠테이션 레이어로 전달할 수 있습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionRecommendRoutineUiModel.kt (1)
7-26: 구현이 잘 되어 있습니다.UI 모델 클래스의 구조가 올바르고, Parcelable 구현과 도메인 모델 매핑 팩토리 메서드가 적절하게 구현되었습니다.
selected속성의 기본값도 합리적입니다.presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionState.kt (2)
15-16: 새로운 상태 속성들이 적절히 추가되었습니다.
recommendRoutines와step속성이 멀티 스텝 감정 플로우를 지원하기 위해 적절히 추가되었고, 기본값 설정도 올바릅니다.
26-27: 계산된 속성의 구현이 올바릅니다.추천 루틴 등록 버튼 활성화 상태를 계산하는 로직이 올바르게 구현되었습니다. 선택된 루틴이 하나라도 있으면 버튼이 활성화되는 것이 적절합니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/model/OnBoardingSetType.kt (2)
5-20: 온보딩 타입 열거형이 잘 설계되었습니다.각 온보딩 시나리오(NEW, RESET)에 따른 UI 동작을 제어하는 속성들이 적절히 정의되었습니다. RESET 타입의 경우 건너뛰기와 루틴 선택이 비활성화되는 것이 비즈니스 로직상 올바른지 확인해보세요.
22-31: 매핑 함수가 올바르게 구현되었습니다.
OnBoardingScreenArg에서OnBoardingSetType으로의 매핑이 명확하고 타입 안전하게 구현되었습니다.data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt (1)
30-45: toEmotionRecommendRoutine 확장 함수 구현 확인 완료
- data/src/main/java/com/threegap/bitnagil/data/emotion/model/dto/EmotionRecommendedRoutineDto.kt:
toEmotionRecommendRoutine()확장 함수가 올바르게 구현되어 있습니다.반환 타입 변경과 추천 루틴 처리 로직 모두 기대한 대로 작동하므로 이 변경사항을 승인합니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/OnBoardingScreen.kt (2)
92-105: 조건부 UI 제어가 올바르게 구현되었습니다.
OnBoardingSetType의 속성에 따라 동적으로 서브텍스트, 아이템 클릭, 건너뛰기 콜백을 제어하는 로직이 적절히 구현되었습니다. null 콜백을 통한 기능 비활성화 방식도 올바릅니다.
134-141: 미리보기가 업데이트된 구조를 반영합니다.새로운
OnBoardingItem데이터와OnBoardingSetType.RESET을 사용하는 미리보기가 변경사항을 적절히 반영하고 있습니다.app/src/main/java/com/threegap/bitnagil/MainNavHost.kt (4)
14-15: Import 구문 추가 확인Assisted Injection 패턴 구현에 필요한 import 구문이 올바르게 추가되었습니다.
97-97: 목표 재설정 시나리오 구현 확인홈 화면에서 목표 재설정을 위한 온보딩 호출 시
isNew = false로 올바르게 설정되었습니다. PR 목표에 부합합니다.
155-168: Assisted Injection 패턴 구현 우수OnBoarding 라우트의 파라미터 처리와 ViewModel 생성이 올바르게 구현되었습니다:
- 네비게이션 인자 추출 로직이 명확함
OnBoardingScreenArgenum으로의 변환이 적절함- Assisted Factory 패턴이 올바르게 사용됨
85-85: OnBoarding 라우트 기본값isNew=true가 올바르게 설정되었습니다.
Route.OnBoarding()호출 시isNew의 기본값이true로 지정되어 있어, 약관 동의 화면에서 신규 사용자 온보딩으로 이동할 때 의도한 동작을 합니다.presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionIntent.kt (1)
5-16: MVI Intent 패턴 구현 적절감정 등록 후 추천 루틴 표시 기능을 위한 Intent들이 일관된 패턴으로 잘 구현되었습니다:
RegisterEmotionSuccess가 추천 루틴 데이터를 포함하도록 수정됨- Loading/Success/Failure 패턴이 일관되게 적용됨
- UI 상태 전환과 네비게이션을 위한 Intent들이 명확히 정의됨
data/src/main/java/com/threegap/bitnagil/data/onboarding/model/dto/OnBoardingItemDto.kt (1)
38-98: 온보딩 아이템 ID 변경의 호환성 재확인 필요로컬 저장소에서 해당 ID들이 사용되는 흔적은 발견되지 않았습니다. 그러나 외부 스펙(서버 API)나 다른 저장소(DataStore 등)에서 여전히 기존 ID를 참조 중일 수 있으므로 아래 사항을 추가로 확인해주세요.
- 로컬 DB 엔티티/DAO, SharedPreferences, 마이그레이션 코드 검색 결과: 관련 사용처 없음
- DataStore 또는 다른 커스텀 저장소에서 온보딩 ID 저장 여부
- 네트워크(API) 레이어에서 OnBoardingItemDto.id가 서버 요청·응답 스펙에 사용되는지
위 항목들을 점검하신 뒤, 기존 사용자 데이터 및 백엔드 연동에 영향이 없는지 검증 부탁드립니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionViewModel.kt (4)
7-26: 의존성 주입 구현 적절새로운 추천 루틴 등록 기능을 위한 UseCase와 UI 모델이 올바르게 추가되었습니다.
58-64: 감정 등록 성공 처리 로직 적절감정 등록 성공 시 추천 루틴을 상태에 저장하고 다음 단계로 전환하는 로직이 올바르게 구현되었습니다.
70-106: 상태 관리 로직 우수추천 루틴 관련 Intent 처리가 체계적으로 구현되었습니다:
- 로딩 상태 관리가 일관됨
- 단계 간 네비게이션이 명확함
- 루틴 선택 토글이 불변성을 유지하며 구현됨
116-119: 감정 선택 후 추천 루틴 처리 적절감정 등록 API가 추천 루틴 목록을 반환하도록 변경된 것에 맞춰 올바르게 구현되었습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/OnBoardingViewModel.kt (3)
13-43: Assisted Injection 패턴 구현 완벽런타임 파라미터를 받기 위한 Assisted Injection이 표준 패턴에 따라 올바르게 구현되었습니다:
@HiltViewModel어노테이션에 factory 지정@AssistedInject생성자 사용- Factory 인터페이스 정의
80-80: 온보딩 타입 설정 적절
OnBoardingScreenArg에서OnBoardingSetType으로의 변환이 초기 상태 설정에 올바르게 반영되었습니다.
150-150: 다음 버튼 활성화 로직 의도 확인 – 변경 불필요
canSelectRoutine이 true인 페이지(루틴 선택 페이지)에서는 사용자가 실제로 루틴을 선택해야만 다음 버튼이 활성화되고, false인 페이지(루틴 선택이 불필요한 페이지)에서는 즉시 다음 단계로 진행할 수 있도록nextButtonEnable = !canSelectRoutine로 구현되어 있습니다. 의도된 동작이므로 별도 수정은 필요하지 않습니다.presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt (4)
3-3: 새로운 import들이 적절하게 추가되었습니다.BackHandler, 스크롤 기능, 디자인 시스템 컴포넌트, 새로운 모델들이 모두 코드에서 사용되고 있어 적절합니다.
Also applies to: 15-16, 23-23, 26-26, 31-34, 39-40
51-53: BackHandler 구현이 적절합니다.시스템 백 버튼 처리를 ViewModel에 위임하여 현재 단계에 따른 적절한 네비게이션 로직을 처리할 수 있도록 구현되었습니다.
61-74: 단계별 UI 렌더링 로직이 잘 구현되었습니다.
when표현식을 사용한 조건부 렌더링으로 감정 선택과 추천 루틴 단계를 깔끔하게 분리하였고, 각 콜백이 적절하게 ViewModel 메서드에 위임되어 있습니다.
221-259: Preview 구현이 적절합니다.기존 Preview가 새로운 step 파라미터로 업데이트되었고, 새로운 추천 루틴 화면용 Preview도 적절한 mock 데이터와 함께 추가되어 개발 및 UI 테스트에 도움이 됩니다.
wjdrjs00
left a comment
There was a problem hiding this comment.
여기도 분기 처리작업,, 고생하셨습니다요!
화면 flow 자체가 어려우니 코드도 어려워지는거 같습니다요!
리뷰 확인해주세요~!
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionState.kt
Outdated
Show resolved
Hide resolved
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionViewModel.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt (2)
183-192: 루틴 목록 렌더링 성능 개선을 고려해보세요.현재 for 루프를 사용하고 있는데, 추천 루틴이 많아질 경우를 대비해 LazyColumn 사용을 고려해보세요.
- for (recommendRoutine in state.recommendRoutines) { - BitnagilSelectButton( - title = recommendRoutine.name, - description = recommendRoutine.description, - onClick = { onClickRoutine(recommendRoutine.id) }, - selected = recommendRoutine.selected, - modifier = Modifier.padding(bottom = 12.dp), - ) - } + LazyColumn { + items(state.recommendRoutines) { recommendRoutine -> + BitnagilSelectButton( + title = recommendRoutine.name, + description = recommendRoutine.description, + onClick = { onClickRoutine(recommendRoutine.id) }, + selected = recommendRoutine.selected, + modifier = Modifier.padding(bottom = 12.dp), + ) + } + }
204-214: 건너뛰기 버튼 스타일링 추출을 고려해보세요.복잡한 커스텀 스타일링이 인라인으로 구현되어 있습니다. 이 패턴이 다른 곳에서도 사용될 가능성이 있다면 재사용 가능한 컴포넌트나 헬퍼 함수로 추출하는 것을 고려해보세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt(4 hunks)
🧰 Additional context used
🧠 Learnings (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt (1)
Learnt from: l5x5l
PR: #38
File: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt:30-35
Timestamp: 2025-07-21T10:38:49.104Z
Learning: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt의 TextButton 컴포넌트는 임시로 구현된 컴포넌트로, 디자인 시스템 구현시 대체 예정입니다.
⏰ 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). (1)
- GitHub Check: build
🔇 Additional comments (5)
presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt (5)
3-3: 새로운 기능에 필요한 임포트들이 적절히 추가되었습니다.BackHandler, 스크롤 관련 컴포넌트, 디자인 시스템 컴포넌트, 새로운 UI 모델들이 모두 적절히 사용되고 있습니다.
Also applies to: 15-16, 23-23, 26-26, 31-34, 39-40
51-53: BackHandler 구현이 적절합니다.다단계 플로우에서 뒤로가기 동작을 ViewModel에 위임하여 상태 전환을 적절히 관리하고 있습니다.
61-74: 단계별 조건부 렌더링이 깔끔하게 구현되었습니다.when 표현식을 사용한 화면 전환 로직이 명확하고, 각 화면에 적절한 props와 콜백이 전달되고 있습니다.
151-154: 진행률 값이 하드코딩되어 있습니다.
progress = 1f가 하드코딩되어 있는데, 실제 단계에 따른 진행률을 계산하는 것이 더 적절할 수 있습니다. 2단계 플로우에서 마지막 단계라면 올바르지만, 향후 단계가 추가될 가능성을 고려해보세요.
221-260: 프리뷰 함수들이 적절히 구현되었습니다.기존 프리뷰가 새로운 상태 속성으로 업데이트되었고, 새로운 추천 루틴 화면에 대한 프리뷰도 적절한 샘플 데이터와 함께 추가되었습니다.
[ PR Content ]
설정 화면-내 목표 재설정시 사용되는 온보딩 수정 flow와, 감정 구슬 선택 화면에서 감정 구슬 선택 이후 추천 루틴 표시 부분을 구현합니다.
Related issue
Screenshot 📸
KakaoTalk_Video_2025-07-30-20-24-10.mp4
Work Description
To Reviewers 📢
Summary by CodeRabbit
신규 기능
개선 사항
버그 수정