Skip to content

Commit 9ef1c36

Browse files
committed
Refactor: Withdrawal MviViewmodel 제거 및 responseDto 추가
1 parent 1bfff58 commit 9ef1c36

12 files changed

Lines changed: 87 additions & 95 deletions

File tree

data/src/main/java/com/threegap/bitnagil/data/auth/datasource/AuthRemoteDataSource.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ interface AuthRemoteDataSource {
88
suspend fun login(socialAccessToken: String, loginRequestDto: LoginRequestDto): Result<LoginResponseDto>
99
suspend fun submitAgreement(termsAgreementRequestDto: TermsAgreementRequestDto): Result<Unit>
1010
suspend fun logout(): Result<Unit>
11-
suspend fun withdrawal(): Result<Unit>
11+
suspend fun withdrawal(reason: String): Result<Unit>
1212
suspend fun reissueToken(refreshToken: String): Result<LoginResponseDto>
1313
}

data/src/main/java/com/threegap/bitnagil/data/auth/datasourceimpl/AuthRemoteDataSourceImpl.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.threegap.bitnagil.data.auth.datasourceimpl
33
import com.threegap.bitnagil.data.auth.datasource.AuthRemoteDataSource
44
import com.threegap.bitnagil.data.auth.model.request.LoginRequestDto
55
import com.threegap.bitnagil.data.auth.model.request.TermsAgreementRequestDto
6+
import com.threegap.bitnagil.data.auth.model.request.WithdrawalReasonResponse
67
import com.threegap.bitnagil.data.auth.model.response.LoginResponseDto
78
import com.threegap.bitnagil.data.auth.service.AuthService
89
import com.threegap.bitnagil.data.common.safeApiCall
@@ -27,9 +28,9 @@ class AuthRemoteDataSourceImpl @Inject constructor(
2728
authService.postLogout()
2829
}
2930

30-
override suspend fun withdrawal(): Result<Unit> =
31+
override suspend fun withdrawal(reason: String): Result<Unit> =
3132
safeUnitApiCall {
32-
authService.postWithdrawal()
33+
authService.postWithdrawal(WithdrawalReasonResponse(reason))
3334
}
3435

3536
override suspend fun reissueToken(refreshToken: String): Result<LoginResponseDto> =
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.threegap.bitnagil.data.auth.model.request
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
data class WithdrawalReasonResponse(
8+
@SerialName("reasonOfWithdrawal") val reasonOfWithdrawal: String,
9+
)

data/src/main/java/com/threegap/bitnagil/data/auth/repositoryimpl/AuthRepositoryImpl.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class AuthRepositoryImpl @Inject constructor(
2929
}
3030
}
3131

32-
override suspend fun withdrawal(): Result<Unit> {
33-
return authRemoteDataSource.withdrawal().also {
32+
override suspend fun withdrawal(reason: String): Result<Unit> {
33+
return authRemoteDataSource.withdrawal(reason).also {
3434
if (it.isSuccess) authLocalDataSource.clearAuthToken()
3535
}
3636
}

data/src/main/java/com/threegap/bitnagil/data/auth/service/AuthService.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.threegap.bitnagil.data.auth.service
22

33
import com.threegap.bitnagil.data.auth.model.request.LoginRequestDto
44
import com.threegap.bitnagil.data.auth.model.request.TermsAgreementRequestDto
5+
import com.threegap.bitnagil.data.auth.model.request.WithdrawalReasonResponse
56
import com.threegap.bitnagil.data.auth.model.response.LoginResponseDto
67
import com.threegap.bitnagil.network.model.BaseResponse
78
import retrofit2.http.Body
@@ -23,7 +24,7 @@ interface AuthService {
2324
): BaseResponse<Unit>
2425

2526
@POST("/api/v1/auth/withdrawal")
26-
suspend fun postWithdrawal(): BaseResponse<Unit>
27+
suspend fun postWithdrawal(@Body request: WithdrawalReasonResponse): BaseResponse<Unit>
2728

2829
@POST("/api/v1/auth/logout")
2930
suspend fun postLogout(): BaseResponse<Unit>

domain/src/main/java/com/threegap/bitnagil/domain/auth/repository/AuthRepository.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ interface AuthRepository {
77
suspend fun login(socialAccessToken: String, socialType: String): Result<AuthSession>
88
suspend fun submitAgreement(termsAgreement: TermsAgreement): Result<Unit>
99
suspend fun logout(): Result<Unit>
10-
suspend fun withdrawal(): Result<Unit>
10+
suspend fun withdrawal(reason: String): Result<Unit>
1111

1212
suspend fun reissueToken(refreshToken: String): Result<AuthSession>
1313
suspend fun getRefreshToken(): String?

domain/src/main/java/com/threegap/bitnagil/domain/auth/usecase/WithdrawalUseCase.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ import javax.inject.Inject
66
class WithdrawalUseCase @Inject constructor(
77
private val authRepository: AuthRepository,
88
) {
9-
suspend operator fun invoke(): Result<Unit> = authRepository.withdrawal()
9+
suspend operator fun invoke(reason: String): Result<Unit> = authRepository.withdrawal(reason)
1010
}

presentation/src/main/java/com/threegap/bitnagil/presentation/withdrawal/WithdrawalScreen.kt

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import androidx.compose.ui.platform.LocalFocusManager
3131
import androidx.compose.ui.tooling.preview.Preview
3232
import androidx.compose.ui.unit.dp
3333
import androidx.hilt.navigation.compose.hiltViewModel
34-
import androidx.lifecycle.compose.collectAsStateWithLifecycle
3534
import com.threegap.bitnagil.designsystem.BitnagilTheme
3635
import com.threegap.bitnagil.designsystem.R
3736
import com.threegap.bitnagil.designsystem.component.atom.BitnagilIcon
@@ -40,22 +39,22 @@ import com.threegap.bitnagil.designsystem.component.atom.BitnagilSelectButtonCol
4039
import com.threegap.bitnagil.designsystem.component.atom.BitnagilTextButton
4140
import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar
4241
import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple
43-
import com.threegap.bitnagil.presentation.common.flow.collectAsEffect
4442
import com.threegap.bitnagil.presentation.withdrawal.component.WithdrawalConfirmDialog
45-
import com.threegap.bitnagil.presentation.withdrawal.model.WithdrawalIntent
4643
import com.threegap.bitnagil.presentation.withdrawal.model.WithdrawalReason
4744
import com.threegap.bitnagil.presentation.withdrawal.model.WithdrawalSideEffect
4845
import com.threegap.bitnagil.presentation.withdrawal.model.WithdrawalState
46+
import org.orbitmvi.orbit.compose.collectAsState
47+
import org.orbitmvi.orbit.compose.collectSideEffect
4948

5049
@Composable
5150
fun WithdrawalScreenContainer(
51+
viewModel: WithdrawalViewModel = hiltViewModel(),
5252
navigateToBack: () -> Unit,
5353
navigateToLogin: () -> Unit,
54-
viewModel: WithdrawalViewModel = hiltViewModel(),
5554
) {
56-
val uiState by viewModel.container.stateFlow.collectAsStateWithLifecycle()
55+
val uiState by viewModel.collectAsState()
5756

58-
viewModel.sideEffectFlow.collectAsEffect { sideEffect ->
57+
viewModel.collectSideEffect { sideEffect ->
5958
when (sideEffect) {
6059
is WithdrawalSideEffect.NavigateToBack -> navigateToBack()
6160
is WithdrawalSideEffect.NavigateToLogin -> navigateToLogin()
@@ -64,16 +63,16 @@ fun WithdrawalScreenContainer(
6463

6564
if (uiState.showSuccessDialog) {
6665
WithdrawalConfirmDialog(
67-
onConfirm = { viewModel.sendIntent(WithdrawalIntent.OnSuccessDialogConfirm) },
66+
onConfirm = viewModel::navigateToLogin,
6867
)
6968
}
7069

7170
WithdrawalScreen(
7271
uiState = uiState,
73-
onTermsToggle = { viewModel.sendIntent(WithdrawalIntent.OnTermsToggle) },
74-
onReasonSelect = { viewModel.sendIntent(WithdrawalIntent.OnReasonSelected(it)) },
75-
onCustomReasonChanged = { viewModel.sendIntent(WithdrawalIntent.OnCustomReasonChanged(it)) },
76-
onBackClick = { viewModel.sendIntent(WithdrawalIntent.OnBackClick) },
72+
onTermsToggle = viewModel::onTermsToggle,
73+
onReasonSelect = viewModel::updateSelectedReason,
74+
onCustomReasonChanged = viewModel::updateCustomReason,
75+
onBackClick = viewModel::navigateToBack,
7776
onWithdrawalClick = viewModel::withdrawal,
7877
)
7978
}
@@ -94,7 +93,6 @@ private fun WithdrawalScreen(
9493
Column(
9594
modifier = Modifier
9695
.fillMaxSize()
97-
.background(BitnagilTheme.colors.white)
9896
.statusBarsPadding()
9997
.windowInsetsPadding(WindowInsets.ime),
10098
) {
@@ -221,13 +219,11 @@ private fun WithdrawalScreen(
221219
}
222220
}
223221

224-
@Preview
222+
@Preview(showBackground = true)
225223
@Composable
226224
private fun WithdrawalScreenPreview() {
227225
WithdrawalScreen(
228-
uiState = WithdrawalState(
229-
isTermsChecked = true,
230-
),
226+
uiState = WithdrawalState.INIT,
231227
onTermsToggle = {},
232228
onReasonSelect = {},
233229
onCustomReasonChanged = {},
Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,66 @@
11
package com.threegap.bitnagil.presentation.withdrawal
22

3-
import androidx.lifecycle.SavedStateHandle
4-
import androidx.lifecycle.viewModelScope
3+
import androidx.lifecycle.ViewModel
54
import com.threegap.bitnagil.domain.auth.usecase.WithdrawalUseCase
6-
import com.threegap.bitnagil.presentation.common.mviviewmodel.MviViewModel
7-
import com.threegap.bitnagil.presentation.withdrawal.model.WithdrawalIntent
5+
import com.threegap.bitnagil.presentation.withdrawal.model.WithdrawalReason
86
import com.threegap.bitnagil.presentation.withdrawal.model.WithdrawalSideEffect
97
import com.threegap.bitnagil.presentation.withdrawal.model.WithdrawalState
108
import dagger.hilt.android.lifecycle.HiltViewModel
11-
import kotlinx.coroutines.launch
12-
import org.orbitmvi.orbit.syntax.Syntax
9+
import org.orbitmvi.orbit.Container
10+
import org.orbitmvi.orbit.ContainerHost
11+
import org.orbitmvi.orbit.viewmodel.container
1312
import javax.inject.Inject
1413

1514
@HiltViewModel
1615
class WithdrawalViewModel @Inject constructor(
17-
savedStateHandle: SavedStateHandle,
1816
private val withdrawalUseCase: WithdrawalUseCase,
19-
) : MviViewModel<WithdrawalState, WithdrawalSideEffect, WithdrawalIntent>(
20-
savedStateHandle = savedStateHandle,
21-
initState = WithdrawalState(),
22-
) {
23-
override suspend fun Syntax<WithdrawalState, WithdrawalSideEffect>.reduceState(
24-
intent: WithdrawalIntent,
25-
state: WithdrawalState,
26-
): WithdrawalState? {
27-
val newState = when (intent) {
28-
is WithdrawalIntent.UpdateLoading -> state.copy(isLoading = intent.isLoading)
29-
is WithdrawalIntent.OnTermsToggle -> state.copy(isTermsChecked = !state.isTermsChecked)
30-
is WithdrawalIntent.ShowSuccessDialog -> state.copy(showSuccessDialog = true)
17+
) : ContainerHost<WithdrawalState, WithdrawalSideEffect>, ViewModel() {
3118

32-
is WithdrawalIntent.OnCustomReasonChanged -> {
33-
state.copy(customReasonText = intent.text)
34-
}
19+
override val container: Container<WithdrawalState, WithdrawalSideEffect> = container(initialState = WithdrawalState.INIT)
3520

36-
is WithdrawalIntent.OnReasonSelected -> {
37-
state.copy(
38-
selectedReason = intent.reason,
39-
customReasonText = "",
40-
)
41-
}
42-
43-
is WithdrawalIntent.OnBackClick -> {
44-
sendSideEffect(WithdrawalSideEffect.NavigateToBack)
45-
null
46-
}
21+
fun onTermsToggle() {
22+
intent {
23+
reduce { state.copy(isTermsChecked = !state.isTermsChecked) }
24+
}
25+
}
4726

48-
is WithdrawalIntent.OnSuccessDialogConfirm -> {
49-
sendSideEffect(WithdrawalSideEffect.NavigateToLogin)
50-
null
51-
}
27+
fun updateCustomReason(text: String) {
28+
intent {
29+
reduce { state.copy(customReasonText = text) }
5230
}
31+
}
5332

54-
return newState
33+
fun updateSelectedReason(reason: WithdrawalReason?) {
34+
intent {
35+
reduce { state.copy(selectedReason = reason, customReasonText = "") }
36+
}
5537
}
5638

5739
fun withdrawal() {
58-
if (container.stateFlow.value.isLoading) return
59-
sendIntent(WithdrawalIntent.UpdateLoading(true))
60-
viewModelScope.launch {
61-
withdrawalUseCase().fold(
40+
intent {
41+
if (state.isLoading) return@intent
42+
reduce { state.copy(isLoading = true) }
43+
val reason = state.finalWithdrawalReason
44+
withdrawalUseCase(reason).fold(
6245
onSuccess = {
63-
sendIntent(WithdrawalIntent.UpdateLoading(false))
64-
sendIntent(WithdrawalIntent.ShowSuccessDialog)
46+
reduce { state.copy(isLoading = false, showSuccessDialog = true) }
6547
},
6648
onFailure = {
67-
sendIntent(WithdrawalIntent.UpdateLoading(false))
49+
reduce { state.copy(isLoading = false) }
6850
},
6951
)
7052
}
7153
}
54+
55+
fun navigateToBack() {
56+
intent {
57+
postSideEffect(WithdrawalSideEffect.NavigateToBack)
58+
}
59+
}
60+
61+
fun navigateToLogin() {
62+
intent {
63+
postSideEffect(WithdrawalSideEffect.NavigateToLogin)
64+
}
65+
}
7266
}

presentation/src/main/java/com/threegap/bitnagil/presentation/withdrawal/model/WithdrawalIntent.kt

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)