diff --git a/app/src/main/java/com/sopetit/softie/data/entity/request/AddDailyRoutineRequest.kt b/app/src/main/java/com/sopetit/softie/data/entity/request/AddDailyRoutineRequest.kt new file mode 100644 index 00000000..27a234e1 --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/data/entity/request/AddDailyRoutineRequest.kt @@ -0,0 +1,10 @@ +package com.sopetit.softie.data.entity.request + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class AddDailyRoutineRequest( + @SerialName("routineId") + val routineId: Int +) diff --git a/app/src/main/java/com/sopetit/softie/data/entity/response/AchieveDailyResponse.kt b/app/src/main/java/com/sopetit/softie/data/entity/response/AchieveDailyResponse.kt new file mode 100644 index 00000000..6b0d7114 --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/data/entity/response/AchieveDailyResponse.kt @@ -0,0 +1,21 @@ +package com.sopetit.softie.data.entity.response + +import com.sopetit.softie.domain.entity.DailyAchieve +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class AchieveDailyResponse( + @SerialName("routineId") + val routineId: Int, + @SerialName("isAchieve") + val isAchieve: Boolean, + @SerialName("achieveCount") + val achieveCount: Int +) { + fun toAchieveDaily(): DailyAchieve = DailyAchieve( + routineId = this.routineId, + isAchieve = this.isAchieve, + achieveCount = this.achieveCount + ) +} diff --git a/app/src/main/java/com/sopetit/softie/data/entity/response/AddDailyRoutineResponse.kt b/app/src/main/java/com/sopetit/softie/data/entity/response/AddDailyRoutineResponse.kt new file mode 100644 index 00000000..2768c32e --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/data/entity/response/AddDailyRoutineResponse.kt @@ -0,0 +1,15 @@ +package com.sopetit.softie.data.entity.response + +import com.sopetit.softie.domain.entity.AddRoutine +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class AddDailyRoutineResponse( + @SerialName("routineId") + val routineId: Int +) { + fun toAddDailyRoutine(): AddRoutine = AddRoutine( + routineId = this.routineId + ) +} diff --git a/app/src/main/java/com/sopetit/softie/data/entity/response/DailyCardResponse.kt b/app/src/main/java/com/sopetit/softie/data/entity/response/DailyCardResponse.kt new file mode 100644 index 00000000..406626cd --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/data/entity/response/DailyCardResponse.kt @@ -0,0 +1,25 @@ +package com.sopetit.softie.data.entity.response + +import com.sopetit.softie.domain.entity.Routine +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +data class DailyCardResponse( + @SerialName("routines") + val routines: List +) { + @Serializable + data class RoutineItem( + @SerialName("routineId") + val routineId: Int, + @SerialName("content") + val content: String + ) + + fun toRoutine() = routines.map { + Routine( + routineId = it.routineId, + content = it.content + ) + } +} diff --git a/app/src/main/java/com/sopetit/softie/data/entity/response/DailyRoutineResponse.kt b/app/src/main/java/com/sopetit/softie/data/entity/response/DailyRoutineResponse.kt new file mode 100644 index 00000000..eafe60d4 --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/data/entity/response/DailyRoutineResponse.kt @@ -0,0 +1,35 @@ +package com.sopetit.softie.data.entity.response + +import com.sopetit.softie.domain.entity.DailyRoutine +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class DailyRoutineResponse( + @SerialName("routines") + val routines: List +) { + @Serializable + data class DailyRoutineItem( + @SerialName("routineId") + val routineId: Int, + @SerialName("content") + val content: String, + @SerialName("iconImageUrl") + val iconImageUrl: String, + @SerialName("achieveCount") + val achieveCount: Int, + @SerialName("isAchieve") + val isAchieve: Boolean + ) + + fun toUserDailyRoutine() = routines.map { + DailyRoutine( + routineId = it.routineId, + content = it.content, + iconImageUrl = it.iconImageUrl, + achieveCount = it.achieveCount, + isAchieve = it.isAchieve + ) + } +} diff --git a/app/src/main/java/com/sopetit/softie/data/repositoryImpl/DailyRoutineRepositoryImpl.kt b/app/src/main/java/com/sopetit/softie/data/repositoryImpl/DailyRoutineRepositoryImpl.kt index 5a08ad38..ad5641f6 100644 --- a/app/src/main/java/com/sopetit/softie/data/repositoryImpl/DailyRoutineRepositoryImpl.kt +++ b/app/src/main/java/com/sopetit/softie/data/repositoryImpl/DailyRoutineRepositoryImpl.kt @@ -1,6 +1,9 @@ package com.sopetit.softie.data.repositoryImpl import com.sopetit.softie.data.source.DailyRoutineDataSource +import com.sopetit.softie.domain.entity.AddRoutine +import com.sopetit.softie.domain.entity.DailyAchieve +import com.sopetit.softie.domain.entity.DailyRoutine import com.sopetit.softie.domain.entity.Routine import com.sopetit.softie.domain.entity.Theme import com.sopetit.softie.domain.repository.DailyRoutineRepository @@ -9,6 +12,18 @@ import javax.inject.Inject class DailyRoutineRepositoryImpl @Inject constructor( private val dailyRoutineDataSource: DailyRoutineDataSource ) : DailyRoutineRepository { + override suspend fun getDailyRoutine(): Result> = + runCatching { dailyRoutineDataSource.getDailyRoutine() }.mapCatching { response -> + requireNotNull(response.data).toUserDailyRoutine() + } + + override suspend fun patchAchieveDaily(routineId: Int): Result = + runCatching { dailyRoutineDataSource.patchAchieveDaily(routineId) }.map { response -> + requireNotNull(response.data).toAchieveDaily() + } + + override suspend fun deleteDailyRoutine(routineIdList: List): Result = + runCatching { dailyRoutineDataSource.deleteDailyRoutine(routineIdList) } override suspend fun getTheme(): Result> = runCatching { dailyRoutineDataSource.getTheme() @@ -21,4 +36,11 @@ class DailyRoutineRepositoryImpl @Inject constructor( }.mapCatching { dailyRoutineList -> requireNotNull(dailyRoutineList.data).toRoutine() } + + override suspend fun postAddDailyRoutine(routineId: Int): Result = + runCatching { + dailyRoutineDataSource.postAddDailyRoutine(routineId) + }.map { response -> + requireNotNull(response.data).toAddDailyRoutine() + } } diff --git a/app/src/main/java/com/sopetit/softie/data/service/DailyRoutineService.kt b/app/src/main/java/com/sopetit/softie/data/service/DailyRoutineService.kt index d33a93e0..27172de8 100644 --- a/app/src/main/java/com/sopetit/softie/data/service/DailyRoutineService.kt +++ b/app/src/main/java/com/sopetit/softie/data/service/DailyRoutineService.kt @@ -1,13 +1,21 @@ package com.sopetit.softie.data.service import com.sopetit.softie.data.entity.BaseResponse +import com.sopetit.softie.data.entity.response.AchieveDailyResponse +import com.sopetit.softie.data.entity.response.AddDailyRoutineResponse +import com.sopetit.softie.data.entity.response.DailyCardResponse import com.sopetit.softie.data.entity.response.DailyRoutineListResponse +import com.sopetit.softie.data.entity.response.DailyRoutineResponse import com.sopetit.softie.data.entity.response.ThemeListResponse +import retrofit2.http.Body +import retrofit2.http.DELETE import retrofit2.http.GET +import retrofit2.http.PATCH +import retrofit2.http.POST +import retrofit2.http.Path import retrofit2.http.Query interface DailyRoutineService { - @GET("api/v1/routines/daily/themes") suspend fun getTheme(): BaseResponse @@ -15,4 +23,19 @@ interface DailyRoutineService { suspend fun getRoutineList( @Query("themes") themes: List ): BaseResponse + + @GET("api/v1/routines/daily/member") + suspend fun getDailyRoutine(): BaseResponse + + @PATCH("api/v1/routines/daily/member/routine/{routineId}") + suspend fun patchAchieveDaily(@Path("routineId") routineId: Int): BaseResponse + + @DELETE("api/v1/routines/daily/member") + suspend fun deleteDailyRoutine(@Query("routines") routineIdList: List): BaseResponse + + @POST("api/v1/routines/daily/member") + suspend fun postAddDailyRoutine(@Body routineId: Int): BaseResponse + + @GET("api/v1/routines/daily/theme/{themeId}") + suspend fun getDailyCardList(@Path("themeId") themeId: Int): BaseResponse } diff --git a/app/src/main/java/com/sopetit/softie/data/source/DailyRoutineDataSource.kt b/app/src/main/java/com/sopetit/softie/data/source/DailyRoutineDataSource.kt index fee3ce7b..25642a70 100644 --- a/app/src/main/java/com/sopetit/softie/data/source/DailyRoutineDataSource.kt +++ b/app/src/main/java/com/sopetit/softie/data/source/DailyRoutineDataSource.kt @@ -1,7 +1,10 @@ package com.sopetit.softie.data.source import com.sopetit.softie.data.entity.BaseResponse +import com.sopetit.softie.data.entity.response.AchieveDailyResponse +import com.sopetit.softie.data.entity.response.AddDailyRoutineResponse import com.sopetit.softie.data.entity.response.DailyRoutineListResponse +import com.sopetit.softie.data.entity.response.DailyRoutineResponse import com.sopetit.softie.data.entity.response.ThemeListResponse import com.sopetit.softie.data.service.DailyRoutineService import javax.inject.Inject @@ -9,8 +12,20 @@ import javax.inject.Inject class DailyRoutineDataSource @Inject constructor( private val dailyRoutineService: DailyRoutineService ) { + suspend fun getDailyRoutine(): BaseResponse = + dailyRoutineService.getDailyRoutine() + + suspend fun patchAchieveDaily(routineId: Int): BaseResponse = + dailyRoutineService.patchAchieveDaily(routineId) + + suspend fun deleteDailyRoutine(routineIdList: List): BaseResponse = + dailyRoutineService.deleteDailyRoutine(routineIdList) + suspend fun getTheme(): BaseResponse = dailyRoutineService.getTheme() suspend fun getRoutineList(themeId: List): BaseResponse = dailyRoutineService.getRoutineList(themeId) + + suspend fun postAddDailyRoutine(routineId: Int): BaseResponse = + dailyRoutineService.postAddDailyRoutine(routineId) } diff --git a/app/src/main/java/com/sopetit/softie/domain/entity/AddRoutine.kt b/app/src/main/java/com/sopetit/softie/domain/entity/AddRoutine.kt new file mode 100644 index 00000000..43eab5a2 --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/domain/entity/AddRoutine.kt @@ -0,0 +1,5 @@ +package com.sopetit.softie.domain.entity + +data class AddRoutine( + val routineId: Int +) diff --git a/app/src/main/java/com/sopetit/softie/domain/entity/DailyAchieve.kt b/app/src/main/java/com/sopetit/softie/domain/entity/DailyAchieve.kt new file mode 100644 index 00000000..17fe3291 --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/domain/entity/DailyAchieve.kt @@ -0,0 +1,7 @@ +package com.sopetit.softie.domain.entity + +data class DailyAchieve( + val routineId: Int, + val isAchieve: Boolean, + val achieveCount: Int +) diff --git a/app/src/main/java/com/sopetit/softie/domain/entity/UserDailyRoutine.kt b/app/src/main/java/com/sopetit/softie/domain/entity/UserDailyRoutine.kt new file mode 100644 index 00000000..1bf8de82 --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/domain/entity/UserDailyRoutine.kt @@ -0,0 +1,8 @@ +package com.sopetit.softie.domain.entity + +data class UserDailyRoutine( + val routineId: Int, + val iconImageUrl: String, + val content: String, + val backgroundImageUrl: String +) diff --git a/app/src/main/java/com/sopetit/softie/domain/repository/DailyRoutineRepository.kt b/app/src/main/java/com/sopetit/softie/domain/repository/DailyRoutineRepository.kt index a999bffe..f731db79 100644 --- a/app/src/main/java/com/sopetit/softie/domain/repository/DailyRoutineRepository.kt +++ b/app/src/main/java/com/sopetit/softie/domain/repository/DailyRoutineRepository.kt @@ -1,11 +1,18 @@ package com.sopetit.softie.domain.repository +import com.sopetit.softie.domain.entity.AddRoutine +import com.sopetit.softie.domain.entity.DailyAchieve +import com.sopetit.softie.domain.entity.DailyRoutine import com.sopetit.softie.domain.entity.Routine import com.sopetit.softie.domain.entity.Theme interface DailyRoutineRepository { - + suspend fun getDailyRoutine(): Result> + suspend fun patchAchieveDaily(routineId: Int): Result + suspend fun deleteDailyRoutine(routineIdList: List): Result suspend fun getTheme(): Result> suspend fun getRoutineList(themeId: List): Result> + + suspend fun postAddDailyRoutine(routineId: Int): Result } diff --git a/app/src/main/java/com/sopetit/softie/domain/usecase/DeleteDailyRoutineUseCase.kt b/app/src/main/java/com/sopetit/softie/domain/usecase/DeleteDailyRoutineUseCase.kt new file mode 100644 index 00000000..86f88fce --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/domain/usecase/DeleteDailyRoutineUseCase.kt @@ -0,0 +1,11 @@ +package com.sopetit.softie.domain.usecase + +import com.sopetit.softie.domain.repository.DailyRoutineRepository +import javax.inject.Inject + +class DeleteDailyRoutineUseCase @Inject constructor( + private val deleteDailyRoutine: DailyRoutineRepository +) { + suspend operator fun invoke(routineIdList: List) = + deleteDailyRoutine.deleteDailyRoutine(routineIdList) +} diff --git a/app/src/main/java/com/sopetit/softie/domain/usecase/GetDailyRoutineUseCase.kt b/app/src/main/java/com/sopetit/softie/domain/usecase/GetDailyRoutineUseCase.kt new file mode 100644 index 00000000..31cba036 --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/domain/usecase/GetDailyRoutineUseCase.kt @@ -0,0 +1,10 @@ +package com.sopetit.softie.domain.usecase + +import com.sopetit.softie.domain.repository.DailyRoutineRepository +import javax.inject.Inject + +class GetDailyRoutineUseCase @Inject constructor( + private val dailyRoutineRepository: DailyRoutineRepository +) { + suspend operator fun invoke() = dailyRoutineRepository.getDailyRoutine() +} diff --git a/app/src/main/java/com/sopetit/softie/domain/usecase/PatchAchieveDailyUseCase.kt b/app/src/main/java/com/sopetit/softie/domain/usecase/PatchAchieveDailyUseCase.kt new file mode 100644 index 00000000..0bd337f9 --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/domain/usecase/PatchAchieveDailyUseCase.kt @@ -0,0 +1,11 @@ +package com.sopetit.softie.domain.usecase + +import com.sopetit.softie.domain.repository.DailyRoutineRepository +import javax.inject.Inject + +class PatchAchieveDailyUseCase @Inject constructor( + private val achieveDailyRepository: DailyRoutineRepository +) { + suspend operator fun invoke(routineId: Int) = + achieveDailyRepository.patchAchieveDaily(routineId) +} diff --git a/app/src/main/java/com/sopetit/softie/domain/usecase/PostAddDailyRoutineUseCase.kt b/app/src/main/java/com/sopetit/softie/domain/usecase/PostAddDailyRoutineUseCase.kt new file mode 100644 index 00000000..d02742be --- /dev/null +++ b/app/src/main/java/com/sopetit/softie/domain/usecase/PostAddDailyRoutineUseCase.kt @@ -0,0 +1,11 @@ +package com.sopetit.softie.domain.usecase + +import com.sopetit.softie.domain.repository.DailyRoutineRepository +import javax.inject.Inject + +class PostAddDailyRoutineUseCase @Inject constructor( + private val dailyRoutineRepository: DailyRoutineRepository +) { + suspend operator fun invoke(routineId: Int) = + dailyRoutineRepository.postAddDailyRoutine(routineId) +} diff --git a/app/src/main/java/com/sopetit/softie/ui/dailyroutine/DailyRoutineFragment.kt b/app/src/main/java/com/sopetit/softie/ui/dailyroutine/DailyRoutineFragment.kt index 1843fe1c..5b7de322 100644 --- a/app/src/main/java/com/sopetit/softie/ui/dailyroutine/DailyRoutineFragment.kt +++ b/app/src/main/java/com/sopetit/softie/ui/dailyroutine/DailyRoutineFragment.kt @@ -3,6 +3,7 @@ package com.sopetit.softie.ui.dailyroutine import android.content.Intent import android.os.Bundle import android.view.View +import android.widget.ImageView import android.widget.TextView import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity @@ -12,11 +13,14 @@ import com.sopetit.softie.databinding.FragmentDailyRoutineBinding import com.sopetit.softie.domain.entity.Bear import com.sopetit.softie.ui.dailyroutine.dailyroutineadd.DailyRoutineAddActivity import com.sopetit.softie.util.OriginalBottomSheet.Companion.BOTTOM_SHEET_TAG +import com.sopetit.softie.util.binding.BindingAdapter.setCoilImage import com.sopetit.softie.util.binding.BindingBottomSheet import com.sopetit.softie.util.binding.BindingFragment import com.sopetit.softie.util.setStatusBarColor import com.sopetit.softie.util.snackBar +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class DailyRoutineFragment : BindingFragment(R.layout.fragment_daily_routine) { @@ -29,12 +33,15 @@ class DailyRoutineFragment : binding.viewModel = viewModel + viewModel.getDailyRoutine() + moveToAddRoutine() getBundle() initSetDailyRoutineContent() initSetDeleteView() initSetRoutineDelete() addDailyRoutineMsg() + achieveRoutine() } private fun getBundle() { @@ -44,14 +51,42 @@ class DailyRoutineFragment : } private fun initSetDailyRoutineContent() { + viewModel.dailyRoutineListResponse.observe(viewLifecycleOwner) { dailyRoutineList -> + when (dailyRoutineList.size) { + 3 -> { + makeRoutineItemThirdView() + makeRoutineItemSecondView() + makeRoutineItemFirstView() + } + + 2 -> { + makeRoutineItemFirstView() + makeRoutineItemSecondView() + } + + 1 -> { + makeRoutineItemFirstView() + } + } + } + } + + private fun makeRoutineItemFirstView() { with(binding) { routineItemView( + ivDailyRoutineIconFirst, tvDailyRoutineAddNameFirst, tvDailyRoutineIngFirst, btnDailyRoutineYetFinFirst, 0 ) + } + } + + private fun makeRoutineItemSecondView() { + with(binding) { routineItemView( + ivDailyRoutineIconSecond, tvDailyRoutineAddNameSecond, tvDailyRoutineIngSecond, btnDailyRoutineYetFinSecond, @@ -60,27 +95,48 @@ class DailyRoutineFragment : } } + private fun makeRoutineItemThirdView() { + with(binding) { + routineItemView( + ivDailyRoutineIconThird, + tvDailyRoutineAddNameThird, + tvDailyRoutineIngThird, + btnDailyRoutineYetFinThird, + 2 + ) + } + } + private fun routineItemView( + dailyIcon: ImageView, routineTitle: TextView, achieveMsg: TextView, btn: View, index: Int ) { - viewModel.mockDailyRoutineList.observe(viewLifecycleOwner) { dailyRoutineList -> - val achieveCountMsg = - getString(R.string.daily_routine_ing).format(dailyRoutineList[index].achieveCount) - achieveMsg.text = achieveCountMsg - routineTitle.text = dailyRoutineList[index].content - viewModel.setRoutineAchieve(dailyRoutineList[index].isAchieve, index) + val dailyRoutine = viewModel.dailyRoutineListResponse.value - initSetDailyRoutineAchieve(btn, dailyRoutineList[index].routineId) + val achieveCountMsg = + getString(R.string.daily_routine_ing).format(dailyRoutine?.get(index)?.achieveCount) + achieveMsg.text = achieveCountMsg + routineTitle.text = dailyRoutine?.get(index)?.content + dailyIcon.setCoilImage(dailyRoutine?.get(index)?.iconImageUrl) + viewModel.setRoutineAchieve(dailyRoutine?.get(index)?.isAchieve ?: false, index) + + initSetDailyRoutineAchieve(btn, dailyRoutine?.get(index)?.routineId ?: 0) + } + + private fun achieveRoutine() { + viewModel.isRoutineAchieveFirst.observe(viewLifecycleOwner) { + } + viewModel.isRoutineAchieveSecond.observe(viewLifecycleOwner) { + } + viewModel.isRoutineAchieveThird.observe(viewLifecycleOwner) { } } private fun initSetDailyRoutineAchieve(btn: View, routineId: Int) { btn.setOnClickListener { - // TODO 서버통신 구현 후 imageUri 버전으로 수정 - BindingBottomSheet.Builder().build( isDrawable = true, imageDrawable = R.drawable.ic_bear_face_crying, @@ -95,6 +151,7 @@ class DailyRoutineFragment : backBtnAction = {}, doBtnAction = { startDailyRoutineCompleteActivity() + viewModel.patchAchieveDaily(routineId) } ).show(parentFragmentManager, BOTTOM_SHEET_TAG) } @@ -125,10 +182,28 @@ class DailyRoutineFragment : } private fun clickEditRadioBtn() { - viewModel.mockDailyRoutineList.observe(viewLifecycleOwner) { routineList -> - with(binding) { - changeBtnSelectState(btnDailyRoutineRadioFirst, routineList[0].routineId) - changeBtnSelectState(btnDailyRoutineRadioSecond, routineList[1].routineId) + viewModel.dailyRoutineListResponse.observe(viewLifecycleOwner) { routineList -> + when (routineList.size) { + 3 -> { + with(binding) { + changeBtnSelectState(btnDailyRoutineRadioFirst, routineList[0].routineId) + changeBtnSelectState(btnDailyRoutineRadioSecond, routineList[1].routineId) + changeBtnSelectState(btnDailyRoutineRadioThird, routineList[2].routineId) + } + } + + 2 -> { + with(binding) { + changeBtnSelectState(btnDailyRoutineRadioFirst, routineList[0].routineId) + changeBtnSelectState(btnDailyRoutineRadioSecond, routineList[1].routineId) + } + } + + 1 -> { + with(binding) { + changeBtnSelectState(btnDailyRoutineRadioFirst, routineList[0].routineId) + } + } } } } @@ -156,31 +231,31 @@ class DailyRoutineFragment : } private fun initSetRoutineDelete() { - viewModel.isEditBtnEnabled.observe(viewLifecycleOwner) { isBtnEnabled -> - if (isBtnEnabled) { - binding.btnDailyRoutineDelete.setOnClickListener { - BindingBottomSheet.Builder().build( - isDrawable = true, - imageDrawable = R.drawable.ic_bear_face_crying, - imageUri = "", - title = "정말 삭제할까요?", - content = "루틴을 삭제해도 달성 횟수는 저장돼요", - isContentVisible = true, - contentColor = R.color.red, - backBtnContent = "취소", - doBtnContent = "삭제할래", - doBtnColor = R.drawable.shape_red_fill_12_rect, - backBtnAction = {}, - doBtnAction = { - snackBar( - binding.root.rootView, - "데일리 루틴을 ${viewModel.editRoutineIdArray.size}개 삭제했어요" - ) - viewModel.setDeleteView(false) - } - ).show(parentFragmentManager, BOTTOM_SHEET_TAG) + binding.btnDailyRoutineDelete.setOnClickListener { + BindingBottomSheet.Builder().build( + isDrawable = true, + imageDrawable = R.drawable.ic_bear_face_crying, + imageUri = "", + title = "정말 삭제할까요?", + content = "루틴을 삭제해도 달성 횟수는 저장돼요", + isContentVisible = true, + contentColor = R.color.red, + backBtnContent = "취소", + doBtnContent = "삭제할래", + doBtnColor = R.drawable.shape_red_fill_12_rect, + backBtnAction = {}, + doBtnAction = { + viewModel.deleteDailyRoutine() + viewModel.isDailyRoutineDelete.observe(viewLifecycleOwner) { + snackBar( + binding.root.rootView, + "데일리 루틴을 ${viewModel.editRoutineIdArray.size}개 삭제했어요" + ) + viewModel.setDeleteView(false) + viewModel.getDailyRoutine() + } } - } + ).show(parentFragmentManager, BOTTOM_SHEET_TAG) } } diff --git a/app/src/main/java/com/sopetit/softie/ui/dailyroutine/DailyRoutineViewModel.kt b/app/src/main/java/com/sopetit/softie/ui/dailyroutine/DailyRoutineViewModel.kt index 59fb7b4f..67808b7a 100644 --- a/app/src/main/java/com/sopetit/softie/ui/dailyroutine/DailyRoutineViewModel.kt +++ b/app/src/main/java/com/sopetit/softie/ui/dailyroutine/DailyRoutineViewModel.kt @@ -3,31 +3,41 @@ package com.sopetit.softie.ui.dailyroutine import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.sopetit.softie.domain.entity.DailyRoutine +import com.sopetit.softie.domain.entity.UserDailyRoutine +import com.sopetit.softie.domain.usecase.DeleteDailyRoutineUseCase +import com.sopetit.softie.domain.usecase.GetDailyRoutineUseCase +import com.sopetit.softie.domain.usecase.PatchAchieveDailyUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject -class DailyRoutineViewModel : ViewModel() { - - private val _mockDailyRoutineList: MutableLiveData> = MutableLiveData( - mutableListOf( - DailyRoutine( - 1, - "일찍 일어나기", - "", - 3, - true - ), - DailyRoutine( - 2, - "작업 끝내기", - "", - 5, - false - ) - ) - ) - - val mockDailyRoutineList: LiveData> - get() = _mockDailyRoutineList +@HiltViewModel +class DailyRoutineViewModel @Inject constructor( + private val getDailyRoutineUseCase: GetDailyRoutineUseCase, + private val patchAchieveDailyUseCase: PatchAchieveDailyUseCase, + private val deleteDailyRoutineUseCase: DeleteDailyRoutineUseCase +) : + ViewModel() { + private val _dailyRoutineListResponse: MutableLiveData> = MutableLiveData() + val dailyRoutineListResponse: LiveData> + get() = _dailyRoutineListResponse + + fun getDailyRoutine() { + viewModelScope.launch { + getDailyRoutineUseCase() + .onSuccess { response -> + _dailyRoutineListResponse.value = response + Timber.d("유저 데일리 성공") + } + .onFailure { throwable -> + Timber.e("$throwable") + Timber.d("유저 데일리 실패") + } + } + } private val _isRoutineAchieveFirst: MutableLiveData = MutableLiveData() val isRoutineAchieveFirst: LiveData @@ -41,6 +51,30 @@ class DailyRoutineViewModel : ViewModel() { val isRoutineAchieveThird: LiveData get() = _isRoutineAchieveThird + private val _isDailyRoutineDelete: MutableLiveData = MutableLiveData(false) + val isDailyRoutineDelete: LiveData get() = _isDailyRoutineDelete + + fun patchAchieveDaily(routineId: Int) { + viewModelScope.launch { + patchAchieveDailyUseCase(routineId) + .onSuccess { response -> + routineAchieve(routineId, response.isAchieve) + _isDailyRoutineDelete.value = false + } + .onFailure { throwable -> + Timber.e("$throwable") + } + } + } + + private fun routineAchieve(routineId: Int, isAchieve: Boolean) { + when (routineId) { + dailyRoutineListResponse.value?.get(0)?.routineId -> setRoutineAchieve(isAchieve, 0) + dailyRoutineListResponse.value?.get(1)?.routineId -> setRoutineAchieve(isAchieve, 1) + dailyRoutineListResponse.value?.get(2)?.routineId -> setRoutineAchieve(isAchieve, 2) + } + } + private val _isDeleteView: MutableLiveData = MutableLiveData(false) val isDeleteView: LiveData get() = _isDeleteView @@ -63,6 +97,21 @@ class DailyRoutineViewModel : ViewModel() { _isDeleteView.value = deleteEnabled } + fun deleteDailyRoutine() { + viewModelScope.launch { + deleteDailyRoutineUseCase(editRoutineIdArray) + .onSuccess { + setDeleteView(deleteEnabled = false) + Timber.d("삭제 서버 성공") + _isDailyRoutineDelete.value = true + } + .onFailure { throwable -> + Timber.d("삭제 서버 실패") + Timber.e("$throwable") + } + } + } + fun setEditRoutineIdArray(routineId: Int) { if (editRoutineIdArray.contains(routineId)) { editRoutineIdArray.removeAt(editRoutineIdArray.indexOf(routineId)) @@ -74,4 +123,8 @@ class DailyRoutineViewModel : ViewModel() { fun setEditBtnEnabled(enabled: Boolean) { _isEditBtnEnabled.value = enabled } + + private val _userDaily: LiveData = MutableLiveData() + val userDaily: LiveData + get() = _userDaily } diff --git a/app/src/main/java/com/sopetit/softie/ui/dailyroutine/dailyroutineadd/DailyRoutineAddActivity.kt b/app/src/main/java/com/sopetit/softie/ui/dailyroutine/dailyroutineadd/DailyRoutineAddActivity.kt index a77968c2..3fb478a9 100644 --- a/app/src/main/java/com/sopetit/softie/ui/dailyroutine/dailyroutineadd/DailyRoutineAddActivity.kt +++ b/app/src/main/java/com/sopetit/softie/ui/dailyroutine/dailyroutineadd/DailyRoutineAddActivity.kt @@ -11,6 +11,7 @@ import androidx.viewpager2.widget.CompositePageTransformer import androidx.viewpager2.widget.MarginPageTransformer import androidx.viewpager2.widget.ViewPager2 import com.sopetit.softie.R +import com.sopetit.softie.data.entity.request.AddDailyRoutineRequest import com.sopetit.softie.databinding.ActivityDailyRoutineAddBinding import com.sopetit.softie.domain.entity.Theme import com.sopetit.softie.ui.main.MainActivity @@ -18,7 +19,9 @@ import com.sopetit.softie.util.OriginalBottomSheet import com.sopetit.softie.util.binding.BindingActivity import com.sopetit.softie.util.binding.BindingBottomSheet import com.sopetit.softie.util.setStatusBarColorFromResource +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class DailyRoutineAddActivity : BindingActivity(R.layout.activity_daily_routine_add) { private lateinit var viewPager: ViewPager2 @@ -30,9 +33,13 @@ class DailyRoutineAddActivity : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewPager = binding.vpDailyRoutineAddCard + binding.viewModel = dailyRoutineAddViewModel setStatusBarColorFromResource(R.color.background) + val request = AddDailyRoutineRequest(routineId = 1) + initSetDailyRoutineAdd(request) + setupAdapter() setViewPager() setupList() @@ -40,11 +47,9 @@ class DailyRoutineAddActivity : setItemDiv() initPagerDiv(0, 90) addClickListener() - initSetDailyRoutineAdd() } private fun addClickListener() { - addRoutine() backToDailyRoutine() } @@ -146,22 +151,14 @@ class DailyRoutineAddActivity : binding.rvDailyRoutineAddTheme.addItemDecoration(HorizontalItemDecorator(16)) } - private fun addRoutine() { - binding.btnDailyRoutineAdd.setOnClickListener { - finish() - } - } - private fun backToDailyRoutine() { binding.ivDailyRoutineAddBack.setOnClickListener { finish() } } - private fun initSetDailyRoutineAdd() { + private fun initSetDailyRoutineAdd(request: AddDailyRoutineRequest) { binding.btnDailyRoutineAdd.setOnClickListener { - // TODO 서버통신 구현 후 imageUri 버전으로 수정 - BindingBottomSheet.Builder().build( isDrawable = false, imageDrawable = 0, @@ -176,6 +173,7 @@ class DailyRoutineAddActivity : backBtnAction = {}, doBtnAction = { tossMsg() + dailyRoutineAddViewModel.postAddDailyRoutine(request.routineId) } ).show(supportFragmentManager, OriginalBottomSheet.BOTTOM_SHEET_TAG) } @@ -191,5 +189,6 @@ class DailyRoutineAddActivity : const val VIEW_PAGE = 3 const val PADDING_PAGE = 40 const val PADDING_CARD = 0 + const val ID = "id" } } diff --git a/app/src/main/java/com/sopetit/softie/ui/dailyroutine/dailyroutineadd/DailyRoutineAddViewModel.kt b/app/src/main/java/com/sopetit/softie/ui/dailyroutine/dailyroutineadd/DailyRoutineAddViewModel.kt index 5fd3feb8..10fc57bf 100644 --- a/app/src/main/java/com/sopetit/softie/ui/dailyroutine/dailyroutineadd/DailyRoutineAddViewModel.kt +++ b/app/src/main/java/com/sopetit/softie/ui/dailyroutine/dailyroutineadd/DailyRoutineAddViewModel.kt @@ -3,11 +3,20 @@ package com.sopetit.softie.ui.dailyroutine.dailyroutineadd import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sopetit.softie.domain.entity.AddRoutine import com.sopetit.softie.domain.entity.DailyCard import com.sopetit.softie.domain.entity.DailyRoutineAdd import com.sopetit.softie.domain.entity.Theme +import com.sopetit.softie.domain.usecase.PostAddDailyRoutineUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject -class DailyRoutineAddViewModel : ViewModel() { +@HiltViewModel +class DailyRoutineAddViewModel @Inject constructor(private val postAddDailyRoutineUseCase: PostAddDailyRoutineUseCase) : + ViewModel() { private val _mockThemeList: MutableLiveData> = MutableLiveData( mutableListOf( Theme( @@ -545,4 +554,22 @@ class DailyRoutineAddViewModel : ViewModel() { fun getDailyCardListForId(themeId: Int): List { return themeDailyRoutineList.value?.filter { it.themeId == themeId } ?: emptyList() } + + private val _addDailyRoutine: MutableLiveData = MutableLiveData() + val addDailyRoutine: LiveData + get() = _addDailyRoutine + + fun postAddDailyRoutine(routineId: Int) { + viewModelScope.launch { + postAddDailyRoutineUseCase.invoke(routineId) + .onSuccess { response -> + _addDailyRoutine.value = response + Timber.d("추가 성공") + } + .onFailure { throwable -> + Timber.e("$throwable") + Timber.d("추가 실패") + } + } + } } diff --git a/app/src/main/res/layout/fragment_daily_routine.xml b/app/src/main/res/layout/fragment_daily_routine.xml index 274e3f81..c4a6fd3b 100644 --- a/app/src/main/res/layout/fragment_daily_routine.xml +++ b/app/src/main/res/layout/fragment_daily_routine.xml @@ -34,11 +34,12 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="6dp" + android:clickable="@{viewModel.dailyRoutineListResponse.size() == 0 ? false : true}" + android:paddingHorizontal="14dp" + android:paddingVertical="12dp" android:text="@{viewModel.isDeleteView ? @string/daily_routine_edit_cancel : @string/daily_routine_edit}" android:textAppearance="@style/body4" android:textColor="@color/gray400" - android:paddingVertical="12dp" - android:paddingHorizontal="14dp" app:layout_constraintBottom_toBottomOf="@id/tv_daily_routine_name" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@id/tv_daily_routine_name" /> @@ -47,17 +48,17 @@ android:id="@+id/v_daily_routine_blank" android:layout_width="match_parent" android:layout_height="2dp" - android:visibility="@{viewModel.mockDailyRoutineList.size() == 0 ? View.VISIBLE : View.GONE}" + android:visibility="@{viewModel.dailyRoutineListResponse.size() == 0 ? View.VISIBLE : View.GONE}" app:layout_constraintTop_toBottomOf="@id/tv_daily_routine_name" /> @@ -88,6 +89,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="12dp" + android:lineSpacingMultiplier="1.5" android:text="@string/daily_routine_user_add" android:textAppearance="@style/body1" app:layout_constraintStart_toEndOf="@id/iv_daily_routine_icon_first" @@ -108,9 +110,11 @@ android:layout_height="wrap_content" android:layout_marginStart="4dp" android:layout_marginTop="5dp" - android:text="@{@string/daily_routine_ing(viewModel.mockDailyRoutineList[0].achieveCount)}" + android:layout_marginBottom="21dp" + android:text="@{@string/daily_routine_ing(viewModel.dailyRoutineListResponse[0].achieveCount)}" android:textAppearance="@style/caption1" android:textColor="@color/gray300" + app:layout_constraintBottom_toTopOf="@id/btn_daily_routine_yet_fin_first" app:layout_constraintStart_toEndOf="@id/iv_daily_routine_fin_first" app:layout_constraintTop_toBottomOf="@id/tv_daily_routine_add_name_first" /> @@ -119,20 +123,22 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginHorizontal="20dp" + android:layout_marginTop="82dp" android:layout_marginBottom="16dp" android:background="@{viewModel.isRoutineAchieveFirst ? @drawable/shape_gray100_fill_10_rect : @drawable/shape_main1_fill_10_rect}" - android:enabled="@{!viewModel.isRoutineAchieveFirst}" android:clickable="@{!viewModel.isRoutineAchieveFirst}" - android:text="@{viewModel.isRoutineAchieveFirst ? @string/daily_routine_fin : @string/daily_routine_fin_btn}" + android:enabled="@{!viewModel.isRoutineAchieveFirst}" android:minHeight="0dp" + android:outlineProvider="none" android:paddingTop="10dp" android:paddingBottom="11dp" + android:text="@{viewModel.isRoutineAchieveFirst ? @string/daily_routine_fin : @string/daily_routine_fin_btn}" android:textAppearance="@style/body4" android:textColor="@color/white" - android:outlineProvider="none" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> @@ -141,11 +147,11 @@ @@ -176,6 +182,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="12dp" + android:lineSpacingMultiplier="1.5" android:text="@string/daily_routine_user_add" android:textAppearance="@style/body1" app:layout_constraintStart_toEndOf="@id/iv_daily_routine_icon_second" @@ -183,8 +190,8 @@ @@ -207,28 +216,30 @@ android:layout_width="0dp" android:layout_height="38dp" android:layout_marginHorizontal="20dp" + android:layout_marginTop="82dp" android:layout_marginBottom="16dp" android:background="@{viewModel.isRoutineAchieveSecond ? @drawable/shape_gray100_fill_10_rect : @drawable/shape_main1_fill_10_rect}" - android:enabled="@{!viewModel.isRoutineAchieveSecond}" android:clickable="@{!viewModel.isRoutineAchieveSecond}" + android:enabled="@{!viewModel.isRoutineAchieveSecond}" + android:outlineProvider="none" android:text="@{viewModel.isRoutineAchieveSecond ? @string/daily_routine_fin : @string/daily_routine_fin_btn}" android:textAppearance="@style/body4" android:textColor="@color/white" - android:outlineProvider="none" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> @@ -259,6 +270,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="12dp" + android:lineSpacingMultiplier="1.5" android:text="@string/daily_routine_user_add" android:textAppearance="@style/body1" app:layout_constraintStart_toEndOf="@id/iv_daily_routine_icon_third" @@ -279,9 +291,11 @@ android:layout_height="wrap_content" android:layout_marginStart="4dp" android:layout_marginTop="5dp" + android:layout_marginBottom="21dp" android:text="@string/daily_routine_ing" android:textAppearance="@style/caption1" android:textColor="@color/gray300" + app:layout_constraintBottom_toTopOf="@id/btn_daily_routine_yet_fin_third" app:layout_constraintStart_toEndOf="@id/iv_daily_routine_fin_third" app:layout_constraintTop_toBottomOf="@id/tv_daily_routine_add_name_third" /> @@ -290,20 +304,22 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginHorizontal="20dp" + android:layout_marginTop="82dp" android:layout_marginBottom="16dp" android:background="@{viewModel.isRoutineAchieveThird ? @drawable/shape_gray100_fill_10_rect : @drawable/shape_main1_fill_10_rect}" - android:enabled="@{!viewModel.isRoutineAchieveThird}" android:clickable="@{!viewModel.isRoutineAchieveThird}" - android:text="@{viewModel.isRoutineAchieveThird ? @string/daily_routine_fin : @string/daily_routine_fin_btn}" + android:enabled="@{!viewModel.isRoutineAchieveThird}" android:minHeight="0dp" + android:outlineProvider="none" android:paddingTop="10dp" android:paddingBottom="11dp" + android:text="@{viewModel.isRoutineAchieveThird ? @string/daily_routine_fin : @string/daily_routine_fin_btn}" android:textAppearance="@style/body4" android:textColor="@color/white" - android:outlineProvider="none" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> @@ -315,7 +331,7 @@ android:layout_marginTop="8dp" android:background="@drawable/shape_gray200_line_20_rect" android:clickable="true" - android:visibility="@{viewModel.mockDailyRoutineList.size() == 3 ? View.GONE : View.VISIBLE}" + android:visibility="@{viewModel.dailyRoutineListResponse.size() == 3 ? View.GONE : View.VISIBLE}" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/cl_daily_routine_third"> @@ -340,13 +356,13 @@ android:background="@{viewModel.isEditBtnEnabled ? @drawable/shape_red_fill_12_rect : @drawable/shape_gray200_fill_12_rect}" android:clickable="@{viewModel.isEditBtnEnabled ? true : false}" android:enabled="@{viewModel.isEditBtnEnabled ? true : false}" + android:outlineProvider="none" android:paddingTop="20dp" android:paddingBottom="18dp" android:text="@{@string/daily_routine_edit_delete(viewModel.editRoutineIdArray.size)}" android:textAppearance="@style/body1" android:textColor="@color/gray000" android:visibility="@{viewModel.isDeleteView ? View.VISIBLE : View.INVISIBLE}" - android:outlineProvider="none" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" />