Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
9.8 kB
0
Indexable
Never
package com.dict.egov.ui.profile.edit.address

import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.dict.egov.domain.kyc.GetBarangayUseCase
import com.dict.egov.domain.kyc.GetMunicipalitiesUseCase
import com.dict.egov.domain.kyc.GetProvincesUseCase
import com.dict.egov.domain.profile.GetProfileUseCase
import com.dict.egov.domain.profile.UpdateProfileAddressUseCase
import com.dict.egov.models.Address
import com.dict.egov.models.Barangay
import com.dict.egov.models.Municipality
import com.dict.egov.models.Profile
import com.dict.egov.models.Province
import com.dict.egov.models.Result
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlin.coroutines.CoroutineContext

data class ProfileEditAddressUiState(
    val isLoading: Boolean = false,
    val errorMessage: String? = null,
    val provinces: List<Province> = emptyList(),
    val municipalities: List<Municipality> = emptyList(),
    val barangays: List<Barangay> = emptyList(),
    val province: Province? = null,
    val municipality: Municipality? = null,
    val barangay: Barangay? = null,
    val profile: Profile? = null,
    val updateSuccess: Boolean = false,
)

class ProfileEditAddressViewModel @ViewModelInject constructor(
    private val getProfileUseCase: GetProfileUseCase,
    private val getProvincesUseCase: GetProvincesUseCase,
    private val getMunicipalitiesUseCase: GetMunicipalitiesUseCase,
    private val getBarangayUseCase: GetBarangayUseCase,
    private val updateProfileAddressUseCase: UpdateProfileAddressUseCase
) : ViewModel(), CoroutineScope {

    private val job = Job()
    override val coroutineContext: CoroutineContext = Dispatchers.IO + job

    private val viewModelState = MutableStateFlow(value = ProfileEditAddressUiState())
    val uiState = viewModelState.stateIn(
        scope = viewModelScope,
        started = SharingStarted.Eagerly,
        initialValue = viewModelState.value
    )

    val onGetProfile: () -> Unit = {
        viewModelScope.launch {
            viewModelState.update { state ->
                state.copy(isLoading = true)
            }
            when (val result = getProfileUseCase()) {
                is Result.Success -> {
                    viewModelState.update { state ->
                        state.copy(profile = result.data)
                    }
                }
                is Result.Error -> {
                    viewModelState.update { state ->
                        state.copy(errorMessage = result.getMessage())
                    }
                }
                is Result.Loading -> {}
            }
            viewModelState.update { state ->
                state.copy(isLoading = false)
            }
        }
    }

    val onGetProvince: (provinceCode: String) -> Unit = {
        viewModelScope.launch {
            viewModelState.update { state ->
                state.copy(isLoading = true)
            }
            when (val result = getProvincesUseCase()) {
                is Result.Success -> {
                    viewModelState.update { state ->
                        state.copy(
                            provinces = result.data,
                            province = result.data.singleOrNull { province ->
                                province.code == it
                            }
                        )
                    }
                    onGetMunicipality(it)
                }
                is Result.Error -> {
                    viewModelState.update { state ->
                        state.copy(
                            isLoading = false,
                            errorMessage = result.getMessage()
                        )
                    }
                }
                is Result.Loading -> {}
            }
        }
    }

    val onGetMunicipality: (provinceCode: String) -> Unit = { provinceCode ->
        viewModelScope.launch {
            viewModelState.update { state ->
                state.copy(isLoading = true)
            }
            when (val result = getMunicipalitiesUseCase(provinceCode = provinceCode)) {
                is Result.Success -> {
                    viewModelState.update { state ->
                        state.copy(
                            municipalities = result.data,
                            municipality = result.data.singleOrNull { municipality ->
                                municipality.code == (state.profile?.municipalityCode ?: "")
                            }
                        )
                    }
                    viewModelState.value.municipality?.let {
                        onGetBarangay(
                            provinceCode,
                            it.code
                        )
                    } ?: run {
                        viewModelState.update { state ->
                            state.copy(
                                isLoading = false,
                                barangays = emptyList(),
                                barangay = null,
                            )
                        }
                    }
                }
                is Result.Error -> {
                    viewModelState.update { state ->
                        state.copy(
                            isLoading = false,
                            errorMessage = result.getMessage()
                        )
                    }
                }
                is Result.Loading -> {}
            }
        }
    }

    val onGetBarangay: (
        provinceCode: String,
        municipalityCode: String
    ) -> Unit = { provinceCode, municipalityCode ->
        viewModelScope.launch {
            viewModelState.update { state ->
                state.copy(isLoading = true)
            }
            when (
                val result = getBarangayUseCase(
                    provinceCode = provinceCode,
                    municipalityCode = municipalityCode
                )
            ) {
                is Result.Success -> {
                    viewModelState.update { state ->
                        state.copy(
                            isLoading = false,
                            barangays = result.data,
                            barangay = result.data.singleOrNull { barangay ->
                                barangay.code == (state.profile?.barangayCode ?: "")
                            }
                        )
                    }
                }
                is Result.Error -> {
                    viewModelState.update { state ->
                        state.copy(
                            isLoading = false,
                            errorMessage = result.getMessage()
                        )
                    }
                }
                is Result.Loading -> {}
            }
        }
    }

    val onGetBarangayByMunicipalityCode: (
        provinceCode: String,
        municipality: Municipality
    ) -> Unit = { provinceCode, municipality ->
        viewModelScope.launch {
            viewModelState.update { state ->
                state.copy(isLoading = true)
            }
            when (
                val result = getBarangayUseCase(
                    provinceCode = provinceCode,
                    municipalityCode = municipality.code
                )
            ) {
                is Result.Success -> {
                    viewModelState.update { state ->
                        state.copy(
                            isLoading = false,
                            barangays = result.data,
                            municipality = municipality
                        )
                    }
                }
                is Result.Error -> {
                    viewModelState.update { state ->
                        state.copy(
                            isLoading = false,
                            errorMessage = result.getMessage()
                        )
                    }
                }
                is Result.Loading -> {}
            }
        }
    }

    val onSetBarangay: (barangay: Barangay) -> Unit = {
        viewModelScope.launch {
            viewModelState.update { state ->
                state.copy(barangay = it)
            }
        }
    }

    val onUpdateAddress: (address: Address) -> Unit = {
        viewModelScope.launch {
            viewModelState.update { state ->
                state.copy(isLoading = true)
            }
            when (val result = updateProfileAddressUseCase(address = it)) {
                is Result.Success -> {
                    viewModelState.update { state ->
                        state.copy(updateSuccess = true)
                    }
                }
                is Result.Error -> {
                    viewModelState.update { state ->
                        state.copy(errorMessage = result.getMessage())
                    }
                }
                is Result.Loading -> {}
            }
            viewModelState.update { state ->
                state.copy(isLoading = false)
            }
        }
    }

    val onResetState: () -> Unit = {
        viewModelState.update { state ->
            state.copy(
                isLoading = false,
                updateSuccess = false,
                errorMessage = null
            )
        }
    }

    override fun onCleared() {
        super.onCleared()
        job.cancel()
    }
}
Leave a Comment