diff --git a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/CardsContract.java b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/CardsContract.java deleted file mode 100644 index bb6f9e880..000000000 --- a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/CardsContract.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.mifos.mobilewallet.mifospay.savedcards; - - -import org.mifos.mobilewallet.core.data.fineract.entity.savedcards.Card; -import org.mifos.mobilewallet.mifospay.base.BasePresenter; -import org.mifos.mobilewallet.mifospay.base.BaseView; - -import java.util.List; - -/** - * This a contract class working as an Interface for UI - * and Presenter components of the SavedCards Architecture. - * - * @author ankur - * @since 19/May/2018 - */ - -public interface CardsContract { - - /** - * Defines all the functions in UI Component. - */ - interface CardsView extends BaseView { - - void showSavedCards(List cards); - - void showToast(String message); - - void showProgressDialog(String message); - - void hideProgressDialog(); - - void showErrorStateView(int drawable, int title, int subtitle); - - void showFetchingProcess(); - - void hideSwipeProgress(); - } - - /** - * Defines all the functions in Presenter Component. - */ - interface CardsPresenter extends BasePresenter { - - void fetchSavedCards(); - - void addCard(Card card); - - void editCard(Card card); - - void deleteCard(int position); - } -} diff --git a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/CardsContract.kt b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/CardsContract.kt new file mode 100644 index 000000000..6c9e7045b --- /dev/null +++ b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/CardsContract.kt @@ -0,0 +1,37 @@ +package org.mifos.mobilewallet.mifospay.savedcards + +import org.mifos.mobilewallet.core.data.fineract.entity.savedcards.Card +import org.mifos.mobilewallet.mifospay.base.BasePresenter +import org.mifos.mobilewallet.mifospay.base.BaseView + +/** + * This a contract class working as an Interface for UI + * and Presenter components of the SavedCards Architecture. + * + * @author ankur + * @since 19/May/2018 + */ +interface CardsContract { + /** + * Defines all the functions in UI Component. + */ + interface CardsView : BaseView { + fun showSavedCards(cards: List) + fun showToast(message: String?) + fun showProgressDialog(message: String?) + fun hideProgressDialog() + fun showErrorStateView(drawable: Int, title: Int, subtitle: Int) + fun showFetchingProcess() + fun hideSwipeProgress() + } + + /** + * Defines all the functions in Presenter Component. + */ + interface CardsPresenter : BasePresenter { + fun fetchSavedCards() + fun addCard(card: Card?) + fun editCard(card: Card?) + fun deleteCard(position: Int) + } +} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/presenter/CardsPresenter.java b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/presenter/CardsPresenter.java deleted file mode 100644 index b8cbb2afc..000000000 --- a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/presenter/CardsPresenter.java +++ /dev/null @@ -1,233 +0,0 @@ -package org.mifos.mobilewallet.mifospay.savedcards.presenter; - -import org.mifos.mobilewallet.core.base.UseCase; -import org.mifos.mobilewallet.core.base.UseCaseHandler; -import org.mifos.mobilewallet.core.data.fineract.entity.savedcards.Card; -import org.mifos.mobilewallet.core.domain.usecase.savedcards.AddCard; -import org.mifos.mobilewallet.core.domain.usecase.savedcards.DeleteCard; -import org.mifos.mobilewallet.core.domain.usecase.savedcards.EditCard; -import org.mifos.mobilewallet.core.domain.usecase.savedcards.FetchSavedCards; -import org.mifos.mobilewallet.mifospay.R; -import org.mifos.mobilewallet.mifospay.base.BaseView; -import org.mifos.mobilewallet.mifospay.data.local.LocalRepository; -import org.mifos.mobilewallet.mifospay.savedcards.CardsContract; -import org.mifos.mobilewallet.mifospay.utils.Constants; - -import javax.inject.Inject; - -/** - * This class is the Presenter component of the Architecture. - * - * @author ankur - * @since 19/May/2018 - */ - -public class CardsPresenter implements CardsContract.CardsPresenter { - - private final LocalRepository mLocalRepository; - private final UseCaseHandler mUseCaseHandler; - - @Inject - AddCard addCardUseCase; - - @Inject - FetchSavedCards fetchSavedCardsUseCase; - - @Inject - EditCard editCardUseCase; - - @Inject - DeleteCard deleteCardUseCase; - - private CardsContract.CardsView mCardsView; - - @Inject - public CardsPresenter(UseCaseHandler useCaseHandler, LocalRepository localRepository) { - mUseCaseHandler = useCaseHandler; - mLocalRepository = localRepository; - } - - @Override - public void attachView(BaseView baseView) { - mCardsView = (CardsContract.CardsView) baseView; - mCardsView.setPresenter(this); - } - - /** - * An overridden method from Contract to fetch Saved Cards. - */ - @Override - public void fetchSavedCards() { - mCardsView.showFetchingProcess(); - fetchSavedCardsUseCase.setRequestValues( - new FetchSavedCards.RequestValues( - mLocalRepository.getClientDetails().getClientId())); - - final FetchSavedCards.RequestValues requestValues = - fetchSavedCardsUseCase.getRequestValues(); - - mUseCaseHandler.execute(fetchSavedCardsUseCase, requestValues, - new UseCase.UseCaseCallback() { - @Override - public void onSuccess(FetchSavedCards.ResponseValue response) { - mCardsView.showSavedCards(response.getCardList()); - } - - @Override - public void onError(String message) { - mCardsView.hideSwipeProgress(); - mCardsView.showErrorStateView(R.drawable.ic_error_state, - R.string.error_oops, - R.string.error_no_cards_found); - } - }); - } - - /** - * An overridden method from Contract to Add a new Card. - * - * @param card : The card to be added. - */ - @Override - public void addCard(Card card) { - - mCardsView.showProgressDialog(Constants.ADDING_CARD); - - if (!validateCreditCardNumber(card.getCardNumber())) { - mCardsView.showToast(Constants.INVALID_CREDIT_CARD_NUMBER); - mCardsView.hideProgressDialog(); - return; - } - - addCardUseCase.setRequestValues( - new AddCard.RequestValues(mLocalRepository.getClientDetails().getClientId(), - card)); - - final AddCard.RequestValues requestValues = addCardUseCase.getRequestValues(); - - mUseCaseHandler.execute(addCardUseCase, requestValues, - new UseCase.UseCaseCallback() { - @Override - public void onSuccess(AddCard.ResponseValue response) { - mCardsView.hideProgressDialog(); - mCardsView.showToast(Constants.CARD_ADDED_SUCCESSFULLY); - fetchSavedCards(); - } - - @Override - public void onError(String message) { - mCardsView.hideSwipeProgress(); - mCardsView.showToast(Constants.ERROR_ADDING_CARD); - } - }); - } - - /** - * An overridden method from Contract to edit a Card. - * - * @param card : Card to be edited. - */ - @Override - public void editCard(Card card) { - - mCardsView.showProgressDialog(Constants.UPDATING_CARD); - - if (!validateCreditCardNumber(card.getCardNumber())) { - mCardsView.showToast(Constants.INVALID_CREDIT_CARD_NUMBER); - mCardsView.hideProgressDialog(); - return; - } - - editCardUseCase.setRequestValues( - new EditCard.RequestValues((int) mLocalRepository.getClientDetails().getClientId(), - card)); - final EditCard.RequestValues requestValues = editCardUseCase.getRequestValues(); - - mUseCaseHandler.execute(editCardUseCase, requestValues, - new UseCase.UseCaseCallback() { - @Override - public void onSuccess(EditCard.ResponseValue response) { - mCardsView.hideProgressDialog(); - mCardsView.showToast(Constants.CARD_UPDATED_SUCCESSFULLY); - fetchSavedCards(); - } - - @Override - public void onError(String message) { - mCardsView.hideProgressDialog(); - mCardsView.showToast(Constants.ERROR_UPDATING_CARD); - } - }); - } - - /** - * An overridden method from Contract to delete a particular card. - * - * @param cardId : Card to be deleted. - */ - @Override - public void deleteCard(int cardId) { - mCardsView.showProgressDialog(Constants.DELETING_CARD); - - deleteCardUseCase.setRequestValues( - new DeleteCard.RequestValues( - (int) mLocalRepository.getClientDetails().getClientId(), - cardId)); - final DeleteCard.RequestValues requestValues = deleteCardUseCase.getRequestValues(); - - mUseCaseHandler.execute(deleteCardUseCase, requestValues, - new UseCase.UseCaseCallback() { - @Override - public void onSuccess(DeleteCard.ResponseValue response) { - mCardsView.hideProgressDialog(); - mCardsView.showToast(Constants.CARD_DELETED_SUCCESSFULLY); - fetchSavedCards(); - } - - @Override - public void onError(String message) { - mCardsView.hideProgressDialog(); - mCardsView.showToast(Constants.ERROR_DELETING_CARD); - } - }); - } - - - /** - * An utility function to validate a Credit Card Nnumber. - * - * @param str : String to be validated - * Luhn Algorithm for validating Credit Card Number - * src: https://www.journaldev - * .com/1443/java-credit-card-validation-luhn-algorithm-java - */ - private boolean validateCreditCardNumber(String str) { - - int u = 2; - if (u - 2 == 0) { - return true; // for backend testing. remove after testing. - } - - if (str.length() == 0) { - return false; - } - - int[] ints = new int[str.length()]; - for (int i = 0; i < str.length(); i++) { - ints[i] = Integer.parseInt(str.substring(i, i + 1)); - } - for (int i = ints.length - 2; i >= 0; i = i - 2) { - int j = ints[i]; - j = j * 2; - if (j > 9) { - j = j % 10 + 1; - } - ints[i] = j; - } - int sum = 0; - for (int i = 0; i < ints.length; i++) { - sum += ints[i]; - } - return sum % 10 == 0; - } -} diff --git a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/presenter/CardsPresenter.kt b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/presenter/CardsPresenter.kt new file mode 100644 index 000000000..b9a7ffef8 --- /dev/null +++ b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/presenter/CardsPresenter.kt @@ -0,0 +1,204 @@ +package org.mifos.mobilewallet.mifospay.savedcards.presenter + +import org.mifos.mobilewallet.core.base.UseCase.UseCaseCallback +import org.mifos.mobilewallet.core.base.UseCaseHandler +import org.mifos.mobilewallet.core.data.fineract.entity.savedcards.Card +import org.mifos.mobilewallet.core.domain.usecase.savedcards.AddCard +import org.mifos.mobilewallet.core.domain.usecase.savedcards.DeleteCard +import org.mifos.mobilewallet.core.domain.usecase.savedcards.EditCard +import org.mifos.mobilewallet.core.domain.usecase.savedcards.FetchSavedCards +import org.mifos.mobilewallet.mifospay.R +import org.mifos.mobilewallet.mifospay.base.BaseView +import org.mifos.mobilewallet.mifospay.data.local.LocalRepository +import org.mifos.mobilewallet.mifospay.savedcards.CardsContract +import org.mifos.mobilewallet.mifospay.savedcards.CardsContract.CardsView +import org.mifos.mobilewallet.mifospay.utils.Constants +import javax.inject.Inject + +/** + * This class is the Presenter component of the Architecture. + * + * @author ankur + * @since 19/May/2018 + */ +class CardsPresenter @Inject constructor( + private val mUseCaseHandler: UseCaseHandler, + private val mLocalRepository: LocalRepository +) : CardsContract.CardsPresenter { + @JvmField + @Inject + var addCardUseCase: AddCard? = null + + @JvmField + @Inject + var fetchSavedCardsUseCase: FetchSavedCards? = null + + @JvmField + @Inject + var editCardUseCase: EditCard? = null + + @JvmField + @Inject + var deleteCardUseCase: DeleteCard? = null + private var mCardsView: CardsView? = null + override fun attachView(baseView: BaseView<*>?) { + mCardsView = baseView as CardsView? + mCardsView!!.setPresenter(this) + } + + /** + * An overridden method from Contract to fetch Saved Cards. + */ + override fun fetchSavedCards() { + mCardsView!!.showFetchingProcess() + fetchSavedCardsUseCase!!.requestValues = FetchSavedCards.RequestValues( + mLocalRepository.clientDetails.clientId + ) + val requestValues = fetchSavedCardsUseCase!!.requestValues + mUseCaseHandler.execute(fetchSavedCardsUseCase, requestValues, + object : UseCaseCallback { + override fun onSuccess(response: FetchSavedCards.ResponseValue?) { + response?.cardList?.let { mCardsView!!.showSavedCards(it) } + } + + override fun onError(message: String) { + mCardsView!!.hideSwipeProgress() + mCardsView!!.showErrorStateView( + R.drawable.ic_error_state, + R.string.error_oops, + R.string.error_no_cards_found + ) + } + }) + } + + /** + * An overridden method from Contract to Add a new Card. + * + * @param card : The card to be added. + */ + override fun addCard(card: Card?) { + mCardsView!!.showProgressDialog(Constants.ADDING_CARD) + if (!validateCreditCardNumber(card!!.cardNumber)) { + mCardsView!!.showToast(Constants.INVALID_CREDIT_CARD_NUMBER) + mCardsView!!.hideProgressDialog() + return + } + addCardUseCase!!.requestValues = AddCard.RequestValues( + mLocalRepository.clientDetails.clientId, + card + ) + val requestValues = addCardUseCase!!.requestValues + mUseCaseHandler.execute(addCardUseCase, requestValues, + object : UseCaseCallback { + override fun onSuccess(response: AddCard.ResponseValue?) { + mCardsView!!.hideProgressDialog() + mCardsView!!.showToast(Constants.CARD_ADDED_SUCCESSFULLY) + fetchSavedCards() + } + + override fun onError(message: String) { + mCardsView!!.hideSwipeProgress() + mCardsView!!.showToast(Constants.ERROR_ADDING_CARD) + } + }) + } + + /** + * An overridden method from Contract to edit a Card. + * + * @param card : Card to be edited. + */ + override fun editCard(card: Card?) { + mCardsView!!.showProgressDialog(Constants.UPDATING_CARD) + if (!validateCreditCardNumber(card!!.cardNumber)) { + mCardsView!!.showToast(Constants.INVALID_CREDIT_CARD_NUMBER) + mCardsView!!.hideProgressDialog() + return + } + editCardUseCase!!.requestValues = EditCard.RequestValues( + mLocalRepository.clientDetails.clientId.toInt(), + card + ) + val requestValues = editCardUseCase!!.requestValues + mUseCaseHandler.execute(editCardUseCase, requestValues, + object : UseCaseCallback { + override fun onSuccess(response: EditCard.ResponseValue?) { + mCardsView!!.hideProgressDialog() + mCardsView!!.showToast(Constants.CARD_UPDATED_SUCCESSFULLY) + fetchSavedCards() + } + + override fun onError(message: String) { + mCardsView!!.hideProgressDialog() + mCardsView!!.showToast(Constants.ERROR_UPDATING_CARD) + } + }) + } + + /** + * An overridden method from Contract to delete a particular card. + * + * @param cardId : Card to be deleted. + */ + override fun deleteCard(cardId: Int) { + mCardsView!!.showProgressDialog(Constants.DELETING_CARD) + deleteCardUseCase!!.requestValues = DeleteCard.RequestValues( + mLocalRepository.clientDetails.clientId.toInt(), + cardId + ) + val requestValues = deleteCardUseCase!!.requestValues + mUseCaseHandler.execute(deleteCardUseCase, requestValues, + object : UseCaseCallback { + override fun onSuccess(response: DeleteCard.ResponseValue?) { + mCardsView!!.hideProgressDialog() + mCardsView!!.showToast(Constants.CARD_DELETED_SUCCESSFULLY) + fetchSavedCards() + } + + override fun onError(message: String) { + mCardsView!!.hideProgressDialog() + mCardsView!!.showToast(Constants.ERROR_DELETING_CARD) + } + }) + } + + /** + * An utility function to validate a Credit Card Nnumber. + * + * @param str : String to be validated + * Luhn Algorithm for validating Credit Card Number + * src: https://www.journaldev + * .com/1443/java-credit-card-validation-luhn-algorithm-java + */ + private fun validateCreditCardNumber(str: String): Boolean { + val u = 2 + if (u - 2 == 0) { + return true // for backend testing. remove after testing. + } + if (str.length == 0) { + return false + } + val ints = IntArray(str.length) + for (i in 0 until str.length) { + ints[i] = str.substring(i, i + 1).toInt() + } + run { + var i = ints.size - 2 + while (i >= 0) { + var j = ints[i] + j = j * 2 + if (j > 9) { + j = j % 10 + 1 + } + ints[i] = j + i = i - 2 + } + } + var sum = 0 + for (i in ints.indices) { + sum += ints[i] + } + return sum % 10 == 0 + } +} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/AddCardDialog.java b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/AddCardDialog.java deleted file mode 100644 index a4119d845..000000000 --- a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/AddCardDialog.java +++ /dev/null @@ -1,189 +0,0 @@ -package org.mifos.mobilewallet.mifospay.savedcards.ui; - -import android.app.Dialog; -import android.content.DialogInterface; -import android.os.Bundle; -import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.EditText; -import android.widget.Spinner; - -import androidx.annotation.NonNull; - -import com.google.android.material.bottomsheet.BottomSheetBehavior; -import com.google.android.material.bottomsheet.BottomSheetDialog; -import com.google.android.material.bottomsheet.BottomSheetDialogFragment; -import com.google.android.material.textfield.TextInputLayout; - -import org.mifos.mobilewallet.core.data.fineract.entity.savedcards.Card; -import org.mifos.mobilewallet.mifospay.R; -import org.mifos.mobilewallet.mifospay.savedcards.CardsContract; -import org.mifos.mobilewallet.mifospay.utils.Constants; -import org.mifos.mobilewallet.mifospay.utils.Toaster; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - -import butterknife.Action; -import butterknife.BindView; -import butterknife.BindViews; -import butterknife.ButterKnife; -import butterknife.OnClick; - -/** - * This is a Dialog class to add a new card. - * - * @author ankur - * @since 19/May/2018 - */ - -public class AddCardDialog extends BottomSheetDialogFragment { - - private static final String TAG = "AddCardDialog"; - boolean forEdit; - Card editCard; - @BindView(R.id.et_card_number) - EditText etCardNumber; - @BindView(R.id.et_cvv) - EditText etCVV; - @BindView(R.id.spn_mm) - Spinner spnMM; - @BindView(R.id.spn_yy) - Spinner spnYY; - @BindView(R.id.et_fName) - EditText etFname; - @BindView(R.id.et_lName) - EditText etLname; - @BindView(R.id.btn_add) - Button btnAdd; - @BindView(R.id.btn_cancel) - Button btnCancel; - CardsContract.CardsPresenter mCardsPresenter; - @BindViews({R.id.til_fName, R.id.til_lName, R.id.til_card_number, R.id.til_cvv}) - List mTextInputLayouts; - private BottomSheetBehavior mBottomSheetBehavior; - private boolean fieldsValid; - private final Action CHECK_ERROR = - new Action() { - @Override - public void apply(@NonNull TextInputLayout view, int index) { - EditText editText = view.getEditText(); - if (editText == null || editText.getEditableText() == null - || editText.getEditableText().toString().trim().isEmpty()) { - view.setError(AddCardDialog.this.getString(R.string.field_required)); - fieldsValid = false; - } else { - view.setError(null); - } - } - }; - - /** - * A function to set the Presenter. - * - * @param cardsPresenter : Cards Presenter from Contract Class. - */ - public void setCardsPresenter( - CardsContract.CardsPresenter cardsPresenter) { - mCardsPresenter = cardsPresenter; - } - - @Override - public void onDismiss(DialogInterface dialog) { - super.onDismiss(dialog); - } - - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState); - - View view = View.inflate(getContext(), R.layout.dialog_add_card, null); - - dialog.setContentView(view); - mBottomSheetBehavior = BottomSheetBehavior.from((View) view.getParent()); - - ButterKnife.bind(this, view); - - // add items to spnYY - List items = new ArrayList<>(); - int currentYear = Calendar.getInstance().get(Calendar.YEAR); - for (int i = 0; i < 50; i++) { - int j = currentYear + i; - items.add("" + j); - } - ArrayAdapter dataAdapter = new ArrayAdapter<>(getContext(), - android.R.layout.simple_spinner_item, items); - dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spnYY.setAdapter(dataAdapter); - - return dialog; - } - - @Override - public void onStart() { - super.onStart(); - mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); - // make swipe-able up and parameters to edit text to num only and do backend - - if (forEdit) { - etFname.setText(editCard.getFirstName()); - etLname.setText(editCard.getLastName()); - etCardNumber.setText(editCard.getCardNumber()); - String[] expiryDate = editCard.getExpiryDate().split("/"); - int currentYear = Calendar.getInstance().get(Calendar.YEAR); - spnMM.setSelection(Integer.parseInt(expiryDate[0]) - 1); - spnYY.setSelection(Integer.parseInt(expiryDate[1]) - currentYear); - btnAdd.setText(Constants.UPDATE); - } - } - - /** - * A function to dismiss the dialog box when user presses cancel button. - */ - @OnClick(R.id.btn_cancel) - public void onCancelClicked() { - dismiss(); - } - - /** - * A function to add a new card after entering all the valid details. - */ - @OnClick(R.id.btn_add) - public void onAddClicked() { - if (!areFieldsValid()) { - return; - } - Card card = new Card(etCardNumber.getText().toString().trim(), etCVV.getText().toString(), - spnMM.getSelectedItem() + "/" + spnYY.getSelectedItem(), - etFname.getText().toString().trim(), etLname.getText().toString().trim()); - - if (forEdit) { - card.setId(editCard.getId()); - mCardsPresenter.editCard(card); - } else { - mCardsPresenter.addCard(card); - } - - dismiss(); - } - - /** - * An utility function to check if the new Card entries are valid or not. - */ - private boolean areFieldsValid() { - fieldsValid = true; - butterknife.ViewCollections.run(mTextInputLayouts, CHECK_ERROR); - int expiryMonth = Integer.parseInt(spnMM.getSelectedItem().toString()); - int expiryYear = Integer.parseInt(spnYY.getSelectedItem().toString()); - Calendar calendar = Calendar.getInstance(); - if (expiryYear == calendar.get(Calendar.YEAR) - && expiryMonth < (calendar.get(Calendar.MONTH) + 1) && fieldsValid) { - Toaster.showToast(getContext(), getString(R.string.card_expiry_message)); - fieldsValid = false; - } - return fieldsValid; - } -} diff --git a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/AddCardDialog.kt b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/AddCardDialog.kt new file mode 100644 index 000000000..7d3ee7570 --- /dev/null +++ b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/AddCardDialog.kt @@ -0,0 +1,196 @@ +package org.mifos.mobilewallet.mifospay.savedcards.ui + +import android.app.Dialog +import android.content.DialogInterface +import android.os.Bundle +import android.view.View +import android.widget.ArrayAdapter +import android.widget.Button +import android.widget.EditText +import android.widget.Spinner +import butterknife.Action +import butterknife.BindView +import butterknife.BindViews +import butterknife.ButterKnife +import butterknife.OnClick +import butterknife.ViewCollections +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetDialog +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import com.google.android.material.textfield.TextInputLayout +import org.mifos.mobilewallet.core.data.fineract.entity.savedcards.Card +import org.mifos.mobilewallet.mifospay.R +import org.mifos.mobilewallet.mifospay.savedcards.CardsContract +import org.mifos.mobilewallet.mifospay.utils.Constants +import org.mifos.mobilewallet.mifospay.utils.Toaster +import java.util.Calendar + +/** + * This is a Dialog class to add a new card. + * + * @author ankur + * @since 19/May/2018 + */ +class AddCardDialog : BottomSheetDialogFragment() { + @JvmField + var forEdit = false + + @JvmField + var editCard: Card? = null + + @JvmField + @BindView(R.id.et_card_number) + var etCardNumber: EditText? = null + + @JvmField + @BindView(R.id.et_cvv) + var etCVV: EditText? = null + + @JvmField + @BindView(R.id.spn_mm) + var spnMM: Spinner? = null + + @JvmField + @BindView(R.id.spn_yy) + var spnYY: Spinner? = null + + @JvmField + @BindView(R.id.et_fName) + var etFname: EditText? = null + + @JvmField + @BindView(R.id.et_lName) + var etLname: EditText? = null + + @JvmField + @BindView(R.id.btn_add) + var btnAdd: Button? = null + + @JvmField + @BindView(R.id.btn_cancel) + var btnCancel: Button? = null + var mCardsPresenter: CardsContract.CardsPresenter? = null + + @BindViews(R.id.til_fName, R.id.til_lName, R.id.til_card_number, R.id.til_cvv) + lateinit var mTextInputLayouts: MutableList + + private var mBottomSheetBehavior: BottomSheetBehavior<*>? = null + private var fieldsValid = false + private val CHECK_ERROR: Action = Action { view, index -> + val editText = view.editText + if (editText == null || editText.editableText == null || editText.editableText.toString() + .trim { it <= ' ' }.isEmpty() + ) { + view.error = this@AddCardDialog.getString(R.string.field_required) + fieldsValid = false + } else { + view.error = null + } + } + + /** + * A function to set the Presenter. + * + * @param cardsPresenter : Cards Presenter from Contract Class. + */ + fun setCardsPresenter( + cardsPresenter: CardsContract.CardsPresenter? + ) { + mCardsPresenter = cardsPresenter + } + + override fun onDismiss(dialog: DialogInterface) { + super.onDismiss(dialog) + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog + val view = View.inflate(context, R.layout.dialog_add_card, null) + dialog.setContentView(view) + mBottomSheetBehavior = BottomSheetBehavior.from(view.parent as View) + ButterKnife.bind(this, view) + + // add items to spnYY + val items: MutableList = ArrayList() + val currentYear = Calendar.getInstance()[Calendar.YEAR] + for (i in 0..49) { + val j = currentYear + i + items.add("" + j) + } + val dataAdapter = ArrayAdapter( + requireContext(), + android.R.layout.simple_spinner_item, items + ) + dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + spnYY!!.adapter = dataAdapter + return dialog + } + + override fun onStart() { + super.onStart() + mBottomSheetBehavior!!.state = BottomSheetBehavior.STATE_EXPANDED + // make swipe-able up and parameters to edit text to num only and do backend + if (forEdit) { + etFname!!.setText(editCard!!.firstName) + etLname!!.setText(editCard!!.lastName) + etCardNumber!!.setText(editCard!!.cardNumber) + val expiryDate = + editCard!!.expiryDate.split("/".toRegex()).dropLastWhile { it.isEmpty() } + .toTypedArray() + val currentYear = Calendar.getInstance()[Calendar.YEAR] + spnMM!!.setSelection(expiryDate[0].toInt() - 1) + spnYY!!.setSelection(expiryDate[1].toInt() - currentYear) + btnAdd!!.text = Constants.UPDATE + } + } + + /** + * A function to dismiss the dialog box when user presses cancel button. + */ + @OnClick(R.id.btn_cancel) + fun onCancelClicked() { + dismiss() + } + + /** + * A function to add a new card after entering all the valid details. + */ + @OnClick(R.id.btn_add) + fun onAddClicked() { + if (!areFieldsValid()) { + return + } + val card = Card(etCardNumber!!.text.toString().trim { it <= ' ' }, + etCVV!!.text.toString(), + spnMM!!.selectedItem.toString() + "/" + spnYY!!.selectedItem, + etFname!!.text.toString().trim { it <= ' ' }, + etLname!!.text.toString().trim { it <= ' ' }) + if (forEdit) { + card.id = editCard!!.id + mCardsPresenter!!.editCard(card) + } else { + mCardsPresenter!!.addCard(card) + } + dismiss() + } + + /** + * An utility function to check if the new Card entries are valid or not. + */ + private fun areFieldsValid(): Boolean { + fieldsValid = true + ViewCollections.run(mTextInputLayouts, CHECK_ERROR) + val expiryMonth = spnMM!!.selectedItem.toString().toInt() + val expiryYear = spnYY!!.selectedItem.toString().toInt() + val calendar = Calendar.getInstance() + if (expiryYear == calendar[Calendar.YEAR] && expiryMonth < calendar[Calendar.MONTH] + 1 && fieldsValid) { + Toaster.showToast(context, getString(R.string.card_expiry_message)) + fieldsValid = false + } + return fieldsValid + } + + companion object { + private const val TAG = "AddCardDialog" + } +} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsAdapter.java b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsAdapter.java deleted file mode 100644 index 05abebccb..000000000 --- a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsAdapter.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.mifos.mobilewallet.mifospay.savedcards.ui; - -import androidx.recyclerview.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import org.mifos.mobilewallet.core.data.fineract.entity.savedcards.Card; -import org.mifos.mobilewallet.mifospay.R; - -import java.util.List; - -import javax.inject.Inject; - -import butterknife.BindView; -import butterknife.ButterKnife; - -/** - * This is a Adapter Class to display Cards. - * - * @author ankur - * @since 21/May/2018 - */ - -public class CardsAdapter extends RecyclerView.Adapter { - - private List cards; - - @Inject - public CardsAdapter() { - } - - @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View v = LayoutInflater.from(parent.getContext()).inflate( - R.layout.item_card, parent, false); - return new ViewHolder(v); - } - - @Override - public void onBindViewHolder(ViewHolder holder, final int position) { - holder.tvFname.setText(cards.get(position).getFirstName()); - holder.tvLname.setText(cards.get(position).getLastName()); - holder.tvCardNumber.setText(cards.get(position).getCardNumber()); - holder.tvExpirayDate.setText(cards.get(position).getExpiryDate()); - } - - @Override - public int getItemCount() { - if (cards != null) { - return cards.size(); - } else { - return 0; - } - } - - public List getCards() { - return cards; - } - - public void setCards(List cards) { - this.cards = cards; - notifyDataSetChanged(); - } - - public class ViewHolder extends RecyclerView.ViewHolder { - - @BindView(R.id.tv_fName) - TextView tvFname; - - @BindView(R.id.tv_lName) - TextView tvLname; - - @BindView(R.id.tv_card_number) - TextView tvCardNumber; - - @BindView(R.id.tv_expiry_date) - TextView tvExpirayDate; - - public ViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } -} diff --git a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsAdapter.kt b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsAdapter.kt new file mode 100644 index 000000000..5cf1eed7a --- /dev/null +++ b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsAdapter.kt @@ -0,0 +1,76 @@ +package org.mifos.mobilewallet.mifospay.savedcards.ui + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import butterknife.BindView +import butterknife.ButterKnife +import org.mifos.mobilewallet.core.data.fineract.entity.savedcards.Card +import org.mifos.mobilewallet.mifospay.R +import javax.inject.Inject + +/** + * This is a Adapter Class to display Cards. + * + * @author ankur + * @since 21/May/2018 + */ +class CardsAdapter @Inject constructor() : RecyclerView.Adapter() { + private var cards: List? = null + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val v = LayoutInflater.from(parent.context).inflate( + R.layout.item_card, parent, false + ) + return ViewHolder(v) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.tvFname!!.text = cards!![position].firstName + holder.tvLname!!.text = cards!![position].lastName + holder.tvCardNumber!!.text = cards!![position].cardNumber + holder.tvExpirayDate!!.text = cards!![position].expiryDate + } + + override fun getItemCount(): Int { + return if (cards != null) { + cards!!.size + } else { + 0 + } + } + + fun getCards(): List? { + return cards + } + + fun setCards(cards: List) { + this.cards = cards + notifyDataSetChanged() + } + + inner class ViewHolder(itemView: View?) : RecyclerView.ViewHolder( + itemView!! + ) { + @JvmField + @BindView(R.id.tv_fName) + var tvFname: TextView? = null + + @JvmField + @BindView(R.id.tv_lName) + var tvLname: TextView? = null + + @JvmField + @BindView(R.id.tv_card_number) + var tvCardNumber: TextView? = null + + @JvmField + @BindView(R.id.tv_expiry_date) + var tvExpirayDate: TextView? = null + + init { + ButterKnife.bind(this, itemView!!) + } + } +} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsFragment.java b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsFragment.java deleted file mode 100644 index 593957c3c..000000000 --- a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsFragment.java +++ /dev/null @@ -1,327 +0,0 @@ -package org.mifos.mobilewallet.mifospay.savedcards.ui; - -import static org.mifos.mobilewallet.mifospay.utils.Utils.isBlank; - -import android.content.res.Resources; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.PopupMenu; -import android.widget.ProgressBar; -import android.widget.TextView; - -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.DividerItemDecoration; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -import com.google.android.material.chip.Chip; - -import org.mifos.mobilewallet.core.data.fineract.entity.savedcards.Card; -import org.mifos.mobilewallet.mifospay.R; -import org.mifos.mobilewallet.mifospay.base.BaseFragment; -import org.mifos.mobilewallet.mifospay.savedcards.CardsContract; -import org.mifos.mobilewallet.mifospay.savedcards.presenter.CardsPresenter; -import org.mifos.mobilewallet.mifospay.utils.Constants; -import org.mifos.mobilewallet.mifospay.utils.RecyclerItemClickListener; -import org.mifos.mobilewallet.mifospay.utils.Toaster; - -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.OnTextChanged; -import dagger.hilt.android.AndroidEntryPoint; - -/** - * This is the UI component of the SavedCards Architecture. - * @author ankur - * @since 21/May/2018 - */ -@AndroidEntryPoint -public class CardsFragment extends BaseFragment implements CardsContract.CardsView { - - @Inject - CardsPresenter mPresenter; - - CardsContract.CardsPresenter mCardsPresenter; - - @BindView(R.id.inc_state_view) - View vStateView; - - @BindView(R.id.iv_empty_no_transaction_history) - ImageView ivTransactionsStateIcon; - - @BindView(R.id.tv_empty_no_transaction_history_title) - TextView tvTransactionsStateTitle; - - @BindView(R.id.tv_empty_no_transaction_history_subtitle) - TextView tvTransactionsStateSubtitle; - - @BindView(R.id.rv_cards) - RecyclerView rvCards; - - @BindView(R.id.pb_cards) - ProgressBar pbCards; - - @Inject - CardsAdapter mCardsAdapter; - - @BindView(R.id.btn_add_card) - Chip addCard; - - @BindView(R.id.et_search_cards) - EditText etCardSearch; - - @BindView(R.id.ll_search_cards) - LinearLayout searchView; - - private List cardsList; - - View rootView; - - public static CardsFragment newInstance() { - Bundle args = new Bundle(); - - CardsFragment fragment = new CardsFragment(); - fragment.setArguments(args); - return fragment; - } - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - rootView = inflater.inflate(R.layout.fragment_cards, container, false); - ButterKnife.bind(this, rootView); - mPresenter.attachView(this); - setUpSwipeRefresh(); - setupCardsRecyclerView(); - showSwipeProgress(); - mCardsPresenter.fetchSavedCards(); - return rootView; - } - - private void setUpSwipeRefresh() { - getSwipeRefreshLayout().setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { - @Override - public void onRefresh() { - getSwipeRefreshLayout().setRefreshing(false); - mCardsPresenter.fetchSavedCards(); - } - }); - } - - private void showEmptyStateView() { - if (getActivity() != null) { - searchView.setVisibility(View.GONE); - vStateView.setVisibility(View.VISIBLE); - pbCards.setVisibility(View.GONE); - Resources res = getResources(); - ivTransactionsStateIcon - .setImageDrawable(res.getDrawable(R.drawable.ic_cards)); - tvTransactionsStateTitle - .setText(res.getString(R.string.empty_no_cards_title)); - tvTransactionsStateSubtitle - .setText(res.getString(R.string.empty_no_cards_subtitle)); - } - } - - @Override - public void showErrorStateView(int drawable, int title, int subtitle) { - pbCards.setVisibility(View.GONE); - hideSwipeProgress(); - vStateView.setVisibility(View.VISIBLE); - if (getActivity() != null) { - Resources res = getResources(); - ivTransactionsStateIcon - .setImageDrawable(res.getDrawable(drawable)); - tvTransactionsStateTitle - .setText(res.getString(title)); - tvTransactionsStateSubtitle - .setText(res.getString(subtitle)); - } - } - - @Override - public void showFetchingProcess() { - vStateView.setVisibility(View.GONE); - searchView.setVisibility(View.GONE); - rvCards.setVisibility(View.GONE); - pbCards.setVisibility(View.VISIBLE); - addCard.setVisibility(View.GONE); - } - - - private void hideEmptyStateView() { - vStateView.setVisibility(View.GONE); - } - - /** - * A function to setup the Layout Manager and Integrate the RecyclerView with Adapter. - * This function also implements click action on CardList. - */ - private void setupCardsRecyclerView() { - LinearLayoutManager llm = new LinearLayoutManager(getActivity()); - rvCards.setLayoutManager(llm); - rvCards.setHasFixedSize(true); - rvCards.addItemDecoration(new DividerItemDecoration(getActivity(), - DividerItemDecoration.VERTICAL)); - rvCards.setAdapter(mCardsAdapter); - - rvCards.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), - new RecyclerItemClickListener.OnItemClickListener() { - @Override - public void onItemClick(final View childView, final int position) { - - PopupMenu savedCardMenu = new PopupMenu(getContext(), childView); - savedCardMenu.getMenuInflater().inflate(R.menu.menu_saved_card, - savedCardMenu.getMenu()); - - savedCardMenu.setOnMenuItemClickListener( - new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - switch (item.getItemId()) { - case R.id.edit_card: - AddCardDialog addCardDialog = new AddCardDialog(); - - addCardDialog.forEdit = true; - - addCardDialog.editCard = - mCardsAdapter.getCards().get(position); - - addCardDialog.setCardsPresenter(mCardsPresenter); - - addCardDialog.show(getFragmentManager(), - Constants.EDIT_CARD_DIALOG); - break; - case R.id.delete_card: - mCardsPresenter.deleteCard( - mCardsAdapter.getCards().get( - position).getId()); - break; - case R.id.cancel: - break; - } - return true; - } - }); - - savedCardMenu.show(); - } - - @Override - public void onItemLongPress(View childView, int position) { - - } - })); - } - - /** - * An overridden function to set Presenter reference in this UI Component. - * @param presenter : Presenter component reference for the Architecture. - */ - @Override - public void setPresenter(CardsContract.CardsPresenter presenter) { - mCardsPresenter = presenter; - } - - /** - * A function to show Add Card Dialog box. - */ - @OnClick(R.id.btn_add_card) - public void onClickAddCard() { - AddCardDialog addCardDialog = new AddCardDialog(); - addCardDialog.forEdit = false; - addCardDialog.setCardsPresenter(mCardsPresenter); - addCardDialog.show(getFragmentManager(), Constants.ADD_CARD_DIALOG); - } - - /** - * A function to show setup the cards list with adapter. - * @param cards: List of cards. - */ - @Override - public void showSavedCards(List cards) { - pbCards.setVisibility(View.GONE); - if (cards == null || cards.size() == 0) { - showEmptyStateView(); - } else { - hideEmptyStateView(); - searchView.setVisibility(View.VISIBLE); - rvCards.setVisibility(View.VISIBLE); - mCardsAdapter.setCards(cards); - } - cardsList = cards; - mCardsAdapter.setCards(cards); - hideSwipeProgress(); - addCard.setVisibility(View.VISIBLE); - } - - @OnTextChanged(R.id.et_search_cards) - void filterCards() { - String text = etCardSearch.getText().toString().trim(); - List filteredList = new ArrayList<>(); - - if (cardsList != null) { - if (isBlank(text)) { - filteredList = cardsList; - } else { - for (Card mycard : cardsList ) { - String fullName = mycard.getFirstName().toLowerCase() + " " + - mycard.getLastName().toLowerCase(); - String cardNo = mycard.getCardNumber().toLowerCase(); - if (fullName.contains(text.toLowerCase()) || - cardNo.contains(text.toLowerCase())) { - filteredList.add(mycard); - } - } - } - mCardsAdapter.setCards(filteredList); - } - } - - /** - * An overridden method to show a toast message. - */ - @Override - public void showToast(String message) { - Toaster.show(getView(), message); - } - - /** - * An overridden method to show a progress dialog. - */ - @Override - public void showProgressDialog(String message) { - super.showProgressDialog(message); - } - - /** - * An overridden method to hide a progress dialog. - */ - @Override - public void hideProgressDialog() { - super.hideProgressDialog(); - } - - /** - * An overridden method to hide the swipe progress. - */ - @Override - public void hideSwipeProgress() { - super.hideSwipeProgress(); - } - -} diff --git a/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsFragment.kt b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsFragment.kt new file mode 100644 index 000000000..b306e69ce --- /dev/null +++ b/mifospay/src/main/java/org/mifos/mobilewallet/mifospay/savedcards/ui/CardsFragment.kt @@ -0,0 +1,297 @@ +package org.mifos.mobilewallet.mifospay.savedcards.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.EditText +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.PopupMenu +import android.widget.ProgressBar +import android.widget.TextView +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import butterknife.BindView +import butterknife.ButterKnife +import butterknife.OnClick +import butterknife.OnTextChanged +import com.google.android.material.chip.Chip +import dagger.hilt.android.AndroidEntryPoint +import org.mifos.mobilewallet.core.data.fineract.entity.savedcards.Card +import org.mifos.mobilewallet.mifospay.R +import org.mifos.mobilewallet.mifospay.base.BaseFragment +import org.mifos.mobilewallet.mifospay.savedcards.CardsContract +import org.mifos.mobilewallet.mifospay.savedcards.CardsContract.CardsView +import org.mifos.mobilewallet.mifospay.savedcards.presenter.CardsPresenter +import org.mifos.mobilewallet.mifospay.utils.Constants +import org.mifos.mobilewallet.mifospay.utils.RecyclerItemClickListener +import org.mifos.mobilewallet.mifospay.utils.Toaster +import org.mifos.mobilewallet.mifospay.utils.Utils.isBlank +import java.util.Locale +import javax.inject.Inject + +/** + * This is the UI component of the SavedCards Architecture. + * @author ankur + * @since 21/May/2018 + */ +@AndroidEntryPoint +class CardsFragment : BaseFragment(), CardsView { + @JvmField + @Inject + var mPresenter: CardsPresenter? = null + var mCardsPresenter: CardsContract.CardsPresenter? = null + + @JvmField + @BindView(R.id.inc_state_view) + var vStateView: View? = null + + @JvmField + @BindView(R.id.iv_empty_no_transaction_history) + var ivTransactionsStateIcon: ImageView? = null + + @JvmField + @BindView(R.id.tv_empty_no_transaction_history_title) + var tvTransactionsStateTitle: TextView? = null + + @JvmField + @BindView(R.id.tv_empty_no_transaction_history_subtitle) + var tvTransactionsStateSubtitle: TextView? = null + + @JvmField + @BindView(R.id.rv_cards) + var rvCards: RecyclerView? = null + + @JvmField + @BindView(R.id.pb_cards) + var pbCards: ProgressBar? = null + + @JvmField + @Inject + var mCardsAdapter: CardsAdapter? = null + + @JvmField + @BindView(R.id.btn_add_card) + var addCard: Chip? = null + + @JvmField + @BindView(R.id.et_search_cards) + var etCardSearch: EditText? = null + + @JvmField + @BindView(R.id.ll_search_cards) + var searchView: LinearLayout? = null + private var cardsList: List = ArrayList() + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val rootView = inflater.inflate(R.layout.fragment_cards, container, false) + ButterKnife.bind(this, rootView) + mPresenter!!.attachView(this) + setUpSwipeRefresh() + setupCardsRecyclerView() + showSwipeProgress() + mCardsPresenter!!.fetchSavedCards() + return rootView + } + + private fun setUpSwipeRefresh() { + swipeRefreshLayout.setOnRefreshListener { + swipeRefreshLayout.isRefreshing = false + mCardsPresenter!!.fetchSavedCards() + } + } + + private fun showEmptyStateView() { + if (activity != null) { + searchView!!.visibility = View.GONE + vStateView!!.visibility = View.VISIBLE + pbCards!!.visibility = View.GONE + val res = resources + ivTransactionsStateIcon + ?.setImageDrawable(res.getDrawable(R.drawable.ic_cards)) + tvTransactionsStateTitle?.text = res.getString(R.string.empty_no_cards_title) + tvTransactionsStateSubtitle?.text = res.getString(R.string.empty_no_cards_subtitle) + } + } + + override fun showErrorStateView(drawable: Int, title: Int, subtitle: Int) { + pbCards!!.visibility = View.GONE + hideSwipeProgress() + vStateView!!.visibility = View.VISIBLE + if (activity != null) { + val res = resources + ivTransactionsStateIcon + ?.setImageDrawable(res.getDrawable(drawable)) + tvTransactionsStateTitle?.text = res.getString(title) + tvTransactionsStateSubtitle?.text = res.getString(subtitle) + } + } + + override fun showFetchingProcess() { + vStateView!!.visibility = View.GONE + searchView!!.visibility = View.GONE + rvCards!!.visibility = View.GONE + pbCards!!.visibility = View.VISIBLE + addCard!!.visibility = View.GONE + } + + private fun hideEmptyStateView() { + vStateView!!.visibility = View.GONE + } + + /** + * A function to setup the Layout Manager and Integrate the RecyclerView with Adapter. + * This function also implements click action on CardList. + */ + private fun setupCardsRecyclerView() { + val llm = LinearLayoutManager(activity) + rvCards!!.layoutManager = llm + rvCards!!.setHasFixedSize(true) + rvCards!!.addItemDecoration( + DividerItemDecoration( + activity, + DividerItemDecoration.VERTICAL + ) + ) + rvCards!!.adapter = mCardsAdapter + rvCards!!.addOnItemTouchListener( + RecyclerItemClickListener( + activity, + object : RecyclerItemClickListener.OnItemClickListener { + override fun onItemClick(childView: View, position: Int) { + val savedCardMenu = PopupMenu(context, childView) + savedCardMenu.menuInflater.inflate( + R.menu.menu_saved_card, + savedCardMenu.menu + ) + savedCardMenu.setOnMenuItemClickListener { item -> + when (item.itemId) { + R.id.edit_card -> { + val addCardDialog = AddCardDialog() + addCardDialog.forEdit = true + addCardDialog.editCard = mCardsAdapter!!.getCards()!![position] + addCardDialog.setCardsPresenter(mCardsPresenter) + addCardDialog.show( + fragmentManager!!, + Constants.EDIT_CARD_DIALOG + ) + } + + R.id.delete_card -> mCardsPresenter!!.deleteCard( + mCardsAdapter!!.getCards()!![position].id + ) + + R.id.cancel -> {} + } + true + } + savedCardMenu.show() + } + + override fun onItemLongPress(childView: View, position: Int) {} + }) + ) + } + + /** + * An overridden function to set Presenter reference in this UI Component. + * @param presenter : Presenter component reference for the Architecture. + */ + + /** + * A function to show Add Card Dialog box. + */ + @OnClick(R.id.btn_add_card) + fun onClickAddCard() { + val addCardDialog = AddCardDialog() + addCardDialog.forEdit = false + addCardDialog.setCardsPresenter(mCardsPresenter) + addCardDialog.show(requireFragmentManager(), Constants.ADD_CARD_DIALOG) + } + + /** + * A function to show setup the cards list with adapter. + * @param cards: List of cards. + */ + override fun showSavedCards(cards: List) { + pbCards!!.visibility = View.GONE + if (cards.isEmpty()) { + showEmptyStateView() + } else { + hideEmptyStateView() + searchView!!.visibility = View.VISIBLE + rvCards!!.visibility = View.VISIBLE + mCardsAdapter!!.setCards(cards) + } + cardsList = cards + mCardsAdapter!!.setCards(cards) + hideSwipeProgress() + addCard!!.visibility = View.VISIBLE + } + + @OnTextChanged(R.id.et_search_cards) + fun filterCards() { + val text = etCardSearch!!.text.toString().trim { it <= ' ' } + var filteredList: MutableList = ArrayList() + if (text.isBlank()) { + filteredList = cardsList.toMutableList() + } else { + for (mycard in cardsList) { + val fullName = mycard.firstName.lowercase(Locale.getDefault()) + " " + + mycard.lastName.lowercase(Locale.getDefault()) + val cardNo = mycard.cardNumber.lowercase(Locale.getDefault()) + if (fullName.contains(text.lowercase(Locale.getDefault())) || + cardNo.contains(text.lowercase(Locale.getDefault())) + ) { + filteredList.add(mycard) + } + } + } + mCardsAdapter!!.setCards(filteredList) + } + + /** + * An overridden method to show a toast message. + */ + override fun showToast(message: String?) { + Toaster.show(view, message) + } + + /** + * An overridden method to show a progress dialog. + */ + override fun showProgressDialog(message: String?) { + super.showProgressDialog(message) + } + + /** + * An overridden method to hide a progress dialog. + */ + override fun hideProgressDialog() { + super.hideProgressDialog() + } + + /** + * An overridden method to hide the swipe progress. + */ + override fun hideSwipeProgress() { + super.hideSwipeProgress() + } + + override fun setPresenter(presenter: CardsContract.CardsPresenter?) { + mCardsPresenter = presenter + } + + companion object { + fun newInstance(): CardsFragment { + val args = Bundle() + val fragment = CardsFragment() + fragment.arguments = args + return fragment + } + } +} \ No newline at end of file