diff --git a/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosEditTextField.kt b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosEditTextField.kt index 4abb2a5a4d1..edf4815dbe9 100644 --- a/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosEditTextField.kt +++ b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosEditTextField.kt @@ -242,7 +242,8 @@ fun MifosOutlinedTextField( singleLine = singleLine, colors = OutlinedTextFieldDefaults.colors( focusedBorderColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary, - focusedLabelColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary + focusedLabelColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary, + cursorColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary, ), textStyle = LocalDensity.current.run { TextStyle(fontSize = 18.sp) diff --git a/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosScaffold.kt b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosScaffold.kt index 852892aa853..49090830388 100644 --- a/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosScaffold.kt +++ b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosScaffold.kt @@ -35,6 +35,7 @@ fun MifosScaffold( isAppBarPresent: Boolean = true, icon: ImageVector? = null, title: String? = null, + fontsizeInSp : Int = 24, onBackPressed: () -> Unit = {}, actions: @Composable () -> Unit = {}, snackbarHostState: SnackbarHostState?, @@ -67,7 +68,7 @@ fun MifosScaffold( Text( text = it, style = TextStyle( - fontSize = 24.sp, + fontSize = fontsizeInSp.sp, fontWeight = FontWeight.Medium, fontStyle = FontStyle.Normal ), diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/loanrepayment/LoanRepaymentScreen.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/loanrepayment/LoanRepaymentScreen.kt index 9c99c5fb218..9b8091bbc93 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/loanrepayment/LoanRepaymentScreen.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/loanrepayment/LoanRepaymentScreen.kt @@ -16,7 +16,7 @@ import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.AlertDialog +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.DatePicker diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/loanrepaymentschedule/LoanRepaymentScheduleScreen.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/loanrepaymentschedule/LoanRepaymentScheduleScreen.kt index c38207c0a15..1e7ef4c6742 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/loanrepaymentschedule/LoanRepaymentScheduleScreen.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/loanrepaymentschedule/LoanRepaymentScheduleScreen.kt @@ -351,7 +351,4 @@ fun PreviewLoanRepaymentSchedule( navigateBack = { }, onRetry = {} ) -} - - - +} \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccountsummary/SavingsAccountSummaryScreen.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccountsummary/SavingsAccountSummaryScreen.kt index bd3ba999f35..31a2010952d 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccountsummary/SavingsAccountSummaryScreen.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccountsummary/SavingsAccountSummaryScreen.kt @@ -1,7 +1,6 @@ package com.mifos.mifosxdroid.online.savingaccountsummary import android.content.Context -import android.util.Log import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.isSystemInDarkTheme @@ -25,12 +24,10 @@ import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.DropdownMenu -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.MultiChoiceSegmentedButtonRow import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -68,12 +65,8 @@ import com.mifos.core.objects.accounts.savings.Status import com.mifos.core.objects.accounts.savings.Summary import com.mifos.core.objects.accounts.savings.Transaction import com.mifos.core.objects.accounts.savings.TransactionType -import com.mifos.core.objects.response.SaveResponse import com.mifos.core.ui.components.MifosEmptyUi import com.mifos.mifosxdroid.R -import com.mifos.mifosxdroid.online.createnewgroup.CreateNewGroupScreen -import com.mifos.mifosxdroid.online.createnewgroup.CreateNewGroupScreenPreviewProvider -import com.mifos.mifosxdroid.online.createnewgroup.CreateNewGroupUiState import com.mifos.utils.DateHelper /** @@ -145,6 +138,7 @@ fun SavingsAccountSummaryScreen( onBackPressed = navigateBack, title = stringResource(id = R.string.savingsAccountSummary), icon = MifosIcons.arrowBack, + fontsizeInSp = 22, actions = { IconButton(onClick = { showDropdown = !showDropdown }) { Icon(imageVector = MifosIcons.moreVert, contentDescription = "") diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionFragment.kt index a21e5d739f1..45b1f89754d 100755 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionFragment.kt @@ -13,8 +13,12 @@ import android.widget.AdapterView import android.widget.AdapterView.OnItemSelectedListener import android.widget.ArrayAdapter import android.widget.Toast +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.fragment.app.DialogFragment +import androidx.fragment.app.viewModels import androidx.lifecycle.ViewModelProvider +import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.google.gson.Gson import com.jakewharton.fliptables.FlipTable @@ -26,9 +30,11 @@ import com.mifos.core.objects.templates.savings.SavingsAccountTransactionTemplat import com.mifos.exceptions.RequiredFieldException import com.mifos.mifosxdroid.R import com.mifos.mifosxdroid.core.MaterialDialog +import com.mifos.mifosxdroid.core.MifosBaseFragment import com.mifos.mifosxdroid.core.ProgressableFragment import com.mifos.mifosxdroid.core.util.Toaster import com.mifos.mifosxdroid.databinding.FragmentSavingsAccountTransactionBinding +import com.mifos.mifosxdroid.online.savingsaccount.SavingsAccountScreen import com.mifos.mifosxdroid.uihelpers.MFDatePicker import com.mifos.mifosxdroid.uihelpers.MFDatePicker.OnDatePickListener import com.mifos.utils.FragmentConstants @@ -38,34 +44,18 @@ import com.mifos.utils.Utils import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint -class SavingsAccountTransactionFragment : ProgressableFragment(), OnDatePickListener { +class SavingsAccountTransactionFragment : MifosBaseFragment() { - - private lateinit var binding: FragmentSavingsAccountTransactionBinding private val arg: SavingsAccountTransactionFragmentArgs by navArgs() - val LOG_TAG = javaClass.simpleName - - private lateinit var viewModel: SavingsAccountTransactionViewModel - - private var savingsAccountNumber: String? = null - private var savingsAccountId: Int? = null - private var savingsAccountType: DepositType? = null - private var transactionType //Defines if the Transaction is a Deposit to an Account - : String? = null - - // or a Withdrawal from an Account - private var clientName: String? = null + val viewModel: SavingsAccountTransactionViewModel by viewModels() - // Values to be fetched from Savings Account Template - private var paymentTypeOptionId = 0 - private var mfDatePicker: DialogFragment? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - savingsAccountId = arg.savingsAccountWithAssociations.accountNo - savingsAccountId = arg.savingsAccountWithAssociations.id - transactionType = arg.transactionType - clientName = arg.savingsAccountWithAssociations.clientName - savingsAccountType = arg.accountType + viewModel.accountId = arg.savingsAccountWithAssociations.id + viewModel.transactionType = arg.transactionType + viewModel.clientName = arg.savingsAccountWithAssociations.clientName + viewModel.savingsAccountNumber = arg.savingsAccountWithAssociations.accountNo + viewModel.savingsAccountType = arg.accountType } override fun onCreateView( @@ -73,266 +63,23 @@ class SavingsAccountTransactionFragment : ProgressableFragment(), OnDatePickList container: ViewGroup?, savedInstanceState: Bundle? ): View { - binding = FragmentSavingsAccountTransactionBinding.inflate(inflater, container, false) - if (transactionType == Constants.SAVINGS_ACCOUNT_TRANSACTION_DEPOSIT) { - setToolbarTitle( - resources.getString(R.string.savingsAccount) + resources - .getString(R.string.space) + resources.getString(R.string.deposit) - ) - } else { - setToolbarTitle( - resources.getString(R.string.savingsAccount) + resources - .getString(R.string.space) + resources.getString(R.string.withdrawal) - ) - } - viewModel = ViewModelProvider(this)[SavingsAccountTransactionViewModel::class.java] - - //This Method Checking SavingAccountTransaction made before in Offline mode or not. - //If yes then User have to sync that first then he will be able to make transaction. - //If not then User able to make SavingAccountTransaction in Online or Offline. - checkSavingAccountTransactionStatusInDatabase() - - viewModel.savingsAccountTransactionUiState.observe(viewLifecycleOwner) { - when (it) { - is SavingsAccountTransactionUiState.ShowError -> { - showProgressbar(false) - showError(it.message) - } - - is SavingsAccountTransactionUiState.ShowProgressbar -> showProgressbar(true) - - is SavingsAccountTransactionUiState.ShowSavingAccountTemplate -> { - showProgressbar(false) - showSavingAccountTemplate(it.savingsAccountTransactionTemplate) - } - - is SavingsAccountTransactionUiState.ShowSavingAccountTransactionExistInDatabase -> { - showProgressbar(false) - showSavingAccountTransactionDoesNotExistInDatabase() + return ComposeView(requireContext()).apply { + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + setContent { + SavingsAccountTransactionScreen { + findNavController().popBackStack() } - - is SavingsAccountTransactionUiState.ShowTransactionSuccessfullyDone -> { - showProgressbar(false) - showTransactionSuccessfullyDone(it.savingsAccountTransactionResponse) - } - } - } - - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - binding.btReviewTransaction.setOnClickListener { - onReviewTransactionButtonClicked() - } - - binding.btCancelTransaction.setOnClickListener { - onCancelTransactionButtonClicked() - } - - } - - private fun checkSavingAccountTransactionStatusInDatabase() { - // Checking SavingAccountTransaction Already made in Offline mode or Not. - savingsAccountId?.let { - viewModel - .checkInDatabaseSavingAccountTransaction(it) - } - } - - private fun showSavingAccountTransactionExistInDatabase() { - //Visibility of ParentLayout GONE, If SavingAccountTransaction Already made in Offline Mode - binding.viewFlipper.visibility = View.GONE - MaterialDialog.Builder().init(activity) - .setTitle(R.string.sync_previous_transaction) - .setMessage(R.string.dialog_message_sync_savingaccounttransaction) - .setPositiveButton( - R.string.dialog_action_ok - ) { dialog, which -> requireActivity().supportFragmentManager.popBackStackImmediate() } - .setCancelable(false) - .createMaterialDialog() - .show() - } - - private fun showSavingAccountTransactionDoesNotExistInDatabase() { - // This Method Inflating UI and Initializing the Loading SavingAccountTransaction - // Template for transaction. - inflateUI() - } - - private fun inflateUI() { - binding.tvClientName.text = clientName - binding.tvSavingsAccountNumber.text = savingsAccountNumber - //TODO Implement QuickContactBadge here - inflateRepaymentDate() - inflateSavingsAccountTemplate() - } - - private fun inflateSavingsAccountTemplate() { - savingsAccountId?.let { - viewModel.loadSavingAccountTemplate( - savingsAccountType?.endpoint, it, transactionType - ) - } - } - - private fun onReviewTransactionButtonClicked() { - // Notify user if Amount field is blank and Review - // Transaction button is pressed. - if (binding.etTransactionAmount.editableText.toString().isEmpty()) { - RequiredFieldException( - getString(R.string.amount), - getString(R.string.message_field_required) - ).notifyUserWithToast(activity) - return - } - // Notify the user if zero is entered in the Amount - // field or only "." (Decimal point) is entered. - try { - if (binding.etTransactionAmount.editableText.toString().toFloat() == 0f) { - RequiredFieldException( - getString(R.string.amount), - getString(R.string.message_cannot_be_zero) - ).notifyUserWithToast(activity) - return - } - } catch (e: NumberFormatException) { - Toast.makeText(activity, R.string.error_invalid_amount, Toast.LENGTH_SHORT).show() - return - } - val headers = arrayOf( - resources.getString(R.string.field), - resources.getString(R.string.value) - ) - val data = arrayOf( - arrayOf( - resources.getString(R.string.transaction_date), - binding.tvTransactionDate.text.toString() - ), arrayOf( - resources.getString(R.string.payment_type), - binding.spPaymentType.selectedItem.toString() - ), arrayOf( - resources.getString(R.string.amount), - binding.etTransactionAmount.editableText.toString() - ) - ) - Log.d(LOG_TAG, FlipTable.of(headers, data)) - val formReviewStringBuilder = StringBuilder() - for (i in 0..2) { - for (j in 0..1) { - formReviewStringBuilder.append(data[i][j]) - if (j == 0) formReviewStringBuilder.append(" : ") - } - formReviewStringBuilder.append('\n') - } - MaterialDialog.Builder().init(activity) - .setTitle(resources.getString(R.string.review_transaction_details)) - .setMessage(formReviewStringBuilder.toString()) - .setPositiveButton( - resources.getString(R.string.process_transaction) - ) { dialogInterface, i -> processTransaction() } - .setNegativeButton( - resources.getString(R.string.dialog_action_cancel) - ) { dialogInterface, i -> dialogInterface.dismiss() } - .createMaterialDialog() - .show() - } - - private fun processTransaction() { - val dateString = binding.tvTransactionDate.text.toString().replace("-", " ") - val savingsAccountTransactionRequest = SavingsAccountTransactionRequest() - savingsAccountTransactionRequest.locale = "en" - savingsAccountTransactionRequest.dateFormat = "dd MM yyyy" - savingsAccountTransactionRequest.transactionDate = dateString - savingsAccountTransactionRequest.transactionAmount = binding.etTransactionAmount - .editableText.toString() - savingsAccountTransactionRequest.paymentTypeId = paymentTypeOptionId.toString() - val builtTransactionRequestAsJson = Gson().toJson(savingsAccountTransactionRequest) - Log.i(resources.getString(R.string.transaction_body), builtTransactionRequestAsJson) - if (!Network.isOnline(requireActivity())) PrefManager.userStatus = Constants.USER_OFFLINE - savingsAccountId?.let { - viewModel.processTransaction( - savingsAccountType?.endpoint, - it, transactionType, savingsAccountTransactionRequest - ) - } - } - - private fun onCancelTransactionButtonClicked() { - requireActivity().supportFragmentManager.popBackStackImmediate() - } - - private fun inflateRepaymentDate() { - mfDatePicker = MFDatePicker.newInsance(this) - binding.tvTransactionDate.text = MFDatePicker.datePickedAsString - // TODO Add Validation to make sure : - // 1. Date Is in Correct Format - // 2. Date Entered is not greater than Date Today i.e Date is not in future - binding.tvTransactionDate.setOnClickListener { - (mfDatePicker as MFDatePicker?)?.show( - requireActivity().supportFragmentManager, - FragmentConstants.DFRAG_DATE_PICKER - ) - } - } - - override fun onDatePicked(date: String?) { - binding.tvTransactionDate.text = date - } - - private fun showSavingAccountTemplate(savingsAccountTransactionTemplate: SavingsAccountTransactionTemplate?) { - if (savingsAccountTransactionTemplate != null) { - val listOfPaymentTypes = Utils.getPaymentTypeOptions( - savingsAccountTransactionTemplate.paymentTypeOptions - ) - val paymentTypeAdapter = ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_item, listOfPaymentTypes - ) - paymentTypeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spPaymentType.adapter = paymentTypeAdapter - binding.spPaymentType.onItemSelectedListener = object : OnItemSelectedListener { - override fun onItemSelected( - parent: AdapterView<*>?, - view: View, - position: Int, - id: Long - ) { - paymentTypeOptionId = savingsAccountTransactionTemplate - .paymentTypeOptions[position].id - } - - override fun onNothingSelected(parent: AdapterView<*>?) {} - } - } - } - - private fun showTransactionSuccessfullyDone(savingsAccountTransactionResponse: SavingsAccountTransactionResponse?) { - if (savingsAccountTransactionResponse?.resourceId == null) { - Toaster.show(binding.root, resources.getString(R.string.transaction_saved_in_db)) - } else { - if (transactionType == Constants.SAVINGS_ACCOUNT_TRANSACTION_DEPOSIT) { - Toaster.show( - binding.root, "Deposit Successful, Transaction ID = " + - savingsAccountTransactionResponse.resourceId - ) - } else if (transactionType == Constants.SAVINGS_ACCOUNT_TRANSACTION_WITHDRAWAL) { - Toaster.show( - binding.root, "Withdrawal Successful, Transaction ID = " - + savingsAccountTransactionResponse.resourceId - ) } } - requireActivity().supportFragmentManager.popBackStackImmediate() } - private fun showError(errorMessage: String) { - Toaster.show(binding.root, errorMessage) + override fun onResume() { + super.onResume() + toolbar?.visibility = View.GONE } - private fun showProgressbar(b: Boolean) { - showProgress(b) + override fun onStop() { + super.onStop() + toolbar?.visibility = View.VISIBLE } } \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionFragmentOld.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionFragmentOld.kt new file mode 100644 index 00000000000..f8d79c7f4ee --- /dev/null +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionFragmentOld.kt @@ -0,0 +1,339 @@ +///* +// * This project is licensed under the open source MPL V2. +// * See https://github.com/openMF/android-client/blob/master/LICENSE.md +// */ +//package com.mifos.mifosxdroid.online.savingaccounttransaction +// +//import android.os.Bundle +//import android.util.Log +//import android.view.LayoutInflater +//import android.view.View +//import android.view.ViewGroup +//import android.widget.AdapterView +//import android.widget.AdapterView.OnItemSelectedListener +//import android.widget.ArrayAdapter +//import android.widget.Toast +//import androidx.fragment.app.DialogFragment +//import androidx.lifecycle.ViewModelProvider +//import androidx.navigation.fragment.navArgs +//import com.google.gson.Gson +//import com.jakewharton.fliptables.FlipTable +//import com.mifos.core.common.utils.Constants +//import com.mifos.core.objects.accounts.savings.DepositType +//import com.mifos.core.objects.accounts.savings.SavingsAccountTransactionRequest +//import com.mifos.core.objects.accounts.savings.SavingsAccountTransactionResponse +//import com.mifos.core.objects.templates.savings.SavingsAccountTransactionTemplate +//import com.mifos.exceptions.RequiredFieldException +//import com.mifos.mifosxdroid.R +//import com.mifos.mifosxdroid.core.MaterialDialog +//import com.mifos.mifosxdroid.core.ProgressableFragment +//import com.mifos.mifosxdroid.core.util.Toaster +//import com.mifos.mifosxdroid.databinding.FragmentSavingsAccountTransactionBinding +//import com.mifos.mifosxdroid.uihelpers.MFDatePicker +//import com.mifos.mifosxdroid.uihelpers.MFDatePicker.OnDatePickListener +//import com.mifos.utils.FragmentConstants +//import com.mifos.utils.Network +//import com.mifos.utils.PrefManager +//import com.mifos.utils.Utils +//import dagger.hilt.android.AndroidEntryPoint +// +//@AndroidEntryPoint +//class SavingsAccountTransactionFragment : ProgressableFragment(), OnDatePickListener { +// +// +// private lateinit var binding: FragmentSavingsAccountTransactionBinding +// private val arg: SavingsAccountTransactionFragmentArgs by navArgs() +// val LOG_TAG = javaClass.simpleName +// +// private lateinit var viewModel: SavingsAccountTransactionViewModel +// +// private var savingsAccountNumber: String? = null +// private var savingsAccountId: Int? = null +// private var savingsAccountType: DepositType? = null +// private var transactionType //Defines if the Transaction is a Deposit to an Account +// : String? = null +// +// // or a Withdrawal from an Account +// private var clientName: String? = null +// +// // Values to be fetched from Savings Account Template +// private var paymentTypeOptionId = 0 +// private var mfDatePicker: DialogFragment? = null +// override fun onCreate(savedInstanceState: Bundle?) { +// super.onCreate(savedInstanceState) +// savingsAccountId = arg.savingsAccountWithAssociations.accountNo +// savingsAccountId = arg.savingsAccountWithAssociations.id +// transactionType = arg.transactionType +// clientName = arg.savingsAccountWithAssociations.clientName +// savingsAccountType = arg.accountType +// } +// +// override fun onCreateView( +// inflater: LayoutInflater, +// container: ViewGroup?, +// savedInstanceState: Bundle? +// ): View { +// binding = FragmentSavingsAccountTransactionBinding.inflate(inflater, container, false) +// if (transactionType == Constants.SAVINGS_ACCOUNT_TRANSACTION_DEPOSIT) { +// setToolbarTitle( +// resources.getString(R.string.savingsAccount) + resources +// .getString(R.string.space) + resources.getString(R.string.deposit) +// ) +// } else { +// setToolbarTitle( +// resources.getString(R.string.savingsAccount) + resources +// .getString(R.string.space) + resources.getString(R.string.withdrawal) +// ) +// } +// viewModel = ViewModelProvider(this)[SavingsAccountTransactionViewModel::class.java] +// +// //This Method Checking SavingAccountTransaction made before in Offline mode or not. +// //If yes then User have to sync that first then he will be able to make transaction. +// //If not then User able to make SavingAccountTransaction in Online or Offline. +// checkSavingAccountTransactionStatusInDatabase() +// +// viewModel.savingsAccountTransactionUiState.observe(viewLifecycleOwner) { +// when (it) { +// is SavingsAccountTransactionUiState.ShowError -> { +// showProgressbar(false) +// showError(it.message) +// } +// +// is SavingsAccountTransactionUiState.ShowProgressbar -> showProgressbar(true) +// +// is SavingsAccountTransactionUiState.ShowSavingAccountTemplate -> { +// showProgressbar(false) +// showSavingAccountTemplate(it.savingsAccountTransactionTemplate) +// } +// +// is SavingsAccountTransactionUiState.ShowSavingAccountTransactionExistInDatabase -> { +// showProgressbar(false) +// showSavingAccountTransactionDoesNotExistInDatabase() +// } +// +// is SavingsAccountTransactionUiState.ShowTransactionSuccessfullyDone -> { +// showProgressbar(false) +// showTransactionSuccessfullyDone(it.savingsAccountTransactionResponse) +// } +// } +// } +// +// return binding.root +// } +// +// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +// super.onViewCreated(view, savedInstanceState) +// +// binding.btReviewTransaction.setOnClickListener { +// onReviewTransactionButtonClicked() +// } +// +// binding.btCancelTransaction.setOnClickListener { +// onCancelTransactionButtonClicked() +// } +// +// } +// +// private fun checkSavingAccountTransactionStatusInDatabase() { +// // Checking SavingAccountTransaction Already made in Offline mode or Not. +// savingsAccountId?.let { +// viewModel +// .checkInDatabaseSavingAccountTransaction(it) +// } +// } +// +// private fun showSavingAccountTransactionExistInDatabase() { +// //Visibility of ParentLayout GONE, If SavingAccountTransaction Already made in Offline Mode +// binding.viewFlipper.visibility = View.GONE +// MaterialDialog.Builder().init(activity) +// .setTitle(R.string.sync_previous_transaction) +// .setMessage(R.string.dialog_message_sync_savingaccounttransaction) +// .setPositiveButton( +// R.string.dialog_action_ok +// ) { dialog, which -> requireActivity().supportFragmentManager.popBackStackImmediate() } +// .setCancelable(false) +// .createMaterialDialog() +// .show() +// } +// +// private fun showSavingAccountTransactionDoesNotExistInDatabase() { +// // This Method Inflating UI and Initializing the Loading SavingAccountTransaction +// // Template for transaction. +// inflateUI() +// } +// +// private fun inflateUI() { +// binding.tvClientName.text = clientName +// binding.tvSavingsAccountNumber.text = savingsAccountNumber +// //TODO Implement QuickContactBadge here +// inflateRepaymentDate() +// inflateSavingsAccountTemplate() +// } +// +// private fun inflateSavingsAccountTemplate() { +// savingsAccountId?.let { +// viewModel.loadSavingAccountTemplate( +// savingsAccountType?.endpoint, it, transactionType +// ) +// } +// } +// +// private fun onReviewTransactionButtonClicked() { +// // Notify user if Amount field is blank and Review +// // Transaction button is pressed. +// if (binding.etTransactionAmount.editableText.toString().isEmpty()) { +// RequiredFieldException( +// getString(R.string.amount), +// getString(R.string.message_field_required) +// ).notifyUserWithToast(activity) +// return +// } +// // Notify the user if zero is entered in the Amount +// // field or only "." (Decimal point) is entered. +// try { +// if (binding.etTransactionAmount.editableText.toString().toFloat() == 0f) { +// RequiredFieldException( +// getString(R.string.amount), +// getString(R.string.message_cannot_be_zero) +// ).notifyUserWithToast(activity) +// return +// } +// } catch (e: NumberFormatException) { +// Toast.makeText(activity, R.string.error_invalid_amount, Toast.LENGTH_SHORT).show() +// return +// } +// val headers = arrayOf( +// resources.getString(R.string.field), +// resources.getString(R.string.value) +// ) +// val data = arrayOf( +// arrayOf( +// resources.getString(R.string.transaction_date), +// binding.tvTransactionDate.text.toString() +// ), arrayOf( +// resources.getString(R.string.payment_type), +// binding.spPaymentType.selectedItem.toString() +// ), arrayOf( +// resources.getString(R.string.amount), +// binding.etTransactionAmount.editableText.toString() +// ) +// ) +// Log.d(LOG_TAG, FlipTable.of(headers, data)) +// val formReviewStringBuilder = StringBuilder() +// for (i in 0..2) { +// for (j in 0..1) { +// formReviewStringBuilder.append(data[i][j]) +// if (j == 0) formReviewStringBuilder.append(" : ") +// } +// formReviewStringBuilder.append('\n') +// } +// MaterialDialog.Builder().init(activity) +// .setTitle(resources.getString(R.string.review_transaction_details)) +// .setMessage(formReviewStringBuilder.toString()) +// .setPositiveButton( +// resources.getString(R.string.process_transaction) +// ) { dialogInterface, i -> processTransaction() } +// .setNegativeButton( +// resources.getString(R.string.dialog_action_cancel) +// ) { dialogInterface, i -> dialogInterface.dismiss() } +// .createMaterialDialog() +// .show() +// } +// +// private fun processTransaction() { +// val dateString = binding.tvTransactionDate.text.toString().replace("-", " ") +// val savingsAccountTransactionRequest = SavingsAccountTransactionRequest() +// savingsAccountTransactionRequest.locale = "en" +// savingsAccountTransactionRequest.dateFormat = "dd MM yyyy" +// savingsAccountTransactionRequest.transactionDate = dateString +// savingsAccountTransactionRequest.transactionAmount = binding.etTransactionAmount.editableText.toString() +// savingsAccountTransactionRequest.paymentTypeId = paymentTypeOptionId.toString() +// val builtTransactionRequestAsJson = Gson().toJson(savingsAccountTransactionRequest) +// Log.i(resources.getString(R.string.transaction_body), builtTransactionRequestAsJson) +// +// //why +// if (!Network.isOnline(requireActivity())) PrefManager.userStatus = Constants.USER_OFFLINE +// savingsAccountId?.let { +// viewModel.processTransaction( +// savingsAccountType?.endpoint, +// it, transactionType, savingsAccountTransactionRequest +// ) +// } +// } +// +// private fun onCancelTransactionButtonClicked() { +// requireActivity().supportFragmentManager.popBackStackImmediate() +// } +// +// private fun inflateRepaymentDate() { +// mfDatePicker = MFDatePicker.newInsance(this) +// binding.tvTransactionDate.text = MFDatePicker.datePickedAsString +// // TODO Add Validation to make sure : +// // 1. Date Is in Correct Format +// // 2. Date Entered is not greater than Date Today i.e Date is not in future +// binding.tvTransactionDate.setOnClickListener { +// (mfDatePicker as MFDatePicker?)?.show( +// requireActivity().supportFragmentManager, +// FragmentConstants.DFRAG_DATE_PICKER +// ) +// } +// } +// +// override fun onDatePicked(date: String?) { +// binding.tvTransactionDate.text = date +// } +// +// private fun showSavingAccountTemplate(savingsAccountTransactionTemplate: SavingsAccountTransactionTemplate?) { +// if (savingsAccountTransactionTemplate != null) { +// val listOfPaymentTypes = Utils.getPaymentTypeOptions( +// savingsAccountTransactionTemplate.paymentTypeOptions +// ) +// val paymentTypeAdapter = ArrayAdapter( +// requireActivity(), +// android.R.layout.simple_spinner_item, listOfPaymentTypes +// ) +// paymentTypeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) +// binding.spPaymentType.adapter = paymentTypeAdapter +// binding.spPaymentType.onItemSelectedListener = object : OnItemSelectedListener { +// override fun onItemSelected( +// parent: AdapterView<*>?, +// view: View, +// position: Int, +// id: Long +// ) { +// paymentTypeOptionId = savingsAccountTransactionTemplate +// .paymentTypeOptions[position].id +// } +// +// override fun onNothingSelected(parent: AdapterView<*>?) {} +// } +// } +// } +// +// private fun showTransactionSuccessfullyDone(savingsAccountTransactionResponse: SavingsAccountTransactionResponse?) { +// if (savingsAccountTransactionResponse?.resourceId == null) { +// Toaster.show(binding.root, resources.getString(R.string.transaction_saved_in_db)) +// } else { +// if (transactionType == Constants.SAVINGS_ACCOUNT_TRANSACTION_DEPOSIT) { +// Toaster.show( +// binding.root, "Deposit Successful, Transaction ID = " + +// savingsAccountTransactionResponse.resourceId +// ) +// } else if (transactionType == Constants.SAVINGS_ACCOUNT_TRANSACTION_WITHDRAWAL) { +// Toaster.show( +// binding.root, "Withdrawal Successful, Transaction ID = " +// + savingsAccountTransactionResponse.resourceId +// ) +// } +// } +// requireActivity().supportFragmentManager.popBackStackImmediate() +// } +// +// private fun showError(errorMessage: String) { +// Toaster.show(binding.root, errorMessage) +// } +// +// private fun showProgressbar(b: Boolean) { +// showProgress(b) +// } +//} \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionScreen.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionScreen.kt new file mode 100644 index 00000000000..a57e6611234 --- /dev/null +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionScreen.kt @@ -0,0 +1,528 @@ +package com.mifos.mifosxdroid.online.savingaccounttransaction + +import android.content.Context +import android.util.Log +import android.widget.Toast +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.DatePicker +import androidx.compose.material3.DatePickerDialog +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SelectableDates +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.rememberDatePickerState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableLongStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +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.google.gson.Gson +import com.mifos.core.common.utils.Constants +import com.mifos.core.common.utils.Network +import com.mifos.core.designsystem.component.MifosCircularProgress +import com.mifos.core.designsystem.component.MifosDatePickerTextField +import com.mifos.core.designsystem.component.MifosOutlinedTextField +import com.mifos.core.designsystem.component.MifosScaffold +import com.mifos.core.designsystem.component.MifosSweetError +import com.mifos.core.designsystem.component.MifosTextFieldDropdown +import com.mifos.core.designsystem.icon.MifosIcons +import com.mifos.core.designsystem.theme.Black +import com.mifos.core.designsystem.theme.BluePrimary +import com.mifos.core.designsystem.theme.BluePrimaryDark +import com.mifos.core.designsystem.theme.DarkGray +import com.mifos.core.network.GenericResponse +import com.mifos.core.objects.accounts.savings.SavingsAccountTransactionRequest +import com.mifos.core.objects.accounts.savings.SavingsAccountTransactionResponse +import com.mifos.core.objects.templates.savings.SavingsAccountTransactionTemplate +import com.mifos.mifosxdroid.R +import com.mifos.mifosxdroid.online.savingsaccountactivate.SavingsAccountActivateScreen +import com.mifos.mifosxdroid.online.savingsaccountactivate.SavingsAccountActivateScreenPreviewProvider +import com.mifos.mifosxdroid.online.savingsaccountactivate.SavingsAccountActivateUiState +import com.mifos.utils.PrefManager +import java.text.SimpleDateFormat +import java.util.Locale + +/** + * Created by Pronay Sarker on 18/07/2024 (8:28 PM) + */ + +@Composable +fun SavingsAccountTransactionScreen( + navigateBack: () -> Unit +) { + val viewmodel: SavingsAccountTransactionViewModel = hiltViewModel() + val uiState by viewmodel.savingsAccountTransactionUiState.collectAsStateWithLifecycle() + + LaunchedEffect(key1 = Unit) { + viewmodel.checkInDatabaseSavingAccountTransaction() + } + + SavingsAccountTransactionScreen( + clientName = viewmodel.clientName, + uiState = uiState, + navigateBack = navigateBack, + onRetry = { + viewmodel.checkInDatabaseSavingAccountTransaction() + }, + transactionType = viewmodel.transactionType ?: "", + loadSavingAccountTemplate = { + viewmodel.loadSavingAccountTemplate() + }, + savingsAccountNumber = viewmodel.savingsAccountNumber, + onProcessTransaction = { + viewmodel.processTransaction(it) + } + ) +} + +@Composable +fun SavingsAccountTransactionScreen( + clientName: String?, + savingsAccountNumber: Int?, + uiState: SavingsAccountTransactionUiState, + navigateBack: () -> Unit, + onRetry: () -> Unit, + transactionType: String, + loadSavingAccountTemplate: () -> Unit, + onProcessTransaction: (savingsAccountTransactionRequest: SavingsAccountTransactionRequest) -> Unit +) { + val snackBarHostState = remember { SnackbarHostState() } + val context = LocalContext.current + val topbarTitle = if (transactionType == Constants.SAVINGS_ACCOUNT_TRANSACTION_DEPOSIT) { + stringResource(id = R.string.savingsAccount) + " " + stringResource(id = R.string.deposit) + } else { + stringResource(id = R.string.savingsAccount) + " " + stringResource(id = R.string.withdrawal) + } + + MifosScaffold( + snackbarHostState = snackBarHostState, + title = topbarTitle, + icon = MifosIcons.arrowBack, + onBackPressed = navigateBack + ) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(it) + ) { + when (uiState) { + is SavingsAccountTransactionUiState.ShowError -> { + MifosSweetError(message = uiState.message) { + onRetry() + } + } + + SavingsAccountTransactionUiState.ShowProgressbar -> { + MifosCircularProgress() + } + + is SavingsAccountTransactionUiState.ShowSavingAccountTemplate -> { + SavingsAccountTransactionContent( + clientName = clientName, + navigateBack = navigateBack, + savingsAccountTransactionTemplate = uiState.savingsAccountTransactionTemplate, + savingsAccountNumber = savingsAccountNumber, + onProcessTransaction = onProcessTransaction + ) + } + + SavingsAccountTransactionUiState.ShowSavingAccountTransactionDoesNotExistInDatabase -> { + loadSavingAccountTemplate() + } + + SavingsAccountTransactionUiState.ShowSavingAccountTransactionExistInDatabase -> { + AlertDialog(onDismissRequest = { }, + title = { + Text( + style = MaterialTheme.typography.titleLarge, + text = stringResource(id = R.string.sync_previous_transaction) + ) + }, + text = { Text(text = stringResource(id = R.string.dialog_message_sync_savingaccounttransaction)) }, + confirmButton = { + TextButton(onClick = { navigateBack() }) { + Text(text = stringResource(id = R.string.dialog_action_ok)) + } + } + ) + } + + is SavingsAccountTransactionUiState.ShowTransactionSuccessfullyDone -> { + if (uiState.savingsAccountTransactionResponse.resourceId == null) { + Toast.makeText( + context, + context.resources.getString(R.string.transaction_saved_in_db), + Toast.LENGTH_SHORT + ).show() + } else { + if (transactionType == Constants.SAVINGS_ACCOUNT_TRANSACTION_DEPOSIT) { + Toast.makeText( + context, + context.resources.getString(R.string.deposit_successful_transaction_ID) + uiState.savingsAccountTransactionResponse.resourceId, + Toast.LENGTH_SHORT + ).show() + } else if (transactionType == Constants.SAVINGS_ACCOUNT_TRANSACTION_WITHDRAWAL) { + Toast.makeText( + context, + context.resources.getString(R.string.withdrawal_successful_transaction_ID) + uiState.savingsAccountTransactionResponse.resourceId, + Toast.LENGTH_SHORT + ).show() + } + } + } + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SavingsAccountTransactionContent( + clientName: String?, + savingsAccountNumber: Int?, + navigateBack: () -> Unit, + savingsAccountTransactionTemplate: SavingsAccountTransactionTemplate, + onProcessTransaction: (savingsAccountTransactionRequest: SavingsAccountTransactionRequest) -> Unit +) { + var amount by rememberSaveable { + mutableStateOf("") + } + var paymentType by rememberSaveable { + mutableStateOf("") + } + var paymentTypeId by rememberSaveable { + mutableStateOf(0) + } + + var transactionDate by rememberSaveable { + mutableLongStateOf(System.currentTimeMillis()) + } + var openDatepicker by rememberSaveable { + mutableStateOf(false) + } + val datePickerState = rememberDatePickerState( + initialSelectedDateMillis = transactionDate, + selectableDates = object : SelectableDates { + override fun isSelectableDate(utcTimeMillis: Long): Boolean { + return utcTimeMillis >= System.currentTimeMillis() + } + } + ) + val context = LocalContext.current + val scrollState = rememberScrollState() + var showReviewTransactionDialog by rememberSaveable { + mutableStateOf(false) + } + + if (showReviewTransactionDialog) { + AlertDialog(onDismissRequest = { showReviewTransactionDialog = false }, + title = { + Text(text = stringResource(id = R.string.review_transaction_details), style = MaterialTheme.typography.titleLarge)}, + text = { + Column { + Text( + text = stringResource(id = R.string.transaction_date) + " : " + SimpleDateFormat( + "dd MMMM yyyy", + Locale.getDefault() + ).format(transactionDate) + ) + Text(text = stringResource(id = R.string.payment_type) + " : " + paymentType) + Text(text = stringResource(id = R.string.amount) + " : " + amount) + } + }, + confirmButton = { + TextButton( + onClick = { + showReviewTransactionDialog = false + val savingsAccountTransactionRequest = SavingsAccountTransactionRequest() + + savingsAccountTransactionRequest.locale = "en" + savingsAccountTransactionRequest.dateFormat = "dd MM yyyy" + savingsAccountTransactionRequest.transactionDate = SimpleDateFormat( + "dd MMMM yyyy", + Locale.getDefault() + ).format(transactionDate) + savingsAccountTransactionRequest.transactionAmount = amount + savingsAccountTransactionRequest.paymentTypeId = paymentTypeId.toString() + + val builtTransactionRequestAsJson = + Gson().toJson(savingsAccountTransactionRequest) + Log.i( + context.resources.getString(R.string.transaction_body), + builtTransactionRequestAsJson + ) + + onProcessTransaction.invoke(savingsAccountTransactionRequest) + }) { + Text(text = stringResource(id = R.string.review_transaction)) + } + }, + dismissButton = { + TextButton(onClick = { showReviewTransactionDialog = false }) { + Text(text = stringResource(id = R.string.cancel)) + } + } + ) + } + + if (openDatepicker) { + DatePickerDialog( + onDismissRequest = { + openDatepicker = false + }, + confirmButton = { + TextButton( + onClick = { + datePickerState.selectedDateMillis?.let { + transactionDate = it + } + openDatepicker = false + } + ) { Text(stringResource(id = R.string.select_date)) } + }, + dismissButton = { + TextButton( + onClick = { + openDatepicker = false + } + ) { Text(stringResource(id = R.string.cancel)) } + } + ) + { + DatePicker(state = datePickerState) + } + } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp, vertical = 10.dp) + .verticalScroll(scrollState) + ) { + Text( + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.onBackground, + text = clientName ?: "" + + // TODO from old fragment + // 1. Implement QuickContactBadge here + ) + + HorizontalDivider(modifier = Modifier.padding(top = 6.dp)) + + FarApartTextItem( + title = stringResource(id = R.string.account_number), + value = savingsAccountNumber?.toString() ?: "" + ) + + Spacer(modifier = Modifier.height(16.dp)) + + // TODO from old fragment: Add Validation to make sure : + // 1. Date Is in Correct Format + // 2. Date Entered is not greater than Date Today i.e Date is not in future + + MifosDatePickerTextField( + value = SimpleDateFormat( + "dd-MMMM-yyyy", + Locale.getDefault() + ).format(transactionDate), label = R.string.date, + modifier = Modifier.fillMaxWidth() + ) { + openDatepicker = true + } + + Spacer(modifier = Modifier.height(16.dp)) + + MifosOutlinedTextField( + modifier = Modifier.fillMaxWidth(), + value = amount, + onValueChange = { amount = it }, + label = stringResource(id = R.string.amount), + error = null, + keyboardType = KeyboardType.Number + ) + + Spacer(modifier = Modifier.height(16.dp)) + + MifosTextFieldDropdown( + modifier = Modifier.fillMaxWidth(), + value = paymentType, + onValueChanged = { paymentType = it }, + onOptionSelected = { index, value -> + paymentType = value + paymentTypeId = savingsAccountTransactionTemplate.paymentTypeOptions[index].id + }, + label = R.string.payment_type, + options = savingsAccountTransactionTemplate.paymentTypeOptions.map { it.name }, + readOnly = true + ) + + Spacer(modifier = Modifier.height(16.dp)) + + Row( + modifier = Modifier.fillMaxSize(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Button( + modifier = Modifier.heightIn(46.dp), + colors = ButtonDefaults.buttonColors( + containerColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary + ), + onClick = { navigateBack.invoke() }) { + Text(text = stringResource(id = R.string.cancel)) + } + + Button( + modifier = Modifier.heightIn(46.dp), + colors = ButtonDefaults.buttonColors( + containerColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary + ), + onClick = { + if (isAmountValid(context, amount)) { + if (Network.isOnline(context = context)) { + showReviewTransactionDialog = true + } else { + PrefManager.userStatus = Constants.USER_OFFLINE + + Toast.makeText( + context, + context.resources.getString(R.string.error_not_connected_internet), + Toast.LENGTH_SHORT + ).show() + } + } + } + ) { + Text(text = stringResource(id = R.string.review_transaction)) + } + } + + } +} + +fun isAmountValid( + context: Context, + amount: String, +): Boolean { + if (amount.isEmpty()) { + Toast.makeText( + context, + context.resources.getString(R.string.amount) + " " + context.resources.getString(R.string.message_field_required), + Toast.LENGTH_SHORT + ).show() + + return false + } + + try { + if (amount.toFloat() == 0f) { + Toast.makeText( + context, + context.resources.getString(R.string.error_amount_can_not_be_empty), + Toast.LENGTH_SHORT + ).show() + + return false + } + } catch (e: NumberFormatException) { + Toast.makeText( + context, + context.resources.getString(R.string.error_invalid_amount), + Toast.LENGTH_SHORT + ).show() + + return false + } + + return true +} + +@Composable +private fun FarApartTextItem(title: String, value: String) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 6.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + style = MaterialTheme.typography.bodyLarge, + text = title, + color = Black, + ) + + Text( + style = MaterialTheme.typography.bodyLarge, + text = value, + color = DarkGray, + ) + } +} + +class SavingsAccountTransactionScreenPreviewProvider : + PreviewParameterProvider { + + override val values: Sequence + get() = sequenceOf( + SavingsAccountTransactionUiState.ShowSavingAccountTemplate( + SavingsAccountTransactionTemplate( + paymentTypeOptions = listOf() + ) + ), + SavingsAccountTransactionUiState.ShowProgressbar, + SavingsAccountTransactionUiState.ShowSavingAccountTransactionDoesNotExistInDatabase, + SavingsAccountTransactionUiState.ShowSavingAccountTransactionExistInDatabase, + SavingsAccountTransactionUiState.ShowError("Failed to fetch"), + SavingsAccountTransactionUiState.ShowTransactionSuccessfullyDone( + SavingsAccountTransactionResponse() + ) + ) +} + +@Composable +@Preview(showSystemUi = true) +fun PreviewSavingsAccountTransactionScreen( + @PreviewParameter(SavingsAccountTransactionScreenPreviewProvider::class) savingsAccountTransactionUiState: SavingsAccountTransactionUiState +) { + SavingsAccountTransactionScreen( + clientName = "Jean Charles", + savingsAccountNumber = 0, + uiState = savingsAccountTransactionUiState, + navigateBack = { }, + onRetry = { }, + transactionType = "type", + loadSavingAccountTemplate = { }) { + } +} + diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionUiState.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionUiState.kt index 52296d68398..13682a7e32b 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionUiState.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionUiState.kt @@ -15,8 +15,11 @@ sealed class SavingsAccountTransactionUiState { data class ShowSavingAccountTemplate(val savingsAccountTransactionTemplate: SavingsAccountTransactionTemplate) : SavingsAccountTransactionUiState() + data class ShowTransactionSuccessfullyDone(val savingsAccountTransactionResponse: SavingsAccountTransactionResponse) : SavingsAccountTransactionUiState() data object ShowSavingAccountTransactionExistInDatabase : SavingsAccountTransactionUiState() + + data object ShowSavingAccountTransactionDoesNotExistInDatabase : SavingsAccountTransactionUiState() } diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionViewModel.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionViewModel.kt index 2667b823f88..6d56f383edb 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionViewModel.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingaccounttransaction/SavingsAccountTransactionViewModel.kt @@ -3,10 +3,15 @@ package com.mifos.mifosxdroid.online.savingaccounttransaction import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import com.mifos.core.objects.accounts.savings.DepositType import com.mifos.core.objects.accounts.savings.SavingsAccountTransactionRequest +import com.mifos.core.objects.accounts.savings.SavingsAccountTransactionRequest_Table.savingAccountId import com.mifos.core.objects.accounts.savings.SavingsAccountTransactionResponse import com.mifos.core.objects.templates.savings.SavingsAccountTransactionTemplate +import com.mifos.mifosxdroid.online.loanrepayment.LoanRepaymentUiState import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import rx.Subscriber import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers @@ -19,75 +24,87 @@ import javax.inject.Inject class SavingsAccountTransactionViewModel @Inject constructor(private val repository: SavingsAccountTransactionRepository) : ViewModel() { - private val _savingsAccountTransactionUiState = - MutableLiveData() + private val _savingsAccountTransactionUiState = MutableStateFlow(SavingsAccountTransactionUiState.ShowProgressbar) + val savingsAccountTransactionUiState: StateFlow get() = _savingsAccountTransactionUiState - val savingsAccountTransactionUiState: LiveData - get() = _savingsAccountTransactionUiState + var transactionType : String? = null + var accountId : Int? = null + var clientName : String? = null + var savingsAccountNumber : Int? = null + var savingsAccountType: DepositType? = null - fun loadSavingAccountTemplate(type: String?, accountId: Int, transactionType: String?) { + fun loadSavingAccountTemplate() { _savingsAccountTransactionUiState.value = SavingsAccountTransactionUiState.ShowProgressbar - repository.getSavingsAccountTransactionTemplate(type, accountId, transactionType) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber() { - override fun onCompleted() {} - override fun onError(e: Throwable) { - _savingsAccountTransactionUiState.value = - SavingsAccountTransactionUiState.ShowError(e.message.toString()) - } + accountId?.let { + repository.getSavingsAccountTransactionTemplate(savingsAccountType?.endpoint, + it, transactionType) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe(object : Subscriber() { + override fun onCompleted() {} + override fun onError(e: Throwable) { + _savingsAccountTransactionUiState.value = + SavingsAccountTransactionUiState.ShowError(e.message.toString()) + } - override fun onNext(savingsAccountTransactionTemplate: SavingsAccountTransactionTemplate) { - _savingsAccountTransactionUiState.value = - SavingsAccountTransactionUiState.ShowSavingAccountTemplate( - savingsAccountTransactionTemplate - ) - } - }) + override fun onNext(savingsAccountTransactionTemplate: SavingsAccountTransactionTemplate) { + _savingsAccountTransactionUiState.value = + SavingsAccountTransactionUiState.ShowSavingAccountTemplate( + savingsAccountTransactionTemplate + ) + } + }) + } } - fun processTransaction( - type: String?, accountId: Int, transactionType: String?, - request: SavingsAccountTransactionRequest - ) { + fun processTransaction(request: SavingsAccountTransactionRequest) { _savingsAccountTransactionUiState.value = SavingsAccountTransactionUiState.ShowProgressbar - repository - .processTransaction(type, accountId, transactionType, request) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber() { - override fun onCompleted() {} - override fun onError(e: Throwable) { - _savingsAccountTransactionUiState.value = - SavingsAccountTransactionUiState.ShowError(e.message.toString()) - } + accountId?.let { + repository + .processTransaction(savingsAccountType?.endpoint, it, transactionType, request) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe(object : Subscriber() { + override fun onCompleted() {} + override fun onError(e: Throwable) { + _savingsAccountTransactionUiState.value = + SavingsAccountTransactionUiState.ShowError(e.message.toString()) + } - override fun onNext(savingsAccountTransactionResponse: SavingsAccountTransactionResponse) { - _savingsAccountTransactionUiState.value = - SavingsAccountTransactionUiState.ShowTransactionSuccessfullyDone( - savingsAccountTransactionResponse - ) - } - }) + override fun onNext(savingsAccountTransactionResponse: SavingsAccountTransactionResponse) { + _savingsAccountTransactionUiState.value = + SavingsAccountTransactionUiState.ShowTransactionSuccessfullyDone( + savingsAccountTransactionResponse + ) + } + }) + } } - fun checkInDatabaseSavingAccountTransaction(savingAccountId: Int) { + fun checkInDatabaseSavingAccountTransaction() { _savingsAccountTransactionUiState.value = SavingsAccountTransactionUiState.ShowProgressbar - repository.getSavingsAccountTransaction(savingAccountId) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber() { - override fun onCompleted() {} - override fun onError(e: Throwable) { - _savingsAccountTransactionUiState.value = - SavingsAccountTransactionUiState.ShowError(e.message.toString()) - } + accountId?.let { + repository.getSavingsAccountTransaction(it) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe(object : Subscriber() { + override fun onCompleted() {} + override fun onError(e: Throwable) { + _savingsAccountTransactionUiState.value = + SavingsAccountTransactionUiState.ShowError(e.message.toString()) + } - override fun onNext(savingsAccountTransactionRequest: SavingsAccountTransactionRequest) { - _savingsAccountTransactionUiState.value = - SavingsAccountTransactionUiState.ShowSavingAccountTransactionExistInDatabase - } - }) + override fun onNext(savingsAccountTransactionRequest: SavingsAccountTransactionRequest?) { + if (savingsAccountTransactionRequest != null) { + _savingsAccountTransactionUiState.value = + SavingsAccountTransactionUiState.ShowSavingAccountTransactionExistInDatabase + } else { + _savingsAccountTransactionUiState.value = + SavingsAccountTransactionUiState.ShowSavingAccountTransactionDoesNotExistInDatabase + } + } + }) + } } } \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingsaccount/SavingsAccountScreen.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingsaccount/SavingsAccountScreen.kt index c9ddd631e64..15b9c44d690 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingsaccount/SavingsAccountScreen.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/savingsaccount/SavingsAccountScreen.kt @@ -572,9 +572,9 @@ class SavingsAccountScreenPreviewProvider : PreviewParameterProvider - - + + + + + + Select Approval Date: Expected disbursement on Approved On* + Withdrawal Successful, Transaction ID = + Deposit Successful, Transaction ID = Activated On* Transaction Id : %1$d , Running Balance : %2$f Enforce Minimum Required Balance