@@ -2,20 +2,22 @@ package com.threegap.bitnagil.presentation.routinelist
22
33import android.util.Log
44import androidx.lifecycle.SavedStateHandle
5+ import androidx.lifecycle.ViewModel
56import androidx.lifecycle.viewModelScope
67import com.threegap.bitnagil.domain.routine.usecase.DeleteRoutineForDayUseCase
78import com.threegap.bitnagil.domain.routine.usecase.DeleteRoutineUseCase
89import com.threegap.bitnagil.domain.routine.usecase.FetchWeeklyRoutinesUseCase
910import com.threegap.bitnagil.domain.writeroutine.usecase.GetWriteRoutineEventFlowUseCase
10- import com.threegap.bitnagil.presentation.common.mviviewmodel.MviViewModel
1111import com.threegap.bitnagil.presentation.home.util.getCurrentWeekDays
12- import com.threegap.bitnagil.presentation.routinelist.model.RoutineListIntent
1312import com.threegap.bitnagil.presentation.routinelist.model.RoutineListSideEffect
1413import com.threegap.bitnagil.presentation.routinelist.model.RoutineListState
14+ import com.threegap.bitnagil.presentation.routinelist.model.RoutineUiModel
1515import com.threegap.bitnagil.presentation.routinelist.model.toUiModel
1616import dagger.hilt.android.lifecycle.HiltViewModel
1717import kotlinx.coroutines.launch
18- import org.orbitmvi.orbit.syntax.Syntax
18+ import org.orbitmvi.orbit.Container
19+ import org.orbitmvi.orbit.ContainerHost
20+ import org.orbitmvi.orbit.viewmodel.container
1921import java.time.LocalDate
2022import javax.inject.Inject
2123
@@ -26,95 +28,51 @@ class RoutineListViewModel @Inject constructor(
2628 private val deleteRoutineUseCase : DeleteRoutineUseCase ,
2729 private val deleteRoutineForDayUseCase : DeleteRoutineForDayUseCase ,
2830 private val getWriteRoutineEventFlowUseCase : GetWriteRoutineEventFlowUseCase ,
29- ) : MviViewModel<RoutineListState, RoutineListSideEffect, RoutineListIntent>(
30- savedStateHandle = savedStateHandle,
31- initState = RoutineListState (
32- selectedDate = savedStateHandle.get<String >("selectedDate")
33- ?.takeIf { it.isNotBlank() }
34- ?.let { dateString ->
35- runCatching { LocalDate .parse(dateString) }.getOrNull()
36- }
37- ? : LocalDate .now(),
38- ),
39- ) {
31+ ) : ContainerHost<RoutineListState, RoutineListSideEffect>, ViewModel() {
32+
33+ override val container: Container <RoutineListState , RoutineListSideEffect > = container(initialState = RoutineListState .INIT )
34+
35+ private val selectedDate = savedStateHandle.get<String >(" selectedDate" )
36+ ?.takeIf { it.isNotBlank() }
37+ ?.let { dateString ->
38+ runCatching { LocalDate .parse(dateString) }.getOrNull()
39+ }
40+ ? : LocalDate .now()
4041
4142 init {
43+ updateDate(selectedDate)
4244 fetchRoutines()
4345 observeRoutineChanges()
4446 }
4547
46- override suspend fun Syntax <RoutineListState , RoutineListSideEffect >.reduceState (
47- intent : RoutineListIntent ,
48- state : RoutineListState ,
49- ): RoutineListState ? {
50- val newState = when (intent) {
51- is RoutineListIntent .UpdateLoading -> state.copy(isLoading = intent.isLoading)
52- is RoutineListIntent .LoadRoutines -> state.copy(routines = intent.routines)
53- is RoutineListIntent .OnDateSelect -> state.copy(selectedDate = intent.date)
54-
55- is RoutineListIntent .ShowDeleteConfirmBottomSheet -> {
56- state.copy(
57- selectedRoutine = intent.routine,
58- deleteConfirmBottomSheetVisible = true ,
59- )
60- }
61-
62- is RoutineListIntent .ShowEditConfirmBottomSheet -> {
63- state.copy(
64- selectedRoutine = intent.routine,
65- editConfirmBottomSheetVisible = true ,
66- )
67- }
68-
69- is RoutineListIntent .HideDeleteConfirmBottomSheet -> state.copy(deleteConfirmBottomSheetVisible = false )
70- is RoutineListIntent .HideEditConfirmBottomSheet -> state.copy(editConfirmBottomSheetVisible = false )
71-
72- is RoutineListIntent .NavigateToBack -> {
73- sendSideEffect(RoutineListSideEffect .NavigateToBack )
74- null
75- }
76-
77- is RoutineListIntent .OnRegisterRoutineClick -> {
78- sendSideEffect(RoutineListSideEffect .NavigateToAddRoutine )
79- null
80- }
48+ fun updateDate (selectedDate : LocalDate ) {
49+ intent {
50+ reduce { state.copy(selectedDate = selectedDate) }
51+ }
52+ }
8153
82- is RoutineListIntent .OnApplyTodayClick -> {
83- val selectedRoutine = state.selectedRoutine
84- if (selectedRoutine != null ) {
85- sendSideEffect(
86- RoutineListSideEffect .NavigateToEditRoutine (
87- routineId = selectedRoutine.routineId,
88- updateRoutineFromNowDate = true ,
89- ),
90- )
91- }
92- null
93- }
54+ fun showDeleteConfirmBottomSheet (routine : RoutineUiModel ) {
55+ intent {
56+ reduce { state.copy(selectedRoutine = routine, deleteConfirmBottomSheetVisible = true ) }
57+ }
58+ }
9459
95- is RoutineListIntent .OnApplyTomorrowClick -> {
96- val selectedRoutine = state.selectedRoutine
97- if (selectedRoutine != null ) {
98- sendSideEffect(
99- RoutineListSideEffect .NavigateToEditRoutine (
100- routineId = selectedRoutine.routineId,
101- updateRoutineFromNowDate = false ,
102- ),
103- )
104- }
105- null
106- }
60+ fun hideDeleteConfirmBottomSheet () {
61+ intent {
62+ reduce { state.copy(deleteConfirmBottomSheetVisible = false ) }
63+ }
64+ }
10765
108- is RoutineListIntent .OnSuccessDeletedRoutine -> {
109- sendSideEffect(RoutineListSideEffect .ShowToast (" 삭제가 완료되었습니다." ))
110- state.copy(
111- isLoading = false ,
112- deleteConfirmBottomSheetVisible = false ,
113- )
114- }
66+ fun showEditConfirmBottomSheet (routine : RoutineUiModel ) {
67+ intent {
68+ reduce { state.copy(selectedRoutine = routine, editConfirmBottomSheetVisible = true ) }
11569 }
70+ }
11671
117- return newState
72+ fun hideEditConfirmBottomSheet () {
73+ intent {
74+ reduce { state.copy(editConfirmBottomSheetVisible = false ) }
75+ }
11876 }
11977
12078 private fun observeRoutineChanges () {
@@ -126,55 +84,80 @@ class RoutineListViewModel @Inject constructor(
12684 }
12785
12886 private fun fetchRoutines () {
129- sendIntent( RoutineListIntent . UpdateLoading ( true ))
130- val currentWeek = stateFlow.value.selectedDate.getCurrentWeekDays()
131- val startDate = currentWeek.first().toString ()
132- val endDate = currentWeek.last ().toString()
133- viewModelScope.launch {
87+ intent {
88+ reduce { state.copy(isLoading = true ) }
89+ val currentWeek = state.selectedDate.getCurrentWeekDays ()
90+ val startDate = currentWeek.first ().toString()
91+ val endDate = currentWeek.last().toString()
13492 fetchWeeklyRoutinesUseCase(startDate, endDate).fold(
135- onSuccess = { routines ->
136- sendIntent(RoutineListIntent .LoadRoutines (routines.toUiModel()))
137- sendIntent(RoutineListIntent .UpdateLoading (false ))
93+ onSuccess = { routineSchedule ->
94+ reduce { state.copy(isLoading = false , routines = routineSchedule.toUiModel()) }
13895 },
13996 onFailure = {
14097 Log .e(" RoutineListViewModel" , " 루틴 가져오기 실패: ${it.message} " )
141- sendIntent( RoutineListIntent . UpdateLoading ( false ))
98+ reduce { state.copy(isLoading = false ) }
14299 },
143100 )
144101 }
145102 }
146103
147104 fun deleteRoutineCompletely () {
148- sendIntent( RoutineListIntent . UpdateLoading ( true ))
149- val selectedRoutine = stateFlow.value.selectedRoutine !!
150- viewModelScope.launch {
105+ intent {
106+ reduce { state.copy(isLoading = true ) }
107+ val selectedRoutine = state.selectedRoutine ? : return @intent
151108 deleteRoutineUseCase(selectedRoutine.routineId).fold(
152109 onSuccess = {
153110 fetchRoutines()
154- sendIntent(RoutineListIntent .OnSuccessDeletedRoutine )
111+ reduce { state.copy(isLoading = false , deleteConfirmBottomSheetVisible = false ) }
112+ postSideEffect(RoutineListSideEffect .ShowToast (" 삭제가 완료되었습니다." ))
155113 },
156114 onFailure = {
157115 Log .e(" RoutineListViewModel" , " 루틴 삭제 실패: ${it.message} " )
158- sendIntent( RoutineListIntent . UpdateLoading ( false ))
116+ reduce { state.copy(isLoading = false ) }
159117 },
160118 )
161119 }
162120 }
163121
164122 fun deleteRoutineForToday () {
165- sendIntent( RoutineListIntent . UpdateLoading ( true ))
166- val selectedRoutine = stateFlow.value.selectedRoutine !!
167- viewModelScope.launch {
123+ intent {
124+ reduce { state.copy(isLoading = true ) }
125+ val selectedRoutine = state.selectedRoutine ? : return @intent
168126 deleteRoutineForDayUseCase(selectedRoutine.routineId).fold(
169127 onSuccess = {
170128 fetchRoutines()
171- sendIntent(RoutineListIntent .OnSuccessDeletedRoutine )
129+ reduce { state.copy(isLoading = false , deleteConfirmBottomSheetVisible = false ) }
130+ postSideEffect(RoutineListSideEffect .ShowToast (" 삭제가 완료되었습니다." ))
172131 },
173132 onFailure = {
174133 Log .e(" RoutineListViewModel" , " 루틴 삭제 실패: ${it.message} " )
175- sendIntent( RoutineListIntent . UpdateLoading ( false ))
134+ reduce { state.copy(isLoading = false ) }
176135 },
177136 )
178137 }
179138 }
139+
140+ fun navigateToAddRoutine () {
141+ intent {
142+ postSideEffect(RoutineListSideEffect .NavigateToAddRoutine )
143+ }
144+ }
145+
146+ fun navigateToEditRoutine (updateFromNow : Boolean ) {
147+ intent {
148+ val selectedRoutine = state.selectedRoutine ? : return @intent
149+ postSideEffect(
150+ RoutineListSideEffect .NavigateToEditRoutine (
151+ routineId = selectedRoutine.routineId,
152+ updateRoutineFromNowDate = updateFromNow,
153+ ),
154+ )
155+ }
156+ }
157+
158+ fun navigateToBack () {
159+ intent {
160+ postSideEffect(RoutineListSideEffect .NavigateToBack )
161+ }
162+ }
180163}
0 commit comments