From 22b43bfb0c4f2210a59cd9e4f4edd5a203057bfa Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Tue, 29 Jul 2025 20:00:15 +0900 Subject: [PATCH 01/12] =?UTF-8?q?Feat:=20routineCompletionId=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../threegap/bitnagil/data/routine/mapper/RoutineMapper.kt | 2 ++ .../bitnagil/data/routine/model/response/RoutineDto.kt | 2 ++ .../bitnagil/data/routine/model/response/SubRoutineDto.kt | 2 ++ .../com/threegap/bitnagil/domain/routine/model/Routine.kt | 1 + .../com/threegap/bitnagil/domain/routine/model/SubRoutine.kt | 1 + .../presentation/home/component/block/RoutineItem.kt | 4 ++++ .../presentation/home/component/block/SubRoutinesItem.kt | 4 ++++ .../home/component/template/RoutineDetailsBottomSheet.kt | 5 +++++ .../presentation/home/component/template/RoutineSection.kt | 4 ++++ .../bitnagil/presentation/home/model/RoutineUiModel.kt | 2 ++ .../bitnagil/presentation/home/model/SubRoutineUiModel.kt | 2 ++ 11 files changed, 29 insertions(+) diff --git a/data/src/main/java/com/threegap/bitnagil/data/routine/mapper/RoutineMapper.kt b/data/src/main/java/com/threegap/bitnagil/data/routine/mapper/RoutineMapper.kt index 593cb6ec..be747e8e 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/routine/mapper/RoutineMapper.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/routine/mapper/RoutineMapper.kt @@ -29,6 +29,7 @@ internal fun RoutineDto.toDomain() = executionTime = this.executionTime, subRoutines = this.subRoutines.map { it.toDomain() }, isModified = this.isModified, + routineCompletionId = this.routineCompletionId, isCompleted = this.isCompleted, repeatDay = this.repeatDay.map { DayOfWeek.fromString(it) }, routineType = RoutineType.fromString(this.routineType), @@ -41,6 +42,7 @@ internal fun SubRoutineDto.toDomain() = subRoutineName = this.subRoutineName, isModified = this.isModified, sortOrder = this.sortOrder, + routineCompletionId = this.routineCompletionId, isCompleted = this.isCompleted, routineType = RoutineType.fromString(this.routineType), ) diff --git a/data/src/main/java/com/threegap/bitnagil/data/routine/model/response/RoutineDto.kt b/data/src/main/java/com/threegap/bitnagil/data/routine/model/response/RoutineDto.kt index f4ccc2ae..5b93cfff 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/routine/model/response/RoutineDto.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/routine/model/response/RoutineDto.kt @@ -19,6 +19,8 @@ data class RoutineDto( val subRoutines: List, @SerialName("modifiedYn") val isModified: Boolean, + @SerialName("routineCompletionId") + val routineCompletionId: Int?, @SerialName("completeYn") val isCompleted: Boolean, @SerialName("routineType") diff --git a/data/src/main/java/com/threegap/bitnagil/data/routine/model/response/SubRoutineDto.kt b/data/src/main/java/com/threegap/bitnagil/data/routine/model/response/SubRoutineDto.kt index 61f79d73..ba573a9b 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/routine/model/response/SubRoutineDto.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/routine/model/response/SubRoutineDto.kt @@ -15,6 +15,8 @@ data class SubRoutineDto( val isModified: Boolean, @SerialName("sortOrder") val sortOrder: Int, + @SerialName("routineCompletionId") + val routineCompletionId: Int?, @SerialName("completeYn") val isCompleted: Boolean, @SerialName("routineType") diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/Routine.kt b/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/Routine.kt index ed64aaa2..808ba180 100644 --- a/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/Routine.kt +++ b/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/Routine.kt @@ -8,6 +8,7 @@ data class Routine( val executionTime: String, val subRoutines: List, val isModified: Boolean, + val routineCompletionId: Int?, val isCompleted: Boolean, val routineType: RoutineType, ) { diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/SubRoutine.kt b/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/SubRoutine.kt index 03dd8b9d..3101b38c 100644 --- a/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/SubRoutine.kt +++ b/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/SubRoutine.kt @@ -6,6 +6,7 @@ data class SubRoutine( val subRoutineName: String, val isModified: Boolean, val sortOrder: Int, + val routineCompletionId: Int?, val isCompleted: Boolean, val routineType: RoutineType, ) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/RoutineItem.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/RoutineItem.kt index d1b90329..7fa94129 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/RoutineItem.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/RoutineItem.kt @@ -78,6 +78,7 @@ private fun RoutineItemPreview() { routineName = "개운하게 일어나기", executionTime = "20:30:00", isCompleted = false, + routineCompletionId = 1, isModified = false, subRoutines = listOf( SubRoutineUiModel( @@ -85,6 +86,7 @@ private fun RoutineItemPreview() { historySeq = 1, subRoutineName = "물 마시기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, @@ -94,6 +96,7 @@ private fun RoutineItemPreview() { historySeq = 1, subRoutineName = "스트레칭하기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, @@ -103,6 +106,7 @@ private fun RoutineItemPreview() { historySeq = 1, subRoutineName = "심호흡하기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt index 64e96c3e..3ec3279e 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt @@ -86,6 +86,7 @@ private fun SubRoutinesItemPreview() { historySeq = 1, subRoutineName = "물 마시기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, @@ -95,6 +96,7 @@ private fun SubRoutinesItemPreview() { historySeq = 1, subRoutineName = "스트레칭하기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, @@ -104,6 +106,7 @@ private fun SubRoutinesItemPreview() { historySeq = 1, subRoutineName = "심호흡하기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, @@ -112,3 +115,4 @@ private fun SubRoutinesItemPreview() { onSubRoutineToggle = { _, _ -> }, ) } + diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineDetailsBottomSheet.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineDetailsBottomSheet.kt index b79a7bb0..c841ce1d 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineDetailsBottomSheet.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineDetailsBottomSheet.kt @@ -266,6 +266,7 @@ private fun RoutineInfoContentPreview() { routineName = "개운하게 일어나기", executionTime = "20:30:00", isCompleted = false, + routineCompletionId = 1, isModified = false, subRoutines = listOf( SubRoutineUiModel( @@ -273,6 +274,7 @@ private fun RoutineInfoContentPreview() { historySeq = 1, subRoutineName = "물 마시기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, @@ -282,6 +284,7 @@ private fun RoutineInfoContentPreview() { historySeq = 1, subRoutineName = "스트레칭하기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, @@ -291,6 +294,7 @@ private fun RoutineInfoContentPreview() { historySeq = 1, subRoutineName = "심호흡하기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, @@ -313,6 +317,7 @@ private fun RoutineInfoContentSinglePreview() { routineName = "개운하게 일어나기", executionTime = "20:30:00", isCompleted = false, + routineCompletionId = 1, isModified = false, subRoutines = emptyList(), repeatDay = emptyList(), diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineSection.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineSection.kt index 5d9bf07d..7e35b987 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineSection.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineSection.kt @@ -107,6 +107,7 @@ private fun RoutineTemplatePreview() { routineId = "uuid1", routineName = "개운하게 일어나기", executionTime = "20:30:00", + routineCompletionId = 1, isCompleted = false, isModified = false, subRoutines = listOf( @@ -115,6 +116,7 @@ private fun RoutineTemplatePreview() { historySeq = 1, subRoutineName = "물 마시기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, @@ -124,6 +126,7 @@ private fun RoutineTemplatePreview() { historySeq = 1, subRoutineName = "스트레칭하기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, @@ -133,6 +136,7 @@ private fun RoutineTemplatePreview() { historySeq = 1, subRoutineName = "심호흡하기", sortOrder = 1, + routineCompletionId = 1, isCompleted = false, isModified = false, routineType = RoutineType.SUB_ROUTINE, diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/RoutineUiModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/RoutineUiModel.kt index 8c613f1d..9dc7fdff 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/RoutineUiModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/RoutineUiModel.kt @@ -15,6 +15,7 @@ data class RoutineUiModel( val executionTime: String, val subRoutines: List, val isModified: Boolean = false, + val routineCompletionId: Int?, val isCompleted: Boolean = false, val routineType: RoutineType, ) : Parcelable @@ -28,6 +29,7 @@ fun Routine.toUiModel(): RoutineUiModel = executionTime = this.executionTime, subRoutines = this.subRoutines.map { it.toUiModel() }, isModified = this.isModified, + routineCompletionId = this.routineCompletionId, isCompleted = this.isCompleted, routineType = this.routineType, ) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/SubRoutineUiModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/SubRoutineUiModel.kt index 766cb702..6d995543 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/SubRoutineUiModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/SubRoutineUiModel.kt @@ -11,6 +11,7 @@ data class SubRoutineUiModel( val historySeq: Int, val subRoutineName: String, val sortOrder: Int, + val routineCompletionId: Int?, val isCompleted: Boolean = false, val isModified: Boolean = false, val routineType: RoutineType, @@ -21,6 +22,7 @@ fun SubRoutine.toUiModel(): SubRoutineUiModel = subRoutineId = this.subRoutineId, historySeq = this.historySeq, subRoutineName = this.subRoutineName, + routineCompletionId = this.routineCompletionId, sortOrder = this.sortOrder, isCompleted = this.isCompleted, isModified = this.isModified, From 83a6d18140e3c005a8e2c98e175433f0c5758e6d Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Tue, 29 Jul 2025 21:28:38 +0900 Subject: [PATCH 02/12] =?UTF-8?q?Feat:=20=EB=B0=98=EB=B3=B5=EB=A3=A8?= =?UTF-8?q?=ED=8B=B4=20=EB=8B=A8=EC=9D=BC=20=EC=82=AD=EC=A0=9C=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RoutineByDayDeletion: 특정 날짜의 루틴 삭제 정보 - SubRoutineDeletionInfo: 하위 루틴 삭제 정보 --- .../domain/routine/model/RoutineByDayDeletion.kt | 9 +++++++++ .../domain/routine/model/SubRoutineDeletionInfo.kt | 6 ++++++ 2 files changed, 15 insertions(+) create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/routine/model/RoutineByDayDeletion.kt create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/routine/model/SubRoutineDeletionInfo.kt diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/RoutineByDayDeletion.kt b/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/RoutineByDayDeletion.kt new file mode 100644 index 00000000..a5b7c7cb --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/RoutineByDayDeletion.kt @@ -0,0 +1,9 @@ +package com.threegap.bitnagil.domain.routine.model + +data class RoutineByDayDeletion( + val routineCompletionId: Int?, + val routineId: String, + val subRoutineInfosForDelete: List, + val performedDate: String, + val historySeq: Int, +) diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/SubRoutineDeletionInfo.kt b/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/SubRoutineDeletionInfo.kt new file mode 100644 index 00000000..24289e58 --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/SubRoutineDeletionInfo.kt @@ -0,0 +1,6 @@ +package com.threegap.bitnagil.domain.routine.model + +data class SubRoutineDeletionInfo( + val routineCompletionId: Int?, + val subRoutineId: String, +) From e8f6d41efd258f5671d2596ca5f8a904f74c0469 Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Tue, 29 Jul 2025 21:36:20 +0900 Subject: [PATCH 03/12] =?UTF-8?q?Feat:=20=EB=B0=98=EB=B3=B5=EB=A3=A8?= =?UTF-8?q?=ED=8B=B4=20=EB=8B=A8=EC=9D=BC=20=EC=82=AD=EC=A0=9C=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20Dto=20=EB=AA=A8=EB=8D=B8=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RoutineByDayDeletion DTO 및 Mapper 추가 --- .../request/RoutineByDayDeletionRequestDto.kt | 28 +++++++++++++++++++ .../request/SubRoutineDeletionInfoDto.kt | 19 +++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 data/src/main/java/com/threegap/bitnagil/data/routine/model/request/RoutineByDayDeletionRequestDto.kt create mode 100644 data/src/main/java/com/threegap/bitnagil/data/routine/model/request/SubRoutineDeletionInfoDto.kt diff --git a/data/src/main/java/com/threegap/bitnagil/data/routine/model/request/RoutineByDayDeletionRequestDto.kt b/data/src/main/java/com/threegap/bitnagil/data/routine/model/request/RoutineByDayDeletionRequestDto.kt new file mode 100644 index 00000000..b4ce96d2 --- /dev/null +++ b/data/src/main/java/com/threegap/bitnagil/data/routine/model/request/RoutineByDayDeletionRequestDto.kt @@ -0,0 +1,28 @@ +package com.threegap.bitnagil.data.routine.model.request + +import com.threegap.bitnagil.domain.routine.model.RoutineByDayDeletion +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class RoutineByDayDeletionRequestDto( + @SerialName("routineCompletionId") + val routineCompletionId: Int?, + @SerialName("routineId") + val routineId: String, + @SerialName("subRoutineInfosForDelete") + val subRoutineInfosForDelete: List, + @SerialName("performedDate") + val performedDate: String, + @SerialName("historySeq") + val historySeq: Int, +) + +fun RoutineByDayDeletion.toDto() = + RoutineByDayDeletionRequestDto( + routineCompletionId = this.routineCompletionId, + routineId = this.routineId, + subRoutineInfosForDelete = this.subRoutineInfosForDelete.map { it.toDto() }, + performedDate = this.performedDate, + historySeq = this.historySeq, + ) diff --git a/data/src/main/java/com/threegap/bitnagil/data/routine/model/request/SubRoutineDeletionInfoDto.kt b/data/src/main/java/com/threegap/bitnagil/data/routine/model/request/SubRoutineDeletionInfoDto.kt new file mode 100644 index 00000000..f10463ec --- /dev/null +++ b/data/src/main/java/com/threegap/bitnagil/data/routine/model/request/SubRoutineDeletionInfoDto.kt @@ -0,0 +1,19 @@ +package com.threegap.bitnagil.data.routine.model.request + +import com.threegap.bitnagil.domain.routine.model.SubRoutineDeletionInfo +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SubRoutineDeletionInfoDto( + @SerialName("routineCompletionId") + val routineCompletionId: Int?, + @SerialName("subRoutineId") + val subRoutineId: String, +) + +fun SubRoutineDeletionInfo.toDto() = + SubRoutineDeletionInfoDto( + routineCompletionId = this.routineCompletionId, + subRoutineId = this.subRoutineId, + ) From 55db03653614127a799ebcb2cd5b2fad9bc11a49 Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Tue, 29 Jul 2025 22:32:53 +0900 Subject: [PATCH 04/12] =?UTF-8?q?Feat:=20=EB=B0=98=EB=B3=B5=EB=A3=A8?= =?UTF-8?q?=ED=8B=B4=20=EB=8B=A8=EC=9D=BC=20=EC=82=AD=EC=A0=9C=20API=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../routine/datasource/RoutineRemoteDataSource.kt | 2 ++ .../datasourceImpl/RoutineRemoteDataSourceImpl.kt | 6 ++++++ .../routine/repositoryImpl/RoutineRepositoryImpl.kt | 5 +++++ .../bitnagil/data/routine/service/RoutineService.kt | 7 +++++++ .../domain/routine/repository/RoutineRepository.kt | 2 ++ .../routine/usecase/DeleteRoutineByDayUseCase.kt | 12 ++++++++++++ 6 files changed, 34 insertions(+) create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/routine/usecase/DeleteRoutineByDayUseCase.kt diff --git a/data/src/main/java/com/threegap/bitnagil/data/routine/datasource/RoutineRemoteDataSource.kt b/data/src/main/java/com/threegap/bitnagil/data/routine/datasource/RoutineRemoteDataSource.kt index f21e8b93..daaae4f0 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/routine/datasource/RoutineRemoteDataSource.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/routine/datasource/RoutineRemoteDataSource.kt @@ -1,5 +1,6 @@ package com.threegap.bitnagil.data.routine.datasource +import com.threegap.bitnagil.data.routine.model.request.RoutineByDayDeletionRequestDto import com.threegap.bitnagil.data.routine.model.request.RoutineCompletionRequestDto import com.threegap.bitnagil.data.routine.model.response.RoutinesResponseDto @@ -7,4 +8,5 @@ interface RoutineRemoteDataSource { suspend fun fetchWeeklyRoutines(startDate: String, endDate: String): Result suspend fun syncRoutineCompletion(routineCompletionRequestDto: RoutineCompletionRequestDto): Result suspend fun deleteRoutine(routineId: String): Result + suspend fun deleteRoutineByDay(routineByDayDeletionRequestDto: RoutineByDayDeletionRequestDto): Result } diff --git a/data/src/main/java/com/threegap/bitnagil/data/routine/datasourceImpl/RoutineRemoteDataSourceImpl.kt b/data/src/main/java/com/threegap/bitnagil/data/routine/datasourceImpl/RoutineRemoteDataSourceImpl.kt index 02340651..9e263f27 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/routine/datasourceImpl/RoutineRemoteDataSourceImpl.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/routine/datasourceImpl/RoutineRemoteDataSourceImpl.kt @@ -3,6 +3,7 @@ package com.threegap.bitnagil.data.routine.datasourceImpl import com.threegap.bitnagil.data.common.safeApiCall import com.threegap.bitnagil.data.common.safeUnitApiCall import com.threegap.bitnagil.data.routine.datasource.RoutineRemoteDataSource +import com.threegap.bitnagil.data.routine.model.request.RoutineByDayDeletionRequestDto import com.threegap.bitnagil.data.routine.model.request.RoutineCompletionRequestDto import com.threegap.bitnagil.data.routine.model.response.RoutinesResponseDto import com.threegap.bitnagil.data.routine.service.RoutineService @@ -25,4 +26,9 @@ class RoutineRemoteDataSourceImpl @Inject constructor( safeUnitApiCall { routineService.deleteRoutine(routineId) } + + override suspend fun deleteRoutineByDay(routineByDayDeletionRequestDto: RoutineByDayDeletionRequestDto): Result = + safeUnitApiCall { + routineService.deleteRoutineByDay(routineByDayDeletionRequestDto) + } } diff --git a/data/src/main/java/com/threegap/bitnagil/data/routine/repositoryImpl/RoutineRepositoryImpl.kt b/data/src/main/java/com/threegap/bitnagil/data/routine/repositoryImpl/RoutineRepositoryImpl.kt index 81f7f23c..d38e89c5 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/routine/repositoryImpl/RoutineRepositoryImpl.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/routine/repositoryImpl/RoutineRepositoryImpl.kt @@ -3,6 +3,8 @@ package com.threegap.bitnagil.data.routine.repositoryImpl import com.threegap.bitnagil.data.routine.datasource.RoutineRemoteDataSource import com.threegap.bitnagil.data.routine.mapper.toDomain import com.threegap.bitnagil.data.routine.mapper.toDto +import com.threegap.bitnagil.data.routine.model.request.toDto +import com.threegap.bitnagil.domain.routine.model.RoutineByDayDeletion import com.threegap.bitnagil.domain.routine.model.RoutineCompletion import com.threegap.bitnagil.domain.routine.model.Routines import com.threegap.bitnagil.domain.routine.repository.RoutineRepository @@ -20,4 +22,7 @@ class RoutineRepositoryImpl @Inject constructor( override suspend fun deleteRoutine(routineId: String): Result = routineRemoteDataSource.deleteRoutine(routineId) + + override suspend fun deleteRoutineByDay(routineByDayDeletion: RoutineByDayDeletion): Result = + routineRemoteDataSource.deleteRoutineByDay(routineByDayDeletion.toDto()) } diff --git a/data/src/main/java/com/threegap/bitnagil/data/routine/service/RoutineService.kt b/data/src/main/java/com/threegap/bitnagil/data/routine/service/RoutineService.kt index 122e36bc..9d567e93 100644 --- a/data/src/main/java/com/threegap/bitnagil/data/routine/service/RoutineService.kt +++ b/data/src/main/java/com/threegap/bitnagil/data/routine/service/RoutineService.kt @@ -1,11 +1,13 @@ package com.threegap.bitnagil.data.routine.service +import com.threegap.bitnagil.data.routine.model.request.RoutineByDayDeletionRequestDto import com.threegap.bitnagil.data.routine.model.request.RoutineCompletionRequestDto import com.threegap.bitnagil.data.routine.model.response.RoutinesResponseDto import com.threegap.bitnagil.network.model.BaseResponse import retrofit2.http.Body import retrofit2.http.DELETE import retrofit2.http.GET +import retrofit2.http.HTTP import retrofit2.http.POST import retrofit2.http.Path import retrofit2.http.Query @@ -26,4 +28,9 @@ interface RoutineService { suspend fun deleteRoutine( @Path("routineId") routineId: String, ): BaseResponse + + @HTTP(method = "DELETE", path = "/api/v1/routines/day", hasBody = true) + suspend fun deleteRoutineByDay( + @Body request: RoutineByDayDeletionRequestDto, + ): BaseResponse } diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/routine/repository/RoutineRepository.kt b/domain/src/main/java/com/threegap/bitnagil/domain/routine/repository/RoutineRepository.kt index dfb917bb..8cb09cfc 100644 --- a/domain/src/main/java/com/threegap/bitnagil/domain/routine/repository/RoutineRepository.kt +++ b/domain/src/main/java/com/threegap/bitnagil/domain/routine/repository/RoutineRepository.kt @@ -1,5 +1,6 @@ package com.threegap.bitnagil.domain.routine.repository +import com.threegap.bitnagil.domain.routine.model.RoutineByDayDeletion import com.threegap.bitnagil.domain.routine.model.RoutineCompletion import com.threegap.bitnagil.domain.routine.model.Routines @@ -7,4 +8,5 @@ interface RoutineRepository { suspend fun fetchWeeklyRoutines(startDate: String, endDate: String): Result suspend fun syncRoutineCompletion(routineCompletion: RoutineCompletion): Result suspend fun deleteRoutine(routineId: String): Result + suspend fun deleteRoutineByDay(routineByDayDeletion: RoutineByDayDeletion): Result } diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/routine/usecase/DeleteRoutineByDayUseCase.kt b/domain/src/main/java/com/threegap/bitnagil/domain/routine/usecase/DeleteRoutineByDayUseCase.kt new file mode 100644 index 00000000..01df72f1 --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/routine/usecase/DeleteRoutineByDayUseCase.kt @@ -0,0 +1,12 @@ +package com.threegap.bitnagil.domain.routine.usecase + +import com.threegap.bitnagil.domain.routine.model.RoutineByDayDeletion +import com.threegap.bitnagil.domain.routine.repository.RoutineRepository +import javax.inject.Inject + +class DeleteRoutineByDayUseCase @Inject constructor( + private val routineRepository: RoutineRepository, +) { + suspend operator fun invoke(routineByDayDeletion: RoutineByDayDeletion) = + routineRepository.deleteRoutineByDay(routineByDayDeletion) +} From 7ae11c6e08003ec43ab48c40143384fe25f4dfcc Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Tue, 29 Jul 2025 22:44:59 +0900 Subject: [PATCH 05/12] =?UTF-8?q?Feat:=20=EB=B0=98=EB=B3=B5=20=EB=A3=A8?= =?UTF-8?q?=ED=8B=B4=20=EB=8B=A8=EC=9D=BC=20=EC=82=AD=EC=A0=9C=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20Intent=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../threegap/bitnagil/presentation/home/model/HomeIntent.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt index b6cd986a..eb2659a9 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt @@ -13,6 +13,9 @@ sealed class HomeIntent : MviIntent { data class DeleteRoutineOptimistically(val routineId: String) : HomeIntent() data class ConfirmRoutineDeletion(val routineId: String) : HomeIntent() data class RestoreRoutinesAfterDeleteFailure(val backupRoutines: RoutinesUiModel) : HomeIntent() + data class DeleteRoutineByDayOptimistically(val routineId: String, val performedDate: String) : HomeIntent() + data class ConfirmRoutineByDayDeletion(val routineId: String, val performedDate: String) : HomeIntent() + data class RestoreRoutinesAfterDeleteByDayFailure(val backupRoutines: RoutinesUiModel) : HomeIntent() data class ShowRoutineDetailsBottomSheet(val routine: RoutineUiModel) : HomeIntent() data class ShowDeleteConfirmDialog(val routine: RoutineUiModel) : HomeIntent() data object OnPreviousWeekClick : HomeIntent() From 341a1ebc6baeaf7d57e774cd829ec55200c69ab2 Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Tue, 29 Jul 2025 22:47:33 +0900 Subject: [PATCH 06/12] =?UTF-8?q?Feat:=20=EB=A3=A8=ED=8B=B4=20=EB=8B=B9?= =?UTF-8?q?=EC=9D=BC=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 루틴 당일 삭제를 위한 유스케이스 및 UI 로직 추가 - RoutineUiModel 및 SubRoutineUiModel에 삭제 정보 변환 메소드 추가 - 삭제 확인 다이얼로그에서 당일 삭제 기능 연동 --- .../bitnagil/presentation/home/HomeScreen.kt | 1 + .../presentation/home/HomeViewModel.kt | 58 +++++++++++++++++++ .../home/component/block/SubRoutinesItem.kt | 1 - .../presentation/home/model/RoutineUiModel.kt | 10 ++++ .../home/model/SubRoutineUiModel.kt | 7 +++ 5 files changed, 76 insertions(+), 1 deletion(-) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt index a6630a0a..5a019f03 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt @@ -81,6 +81,7 @@ fun HomeScreenContainer( if (uiState.showDeleteConfirmDialog) { DeleteConfirmDialog( onDeleteToday = { + viewModel.deleteRoutineByDay(routine) viewModel.sendIntent(HomeIntent.HideDeleteConfirmDialog) }, onDeleteAll = { 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 05c1384f..e2c6088c 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 @@ -5,6 +5,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import com.threegap.bitnagil.domain.routine.model.RoutineCompletion import com.threegap.bitnagil.domain.routine.model.RoutineCompletionInfo +import com.threegap.bitnagil.domain.routine.usecase.DeleteRoutineByDayUseCase import com.threegap.bitnagil.domain.routine.usecase.DeleteRoutineUseCase import com.threegap.bitnagil.domain.routine.usecase.FetchWeeklyRoutinesUseCase import com.threegap.bitnagil.domain.routine.usecase.RoutineCompletionUseCase @@ -15,6 +16,7 @@ import com.threegap.bitnagil.presentation.home.model.HomeState import com.threegap.bitnagil.presentation.home.model.RoutineSortType import com.threegap.bitnagil.presentation.home.model.RoutineUiModel import com.threegap.bitnagil.presentation.home.model.RoutinesUiModel +import com.threegap.bitnagil.presentation.home.model.toRoutineByDayDeletion import com.threegap.bitnagil.presentation.home.model.toUiModel import com.threegap.bitnagil.presentation.home.util.getCurrentWeekDays import dagger.hilt.android.lifecycle.HiltViewModel @@ -35,6 +37,7 @@ class HomeViewModel @Inject constructor( private val fetchWeeklyRoutinesUseCase: FetchWeeklyRoutinesUseCase, private val routineCompletionUseCase: RoutineCompletionUseCase, private val deleteRoutineUseCase: DeleteRoutineUseCase, + private val deleteRoutineByDayUseCase: DeleteRoutineByDayUseCase, ) : MviViewModel( initState = HomeState(), savedStateHandle = savedStateHandle, @@ -154,6 +157,30 @@ class HomeViewModel @Inject constructor( deletingRoutine = null, ) } + + is HomeIntent.DeleteRoutineByDayOptimistically -> { + val dateKey = intent.performedDate + val updatedRoutinesByDate = state.routines.routinesByDate.toMutableMap() + val routinesForDate = updatedRoutinesByDate[dateKey]?.toMutableList() + + if (routinesForDate != null) { + updatedRoutinesByDate[dateKey] = routinesForDate.filterNot { + it.routineId == intent.routineId + } + } + + state.copy( + routines = RoutinesUiModel(routinesByDate = updatedRoutinesByDate), + showDeleteConfirmDialog = false, + deletingRoutine = null, + ) + } + + is HomeIntent.RestoreRoutinesAfterDeleteByDayFailure -> { + state.copy(routines = intent.backupRoutines) + } + + is HomeIntent.ConfirmRoutineByDayDeletion -> null } return newState } @@ -395,4 +422,35 @@ class HomeViewModel @Inject constructor( ) } } + + fun deleteRoutineByDay(routineUiModel: RoutineUiModel) { + val currentRoutines = container.stateFlow.value.routines + val performedDate = container.stateFlow.value.selectedDate.toString() + + sendIntent( + HomeIntent.DeleteRoutineByDayOptimistically( + routineId = routineUiModel.routineId, + performedDate = performedDate, + ), + ) + + viewModelScope.launch { + val routineByDayDeletion = routineUiModel.toRoutineByDayDeletion(performedDate) + + deleteRoutineByDayUseCase(routineByDayDeletion).fold( + onSuccess = { + sendIntent( + HomeIntent.ConfirmRoutineByDayDeletion( + routineId = routineUiModel.routineId, + performedDate = performedDate, + ), + ) + }, + onFailure = { + Log.e("HomeViewModel", "루틴 삭제 실패: ${it.message}") + sendIntent(HomeIntent.RestoreRoutinesAfterDeleteByDayFailure(currentRoutines)) + }, + ) + } + } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt index 3ec3279e..5f787836 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt @@ -115,4 +115,3 @@ private fun SubRoutinesItemPreview() { onSubRoutineToggle = { _, _ -> }, ) } - diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/RoutineUiModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/RoutineUiModel.kt index 9dc7fdff..9db3aa49 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/RoutineUiModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/RoutineUiModel.kt @@ -3,6 +3,7 @@ package com.threegap.bitnagil.presentation.home.model import android.os.Parcelable import com.threegap.bitnagil.domain.routine.model.DayOfWeek import com.threegap.bitnagil.domain.routine.model.Routine +import com.threegap.bitnagil.domain.routine.model.RoutineByDayDeletion import com.threegap.bitnagil.domain.routine.model.RoutineType import kotlinx.parcelize.Parcelize @@ -33,3 +34,12 @@ fun Routine.toUiModel(): RoutineUiModel = isCompleted = this.isCompleted, routineType = this.routineType, ) + +fun RoutineUiModel.toRoutineByDayDeletion(performedDate: String): RoutineByDayDeletion = + RoutineByDayDeletion( + routineCompletionId = this.routineCompletionId, + routineId = this.routineId, + subRoutineInfosForDelete = this.subRoutines.map { it.toSubRoutineDeletionInfo() }, + performedDate = performedDate, + historySeq = this.historySeq, + ) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/SubRoutineUiModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/SubRoutineUiModel.kt index 6d995543..ca442a40 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/SubRoutineUiModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/SubRoutineUiModel.kt @@ -3,6 +3,7 @@ package com.threegap.bitnagil.presentation.home.model import android.os.Parcelable import com.threegap.bitnagil.domain.routine.model.RoutineType import com.threegap.bitnagil.domain.routine.model.SubRoutine +import com.threegap.bitnagil.domain.routine.model.SubRoutineDeletionInfo import kotlinx.parcelize.Parcelize @Parcelize @@ -28,3 +29,9 @@ fun SubRoutine.toUiModel(): SubRoutineUiModel = isModified = this.isModified, routineType = this.routineType, ) + +fun SubRoutineUiModel.toSubRoutineDeletionInfo(): SubRoutineDeletionInfo = + SubRoutineDeletionInfo( + routineCompletionId = this.routineCompletionId, + subRoutineId = this.subRoutineId, + ) From 4808be91cb4a8be365bb73e67cf5e4c7c2a85c16 Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Wed, 30 Jul 2025 01:05:57 +0900 Subject: [PATCH 07/12] =?UTF-8?q?Feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=A0=95=EB=B3=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 사용자 프로필 정보 조회 API 연동 - 홈 화면에 사용자 닉네임 표시 - 관련 DataSource, Repository, UseCase, DTO, DI 모듈 추가 --- .../bitnagil/di/data/DataSourceModule.kt | 6 +++++ .../bitnagil/di/data/RepositoryModule.kt | 6 +++++ .../bitnagil/di/data/ServiceModule.kt | 6 +++++ .../data/user/datasource/UserDataSource.kt | 7 ++++++ .../user/datasourceImpl/UserDataSourceImpl.kt | 16 +++++++++++++ .../model/response/UserProfileResponseDto.kt | 16 +++++++++++++ .../user/repositoryImpl/UserRepositoryImpl.kt | 14 +++++++++++ .../bitnagil/data/user/service/UserService.kt | 10 ++++++++ .../bitnagil/domain/user/model/UserProfile.kt | 5 ++++ .../domain/user/repository/UserRepository.kt | 7 ++++++ .../user/usecase/FetchUserProfileUseCase.kt | 12 ++++++++++ .../bitnagil/presentation/home/HomeScreen.kt | 2 +- .../presentation/home/HomeViewModel.kt | 23 +++++++++++++++++++ .../presentation/home/model/HomeIntent.kt | 1 + .../presentation/home/model/HomeState.kt | 1 + 15 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 data/src/main/java/com/threegap/bitnagil/data/user/datasource/UserDataSource.kt create mode 100644 data/src/main/java/com/threegap/bitnagil/data/user/datasourceImpl/UserDataSourceImpl.kt create mode 100644 data/src/main/java/com/threegap/bitnagil/data/user/model/response/UserProfileResponseDto.kt create mode 100644 data/src/main/java/com/threegap/bitnagil/data/user/repositoryImpl/UserRepositoryImpl.kt create mode 100644 data/src/main/java/com/threegap/bitnagil/data/user/service/UserService.kt create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/user/model/UserProfile.kt create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/user/repository/UserRepository.kt create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/user/usecase/FetchUserProfileUseCase.kt diff --git a/app/src/main/java/com/threegap/bitnagil/di/data/DataSourceModule.kt b/app/src/main/java/com/threegap/bitnagil/di/data/DataSourceModule.kt index d9ea19a1..469c4901 100644 --- a/app/src/main/java/com/threegap/bitnagil/di/data/DataSourceModule.kt +++ b/app/src/main/java/com/threegap/bitnagil/di/data/DataSourceModule.kt @@ -10,6 +10,8 @@ import com.threegap.bitnagil.data.onboarding.datasource.OnBoardingDataSource import com.threegap.bitnagil.data.onboarding.datasourceImpl.OnBoardingDataSourceImpl import com.threegap.bitnagil.data.routine.datasource.RoutineRemoteDataSource import com.threegap.bitnagil.data.routine.datasourceImpl.RoutineRemoteDataSourceImpl +import com.threegap.bitnagil.data.user.datasource.UserDataSource +import com.threegap.bitnagil.data.user.datasourceImpl.UserDataSourceImpl import com.threegap.bitnagil.data.writeroutine.datasource.WriteRoutineDataSource import com.threegap.bitnagil.data.writeroutine.datasourceImpl.WriteRoutineDataSourceImpl import dagger.Binds @@ -45,4 +47,8 @@ abstract class DataSourceModule { @Binds @Singleton abstract fun bindWriteRoutineDataSource(writeRoutineDataSourceImpl: WriteRoutineDataSourceImpl): WriteRoutineDataSource + + @Binds + @Singleton + abstract fun bindUserDataSource(userDataSourceImpl: UserDataSourceImpl): UserDataSource } diff --git a/app/src/main/java/com/threegap/bitnagil/di/data/RepositoryModule.kt b/app/src/main/java/com/threegap/bitnagil/di/data/RepositoryModule.kt index 4c630552..c03b4263 100644 --- a/app/src/main/java/com/threegap/bitnagil/di/data/RepositoryModule.kt +++ b/app/src/main/java/com/threegap/bitnagil/di/data/RepositoryModule.kt @@ -4,11 +4,13 @@ import com.threegap.bitnagil.data.auth.repositoryimpl.AuthRepositoryImpl import com.threegap.bitnagil.data.emotion.repositoryImpl.EmotionRepositoryImpl import com.threegap.bitnagil.data.onboarding.repositoryImpl.OnBoardingRepositoryImpl import com.threegap.bitnagil.data.routine.repositoryImpl.RoutineRepositoryImpl +import com.threegap.bitnagil.data.user.repositoryImpl.UserRepositoryImpl import com.threegap.bitnagil.data.writeroutine.repositoryImpl.WriteRoutineRepositoryImpl import com.threegap.bitnagil.domain.auth.repository.AuthRepository import com.threegap.bitnagil.domain.emotion.repository.EmotionRepository import com.threegap.bitnagil.domain.onboarding.repository.OnBoardingRepository import com.threegap.bitnagil.domain.routine.repository.RoutineRepository +import com.threegap.bitnagil.domain.user.repository.UserRepository import com.threegap.bitnagil.domain.writeroutine.repository.WriteRoutineRepository import dagger.Binds import dagger.Module @@ -39,4 +41,8 @@ abstract class RepositoryModule { @Binds @Singleton abstract fun bindWriteRoutineRepository(writeRoutineRepositoryImpl: WriteRoutineRepositoryImpl): WriteRoutineRepository + + @Binds + @Singleton + abstract fun bindUserRepository(userRepositoryImpl: UserRepositoryImpl): UserRepository } diff --git a/app/src/main/java/com/threegap/bitnagil/di/data/ServiceModule.kt b/app/src/main/java/com/threegap/bitnagil/di/data/ServiceModule.kt index 653db11c..a36bf62c 100644 --- a/app/src/main/java/com/threegap/bitnagil/di/data/ServiceModule.kt +++ b/app/src/main/java/com/threegap/bitnagil/di/data/ServiceModule.kt @@ -4,6 +4,7 @@ import com.threegap.bitnagil.data.auth.service.AuthService import com.threegap.bitnagil.data.emotion.service.EmotionService import com.threegap.bitnagil.data.onboarding.service.OnBoardingService import com.threegap.bitnagil.data.routine.service.RoutineService +import com.threegap.bitnagil.data.user.service.UserService import com.threegap.bitnagil.data.writeroutine.service.WriteRoutineService import com.threegap.bitnagil.di.core.Auth import com.threegap.bitnagil.di.core.NoneAuth @@ -48,4 +49,9 @@ object ServiceModule { @Singleton fun provideReissueService(@NoneAuth retrofit: Retrofit): ReissueService = retrofit.create(ReissueService::class.java) + + @Provides + @Singleton + fun provideUserService(@Auth retrofit: Retrofit): UserService = + retrofit.create(UserService::class.java) } diff --git a/data/src/main/java/com/threegap/bitnagil/data/user/datasource/UserDataSource.kt b/data/src/main/java/com/threegap/bitnagil/data/user/datasource/UserDataSource.kt new file mode 100644 index 00000000..55cac914 --- /dev/null +++ b/data/src/main/java/com/threegap/bitnagil/data/user/datasource/UserDataSource.kt @@ -0,0 +1,7 @@ +package com.threegap.bitnagil.data.user.datasource + +import com.threegap.bitnagil.data.user.model.response.UserProfileResponseDto + +interface UserDataSource { + suspend fun fetchUserProfile(): Result +} diff --git a/data/src/main/java/com/threegap/bitnagil/data/user/datasourceImpl/UserDataSourceImpl.kt b/data/src/main/java/com/threegap/bitnagil/data/user/datasourceImpl/UserDataSourceImpl.kt new file mode 100644 index 00000000..dbde8d74 --- /dev/null +++ b/data/src/main/java/com/threegap/bitnagil/data/user/datasourceImpl/UserDataSourceImpl.kt @@ -0,0 +1,16 @@ +package com.threegap.bitnagil.data.user.datasourceImpl + +import com.threegap.bitnagil.data.common.safeApiCall +import com.threegap.bitnagil.data.user.datasource.UserDataSource +import com.threegap.bitnagil.data.user.model.response.UserProfileResponseDto +import com.threegap.bitnagil.data.user.service.UserService +import javax.inject.Inject + +class UserDataSourceImpl @Inject constructor( + private val userService: UserService, +) : UserDataSource { + override suspend fun fetchUserProfile(): Result = + safeApiCall { + userService.fetchUserProfile() + } +} diff --git a/data/src/main/java/com/threegap/bitnagil/data/user/model/response/UserProfileResponseDto.kt b/data/src/main/java/com/threegap/bitnagil/data/user/model/response/UserProfileResponseDto.kt new file mode 100644 index 00000000..5f3749d2 --- /dev/null +++ b/data/src/main/java/com/threegap/bitnagil/data/user/model/response/UserProfileResponseDto.kt @@ -0,0 +1,16 @@ +package com.threegap.bitnagil.data.user.model.response + +import com.threegap.bitnagil.domain.user.model.UserProfile +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class UserProfileResponseDto( + @SerialName("nickname") + val nickname: String, +) + +fun UserProfileResponseDto.toDomain() = + UserProfile( + nickname = this.nickname, + ) diff --git a/data/src/main/java/com/threegap/bitnagil/data/user/repositoryImpl/UserRepositoryImpl.kt b/data/src/main/java/com/threegap/bitnagil/data/user/repositoryImpl/UserRepositoryImpl.kt new file mode 100644 index 00000000..e0506f24 --- /dev/null +++ b/data/src/main/java/com/threegap/bitnagil/data/user/repositoryImpl/UserRepositoryImpl.kt @@ -0,0 +1,14 @@ +package com.threegap.bitnagil.data.user.repositoryImpl + +import com.threegap.bitnagil.data.user.datasource.UserDataSource +import com.threegap.bitnagil.data.user.model.response.toDomain +import com.threegap.bitnagil.domain.user.model.UserProfile +import com.threegap.bitnagil.domain.user.repository.UserRepository +import javax.inject.Inject + +class UserRepositoryImpl @Inject constructor( + private val userDataSource: UserDataSource, +) : UserRepository { + override suspend fun fetchUserProfile(): Result = + userDataSource.fetchUserProfile().map { it.toDomain() } +} diff --git a/data/src/main/java/com/threegap/bitnagil/data/user/service/UserService.kt b/data/src/main/java/com/threegap/bitnagil/data/user/service/UserService.kt new file mode 100644 index 00000000..76b4823e --- /dev/null +++ b/data/src/main/java/com/threegap/bitnagil/data/user/service/UserService.kt @@ -0,0 +1,10 @@ +package com.threegap.bitnagil.data.user.service + +import com.threegap.bitnagil.data.user.model.response.UserProfileResponseDto +import com.threegap.bitnagil.network.model.BaseResponse +import retrofit2.http.GET + +interface UserService { + @GET("/api/v1/users/nickname") + suspend fun fetchUserProfile(): BaseResponse +} diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/user/model/UserProfile.kt b/domain/src/main/java/com/threegap/bitnagil/domain/user/model/UserProfile.kt new file mode 100644 index 00000000..b02eadb6 --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/user/model/UserProfile.kt @@ -0,0 +1,5 @@ +package com.threegap.bitnagil.domain.user.model + +data class UserProfile( + val nickname: String, +) diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/user/repository/UserRepository.kt b/domain/src/main/java/com/threegap/bitnagil/domain/user/repository/UserRepository.kt new file mode 100644 index 00000000..de352843 --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/user/repository/UserRepository.kt @@ -0,0 +1,7 @@ +package com.threegap.bitnagil.domain.user.repository + +import com.threegap.bitnagil.domain.user.model.UserProfile + +interface UserRepository { + suspend fun fetchUserProfile(): Result +} diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/user/usecase/FetchUserProfileUseCase.kt b/domain/src/main/java/com/threegap/bitnagil/domain/user/usecase/FetchUserProfileUseCase.kt new file mode 100644 index 00000000..baee4a20 --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/user/usecase/FetchUserProfileUseCase.kt @@ -0,0 +1,12 @@ +package com.threegap.bitnagil.domain.user.usecase + +import com.threegap.bitnagil.domain.user.model.UserProfile +import com.threegap.bitnagil.domain.user.repository.UserRepository +import javax.inject.Inject + +class FetchUserProfileUseCase @Inject constructor( + private val userRepository: UserRepository, +) { + suspend operator fun invoke(): Result = + userRepository.fetchUserProfile() +} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt index 5a019f03..bcd90478 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt @@ -240,7 +240,7 @@ private fun HomeScreen( } CollapsibleHomeHeader( - userName = "대현", + userName = uiState.userNickname, collapsibleHeaderState = collapsibleHeaderState, onEmotionRecordClick = onRegisterEmotionClick, ) 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 e2c6088c..fe514e0f 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 @@ -9,6 +9,7 @@ import com.threegap.bitnagil.domain.routine.usecase.DeleteRoutineByDayUseCase import com.threegap.bitnagil.domain.routine.usecase.DeleteRoutineUseCase import com.threegap.bitnagil.domain.routine.usecase.FetchWeeklyRoutinesUseCase import com.threegap.bitnagil.domain.routine.usecase.RoutineCompletionUseCase +import com.threegap.bitnagil.domain.user.usecase.FetchUserProfileUseCase import com.threegap.bitnagil.presentation.common.mviviewmodel.MviViewModel import com.threegap.bitnagil.presentation.home.model.HomeIntent import com.threegap.bitnagil.presentation.home.model.HomeSideEffect @@ -35,6 +36,7 @@ import javax.inject.Inject class HomeViewModel @Inject constructor( savedStateHandle: SavedStateHandle, private val fetchWeeklyRoutinesUseCase: FetchWeeklyRoutinesUseCase, + private val fetchUserProfileUseCase: FetchUserProfileUseCase, private val routineCompletionUseCase: RoutineCompletionUseCase, private val deleteRoutineUseCase: DeleteRoutineUseCase, private val deleteRoutineByDayUseCase: DeleteRoutineByDayUseCase, @@ -50,6 +52,7 @@ class HomeViewModel @Inject constructor( observeWeekChanges() observeRoutineUpdates() fetchWeeklyRoutines(container.stateFlow.value.currentWeeks) + fetchUserProfile() } override suspend fun SimpleSyntax.reduceState( @@ -61,6 +64,10 @@ class HomeViewModel @Inject constructor( state.copy(isLoading = intent.isLoading) } + is HomeIntent.LoadUserProfile -> { + state.copy(userNickname = intent.nickname) + } + is HomeIntent.LoadWeeklyRoutines -> { state.copy(routines = intent.routines) } @@ -210,6 +217,22 @@ class HomeViewModel @Inject constructor( } } + private fun fetchUserProfile() { + sendIntent(HomeIntent.UpdateLoading(true)) + viewModelScope.launch { + fetchUserProfileUseCase().fold( + onSuccess = { + sendIntent(HomeIntent.LoadUserProfile(it.nickname)) + sendIntent(HomeIntent.UpdateLoading(false)) + }, + onFailure = { error -> + Log.e("HomeViewModel", "유저 정보 가져오기 실패: ${error.message}") + sendIntent(HomeIntent.UpdateLoading(false)) + }, + ) + } + } + private fun fetchWeeklyRoutines(currentWeeks: List) { sendIntent(HomeIntent.UpdateLoading(true)) val startDate = currentWeeks.first().toString() diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt index eb2659a9..c105e271 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt @@ -5,6 +5,7 @@ import java.time.LocalDate sealed class HomeIntent : MviIntent { data class UpdateLoading(val isLoading: Boolean) : HomeIntent() + data class LoadUserProfile(val nickname: String) : HomeIntent() data class LoadWeeklyRoutines(val routines: RoutinesUiModel) : HomeIntent() data class OnDateSelect(val date: LocalDate) : HomeIntent() data class OnRoutineCompletionToggle(val routineId: String, val isCompleted: Boolean) : HomeIntent() diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeState.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeState.kt index bb28206a..97c8e1f8 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeState.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeState.kt @@ -8,6 +8,7 @@ import java.time.LocalDate @Parcelize data class HomeState( val isLoading: Boolean = false, + val userNickname: String = "", val selectedDate: LocalDate = LocalDate.now(), val currentWeeks: List = LocalDate.now().getCurrentWeekDays(), val routines: RoutinesUiModel = RoutinesUiModel(), From d5b86ac821101a3975a4e1106ff0a3013d0e34f7 Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Wed, 30 Jul 2025 02:02:54 +0900 Subject: [PATCH 08/12] =?UTF-8?q?Feat:=20=EB=82=98=EC=9D=98=20=EA=B0=90?= =?UTF-8?q?=EC=A0=95=20=EC=A1=B0=ED=9A=8C=EB=A5=BC=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=AA=A8=EB=8D=B8=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../threegap/bitnagil/domain/emotion/model/MyEmotion.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/MyEmotion.kt 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 new file mode 100644 index 00000000..36e226a9 --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/model/MyEmotion.kt @@ -0,0 +1,7 @@ +package com.threegap.bitnagil.domain.emotion.model + +data class MyEmotion( + val emotionMarbleType: Emotion?, + val emotionMarbleName: String?, + val imageUrl: String?, +) From b9c7ef9bec039934f785fa3bdafd58b038ac70e8 Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Wed, 30 Jul 2025 02:03:28 +0900 Subject: [PATCH 09/12] =?UTF-8?q?Feat:=20=EB=82=98=EC=9D=98=20=EA=B0=90?= =?UTF-8?q?=EC=A0=95=20=EC=A1=B0=ED=9A=8C=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../emotion/datasource/EmotionDataSource.kt | 2 ++ .../datasourceImpl/EmotionDataSourceImpl.kt | 6 +++++ .../model/response/MyEmotionResponseDto.kt | 23 +++++++++++++++++++ .../repositoryImpl/EmotionRepositoryImpl.kt | 5 ++++ .../data/emotion/service/EmotionService.kt | 7 ++++++ .../emotion/repository/EmotionRepository.kt | 2 ++ .../emotion/usecase/GetMyEmotionUseCase.kt | 12 ++++++++++ 7 files changed, 57 insertions(+) create mode 100644 data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/MyEmotionResponseDto.kt create mode 100644 domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetMyEmotionUseCase.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 4129c2b6..1267dd6a 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,9 +1,11 @@ package com.threegap.bitnagil.data.emotion.datasource import com.threegap.bitnagil.data.emotion.model.response.GetEmotionsResponse +import com.threegap.bitnagil.data.emotion.model.response.MyEmotionResponseDto 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 } 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 0337c003..674c25ea 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,6 +4,7 @@ import com.threegap.bitnagil.data.common.safeApiCall import com.threegap.bitnagil.data.emotion.datasource.EmotionDataSource import com.threegap.bitnagil.data.emotion.model.request.RegisterEmotionRequest import com.threegap.bitnagil.data.emotion.model.response.GetEmotionsResponse +import com.threegap.bitnagil.data.emotion.model.response.MyEmotionResponseDto import com.threegap.bitnagil.data.emotion.model.response.RegisterEmotionResponse import com.threegap.bitnagil.data.emotion.service.EmotionService import javax.inject.Inject @@ -23,4 +24,9 @@ class EmotionDataSourceImpl @Inject constructor( emotionService.postEmotions(registerEmotionRequest) } } + + override suspend fun getMyEmotionMarble(currentDate: String): Result = + safeApiCall { + emotionService.getMyEmotionMarble(currentDate) + } } 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/MyEmotionResponseDto.kt new file mode 100644 index 00000000..77243076 --- /dev/null +++ b/data/src/main/java/com/threegap/bitnagil/data/emotion/model/response/MyEmotionResponseDto.kt @@ -0,0 +1,23 @@ +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( + @SerialName("emotionMarbleType") + val emotionMarbleType: String?, + @SerialName("emotionMarbleName") + val emotionMarbleName: String?, + @SerialName("imageUrl") + val imageUrl: String?, +) + +fun MyEmotionResponseDto.toDomain(): MyEmotion = + MyEmotion( + emotionMarbleType = emotionMarbleType?.let { Emotion.valueOf(it) }, + emotionMarbleName = emotionMarbleName, + imageUrl = imageUrl, + ) 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 1c27ee61..740a6274 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 @@ -1,7 +1,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.Emotion +import com.threegap.bitnagil.domain.emotion.model.MyEmotion import com.threegap.bitnagil.domain.emotion.repository.EmotionRepository import javax.inject.Inject @@ -36,4 +38,7 @@ class EmotionRepositoryImpl @Inject constructor( return emotionDataSource.registerEmotion(selectedEmotion).map { _ -> } } + + override suspend fun getMyEmotionMarble(currentDate: String): Result = + emotionDataSource.getMyEmotionMarble(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 61b18264..82eb3dcb 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,11 +2,13 @@ package com.threegap.bitnagil.data.emotion.service import com.threegap.bitnagil.data.emotion.model.request.RegisterEmotionRequest import com.threegap.bitnagil.data.emotion.model.response.GetEmotionsResponse +import com.threegap.bitnagil.data.emotion.model.response.MyEmotionResponseDto import com.threegap.bitnagil.data.emotion.model.response.RegisterEmotionResponse import com.threegap.bitnagil.network.model.BaseResponse import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.POST +import retrofit2.http.Query interface EmotionService { @GET("/api/v1/emotion-marbles") @@ -16,4 +18,9 @@ interface EmotionService { suspend fun postEmotions( @Body request: RegisterEmotionRequest, ): BaseResponse + + @GET("/api/v1/emotion-marbles/me") + suspend fun getMyEmotionMarble( + @Query("searchDate") date: String, + ): BaseResponse } 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 5935aab9..a47ca36b 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,10 @@ package com.threegap.bitnagil.domain.emotion.repository import com.threegap.bitnagil.domain.emotion.model.Emotion +import com.threegap.bitnagil.domain.emotion.model.MyEmotion interface EmotionRepository { suspend fun getEmotions(): Result> suspend fun registerEmotion(emotion: Emotion): Result + suspend fun getMyEmotionMarble(currentDate: String): Result } 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 new file mode 100644 index 00000000..a72157c9 --- /dev/null +++ b/domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/GetMyEmotionUseCase.kt @@ -0,0 +1,12 @@ +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) +} From 65d1dfb7a93b6d9be870d85b4587bcbe2bd196a4 Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Wed, 30 Jul 2025 02:04:52 +0900 Subject: [PATCH 10/12] =?UTF-8?q?Feat:=20=EC=98=A4=EB=8A=98=EC=9D=98=20?= =?UTF-8?q?=EA=B0=90=EC=A0=95=20=EA=B5=AC=EC=8A=AC=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 조회한 나의 감정에 따른 감정 구슬을 홈 화면에서 표시하는 기능 구현 --- .../bitnagil/presentation/home/HomeScreen.kt | 1 + .../presentation/home/HomeViewModel.kt | 25 +++++++++++++++++++ .../template/CollapsibleHomeHeader.kt | 5 +++- .../home/model/EmotionBallType.kt | 7 ++++++ .../presentation/home/model/HomeIntent.kt | 1 + .../presentation/home/model/HomeState.kt | 1 + 6 files changed, 39 insertions(+), 1 deletion(-) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt index bcd90478..5e574b19 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt @@ -241,6 +241,7 @@ private fun HomeScreen( CollapsibleHomeHeader( userName = uiState.userNickname, + emotionBallType = uiState.myEmotion, collapsibleHeaderState = collapsibleHeaderState, onEmotionRecordClick = onRegisterEmotionClick, ) 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 fe514e0f..913a0ffd 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.GetMyEmotionUseCase import com.threegap.bitnagil.domain.routine.model.RoutineCompletion import com.threegap.bitnagil.domain.routine.model.RoutineCompletionInfo import com.threegap.bitnagil.domain.routine.usecase.DeleteRoutineByDayUseCase @@ -11,6 +12,7 @@ import com.threegap.bitnagil.domain.routine.usecase.FetchWeeklyRoutinesUseCase import com.threegap.bitnagil.domain.routine.usecase.RoutineCompletionUseCase import com.threegap.bitnagil.domain.user.usecase.FetchUserProfileUseCase import com.threegap.bitnagil.presentation.common.mviviewmodel.MviViewModel +import com.threegap.bitnagil.presentation.home.model.EmotionBallType import com.threegap.bitnagil.presentation.home.model.HomeIntent import com.threegap.bitnagil.presentation.home.model.HomeSideEffect import com.threegap.bitnagil.presentation.home.model.HomeState @@ -37,6 +39,7 @@ class HomeViewModel @Inject constructor( savedStateHandle: SavedStateHandle, private val fetchWeeklyRoutinesUseCase: FetchWeeklyRoutinesUseCase, private val fetchUserProfileUseCase: FetchUserProfileUseCase, + private val getMyEmotionUseCase: GetMyEmotionUseCase, private val routineCompletionUseCase: RoutineCompletionUseCase, private val deleteRoutineUseCase: DeleteRoutineUseCase, private val deleteRoutineByDayUseCase: DeleteRoutineByDayUseCase, @@ -53,6 +56,7 @@ class HomeViewModel @Inject constructor( observeRoutineUpdates() fetchWeeklyRoutines(container.stateFlow.value.currentWeeks) fetchUserProfile() + getMyEmotion(container.stateFlow.value.selectedDate) } override suspend fun SimpleSyntax.reduceState( @@ -188,6 +192,10 @@ class HomeViewModel @Inject constructor( } is HomeIntent.ConfirmRoutineByDayDeletion -> null + + is HomeIntent.LoadMyEmotion -> { + state.copy(myEmotion = intent.emotion) + } } return newState } @@ -252,6 +260,23 @@ class HomeViewModel @Inject constructor( } } + private fun getMyEmotion(currentDate: LocalDate) { + sendIntent(HomeIntent.UpdateLoading(true)) + viewModelScope.launch { + getMyEmotionUseCase(currentDate.toString()).fold( + onSuccess = { emotion -> + val ballType = EmotionBallType.fromDomainEmotion(emotion.emotionMarbleType) + sendIntent(HomeIntent.LoadMyEmotion(ballType)) + sendIntent(HomeIntent.UpdateLoading(false)) + }, + onFailure = { error -> + Log.e("HomeViewModel", "나의 감정 실패: ${error.message}") + sendIntent(HomeIntent.UpdateLoading(false)) + }, + ) + } + } + fun toggleRoutineCompletion(routineId: String, isCompleted: Boolean) { val originalState = container.stateFlow.value sendIntent(HomeIntent.OnRoutineCompletionToggle(routineId, isCompleted)) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/CollapsibleHomeHeader.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/CollapsibleHomeHeader.kt index 207ec100..e0e741ab 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/CollapsibleHomeHeader.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/CollapsibleHomeHeader.kt @@ -26,12 +26,14 @@ import com.threegap.bitnagil.designsystem.component.atom.BitnagilIcon import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple import com.threegap.bitnagil.presentation.home.component.atom.EmotionBall import com.threegap.bitnagil.presentation.home.component.block.SpeechBubbleTooltip +import com.threegap.bitnagil.presentation.home.model.EmotionBallType import com.threegap.bitnagil.presentation.home.util.CollapsibleHeaderState import com.threegap.bitnagil.presentation.home.util.rememberCollapsibleHeaderState @Composable fun CollapsibleHomeHeader( userName: String, + emotionBallType: EmotionBallType?, collapsibleHeaderState: CollapsibleHeaderState, onEmotionRecordClick: () -> Unit, modifier: Modifier = Modifier, @@ -96,7 +98,7 @@ fun CollapsibleHomeHeader( .align(Alignment.BottomEnd), ) { EmotionBall( - emotionType = null, + emotionType = emotionBallType, onClick = {}, ) } @@ -149,6 +151,7 @@ private fun GreetingMessage( private fun HomeTopBarPreview() { CollapsibleHomeHeader( userName = "대현", + emotionBallType = null, collapsibleHeaderState = rememberCollapsibleHeaderState(), onEmotionRecordClick = {}, ) 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 0e319db9..6e4fbfd0 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,6 +3,7 @@ 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, @@ -39,4 +40,10 @@ enum class EmotionBallType( ambientColor = Color(0xFFC71A1A).copy(alpha = 0.28f), spotColor = Color(0xFFC71A1A), ), + ; + + companion object { + fun fromDomainEmotion(emotion: Emotion?): EmotionBallType? = + emotion?.let { valueOf(it.name) } + } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt index c105e271..f93ad5af 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeIntent.kt @@ -6,6 +6,7 @@ import java.time.LocalDate sealed class HomeIntent : MviIntent { data class UpdateLoading(val isLoading: Boolean) : HomeIntent() data class LoadUserProfile(val nickname: String) : HomeIntent() + data class LoadMyEmotion(val emotion: EmotionBallType?) : HomeIntent() data class LoadWeeklyRoutines(val routines: RoutinesUiModel) : HomeIntent() data class OnDateSelect(val date: LocalDate) : HomeIntent() data class OnRoutineCompletionToggle(val routineId: String, val isCompleted: Boolean) : HomeIntent() diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeState.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeState.kt index 97c8e1f8..c7f6b0a1 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeState.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeState.kt @@ -9,6 +9,7 @@ import java.time.LocalDate data class HomeState( val isLoading: Boolean = false, val userNickname: String = "", + val myEmotion: EmotionBallType? = null, val selectedDate: LocalDate = LocalDate.now(), val currentWeeks: List = LocalDate.now().getCurrentWeekDays(), val routines: RoutinesUiModel = RoutinesUiModel(), From bb3ec6d63c780923a07074217dc2d465e9256efe Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Wed, 30 Jul 2025 02:14:32 +0900 Subject: [PATCH 11/12] =?UTF-8?q?Refactor:=20AuthToken=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20role=20=ED=95=84=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/threegap/bitnagil/network/model/AuthToken.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/network/src/main/java/com/threegap/bitnagil/network/model/AuthToken.kt b/core/network/src/main/java/com/threegap/bitnagil/network/model/AuthToken.kt index 4cb68dae..33afb790 100644 --- a/core/network/src/main/java/com/threegap/bitnagil/network/model/AuthToken.kt +++ b/core/network/src/main/java/com/threegap/bitnagil/network/model/AuthToken.kt @@ -9,6 +9,4 @@ data class AuthToken( val accessToken: String, @SerialName("refreshToken") val refreshToken: String, - @SerialName("role") // todo: 제거 예정 - val role: String, ) From b2b1a76a2e44ddcc485c7a3535eb78c2cdad14b4 Mon Sep 17 00:00:00 2001 From: wjdrjs00 Date: Wed, 30 Jul 2025 12:38:45 +0900 Subject: [PATCH 12/12] =?UTF-8?q?Refactor:=20=EB=A3=A8=ED=8B=B4=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=8B=9C=20BottomSheet=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 루틴 삭제 시 해당 루틴의 상세정보를 보여주는 바텀시트가 올라와 있는 경우 내려가도록 상태 초기화 --- .../com/threegap/bitnagil/presentation/home/HomeViewModel.kt | 4 ++++ 1 file changed, 4 insertions(+) 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 913a0ffd..ee88201d 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 @@ -124,6 +124,8 @@ class HomeViewModel @Inject constructor( routines = RoutinesUiModel(routinesByDate = updatedRoutinesByDate), showDeleteConfirmDialog = false, deletingRoutine = null, + routineDetailsBottomSheetVisible = false, + selectedRoutine = null, ) } @@ -184,6 +186,8 @@ class HomeViewModel @Inject constructor( routines = RoutinesUiModel(routinesByDate = updatedRoutinesByDate), showDeleteConfirmDialog = false, deletingRoutine = null, + routineDetailsBottomSheetVisible = false, + selectedRoutine = null, ) }