diff --git a/app/build.gradle b/app/build.gradle index 3245137d..b408f519 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -167,32 +167,32 @@ dependencies { testImplementation 'org.robolectric:robolectric:3.3.1' } - // Log out test results to console - tasks.matching { it instanceof Test }.all { - testLogging.events = ["failed", "passed", "skipped"] - } +// Log out test results to console +tasks.matching { it instanceof Test }.all { + testLogging.events = ["failed", "passed", "skipped"] +} - /* +/* Resolves dependency versions across test and production APKs, specifically, transitive dependencies. This is required since Espresso internally has a dependency on support-annotations. */ - configurations.all { - resolutionStrategy { - force 'com.android.support:support-annotations:27.1.1' - force 'com.google.code.findbugs:jsr305:1.3.9' - } +configurations.all { + resolutionStrategy { + force 'com.android.support:support-annotations:27.1.1' + force 'com.google.code.findbugs:jsr305:1.3.9' } +} - /* +/* All direct/transitive dependencies shared between your test and production APKs need to be excluded from the test APK! This is necessary because both APKs will contain the same classes. Not excluding these dependencies from your test configuration will result in an dex pre-verifier error at runtime. More info in this tools bug: (https://code.google.com/p/android/issues/detail?id=192497) */ - configurations.compile.dependencies.each { compileDependency -> +configurations.compile.dependencies.each { compileDependency -> println "Excluding compile dependency: ${compileDependency.getName()}" configurations.androidTestCompile.dependencies.each { androidTestCompileDependency -> configurations.androidTestCompile.exclude module: "${compileDependency.getName()}" } - } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index db3b07b5..a6bde875 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,28 +1,30 @@ + package="org.mifos.mobile.cn"> - - + + + - + - + - + - @@ -36,7 +38,11 @@ - + + + + diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/data/models/beneficiaries/listBeneficiaries.kt b/app/src/main/kotlin/org/mifos/mobile/cn/data/models/beneficiaries/listBeneficiaries.kt new file mode 100644 index 00000000..49e9aade --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/data/models/beneficiaries/listBeneficiaries.kt @@ -0,0 +1,3 @@ +package org.mifos.mobile.cn.data.models.beneficiaries + +data class Beneficiary(val name: String, val description: String, val price: String) \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/injection/component/ActivityComponent.kt b/app/src/main/kotlin/org/mifos/mobile/cn/injection/component/ActivityComponent.kt index 13cbf11c..b67631ae 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/injection/component/ActivityComponent.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/injection/component/ActivityComponent.kt @@ -4,6 +4,7 @@ package org.mifos.mobile.cn.injection.component import dagger.Subcomponent import org.mifos.mobile.cn.injection.PerActivity import org.mifos.mobile.cn.injection.module.ActivityModule +import org.mifos.mobile.cn.ui.mifos.Account import org.mifos.mobile.cn.ui.mifos.DashboardActivity import org.mifos.mobile.cn.ui.mifos.aboutus.AboutUsFragment import org.mifos.mobile.cn.ui.mifos.accounts.AccountsFragment @@ -39,6 +40,8 @@ interface ActivityComponent { fun inject(passcodeActivity: PasscodeActivity) + fun inject(account :Account) + fun inject(launcherActivity: LauncherActivity) fun inject(dashboardActivity: DashboardActivity) diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/adapter/BeneficiariesAdapter.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/adapter/BeneficiariesAdapter.kt new file mode 100644 index 00000000..61c64a50 --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/adapter/BeneficiariesAdapter.kt @@ -0,0 +1,35 @@ +package org.mifos.mobile.cn.ui.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import org.mifos.mobile.cn.R +import org.mifos.mobile.cn.data.models.beneficiaries.Beneficiary + + +class BeneficiariesAdapter(val beneficiariesList: ArrayList) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val v = LayoutInflater.from(parent.context).inflate(R.layout.item_beneficiaries, parent, false) + return ViewHolder(v) + } + + override fun getItemCount(): Int { + return beneficiariesList.size + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val list: Beneficiary = beneficiariesList[position] + holder.textViewName?.text = list.name + holder.textViewDescription?.text = list.description + holder.textViewPrice?.text = list.price + } + + class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val textViewName = itemView.findViewById(R.id.tv_name) + val textViewDescription = itemView.findViewById(R.id.tv_beneficiaries_decription) + val textViewPrice = itemView.findViewById(R.id.tv_price) + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/base/MifosBaseFragment.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/base/MifosBaseFragment.kt index ff78b31b..c47fb543 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/base/MifosBaseFragment.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/base/MifosBaseFragment.kt @@ -63,7 +63,7 @@ open class MifosBaseFragment : Fragment() { callback.showTabLayout(false) } - override fun onAttach(context: Context?) { + override fun onAttach(context: Context?) { super.onAttach(context) val activity = context as? Activity try { diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Account.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Account.kt new file mode 100644 index 00000000..f5395e73 --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Account.kt @@ -0,0 +1,292 @@ +package org.mifos.mobile.cn.ui.mifos + +import android.app.SearchManager +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.viewpager.widget.ViewPager +import androidx.appcompat.widget.SearchView +import android.view.* +import android.widget.Toast +import kotlinx.android.synthetic.main.fragment_client_accounts.* +import org.mifos.mobile.cn.R +import org.mifos.mobile.cn.data.models.accounts.deposit.DepositAccount +import org.mifos.mobile.cn.data.models.accounts.loan.LoanAccount +import org.mifos.mobile.cn.enums.AccountType +import org.mifos.mobile.cn.ui.adapter.ViewPagerAdapter +import org.mifos.mobile.cn.ui.base.MifosBaseActivity +import org.mifos.mobile.cn.ui.base.MifosBaseFragment +import org.mifos.mobile.cn.ui.mifos.accounts.AccountsContract +import org.mifos.mobile.cn.ui.mifos.accounts.AccountsFragment +import org.mifos.mobile.cn.ui.mifos.accounts.AccountsPresenter +import org.mifos.mobile.cn.ui.mifos.accountsFilter.AccountsFilterBottomSheet +import org.mifos.mobile.cn.ui.mifos.customerAccounts.CustomerAccountFragment +import org.mifos.mobile.cn.ui.mifos.loanApplication.loanActivity.LoanApplicationActivity +import org.mifos.mobile.cn.ui.utils.ConstantKeys +import org.mifos.mobile.cn.ui.utils.StatusUtils +import javax.inject.Inject + +class Account : MifosBaseFragment() , AccountsContract.View { + private lateinit var accountType: AccountType + + + @Inject + internal lateinit var accountsPresenter: AccountsPresenter + + companion object { + fun newInstance(accountType: AccountType): CustomerAccountFragment { + val fragment = CustomerAccountFragment() + val args = Bundle() + args.putSerializable(ConstantKeys.ACCOUNT_TYPE, accountType) + fragment.arguments = args + return fragment + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setHasOptionsMenu(true) + if (arguments != null) { + accountType = arguments!!.getSerializable(ConstantKeys.ACCOUNT_TYPE) as AccountType + } + + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val rootview: View = inflater.inflate(R.layout.fragment_client_accounts, + container, false) + (activity as MifosBaseActivity).activityComponent.inject(this) + accountsPresenter.attachView(this) + return rootview + + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setUpViewPagerAndTabLayout() + setToolbarTitle(getString(R.string.accounts)) + accountsPresenter.loadLoanAccounts() + accountsPresenter.loadDepositAccounts() + } + + /** + * Returns tag of Fragment present at `position` + * @param position position of Fragment + * @return Tag of Fragment + */ + private fun getFragmentTag(position: Int): String { + return "android:switcher:" + R.id.viewpager + ":" + position + } + + + private fun setUpViewPagerAndTabLayout() { + val viewPagerAdapter = ViewPagerAdapter(childFragmentManager) + viewPagerAdapter.addFragment(AccountsFragment.newInstance(ConstantKeys.DEPOSIT_ACCOUNTS), + getString(R.string.deposit)) + viewPagerAdapter.addFragment(AccountsFragment.newInstance(ConstantKeys.LOAN_ACCOUNTS), + getString(R.string.loan)) + viewpager.adapter = viewPagerAdapter + viewpager.offscreenPageLimit = 2 + when (accountType) { + AccountType.DEPOSIT -> viewpager.currentItem = 0 + AccountType.LOAN -> viewpager.currentItem = 1 + } + + deposit_toggle_btn.setOnClickListener { + viewpager.currentItem = 0 + } + loan_toggle_btn.setOnClickListener { + viewpager.currentItem = 1 + } + + tabs.setupWithViewPager(viewpager) + viewpager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { + override fun onPageScrolled(position: Int, positionOffset: Float, + positionOffsetPixels: Int) { + activity?.invalidateOptionsMenu() + (activity as MifosBaseActivity).hideKeyBoard(view!!) + } + + override fun onPageSelected(position: Int) {} + + override fun onPageScrollStateChanged(state: Int) {} + }) + + + } + + /** + * It provides with `loanAccounts` fetched from server which is then passed to fragment + * implementing [AccountsContract.View] i.e. [AccountsFragment] which further displays them + * in a recyclerView + * @param loanAccounts [List] of [LoanAccount] + */ + override fun showLoanAccounts(loanAccounts: List) { + + (childFragmentManager.findFragmentByTag(getFragmentTag(1)) as AccountsContract.View) + .showLoanAccounts(loanAccounts) + (childFragmentManager.findFragmentByTag(getFragmentTag(1)) as AccountsContract.View) + .hideProgress() + } + + /** + * It provides with `depositAccounts` fetched from server which is then passed to fragment + * implementing [AccountsContract.View] i.e. [AccountsFragment] which further displays them + * in a recyclerView + * @param depositAccounts [List] of [DepositAccount] + */ + + override fun showDepositAccounts(depositAccounts: List) { + (childFragmentManager.findFragmentByTag(getFragmentTag(0)) as AccountsContract.View) + .showDepositAccounts(depositAccounts) + (childFragmentManager.findFragmentByTag(getFragmentTag(0)) as AccountsContract.View) + .hideProgress() + } + + + override fun showError(message: String) { + (childFragmentManager.findFragmentByTag(getFragmentTag(1)) as AccountsContract.View) + .showError(getString(R.string.loan)) + (childFragmentManager.findFragmentByTag(getFragmentTag(0)) as AccountsContract.View) + .showError(getString(R.string.deposit)) + Toast.makeText(activity, message, Toast.LENGTH_SHORT).show() + } + + override fun showEmptyAccounts(feature: String) { + (childFragmentManager.findFragmentByTag(getFragmentTag(1)) as AccountsContract.View) + .showEmptyAccounts(getString(R.string.loan)) + (childFragmentManager.findFragmentByTag(getFragmentTag(0)) as AccountsContract.View) + .showEmptyAccounts(getString(R.string.deposit)) + } + + + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + inflater?.inflate(R.menu.menu_account, menu) + if (viewpager.currentItem == 1) { + loan_toggle_focus_btn.visibility = View.VISIBLE + deposit_toggle_focus_btn.visibility = View.GONE + iv_apply_for_loan.visibility = View.VISIBLE + applyForLoan() + menu?.findItem(R.id.menu_filter_loan)?.isVisible = true + menu?.findItem(R.id.menu_filter_deposit)?.isVisible = false + menu?.findItem(R.id.menu_search_loan)?.isVisible = true + menu?.findItem(R.id.menu_search_deposit)?.isVisible = false + initSearch(menu!!, AccountType.LOAN) + } else if (viewpager.currentItem == 0) { + deposit_toggle_focus_btn.visibility = View.VISIBLE + loan_toggle_focus_btn.visibility = View.GONE + iv_apply_for_loan.visibility = View.GONE + menu?.findItem(R.id.menu_filter_loan)?.isVisible = false + menu?.findItem(R.id.menu_filter_deposit)?.isVisible = true + menu?.findItem(R.id.menu_search_deposit)?.isVisible = true + menu?.findItem(R.id.menu_search_loan)?.isVisible = false + initSearch(menu!!, AccountType.DEPOSIT) + } + super.onCreateOptionsMenu(menu, inflater) + + } + + private fun applyForLoan() { + iv_apply_for_loan.setOnClickListener(View.OnClickListener { + val intent = Intent(activity, LoanApplicationActivity::class.java) + intent.putExtra(ConstantKeys.CUSTOMER_IDENTIFIER, "customer_identifier") + startActivity(intent) + }) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + when (item?.itemId) { + R.id.menu_filter_loan -> showFilterDialog(AccountType.LOAN) + R.id.menu_filter_deposit -> showFilterDialog(AccountType.DEPOSIT) + } + return true + } + + private fun showFilterDialog(accountType: AccountType) { + val accountFilterBottomSheet = AccountsFilterBottomSheet() + when (accountType) { + AccountType.LOAN -> { + if ((childFragmentManager.findFragmentByTag(getFragmentTag(1)) + as AccountsFragment).currentFilterList == null) { + accountFilterBottomSheet.filterList = StatusUtils.getLoanAccountsStatusList(context!!) + } else { + accountFilterBottomSheet.filterList = (childFragmentManager + .findFragmentByTag(getFragmentTag(1)) + as AccountsFragment).currentFilterList + } + } + + AccountType.DEPOSIT -> { + if ((childFragmentManager.findFragmentByTag(getFragmentTag(0)) + as AccountsFragment).currentFilterList == null) { + accountFilterBottomSheet.filterList = StatusUtils.getDepositAccountsStatusList(context!!) + } else { + accountFilterBottomSheet.filterList = (childFragmentManager + .findFragmentByTag(getFragmentTag(0)) + as AccountsFragment).currentFilterList + } + } + + } + + accountFilterBottomSheet.accountType = accountType + accountFilterBottomSheet.show(childFragmentManager, getString(R.string.filter_accounts)) + } + + /** + * Initializes the search option in [Menu] depending upon `account` + * @param menu Interface for managing the items in a menu. + * @param account An enum of [AccountType] + */ + private fun initSearch(menu: Menu, account: AccountType) { + val manager = activity?.getSystemService(Context.SEARCH_SERVICE) as SearchManager + var search: SearchView? = null + + if (account == AccountType.LOAN) { + search = menu.findItem(R.id.menu_search_loan).actionView as SearchView + } else if (account == AccountType.DEPOSIT) { + search = menu.findItem(R.id.menu_search_deposit).actionView as SearchView + } + + search!!.setSearchableInfo(manager.getSearchableInfo(activity?.componentName)) + search.setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String): Boolean { + return false + } + + override fun onQueryTextChange(newText: String): Boolean { + + if (account == AccountType.LOAN) { + (childFragmentManager.findFragmentByTag( + getFragmentTag(1)) as AccountsFragment).searchLoanAccount(newText) + } else if (account == AccountType.DEPOSIT) { + (childFragmentManager.findFragmentByTag( + getFragmentTag(0)) as AccountsFragment).searchDepositAccount(newText) + } + + return false + } + }) + } + + override fun showProgress() { + + } + + override fun hideProgress() { + + } + + + override fun onResume() { + super.onResume() + (activity as MifosBaseActivity).hideToolbarElevation() + } + + override fun onPause() { + super.onPause() + (activity as MifosBaseActivity).setToolbarElevation() + } + +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/DashboardActivity.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/DashboardActivity.kt index 6895b8e2..e54a334b 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/DashboardActivity.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/DashboardActivity.kt @@ -31,12 +31,15 @@ import org.mifos.mobile.cn.ui.mifos.settings.SettingsFragment import org.mifos.mobile.cn.ui.utils.CircularImageView import org.mifos.mobile.cn.ui.utils.Toaster import android.widget.Toast +import com.mifos.mobile.passcode.utils.PasscodePreferencesHelper +import org.mifos.mobile.cn.ui.mifos.passcode.PasscodeActivity +import org.mifos.mobile.cn.ui.utils.ConstantKeys class DashboardActivity : MifosBaseActivity(), View.OnClickListener, NavigationView.OnNavigationItemSelectedListener { @Inject internal lateinit var preferencesHelper: PreferencesHelper - + private var passcodePreferencesHelper: PasscodePreferencesHelper? = null private lateinit var tvUsername: TextView private lateinit var ivCircularUserProfilePicture: CircularImageView private lateinit var ivTextDrawableUserProfilePicture: ImageView @@ -52,7 +55,7 @@ class DashboardActivity : MifosBaseActivity(), View.OnClickListener, NavigationV setupNavigationBar() setToolbarElevation() - replaceFragment(DashboardFragment.newInstance(), false, R.id.container) + replaceFragment(DashboardFragment.newInstance("customer_identifier"), false, R.id.container) } @@ -160,22 +163,30 @@ class DashboardActivity : MifosBaseActivity(), View.OnClickListener, NavigationV when (item.itemId) { R.id.item_home -> { hideToolbarElevation() - replaceFragment(DashboardFragment.newInstance(), true, R.id.container) + replaceFragment(DashboardFragment.newInstance("customer_identifier"), true, R.id.container) } R.id.item_accounts -> { replaceFragment(CustomerAccountFragment.newInstance(AccountType.DEPOSIT), true, R.id.container) } - R.id.item_logout -> { showLogoutDialog() } - + R.id.item_passcode ->{ + if (this != null) { + passcodePreferencesHelper = PasscodePreferencesHelper(this) + val currentPass: String = passcodePreferencesHelper!!.getPassCode() + passcodePreferencesHelper!!.savePassCode("") + val intent = Intent(this, PasscodeActivity::class.java) + intent.putExtra(ConstantKeys.CURR_PASSWORD, currentPass) + intent.putExtra(ConstantKeys.UPDATE_PASSWORD_KEY, true) + startActivity(intent) + } + } R.id.item_product -> { replaceFragment(ProductFragment.Companion.newInstance(), true, R.id.container) } - R.id.item_recent_transactions -> { replaceFragment(RecentTransactionsFragment.Companion.newInstance(),true,R.id.container) } @@ -185,8 +196,14 @@ class DashboardActivity : MifosBaseActivity(), View.OnClickListener, NavigationV R.id.item_settings -> { replaceFragment(SettingsFragment.newInstance(), true, R.id.container) } + R.id.item_share -> { + val sharingIntent = Intent(android.content.Intent.ACTION_SEND) + sharingIntent.type = "text/plain" + sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getString(R.string.app_link)) + sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, getString(R.string.share_message)) + startActivity(Intent.createChooser(sharingIntent, getString(R.string.share_the_app_link))) + } } - // close the drawer drawerLayout.closeDrawer(GravityCompat.START) setNavigationViewSelectedItem(R.id.item_home) diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Home.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Home.kt new file mode 100644 index 00000000..9700a799 --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Home.kt @@ -0,0 +1,68 @@ +package org.mifos.mobile.cn.ui.mifos + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.google.android.material.bottomsheet.BottomSheetBehavior +import kotlinx.android.synthetic.main.fragment_home.* +import org.mifos.mobile.cn.R +import org.mifos.mobile.cn.ui.base.MifosBaseFragment +import org.mifos.mobile.cn.ui.mifos.recentTransactions.RecentTransactionsFragment + + +class Home : MifosBaseFragment(), View.OnClickListener { + + private lateinit var rootView: View + private lateinit var sheetBehavior: BottomSheetBehavior<*> + + companion object { + fun newInstance(): Home = Home() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + rootView = inflater.inflate(R.layout.fragment_home, container, false) + val ft = childFragmentManager.beginTransaction() + val rt = RecentTransactionsFragment() + ft.replace(R.id.fl_recentTransactions, rt) + ft.addToBackStack(null) + ft.commit() + return rootView + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + sheetBehavior = BottomSheetBehavior.from(rt_bottom_sheet) + sheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { + override fun onStateChanged(bottomSheet: View, newState: Int) { + // React to state change + when (newState) { + BottomSheetBehavior.STATE_HIDDEN -> { + } + BottomSheetBehavior.STATE_EXPANDED -> { + } + BottomSheetBehavior.STATE_COLLAPSED -> { + } + BottomSheetBehavior.STATE_HALF_EXPANDED -> { + } + BottomSheetBehavior.STATE_DRAGGING -> { + } + BottomSheetBehavior.STATE_SETTLING -> { + } + } + } + + override fun onSlide(bottomSheet: View, slideOffset: Float) { + // React to dragging events + } + }) + } + + override fun onClick(view: View) { + + when (view.id) { + } + } + +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Main.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Main.kt new file mode 100644 index 00000000..c20067bd --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Main.kt @@ -0,0 +1,77 @@ +package org.mifos.mobile.cn.ui.mifos + +import android.os.Bundle +import androidx.annotation.NonNull +import androidx.fragment.app.Fragment +import com.google.android.material.bottomnavigation.BottomNavigationView +import org.mifos.mobile.cn.R +import org.mifos.mobile.cn.enums.AccountType +import org.mifos.mobile.cn.ui.base.MifosBaseActivity +import org.mifos.mobile.cn.ui.utils.ConstantKeys +import android.view.MenuItem as MenuItem1 + + +class Main : MifosBaseActivity(), BottomNavigationView.OnNavigationItemSelectedListener { + private var bottomNavigationView: BottomNavigationView? = null + private var menuItem = -1 + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_home) + + bottomNavigationView = findViewById(R.id.bottom_navigation) + setupNavigationBar() + bottomNavigationView?.run { setSelectedItemId(R.id.action_home) + } + + + } + + override fun onNavigationItemSelected(item: MenuItem1): Boolean { + clearFragmentBackStack() + setToolbarElevation() + menuItem = item.itemId +navigateFragment(item.itemId,false) + return true + } + private fun setupNavigationBar() { + + bottomNavigationView?.setOnNavigationItemSelectedListener(object : BottomNavigationView.OnNavigationItemSelectedListener { + override fun onNavigationItemSelected(@NonNull item: android.view.MenuItem): Boolean { + navigateFragment(item.itemId, false) + return true + } + }) + + } + override fun onBackPressed() { + val fragment: Fragment? = supportFragmentManager + .findFragmentById(R.id.bottom_navigation_fragment_container) + if (fragment != null && fragment !is Home && fragment.isVisible()) { + navigateFragment(R.id.action_home, true) + return + } + val count = supportFragmentManager.backStackEntryCount + if (count == 0) { + super.onBackPressed() + //additional code + } else { + supportFragmentManager.popBackStack() + } + } + private fun navigateFragment(id: Int, shouldSelect: Boolean) { + if (shouldSelect) { + bottomNavigationView?.setSelectedItemId(id) + } else { + when (id) { + R.id.action_home -> replaceFragment(Home.newInstance(), false, + R.id.bottom_navigation_fragment_container) + R.id.action_acounts -> replaceFragment(Account.newInstance(AccountType.DEPOSIT), false, + R.id.bottom_navigation_fragment_container) + R.id.action_transfer -> replaceFragment(Transfer.newInstance(), false, + R.id.bottom_navigation_fragment_container) + R.id.action_profile -> replaceFragment(Profile.newInstance(), false, + R.id.bottom_navigation_fragment_container) + } + } + } +} diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Notification.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Notification.kt new file mode 100644 index 00000000..4755ef9b --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Notification.kt @@ -0,0 +1,14 @@ +package org.mifos.mobile.cn.ui.mifos + +import android.os.Bundle +import org.mifos.mobile.cn.R +import org.mifos.mobile.cn.ui.base.MifosBaseActivity + +class Notification: MifosBaseActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_notification) + showBackButton() + setToolbarTitle("Notifications") + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Profile.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Profile.kt new file mode 100644 index 00000000..e7bd605c --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Profile.kt @@ -0,0 +1,57 @@ +package org.mifos.mobile.cn.ui.mifos + +import android.content.Intent +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.PopupWindow +import android.widget.RelativeLayout +import kotlinx.android.synthetic.main.fragment_client_accounts.* +import kotlinx.android.synthetic.main.fragment_profile.* +import kotlinx.android.synthetic.main.menu_layout.* +import org.mifos.mobile.cn.R +import org.mifos.mobile.cn.ui.base.MifosBaseFragment +import org.mifos.mobile.cn.ui.mifos.beneficiaries.BeneficiariesActivity + + +class Profile : MifosBaseFragment(){ + var mypopupWindow: PopupWindow? = null + companion object { + fun newInstance(): Profile = Profile() + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // Inflate the layout for this fragment + getToolbar().setVisibility(View.GONE); + return inflater.inflate(R.layout.fragment_profile, container, false) + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + notify.setOnClickListener { + val intent = Intent(activity, Notification::class.java) + startActivity(intent) + } + setPopUpWindow(view) + val clickListener = View.OnClickListener { view -> + when (view.id) { + R.id.image_menu -> { + mypopupWindow?.showAsDropDown(view,0,0); + } + } + } + + image_menu.setOnClickListener(clickListener) + } + + private fun setPopUpWindow(view: View) { + val view = LayoutInflater.from(context).inflate(R.layout.menu_layout, null) + mypopupWindow = PopupWindow(view, 350, RelativeLayout.LayoutParams.WRAP_CONTENT, true) + val beneficiary = view.findViewById(R.id.text_beneficiary) as RelativeLayout + beneficiary.setOnClickListener(View.OnClickListener { + val intent = Intent(activity, BeneficiariesActivity::class.java) + startActivity(intent) + }) + } + +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/ShowActivity.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/ShowActivity.kt new file mode 100644 index 00000000..0f8c5197 --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/ShowActivity.kt @@ -0,0 +1,13 @@ +package org.mifos.mobile.cn.ui.mifos + +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import org.mifos.mobile.cn.R + +class ShowActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_show) + } +} diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Transfer.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Transfer.kt new file mode 100644 index 00000000..56680c25 --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/Transfer.kt @@ -0,0 +1,20 @@ +package org.mifos.mobile.cn.ui.mifos + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import org.mifos.mobile.cn.R +import org.mifos.mobile.cn.ui.base.MifosBaseFragment + +class Transfer : MifosBaseFragment() { + companion object { + fun newInstance(): Transfer = Transfer() + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // Inflate the layout for this fragment + getToolbar().setVisibility(View.GONE); + return inflater.inflate(R.layout.fragment_transfer, container, false) + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/accounts/AccountsFragment.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/accounts/AccountsFragment.kt index 66d67927..9ed2aa49 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/accounts/AccountsFragment.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/accounts/AccountsFragment.kt @@ -1,14 +1,13 @@ package org.mifos.mobile.cn.ui.mifos.accounts import android.os.Bundle -import android.util.Log -import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.github.therajanmaurya.sweeterror.SweetUIErrorHandler import kotlinx.android.synthetic.main.fragment_accounts.* +import kotlinx.android.synthetic.main.layout_exception_handler.* import org.mifos.mobile.cn.R import org.mifos.mobile.cn.data.models.accounts.deposit.DepositAccount import org.mifos.mobile.cn.data.models.accounts.loan.LoanAccount @@ -19,7 +18,6 @@ import org.mifos.mobile.cn.ui.base.MifosBaseFragment import org.mifos.mobile.cn.ui.utils.ConstantKeys import org.mifos.mobile.cn.ui.utils.Network import javax.inject.Inject -import kotlinx.android.synthetic.main.layout_sweet_exception_handler.* import org.mifos.mobile.cn.data.models.CheckboxStatus import org.mifos.mobile.cn.ui.base.OnItemClickListener import org.mifos.mobile.cn.ui.mifos.customerDepositDetails.CustomerDepositDetailsFragment @@ -115,8 +113,6 @@ class AccountsFragment : MifosBaseFragment(), AccountsContract.View, OnItemClick layoutManager.orientation = LinearLayoutManager.VERTICAL rv_accounts.layoutManager = layoutManager rv_accounts.setHasFixedSize(true) - rv_accounts.addItemDecoration(DividerItemDecoration(activity, - layoutManager.orientation)) btn_try_again.setOnClickListener { retry() } when (accountType) { @@ -143,7 +139,7 @@ class AccountsFragment : MifosBaseFragment(), AccountsContract.View, OnItemClick (activity as MifosBaseActivity).replaceFragment( CustomerDepositDetailsFragment.newInstance( depositAccounts[position].accountIdentifier!!),true,R.id.container - ) + ) } } } diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/beneficiaries/BeneficiariesActivity.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/beneficiaries/BeneficiariesActivity.kt new file mode 100644 index 00000000..74d5351c --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/beneficiaries/BeneficiariesActivity.kt @@ -0,0 +1,66 @@ +package org.mifos.mobile.cn.ui.mifos.beneficiaries + +import android.annotation.SuppressLint +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.widget.LinearLayout +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kotlinx.android.synthetic.main.activity_beneficiaries.* +import org.mifos.mobile.cn.R +import org.mifos.mobile.cn.data.models.beneficiaries.Beneficiary +import org.mifos.mobile.cn.ui.adapter.BeneficiariesAdapter + +class BeneficiariesActivity : AppCompatActivity() { + + @SuppressLint("ResourceAsColor") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_beneficiaries) + + val name: String = getString(R.string.name) + val description: String = getString(R.string.description) + val price: String = getString(R.string.dummy_price) + + beneficiariesRecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) + + val items = ArrayList() + items.add(Beneficiary(name, description, price)) + items.add(Beneficiary(name, description, price)) + items.add(Beneficiary(name, description, price)) + items.add(Beneficiary(name, description, price)) + items.add(Beneficiary(name, description, price)) + items.add(Beneficiary(name, description, price)) + items.add(Beneficiary(name, description, price)) + items.add(Beneficiary(name, description, price)) + items.add(Beneficiary(name, description, price)) + items.add(Beneficiary(name, description, price)) + + val adapter = BeneficiariesAdapter(items) + beneficiariesRecyclerView.adapter = adapter + + btnListBeneficiary.setTextColor(ContextCompat.getColorStateList(getApplicationContext(), R.color.white)) + btnAddBeneficiary.setTextColor(ContextCompat.getColorStateList(getApplicationContext(), R.color.violet)) + btnAddBeneficiary.setBackgroundTintList(ContextCompat.getColorStateList(getApplicationContext(), R.color.white)) + btnListBeneficiary.setBackgroundTintList(ContextCompat.getColorStateList(getApplicationContext(), R.color.violet)) + + btnAddBeneficiary.setOnClickListener { + mBtnAddFocused.visibility = LinearLayout.VISIBLE + mBtnListFocused.visibility = LinearLayout.INVISIBLE + btnListBeneficiary.setTextColor(ContextCompat.getColorStateList(getApplicationContext(), R.color.violet)) + btnAddBeneficiary.setTextColor(ContextCompat.getColorStateList(getApplicationContext(), R.color.white)) + btnListBeneficiary.setBackgroundTintList(ContextCompat.getColorStateList(getApplicationContext(), R.color.white)) + btnAddBeneficiary.setBackgroundTintList(ContextCompat.getColorStateList(getApplicationContext(), R.color.violet)) + } + + btnListBeneficiary.setOnClickListener { + mBtnAddFocused.visibility = LinearLayout.INVISIBLE + mBtnListFocused.visibility = LinearLayout.VISIBLE + btnAddBeneficiary.setTextColor(ContextCompat.getColorStateList(getApplicationContext(), R.color.violet)) + btnListBeneficiary.setTextColor(ContextCompat.getColorStateList(getApplicationContext(), R.color.white)) + btnListBeneficiary.setBackgroundTintList(ContextCompat.getColorStateList(getApplicationContext(), R.color.violet)) + btnAddBeneficiary.setBackgroundTintList(ContextCompat.getColorStateList(getApplicationContext(), R.color.white)) + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/customerAccounts/CustomerAccountFragment.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/customerAccounts/CustomerAccountFragment.kt index 36598fc8..fc87286b 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/customerAccounts/CustomerAccountFragment.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/customerAccounts/CustomerAccountFragment.kt @@ -2,6 +2,7 @@ package org.mifos.mobile.cn.ui.mifos.customerAccounts import android.app.SearchManager import android.content.Context +import android.content.Intent import android.os.Bundle import androidx.viewpager.widget.ViewPager import androidx.appcompat.widget.SearchView @@ -19,6 +20,7 @@ import org.mifos.mobile.cn.ui.mifos.accounts.AccountsContract import org.mifos.mobile.cn.ui.mifos.accounts.AccountsFragment import org.mifos.mobile.cn.ui.mifos.accounts.AccountsPresenter import org.mifos.mobile.cn.ui.mifos.accountsFilter.AccountsFilterBottomSheet +import org.mifos.mobile.cn.ui.mifos.loanApplication.loanActivity.LoanApplicationActivity import org.mifos.mobile.cn.ui.utils.ConstantKeys import org.mifos.mobile.cn.ui.utils.StatusUtils import javax.inject.Inject @@ -93,6 +95,13 @@ class CustomerAccountFragment : MifosBaseFragment(), AccountsContract.View { AccountType.LOAN -> viewpager.currentItem = 1 } + deposit_toggle_btn.setOnClickListener { + viewpager.currentItem = 0 + } + loan_toggle_btn.setOnClickListener { + viewpager.currentItem = 1 + } + tabs.setupWithViewPager(viewpager) viewpager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { override fun onPageScrolled(position: Int, positionOffset: Float, @@ -157,12 +166,19 @@ class CustomerAccountFragment : MifosBaseFragment(), AccountsContract.View { override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { inflater?.inflate(R.menu.menu_account, menu) if (viewpager.currentItem == 1) { + loan_toggle_focus_btn.visibility = View.VISIBLE + deposit_toggle_focus_btn.visibility = View.GONE + iv_apply_for_loan.visibility = View.VISIBLE + applyForLoan() menu?.findItem(R.id.menu_filter_loan)?.isVisible = true menu?.findItem(R.id.menu_filter_deposit)?.isVisible = false menu?.findItem(R.id.menu_search_loan)?.isVisible = true menu?.findItem(R.id.menu_search_deposit)?.isVisible = false initSearch(menu!!, AccountType.LOAN) } else if (viewpager.currentItem == 0) { + deposit_toggle_focus_btn.visibility = View.VISIBLE + loan_toggle_focus_btn.visibility = View.GONE + iv_apply_for_loan.visibility = View.GONE menu?.findItem(R.id.menu_filter_loan)?.isVisible = false menu?.findItem(R.id.menu_filter_deposit)?.isVisible = true menu?.findItem(R.id.menu_search_deposit)?.isVisible = true @@ -173,6 +189,14 @@ class CustomerAccountFragment : MifosBaseFragment(), AccountsContract.View { } + private fun applyForLoan() { + iv_apply_for_loan.setOnClickListener(View.OnClickListener { + val intent = Intent(activity, LoanApplicationActivity::class.java) + intent.putExtra(ConstantKeys.CUSTOMER_IDENTIFIER, "customer_identifier") + startActivity(intent) + }) + } + override fun onOptionsItemSelected(item: MenuItem?): Boolean { when (item?.itemId) { R.id.menu_filter_loan -> showFilterDialog(AccountType.LOAN) diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/customerProfile/CustomerProfileActivity.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/customerProfile/CustomerProfileActivity.kt index 27cf1165..00b253c8 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/customerProfile/CustomerProfileActivity.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/customerProfile/CustomerProfileActivity.kt @@ -98,6 +98,10 @@ class CustomerProfileActivity: MifosBaseActivity(),CustomerProfileContract.View resources.getString( R.string.dialog_message_write_permission_for_share_never_ask_again), ConstantKeys.PERMISSIONS_WRITE_EXTERNAL_STORAGE_STATUS) + if (CheckSelfPermissionAndRequest.checkSelfPermission(this, + android.Manifest.permission.WRITE_EXTERNAL_STORAGE)){ + shareImage() + } } override fun loadCustomerPortrait() { diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/dashboard/DashboardFragment.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/dashboard/DashboardFragment.kt index 977343ff..bdbc0649 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/dashboard/DashboardFragment.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/dashboard/DashboardFragment.kt @@ -5,28 +5,33 @@ import android.content.Intent import android.os.Bundle import android.view.* +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import kotlinx.android.synthetic.main.fragment_dashboard.* import org.mifos.mobile.cn.data.models.customer.Customer import org.mifos.mobile.cn.R import org.mifos.mobile.cn.enums.AccountType import org.mifos.mobile.cn.ui.base.MifosBaseActivity import org.mifos.mobile.cn.ui.base.MifosBaseFragment +import org.mifos.mobile.cn.ui.mifos.Main import org.mifos.mobile.cn.ui.mifos.customerAccounts.CustomerAccountFragment import org.mifos.mobile.cn.ui.mifos.customerDetails.CustomerDetailsActivity +import org.mifos.mobile.cn.ui.mifos.customerProfile.CustomerProfileActivity import org.mifos.mobile.cn.ui.mifos.loanApplication.loanActivity.LoanApplicationActivity import org.mifos.mobile.cn.ui.mifos.recentTransactions.RecentTransactionsFragment import org.mifos.mobile.cn.ui.utils.ConstantKeys -class DashboardFragment : MifosBaseFragment(), View.OnClickListener { - +class DashboardFragment : MifosBaseFragment(), View.OnClickListener, SwipeRefreshLayout.OnRefreshListener { + private lateinit var customerIdentification: String private lateinit var rootView: View private lateinit var customer: Customer + companion object { - fun newInstance(): DashboardFragment { + fun newInstance(identifier: String): DashboardFragment { val fragment = DashboardFragment() val args = Bundle() + args.putString(ConstantKeys.CUSTOMER_IDENTIFIER, identifier) fragment.arguments = args return fragment } @@ -38,6 +43,10 @@ class DashboardFragment : MifosBaseFragment(), View.OnClickListener { rootView = inflater.inflate(R.layout.fragment_dashboard, container, false) setHasOptionsMenu(true) setToolbarTitle(getString(R.string.home)) + if (arguments != null) { + 1 + customerIdentification = arguments!!.getString(ConstantKeys.CUSTOMER_IDENTIFIER) + } return rootView } @@ -47,6 +56,8 @@ class DashboardFragment : MifosBaseFragment(), View.OnClickListener { ll_accounts.setOnClickListener(this) ll_account_overview.setOnClickListener(this) ll_recent_transactions.setOnClickListener(this) + ll_charges.setOnClickListener(this) + swipe_home_container.setOnRefreshListener(this) } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { @@ -54,6 +65,11 @@ class DashboardFragment : MifosBaseFragment(), View.OnClickListener { super.onCreateOptionsMenu(menu, inflater) } + override fun onResume() { + super.onResume() + this.onCreate(null) + } + override fun onClick(view: View) { when (view.id) { @@ -69,6 +85,9 @@ class DashboardFragment : MifosBaseFragment(), View.OnClickListener { R.id.ll_recent_transactions -> { showRecentTransactions() } + R.id.ll_charges ->{ + test() + } } } @@ -81,18 +100,30 @@ class DashboardFragment : MifosBaseFragment(), View.OnClickListener { private fun openAccount() { (activity as MifosBaseActivity) .replaceFragment(CustomerAccountFragment.newInstance(AccountType.DEPOSIT), - true, R.id.container) + true, R.id.container) } - private fun showCustomerDetails(){ - val intent = Intent(activity,CustomerDetailsActivity::class.java) - intent.putExtra(ConstantKeys.CUSTOMER_IDENTIFIER,"customer_identifier") - startActivity(intent) + + private fun showCustomerDetails() { + val intent = Intent(activity, CustomerDetailsActivity::class.java) + intent.putExtra(ConstantKeys.CUSTOMER_IDENTIFIER, "customer_identifier") + startActivity(intent) } - private fun showRecentTransactions(){ + + private fun showRecentTransactions() { (activity as MifosBaseActivity) .replaceFragment(RecentTransactionsFragment.Companion.newInstance(), - true,R.id.container) + true, R.id.container) + } + private fun test(){ + val intent = Intent(activity, Main::class.java) + intent.putExtra(ConstantKeys.CUSTOMER_IDENTIFIER, "customer_identifier") + startActivity(intent) + } + + override fun onRefresh() { + this.onResume() + swipe_home_container.isRefreshing = false } } \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/login/LoginActivity.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/login/LoginActivity.kt index 31a84ca1..5427c155 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/login/LoginActivity.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/login/LoginActivity.kt @@ -13,6 +13,7 @@ import org.mifos.mobile.cn.ui.utils.ConstantKeys import org.mifos.mobile.cn.ui.utils.Toaster import javax.inject.Inject import kotlinx.android.synthetic.main.activity_login.* +import org.mifos.mobile.cn.ui.mifos.signup.SignupActivity class LoginActivity : MifosBaseActivity(), LoginContract.View, View.OnClickListener { @@ -27,23 +28,31 @@ class LoginActivity : MifosBaseActivity(), LoginContract.View, View.OnClickListe override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) - setToolbarTitle(getString(R.string.login)) + //setToolbarTitle(getString(R.string.login)) activityComponent.inject(this) loginPresenter.attachView(this) preferencesHelper.clear() //TODO:remove this while implementing API btnLogin.setOnClickListener(this) + create.setOnClickListener(this) } override fun onClick(view: View) { when (view.id) { R.id.btnLogin -> login() + R.id.create -> signup() } } + private fun signup() { + val intent = Intent(this, SignupActivity::class.java) + startActivity(intent) + finish() + } + internal fun login() { val username = etUsername.text.toString().trim() diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/passcode/PasscodeActivity.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/passcode/PasscodeActivity.kt index f04d00e1..023b1318 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/passcode/PasscodeActivity.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/passcode/PasscodeActivity.kt @@ -1,19 +1,47 @@ package org.mifos.mobile.cn.ui.mifos.passcode +import android.Manifest import android.content.DialogInterface import android.content.Intent +import android.os.Bundle import android.view.View import android.widget.Toast import com.mifos.mobile.passcode.MifosPassCodeActivity import com.mifos.mobile.passcode.utils.EncryptionUtil +import com.mifos.mobile.passcode.utils.PasscodePreferencesHelper import org.mifos.mobile.cn.R import org.mifos.mobile.cn.ui.mifos.DashboardActivity import org.mifos.mobile.cn.ui.mifos.login.LoginActivity +import org.mifos.mobile.cn.ui.utils.CheckSelfPermissionAndRequest.checkSelfPermission +import org.mifos.mobile.cn.ui.utils.CheckSelfPermissionAndRequest.requestPermission +import org.mifos.mobile.cn.ui.utils.ConstantKeys import org.mifos.mobile.cn.ui.utils.MaterialDialog import org.mifos.mobile.cn.ui.utils.Toaster class PasscodeActivity : MifosPassCodeActivity(){ + private var currPass = "" + private var updatePassword = false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (!checkSelfPermission(this, + Manifest.permission.READ_PHONE_STATE)) { + requestPermission() + } + + } + + private fun requestPermission() { + requestPermission( + this, + Manifest.permission.READ_PHONE_STATE, + ConstantKeys.PERMISSIONS_REQUEST_READ_PHONE_STATE, + resources.getString( + R.string.dialog_message_phone_state_permission_denied_prompt), + resources.getString(R.string.dialog_message_phone_state_permission_never_ask_again), + ConstantKeys.PERMISSIONS_READ_PHONE_STATE_STATUS) + } override fun getLogo(): Int { return R.drawable.mifos_logo_new @@ -49,5 +77,12 @@ class PasscodeActivity : MifosPassCodeActivity(){ override fun getEncryptionType(): Int { return EncryptionUtil.FINERACT_CN } - + override fun onBackPressed() { + super.onBackPressed() + if (updatePassword && !currPass.isEmpty()) { + val helper = PasscodePreferencesHelper(this) + helper.savePassCode(currPass) + } + finish() + } } \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/recentTransactions/RecentTransactionsFragment.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/recentTransactions/RecentTransactionsFragment.kt index 743a3db2..c0ae1fc3 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/recentTransactions/RecentTransactionsFragment.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/recentTransactions/RecentTransactionsFragment.kt @@ -37,7 +37,6 @@ SwipeRefreshLayout.OnRefreshListener{ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setHasOptionsMenu(true) recentTransactionList = ArrayList() } @@ -62,7 +61,6 @@ SwipeRefreshLayout.OnRefreshListener{ } override fun showUserInterface() { - setToolbarTitle("Recent Transactions") val layoutManager = LinearLayoutManager(activity) layoutManager.orientation = RecyclerView.VERTICAL rvRecentTransactions.layoutManager = layoutManager @@ -86,7 +84,7 @@ SwipeRefreshLayout.OnRefreshListener{ showRecyclerView(false) } - override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { super.onCreateOptionsMenu(menu, inflater) inflater?.inflate(R.menu.menu_transactions_search,menu) setUpSearchInterface(menu) diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/settings/SettingsFragment.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/settings/SettingsFragment.kt index 21f01cec..7e6913b1 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/settings/SettingsFragment.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/settings/SettingsFragment.kt @@ -1,13 +1,16 @@ package org.mifos.mobile.cn.ui.mifos.settings -import android.content.Context -import android.net.Uri +import android.content.Intent import android.os.Bundle -import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.mifos.mobile.passcode.utils.PasscodePreferencesHelper import org.mifos.mobile.cn.R +import org.mifos.mobile.cn.ui.mifos.passcode.PasscodeActivity +import org.mifos.mobile.cn.ui.utils.ConstantKeys + // TODO: Rename parameter arguments, choose names that match // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER @@ -27,6 +30,7 @@ class SettingsFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // Inflate the layout for this fragment + return inflater.inflate(R.layout.fragment_settings, container, false) } diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/signup/SignupActivity.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/signup/SignupActivity.kt new file mode 100644 index 00000000..1ff853f8 --- /dev/null +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/mifos/signup/SignupActivity.kt @@ -0,0 +1,15 @@ +package org.mifos.mobile.cn.ui.mifos.signup + +import android.os.Bundle +import android.view.View +import kotlinx.android.synthetic.main.activity_login.* +import org.mifos.mobile.cn.R +import org.mifos.mobile.cn.ui.base.MifosBaseActivity +import org.mifos.mobile.cn.ui.mifos.login.LoginContract + +class SignupActivity: MifosBaseActivity(){ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_signup) + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/utils/ConstantKeys.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/utils/ConstantKeys.kt index 64fabae7..348066d7 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/utils/ConstantKeys.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/utils/ConstantKeys.kt @@ -10,7 +10,11 @@ object ConstantKeys { const val REQUEST_PERMISSION_SETTING = 254 const val PERMISSION_REQUEST_ALL = 4 const val PERMISSION_REQUEST_CAMERA = 5 - + const val PASSCODE = "Passcode" + const val CURR_PASSWORD = "currentPassword" + const val PERMISSIONS_READ_PHONE_STATE_STATUS = "read_phone_status" + const val PERMISSIONS_REQUEST_READ_PHONE_STATE = 2 + const val UPDATE_PASSWORD_KEY = "updatePassword" const val PERMISSIONS_WRITE_EXTERNAL_STORAGE_STATUS = "write_status" const val PERMISSION_READ_EXTERNAL_STORAGE_STATUS = "read_status" const val PERMISSIONS_CAMERA_STATUS = "camera_status" diff --git a/app/src/main/kotlin/org/mifos/mobile/cn/ui/utils/Utils.kt b/app/src/main/kotlin/org/mifos/mobile/cn/ui/utils/Utils.kt index 8802c272..5e4fa9a0 100644 --- a/app/src/main/kotlin/org/mifos/mobile/cn/ui/utils/Utils.kt +++ b/app/src/main/kotlin/org/mifos/mobile/cn/ui/utils/Utils.kt @@ -1,6 +1,7 @@ package org.mifos.mobile.cn.ui.utils import android.content.Context +import android.content.res.Resources import android.graphics.PorterDuff import android.view.Menu import androidx.core.content.ContextCompat @@ -15,6 +16,13 @@ import java.util.* class Utils { companion object { + fun dpToPx(dp: Int): Int { + return ((dp * Resources.getSystem().displayMetrics.density).toInt()); + } + + fun pxToDp(px: Int, context: Context): Int { + return ((px / Resources.getSystem().displayMetrics.density).toInt()); + } fun getPrecision(aDouble: Double?): String { return String.format(Locale.ENGLISH, "%.2f", aDouble) } diff --git a/app/src/main/res/drawable-v24/arrow.png b/app/src/main/res/drawable-v24/arrow.png new file mode 100644 index 00000000..015dbf8c Binary files /dev/null and b/app/src/main/res/drawable-v24/arrow.png differ diff --git a/app/src/main/res/drawable-v24/circle_arrow.png b/app/src/main/res/drawable-v24/circle_arrow.png new file mode 100644 index 00000000..a04090a9 Binary files /dev/null and b/app/src/main/res/drawable-v24/circle_arrow.png differ diff --git a/app/src/main/res/drawable-v24/drawable_editable_image_hint.xml b/app/src/main/res/drawable-v24/drawable_editable_image_hint.xml new file mode 100644 index 00000000..9790605f --- /dev/null +++ b/app/src/main/res/drawable-v24/drawable_editable_image_hint.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_cam.png b/app/src/main/res/drawable-v24/ic_cam.png new file mode 100644 index 00000000..22a721d6 Binary files /dev/null and b/app/src/main/res/drawable-v24/ic_cam.png differ diff --git a/app/src/main/res/drawable-v24/ic_camera.xml b/app/src/main/res/drawable-v24/ic_camera.xml new file mode 100644 index 00000000..7b9b5cd4 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_camera.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable-v24/ic_error_state.xml b/app/src/main/res/drawable-v24/ic_error_state.xml new file mode 100644 index 00000000..c01af649 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_error_state.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v24/ic_transaction.xml b/app/src/main/res/drawable-v24/ic_transaction.xml new file mode 100644 index 00000000..fad1fe3e --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_transaction.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable-v24/nav_drawer.png b/app/src/main/res/drawable-v24/nav_drawer.png new file mode 100644 index 00000000..fe9a429c Binary files /dev/null and b/app/src/main/res/drawable-v24/nav_drawer.png differ diff --git a/app/src/main/res/drawable-v24/outline_button.png b/app/src/main/res/drawable-v24/outline_button.png new file mode 100644 index 00000000..958105dc Binary files /dev/null and b/app/src/main/res/drawable-v24/outline_button.png differ diff --git a/app/src/main/res/drawable-v24/profile.png b/app/src/main/res/drawable-v24/profile.png new file mode 100644 index 00000000..0dcfeb06 Binary files /dev/null and b/app/src/main/res/drawable-v24/profile.png differ diff --git a/app/src/main/res/drawable-v24/shape_bottom_sheet_dialog_grip.xml b/app/src/main/res/drawable-v24/shape_bottom_sheet_dialog_grip.xml new file mode 100644 index 00000000..792c8361 --- /dev/null +++ b/app/src/main/res/drawable-v24/shape_bottom_sheet_dialog_grip.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/bottomview_selector.xml b/app/src/main/res/drawable/bottomview_selector.xml new file mode 100644 index 00000000..b18401d2 --- /dev/null +++ b/app/src/main/res/drawable/bottomview_selector.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/chip_outline.xml b/app/src/main/res/drawable/chip_outline.xml new file mode 100644 index 00000000..4d772740 --- /dev/null +++ b/app/src/main/res/drawable/chip_outline.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/chip_outline_selected.xml b/app/src/main/res/drawable/chip_outline_selected.xml new file mode 100644 index 00000000..0dae89da --- /dev/null +++ b/app/src/main/res/drawable/chip_outline_selected.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/gray_box.xml b/app/src/main/res/drawable/gray_box.xml new file mode 100644 index 00000000..a23f364f --- /dev/null +++ b/app/src/main/res/drawable/gray_box.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/greyborder.xml b/app/src/main/res/drawable/greyborder.xml new file mode 100644 index 00000000..4a9acdf3 --- /dev/null +++ b/app/src/main/res/drawable/greyborder.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_account.xml b/app/src/main/res/drawable/ic_account.xml new file mode 100644 index 00000000..b9d5db60 --- /dev/null +++ b/app/src/main/res/drawable/ic_account.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_add_circle_black_24dp.xml b/app/src/main/res/drawable/ic_add_circle_black_24dp.xml new file mode 100644 index 00000000..be629131 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_circle_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home.xml b/app/src/main/res/drawable/ic_home.xml new file mode 100644 index 00000000..70fb2910 --- /dev/null +++ b/app/src/main/res/drawable/ic_home.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_profile.xml b/app/src/main/res/drawable/ic_profile.xml new file mode 100644 index 00000000..76785806 --- /dev/null +++ b/app/src/main/res/drawable/ic_profile.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_swap_horiz.xml b/app/src/main/res/drawable/ic_swap_horiz.xml new file mode 100644 index 00000000..f9df11df --- /dev/null +++ b/app/src/main/res/drawable/ic_swap_horiz.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/launcher_background.xml b/app/src/main/res/drawable/launcher_background.xml index 03dd5b62..5aca7c3d 100644 --- a/app/src/main/res/drawable/launcher_background.xml +++ b/app/src/main/res/drawable/launcher_background.xml @@ -4,8 +4,7 @@ - diff --git a/app/src/main/res/drawable/login_bg.png b/app/src/main/res/drawable/login_bg.png new file mode 100644 index 00000000..3fbe488e Binary files /dev/null and b/app/src/main/res/drawable/login_bg.png differ diff --git a/app/src/main/res/drawable/mifos_splash_screen_logo.png b/app/src/main/res/drawable/mifos_splash_screen_logo.png new file mode 100644 index 00000000..c1819abf Binary files /dev/null and b/app/src/main/res/drawable/mifos_splash_screen_logo.png differ diff --git a/app/src/main/res/drawable/more_icon.png b/app/src/main/res/drawable/more_icon.png new file mode 100644 index 00000000..82f45f34 Binary files /dev/null and b/app/src/main/res/drawable/more_icon.png differ diff --git a/app/src/main/res/drawable/notification.xml b/app/src/main/res/drawable/notification.xml new file mode 100644 index 00000000..3ebf17e7 --- /dev/null +++ b/app/src/main/res/drawable/notification.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/notification_circle.xml b/app/src/main/res/drawable/notification_circle.xml index f112527e..721e9c80 100644 --- a/app/src/main/res/drawable/notification_circle.xml +++ b/app/src/main/res/drawable/notification_circle.xml @@ -2,7 +2,7 @@ + android:width="35dp" + android:height="35dp" /> \ No newline at end of file diff --git a/app/src/main/res/drawable/pick_contact.png b/app/src/main/res/drawable/pick_contact.png new file mode 100644 index 00000000..0a33393a Binary files /dev/null and b/app/src/main/res/drawable/pick_contact.png differ diff --git a/app/src/main/res/drawable/qrcode.png b/app/src/main/res/drawable/qrcode.png new file mode 100644 index 00000000..c9fef9c3 Binary files /dev/null and b/app/src/main/res/drawable/qrcode.png differ diff --git a/app/src/main/res/drawable/round_gray.xml b/app/src/main/res/drawable/round_gray.xml new file mode 100644 index 00000000..81cf96d7 --- /dev/null +++ b/app/src/main/res/drawable/round_gray.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/rounded_shape.xml b/app/src/main/res/drawable/rounded_shape.xml new file mode 100644 index 00000000..1f0b683a --- /dev/null +++ b/app/src/main/res/drawable/rounded_shape.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_tab.xml b/app/src/main/res/drawable/selector_tab.xml new file mode 100644 index 00000000..6cc08e7d --- /dev/null +++ b/app/src/main/res/drawable/selector_tab.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/violet_concave.xml b/app/src/main/res/drawable/violet_concave.xml new file mode 100644 index 00000000..518afafc --- /dev/null +++ b/app/src/main/res/drawable/violet_concave.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/violet_round.xml b/app/src/main/res/drawable/violet_round.xml new file mode 100644 index 00000000..30cca1a2 --- /dev/null +++ b/app/src/main/res/drawable/violet_round.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/white_card.xml b/app/src/main/res/drawable/white_card.xml new file mode 100644 index 00000000..57a1b6f1 --- /dev/null +++ b/app/src/main/res/drawable/white_card.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_beneficiaries.xml b/app/src/main/res/layout/activity_beneficiaries.xml new file mode 100644 index 00000000..2be7d0c8 --- /dev/null +++ b/app/src/main/res/layout/activity_beneficiaries.xml @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml new file mode 100644 index 00000000..1377e128 --- /dev/null +++ b/app/src/main/res/layout/activity_home.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_loan_application.xml b/app/src/main/res/layout/activity_loan_application.xml index 20819ace..a59bb838 100644 --- a/app/src/main/res/layout/activity_loan_application.xml +++ b/app/src/main/res/layout/activity_loan_application.xml @@ -1,24 +1,48 @@ + android:layout_width="match_parent" + android:background="@color/violet"> + + - - - + + + + - + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 5f9704e1..598de8a6 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -1,98 +1,105 @@ - - + - - - - - - - + android:layout_height="wrap_content" + android:fontFamily="@font/productsans" + android:text="@string/mifos_mobile_cn" + android:textAlignment="center" + android:textColor="@color/white" + android:textSize="@dimen/text_size_35sp" /> + android:layout_marginBottom="@dimen/layout_padding_20dp" + android:backgroundTint="@color/white" + android:textColorHint="@color/white"> - + android:fontFamily="@font/productsans" + android:hint="@string/username" + android:inputType="text" + android:textColor="@color/white" /> + android:layout_height="wrap_content" + android:backgroundTint="@color/white" + android:textColorHint="@color/white" + app:passwordToggleEnabled="true" + app:passwordToggleTint="@color/white"> - + android:fontFamily="@font/productsans" + android:hint="@string/password" + android:inputType="textPassword" + android:textColor="@color/white" + android:textColorHighlight="@color/white" /> -