-
Notifications
You must be signed in to change notification settings - Fork 0
[Feature/#50] 추천 루틴 API 연동 #51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- ProgressBarGradientStartColor 추가 - ProgressBarGradientEndColor 추가 - HomeGradientStartColor 추가 - HomeGradientEndColor 추가 - CoolGray7 색상값 수정
- ProgressBarGradientStartColor 추가 - ProgressBarGradientEndColor 추가 - HomeGradientStartColor 추가 - HomeGradientEndColor 추가 - CoolGray7 색상값 수정
…hub/Bitnagil-Android into ui/#45-common-component
- 감정 선택 화면 UI를 디자인에 맞게 수정 - 각 감정에 해당하는 아이콘을 적용
- 기존의 Box로 구현되어 있던 TopBar들을 BitnagilTopBar로 대체
- FloatingActionButton, FloatingActionMenu 컴포넌트 추가
- 기존: MyPageScreen 및 SettingScreen에서 BitnagilOptionButton 사용 시 padding을 적용 - 변경: BitnagilOptionButton 컴포넌트 내부에서 padding 적용
- RecommendedRoutineDto, RecommendedSubRoutineDto, RecommendRoutinesDto 모델을 추가
""" Walkthrough추천 루틴(Recommend Routine) API 연동을 위해 도메인, 데이터, 프레젠테이션 계층 전반에 걸쳐 새로운 모델, 데이터 소스, 레포지토리, 서비스, 유즈케이스, UI 모델, ViewModel 로직, 그리고 DI 모듈이 추가 및 수정되었습니다. 기존 더미 데이터 및 난이도/카테고리 관련 타입은 도메인 기반으로 대체되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant UI
participant ViewModel
participant UseCase
participant Repository
participant DataSource
participant Service
participant API
UI->>ViewModel: 화면 진입/새로고침
ViewModel->>UseCase: fetchRecommendRoutinesUseCase()
UseCase->>Repository: fetchRecommendRoutines()
Repository->>DataSource: fetchRecommendRoutines()
DataSource->>Service: fetchRecommendRoutines()
Service->>API: GET /api/v1/recommend-routines
API-->>Service: BaseResponse<RecommendRoutinesDto>
Service-->>DataSource: RecommendRoutinesDto
DataSource-->>Repository: Result<RecommendRoutinesDto>
Repository-->>UseCase: Result<RecommendRoutines>
UseCase-->>ViewModel: Result<RecommendRoutines>
ViewModel-->>UI: 상태 갱신(추천 루틴 목록, 감정 구슬 등)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes(해당 PR의 모든 변경 사항은 명시된 이슈(#50)의 "추천 루틴 조회 API 연동" 목적에 부합합니다. 범위를 벗어난 기능적 코드 변경은 발견되지 않았습니다.) Possibly related PRs
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 (
|
[UI/#45] 디자인 컴포넌트 구현 및 ui 화면 퍼블리싱 작업 진행
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (5)
domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendCategory.kt (1)
18-21
: 문자열 변환 로직이 안전합니다.
entries.find
를 사용한 안전한 변환과 기본값(UNKNOWN
) 처리가 올바릅니다.향후 다국어 지원을 고려한다면
displayName
을 리소스 ID나 키 값으로 변경하는 것을 검토해보세요:enum class RecommendCategory( val categoryName: String, val displayNameResId: Int, // 또는 displayNameKey: String val isVisible: Boolean = true, )presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/template/RecommendLevelBottomSheet.kt (2)
87-88
: TODO 주석: 리플 효과 제거리플 효과를 제거하려면
clickable
modifier에indication = null
을 추가하세요.modifier = modifier - // todo: 리플효과 제거하기 - .clickable { onClick() } + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() } + ) { onClick() } .padding(vertical = 8.dp),필요한 import를 추가하세요:
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.runtime.remember
99-100
: TODO 주석 처리 필요아이콘 변경에 대한 TODO가 있습니다. 디자인 시스템의 아이콘을 사용하거나 이슈로 트래킹하는 것을 권장합니다.
이 TODO를 처리하기 위한 이슈를 생성하시겠습니까?
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineViewModel.kt (1)
33-33
: 동시성 문제 가능성
recommendRoutines
가var
로 선언되어 있어 동시성 문제가 발생할 수 있습니다.thread-safe한 방식으로 변경하는 것을 권장합니다:
-private var recommendRoutines: RecommendRoutinesUiModel = RecommendRoutinesUiModel() +private val recommendRoutines = MutableStateFlow(RecommendRoutinesUiModel())또는
@Volatile
어노테이션을 추가하세요:+@Volatile private var recommendRoutines: RecommendRoutinesUiModel = RecommendRoutinesUiModel()
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineScreen.kt (1)
143-144
: TODO 주석 처리 필요다음 TODO 항목들이 남아있습니다:
- 리플 효과 제거 (line 143)
- 아이콘 변경 (line 155)
이슈 트래킹을 위해 별도 태스크로 관리하는 것을 권장합니다.
Also applies to: 155-155
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (31)
app/src/main/java/com/threegap/bitnagil/di/data/DataSourceModule.kt
(2 hunks)app/src/main/java/com/threegap/bitnagil/di/data/RepositoryModule.kt
(2 hunks)app/src/main/java/com/threegap/bitnagil/di/data/ServiceModule.kt
(2 hunks)app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt
(1 hunks)data/src/main/java/com/threegap/bitnagil/data/recommendroutine/datasource/RecommendRoutineDataSource.kt
(1 hunks)data/src/main/java/com/threegap/bitnagil/data/recommendroutine/datasourceImpl/RecommendRoutineDataSourceImpl.kt
(1 hunks)data/src/main/java/com/threegap/bitnagil/data/recommendroutine/model/response/RecommendRoutinesDto.kt
(1 hunks)data/src/main/java/com/threegap/bitnagil/data/recommendroutine/model/response/RecommendedRoutineDto.kt
(1 hunks)data/src/main/java/com/threegap/bitnagil/data/recommendroutine/model/response/RecommendedSubRoutineDto.kt
(1 hunks)data/src/main/java/com/threegap/bitnagil/data/recommendroutine/repositoryImpl/RecommendRoutineRepositoryImpl.kt
(1 hunks)data/src/main/java/com/threegap/bitnagil/data/recommendroutine/service/RecommendRoutineService.kt
(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/EmotionMarbleType.kt
(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendCategory.kt
(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendLevel.kt
(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendRoutine.kt
(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendRoutines.kt
(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendSubRoutine.kt
(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/repository/RecommendRoutineRepository.kt
(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/usecase/FetchRecommendRoutinesUseCase.kt
(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineScreen.kt
(6 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineViewModel.kt
(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/RecommendRoutineItem.kt
(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/template/RecommendLevelBottomSheet.kt
(4 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutine.kt
(0 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutineIntent.kt
(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutineState.kt
(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutineUiModel.kt
(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutinesUiModel.kt
(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendSubRoutineUiModel.kt
(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/type/RecommendRoutineCategory.kt
(0 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/type/RecommendRoutineDifficulty.kt
(0 hunks)
💤 Files with no reviewable changes (3)
- presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/type/RecommendRoutineDifficulty.kt
- presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/type/RecommendRoutineCategory.kt
- presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutine.kt
🧰 Additional context used
🧠 Learnings (6)
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/RecommendRoutineItem.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/recommendroutine/model/RecommendRoutineUiModel.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.
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendSubRoutineUiModel.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.
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineViewModel.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/recommendroutine/model/RecommendRoutinesUiModel.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.
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutineIntent.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 (3)
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineViewModel.kt (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt (1)
sendIntent
(30-37)
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineScreen.kt (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/template/RecommendLevelBottomSheet.kt (1)
RecommendLevelBottomSheet
(25-75)
data/src/main/java/com/threegap/bitnagil/data/recommendroutine/datasourceImpl/RecommendRoutineDataSourceImpl.kt (1)
data/src/main/java/com/threegap/bitnagil/data/common/SafeApiCall.kt (1)
safeApiCall
(10-25)
🔇 Additional comments (32)
domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendRoutine.kt (1)
3-10
: 도메인 모델 구조가 잘 설계되었습니다.불변 데이터 클래스로 구현되어 있고,
RecommendLevel
과RecommendSubRoutine
같은 도메인 특화 타입을 사용하여 타입 안정성을 확보했습니다. 클린 아키텍처 원칙에 잘 부합하는 구현입니다.domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendSubRoutine.kt (1)
3-6
: 간결하고 명확한 도메인 모델입니다.서브루틴을 표현하는 최소한의 필수 속성만 포함되어 있으며, 불변 설계로 일관성이 유지되고 있습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/RecommendRoutineItem.kt (2)
19-19
: 텍스트 오버플로우 처리를 위한 적절한 import 추가입니다.
63-64
: 루틴 설명 텍스트의 오버플로우 처리가 잘 구현되었습니다.
maxLines = 1
과overflow = Ellipsis
를 통해 긴 설명 텍스트가 레이아웃을 깨뜨리지 않도록 하고, 일관된 단일 라인 표시를 보장합니다. UI 일관성 측면에서 좋은 개선입니다.domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/EmotionMarbleType.kt (1)
3-10
: 감정 상태를 나타내는 enum이 명확하게 정의되었습니다.6가지 감정 상태(
CALM
,VITALITY
,LETHARGY
,ANXIETY
,SATISFACTION
,FATIGUE
)가 직관적이고 의미가 명확한 이름으로 정의되어 있어 타입 안전성을 제공합니다.data/src/main/java/com/threegap/bitnagil/data/recommendroutine/datasource/RecommendRoutineDataSource.kt (1)
5-7
: 데이터 소스 인터페이스가 잘 설계되었습니다.
suspend
함수를 사용한 비동기 처리와Result
타입을 통한 에러 핸들링이 적절하게 구현되어 있습니다. 레포지토리와 실제 데이터 가져오기 구현 사이의 깔끔한 추상화를 제공합니다.domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/repository/RecommendRoutineRepository.kt (1)
1-7
: 잘 설계된 도메인 레포지토리 인터페이스입니다.클린 아키텍처 원칙을 잘 따르고 있으며, Result 패턴을 사용한 에러 핸들링과 suspend 함수를 통한 비동기 처리가 적절합니다.
app/src/main/java/com/threegap/bitnagil/di/data/ServiceModule.kt (2)
6-6
: 적절한 import 추가입니다.새로운 RecommendRoutineService에 대한 import가 올바르게 추가되었습니다.
53-56
: 일관된 DI 패턴을 따르고 있습니다.기존 서비스 프로바이더들과 동일한 패턴을 따라 @Auth Retrofit 인스턴스를 사용하여 RecommendRoutineService를 제공하고 있습니다. 적절한 싱글톤 스코프와 어노테이션이 적용되었습니다.
domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/usecase/FetchRecommendRoutinesUseCase.kt (1)
7-12
: 깔끔한 유즈케이스 구현입니다.단일 책임 원칙을 잘 따르고 있으며, Kotlin의 operator fun invoke() 컨벤션을 적절히 활용했습니다. 현재는 레포지토리에 대한 단순한 위임이지만, 향후 추가적인 도메인 로직이 필요할 때 확장하기 좋은 구조입니다.
app/src/main/java/com/threegap/bitnagil/di/data/RepositoryModule.kt (2)
6-6
: 필요한 import가 적절히 추가되었습니다.RecommendRoutineRepositoryImpl과 RecommendRoutineRepository에 대한 import가 올바르게 추가되었습니다.
Also applies to: 12-12
45-47
: 일관된 레포지토리 바인딩 패턴입니다.기존 레포지토리 바인딩들과 동일한 패턴을 따라 @BINDS와 @singleton 어노테이션을 적절히 사용하여 RecommendRoutineRepository 인터페이스를 구현체에 바인딩하고 있습니다.
app/src/main/java/com/threegap/bitnagil/di/data/DataSourceModule.kt (2)
11-12
: 적절한 import 추가입니다.RecommendRoutineDataSource 인터페이스와 구현체에 대한 import가 올바르게 추가되었습니다.
51-53
: 일관된 데이터 소스 바인딩 패턴입니다.기존 데이터 소스 바인딩들과 동일한 패턴을 따라 @BINDS와 @singleton 어노테이션을 적절히 사용하여 RecommendRoutineDataSource 인터페이스를 구현체에 바인딩하고 있습니다.
domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendRoutines.kt (1)
3-6
: 깔끔한 도메인 모델 설계입니다.추천 루틴을 카테고리별로 그룹화하는 Map 구조와 선택적 감정 마블 타입을 포함한 도메인 모델이 잘 설계되었습니다. 비즈니스 로직을 명확하게 표현하고 있습니다.
data/src/main/java/com/threegap/bitnagil/data/recommendroutine/service/RecommendRoutineService.kt (1)
7-10
: Retrofit 서비스 인터페이스가 적절하게 구현되었습니다.suspend 함수를 사용한 코루틴 지원과 BaseResponse 래퍼를 통한 일관된 API 응답 처리가 잘 되어 있습니다.
domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendLevel.kt (2)
12-15
: fromString 메서드의 기본값 처리를 검토해보세요.enum 설계는 잘 되어 있지만, fromString에서 매칭되지 않는 경우 LEVEL1로 기본값을 반환하는 것이 적절한지 검토가 필요합니다. 잘못된 데이터를 마스킹할 수 있습니다.
다음과 같이 예외를 던지거나 nullable을 반환하는 것을 고려해보세요:
companion object { - fun fromString(levelName: String): RecommendLevel = - entries.find { it.level == levelName } ?: LEVEL1 + fun fromString(levelName: String): RecommendLevel = + entries.find { it.level == levelName } + ?: throw IllegalArgumentException("Unknown level: $levelName") }또는:
companion object { + fun fromStringOrNull(levelName: String): RecommendLevel? = + entries.find { it.level == levelName } + fun fromString(levelName: String): RecommendLevel = - entries.find { it.level == levelName } ?: LEVEL1 + fromStringOrNull(levelName) ?: LEVEL1 }
7-9
: 한국어 표시명이 잘 정의되어 있습니다.각 레벨의 의미를 명확하게 전달하는 한국어 표시명이 사용자 친화적으로 작성되었습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendSubRoutineUiModel.kt (2)
7-11
: @parcelize를 사용한 UI 모델이 적절하게 구현되었습니다.Android의 컴포넌트 간 데이터 전달을 위한 Parcelable 구현이 깔끔하게 되어 있습니다.
13-17
: 도메인 모델에서 UI 모델로의 변환 로직이 명확합니다.확장 함수를 통한 도메인 모델 변환이 간결하고 이해하기 쉽게 구현되었습니다.
data/src/main/java/com/threegap/bitnagil/data/recommendroutine/model/response/RecommendedSubRoutineDto.kt (2)
7-13
: DTO 구조가 적절하게 설계되었습니다.@serializable과 @SerialName을 사용한 JSON 직렬화 설정이 올바르게 구현되어 있고, API 응답의 상세한 필드명과 도메인 모델의 간결한 필드명 간의 분리가 잘 되어 있습니다.
15-19
: 도메인 변환 로직이 명확합니다.toDomain() 확장 함수를 통한 DTO에서 도메인 모델로의 변환이 간단하고 명확하게 구현되었습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutinesUiModel.kt (2)
9-13
: UI 모델 구조가 잘 설계되었습니다.데이터 클래스의 구조가 명확하고,
@Parcelize
어노테이션을 통한 Parcelable 구현이 적절합니다. Map을 사용하여 카테고리별 루틴 그룹핑이 효율적으로 구현되었습니다.
15-21
: 도메인-UI 모델 변환 로직이 올바릅니다.확장 함수를 통한 변환 패턴이 Clean Architecture의 원칙에 잘 부합하며, mapValues를 사용한 컬렉션 변환이 효율적입니다.
data/src/main/java/com/threegap/bitnagil/data/recommendroutine/datasourceImpl/RecommendRoutineDataSourceImpl.kt (1)
9-17
: 데이터소스 구현이 올바릅니다.DI 패턴과
safeApiCall
을 활용한 안전한 API 호출 구현이 적절합니다. 코드가 간결하고 책임이 명확히 분리되어 있습니다.presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutineUiModel.kt (2)
8-16
: UI 모델 정의가 적절합니다.모든 필요한 속성들이 명확히 정의되어 있고,
@Parcelize
를 통한 Parcelable 구현이 올바릅니다. 도메인 레벨 타입(RecommendLevel
)을 적절히 활용하고 있습니다.
18-26
: 도메인-UI 변환 로직이 완전합니다.모든 속성이 올바르게 매핑되고 있으며, 서브루틴 리스트의 변환도 적절히 처리되었습니다. 확장 함수 패턴이 일관되게 적용되었습니다.
domain/src/main/java/com/threegap/bitnagil/domain/recommendroutine/model/RecommendCategory.kt (1)
3-16
: enum 설계가 잘 되어 있습니다.카테고리별 속성 정의가 명확하고,
isVisible
플래그를 통한 가시성 제어가 효과적입니다. 숨겨진 카테고리들(OUTING_REPORT
,UNKNOWN
)의 처리도 적절합니다.data/src/main/java/com/threegap/bitnagil/data/recommendroutine/repositoryImpl/RecommendRoutineRepositoryImpl.kt (1)
9-15
: Repository 구현이 깔끔합니다.Repository 패턴이 올바르게 적용되었고,
Result.map
을 사용한 DTO-도메인 모델 변환이 효율적입니다. 데이터소스에 위임하는 방식으로 책임이 명확히 분리되어 있습니다.presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutineIntent.kt (1)
7-15
: Intent 클래스 구조가 적절합니다MVI 아키텍처에 맞게 Intent가 잘 정의되었습니다. 도메인 모델 타입을 사용하고 명명 규칙이 일관성 있게 적용되었습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/model/RecommendRoutineState.kt (1)
3-6
: 도메인 모델로의 마이그레이션이 적절합니다 👍프레젠테이션 레이어에서 도메인 모델(
RecommendCategory
,RecommendLevel
,EmotionMarbleType
)을 직접 사용하는 것은 클린 아키텍처 원칙을 잘 따르고 있습니다.presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineScreen.kt (1)
45-45
: 네비게이션 파라미터 타입 불일치 문제PR 설명에서 언급하신 대로 추천 루틴 ID(Int)와 일반 루틴 ID(String)의 타입 불일치가 확인됩니다. 향후 일관성 있는 타입으로 통일이 필요합니다.
app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt
Outdated
Show resolved
Hide resolved
...ain/java/com/threegap/bitnagil/data/recommendroutine/model/response/RecommendedRoutineDto.kt
Show resolved
Hide resolved
...main/java/com/threegap/bitnagil/data/recommendroutine/model/response/RecommendRoutinesDto.kt
Show resolved
Hide resolved
...c/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineViewModel.kt
Show resolved
Hide resolved
.../src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineScreen.kt
Outdated
Show resolved
Hide resolved
- Int -> String
고생하셨습니다! 미리보기로 올려주신 영상에서 ripple 클릭 효과가 보이는데 이 부분만 제거해주시면 좋을 것 같습니다! |
해당 부분은 디벨롭 브랜치로 병합되면 자연스럽게 해결될거같습니다요! |
- RecommendedRoutineDto, RecommendedSubRoutineDto, RecommendRoutinesDto 모델을 추가
- 추천 루틴 API 연동 - ViewModel에서 실제 데이터를 사용하도록 로직 수정 - 카테고리 및 난이도 필터링 로직 구현 - 불필요한 더미 데이터 생성 코드 제거
- Int -> String
…m/YAPP-Github/Bitnagil-Android into feature/#50-recommend-routine-api
There was a problem hiding this 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 (3)
presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingScreen.kt (1)
138-147
: 색상 명시가 불필요할 수 있습니다
BitnagilTheme.colors.black
을 명시적으로 지정했는데, 이미 테마의 기본값일 가능성이 높습니다.다음과 같이 간소화할 수 있습니다:
- Text( - text = "버전 ", - color = BitnagilTheme.colors.black, - style = BitnagilTheme.typography.body1Regular, - ) - Text( - text = state.version, - color = BitnagilTheme.colors.black, - style = BitnagilTheme.typography.body1SemiBold, - ) + Text( + text = "버전 ", + style = BitnagilTheme.typography.body1Regular, + ) + Text( + text = state.version, + style = BitnagilTheme.typography.body1SemiBold, + )presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/atom/EmotionBall.kt (1)
27-52
: 코드 중복을 줄이고 일관성을 개선해보세요.두 분기에서
Image
컴포넌트가 중복되고 있으며, 하드코딩된 크기와fillMaxSize()
조합이 혼재되어 있습니다.다음과 같이 리팩토링하여 중복을 줄일 수 있습니다:
@Composable fun EmotionBall( emotionType: EmotionBallType?, onClick: () -> Unit, modifier: Modifier = Modifier, ) { + val ballSize = 172.dp + val painter = if (emotionType != null) { + painterResource(emotionType.drawableId) + } else { + painterResource(R.drawable.default_ball) + } + + val imageModifier = modifier + .size(ballSize) + .clickableWithoutRipple { onClick() } + .let { + if (emotionType != null) { + it.padding(10.dp) + .fillMaxSize() + .shadow( + elevation = 24.dp, + shape = CircleShape, + ambientColor = emotionType.ambientColor, + spotColor = emotionType.spotColor, + ) + } else { + it.fillMaxSize() + } + } + - if (emotionType != null) { - Image( - painter = painterResource(emotionType.drawableId), - contentDescription = null, - modifier = modifier - .size(172.dp) - .clickableWithoutRipple { onClick() } - .padding(10.dp) - .fillMaxSize() - .shadow( - elevation = 24.dp, - shape = CircleShape, - ambientColor = emotionType.ambientColor, - spotColor = emotionType.spotColor, - ), - ) - } else { - Image( - painter = painterResource(R.drawable.default_ball), - contentDescription = null, - modifier = modifier - .size(172.dp) - .clickableWithoutRipple { onClick() } - .fillMaxSize(), - ) - } + Image( + painter = painter, + contentDescription = null, + modifier = imageModifier, + ) }core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilCheckBox.kt (1)
25-56
: 체크박스 컴포넌트 구현이 잘 되어 있습니다.컴포넌트의 구조와 로직이 명확하고, ripple 효과 제거를 통한 일관된 UI 경험을 제공합니다. 하지만 몇 가지 개선사항을 제안합니다:
modifier
파라미터가 두 번 사용되고 있습니다 (line 35, 53)- 접근성을 위한
contentDescription
개선이 필요합니다다음과 같이 개선할 수 있습니다:
@Composable fun BitnagilCheckBox( checked: Boolean, modifier: Modifier = Modifier, onCheckedChange: ((Boolean) -> Unit)? = null, colors: BitnagilCheckBoxColor = BitnagilCheckBoxColor.terms(), + contentDescription: String? = null, ) { val iconColor = if (checked) colors.checkedColor else colors.uncheckedColor Box( modifier = modifier .let { if (onCheckedChange != null) { it.clickableWithoutRipple { onCheckedChange(!checked) } } else { it } } .background( color = BitnagilTheme.colors.white, shape = RoundedCornerShape(6.dp), ), contentAlignment = Alignment.Center, ) { Image( imageVector = ImageVector.vectorResource(R.drawable.ic_check), - contentDescription = null, + contentDescription = contentDescription ?: if (checked) "선택됨" else "선택 안됨", colorFilter = ColorFilter.tint(iconColor), - modifier = modifier.size(24.dp), + modifier = Modifier.size(24.dp), ) } }
[ PR Content ]
추천 루틴 화면 api 연동 작업을 진행했습니다.
추가로 ui 개발 과정에서 받은 리뷰 사항도 같이 반영했습니다. → #34 (comment)
Related issue
Screenshot 📸
api.mp4
Work Description
To Reviewers 📢
추천 루틴 id
또는일반 루틴 id
값을 인자로 넘겨받는 상황인데 서로 타입이 Int와 String으로 다르다는 사실을 발견해버렸습니다.. 우선 해당 pr에서는 해결하지 않았는데 추후 반영해서 수정해야할거 같습니다요!Summary by CodeRabbit
신규 기능
UI 개선
리팩터링 및 구조 개선
삭제