diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsFragment.kt index 358c10da9f3..47d35f64832 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsFragment.kt @@ -1,25 +1,13 @@ package com.mifos.mifosxdroid.offline.syncclientpayloads -import android.content.DialogInterface import android.os.Bundle -import android.util.Log import android.view.LayoutInflater -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem import android.view.View import android.view.ViewGroup -import androidx.lifecycle.ViewModelProvider -import androidx.recyclerview.widget.LinearLayoutManager -import com.mifos.core.objects.client.ClientPayload -import com.mifos.mifosxdroid.R -import com.mifos.mifosxdroid.adapters.SyncPayloadsAdapter -import com.mifos.mifosxdroid.core.MaterialDialog +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.navigation.fragment.findNavController import com.mifos.mifosxdroid.core.MifosBaseFragment -import com.mifos.mifosxdroid.core.util.Toaster.show -import com.mifos.mifosxdroid.databinding.FragmentSyncpayloadBinding -import com.mifos.utils.Constants -import com.mifos.utils.PrefManager.userStatus import dagger.hilt.android.AndroidEntryPoint /** @@ -30,271 +18,19 @@ import dagger.hilt.android.AndroidEntryPoint * Created by Rajan Maurya on 08/07/16. */ @AndroidEntryPoint -class SyncClientPayloadsFragment : MifosBaseFragment(), DialogInterface.OnClickListener { - val LOG_TAG = javaClass.simpleName - - private lateinit var binding: FragmentSyncpayloadBinding - - private lateinit var viewModel: SyncClientPayloadsViewModel - - var clientPayloads: MutableList? = null - var mSyncPayloadsAdapter: SyncPayloadsAdapter? = null - var mClientSyncIndex = 0 - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - clientPayloads = ArrayList() - setHasOptionsMenu(true) - } +class SyncClientPayloadsFragment : MifosBaseFragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - binding = FragmentSyncpayloadBinding.inflate(inflater, container, false) - viewModel = ViewModelProvider(this)[SyncClientPayloadsViewModel::class.java] - val mLayoutManager = LinearLayoutManager(activity) - mLayoutManager.orientation = LinearLayoutManager.VERTICAL - binding.rvSyncPayload.layoutManager = mLayoutManager - binding.rvSyncPayload.setHasFixedSize(true) - viewModel.loadDatabaseClientPayload() - /** - * Loading All Client Payloads from Database - */ - binding.swipeContainer.setColorSchemeColors( - *requireActivity().resources.getIntArray(R.array.swipeRefreshColors) - ) - binding.swipeContainer.setOnRefreshListener { - viewModel.loadDatabaseClientPayload() - if (binding.swipeContainer.isRefreshing) binding.swipeContainer.isRefreshing = false - } - - viewModel.syncClientPayloadsUiState.observe(viewLifecycleOwner) { - when (it) { - is SyncClientPayloadsUiState.ShowClientPayloadUpdated -> { - showProgressbar(false) - showClientPayloadUpdated(it.clientPayload) - } - - is SyncClientPayloadsUiState.ShowError -> { - showProgressbar(false) - showError(it.message) - } - - is SyncClientPayloadsUiState.ShowPayloadDeletedAndUpdatePayloads -> { - showProgressbar(false) - showPayloadDeletedAndUpdatePayloads(it.clientPayloads) - } - - is SyncClientPayloadsUiState.ShowPayloads -> { - showProgressbar(false) - showPayloads(it.clientPayloads) - } - - is SyncClientPayloadsUiState.ShowProgressbar -> showProgressbar(true) - - is SyncClientPayloadsUiState.ShowSyncResponse -> { - showProgressbar(false) - showSyncResponse() - } - } - } - - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - binding.noPayloadIcon.setOnClickListener { - reloadOnError() - } - } - - /** - * Show when Database response is null or failed to fetch the client payload - * Onclick Send Fresh Request for Client Payload. - */ - - private fun reloadOnError() { - binding.llError.visibility = View.GONE - viewModel.loadDatabaseClientPayload() - } - - /** - * This method is showing the client payload in the recyclerView. - * If Database Table have no entry then showing make recyclerView visibility gone and - * visible to the noPayloadIcon and noPayloadText to alert the user there is nothing - * to show. - * - * @param clientPayload - */ - private fun showPayloads(clientPayload: List) { - clientPayloads = clientPayload as MutableList - if (clientPayload.isEmpty()) { - binding.llError.visibility = View.VISIBLE - binding.noPayloadText.text = requireActivity() - .resources.getString(R.string.no_client_payload_to_sync) - binding.noPayloadIcon.setImageResource(R.drawable.ic_assignment_turned_in_black_24dp) - } else { - mSyncPayloadsAdapter = SyncPayloadsAdapter(requireActivity(), clientPayload) - binding.rvSyncPayload.adapter = mSyncPayloadsAdapter - } - } - - /** - * Showing Error when failed to fetch client payload from Database - * - * @param s Error String - */ - private fun showError(stringId: String) { - binding.llError.visibility = View.VISIBLE - val message = - stringId + requireActivity().resources.getString(R.string.click_to_refresh) - binding.noPayloadText.text = message - show(binding.root, stringId) - } - - /** - * Called Whenever any client payload is synced to server. - * then first delete that client from database and sync again from Database - * and update the recyclerView - */ - private fun showSyncResponse() { - clientPayloads?.get(mClientSyncIndex)?.id?.let { - clientPayloads?.get(mClientSyncIndex)?.clientCreationTime?.let { it1 -> - viewModel.deleteAndUpdateClientPayload( - it, - it1 - ) - } - } - } - - /** - * Called when client payload synced is failed then there can be some problem with the - * client payload data example externalId or phone number already exist. - * If client synced failed the there is no need to delete from the Database and increase - * the mClientSyncIndex by one and sync the next client payload - */ - private fun showClientSyncFailed(errorMessage: String) { - val clientPayload = clientPayloads!![mClientSyncIndex] - clientPayload.errorMessage = errorMessage - viewModel.updateClientPayload(clientPayload) - } - - /** - * This Method will called whenever user trying to sync the client payload in - * offline mode. - */ - private fun showOfflineModeDialog() { - MaterialDialog.Builder().init(activity) - .setTitle(R.string.offline_mode) - .setMessage(R.string.dialog_message_offline_sync_alert) - .setPositiveButton(R.string.dialog_action_go_online, this) - .setNegativeButton(R.string.dialog_action_cancel, this) - .createMaterialDialog() - .show() - } - - override fun onClick(dialog: DialogInterface, which: Int) { - when (which) { - DialogInterface.BUTTON_NEGATIVE -> {} - DialogInterface.BUTTON_POSITIVE -> { - userStatus = Constants.USER_ONLINE - if (clientPayloads!!.isNotEmpty()) { - mClientSyncIndex = 0 - syncClientPayload() - } else { - show( - binding.root, - requireActivity().resources.getString(R.string.nothing_to_sync) - ) - } - } - - else -> {} - } - } - - /** - * This method will update client Payload in List after adding Error message in - * database - * - * @param clientPayload - */ - private fun showClientPayloadUpdated(clientPayload: ClientPayload) { - clientPayloads?.set(mClientSyncIndex, clientPayload) - mSyncPayloadsAdapter!!.notifyDataSetChanged() - mClientSyncIndex += 1 - if (clientPayloads!!.size != mClientSyncIndex) { - syncClientPayload() - } - } - - /** - * This is called whenever a client payload is synced and synced client payload is - * deleted from the Database and update UI - * - * @param clients - */ - private fun showPayloadDeletedAndUpdatePayloads(clients: List) { - mClientSyncIndex = 0 - clientPayloads?.clear() - clientPayloads = clients as MutableList - mSyncPayloadsAdapter!!.setClientPayload(clientPayloads!!) - if (clientPayloads!!.isNotEmpty()) { - syncClientPayload() - } else { - binding.llError.visibility = View.VISIBLE - binding.noPayloadText.text = requireActivity() - .resources.getString(R.string.all_clients_synced) - binding.noPayloadIcon.setImageResource(R.drawable.ic_assignment_turned_in_black_24dp) - } - } - - private fun showProgressbar(b: Boolean) { - if (b) { - showMifosProgressBar() - } else { - hideMifosProgressBar() - } - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.menu_sync, menu) - super.onCreateOptionsMenu(menu, inflater) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == R.id.action_sync) { - when (userStatus) { - false -> if (clientPayloads!!.isNotEmpty()) { - mClientSyncIndex = 0 - syncClientPayload() - } else { - show( - binding.root, - requireActivity().resources.getString(R.string.nothing_to_sync) - ) - } - - true -> showOfflineModeDialog() - } - } - return super.onOptionsItemSelected(item) - } - - private fun syncClientPayload() { - for (i in clientPayloads!!.indices) { - if (clientPayloads!![i].errorMessage == null) { - viewModel.syncClientPayload(clientPayloads!![i]) - mClientSyncIndex = i - break - } else { - Log.d( - LOG_TAG, - requireActivity().resources.getString(R.string.error_fix_before_sync) + - clientPayloads!![i].errorMessage + return ComposeView(requireContext()).apply { + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + setContent { + SyncClientPayloadsScreenRoute( + onBackPressed = { + findNavController().popBackStack() + } ) } } diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsScreen.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsScreen.kt new file mode 100644 index 00000000000..837154971ae --- /dev/null +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsScreen.kt @@ -0,0 +1,310 @@ +package com.mifos.mifosxdroid.offline.syncclientpayloads + +import android.content.Context +import android.widget.Toast +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Error +import androidx.compose.material.pullrefresh.PullRefreshIndicator +import androidx.compose.material.pullrefresh.pullRefresh +import androidx.compose.material.pullrefresh.rememberPullRefreshState +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.mifos.core.designsystem.component.MifosCircularProgress +import com.mifos.core.designsystem.component.MifosScaffold +import com.mifos.core.designsystem.icon.MifosIcons +import com.mifos.core.objects.client.ClientPayload +import com.mifos.mifosxdroid.R +import com.mifos.utils.Network +import com.mifos.utils.PrefManager.userStatus + +@Composable +fun SyncClientPayloadsScreenRoute( + viewModel: SyncClientPayloadsViewModel = hiltViewModel(), + onBackPressed: () -> Unit, +) { + val uiState by viewModel.syncClientPayloadsUiState.collectAsStateWithLifecycle() + val refreshState by viewModel.isRefreshing.collectAsStateWithLifecycle() + + LaunchedEffect(key1 = Unit) { + viewModel.loadDatabaseClientPayload() + } + + SyncClientPayloadsScreen( + uiState = uiState, + onBackPressed = onBackPressed, + refreshState = refreshState, + onRefresh = { + viewModel.refreshClientPayloads() + }, + syncClientPayloads = { + viewModel.syncClientPayload() + } + ) +} + +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun SyncClientPayloadsScreen( + uiState: SyncClientPayloadsUiState, + onBackPressed: () -> Unit, + refreshState: Boolean, + onRefresh: () -> Unit, + syncClientPayloads: () -> Unit, +) { + val snackbarHostState = remember { SnackbarHostState() } + val context = LocalContext.current + val pullRefreshState = rememberPullRefreshState(refreshing = refreshState, onRefresh = onRefresh) + + MifosScaffold( + icon = MifosIcons.arrowBack, + title = stringResource(id = R.string.sync_clients_payloads), + onBackPressed = onBackPressed, + actions = { + IconButton(onClick = { + when (userStatus) { + false -> checkNetworkConnectionAndSync(context, syncClientPayloads) + true -> TODO("Implement OfflineModeDialog()") + } + }) { + Icon( + MifosIcons.sync, + contentDescription = stringResource(id = R.string.sync_clients) + ) + } + }, + snackbarHostState = snackbarHostState + ) { paddingValues -> + Box( + modifier = Modifier + .padding(paddingValues) + .pullRefresh(pullRefreshState) + ) { + when (uiState) { + is SyncClientPayloadsUiState.ShowProgressbar -> { + MifosCircularProgress() + } + is SyncClientPayloadsUiState.ShowError -> { + ErrorStateScreen(uiState.message, onRefresh) + } + is SyncClientPayloadsUiState.ShowPayloads -> { + ClientPayloadsList(uiState.clientPayloads) + } + } + PullRefreshIndicator( + refreshing = refreshState, + state = pullRefreshState, + modifier = Modifier.align(Alignment.TopCenter) + ) + } + } +} + +@Composable +fun ClientPayloadsList(clientPayloads: List) { + LazyColumn { + items(clientPayloads) { payload -> + ClientPayloadItem(payload) + } + } +} + +@Composable +fun ClientPayloadItem(payload: ClientPayload) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) + ) { + Column(modifier = Modifier.padding(16.dp)) { + val payloadStatus: String = if(payload.active == true){ + "true" + }else{ + "false" + } + + val gender = when (payload.genderId.toString()) { + 24.toString() -> { + "Female" + } + 91.toString() -> { + "Homosexual" + } + else -> { + "Male" + } + } + + PayloadField(stringResource(id = R.string.first_name), payload.firstname ?: "") + PayloadField(stringResource(id = R.string.middle_name), payload.middlename ?: "") + PayloadField(stringResource(id = R.string.last_name), payload.lastname ?: "") + PayloadField(stringResource(id = R.string.mobile_no), payload.mobileNo ?: "") + PayloadField(stringResource(id = R.string.external_id), payload.externalId ?: "") + PayloadField(stringResource(id = R.string.gender), gender) + PayloadField(stringResource(id = R.string.dob), payload.dateOfBirth ?: "") + PayloadField(stringResource(id = R.string.office_id), payload.officeId?.toString() ?: "") + PayloadField(stringResource(id = R.string.activation_date), payload.activationDate ?: "") + PayloadField(stringResource(id = R.string.active), payloadStatus) + + if (payload.errorMessage != null) { + Text( + text = payload.errorMessage!!, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.error, + modifier = Modifier.padding(top = 8.dp) + ) + } + } + } +} + +@Composable +fun PayloadField(label: String, value: String) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp) + ) { + Text( + text = label, + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Bold, + modifier = Modifier.weight(1f) + ) + Text( + text = value, + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.weight(1f) + ) + } +} + +@Composable +fun ErrorStateScreen(message: String, onRefresh: () -> Unit) { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Icon( + imageVector = Icons.Default.Error, + contentDescription = null, + modifier = Modifier.size(48.dp) + ) + Text(text = message, modifier = Modifier.padding(vertical = 16.dp)) + Button(onClick = onRefresh) { + Text(stringResource(id = R.string.click_to_refresh)) + } + } +} + +fun checkNetworkConnectionAndSync( + context: Context, + syncClientPayloads: () -> Unit +) { + if (Network.isOnline(context)) { + syncClientPayloads() + } else { + Toast.makeText( + context, + context.getString(R.string.error_not_connected_internet), + Toast.LENGTH_SHORT + ).show() + } +} + +class SyncClientPayloadsUiStateProvider : PreviewParameterProvider { + override val values = sequenceOf( + SyncClientPayloadsUiState.ShowProgressbar, + SyncClientPayloadsUiState.ShowError("Failed to load client payloads"), + SyncClientPayloadsUiState.ShowPayloads(sampleClientPayloads) + ) +} + +@Preview(showBackground = true) +@Composable +private fun SyncClientPayloadsScreenPreview( + @PreviewParameter(SyncClientPayloadsUiStateProvider::class) uiState: SyncClientPayloadsUiState +) { + SyncClientPayloadsScreen( + uiState = uiState, + onBackPressed = {}, + refreshState = false, + onRefresh = {}, + syncClientPayloads = {} + ) +} + +// Sample data for previews +val sampleClientPayloads = List(5) { index -> + ClientPayload().apply { + firstname = "John$index" + middlename = "Sam$index" + lastname = "Doe$index" + mobileNo = "123456789$index" + externalId = "EXT-$index" + officeId = index + active = index % 2 == 0 + activationDate = "2023-07-${15 + index}" + genderId = if (index % 3 == 0) 24 else 22 + dateOfBirth = "1990-01-0$index" + errorMessage = if (index % 2 == 0) null else "Error in payload" + } +} + +@Preview(showBackground = true) +@Composable +fun ClientPayloadItemPreview() { + val sampleClientPayload = ClientPayload().apply { + firstname = "John" + middlename = "Michael" + lastname = "Doe" + mobileNo = "1234567890" + externalId = "EXT-001" + genderId = 22 + dateOfBirth = "1990-01-01" + officeId = 12 + activationDate = "2023-07-15" + active = true + errorMessage = null + } + + ClientPayloadItem(payload = sampleClientPayload) +} + +class PayloadFieldPreviewProvider : PreviewParameterProvider> { + override val values = sequenceOf( + "First Name" to "John", + "Last Name" to "Doe", + "Mobile No" to "1234567890", + "External ID" to "EXT-001", + "Gender" to "Male", + "Date of Birth" to "1990-01-01", + "Office ID" to "12345", + "Activation Date" to "2023-07-15", + "Active" to "true" + ) +} + +@Preview(showBackground = true) +@Composable +fun PayloadFieldPreview( + @PreviewParameter(PayloadFieldPreviewProvider::class) labelValuePair: Pair +) { + PayloadField(label = labelValuePair.first, value = labelValuePair.second) +} diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsUiState.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsUiState.kt index 1b88f718339..6eeae0a9f82 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsUiState.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsUiState.kt @@ -13,11 +13,4 @@ sealed class SyncClientPayloadsUiState { data class ShowPayloads(val clientPayloads: List) : SyncClientPayloadsUiState() - data object ShowSyncResponse : SyncClientPayloadsUiState() - - data class ShowPayloadDeletedAndUpdatePayloads(val clientPayloads: List) : - SyncClientPayloadsUiState() - - data class ShowClientPayloadUpdated(val clientPayload: ClientPayload) : - SyncClientPayloadsUiState() } \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsViewModel.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsViewModel.kt index 066525a302f..c2ab372f036 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsViewModel.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/offline/syncclientpayloads/SyncClientPayloadsViewModel.kt @@ -1,11 +1,14 @@ package com.mifos.mifosxdroid.offline.syncclientpayloads -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData +import android.util.Log import androidx.lifecycle.ViewModel import com.mifos.core.objects.client.Client import com.mifos.core.objects.client.ClientPayload +import com.mifos.mifosxdroid.dialogfragments.syncclientsdialog.SyncClientsDialogFragment.Companion.LOG_TAG import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import rx.Observer import rx.Subscriber import rx.android.schedulers.AndroidSchedulers @@ -16,14 +19,28 @@ import javax.inject.Inject * Created by Aditya Gupta on 16/08/23. */ @HiltViewModel -class SyncClientPayloadsViewModel @Inject constructor(private val repository: SyncClientPayloadsRepository) : - ViewModel() { +class SyncClientPayloadsViewModel @Inject constructor( + private val repository: SyncClientPayloadsRepository +) : ViewModel() { - private val _syncClientPayloadsRepository = MutableLiveData() + private val _syncClientPayloadsRepository = + MutableStateFlow(SyncClientPayloadsUiState.ShowProgressbar) - val syncClientPayloadsUiState: LiveData + val syncClientPayloadsUiState: StateFlow get() = _syncClientPayloadsRepository + private val _isRefreshing = MutableStateFlow(false) + val isRefreshing: StateFlow = _isRefreshing.asStateFlow() + + private var mClientPayloads: MutableList = mutableListOf() + private var mClientSyncIndex = 0 + + fun refreshClientPayloads() { + _isRefreshing.value = true + loadDatabaseClientPayload() + _isRefreshing.value = false + } + fun loadDatabaseClientPayload() { _syncClientPayloadsRepository.value = SyncClientPayloadsUiState.ShowProgressbar repository.allDatabaseClientPayload() @@ -37,8 +54,9 @@ class SyncClientPayloadsViewModel @Inject constructor(private val repository: Sy } override fun onNext(clientPayloads: List) { + mClientPayloads = clientPayloads.toMutableList() _syncClientPayloadsRepository.value = - SyncClientPayloadsUiState.ShowPayloads(clientPayloads) + SyncClientPayloadsUiState.ShowPayloads(mClientPayloads) } }) @@ -57,7 +75,14 @@ class SyncClientPayloadsViewModel @Inject constructor(private val repository: Sy } override fun onNext(client: Client) { - _syncClientPayloadsRepository.value = SyncClientPayloadsUiState.ShowSyncResponse + mClientPayloads[mClientSyncIndex].id?.let { + mClientPayloads[mClientSyncIndex].clientCreationTime?.let { it1 -> + deleteAndUpdateClientPayload( + it, + it1 + ) + } + } } }) @@ -76,8 +101,13 @@ class SyncClientPayloadsViewModel @Inject constructor(private val repository: Sy } override fun onNext(clientPayloads: List) { + mClientSyncIndex = 0 + if (clientPayloads.isNotEmpty()) { + syncClientPayload() + } + mClientPayloads = clientPayloads.toMutableList() _syncClientPayloadsRepository.value = - SyncClientPayloadsUiState.ShowPayloadDeletedAndUpdatePayloads(clientPayloads) + SyncClientPayloadsUiState.ShowPayloads(mClientPayloads) } }) @@ -96,10 +126,30 @@ class SyncClientPayloadsViewModel @Inject constructor(private val repository: Sy } override fun onNext(clientPayload: ClientPayload) { - _syncClientPayloadsRepository.value = - SyncClientPayloadsUiState.ShowClientPayloadUpdated(clientPayload) + mClientPayloads[mClientSyncIndex] = clientPayload + mClientSyncIndex += 1 + if (mClientPayloads.size != mClientSyncIndex) { + syncClientPayload() + } } }) } + + fun syncClientPayload() { + for (i in mClientPayloads.indices) { + if (mClientPayloads[i].errorMessage == null) { + syncClientPayload(mClientPayloads[i]) + mClientSyncIndex = i + break + } else { + mClientPayloads[i].errorMessage?.let { + Log.d( + LOG_TAG, + it + ) + } + } + } + } } \ No newline at end of file diff --git a/mifosng-android/src/main/res/values/strings.xml b/mifosng-android/src/main/res/values/strings.xml index c966b98d994..283ea00bdb5 100755 --- a/mifosng-android/src/main/res/values/strings.xml +++ b/mifosng-android/src/main/res/values/strings.xml @@ -565,6 +565,7 @@ Submit Date Server Sync Error Clients + Sync Client Payloads Groups Centers LoanRepayments