diff --git a/build.gradle b/build.gradle index a89d7156a8d..7de19df4092 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ task clean(type: Delete) { // Define versions in a single place ext { // Sdk and tools - minSdkVersion = 19 + minSdkVersion = 26 targetSdkVersion = 33 compileSdkVersion = 33 buildToolsVersion = '28.0.3' @@ -103,8 +103,8 @@ ext { crashlyticsVersion = '2.10.1@aar' // android test runner version - androidTestRunnerVersion = '1.1.0' - androidTestRuleVersion = '1.1.0' + androidTestRunnerVersion = '1.5.2' + androidTestRuleVersion = '1.5.0' //jUnit jupiter junitJupiterVersion = '5.7.2' diff --git a/mifosng-android/build.gradle b/mifosng-android/build.gradle index 039dcb45488..5fb4c190df3 100755 --- a/mifosng-android/build.gradle +++ b/mifosng-android/build.gradle @@ -14,7 +14,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:7.2.2' + classpath 'com.android.tools.build:gradle:7.4.2' classpath 'io.fabric.tools:gradle:1.31.0' classpath 'com.github.triplet.gradle:play-publisher:1.1.5' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/AboutActivity.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/AboutActivity.kt index 936dd013f33..bced7f9b290 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/AboutActivity.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/AboutActivity.kt @@ -10,10 +10,11 @@ class AboutActivity : MifosBaseActivity() { private lateinit var binding: ActivityAboutBinding - var contributors = "https://github.com/openMF/android-client/graphs/contributors" - var gitHub = "https://github.com/openMF/android-client" - var twitter = "https://twitter.com/mifos" - var license = "https://github.com/openMF/android-client/blob/master/LICENSE.md" + private val websiteLink = "https://openmf.github.io/mobileapps.github.io/" + private val contributors = "https://github.com/openMF/android-client/graphs/contributors" + private val gitHub = "https://github.com/openMF/android-client" + private val twitter = "https://twitter.com/mifos" + private val license = "https://github.com/openMF/android-client/blob/master/LICENSE.md" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -21,21 +22,26 @@ class AboutActivity : MifosBaseActivity() { setContentView(binding.root) showBackButton() + binding.appVersion.text = BuildConfig.VERSION_NAME + binding.contributor.setOnClickListener { link(contributors) } - binding.GitHub.setOnClickListener { + binding.sourcesText.setOnClickListener { link(gitHub) } - binding.twitter.setOnClickListener { + binding.twitterLinkContainer.setOnClickListener { link(twitter) } - binding.llAboutLicense.setOnClickListener { + binding.selfLicenseContainer.setOnClickListener { link(license) } + binding.aboutWebsiteContainer.setOnClickListener { + link(websiteLink) + } } - fun link(url: String?) { + private fun link(url: String) { val intent = Intent(Intent.ACTION_VIEW) intent.data = Uri.parse(url) startActivity(intent) diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/login/LoginActivity.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/login/LoginActivity.kt index 8fe38792367..634d12e941f 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/login/LoginActivity.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/login/LoginActivity.kt @@ -45,9 +45,8 @@ class LoginActivity : MifosBaseActivity(), LoginMvpView { private lateinit var binding: ActivityLoginBinding - @JvmField @Inject - var mLoginPresenter: LoginPresenter? = null + lateinit var mLoginPresenter: LoginPresenter private lateinit var username: String private lateinit var instanceURL: String private lateinit var password: String @@ -64,7 +63,7 @@ class LoginActivity : MifosBaseActivity(), LoginMvpView { isValidUrl = ValidationUtil.isValidUrl(instanceURL) binding.tvConstructedInstanceUrl.text = instanceURL domain = binding.etInstanceURL.editableText.toString() - if (domain.isEmpty() == true || domain.contains(" ") == true) { + if (domain.isEmpty() || domain.contains(" ")) { isValidUrl = false } binding.tvConstructedInstanceUrl.setTextColor( @@ -80,10 +79,10 @@ class LoginActivity : MifosBaseActivity(), LoginMvpView { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) activityComponent?.inject(this) -// ButterKnife.bind(this) binding = ActivityLoginBinding.inflate(layoutInflater) + title = null setContentView(binding.root) - mLoginPresenter?.attachView(this) + mLoginPresenter.attachView(this) binding.etInstancePort.inputType = InputType.TYPE_CLASS_NUMBER if (port != "80") binding.etInstancePort.setText(port) binding.etInstanceURL.setText(instanceDomain) @@ -204,7 +203,7 @@ class LoginActivity : MifosBaseActivity(), LoginMvpView { // Updating Services BaseApiManager.createService() if (Network.isOnline(this)) { - mLoginPresenter?.login(username, password) + mLoginPresenter.login(username, password) } else { showToastMessage(getString(R.string.error_not_connected_internet)) } @@ -212,6 +211,6 @@ class LoginActivity : MifosBaseActivity(), LoginMvpView { override fun onDestroy() { super.onDestroy() - mLoginPresenter?.detachView() + mLoginPresenter.detachView() } } \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/activate/ActivateFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/activate/ActivateFragment.kt index 5518ab3d0fc..49006f1f23a 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/activate/ActivateFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/activate/ActivateFragment.kt @@ -5,7 +5,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast -import androidx.fragment.app.DialogFragment import androidx.navigation.fragment.navArgs import com.mifos.mifosxdroid.R import com.mifos.mifosxdroid.core.MifosBaseActivity @@ -13,29 +12,38 @@ import com.mifos.mifosxdroid.core.MifosBaseFragment import com.mifos.mifosxdroid.core.util.Toaster import com.mifos.mifosxdroid.core.util.Toaster.show import com.mifos.mifosxdroid.databinding.FragmentActivateClientBinding -import com.mifos.mifosxdroid.uihelpers.MFDatePicker -import com.mifos.mifosxdroid.uihelpers.MFDatePicker.OnDatePickListener import com.mifos.objects.client.ActivatePayload import com.mifos.utils.Constants -import com.mifos.utils.DateHelper +import com.mifos.utils.DatePickerConstrainType import com.mifos.utils.FragmentConstants +import com.mifos.utils.getDatePickerDialog +import com.mifos.utils.getTodayFormatted +import java.text.SimpleDateFormat +import java.time.Instant +import java.util.Locale import javax.inject.Inject /** * Created by Rajan Maurya on 09/02/17. */ -class ActivateFragment : MifosBaseFragment(), ActivateMvpView, OnDatePickListener { +class ActivateFragment : MifosBaseFragment(), ActivateMvpView { private lateinit var binding: FragmentActivateClientBinding - private val arg : ActivateFragmentArgs by navArgs() + private val arg: ActivateFragmentArgs by navArgs() - @JvmField @Inject - var activatePresenter: ActivatePresenter? = null - private var mfDatePicker: DialogFragment? = null - private var activationDate: String? = null + lateinit var activatePresenter: ActivatePresenter private var id = 0 private var activateType: String? = null + private var activationDate: Instant = Instant.now() + private val submissionDatePickerDialog by lazy { + getDatePickerDialog(activationDate, DatePickerConstrainType.ONLY_FUTURE_DAYS) { + val formattedDate = SimpleDateFormat("dd MM yyyy", Locale.getDefault()).format(it) + activationDate = Instant.ofEpochMilli(it) + binding.activateDateFieldContainer.editText?.setText(formattedDate) + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (activity as MifosBaseActivity).activityComponent?.inject(this) @@ -47,7 +55,7 @@ class ActivateFragment : MifosBaseFragment(), ActivateMvpView, OnDatePickListene inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentActivateClientBinding.inflate(inflater, container, false) - activatePresenter?.attachView(this) + activatePresenter.attachView(this) showUserInterface() return binding.root } @@ -59,42 +67,29 @@ class ActivateFragment : MifosBaseFragment(), ActivateMvpView, OnDatePickListene onClickActivationButton() } - binding.tvActivationDate.setOnClickListener { - onClickTextViewActivationDate() + binding.activateDateFieldContainer.setEndIconOnClickListener { + submissionDatePickerDialog.show( + requireActivity().supportFragmentManager, + FragmentConstants.DFRAG_DATE_PICKER + ) } } override fun showUserInterface() { setToolbarTitle(getString(R.string.activate)) - mfDatePicker = MFDatePicker.newInsance(this) - binding.tvActivationDate.text = MFDatePicker.datePickedAsString - activationDate = binding.tvActivationDate.text.toString() - activationDate = DateHelper.getDateAsStringUsedForCollectionSheetPayload(activationDate) - .replace("-", " ") + binding.activateDateFieldContainer.editText?.setText(getTodayFormatted()) } private fun onClickActivationButton() { - val clientActivate = ActivatePayload(activationDate) + val clientActivate = ActivatePayload(activationDate.toString()) activate(clientActivate) } - private fun onClickTextViewActivationDate() { - mfDatePicker?.show( - requireActivity().supportFragmentManager, FragmentConstants.DFRAG_DATE_PICKER - ) - } - - override fun onDatePicked(date: String?) { - binding.tvActivationDate.text = date - activationDate = - DateHelper.getDateAsStringUsedForCollectionSheetPayload(date).replace("-", " ") - } - fun activate(clientActivate: ActivatePayload?) { when (activateType) { - Constants.ACTIVATE_CLIENT -> activatePresenter?.activateClient(id, clientActivate) - Constants.ACTIVATE_CENTER -> activatePresenter?.activateCenter(id, clientActivate) - Constants.ACTIVATE_GROUP -> activatePresenter?.activateGroup(id, clientActivate) + Constants.ACTIVATE_CLIENT -> activatePresenter.activateClient(id, clientActivate) + Constants.ACTIVATE_CENTER -> activatePresenter.activateCenter(id, clientActivate) + Constants.ACTIVATE_GROUP -> activatePresenter.activateGroup(id, clientActivate) else -> {} } } @@ -120,18 +115,6 @@ class ActivateFragment : MifosBaseFragment(), ActivateMvpView, OnDatePickListene override fun onDestroyView() { super.onDestroyView() - activatePresenter?.detachView() - } - - companion object { - val LOG_TAG = ActivateFragment::class.java.simpleName - fun newInstance(id: Int, activationType: String?): ActivateFragment { - val activateFragment = ActivateFragment() - val args = Bundle() - args.putInt(Constants.ID, id) - args.putString(Constants.ACTIVATE_TYPE, activationType) - activateFragment.arguments = args - return activateFragment - } + activatePresenter.detachView() } } \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetFragment.kt index 8189085fc9b..919e00e0600 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetFragment.kt @@ -4,11 +4,6 @@ import android.os.Bundle 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.Spinner -import androidx.fragment.app.DialogFragment import androidx.navigation.fragment.findNavController import com.mifos.api.model.RequestCollectionSheetPayload import com.mifos.mifosxdroid.R @@ -17,17 +12,17 @@ import com.mifos.mifosxdroid.core.MifosBaseFragment import com.mifos.mifosxdroid.core.util.Toaster import com.mifos.mifosxdroid.databinding.FragmentNewCollectionSheetBinding import com.mifos.mifosxdroid.dialogfragments.collectionsheetdialog.CollectionSheetDialogFragment -import com.mifos.mifosxdroid.dialogfragments.searchdialog.SearchDialog -import com.mifos.mifosxdroid.online.collectionsheetindividualdetails.IndividualCollectionSheetDetailsFragment -import com.mifos.mifosxdroid.uihelpers.MFDatePicker -import com.mifos.mifosxdroid.uihelpers.MFDatePicker.OnDatePickListener -import com.mifos.mifosxdroid.views.CustomSpinner.OnSpinnerEventsListener import com.mifos.objects.collectionsheet.IndividualCollectionSheet import com.mifos.objects.organisation.Office import com.mifos.objects.organisation.Staff import com.mifos.utils.Constants -import com.mifos.utils.DateHelper +import com.mifos.utils.DatePickerConstrainType import com.mifos.utils.FragmentConstants +import com.mifos.utils.getDatePickerDialog +import com.mifos.utils.getTodayFormatted +import java.text.SimpleDateFormat +import java.time.Instant +import java.util.Locale import javax.inject.Inject @@ -35,19 +30,16 @@ import javax.inject.Inject * Created by aksh on 18/6/18. */ class NewIndividualCollectionSheetFragment : MifosBaseFragment(), IndividualCollectionSheetMvpView, - OnDatePickListener, OnItemSelectedListener, View.OnClickListener { + View.OnClickListener { private lateinit var binding: FragmentNewCollectionSheetBinding @Inject lateinit var presenter: NewIndividualCollectionSheetPresenter private var sheet: IndividualCollectionSheet? = null - private var datePicker: DialogFragment? = null private var requestPayload: RequestCollectionSheetPayload? = null - private var officeAdapter: ArrayAdapter? = null private lateinit var officeNameList: ArrayList private var officeList: List = ArrayList() - private var staffAdapter: ArrayAdapter? = null private lateinit var staffNameList: ArrayList private var staffList: List = ArrayList() private var officeId: Int? = 0 @@ -57,8 +49,14 @@ class NewIndividualCollectionSheetFragment : MifosBaseFragment(), IndividualColl private var actualDisbursementDate: String? = null private var transactionDate: String? = null - private var officeSearchDialog: SearchDialog? = null - private var staffSearchDialog: SearchDialog? = null + private var selectedRepaymentDate: Instant = Instant.now() + private val datePickerDialog by lazy { + getDatePickerDialog(selectedRepaymentDate, DatePickerConstrainType.ONLY_FUTURE_DAYS) { + val formattedDate = SimpleDateFormat("dd MM yyyy", Locale.getDefault()).format(it) + selectedRepaymentDate = Instant.ofEpochMilli(it) + binding.repaymentDateFieldContainer.editText?.setText(formattedDate) + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -92,72 +90,29 @@ class NewIndividualCollectionSheetFragment : MifosBaseFragment(), IndividualColl private fun setUpUi() { setRepaymentDate() officeNameList = ArrayList() - officeAdapter = ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_item, officeNameList - ) - officeAdapter?.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spOfficeList.adapter = officeAdapter - binding.spOfficeList.onItemSelectedListener = this + binding.officeListField.setSimpleItems(officeNameList.toTypedArray()) + binding.officeListField.setOnItemClickListener { adapterView, view, relativePosition, l -> + val i = officeNameList.indexOf(adapterView.getItemAtPosition(relativePosition)) + Toaster.show(binding.root, officeNameList[i]) + officeId = officeList[i].id + presenter.fetchStaff(officeId!!) + } staffNameList = ArrayList() - staffAdapter = ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_item, staffNameList - ) - staffAdapter?.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spStaffList.adapter = staffAdapter - binding.tvRepaymentDate.setOnClickListener(this) + binding.staffSelectionField.setSimpleItems(staffNameList.toTypedArray()) + binding.repaymentDateFieldContainer.setEndIconOnClickListener { + datePickerDialog.show( + requireActivity().supportFragmentManager, + FragmentConstants.DFRAG_DATE_PICKER + ) + } binding.btnFetchCollectionSheet.setOnClickListener(this) presenter.fetchOffices() - binding.spOfficeList.setSpinnerEventsListener(object : OnSpinnerEventsListener { - override fun onSpinnerOpened(spinner: Spinner, isItemListLarge: Boolean) { - if (isItemListLarge) { - enableOfficeSearch() - } - } - - override fun onSpinnerClosed(spinner: Spinner) {} - }) - - binding.spStaffList.setSpinnerEventsListener(object : OnSpinnerEventsListener { - override fun onSpinnerOpened(spinner: Spinner, isItemListLarge: Boolean) { - if (isItemListLarge) { - enableStaffSearch() - } - } - - override fun onSpinnerClosed(spinner: Spinner) {} - }) - - } - - fun enableOfficeSearch() { - if (officeSearchDialog == null) { - val listener = AdapterView.OnItemClickListener { adapterView, view, i, l -> - binding.spOfficeList.setSelection(i) - } - officeSearchDialog = SearchDialog(requireContext(), officeNameList, listener) - } - officeSearchDialog?.show() - } - - fun enableStaffSearch() { - if (staffSearchDialog == null) { - val listener = AdapterView.OnItemClickListener { adapterView, view, i, l -> - binding.spStaffList.setSelection(i) - } - staffSearchDialog = SearchDialog(requireContext(), staffNameList, listener) - } - staffSearchDialog?.show() } private fun setRepaymentDate() { - datePicker = MFDatePicker.newInsance(this) - val date = - DateHelper.getDateAsStringUsedForCollectionSheetPayload(MFDatePicker.datePickedAsString) - binding.tvRepaymentDate.text = date.replace('-', ' ') - transactionDate = date.replace('-', ' ') + binding.repaymentDateFieldContainer.editText?.setText(getTodayFormatted()) + transactionDate = getTodayFormatted() actualDisbursementDate = transactionDate } @@ -165,7 +120,8 @@ class NewIndividualCollectionSheetFragment : MifosBaseFragment(), IndividualColl requestPayload = RequestCollectionSheetPayload() requestPayload?.officeId = officeId requestPayload?.staffId = staffId - requestPayload?.transactionDate = binding.tvRepaymentDate.text.toString() + requestPayload?.transactionDate = + binding.repaymentDateFieldContainer.editText?.text.toString() } override fun setOfficeSpinner(offices: List?) { @@ -173,14 +129,8 @@ class NewIndividualCollectionSheetFragment : MifosBaseFragment(), IndividualColl officeList = offices } officeNameList.clear() - officeNameList.add(getString(R.string.spinner_office)) officeNameList.addAll(presenter.filterOffices(officeList)) - officeAdapter?.notifyDataSetChanged() - } - - override fun onDatePicked(date: String?) { - val d = DateHelper.getDateAsStringUsedForCollectionSheetPayload(date) - binding.tvRepaymentDate.text = d.replace('-', ' ') + binding.officeListField.setSimpleItems(officeNameList.toTypedArray()) } private fun retrieveCollectionSheet() { @@ -188,45 +138,22 @@ class NewIndividualCollectionSheetFragment : MifosBaseFragment(), IndividualColl presenter.fetchIndividualCollectionSheet(requestPayload) } - private fun setTvRepaymentDate() { - datePicker?.show( - requireActivity().supportFragmentManager, - FragmentConstants.DFRAG_DATE_PICKER - ) - } - override fun setStaffSpinner(staffs: List?) { - binding.spStaffList.onItemSelectedListener = this + binding.staffSelectionField.setOnItemClickListener { adapterView, _, relativePosition, _ -> + val i = staffNameList.indexOf(adapterView.getItemAtPosition(relativePosition)) + staffId = staffList[i].id + } if (staffs != null) { staffList = staffs } staffNameList.clear() - staffNameList.add(getString(R.string.spinner_staff)) staffNameList.addAll(presenter.filterStaff(staffList)) - staffAdapter?.notifyDataSetChanged() - } - - override fun onItemSelected(adapterView: AdapterView<*>, view: View, i: Int, l: Long) { - when (adapterView.id) { - R.id.sp_office_list -> if (i == officeList.size || i == 0) { - Toaster.show(binding.root, getStringMessage(R.string.error_select_office)) - } else { - Toaster.show(binding.root, officeNameList[i]) - officeId = officeList[i - 1].id - officeId?.let { presenter.fetchStaff(it) } - } - - R.id.sp_staff_list -> if (i == staffList.size || i == 0) { - Toaster.show(binding.root, getStringMessage(R.string.error_select_staff)) - } else { - staffId = staffList[i - 1].id - } - } + binding.staffSelectionField.setSimpleItems(staffNameList.toTypedArray()) } private fun popupDialog() { val collectionSheetDialogFragment = CollectionSheetDialogFragment.newInstance( - binding.tvRepaymentDate.text.toString(), + binding.repaymentDateFieldContainer.editText?.text.toString(), sheet?.clients?.size ?: 0 ) collectionSheetDialogFragment.setTargetFragment(this, requestCode) @@ -256,7 +183,6 @@ class NewIndividualCollectionSheetFragment : MifosBaseFragment(), IndividualColl } } - override fun onNothingSelected(adapterView: AdapterView<*>?) {} override fun showSheet(individualCollectionSheet: IndividualCollectionSheet?) { sheet = individualCollectionSheet } @@ -291,15 +217,21 @@ class NewIndividualCollectionSheetFragment : MifosBaseFragment(), IndividualColl override fun onClick(view: View) { when (view.id) { - R.id.tv_repayment_date -> setTvRepaymentDate() - R.id.btn_fetch_collection_sheet -> retrieveCollectionSheet() + R.id.btn_fetch_collection_sheet -> { + if (!officeNameList.contains(binding.officeListField.text.toString())) + Toaster.show(binding.root, getStringMessage(R.string.error_select_office)) + else if (!staffNameList.contains(binding.staffSelectionField.text.toString())) + Toaster.show(binding.root, getStringMessage(R.string.error_select_staff)) + else + retrieveCollectionSheet() + } } } private fun clear() { - binding.spOfficeList.adapter = null - binding.spStaffList.adapter = null + binding.officeListField.setAdapter(null) + binding.staffSelectionField.setAdapter(null) setUpUi() } diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewcenter/CreateNewCenterFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewcenter/CreateNewCenterFragment.kt index 2f41c2dbcd1..1d866781b6c 100755 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewcenter/CreateNewCenterFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewcenter/CreateNewCenterFragment.kt @@ -6,15 +6,10 @@ package com.mifos.mifosxdroid.online.createnewcenter import android.os.Bundle import android.text.TextUtils -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 com.mifos.exceptions.InvalidTextInputException import com.mifos.exceptions.RequiredFieldException import com.mifos.exceptions.ShortOfLengthException @@ -22,33 +17,44 @@ import com.mifos.mifosxdroid.R import com.mifos.mifosxdroid.core.MifosBaseActivity import com.mifos.mifosxdroid.core.MifosBaseFragment import com.mifos.mifosxdroid.databinding.FragmentCreateNewCenterBinding -import com.mifos.mifosxdroid.uihelpers.MFDatePicker -import com.mifos.mifosxdroid.uihelpers.MFDatePicker.OnDatePickListener import com.mifos.objects.organisation.Office import com.mifos.objects.response.SaveResponse import com.mifos.services.data.CenterPayload -import com.mifos.utils.DateHelper +import com.mifos.utils.DatePickerConstrainType import com.mifos.utils.FragmentConstants import com.mifos.utils.MifosResponseHandler import com.mifos.utils.ValidationUtil -import java.util.Collections +import com.mifos.utils.getDatePickerDialog +import com.mifos.utils.getTodayFormatted +import java.text.SimpleDateFormat +import java.time.Instant +import java.util.Locale import javax.inject.Inject /** * Created by nellyk on 1/22/2016. */ -class CreateNewCenterFragment : MifosBaseFragment(), OnDatePickListener, CreateNewCenterMvpView { +class CreateNewCenterFragment : MifosBaseFragment(), CreateNewCenterMvpView { private lateinit var binding: FragmentCreateNewCenterBinding - var officeId = 0 + var officeId: Int? = 0 var result = true @Inject lateinit var mCreateNewCenterPresenter: CreateNewCenterPresenter private var activationDateString: String? = null - private var newDatePicker: DialogFragment? = null private val officeNameIdHashMap = HashMap() + + private var activationDate: Instant = Instant.now() + private val submissionDatePickerDialog by lazy { + getDatePickerDialog(activationDate, DatePickerConstrainType.ONLY_FUTURE_DAYS) { + val formattedDate = SimpleDateFormat("dd MM yyyy", Locale.getDefault()).format(it) + activationDate = Instant.ofEpochMilli(it) + binding.activateDateFieldContainer.editText?.setText(formattedDate) + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (activity as MifosBaseActivity).activityComponent?.inject(this) @@ -73,13 +79,10 @@ class CreateNewCenterFragment : MifosBaseFragment(), OnDatePickListener, CreateN binding.cbCenterActiveStatus.setOnCheckedChangeListener { compoundButton, isChecked -> if (isChecked) { - binding.layoutSubmission.visibility = View.VISIBLE - activationDateString = binding.tvCenterActivationDate.text.toString() - activationDateString = - DateHelper.getDateAsStringUsedForCollectionSheetPayload(activationDateString) - .replace("-", " ") + binding.activateDateFieldContainer.visibility = View.VISIBLE + activationDateString = binding.activateDateFieldContainer.editText?.text.toString() } else { - binding.layoutSubmission.visibility = View.GONE + binding.activateDateFieldContainer.visibility = View.GONE } } binding.btnSubmit.setOnClickListener { @@ -92,6 +95,13 @@ class CreateNewCenterFragment : MifosBaseFragment(), OnDatePickListener, CreateN centerPayload.locale = "en" initiateCenterCreation(centerPayload) } + + binding.activateDateFieldContainer.setEndIconOnClickListener { + submissionDatePickerDialog.show( + requireActivity().supportFragmentManager, + FragmentConstants.DFRAG_DATE_PICKER + ) + } } //inflating office list spinner @@ -105,22 +115,11 @@ class CreateNewCenterFragment : MifosBaseFragment(), OnDatePickListener, CreateN } } - fun inflateActivationDate() { - newDatePicker = MFDatePicker.newInsance(this) - binding.tvCenterActivationDate.text = MFDatePicker.datePickedAsString - binding.tvCenterActivationDate.setOnClickListener { - (newDatePicker as MFDatePicker).show( - requireActivity().supportFragmentManager, - FragmentConstants.DFRAG_DATE_PICKER - ) - } - } - - override fun onDatePicked(date: String?) { - binding.tvCenterActivationDate.text = date + private fun inflateActivationDate() { + binding.activateDateFieldContainer.editText?.setText(getTodayFormatted()) } - val isCenterNameValid: Boolean + private val isCenterNameValid: Boolean get() { result = true try { @@ -168,29 +167,19 @@ class CreateNewCenterFragment : MifosBaseFragment(), OnDatePickListener, CreateN } } } - Collections.sort(officeList) - val officeAdapter = ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_item, officeList - ) - officeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spCenterOffices.adapter = officeAdapter - binding.spCenterOffices.onItemSelectedListener = object : OnItemSelectedListener { - override fun onItemSelected( - adapterView: AdapterView<*>?, - view: View, i: Int, l: Long - ) { - officeId = officeNameIdHashMap[officeList[i]]!! - Log.d("officeId " + officeList[i], officeId.toString()) - if (officeId != -1) { - } else { - Toast.makeText( - activity, getString(R.string.error_select_office), Toast.LENGTH_SHORT - ).show() - } - } + officeList.sort() + + binding.officeListField.setSimpleItems(officeList.toTypedArray()) - override fun onNothingSelected(parent: AdapterView<*>?) {} + binding.officeListField.setOnItemClickListener { adapterView, view, relativePosition, l -> + val index = officeList.indexOf(adapterView.getItemAtPosition(relativePosition)) + officeId = officeNameIdHashMap[officeList[index]] + if (officeId != -1) { + } else { + Toast.makeText( + activity, getString(R.string.error_select_office), Toast.LENGTH_SHORT + ).show() + } } } diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewclient/CreateNewClientFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewclient/CreateNewClientFragment.kt index 56cd5bf0dc0..88dc427ec99 100755 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewclient/CreateNewClientFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewclient/CreateNewClientFragment.kt @@ -20,10 +20,8 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.* -import android.widget.AdapterView.OnItemSelectedListener +import android.widget.Toast import androidx.appcompat.widget.PopupMenu -import androidx.fragment.app.DialogFragment import com.mifos.exceptions.InvalidTextInputException import com.mifos.exceptions.RequiredFieldException import com.mifos.mifosxdroid.R @@ -32,33 +30,26 @@ import com.mifos.mifosxdroid.core.ProgressableFragment import com.mifos.mifosxdroid.core.util.Toaster import com.mifos.mifosxdroid.databinding.FragmentCreateNewClientBinding import com.mifos.mifosxdroid.online.datatablelistfragment.DataTableListFragment -import com.mifos.mifosxdroid.uihelpers.MFDatePicker -import com.mifos.mifosxdroid.uihelpers.MFDatePicker.OnDatePickListener import com.mifos.objects.client.ClientPayload import com.mifos.objects.organisation.Office import com.mifos.objects.organisation.Staff import com.mifos.objects.templates.clients.ClientsTemplate import com.mifos.utils.Constants -import com.mifos.utils.DateHelper +import com.mifos.utils.DatePickerConstrainType import com.mifos.utils.FragmentConstants import com.mifos.utils.ValidationUtil +import com.mifos.utils.getDatePickerDialog +import com.mifos.utils.getTodayFormatted import java.io.File -import java.util.* +import java.text.SimpleDateFormat +import java.time.Instant +import java.util.Locale import javax.inject.Inject -class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, CreateNewClientMvpView, - OnItemSelectedListener { +class CreateNewClientFragment : ProgressableFragment(), CreateNewClientMvpView { private lateinit var binding: FragmentCreateNewClientBinding - private val LOG_TAG = javaClass.simpleName - - @JvmField - var datePickerSubmissionDate: DialogFragment? = null - - @JvmField - var datePickerDateOfBirth: DialogFragment? = null - @Inject lateinit var createNewClientPresenter: CreateNewClientPresenter @@ -66,39 +57,42 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea private var createClientWithImage = false private var hasDataTables = false private var returnedClientId: Int? = null - private var officeId : Int? = 0 - private var clientTypeId = 0 - private var staffId : Int? = 0 - private var genderId = 0 - private var clientClassificationId = 0 + private var officeId: Int? = 0 + private var clientTypeId: Int? = 0 + private var staffId: Int? = 0 + private var genderId: Int? = 0 + private var clientClassificationId: Int? = 0 private var result = true private var submissionDateString: String? = null private var dateOfBirthString: String? = null private var clientsTemplate: ClientsTemplate? = null private var clientOffices: List? = null private var clientStaff: List? = null - private var mCurrentDateView // the view whose click opened the date picker - : View? = null private var ClientImageFile: File? = null private var pickedImageUri: Uri? = null - private var genderOptionsList: MutableList? = null - private var clientClassificationList: MutableList? = null - private var clientTypeList: MutableList? = null - private var officeList: MutableList? = null - private var staffList: MutableList? = null - private var genderOptionsAdapter: ArrayAdapter? = null - private var clientClassificationAdapter: ArrayAdapter? = null - private var clientTypeAdapter: ArrayAdapter? = null - private var officeAdapter: ArrayAdapter? = null - private var staffAdapter: ArrayAdapter? = null + private var genderOptionsList: MutableList = ArrayList() + private var clientClassificationList: MutableList = ArrayList() + private var clientTypeList: MutableList = ArrayList() + private var officeList: MutableList = ArrayList() + private var staffList: MutableList = ArrayList() private var progress: ProgressDialog? = null - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - genderOptionsList = ArrayList() - clientClassificationList = ArrayList() - clientTypeList = ArrayList() - officeList = ArrayList() - staffList = ArrayList() + + private var submissionDate: Instant = Instant.now() + private val submissionDatePickerDialog by lazy { + getDatePickerDialog(dayOfBirthDate, DatePickerConstrainType.ONLY_FUTURE_DAYS) { + val formattedDate = SimpleDateFormat("dd MM yyyy", Locale.getDefault()).format(it) + submissionDate = Instant.ofEpochMilli(it) + binding.submissionDateFieldContainer.editText?.setText(formattedDate) + } + } + + private var dayOfBirthDate: Instant = Instant.now() + private val datePickerDialog by lazy { + getDatePickerDialog(dayOfBirthDate, DatePickerConstrainType.ONLY_PAST_DAYS) { + val formattedDate = SimpleDateFormat("dd MM yyyy", Locale.getDefault()).format(it) + dayOfBirthDate = Instant.ofEpochMilli(it) + binding.dateOfBirthFieldContainer.editText?.setText(formattedDate) + } } override fun onCreateView( @@ -117,62 +111,63 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.tvSubmissionDate.setOnClickListener { - onClickTextViewSubmissionDate() - } - - binding.tvDateofbirth.setOnClickListener { - onClickTextViewDateOfBirth() - } - binding.btnSubmit.setOnClickListener { onClickSubmitButton() } + binding.cbClientActiveStatus.setOnCheckedChangeListener { compoundButton, b -> onClickActiveCheckBox() } + + binding.genderListField.setOnItemClickListener { adapterView, view, relativePosition, l -> + val index = genderOptionsList.indexOf(adapterView.getItemAtPosition(relativePosition)) + genderId = clientsTemplate?.genderOptions?.get(index)?.id + } + + binding.dateOfBirthFieldContainer.setEndIconOnClickListener { + datePickerDialog.show( + requireActivity().supportFragmentManager, + FragmentConstants.DFRAG_DATE_PICKER + ) + } + + binding.clientTypeListField.setOnItemClickListener { adapterView, view, relativePosition, l -> + val index = clientTypeList.indexOf(adapterView.getItemAtPosition(relativePosition)) + clientTypeId = clientsTemplate?.clientTypeOptions?.get(index)?.id + } + + binding.clientClassificationListField.setOnItemClickListener { adapterView, view, relativePosition, l -> + val index = + clientClassificationList.indexOf(adapterView.getItemAtPosition(relativePosition)) + clientClassificationId = clientsTemplate?.clientClassificationOptions?.get(index)?.id + } + + binding.officeListField.setOnItemClickListener { adapterView, view, relativePosition, l -> + val index = officeList.indexOf(adapterView.getItemAtPosition(relativePosition)) + officeId = clientOffices?.get(index)?.id + officeId?.let { createNewClientPresenter.loadStaffInOffices(it) } + } + + binding.staffListField.setOnItemClickListener { adapterView, view, relativePosition, l -> + val index = staffList.indexOf(adapterView.getItemAtPosition(relativePosition)) + staffId = clientStaff?.get(index)?.id + } + + binding.submissionDateFieldContainer.setEndIconOnClickListener { + submissionDatePickerDialog.show( + requireActivity().supportFragmentManager, + FragmentConstants.DFRAG_DATE_PICKER + ) + } + } override fun showUserInterface() { - genderOptionsAdapter = ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_item, genderOptionsList ?: emptyList() - ) - genderOptionsAdapter?.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spGender.adapter = genderOptionsAdapter - binding.spGender.onItemSelectedListener = this - clientClassificationAdapter = ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_item, clientClassificationList ?: emptyList() - ) - clientClassificationAdapter?.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spClientClassification.adapter = clientClassificationAdapter - binding.spClientClassification.onItemSelectedListener = this - clientTypeAdapter = ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_item, clientTypeList ?: emptyList() - ) - clientTypeAdapter?.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spClientType.adapter = clientTypeAdapter - binding.spClientType.onItemSelectedListener = this - officeAdapter = ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_item, officeList ?: emptyList() - ) - officeAdapter?.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spOffices.adapter = officeAdapter - binding.spOffices.onItemSelectedListener = this - staffAdapter = ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_item, staffList ?: emptyList() - ) - staffAdapter?.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spStaff.adapter = staffAdapter - binding.spStaff.onItemSelectedListener = this - datePickerSubmissionDate = MFDatePicker.newInsance(this) - datePickerDateOfBirth = MFDatePicker.newInsance(this) - binding.tvSubmissionDate.text = MFDatePicker.datePickedAsString - binding.tvDateofbirth.text = MFDatePicker.datePickedAsString + + binding.submissionDateFieldContainer.editText?.setText(getTodayFormatted()) + + binding.dateOfBirthFieldContainer.editText?.setText(getTodayFormatted()) + binding.ivClientImage.setOnClickListener { view -> val menu = PopupMenu(requireActivity(), view) menu.menuInflater.inflate( @@ -220,31 +215,12 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea createClientWithImage = false } - private fun onClickTextViewSubmissionDate() { - datePickerSubmissionDate?.show( - requireActivity().supportFragmentManager, - FragmentConstants.DFRAG_DATE_PICKER - ) - mCurrentDateView = binding.tvSubmissionDate - } - private fun onClickTextViewDateOfBirth() { - datePickerDateOfBirth?.show( - requireActivity().supportFragmentManager, - FragmentConstants.DFRAG_DATE_PICKER - ) - mCurrentDateView = binding.tvDateofbirth - } + private fun onClickSubmitButton() { + submissionDateString = binding.dateOfBirthFieldContainer.editText?.text.toString() + dateOfBirthString = binding.dateOfBirthFieldContainer.editText?.text.toString() - private fun onClickSubmitButton() { - submissionDateString = binding.tvSubmissionDate.text.toString() - submissionDateString = DateHelper - .getDateAsStringUsedForCollectionSheetPayload(submissionDateString) - .replace("-", " ") - dateOfBirthString = binding.tvDateofbirth.text.toString() - dateOfBirthString = DateHelper.getDateAsStringUsedForDateofBirth(dateOfBirthString) - .replace("-", " ") val clientPayload = ClientPayload() //Mandatory Fields @@ -268,16 +244,16 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea if (!TextUtils.isEmpty(binding.etClientExternalId.editableText.toString())) { clientPayload.externalId = binding.etClientExternalId.editableText.toString() } - if (clientStaff!!.isNotEmpty()) { + if (clientStaff?.isNotEmpty() == true) { clientPayload.staffId = staffId } - if (genderOptionsList!!.isNotEmpty()) { + if (genderOptionsList.isNotEmpty()) { clientPayload.genderId = genderId } - if (clientTypeList!!.isNotEmpty()) { + if (clientTypeList.isNotEmpty()) { clientPayload.clientTypeId = clientTypeId } - if (clientClassificationList!!.isNotEmpty()) { + if (clientClassificationList.isNotEmpty()) { clientPayload.clientClassificationId = clientClassificationId } if (!isFirstNameValid) { @@ -305,18 +281,10 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea } private fun onClickActiveCheckBox() { - binding.layoutSubmission.visibility = + binding.submissionDateFieldContainer.visibility = if (binding.cbClientActiveStatus.isChecked) View.VISIBLE else View.GONE } - override fun onDatePicked(date: String?) { - if (mCurrentDateView != null && mCurrentDateView === binding.tvSubmissionDate) { - binding.tvSubmissionDate.text = date - } else if (mCurrentDateView != null && mCurrentDateView === binding.tvDateofbirth) { - binding.tvDateofbirth.text = date - } - } - override fun showClientTemplate(clientsTemplate: ClientsTemplate?) { this.clientsTemplate = clientsTemplate if (clientsTemplate != null) { @@ -324,26 +292,28 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea hasDataTables = true } } - genderOptionsList?.addAll( + genderOptionsList.addAll( createNewClientPresenter.filterOptions(clientsTemplate?.genderOptions) ) - genderOptionsAdapter?.notifyDataSetChanged() - clientTypeList?.addAll( + binding.genderListField.setSimpleItems(genderOptionsList.toTypedArray()) + + clientTypeList.addAll( createNewClientPresenter.filterOptions(clientsTemplate?.clientTypeOptions) ) - clientTypeAdapter?.notifyDataSetChanged() - clientClassificationList?.addAll( + binding.clientTypeListField.setSimpleItems(clientTypeList.toTypedArray()) + + clientClassificationList.addAll( createNewClientPresenter .filterOptions(clientsTemplate?.clientClassificationOptions) ) - clientClassificationAdapter?.notifyDataSetChanged() + binding.clientTypeListField.setSimpleItems(clientTypeList.toTypedArray()) } override fun showOffices(offices: List?) { clientOffices = offices as List? - officeList?.addAll(createNewClientPresenter.filterOffices(offices)) - Collections.sort(officeList) - officeAdapter?.notifyDataSetChanged() + officeList.addAll(createNewClientPresenter.filterOffices(offices)) + officeList.sort() + binding.officeListField.setSimpleItems(officeList.toTypedArray()) } override fun showStaffInOffices(staffs: List?) { @@ -353,9 +323,9 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea } } clientStaff = staffs as List? - staffList?.clear() - staffList?.addAll(createNewClientPresenter.filterStaff(staffs)) - staffAdapter?.notifyDataSetChanged() + staffList.clear() + staffList.addAll(createNewClientPresenter.filterStaff(staffs)) + binding.staffListField.setSimpleItems(staffList.toTypedArray()) } override fun showClientCreatedSuccessfully(message: Int) { @@ -384,23 +354,7 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea createNewClientPresenter.detachView() } - override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { - when (parent.id) { - R.id.sp_offices -> { - officeId = clientOffices!![position].id - officeId?.let { createNewClientPresenter.loadStaffInOffices(it) } - } - - R.id.sp_gender -> genderId = clientsTemplate!!.genderOptions[position].id - R.id.sp_client_type -> clientTypeId = clientsTemplate!!.clientTypeOptions[position].id - R.id.sp_staff -> staffId = clientStaff!![position].id - R.id.sp_client_classification -> clientClassificationId = - clientsTemplate!!.clientClassificationOptions[position].id - } - } - - override fun onNothingSelected(parent: AdapterView<*>?) {} - val isFirstNameValid: Boolean + private val isFirstNameValid: Boolean get() { result = true try { @@ -427,7 +381,7 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea return result } - val isMiddleNameValid: Boolean + private val isMiddleNameValid: Boolean get() { result = true try { @@ -450,7 +404,7 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea return result } - val isLastNameValid: Boolean + private val isLastNameValid: Boolean get() { result = true try { @@ -545,7 +499,7 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea requestCode: Int, permissions: Array, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) - if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && requestCode == READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) { + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED && requestCode == READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) { uploadClientImageFromDevice() } } @@ -554,13 +508,5 @@ class CreateNewClientFragment : ProgressableFragment(), OnDatePickListener, Crea private const val CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 1 private const val PICK_IMAGE_ACTIVITY_REQUEST_CODE = 2 private const val READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 3 - - @JvmStatic - fun newInstance(): CreateNewClientFragment { - val createNewClientFragment = CreateNewClientFragment() - val args = Bundle() - createNewClientFragment.arguments = args - return createNewClientFragment - } } } \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewgroup/CreateNewGroupFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewgroup/CreateNewGroupFragment.kt index ad4278cdb3e..95eedb25f81 100755 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewgroup/CreateNewGroupFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/createnewgroup/CreateNewGroupFragment.kt @@ -31,42 +31,55 @@ import com.mifos.objects.organisation.Office import com.mifos.objects.response.SaveResponse import com.mifos.utils.Constants import com.mifos.utils.DateHelper +import com.mifos.utils.DatePickerConstrainType import com.mifos.utils.FragmentConstants import com.mifos.utils.MifosResponseHandler import com.mifos.utils.Network import com.mifos.utils.PrefManager import com.mifos.utils.ValidationUtil +import com.mifos.utils.getDatePickerDialog +import com.mifos.utils.getTodayFormatted +import java.text.SimpleDateFormat +import java.time.Instant +import java.util.Locale import javax.inject.Inject /** * Created by nellyk on 1/22/2016. */ //TODO Show Image and Text after successful or Failed during creation of Group and //TODO A button to Continue or Finish the GroupCreation. -class CreateNewGroupFragment : ProgressableFragment(), OnDatePickListener, CreateNewGroupMvpView, - OnItemSelectedListener { +class CreateNewGroupFragment : ProgressableFragment(), CreateNewGroupMvpView { private lateinit var binding: FragmentCreateNewGroupBinding - private val LOG_TAG = javaClass.simpleName - @Inject lateinit var mCreateNewGroupPresenter: CreateNewGroupPresenter - var activationDateString: String? = null + private var activationDateString: String? = null var officeId : Int? = 0 var result = true - var dateofsubmissionstring: String? = null - private var mfDatePicker: DialogFragment? = null - private var newDatePicker: DialogFragment? = null + private var dateofsubmissionstring: String? = null private val mListOffices: MutableList = ArrayList() - private var officeList: List? = null - private var mOfficesAdapter: ArrayAdapter? = null - override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { - if (parent.id == R.id.sp_group_offices) { - officeId = officeList!![position].id + private var officeList: List = ArrayList() + + private var submissionDate: Instant = Instant.now() + private val submissionDatePickerDialog by lazy { + getDatePickerDialog(submissionDate, DatePickerConstrainType.ONLY_FUTURE_DAYS) { + val formattedDate = SimpleDateFormat("dd MM yyyy", Locale.getDefault()).format(it) + submissionDate = Instant.ofEpochMilli(it) + binding.submittedDateFieldContainer.editText?.setText(formattedDate) + dateofsubmissionstring = binding.submittedDateFieldContainer.editText.toString() + } + } + private var activationDate: Instant = Instant.now() + private val activationDatePickerDialog by lazy { + getDatePickerDialog(activationDate, DatePickerConstrainType.ONLY_FUTURE_DAYS) { + val formattedDate = SimpleDateFormat("dd MM yyyy", Locale.getDefault()).format(it) + activationDate = Instant.ofEpochMilli(it) + binding.activateDateFieldContainer.editText?.setText(formattedDate) + activationDateString = binding.activateDateFieldContainer.editText.toString() } } - override fun onNothingSelected(parent: AdapterView<*>?) {} override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (activity as MifosBaseActivity).activityComponent?.inject(this) @@ -79,20 +92,16 @@ class CreateNewGroupFragment : ProgressableFragment(), OnDatePickListener, Creat ): View { binding = FragmentCreateNewGroupBinding.inflate(inflater, container, false) mCreateNewGroupPresenter.attachView(this) - inflateOfficesSpinner() inflateSubmissionDate() inflateActivationDate() mCreateNewGroupPresenter.loadOffices() //client active checkbox onCheckedListener + dateofsubmissionstring = getTodayFormatted() + binding.submittedDateFieldContainer.editText?.setText(getTodayFormatted()) - activationDateString = binding.tvGroupActivationDate.text.toString() - activationDateString = - DateHelper.getDateAsStringUsedForCollectionSheetPayload(activationDateString) - .replace("-", " ") - dateofsubmissionstring = binding.tvGroupSubmissionDate.text.toString() - dateofsubmissionstring = - DateHelper.getDateAsStringUsedForDateofBirth(dateofsubmissionstring).replace("-", " ") + activationDateString = getTodayFormatted() + binding.activateDateFieldContainer.editText?.setText(getTodayFormatted()) return binding.root } @@ -119,11 +128,16 @@ class CreateNewGroupFragment : ProgressableFragment(), OnDatePickListener, Creat binding.cbGroupActiveStatus.setOnCheckedChangeListener { compoundButton, isChecked -> if (isChecked) { - binding.layoutSubmission.visibility = View.VISIBLE + binding.activateDateFieldContainer.visibility = View.VISIBLE } else { - binding.layoutSubmission.visibility = View.GONE + binding.activateDateFieldContainer.visibility = View.GONE } } + + binding.officeListField.setOnItemClickListener { adapterView, view, relativePosition, l -> + val index = mListOffices.indexOf(adapterView.getItemAtPosition(relativePosition)) + officeId = officeList[index].id + } } private fun initiateGroupCreation(groupPayload: GroupPayload) { @@ -134,21 +148,9 @@ class CreateNewGroupFragment : ProgressableFragment(), OnDatePickListener, Creat mCreateNewGroupPresenter.createGroup(groupPayload) } - private fun inflateOfficesSpinner() { - mOfficesAdapter = ArrayAdapter( - requireActivity(), android.R.layout.simple_spinner_item, - mListOffices - ) - mOfficesAdapter?.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spGroupOffices.adapter = mOfficesAdapter - binding.spGroupOffices.onItemSelectedListener = this - } - private fun inflateSubmissionDate() { - mfDatePicker = MFDatePicker.newInsance(this) - binding.tvGroupSubmissionDate.text = MFDatePicker.datePickedAsString - binding.tvGroupSubmissionDate.setOnClickListener { - (mfDatePicker as MFDatePicker?)?.show( + binding.submittedDateFieldContainer.setEndIconOnClickListener { + submissionDatePickerDialog.show( requireActivity().supportFragmentManager, FragmentConstants.DFRAG_DATE_PICKER ) @@ -156,21 +158,14 @@ class CreateNewGroupFragment : ProgressableFragment(), OnDatePickListener, Creat } private fun inflateActivationDate() { - newDatePicker = MFDatePicker.newInsance(this) - binding.tvGroupActivationDate.text = MFDatePicker.datePickedAsString - binding.tvGroupActivationDate.setOnClickListener { - (newDatePicker as MFDatePicker?)?.show( + binding.activateDateFieldContainer.setEndIconOnClickListener { + activationDatePickerDialog.show( requireActivity().supportFragmentManager, FragmentConstants.DFRAG_DATE_PICKER ) } } - override fun onDatePicked(date: String?) { - binding.tvGroupSubmissionDate.text = date - binding.tvGroupActivationDate.text = date - } - private val isGroupNameValid: Boolean get() { result = true @@ -208,14 +203,12 @@ class CreateNewGroupFragment : ProgressableFragment(), OnDatePickListener, Creat } override fun showOffices(offices: List?) { - officeList = offices as List? - if (offices != null) { - for (office in offices) { - office.name?.let { mListOffices.add(it) } - } + officeList = offices as List + for (office in offices) { + office.name?.let { mListOffices.add(it) } } mListOffices.sort() - mOfficesAdapter?.notifyDataSetChanged() + binding.officeListField.setSimpleItems(mListOffices.toTypedArray()) } override fun showGroupCreatedSuccessfully(group: SaveResponse?) { diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/generatecollectionsheet/GenerateCollectionSheetFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/generatecollectionsheet/GenerateCollectionSheetFragment.kt index e643080954b..415a7e04a5d 100755 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/generatecollectionsheet/GenerateCollectionSheetFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/generatecollectionsheet/GenerateCollectionSheetFragment.kt @@ -12,15 +12,11 @@ import android.view.LayoutInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup -import android.widget.AdapterView -import android.widget.AdapterView.OnItemSelectedListener -import android.widget.ArrayAdapter import android.widget.EditText import android.widget.LinearLayout import android.widget.Spinner import android.widget.TableRow import android.widget.TextView -import androidx.fragment.app.DialogFragment import com.mifos.api.model.BulkRepaymentTransactions import com.mifos.api.model.ClientsAttendance import com.mifos.mifosxdroid.R @@ -28,8 +24,6 @@ import com.mifos.mifosxdroid.core.MifosBaseActivity import com.mifos.mifosxdroid.core.MifosBaseFragment import com.mifos.mifosxdroid.core.util.Toaster import com.mifos.mifosxdroid.databinding.FragmentGenerateCollectionSheetBinding -import com.mifos.mifosxdroid.uihelpers.MFDatePicker -import com.mifos.mifosxdroid.uihelpers.MFDatePicker.OnDatePickListener import com.mifos.objects.collectionsheet.BulkSavingsDueTransaction import com.mifos.objects.collectionsheet.CenterDetail import com.mifos.objects.collectionsheet.CollectionSheetPayload @@ -42,13 +36,17 @@ import com.mifos.objects.group.Group import com.mifos.objects.organisation.Office import com.mifos.objects.organisation.Staff import com.mifos.utils.Constants -import com.mifos.utils.DateHelper +import com.mifos.utils.DatePickerConstrainType import com.mifos.utils.FragmentConstants +import com.mifos.utils.getDatePickerDialog +import com.mifos.utils.getTodayFormatted +import java.text.SimpleDateFormat +import java.time.Instant import java.util.Locale import javax.inject.Inject class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionSheetMvpView, - OnItemSelectedListener, View.OnClickListener, OnDatePickListener { + View.OnClickListener { private lateinit var binding: FragmentGenerateCollectionSheetBinding @@ -59,7 +57,6 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS @Inject lateinit var presenter: GenerateCollectionSheetPresenter - private var datePicker: DialogFragment? = null private var officeNameIdHashMap = HashMap() private var staffNameIdHashMap = HashMap() private var centerNameIdHashMap = HashMap() @@ -76,9 +73,18 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS private var groupId = -1 private var staffId = -1 + private var selectedRepaymentDate: Instant = Instant.now() + private val datePickerDialog by lazy { + getDatePickerDialog(selectedRepaymentDate, DatePickerConstrainType.ONLY_FUTURE_DAYS) { + val formattedDate = SimpleDateFormat("dd MM yyyy", Locale.getDefault()).format(it) + selectedRepaymentDate = Instant.ofEpochMilli(it) + binding.meetingDateFieldContainer.editText?.setText(formattedDate) + } + } + //id of the center whose Productive CollectionSheet has to be retrieved. - private var productiveCenterId : Int? = -1 - private var calendarId : Int? = -1 + private var productiveCenterId: Int? = -1 + private var calendarId: Int? = -1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (activity as MifosBaseActivity).activityComponent?.inject(this) @@ -122,10 +128,6 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS companion object { - fun newInstance(): GenerateCollectionSheetFragment { - return GenerateCollectionSheetFragment() - } - const val LIMIT = "limit" const val ORDER_BY = "orderBy" const val SORT_ORDER = "sortOrder" @@ -152,72 +154,52 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS if (activity == null) return officeNameIdHashMap = presenter.createOfficeNameIdMap(offices, officeNames as MutableList) - setSpinner(binding.spBranchOffices, officeNames) - binding.spBranchOffices.onItemSelectedListener = this + binding.officeField.setSimpleItems(officeNames.toTypedArray()) + binding.officeField.setOnItemClickListener { _, _, i, _ -> + officeId = officeNameIdHashMap[officeNames[i]]!! + if (officeId != -1) { + inflateStaffSpinner(officeId) + inflateCenterSpinner(officeId, -1) + inflateGroupSpinner(officeId, -1) + } else { + Toaster.show(binding.root, getString(R.string.error_select_office)) + } + } } override fun showStaffInOffice(staffs: List, officeId: Int) { this.officeId = officeId - staffNameIdHashMap = - presenter.createStaffIdMap(staffs, staffNames as MutableList) - setSpinner(binding.spStaff, staffNames) - binding.spStaff.onItemSelectedListener = this + staffNameIdHashMap = presenter.createStaffIdMap(staffs, staffNames as MutableList) + binding.staffField.setSimpleItems(staffNames.toTypedArray()) + binding.staffField.setOnItemClickListener { _, _, i, _ -> + staffId = staffNameIdHashMap[staffNames[i]]!! + if (staffId != -1) { + inflateCenterSpinner(officeId, staffId) + inflateGroupSpinner(officeId, staffId) + } else { + Toaster.show(binding.root, getString(R.string.error_select_staff)) + } + } staffId = -1 //Reset staff id } override fun showCentersInOffice(centers: List
) { centerNameIdHashMap = presenter.createCenterIdMap(centers, centerNames as MutableList) - setSpinner(binding.spCenters, centerNames) - binding.spCenters.onItemSelectedListener = this - centerId = -1 //Reset Center id. - } - - override fun onItemSelected(adapterView: AdapterView<*>, view: View, i: Int, l: Long) { - when (adapterView.id) { - R.id.sp_centers -> { - centerId = centerNameIdHashMap.get(centerNames[i])!! - if (centerId != -1) { - inflateGroupSpinner(centerId) - } else { - Toaster.show(binding.root, getString(R.string.error_select_center)) - } - } - - R.id.sp_staff -> { - staffId = staffNameIdHashMap.get(staffNames[i])!! - if (staffId != -1) { - inflateCenterSpinner(officeId, staffId) - inflateGroupSpinner(officeId, staffId) - } else { - Toaster.show(binding.root, getString(R.string.error_select_staff)) - } - } - - R.id.sp_branch_offices -> { - officeId = officeNameIdHashMap.get(officeNames[i])!! - if (officeId != -1) { - inflateStaffSpinner(officeId) - inflateCenterSpinner(officeId, -1) - inflateGroupSpinner(officeId, -1) - } else { - Toaster.show(binding.root, getString(R.string.error_select_office)) - } - } - - R.id.sp_groups -> { - groupId = groupNameIdHashMap.get(groupNames[i])!! - if (groupId == -1) { - Toaster.show(binding.root, getString(R.string.error_select_group)) - } + binding.centerField.setSimpleItems(centerNames.toTypedArray()) + binding.centerField.setOnItemClickListener { _, _, i, _ -> + centerId = centerNameIdHashMap[centerNames[i]]!! + if (centerId != -1) { + inflateGroupSpinner(centerId) + } else { + Toaster.show(binding.root, getString(R.string.error_select_center)) } } + centerId = -1 //Reset Center id. } - override fun onNothingSelected(adapterView: AdapterView<*>?) {} override fun onClick(view: View) { when (view.id) { - R.id.tv_meeting_date -> setMeetingDate() R.id.btn_generate_collection_sheet -> fetchCollectionSheet() R.id.btn_generate_productive_collection_sheet -> fetchCenterDetails() R.id.btn_submit_productive -> when (view.tag as Int) { @@ -230,7 +212,7 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS private fun setUpUi() { inflateOfficeSpinner() inflateMeetingDate() - binding.tvMeetingDate.setOnClickListener(this) + binding.meetingDateFieldContainer.setOnClickListener(this) binding.btnGenerateProductiveCollectionSheet.setOnClickListener(this) binding.btnGenerateCollectionSheet.setOnClickListener(this) } @@ -241,7 +223,7 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS return } val requestPayload = CollectionSheetRequestPayload() - requestPayload.transactionDate = binding.tvMeetingDate.text.toString() + requestPayload.transactionDate = binding.meetingDateFieldContainer.editText?.text.toString() requestPayload.calendarId = calendarId presenter.loadCollectionSheet(groupId, requestPayload) } @@ -249,7 +231,7 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS private fun fetchProductiveCollectionSheet() { //Make RequestPayload and retrieve Productive CollectionSheet. val requestPayload = CollectionSheetRequestPayload() - requestPayload.transactionDate = binding.tvMeetingDate.text.toString() + requestPayload.transactionDate = binding.meetingDateFieldContainer.editText?.text.toString() requestPayload.calendarId = calendarId productiveCenterId?.let { presenter.loadProductiveCollectionSheet(it, requestPayload) } } @@ -257,7 +239,7 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS private fun fetchCenterDetails() { presenter.loadCenterDetails( Constants.DATE_FORMAT_LONG, Constants.LOCALE_EN, - binding.tvMeetingDate.text.toString(), officeId, staffId + binding.meetingDateFieldContainer.editText?.text.toString(), officeId, staffId ) } @@ -389,7 +371,7 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS productContainer.orientation = LinearLayout.HORIZONTAL //Iterate through all the Savings in of this type and add in the container - for (saving in clientCollectionSheet.savings!!) { + for (saving in clientCollectionSheet.savings) { if (saving.productId == product.id) { //Add the saving in the container val editText = EditText(context) @@ -405,11 +387,6 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS } row.addView(productContainer) } - val spAttendance = Spinner(context) - //Set the clientId as its tag which will be used as identifier later. - spAttendance.tag = clientCollectionSheet.clientId - setSpinner(spAttendance, attendanceTypes) - row.addView(spAttendance) binding.tableSheet.addView(row) } if (binding.btnSubmitProductive.visibility != View.VISIBLE) { @@ -429,9 +406,6 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS val tvLabelPayment = TextView(context) tvLabelPayment.text = getString(R.string.payment_type) rowPayment.addView(tvLabelPayment) - val spPayment = Spinner(context) - setSpinner(spPayment, paymentTypes) - rowPayment.addView(spPayment) binding.tableAdditional.addView(rowPayment) val rowAccount = TableRow(context) val tvLabelAccount = TextView(context) @@ -562,9 +536,6 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS } row.addView(productContainer) } - val spAttendance = Spinner(context) - setSpinner(spAttendance, attendanceTypes) - row.addView(spAttendance) binding.tableSheet.addView(row) } if (binding.btnSubmitProductive.visibility != View.VISIBLE) { @@ -581,7 +552,7 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS private fun submitProductiveSheet() { val payload = ProductiveCollectionSheetPayload() payload.calendarId = calendarId - payload.transactionDate = binding.tvMeetingDate.text.toString() + payload.transactionDate = binding.meetingDateFieldContainer.editText?.text.toString() for (i in 0 until binding.tableSheet.childCount) { //In the tableRows which depicts the details of that client. //Loop through all the view of this TableRows. @@ -619,8 +590,8 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS private fun submitCollectionSheet() { val payload = CollectionSheetPayload() payload.calendarId = calendarId - payload.transactionDate = binding.tvMeetingDate.text.toString() - payload.actualDisbursementDate = binding.tvMeetingDate.text.toString() + payload.transactionDate = binding.meetingDateFieldContainer.editText?.text.toString() + payload.actualDisbursementDate = binding.meetingDateFieldContainer.editText?.text.toString() for (i in 0 until binding.tableSheet.childCount) { //In the tableRows which depicts the details of that client. //Loop through all the view of this TableRows. @@ -700,48 +671,31 @@ class GenerateCollectionSheetFragment : MifosBaseFragment(), GenerateCollectionS } private fun inflateMeetingDate() { - datePicker = MFDatePicker.newInsance(this) - val date = - DateHelper.getDateAsStringUsedForCollectionSheetPayload(MFDatePicker.datePickedAsString) - binding.tvMeetingDate.text = date.replace('-', ' ') - } - - private fun setMeetingDate() { - datePicker?.show( - requireActivity().supportFragmentManager, - FragmentConstants.DFRAG_DATE_PICKER - ) - } - - override fun onDatePicked(date: String?) { - val newDate = DateHelper.getDateAsStringUsedForCollectionSheetPayload(date) - binding.tvMeetingDate.text = newDate.replace('-', ' ') + binding.meetingDateFieldContainer.editText?.setText(getTodayFormatted()) + binding.meetingDateFieldContainer.setEndIconOnClickListener { + datePickerDialog.show( + requireActivity().supportFragmentManager, + FragmentConstants.DFRAG_DATE_PICKER + ) + } } override fun showGroupsInOffice(groups: List) { - groupNameIdHashMap = - presenter.createGroupIdMap(groups, groupNames as MutableList) - setSpinner(binding.spGroups, groupNames) + groupNameIdHashMap = presenter.createGroupIdMap(groups, groupNames as MutableList) + binding.groupField.setSimpleItems(groupNames.toTypedArray()) } override fun showGroupByCenter(centerWithAssociations: CenterWithAssociations) { groupNameIdHashMap = presenter.createGroupIdMap( centerWithAssociations.groupMembers, groupNames as MutableList ) - setSpinner(binding.spGroups, groupNames) - calendarId = centerWithAssociations.collectionMeetingCalendar.id - groupId = -1 //Reset group Id - binding.spGroups.onItemSelectedListener = this - } - - private fun setSpinner(spinner: Spinner?, values: List) { - val adapter = ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_item, values - ) - adapter.notifyDataSetChanged() - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - spinner?.adapter = adapter + binding.groupField.setSimpleItems(groupNames.toTypedArray()) + binding.groupField.setOnItemClickListener { _, _, i, _ -> + groupId = groupNameIdHashMap[groupNames[i]]!! + if (groupId == -1) { + Toaster.show(binding.root, getString(R.string.error_select_group)) + } + } } override fun showError(s: String?) { diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/runreports/reportcategory/ReportCategoryFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/runreports/reportcategory/ReportCategoryFragment.kt index f37a17def0b..1d7f58b727e 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/runreports/reportcategory/ReportCategoryFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/runreports/reportcategory/ReportCategoryFragment.kt @@ -9,15 +9,12 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.navigation.fragment.findNavController -import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager -import com.mifos.mifosxdroid.R import com.mifos.mifosxdroid.adapters.ClientReportAdapter import com.mifos.mifosxdroid.core.MifosBaseActivity import com.mifos.mifosxdroid.core.MifosBaseFragment import com.mifos.mifosxdroid.core.util.Toaster.show import com.mifos.mifosxdroid.databinding.FragmentRunreportBinding -import com.mifos.mifosxdroid.online.runreports.reportdetail.ReportDetailFragment import com.mifos.objects.runreports.client.ClientReportTypeItem import com.mifos.utils.Constants import javax.inject.Inject @@ -77,11 +74,7 @@ class ReportCategoryFragment : MifosBaseFragment(), ReportCategoryMvpView { override fun showReportCategories(reportTypes: List) { reportTypeItems = reportTypes val layoutManager = LinearLayoutManager(context) - val dividerItemDecoration = DividerItemDecoration( - binding.recyclerReport.context, layoutManager.orientation - ) binding.recyclerReport.layoutManager = layoutManager - binding.recyclerReport.addItemDecoration(dividerItemDecoration) reportAdapter = ClientReportAdapter { position: Int -> openDetailFragment(position) null diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/search/SearchFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/search/SearchFragment.kt index 39da6458a04..b6643a00c5e 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/search/SearchFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/search/SearchFragment.kt @@ -12,12 +12,11 @@ import android.view.ViewGroup import android.view.animation.Animation import android.view.animation.AnimationUtils import android.view.inputmethod.EditorInfo -import android.widget.AdapterView -import android.widget.AdapterView.OnItemSelectedListener import android.widget.ArrayAdapter import android.widget.Toast import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.mifos.mifosxdroid.HomeActivity import com.mifos.mifosxdroid.R import com.mifos.mifosxdroid.adapters.SearchAdapter @@ -33,7 +32,8 @@ import uk.co.deanwild.materialshowcaseview.MaterialShowcaseSequence import uk.co.deanwild.materialshowcaseview.ShowcaseConfig import javax.inject.Inject -class SearchFragment : MifosBaseFragment(), SearchMvpView, OnItemSelectedListener { + +class SearchFragment : MifosBaseFragment(), SearchMvpView { private lateinit var binding: FragmentClientSearchBinding @@ -48,13 +48,14 @@ class SearchFragment : MifosBaseFragment(), SearchMvpView, OnItemSelectedListene private var autoTriggerSearch = false private lateinit var searchedEntities: MutableList private lateinit var searchOptionsAdapter: ArrayAdapter - private lateinit var resources: String + private var resources: String? = null private var isFabOpen = false private lateinit var fabOpen: Animation private lateinit var fabClose: Animation private lateinit var rotateForward: Animation private lateinit var rotateBackward: Animation private lateinit var layoutManager: LinearLayoutManager + private var checkedFilter = 0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (activity as MifosBaseActivity).activityComponent?.inject(this) @@ -131,14 +132,32 @@ class SearchFragment : MifosBaseFragment(), SearchMvpView, OnItemSelectedListene } } + private fun showFilterDialog() { + val dialogBuilder = MaterialAlertDialogBuilder(requireContext()) + dialogBuilder.setSingleChoiceItems( + R.array.search_options, + checkedFilter + ) { dialog, index -> + checkedFilter = index + resources = if (checkedFilter == 0) null else searchOptionsValues[checkedFilter - 1] + autoTriggerSearch = true + onClickSearch() + binding.filterSelectionButton.text = + getResources().getStringArray(R.array.search_options)[index] + dialog.dismiss() + } + dialogBuilder.show() + } + override fun showUserInterface() { searchOptionsAdapter = ArrayAdapter.createFromResource( (requireActivity()), R.array.search_options, android.R.layout.simple_spinner_item ) searchOptionsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - binding.spSearch.adapter = searchOptionsAdapter - binding.spSearch.onItemSelectedListener = this + binding.filterSelectionButton.setOnClickListener { showFilterDialog() } + binding.filterSelectionButton.text = + getResources().getStringArray(R.array.search_options)[0] binding.etSearch.requestFocus() layoutManager = LinearLayoutManager(activity) layoutManager.orientation = LinearLayoutManager.VERTICAL @@ -210,7 +229,7 @@ class SearchFragment : MifosBaseFragment(), SearchMvpView, OnItemSelectedListene etSearchIntro, getString(R.string.got_it) ) sequence.addSequenceItem( - binding.spSearch, + binding.filterSelectionButton, spSearchIntro, getString(R.string.next) ) sequence.addSequenceItem( @@ -260,22 +279,6 @@ class SearchFragment : MifosBaseFragment(), SearchMvpView, OnItemSelectedListene super.onPause() } - override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) { - if (view != null && parent.id == R.id.sp_search) { - resources = if (position == 0) { - (searchOptionsValues[0] + "," + searchOptionsValues[1] + "," + - searchOptionsValues[2] + "," + searchOptionsValues[3] + "," + - searchOptionsValues[4]) - } else { - searchOptionsValues[position - 1] - } - autoTriggerSearch = true - onClickSearch() - } - } - - override fun onNothingSelected(parent: AdapterView<*>?) {} - /** * There is a need for this method in the following cases : * diff --git a/mifosng-android/src/main/java/com/mifos/services/data/CenterPayload.kt b/mifosng-android/src/main/java/com/mifos/services/data/CenterPayload.kt index b684d764bc6..f93febd820c 100644 --- a/mifosng-android/src/main/java/com/mifos/services/data/CenterPayload.kt +++ b/mifosng-android/src/main/java/com/mifos/services/data/CenterPayload.kt @@ -38,7 +38,7 @@ data class CenterPayload( var name: String? = null, @Column - var officeId: Int = 0, + var officeId: Int? = null, @Column var active: Boolean = false, diff --git a/mifosng-android/src/main/java/com/mifos/utils/MifosDatePicker.kt b/mifosng-android/src/main/java/com/mifos/utils/MifosDatePicker.kt new file mode 100644 index 00000000000..ba30b0761e0 --- /dev/null +++ b/mifosng-android/src/main/java/com/mifos/utils/MifosDatePicker.kt @@ -0,0 +1,44 @@ +package com.mifos.utils + +import com.google.android.material.datepicker.CalendarConstraints +import com.google.android.material.datepicker.DateValidatorPointBackward +import com.google.android.material.datepicker.DateValidatorPointForward +import com.google.android.material.datepicker.MaterialDatePicker +import java.text.SimpleDateFormat +import java.time.Instant +import java.util.Calendar +import java.util.Locale + +/* + created by Aditya Gupta on 02/08/2023 + */ + +enum class DatePickerConstrainType { + ONLY_FUTURE_DAYS, ONLY_PAST_DAYS, NONE +} + +fun getDatePickerDialog( + selectedInstant: Instant = Instant.now(), + constrainType: DatePickerConstrainType = DatePickerConstrainType.NONE, + onDatePick: (dateLong: Long) -> Unit = {}, +): MaterialDatePicker { + val constrainsBuilder = CalendarConstraints.Builder().apply { + when (constrainType) { + DatePickerConstrainType.ONLY_FUTURE_DAYS -> setValidator(DateValidatorPointForward.now()) + DatePickerConstrainType.ONLY_PAST_DAYS -> setValidator(DateValidatorPointBackward.now()) + DatePickerConstrainType.NONE -> {} + } + } + + val dialog = MaterialDatePicker.Builder.datePicker() + .setSelection(selectedInstant.toEpochMilli()) + .setCalendarConstraints(constrainsBuilder.build()) + .build() + dialog.addOnPositiveButtonClickListener { + onDatePick(it) + } + return dialog +} + +fun getTodayFormatted(): String = + SimpleDateFormat("dd MM yyyy", Locale.getDefault()).format(Calendar.getInstance().time) \ No newline at end of file diff --git a/mifosng-android/src/main/res/drawable/baseline_arrow_drop_down_24.xml b/mifosng-android/src/main/res/drawable/baseline_arrow_drop_down_24.xml new file mode 100644 index 00000000000..c1c897af75a --- /dev/null +++ b/mifosng-android/src/main/res/drawable/baseline_arrow_drop_down_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/mifosng-android/src/main/res/drawable/circular_bg_gray.xml b/mifosng-android/src/main/res/drawable/circular_bg_gray.xml index bdeb6229590..d160eada358 100644 --- a/mifosng-android/src/main/res/drawable/circular_bg_gray.xml +++ b/mifosng-android/src/main/res/drawable/circular_bg_gray.xml @@ -4,7 +4,7 @@ android:shape="oval"> + android:color="@color/baby_blue"/> + + + \ No newline at end of file diff --git a/mifosng-android/src/main/res/drawable/ic_website.xml b/mifosng-android/src/main/res/drawable/ic_website.xml new file mode 100644 index 00000000000..c388cb8e8d3 --- /dev/null +++ b/mifosng-android/src/main/res/drawable/ic_website.xml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/mifosng-android/src/main/res/layout/activity_about.xml b/mifosng-android/src/main/res/layout/activity_about.xml index 05f5ec2b6b4..e69d8f139e7 100644 --- a/mifosng-android/src/main/res/layout/activity_about.xml +++ b/mifosng-android/src/main/res/layout/activity_about.xml @@ -1,229 +1,225 @@ - + android:layout_height="match_parent"> - + android:backgroundTint="@color/white"> - - - + android:layout_height="match_parent" + app:title="@string/about" /> + + + - + + + + + + + + + + - - - - - - + + + android:gravity="center_vertical" + android:orientation="horizontal" + android:padding="26dp"> - - + - - - + + + + + - - + android:backgroundTint="@color/white" + android:clickable="true" + app:cardUseCompatPadding="true"> - - - - + + + + - - - - - + android:layout_marginStart="8dp" + android:layout_weight="1" + android:text="Official Website" /> + + + + - - + + - - - - - - - + android:layout_marginStart="8dp" + android:layout_weight="1" + android:text="@string/about_support_twitter" /> - - + - - + android:backgroundTint="@color/white" + android:clickable="true" + app:cardUseCompatPadding="true"> - + android:gravity="center_vertical" + android:orientation="horizontal" + android:padding="20dp"> + + + + + + + + - - - - + + + + - - - - - + android:text="License: MPL-2.0" /> + - - - - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/mifosng-android/src/main/res/layout/activity_login.xml b/mifosng-android/src/main/res/layout/activity_login.xml index dc9e6bd7070..64e201ed4b6 100755 --- a/mifosng-android/src/main/res/layout/activity_login.xml +++ b/mifosng-android/src/main/res/layout/activity_login.xml @@ -35,6 +35,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/marginItemsInSectionLarge" + app:startIconDrawable="@drawable/ic_person_black_24dp" app:layout_constraintBottom_toTopOf="@+id/textInputLayout" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"> @@ -54,6 +55,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/marginItemsInSectionLarge" + app:startIconDrawable="@drawable/ic_passcode" app:layout_constraintBottom_toTopOf="@+id/bt_login" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/mifosng-android/src/main/res/layout/fragment_activate_client.xml b/mifosng-android/src/main/res/layout/fragment_activate_client.xml index 4343430f8d2..378fcd769cc 100644 --- a/mifosng-android/src/main/res/layout/fragment_activate_client.xml +++ b/mifosng-android/src/main/res/layout/fragment_activate_client.xml @@ -6,30 +6,34 @@ --> - + android:layout_marginTop="12dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:layout_marginBottom="8dp" + android:hint="@string/center_activation_date" + app:endIconDrawable="@drawable/baseline_calendar_today_black_24" + app:endIconMode="custom"> - + +