From 61889dc17915aeeec0d5785cdf771adad13a328d Mon Sep 17 00:00:00 2001 From: yunsehwan Date: Wed, 6 Aug 2025 21:28:00 +0900 Subject: [PATCH 1/5] =?UTF-8?q?Add:=20coil-compose,=20coil-network=20?= =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/libs.versions.toml | 10 ++++++++++ presentation/build.gradle.kts | 1 + 2 files changed, 11 insertions(+) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 47973da5..59488ed8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -52,6 +52,7 @@ orbit = "6.1.0" javax = "1" kakaoLogin = "2.21.4" lottie-compose = "6.6.0" +coil = "3.3.0" [libraries] ## Android Gradle Plugin @@ -115,6 +116,10 @@ androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "j androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } kotlin-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" } +## coil +coil-compose = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" } +coil-network = { group = "io.coil-kt.coil3", name = "coil-network-okhttp", version.ref = "coil" } + ## Other material = { group = "com.google.android.material", name = "material", version.ref = "material" } kakao-v2-user = { group = "com.kakao.sdk", name = "v2-user", version.ref = "kakaoLogin" } @@ -171,6 +176,11 @@ orbit = [ "orbit-viewmodel" ] +coil = [ + "coil-compose", + "coil-network" +] + [plugins] android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } diff --git a/presentation/build.gradle.kts b/presentation/build.gradle.kts index d0716ce7..6f8d0b1b 100644 --- a/presentation/build.gradle.kts +++ b/presentation/build.gradle.kts @@ -19,6 +19,7 @@ dependencies { implementation(libs.kakao.v2.user) implementation(libs.kotlinx.serialization.json) implementation(libs.lottie.compose) + implementation(libs.bundles.coil) testImplementation(libs.junit) testImplementation(libs.kotlin.coroutines.test) From 90494f747d2664fb1a8ad20dfbe3efafabb29df3 Mon Sep 17 00:00:00 2001 From: yunsehwan Date: Wed, 6 Aug 2025 21:30:30 +0900 Subject: [PATCH 2/5] =?UTF-8?q?REFACTOR:=20=EA=B0=90=EC=A0=95=20=EA=B5=AC?= =?UTF-8?q?=EC=8A=AC=20=EA=B4=80=EB=A0=A8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=EC=9D=84=20=EC=84=9C=EB=B2=84=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../emotion/datasource/EmotionDataSource.kt | 4 +- .../datasourceImpl/EmotionDataSourceImpl.kt | 6 +- .../data/emotion/model/dto/EmotionDto.kt | 10 +- ...onResponseDto.kt => GetEmotionResponse.kt} | 20 ++- .../repositoryImpl/EmotionRepositoryImpl.kt | 32 +--- .../data/emotion/service/EmotionService.kt | 6 +- .../bitnagil/domain/emotion/model/Emotion.kt | 13 +- .../domain/emotion/model/MyEmotion.kt | 7 - .../emotion/repository/EmotionRepository.kt | 7 +- .../emotion/usecase/GetEmotionUseCase.kt | 12 ++ .../emotion/usecase/GetMyEmotionUseCase.kt | 12 -- .../emotion/usecase/RegisterEmotionUseCase.kt | 5 +- .../presentation/emotion/EmotionScreen.kt | 156 ++++++++++-------- .../presentation/emotion/EmotionViewModel.kt | 10 +- .../presentation/emotion/model/Emotion.kt | 41 ----- .../emotion/model/EmotionUiModel.kt | 35 ++++ .../emotion/model/mvi/EmotionIntent.kt | 4 +- .../emotion/model/mvi/EmotionState.kt | 6 +- .../presentation/home/HomeViewModel.kt | 8 +- .../home/model/EmotionBallType.kt | 5 +- 20 files changed, 195 insertions(+), 204 deletions(-) rename data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/{MyEmotionResponseDto.kt => GetEmotionResponse.kt} (53%) delete mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/MyEmotion.kt create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetEmotionUseCase.kt delete mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetMyEmotionUseCase.kt delete mode 100644 presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/Emotion.kt create mode 100644 presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionUiModel.kt diff --git a/data/src/main/java/com/threegap/bitnagil/data/emotion/datasource/EmotionDataSource.kt b/data/src/main/java/com/threegap/bitnagil/data/emotion/datasource/EmotionDataSource.kt index 0171fe2f..5e21227d 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/emotion/datasource/EmotionDataSource.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/emotion/datasource/EmotionDataSource.kt @@ -1,11 +1,11 @@ package com.threegap.bitnagil.data.emotion.datasource import com.threegap.bitnagil.data.emotion.model.dto.EmotionDto -import com.threegap.bitnagil.data.emotion.model.response.MyEmotionResponseDto +import com.threegap.bitnagil.data.emotion.model.response.GetEmotionResponse import com.threegap.bitnagil.data.emotion.model.response.RegisterEmotionResponse interface EmotionDataSource { suspend fun getEmotions(): Result> suspend fun registerEmotion(emotion: String): Result - suspend fun getMyEmotionMarble(currentDate: String): Result + suspend fun getEmotionMarble(currentDate: String): Result } diff --git a/data/src/main/java/com/threegap/bitnagil/data/emotion/datasourceImpl/EmotionDataSourceImpl.kt b/data/src/main/java/com/threegap/bitnagil/data/emotion/datasourceImpl/EmotionDataSourceImpl.kt index 16cd3a1b..b8893258 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/emotion/datasourceImpl/EmotionDataSourceImpl.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/emotion/datasourceImpl/EmotionDataSourceImpl.kt @@ -4,7 +4,7 @@ import com.threegap.bitnagil.data.common.safeApiCall import com.threegap.bitnagil.data.emotion.datasource.EmotionDataSource import com.threegap.bitnagil.data.emotion.model.dto.EmotionDto import com.threegap.bitnagil.data.emotion.model.request.RegisterEmotionRequest -import com.threegap.bitnagil.data.emotion.model.response.MyEmotionResponseDto +import com.threegap.bitnagil.data.emotion.model.response.GetEmotionResponse import com.threegap.bitnagil.data.emotion.model.response.RegisterEmotionResponse import com.threegap.bitnagil.data.emotion.service.EmotionService import javax.inject.Inject @@ -25,8 +25,8 @@ class EmotionDataSourceImpl @Inject constructor( } } - override suspend fun getMyEmotionMarble(currentDate: String): Result = + override suspend fun getEmotionMarble(currentDate: String): Result = safeApiCall { - emotionService.getMyEmotionMarble(currentDate) + emotionService.getEmotionMarble(currentDate) } } diff --git a/data/src/main/java/com/threegap/bitnagil/data/emotion/model/dto/EmotionDto.kt b/data/src/main/java/com/threegap/bitnagil/data/emotion/model/dto/EmotionDto.kt index c9f8e652..b6bbf455 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/emotion/model/dto/EmotionDto.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/emotion/model/dto/EmotionDto.kt @@ -1,5 +1,6 @@ package com.threegap.bitnagil.data.emotion.model.dto +import com.threegap.bitnagil.domain.emotion.model.Emotion import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -11,4 +12,11 @@ data class EmotionDto( val emotionMarbleName: String, @SerialName("imageUrl") val imageUrl: String, -) +) { + fun toDomain(): Emotion = + Emotion( + emotionType = emotionMarbleType, + emotionMarbleName = emotionMarbleName, + imageUrl = imageUrl, + ) +} diff --git a/data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/MyEmotionResponseDto.kt b/data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/GetEmotionResponse.kt similarity index 53% rename from data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/MyEmotionResponseDto.kt rename to data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/GetEmotionResponse.kt index 77243076..84aff760 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/MyEmotionResponseDto.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/GetEmotionResponse.kt @@ -1,12 +1,11 @@ package com.threegap.bitnagil.data.emotion.model.response import com.threegap.bitnagil.domain.emotion.model.Emotion -import com.threegap.bitnagil.domain.emotion.model.MyEmotion import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class MyEmotionResponseDto( +data class GetEmotionResponse( @SerialName("emotionMarbleType") val emotionMarbleType: String?, @SerialName("emotionMarbleName") @@ -15,9 +14,14 @@ data class MyEmotionResponseDto( val imageUrl: String?, ) -fun MyEmotionResponseDto.toDomain(): MyEmotion = - MyEmotion( - emotionMarbleType = emotionMarbleType?.let { Emotion.valueOf(it) }, - emotionMarbleName = emotionMarbleName, - imageUrl = imageUrl, - ) +fun GetEmotionResponse.toDomain(): Emotion? { + return if (emotionMarbleType != null && emotionMarbleName != null && imageUrl != null) { + Emotion( + emotionType = emotionMarbleType, + emotionMarbleName = emotionMarbleName, + imageUrl = imageUrl + ) + } else { + null + } +} diff --git a/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt b/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt index 6c08bf65..e4b4f401 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt @@ -2,9 +2,8 @@ package com.threegap.bitnagil.data.emotion.repositoryImpl import com.threegap.bitnagil.data.emotion.datasource.EmotionDataSource import com.threegap.bitnagil.data.emotion.model.response.toDomain -import com.threegap.bitnagil.domain.emotion.model.Emotion import com.threegap.bitnagil.domain.emotion.model.EmotionRecommendRoutine -import com.threegap.bitnagil.domain.emotion.model.MyEmotion +import com.threegap.bitnagil.domain.emotion.model.Emotion import com.threegap.bitnagil.domain.emotion.repository.EmotionRepository import javax.inject.Inject @@ -13,31 +12,12 @@ class EmotionRepositoryImpl @Inject constructor( ) : EmotionRepository { override suspend fun getEmotions(): Result> { return emotionDataSource.getEmotions().map { response -> - response.mapNotNull { - when (it.emotionMarbleType) { - "CALM" -> Emotion.CALM - "VITALITY" -> Emotion.VITALITY - "LETHARGY" -> Emotion.LETHARGY - "ANXIETY" -> Emotion.ANXIETY - "SATISFACTION" -> Emotion.SATISFACTION - "FATIGUE" -> Emotion.FATIGUE - else -> null - } - } + response.map { it.toDomain() } } } - override suspend fun registerEmotion(emotion: Emotion): Result> { - val selectedEmotion = when (emotion) { - Emotion.CALM -> "CALM" - Emotion.VITALITY -> "VITALITY" - Emotion.LETHARGY -> "LETHARGY" - Emotion.ANXIETY -> "ANXIETY" - Emotion.SATISFACTION -> "SATISFACTION" - Emotion.FATIGUE -> "FATIGUE" - } - - return emotionDataSource.registerEmotion(selectedEmotion).map { + override suspend fun registerEmotion(emotionMarbleType: String): Result> { + return emotionDataSource.registerEmotion(emotionMarbleType).map { it.recommendedRoutines.map { emotionRecommendedRoutineDto -> emotionRecommendedRoutineDto.toEmotionRecommendRoutine() @@ -45,6 +25,6 @@ class EmotionRepositoryImpl @Inject constructor( } } - override suspend fun getMyEmotionMarble(currentDate: String): Result = - emotionDataSource.getMyEmotionMarble(currentDate).map { it.toDomain() } + override suspend fun getEmotionMarble(currentDate: String): Result = + emotionDataSource.getEmotionMarble(currentDate).map { it.toDomain() } } diff --git a/data/src/main/java/com/threegap/bitnagil/data/emotion/service/EmotionService.kt b/data/src/main/java/com/threegap/bitnagil/data/emotion/service/EmotionService.kt index df8c4e9a..0752f695 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/emotion/service/EmotionService.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/emotion/service/EmotionService.kt @@ -2,7 +2,7 @@ package com.threegap.bitnagil.data.emotion.service import com.threegap.bitnagil.data.emotion.model.dto.EmotionDto import com.threegap.bitnagil.data.emotion.model.request.RegisterEmotionRequest -import com.threegap.bitnagil.data.emotion.model.response.MyEmotionResponseDto +import com.threegap.bitnagil.data.emotion.model.response.GetEmotionResponse import com.threegap.bitnagil.data.emotion.model.response.RegisterEmotionResponse import com.threegap.bitnagil.network.model.BaseResponse import retrofit2.http.Body @@ -20,7 +20,7 @@ interface EmotionService { ): BaseResponse @GET("/api/v1/emotion-marbles/{searchDate}") - suspend fun getMyEmotionMarble( + suspend fun getEmotionMarble( @Path("searchDate") date: String, - ): BaseResponse + ): BaseResponse } diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/Emotion.kt b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/Emotion.kt index daf69bae..f6aa4ede 100644 --- a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/Emotion.kt +++ b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/Emotion.kt @@ -1,10 +1,7 @@ package com.threegap.bitnagil.domain.emotion.model -enum class Emotion { - CALM, - VITALITY, - LETHARGY, - ANXIETY, - SATISFACTION, - FATIGUE, -} +data class Emotion( + val emotionType: String, + val emotionMarbleName: String, + val imageUrl: String, +) diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/MyEmotion.kt b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/MyEmotion.kt deleted file mode 100644 index 36e226a9..00000000 --- a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/MyEmotion.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.threegap.bitnagil.domain.emotion.model - -data class MyEmotion( - val emotionMarbleType: Emotion?, - val emotionMarbleName: String?, - val imageUrl: String?, -) diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt index 1cb68de7..5b529798 100644 --- a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt +++ b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt @@ -1,11 +1,10 @@ package com.threegap.bitnagil.domain.emotion.repository -import com.threegap.bitnagil.domain.emotion.model.Emotion import com.threegap.bitnagil.domain.emotion.model.EmotionRecommendRoutine -import com.threegap.bitnagil.domain.emotion.model.MyEmotion +import com.threegap.bitnagil.domain.emotion.model.Emotion interface EmotionRepository { suspend fun getEmotions(): Result> - suspend fun registerEmotion(emotion: Emotion): Result> - suspend fun getMyEmotionMarble(currentDate: String): Result + suspend fun registerEmotion(emotionMarbleType: String): Result> + suspend fun getEmotionMarble(currentDate: String): Result } diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetEmotionUseCase.kt b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetEmotionUseCase.kt new file mode 100644 index 00000000..16d886d6 --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetEmotionUseCase.kt @@ -0,0 +1,12 @@ +package com.threegap.bitnagil.domain.emotion.usecase + +import com.threegap.bitnagil.domain.emotion.model.Emotion +import com.threegap.bitnagil.domain.emotion.repository.EmotionRepository +import javax.inject.Inject + +class GetEmotionUseCase @Inject constructor( + private val emotionRepository: EmotionRepository, +) { + suspend operator fun invoke(currentDate: String): Result = + emotionRepository.getEmotionMarble(currentDate) +} diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetMyEmotionUseCase.kt b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetMyEmotionUseCase.kt deleted file mode 100644 index a72157c9..00000000 --- a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetMyEmotionUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.threegap.bitnagil.domain.emotion.usecase - -import com.threegap.bitnagil.domain.emotion.model.MyEmotion -import com.threegap.bitnagil.domain.emotion.repository.EmotionRepository -import javax.inject.Inject - -class GetMyEmotionUseCase @Inject constructor( - private val emotionRepository: EmotionRepository, -) { - suspend operator fun invoke(currentDate: String): Result = - emotionRepository.getMyEmotionMarble(currentDate) -} diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/RegisterEmotionUseCase.kt b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/RegisterEmotionUseCase.kt index 6c695312..3e51863e 100644 --- a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/RegisterEmotionUseCase.kt +++ b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/RegisterEmotionUseCase.kt @@ -1,6 +1,5 @@ package com.threegap.bitnagil.domain.emotion.usecase -import com.threegap.bitnagil.domain.emotion.model.Emotion import com.threegap.bitnagil.domain.emotion.model.EmotionRecommendRoutine import com.threegap.bitnagil.domain.emotion.repository.EmotionRepository import javax.inject.Inject @@ -8,7 +7,7 @@ import javax.inject.Inject class RegisterEmotionUseCase @Inject constructor( private val emotionRepository: EmotionRepository, ) { - suspend operator fun invoke(emotion: Emotion): Result> { - return emotionRepository.registerEmotion(emotion) + suspend operator fun invoke(emotionType: String): Result> { + return emotionRepository.registerEmotion(emotionType) } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt index 48eaf1c4..c8c9a022 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt @@ -1,11 +1,11 @@ package com.threegap.bitnagil.presentation.emotion import androidx.activity.compose.BackHandler -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -22,23 +22,26 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import coil3.compose.AsyncImage +import coil3.request.ImageRequest +import coil3.request.crossfade import com.threegap.bitnagil.designsystem.BitnagilTheme import com.threegap.bitnagil.designsystem.component.atom.BitnagilSelectButton import com.threegap.bitnagil.designsystem.component.atom.BitnagilTextButton import com.threegap.bitnagil.designsystem.component.atom.BitnagilTextButtonColor -import com.threegap.bitnagil.designsystem.component.block.BitnagilProgressTopBar import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple import com.threegap.bitnagil.presentation.common.flow.collectAsEffect -import com.threegap.bitnagil.presentation.emotion.model.Emotion import com.threegap.bitnagil.presentation.emotion.model.EmotionRecommendRoutineUiModel import com.threegap.bitnagil.presentation.emotion.model.EmotionScreenStep +import com.threegap.bitnagil.presentation.emotion.model.EmotionUiModel import com.threegap.bitnagil.presentation.emotion.model.mvi.EmotionSideEffect import com.threegap.bitnagil.presentation.emotion.model.mvi.EmotionState @@ -67,7 +70,6 @@ fun EmotionScreenContainer( ) EmotionScreenStep.RecommendRoutines -> EmotionRecommendRoutineScreen( state = state, - onClickPreviousButton = viewModel::moveToPrev, onClickRoutine = viewModel::selectRecommendRoutine, onClickRegisterRecommendRoutines = viewModel::registerRecommendRoutines, onClickSkip = navigateToBack, @@ -79,7 +81,7 @@ fun EmotionScreenContainer( private fun EmotionScreen( state: EmotionState, onClickPreviousButton: () -> Unit, - onClickEmotion: (Emotion) -> Unit, + onClickEmotion: (String) -> Unit, ) { Column( modifier = Modifier @@ -117,18 +119,24 @@ private fun EmotionScreen( horizontalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(28.dp), ) { - items(state.emotions) { emotion -> + items(state.emotionTypeUiModels) { emotion -> Column( modifier = Modifier - .clickableWithoutRipple { onClickEmotion(emotion) }, + .clickableWithoutRipple { onClickEmotion(emotion.emotionType) }, horizontalAlignment = Alignment.CenterHorizontally, ) { - Image( - painter = painterResource(id = emotion.imageResourceId), + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(emotion.imageUrl) + .crossfade(true) + .build(), + modifier = Modifier.aspectRatio(1f), contentDescription = null, + error = emotion.offlineBackupImageResourceId?.let { painterResource(it) }, ) + Text( - text = emotion.emotionName, + text = emotion.emotionMarbleName, style = BitnagilTheme.typography.body1Regular.copy(color = BitnagilTheme.colors.coolGray20), ) } @@ -140,7 +148,6 @@ private fun EmotionScreen( @Composable private fun EmotionRecommendRoutineScreen( state: EmotionState, - onClickPreviousButton: () -> Unit, onClickRoutine: (String) -> Unit, onClickRegisterRecommendRoutines: () -> Unit, onClickSkip: () -> Unit, @@ -149,73 +156,65 @@ private fun EmotionRecommendRoutineScreen( modifier = Modifier .fillMaxSize() .background(color = BitnagilTheme.colors.coolGray99) - .statusBarsPadding(), + .statusBarsPadding() + .padding(start = 16.dp, end = 16.dp, bottom = 20.dp, top = 32.dp), ) { - BitnagilProgressTopBar( - onBackClick = onClickPreviousButton, - progress = 1f, + Spacer(modifier = Modifier.height(54.dp)) + + Text( + text = "오늘 감정에 따른\n루틴을 추천드릴께요!", + color = BitnagilTheme.colors.navy500, + style = BitnagilTheme.typography.title2Bold, ) + Spacer(modifier = Modifier.height(10.dp)) + + Text( + text = "오늘 당신의 감정 상태에 맞춰 구성된 맞춤 루틴이에요.\n원하는 루틴을 선택해서 가볍게 시작해보세요.", + color = BitnagilTheme.colors.coolGray50, + style = BitnagilTheme.typography.body2Medium, + ) + + Spacer(modifier = Modifier.height(28.dp)) + + val scrollState = rememberScrollState() Column( modifier = Modifier .weight(1f) - .padding(start = 16.dp, end = 16.dp, bottom = 20.dp, top = 32.dp), + .verticalScroll(state = scrollState), ) { - Text( - text = "오늘 감정에 따른\n루틴을 추천드릴께요!", - color = BitnagilTheme.colors.navy500, - style = BitnagilTheme.typography.title2Bold, - ) - - Spacer(modifier = Modifier.height(10.dp)) - - Text( - text = "오늘 당신의 감정 상태에 맞춰 구성된 맞춤 루틴이에요.\n원하는 루틴을 선택해서 가볍게 시작해보세요.", - color = BitnagilTheme.colors.coolGray50, - style = BitnagilTheme.typography.body2Medium, - ) - - Spacer(modifier = Modifier.height(28.dp)) - - val scrollState = rememberScrollState() - 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), - ) - } + 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), + ) } + } - Spacer(modifier = Modifier.height(12.dp)) + Spacer(modifier = Modifier.height(12.dp)) - BitnagilTextButton( - text = "변경하기", - onClick = onClickRegisterRecommendRoutines, - enabled = state.registerRecommendRoutinesButtonEnabled, - ) + BitnagilTextButton( + text = "변경하기", + onClick = onClickRegisterRecommendRoutines, + enabled = state.registerRecommendRoutinesButtonEnabled, + ) - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(10.dp)) - BitnagilTextButton( - text = "건너뛰기", - onClick = onClickSkip, - colors = BitnagilTextButtonColor.skip().copy( - defaultBackgroundColor = Color.Transparent, - pressedBackgroundColor = Color.Transparent, - disabledBackgroundColor = Color.Transparent, - ), - textStyle = BitnagilTheme.typography.body2Regular, - textDecoration = TextDecoration.Underline, - ) - } + BitnagilTextButton( + text = "건너뛰기", + onClick = onClickSkip, + colors = BitnagilTextButtonColor.skip().copy( + defaultBackgroundColor = Color.Transparent, + pressedBackgroundColor = Color.Transparent, + disabledBackgroundColor = Color.Transparent, + ), + textStyle = BitnagilTheme.typography.body2Regular, + textDecoration = TextDecoration.Underline, + ) } } @@ -225,7 +224,20 @@ private fun EmotionScreenPreview() { BitnagilTheme { EmotionScreen( state = EmotionState( - emotions = Emotion.entries, + emotionTypeUiModels = listOf( + EmotionUiModel( + emotionType = "emotionType", + imageUrl = "https://bitnagil-s3.s3.ap-northeast-2.amazonaws.com/home_satisfaction.png", + emotionMarbleName = "emotionMarbleName", + offlineBackupImageResourceId = null, + ), + EmotionUiModel( + emotionType = "emotionType", + imageUrl = "https://bitnagil-s3.s3.ap-northeast-2.amazonaws.com/home_satisfaction.png", + emotionMarbleName = "emotionMarbleName", + offlineBackupImageResourceId = null, + ) + ), isLoading = false, step = EmotionScreenStep.Emotion, recommendRoutines = listOf(), @@ -242,7 +254,14 @@ private fun EmotionRecommendRoutineScreenPreview() { BitnagilTheme { EmotionRecommendRoutineScreen( state = EmotionState( - emotions = Emotion.entries, + emotionTypeUiModels = listOf( + EmotionUiModel( + emotionType = "emotionType", + imageUrl = "https://bitnagil-s3.s3.ap-northeast-2.amazonaws.com/home_satisfaction.png", + emotionMarbleName = "emotionMarbleName", + offlineBackupImageResourceId = null, + ) + ), isLoading = false, step = EmotionScreenStep.RecommendRoutines, recommendRoutines = listOf( @@ -254,7 +273,6 @@ private fun EmotionRecommendRoutineScreenPreview() { ), ), ), - onClickPreviousButton = {}, onClickRoutine = {}, onClickRegisterRecommendRoutines = {}, onClickSkip = {}, diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionViewModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionViewModel.kt index 9729b1ec..5e95dd86 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionViewModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionViewModel.kt @@ -6,9 +6,9 @@ import com.threegap.bitnagil.domain.emotion.usecase.GetEmotionsUseCase import com.threegap.bitnagil.domain.emotion.usecase.RegisterEmotionUseCase import com.threegap.bitnagil.domain.onboarding.usecase.RegisterRecommendOnBoardingRoutinesUseCase import com.threegap.bitnagil.presentation.common.mviviewmodel.MviViewModel -import com.threegap.bitnagil.presentation.emotion.model.Emotion import com.threegap.bitnagil.presentation.emotion.model.EmotionRecommendRoutineUiModel import com.threegap.bitnagil.presentation.emotion.model.EmotionScreenStep +import com.threegap.bitnagil.presentation.emotion.model.EmotionUiModel import com.threegap.bitnagil.presentation.emotion.model.mvi.EmotionIntent import com.threegap.bitnagil.presentation.emotion.model.mvi.EmotionSideEffect import com.threegap.bitnagil.presentation.emotion.model.mvi.EmotionState @@ -36,7 +36,7 @@ class EmotionViewModel @Inject constructor( getEmotionsUseCase().fold( onSuccess = { emotions -> sendIntent( - EmotionIntent.EmotionListLoadSuccess(emotions = emotions.map { Emotion.fromDomain(it) }), + EmotionIntent.EmotionListLoadSuccess(emotionTypeUiModels = emotions.map { EmotionUiModel.fromDomain(it) }), ) }, onFailure = { @@ -50,7 +50,7 @@ class EmotionViewModel @Inject constructor( when (intent) { is EmotionIntent.EmotionListLoadSuccess -> { return state.copy( - emotions = intent.emotions, + emotionTypeUiModels = intent.emotionTypeUiModels, isLoading = false, ) } @@ -106,13 +106,13 @@ class EmotionViewModel @Inject constructor( } } - fun selectEmotion(emotion: Emotion) { + fun selectEmotion(emotionType: String) { val isLoading = stateFlow.value.isLoading if (isLoading) return viewModelScope.launch { sendIntent(EmotionIntent.RegisterEmotionLoading) - registerEmotionUseCase(emotion = emotion.toDomain()).fold( + registerEmotionUseCase(emotionType = emotionType).fold( onSuccess = { emotionRecommendRoutines -> val recommendRoutines = emotionRecommendRoutines.map { EmotionRecommendRoutineUiModel.fromEmotionRecommendRoutine(it) } sendIntent(EmotionIntent.RegisterEmotionSuccess(recommendRoutines)) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/Emotion.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/Emotion.kt deleted file mode 100644 index 415935a5..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/Emotion.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.threegap.bitnagil.presentation.emotion.model - -import com.threegap.bitnagil.designsystem.R -import com.threegap.bitnagil.domain.emotion.model.Emotion as DomainEmotion - -enum class Emotion( - val emotionName: String, - val imageResourceId: Int, -) { - CALM(emotionName = "평온함", imageResourceId = R.drawable.calm), - VITALITY(emotionName = "활기참", imageResourceId = R.drawable.vitality), - LETHARGY(emotionName = "무기력함", imageResourceId = R.drawable.lethargy), - ANXIETY(emotionName = "불안함", imageResourceId = R.drawable.anxiety), - SATISFACTION(emotionName = "만족함", imageResourceId = R.drawable.satisfaction), - FATIGUE(emotionName = "피로함", imageResourceId = R.drawable.fatigue), - ; - - companion object { - fun fromDomain(domain: DomainEmotion): Emotion { - return when (domain) { - DomainEmotion.CALM -> CALM - DomainEmotion.VITALITY -> VITALITY - DomainEmotion.LETHARGY -> LETHARGY - DomainEmotion.ANXIETY -> ANXIETY - DomainEmotion.SATISFACTION -> SATISFACTION - DomainEmotion.FATIGUE -> FATIGUE - } - } - } - - fun toDomain(): DomainEmotion { - return when (this) { - CALM -> DomainEmotion.CALM - VITALITY -> DomainEmotion.VITALITY - LETHARGY -> DomainEmotion.LETHARGY - ANXIETY -> DomainEmotion.ANXIETY - SATISFACTION -> DomainEmotion.SATISFACTION - FATIGUE -> DomainEmotion.FATIGUE - } - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionUiModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionUiModel.kt new file mode 100644 index 00000000..bdc13311 --- /dev/null +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionUiModel.kt @@ -0,0 +1,35 @@ +package com.threegap.bitnagil.presentation.emotion.model + +import android.os.Parcelable +import com.threegap.bitnagil.domain.emotion.model.Emotion +import com.threegap.bitnagil.designsystem.R +import kotlinx.parcelize.Parcelize + +@Parcelize +data class EmotionUiModel( + val emotionType: String, + val emotionMarbleName: String, + val imageUrl: String, + val offlineBackupImageResourceId: Int?, +) : Parcelable { + companion object { + fun fromDomain(emotion: Emotion) = EmotionUiModel( + emotionType = emotion.emotionType, + emotionMarbleName = emotion.emotionMarbleName, + imageUrl = emotion.imageUrl, + offlineBackupImageResourceId = getOfflineBackupImageResourceId(emotion.emotionType), + ) + + private fun getOfflineBackupImageResourceId(emotionType: String): Int? { + return when (emotionType) { + "CALM" -> R.drawable.calm + "VITALITY" -> R.drawable.vitality + "LETHARGY" -> R.drawable.lethargy + "ANXIETY" -> R.drawable.anxiety + "SATISFACTION" -> R.drawable.satisfaction + "FATIGUE" -> R.drawable.fatigue + else -> null + } + } + } +} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionIntent.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionIntent.kt index 33e2b74f..49b62216 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionIntent.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionIntent.kt @@ -1,11 +1,11 @@ package com.threegap.bitnagil.presentation.emotion.model.mvi import com.threegap.bitnagil.presentation.common.mviviewmodel.MviIntent -import com.threegap.bitnagil.presentation.emotion.model.Emotion import com.threegap.bitnagil.presentation.emotion.model.EmotionRecommendRoutineUiModel +import com.threegap.bitnagil.presentation.emotion.model.EmotionUiModel sealed class EmotionIntent : MviIntent { - data class EmotionListLoadSuccess(val emotions: List) : EmotionIntent() + data class EmotionListLoadSuccess(val emotionTypeUiModels: List) : EmotionIntent() data class RegisterEmotionSuccess(val recommendRoutines: List) : EmotionIntent() data object RegisterEmotionLoading : EmotionIntent() data object RegisterRecommendRoutinesLoading : EmotionIntent() diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionState.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionState.kt index 511c1b76..3e016ddb 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionState.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/mvi/EmotionState.kt @@ -2,22 +2,22 @@ package com.threegap.bitnagil.presentation.emotion.model.mvi import androidx.compose.runtime.Immutable import com.threegap.bitnagil.presentation.common.mviviewmodel.MviState -import com.threegap.bitnagil.presentation.emotion.model.Emotion import com.threegap.bitnagil.presentation.emotion.model.EmotionRecommendRoutineUiModel import com.threegap.bitnagil.presentation.emotion.model.EmotionScreenStep +import com.threegap.bitnagil.presentation.emotion.model.EmotionUiModel import kotlinx.parcelize.Parcelize @Parcelize @Immutable data class EmotionState( - val emotions: List, + val emotionTypeUiModels: List, val isLoading: Boolean, val recommendRoutines: List, val step: EmotionScreenStep, ) : MviState { companion object { val Init = EmotionState( - emotions = emptyList(), + emotionTypeUiModels = emptyList(), isLoading = true, recommendRoutines = emptyList(), step = EmotionScreenStep.Emotion, diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt index 4d560b72..58bada48 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt @@ -3,7 +3,7 @@ package com.threegap.bitnagil.presentation.home import android.util.Log import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import com.threegap.bitnagil.domain.emotion.usecase.GetMyEmotionUseCase +import com.threegap.bitnagil.domain.emotion.usecase.GetEmotionUseCase import com.threegap.bitnagil.domain.routine.model.RoutineCompletion import com.threegap.bitnagil.domain.routine.model.RoutineCompletionInfo import com.threegap.bitnagil.domain.routine.usecase.DeleteRoutineByDayUseCase @@ -40,7 +40,7 @@ class HomeViewModel @Inject constructor( savedStateHandle: SavedStateHandle, private val fetchWeeklyRoutinesUseCase: FetchWeeklyRoutinesUseCase, private val fetchUserProfileUseCase: FetchUserProfileUseCase, - private val getMyEmotionUseCase: GetMyEmotionUseCase, + private val getEmotionUseCase: GetEmotionUseCase, private val routineCompletionUseCase: RoutineCompletionUseCase, private val deleteRoutineUseCase: DeleteRoutineUseCase, private val deleteRoutineByDayUseCase: DeleteRoutineByDayUseCase, @@ -302,9 +302,9 @@ class HomeViewModel @Inject constructor( private fun getMyEmotion(currentDate: LocalDate) { sendIntent(HomeIntent.UpdateLoading(true)) viewModelScope.launch { - getMyEmotionUseCase(currentDate.toString()).fold( + getEmotionUseCase(currentDate.toString()).fold( onSuccess = { emotion -> - val ballType = EmotionBallType.fromDomainEmotion(emotion.emotionMarbleType) + val ballType = EmotionBallType.fromDomainEmotion(emotion?.emotionType) sendIntent(HomeIntent.LoadMyEmotion(ballType)) sendIntent(HomeIntent.UpdateLoading(false)) }, diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/EmotionBallType.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/EmotionBallType.kt index 6e4fbfd0..a829f0c0 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/EmotionBallType.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/EmotionBallType.kt @@ -3,7 +3,6 @@ package com.threegap.bitnagil.presentation.home.model import androidx.annotation.DrawableRes import androidx.compose.ui.graphics.Color import com.threegap.bitnagil.designsystem.R -import com.threegap.bitnagil.domain.emotion.model.Emotion enum class EmotionBallType( @DrawableRes val drawableId: Int, @@ -43,7 +42,7 @@ enum class EmotionBallType( ; companion object { - fun fromDomainEmotion(emotion: Emotion?): EmotionBallType? = - emotion?.let { valueOf(it.name) } + fun fromDomainEmotion(emotionMarbleType: String?): EmotionBallType? = + emotionMarbleType?.let { valueOf(it) } } } From 6b12a5534c2283e42dd975c5f65bbf8230c30474 Mon Sep 17 00:00:00 2001 From: yunsehwan Date: Wed, 6 Aug 2025 21:50:29 +0900 Subject: [PATCH 3/5] =?UTF-8?q?FEAT:=20=EA=B0=90=EC=A0=95=20=EA=B5=AC?= =?UTF-8?q?=EC=8A=AC=20=EB=B3=80=ED=99=94=EC=97=AC=EB=B6=80=EB=A5=BC=20?= =?UTF-8?q?=ED=99=88=20=ED=99=94=EB=A9=B4=EC=97=90=EC=84=9C=20=EA=B0=90?= =?UTF-8?q?=EC=A7=80=ED=95=98=EC=97=AC=20=EA=B0=90=EC=A0=95=20=EA=B5=AC?= =?UTF-8?q?=EC=8A=AC=EC=9D=84=20=EA=B0=B1=EC=8B=A0=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8F=84=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../emotion/repositoryImpl/EmotionRepositoryImpl.kt | 11 +++++++++++ .../domain/emotion/model/EmotionChangeEvent.kt | 5 +++++ .../domain/emotion/repository/EmotionRepository.kt | 3 +++ .../usecase/GetEmotionChangeEventFlowUseCase.kt | 12 ++++++++++++ .../bitnagil/presentation/home/HomeViewModel.kt | 13 ++++++++++++- 5 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/EmotionChangeEvent.kt create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetEmotionChangeEventFlowUseCase.kt diff --git a/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt b/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt index e4b4f401..d92d6137 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt @@ -4,7 +4,11 @@ import com.threegap.bitnagil.data.emotion.datasource.EmotionDataSource import com.threegap.bitnagil.data.emotion.model.response.toDomain import com.threegap.bitnagil.domain.emotion.model.EmotionRecommendRoutine import com.threegap.bitnagil.domain.emotion.model.Emotion +import com.threegap.bitnagil.domain.emotion.model.EmotionChangeEvent import com.threegap.bitnagil.domain.emotion.repository.EmotionRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asSharedFlow import javax.inject.Inject class EmotionRepositoryImpl @Inject constructor( @@ -22,9 +26,16 @@ class EmotionRepositoryImpl @Inject constructor( emotionRecommendedRoutineDto -> emotionRecommendedRoutineDto.toEmotionRecommendRoutine() } + }.also { + if (it.isSuccess) { + _emotionChangeEventFlow.emit(EmotionChangeEvent.ChangeEmotion(emotionMarbleType)) + } } } override suspend fun getEmotionMarble(currentDate: String): Result = emotionDataSource.getEmotionMarble(currentDate).map { it.toDomain() } + + private val _emotionChangeEventFlow = MutableSharedFlow() + override suspend fun getEmotionChangeEventFlow(): Flow = _emotionChangeEventFlow.asSharedFlow() } diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/EmotionChangeEvent.kt b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/EmotionChangeEvent.kt new file mode 100644 index 00000000..f848a647 --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/EmotionChangeEvent.kt @@ -0,0 +1,5 @@ +package com.threegap.bitnagil.domain.emotion.model + +sealed interface EmotionChangeEvent { + data class ChangeEmotion(val emotionType: String) : EmotionChangeEvent +} diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt index 5b529798..acae5bdf 100644 --- a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt +++ b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt @@ -2,9 +2,12 @@ package com.threegap.bitnagil.domain.emotion.repository import com.threegap.bitnagil.domain.emotion.model.EmotionRecommendRoutine import com.threegap.bitnagil.domain.emotion.model.Emotion +import com.threegap.bitnagil.domain.emotion.model.EmotionChangeEvent +import kotlinx.coroutines.flow.Flow interface EmotionRepository { suspend fun getEmotions(): Result> suspend fun registerEmotion(emotionMarbleType: String): Result> suspend fun getEmotionMarble(currentDate: String): Result + suspend fun getEmotionChangeEventFlow(): Flow } diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetEmotionChangeEventFlowUseCase.kt b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetEmotionChangeEventFlowUseCase.kt new file mode 100644 index 00000000..d30147c4 --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetEmotionChangeEventFlowUseCase.kt @@ -0,0 +1,12 @@ +package com.threegap.bitnagil.domain.emotion.usecase + +import com.threegap.bitnagil.domain.emotion.model.EmotionChangeEvent +import com.threegap.bitnagil.domain.emotion.repository.EmotionRepository +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class GetEmotionChangeEventFlowUseCase @Inject constructor( + private val repository: EmotionRepository, +) { + suspend operator fun invoke(): Flow = repository.getEmotionChangeEventFlow() +} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt index 58bada48..f65874c8 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt @@ -3,6 +3,7 @@ package com.threegap.bitnagil.presentation.home import android.util.Log import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope +import com.threegap.bitnagil.domain.emotion.usecase.GetEmotionChangeEventFlowUseCase import com.threegap.bitnagil.domain.emotion.usecase.GetEmotionUseCase import com.threegap.bitnagil.domain.routine.model.RoutineCompletion import com.threegap.bitnagil.domain.routine.model.RoutineCompletionInfo @@ -45,6 +46,7 @@ class HomeViewModel @Inject constructor( private val deleteRoutineUseCase: DeleteRoutineUseCase, private val deleteRoutineByDayUseCase: DeleteRoutineByDayUseCase, private val getWriteRoutineEventFlowUseCase: GetWriteRoutineEventFlowUseCase, + private val getEmotionChangeEventFlowUseCase: GetEmotionChangeEventFlowUseCase, ) : MviViewModel( initState = HomeState(), savedStateHandle = savedStateHandle, @@ -55,6 +57,7 @@ class HomeViewModel @Inject constructor( init { observeWriteRoutineEvent() + observeEmotionChangeEvent() observeWeekChanges() observeRoutineUpdates() fetchWeeklyRoutines(container.stateFlow.value.currentWeeks) @@ -234,7 +237,15 @@ class HomeViewModel @Inject constructor( private fun observeWriteRoutineEvent() { viewModelScope.launch { getWriteRoutineEventFlowUseCase().collect { - fetchWeeklyRoutines(container.stateFlow.value.currentWeeks) + fetchWeeklyRoutines(stateFlow.value.currentWeeks) + } + } + } + + private fun observeEmotionChangeEvent() { + viewModelScope.launch { + getEmotionChangeEventFlowUseCase().collect { + getMyEmotion(stateFlow.value.selectedDate) } } } From cc7a40f25ceb19394241e994bc1d4719011176bf Mon Sep 17 00:00:00 2001 From: yunsehwan Date: Wed, 6 Aug 2025 21:54:39 +0900 Subject: [PATCH 4/5] =?UTF-8?q?CHORE:=20ktlint=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/emotion/model/response/GetEmotionResponse.kt | 2 +- .../data/emotion/repositoryImpl/EmotionRepositoryImpl.kt | 2 +- .../bitnagil/domain/emotion/repository/EmotionRepository.kt | 2 +- .../threegap/bitnagil/presentation/emotion/EmotionScreen.kt | 4 ++-- .../bitnagil/presentation/emotion/model/EmotionUiModel.kt | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/GetEmotionResponse.kt b/data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/GetEmotionResponse.kt index 84aff760..01e75c86 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/GetEmotionResponse.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/GetEmotionResponse.kt @@ -19,7 +19,7 @@ fun GetEmotionResponse.toDomain(): Emotion? { Emotion( emotionType = emotionMarbleType, emotionMarbleName = emotionMarbleName, - imageUrl = imageUrl + imageUrl = imageUrl, ) } else { null diff --git a/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt b/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt index d92d6137..b5748332 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt @@ -2,9 +2,9 @@ package com.threegap.bitnagil.data.emotion.repositoryImpl import com.threegap.bitnagil.data.emotion.datasource.EmotionDataSource import com.threegap.bitnagil.data.emotion.model.response.toDomain -import com.threegap.bitnagil.domain.emotion.model.EmotionRecommendRoutine import com.threegap.bitnagil.domain.emotion.model.Emotion import com.threegap.bitnagil.domain.emotion.model.EmotionChangeEvent +import com.threegap.bitnagil.domain.emotion.model.EmotionRecommendRoutine import com.threegap.bitnagil.domain.emotion.repository.EmotionRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt index acae5bdf..56367614 100644 --- a/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt +++ b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/repository/EmotionRepository.kt @@ -1,8 +1,8 @@ package com.threegap.bitnagil.domain.emotion.repository -import com.threegap.bitnagil.domain.emotion.model.EmotionRecommendRoutine import com.threegap.bitnagil.domain.emotion.model.Emotion import com.threegap.bitnagil.domain.emotion.model.EmotionChangeEvent +import com.threegap.bitnagil.domain.emotion.model.EmotionRecommendRoutine import kotlinx.coroutines.flow.Flow interface EmotionRepository { diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt index c8c9a022..bcdfb249 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt @@ -236,7 +236,7 @@ private fun EmotionScreenPreview() { imageUrl = "https://bitnagil-s3.s3.ap-northeast-2.amazonaws.com/home_satisfaction.png", emotionMarbleName = "emotionMarbleName", offlineBackupImageResourceId = null, - ) + ), ), isLoading = false, step = EmotionScreenStep.Emotion, @@ -260,7 +260,7 @@ private fun EmotionRecommendRoutineScreenPreview() { imageUrl = "https://bitnagil-s3.s3.ap-northeast-2.amazonaws.com/home_satisfaction.png", emotionMarbleName = "emotionMarbleName", offlineBackupImageResourceId = null, - ) + ), ), isLoading = false, step = EmotionScreenStep.RecommendRoutines, diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionUiModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionUiModel.kt index bdc13311..4f575688 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionUiModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/EmotionUiModel.kt @@ -1,8 +1,8 @@ package com.threegap.bitnagil.presentation.emotion.model import android.os.Parcelable -import com.threegap.bitnagil.domain.emotion.model.Emotion import com.threegap.bitnagil.designsystem.R +import com.threegap.bitnagil.domain.emotion.model.Emotion import kotlinx.parcelize.Parcelize @Parcelize From e615480b1f5254716c0f79591904aa915751ea32 Mon Sep 17 00:00:00 2001 From: yunsehwan Date: Thu, 7 Aug 2025 19:16:42 +0900 Subject: [PATCH 5/5] =?UTF-8?q?FIX:=20=EA=B0=90=EC=A0=95=20=EA=B5=AC?= =?UTF-8?q?=EC=8A=AC=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=EC=8B=9C=20?= =?UTF-8?q?=EC=98=A4=EB=8A=98=20=EB=82=A0=EC=A7=9C=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EA=B0=90=EC=A0=95=20=EA=B5=AC=EC=8A=AC=EC=9D=84=20?= =?UTF-8?q?=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/threegap/bitnagil/presentation/home/HomeViewModel.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt index f65874c8..0a0a3fc8 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt @@ -245,7 +245,8 @@ class HomeViewModel @Inject constructor( private fun observeEmotionChangeEvent() { viewModelScope.launch { getEmotionChangeEventFlowUseCase().collect { - getMyEmotion(stateFlow.value.selectedDate) + val currentDate = LocalDate.now() + getMyEmotion(currentDate) } } }