From ca079b5a87c4f9f72d8253f3eb9efc4fb0a6a14d Mon Sep 17 00:00:00 2001 From: Vishwajeet Srivastava Date: Mon, 6 Jun 2016 19:59:56 +0530 Subject: [PATCH 1/2] authentication, client list, navigation drawer, saving and loan account listing added login authentication added Simple login screen added user authentication added authentication completed with removal of existing issues singleton pattern implemented, refactoring client list,navigation drawer, saving and loan account list features added Handle single clientid case and code refactoring --- .idea/gradle.xml | 7 +- .idea/misc.xml | 46 +---- .idea/modules.xml | 2 +- .idea/runConfigurations.xml | 12 -- app/build.gradle | 10 ++ app/src/main/AndroidManifest.xml | 21 ++- .../adapters/ClientListAdapter.java | 83 +++++++++ .../adapters/LoanAccountsListAdapter.java | 74 ++++++++ .../adapters/SavingAccountsListAdapter.java | 75 ++++++++ .../adapters/ViewPagerAdapter.java | 41 +++++ .../api/ApiRequestInterceptor.java | 49 ++++++ .../selfserviceapp/api/BaseApiManager.java | 73 ++++++++ .../org/mifos/selfserviceapp/api/BaseURL.java | 21 +++ .../mifos/selfserviceapp/api/DataManager.java | 37 ++++ .../api/model/ApiEndPoints.java | 14 ++ .../api/services/AuthenticationService.java | 20 +++ .../api/services/ClientService.java | 19 +++ .../api/services/LoanAccountsListService.java | 17 ++ .../services/SavingAccountsListService.java | 17 ++ .../org/mifos/selfserviceapp/data/Client.java | 117 +++++++++++++ .../org/mifos/selfserviceapp/data/User.java | 70 ++++++++ .../data/accounts/LoanAccount.java | 47 +++++ .../data/accounts/SavingAccount.java | 48 ++++++ .../home/ClientAccountsActivity.java | 43 +++++ .../home/ClientListFragment.java | 146 ++++++++++++++++ .../home/ClientListMvpView.java | 22 +++ .../home/ClientListPresenter.java | 44 +++++ .../selfserviceapp/home/HomeActivity.java | 161 ++++++++++++++++++ .../home/LoanAccountsListFragment.java | 143 ++++++++++++++++ .../home/LoanAccountsListPresenter.java | 46 +++++ .../home/LoanAccountsListView.java | 21 +++ .../home/SavingAccountsListFragment.java | 142 +++++++++++++++ .../home/SavingAccountsListPresenter.java | 44 +++++ .../home/SavingAccountsListView.java | 21 +++ .../selfserviceapp/login/LoginActivity.java | 122 +++++++++++++ .../selfserviceapp/login/LoginPresenter.java | 62 +++++++ .../mifos/selfserviceapp/login/LoginView.java | 23 +++ .../presenters/BasePresenter.java | 4 +- .../mifos/selfserviceapp/utils/Constants.java | 14 ++ .../selfserviceapp/utils/PrefManager.java | 85 +++++++++ .../utils/RecyclerItemClickListener.java | 125 ++++++++++++++ .../res/layout/activity_client_accounts.xml | 32 ++++ app/src/main/res/layout/activity_home.xml | 28 +++ app/src/main/res/layout/activity_login.xml | 57 +++++++ .../main/res/layout/fragment_client_list.xml | 14 ++ .../layout/fragment_loan_accounts_list.xml | 14 ++ .../layout/fragment_saving_accounts_list.xml | 14 ++ app/src/main/res/layout/nav_drawer_header.xml | 22 +++ app/src/main/res/layout/row_client_name.xml | 40 +++++ app/src/main/res/layout/row_loan_account.xml | 40 +++++ .../main/res/layout/row_saving_account.xml | 40 +++++ app/src/main/res/layout/toolbar.xml | 8 + app/src/main/res/menu/menu_nav_drawer.xml | 55 ++++++ app/src/main/res/mipmap-hdpi/ic_clients.png | Bin 0 -> 1001 bytes app/src/main/res/mipmap-hdpi/mifos_logo.jpg | Bin 0 -> 75684 bytes app/src/main/res/values/colors.xml | 56 +++++- app/src/main/res/values/dimens.xml | 4 + app/src/main/res/values/ids.xml | 4 + app/src/main/res/values/strings.xml | 29 ++++ app/src/main/res/values/styles.xml | 22 ++- app/src/main/res/values/styles_frame.xml | 15 ++ app/src/main/res/values/styles_linear.xml | 23 +++ app/src/main/res/values/styles_toolbar.xml | 21 +++ build.gradle | 1 + 64 files changed, 2653 insertions(+), 74 deletions(-) delete mode 100644 .idea/runConfigurations.xml create mode 100644 app/src/main/java/org/mifos/selfserviceapp/adapters/ClientListAdapter.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/adapters/LoanAccountsListAdapter.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/adapters/SavingAccountsListAdapter.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/adapters/ViewPagerAdapter.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/api/ApiRequestInterceptor.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/api/BaseApiManager.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/api/BaseURL.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/api/DataManager.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/api/model/ApiEndPoints.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/api/services/AuthenticationService.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/api/services/ClientService.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/api/services/LoanAccountsListService.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/api/services/SavingAccountsListService.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/data/Client.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/data/User.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/data/accounts/LoanAccount.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/data/accounts/SavingAccount.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/ClientAccountsActivity.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/ClientListFragment.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/ClientListMvpView.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/ClientListPresenter.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/HomeActivity.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListFragment.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListPresenter.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListView.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListFragment.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListPresenter.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListView.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/login/LoginActivity.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/login/LoginPresenter.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/login/LoginView.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/utils/Constants.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/utils/PrefManager.java create mode 100644 app/src/main/java/org/mifos/selfserviceapp/utils/RecyclerItemClickListener.java create mode 100644 app/src/main/res/layout/activity_client_accounts.xml create mode 100644 app/src/main/res/layout/activity_home.xml create mode 100644 app/src/main/res/layout/activity_login.xml create mode 100644 app/src/main/res/layout/fragment_client_list.xml create mode 100644 app/src/main/res/layout/fragment_loan_accounts_list.xml create mode 100644 app/src/main/res/layout/fragment_saving_accounts_list.xml create mode 100644 app/src/main/res/layout/nav_drawer_header.xml create mode 100644 app/src/main/res/layout/row_client_name.xml create mode 100644 app/src/main/res/layout/row_loan_account.xml create mode 100644 app/src/main/res/layout/row_saving_account.xml create mode 100644 app/src/main/res/layout/toolbar.xml create mode 100644 app/src/main/res/menu/menu_nav_drawer.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_clients.png create mode 100644 app/src/main/res/mipmap-hdpi/mifos_logo.jpg create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/ids.xml create mode 100644 app/src/main/res/values/styles_frame.xml create mode 100644 app/src/main/res/values/styles_linear.xml create mode 100644 app/src/main/res/values/styles_toolbar.xml diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 508b3d9b8..7ac24c777 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -11,12 +11,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index 5cef573e1..5484635a4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,9 +3,6 @@ - - - - - - - - - - - Android - - - Android > Lint > Correctness - - - Java - - - Java language level migration aidsJava - - - - - Android - - - - - - - - - - - - - - - - + - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 98ed72a04..5f45b01b2 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,8 +2,8 @@ - + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460d8..000000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 63b93e1df..1174b4839 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.application' +apply plugin: 'android-apt' android { compileSdkVersion 23 @@ -20,7 +21,16 @@ android { } dependencies { + final RETROFIT_VERSION = '2.0.0-beta3' + compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.4.0' + compile 'com.android.support:design:23.4.0' + compile 'com.jakewharton:butterknife:8.0.1' + compile "com.squareup.retrofit2:retrofit:$RETROFIT_VERSION" + compile "com.squareup.retrofit2:converter-gson:$RETROFIT_VERSION" + compile 'com.squareup.okhttp3:logging-interceptor:3.0.0-RC1' + compile 'com.squareup.okhttp3:okhttp:3.0.0-RC1' + apt 'com.jakewharton:butterknife-compiler:8.0.1' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2a139b8a9..6fea96192 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,13 +1,32 @@ + + + android:theme="@style/MaterialAppTheme"> + + + + + + + + diff --git a/app/src/main/java/org/mifos/selfserviceapp/adapters/ClientListAdapter.java b/app/src/main/java/org/mifos/selfserviceapp/adapters/ClientListAdapter.java new file mode 100644 index 000000000..e8be588da --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/adapters/ClientListAdapter.java @@ -0,0 +1,83 @@ +package org.mifos.selfserviceapp.adapters; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.data.Client; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * @author Vishwajeet + * @since 20/06/16 + */ + +public class ClientListAdapter extends RecyclerView.Adapter { + + LayoutInflater layoutInflater; + List listItems; + private Context mContext; + + public ClientListAdapter(Context context, List listItems) { + + layoutInflater = LayoutInflater.from(context); + this.listItems = listItems; + this.mContext = context; + } + + public Client getItem(int position) { + return listItems.get(position); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + RecyclerView.ViewHolder vh; + View v = LayoutInflater.from(parent.getContext()).inflate( + R.layout.row_client_name, parent, false); + vh = new ViewHolder(v); + return vh; + } + + @Override + public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { + if (holder instanceof RecyclerView.ViewHolder) { + + Client client = getItem(position); + ((ViewHolder) holder).tv_clientName.setText(client.getFirstname() + " " + client + .getLastname()); + ((ViewHolder) holder).tv_clientAccountNumber.setText(client.getAccountNo().toString()); + + } + } + + @Override + public long getItemId(int i) { + return 0; + } + + @Override + public int getItemCount() { + return listItems.size(); + } + + + public static class ViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.tv_clientName) + TextView tv_clientName; + @BindView(R.id.tv_clientAccountNumber) + TextView tv_clientAccountNumber; + + public ViewHolder(View v) { + super(v); + ButterKnife.bind(this, v); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/mifos/selfserviceapp/adapters/LoanAccountsListAdapter.java b/app/src/main/java/org/mifos/selfserviceapp/adapters/LoanAccountsListAdapter.java new file mode 100644 index 000000000..b98354e3f --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/adapters/LoanAccountsListAdapter.java @@ -0,0 +1,74 @@ +package org.mifos.selfserviceapp.adapters; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.data.accounts.LoanAccount; +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * @author Vishwajeet + * @since 22/6/16. + */ +public class LoanAccountsListAdapter extends RecyclerView.Adapter { + private final Context context; + private final LayoutInflater layoutInflater; + private List loanAccountsList = new ArrayList<>(); + + public LoanAccountsListAdapter(Context context, List loanAccountsList) { + this.context = context; + layoutInflater = LayoutInflater.from(context); + this.loanAccountsList = loanAccountsList; + } + + public LoanAccount getItem(int position) { + return loanAccountsList.get(position); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + RecyclerView.ViewHolder vh; + View v = LayoutInflater.from(parent.getContext()).inflate( + R.layout.row_loan_account, parent, false); + vh = new ViewHolder(v); + return vh; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (holder instanceof RecyclerView.ViewHolder) { + + LoanAccount loanAccount = getItem(position); + ((ViewHolder) holder).tv_clientLoanAccountNumber.setText(loanAccount.getAccountNo().toString()); + ((ViewHolder) holder).tv_loanAccountProductName.setText(loanAccount.getProductName()); + + } + + } + + @Override + public int getItemCount() { + return loanAccountsList.size(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.tv_clientLoanAccountNumber) + TextView tv_clientLoanAccountNumber; + @BindView(R.id.tv_loanAccountProductName) + TextView tv_loanAccountProductName; + + public ViewHolder(View v) { + super(v); + ButterKnife.bind(this, v); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/mifos/selfserviceapp/adapters/SavingAccountsListAdapter.java b/app/src/main/java/org/mifos/selfserviceapp/adapters/SavingAccountsListAdapter.java new file mode 100644 index 000000000..bf5df1fa5 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/adapters/SavingAccountsListAdapter.java @@ -0,0 +1,75 @@ +package org.mifos.selfserviceapp.adapters; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.data.accounts.SavingAccount; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * @author Vishwajeet + * @since 22/6/16. + */ +public class SavingAccountsListAdapter extends RecyclerView.Adapter { + private final Context context; + private final LayoutInflater layoutInflater; + private List savingAccountsList = new ArrayList<>(); + + public SavingAccountsListAdapter(Context context, List savingAccountsList) { + this.context = context; + layoutInflater = LayoutInflater.from(context); + this.savingAccountsList = savingAccountsList; + } + + public SavingAccount getItem(int position) { + return savingAccountsList.get(position); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + RecyclerView.ViewHolder vh; + View v = LayoutInflater.from(parent.getContext()).inflate( + R.layout.row_saving_account, parent, false); + vh = new ViewHolder(v); + return vh; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (holder instanceof RecyclerView.ViewHolder) { + + SavingAccount savingAccount = getItem(position); + ((ViewHolder) holder).tv_clientSavingAccountNumber.setText(savingAccount.getAccountNo().toString()); + ((ViewHolder) holder).tv_savingAccountProductName.setText(savingAccount.getProductName()); + + } + + } + + @Override + public int getItemCount() { + return savingAccountsList.size(); + } + +public static class ViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.tv_clientSavingAccountNumber) + TextView tv_clientSavingAccountNumber; + @BindView(R.id.tv_savingAccountProductName) + TextView tv_savingAccountProductName; + + public ViewHolder(View v) { + super(v); + ButterKnife.bind(this, v); + } +} +} \ No newline at end of file diff --git a/app/src/main/java/org/mifos/selfserviceapp/adapters/ViewPagerAdapter.java b/app/src/main/java/org/mifos/selfserviceapp/adapters/ViewPagerAdapter.java new file mode 100644 index 000000000..15c1add38 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/adapters/ViewPagerAdapter.java @@ -0,0 +1,41 @@ +package org.mifos.selfserviceapp.adapters; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Vishwajeet + * @since 21/6/16. + */ +public class ViewPagerAdapter extends FragmentPagerAdapter { + private final List mFragmentList = new ArrayList<>(); + private final List mFragmentTitleList = new ArrayList<>(); + + public ViewPagerAdapter(FragmentManager manager) { + super(manager); + } + + @Override + public Fragment getItem(int position) { + return mFragmentList.get(position); + } + + @Override + public int getCount() { + return mFragmentList.size(); + } + + public void addFragment(Fragment fragment, String title) { + mFragmentList.add(fragment); + mFragmentTitleList.add(title); + } + + @Override + public CharSequence getPageTitle(int position) { + return mFragmentTitleList.get(position); + } + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/api/ApiRequestInterceptor.java b/app/src/main/java/org/mifos/selfserviceapp/api/ApiRequestInterceptor.java new file mode 100644 index 000000000..da2073e0d --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/api/ApiRequestInterceptor.java @@ -0,0 +1,49 @@ +/* + * This project is licensed under the open source MPL V2. + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ + +package org.mifos.selfserviceapp.api; + + +import android.content.Context; +import android.util.Log; + +import org.mifos.selfserviceapp.utils.PrefManager; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Request.Builder; +import okhttp3.Response; + +/** + * @author Vishwajeet + * @since 21/06/16 + */ +public class ApiRequestInterceptor implements Interceptor { + + public static final String HEADER_TENANT = "Fineract-Platform-TenantId"; + public static final String HEADER_AUTH = "Authorization"; + private Context context; + + public ApiRequestInterceptor(Context context) { + this.context = context; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request chainrequest = chain.request(); + Builder builder = chainrequest.newBuilder() + .header(HEADER_TENANT, "default"); + + if (PrefManager.getInstance(context).isAuthenticated()) { + builder.header(HEADER_AUTH, PrefManager.getInstance(context).getToken()); + Log.v("TAG", PrefManager.getInstance(context).getToken()); + } + + Request request = builder.build(); + return chain.proceed(request); + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/api/BaseApiManager.java b/app/src/main/java/org/mifos/selfserviceapp/api/BaseApiManager.java new file mode 100644 index 000000000..daa7afa43 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/api/BaseApiManager.java @@ -0,0 +1,73 @@ +package org.mifos.selfserviceapp.api; + +import android.content.Context; + +import org.mifos.selfserviceapp.api.services.AuthenticationService; +import org.mifos.selfserviceapp.api.services.ClientService; +import org.mifos.selfserviceapp.api.services.LoanAccountsListService; +import org.mifos.selfserviceapp.api.services.SavingAccountsListService; +import org.mifos.selfserviceapp.home.SavingAccountsListFragment; + +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; +import retrofit2.GsonConverterFactory; +import retrofit2.Retrofit; + +/** + * @author Vishwajeet + * @since 13/6/16 + */ +public class BaseApiManager { + + private BaseURL baseUrl = new BaseURL(); + private final String BASE_URL = baseUrl.getUrl(); + + private AuthenticationService authenticationApi; + private ClientService clientsApi; + private SavingAccountsListService savingAccountsListApi; + private LoanAccountsListService loanAccountsListApi; + private Context context; + + public BaseApiManager(Context context){ + this.context = context; + authenticationApi = createApi(AuthenticationService.class, BASE_URL); + clientsApi = createApi(ClientService.class, BASE_URL); + savingAccountsListApi = createApi(SavingAccountsListService.class, BASE_URL); + loanAccountsListApi = createApi(LoanAccountsListService.class, BASE_URL); + } + + public OkHttpClient getOkHttpClient() { + HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).addInterceptor(new ApiRequestInterceptor(context)).build(); + + return client; + } + + private T createApi(Class clazz, String baseUrl) { + + return new Retrofit.Builder() + .baseUrl(baseUrl) + .addConverterFactory(GsonConverterFactory.create()) + .client(getOkHttpClient()) + .build() + .create(clazz); + } + + public AuthenticationService getAuthenticationApi(){ + return authenticationApi; + } + + public ClientService getClientsApi() { + return clientsApi; + } + + public SavingAccountsListService getSavingAccountsListApi() { + return savingAccountsListApi; + } + + public LoanAccountsListService getLoanAccountsListApi() { + return loanAccountsListApi; + } + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/api/BaseURL.java b/app/src/main/java/org/mifos/selfserviceapp/api/BaseURL.java new file mode 100644 index 000000000..fc022dcb7 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/api/BaseURL.java @@ -0,0 +1,21 @@ +package org.mifos.selfserviceapp.api; + +/** + * @author Vishwajeet + * @since 09/06/16 + */ + +public class BaseURL { + + public static final String API_ENDPOINT = "demo.openmf.org"; + public static final String API_PATH = "/fineract-provider/api/v1/self/"; + public static final String PROTOCOL_HTTPS = "https://"; + + private String url; + + public String getUrl() { + if (url == null) + return PROTOCOL_HTTPS + API_ENDPOINT + API_PATH; + return url; + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/api/DataManager.java b/app/src/main/java/org/mifos/selfserviceapp/api/DataManager.java new file mode 100644 index 000000000..5d95bc0b8 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/api/DataManager.java @@ -0,0 +1,37 @@ +package org.mifos.selfserviceapp.api; + +import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.data.User; +import org.mifos.selfserviceapp.data.accounts.LoanAccount; +import org.mifos.selfserviceapp.data.accounts.SavingAccount; + +import retrofit2.Call; + +/** + * @author Vishwajeet + * @since 13/6/16. + */ +public class DataManager { + + public final BaseApiManager mBaseApiManager; + + public DataManager(BaseApiManager baseApiManager){ + mBaseApiManager = baseApiManager; + } + + public Call login(String username, String password) { + return mBaseApiManager.getAuthenticationApi().authenticate(username, password); + } + + public Call getClients() { + return mBaseApiManager.getClientsApi().getAllClients(); + } + + public Call getSavingAccounts(int id) { + return mBaseApiManager.getSavingAccountsListApi().getSavingAccountsList(id); + } + + public Call getLoanAccounts(int id) { + return mBaseApiManager.getLoanAccountsListApi().getLoanAccountsList(id); + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/api/model/ApiEndPoints.java b/app/src/main/java/org/mifos/selfserviceapp/api/model/ApiEndPoints.java new file mode 100644 index 000000000..57fb8952a --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/api/model/ApiEndPoints.java @@ -0,0 +1,14 @@ +package org.mifos.selfserviceapp.api.model; + +/** + * @author Vishwajeet + * @since 11/06/16 + */ + +public class ApiEndPoints { + + //This class contains all the Constants for API End Points + + public static final String AUTHENTICATION = "authentication"; + public static final String CLIENTS = "clients"; +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/api/services/AuthenticationService.java b/app/src/main/java/org/mifos/selfserviceapp/api/services/AuthenticationService.java new file mode 100644 index 000000000..6b3c0b373 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/api/services/AuthenticationService.java @@ -0,0 +1,20 @@ +package org.mifos.selfserviceapp.api.services; + +import org.mifos.selfserviceapp.api.model.ApiEndPoints; +import org.mifos.selfserviceapp.data.User; + +import retrofit2.Call; +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * @author Vishwajeet + * @since 09/06/16 + */ + +public interface AuthenticationService { + + @POST(ApiEndPoints.AUTHENTICATION) + Call authenticate(@Query("username") String username, + @Query("password") String password); +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/api/services/ClientService.java b/app/src/main/java/org/mifos/selfserviceapp/api/services/ClientService.java new file mode 100644 index 000000000..6904aa752 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/api/services/ClientService.java @@ -0,0 +1,19 @@ +package org.mifos.selfserviceapp.api.services; + +import org.mifos.selfserviceapp.api.model.ApiEndPoints; +import org.mifos.selfserviceapp.data.Client; + +import retrofit2.Call; +import retrofit2.http.GET; + +/** + * @author Vishwajeet + * @since 20/6/16. + */ +public interface ClientService { + + //This is a default call and Loads client from 0 to 200 + @GET(ApiEndPoints.CLIENTS) + Call getAllClients(); + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/api/services/LoanAccountsListService.java b/app/src/main/java/org/mifos/selfserviceapp/api/services/LoanAccountsListService.java new file mode 100644 index 000000000..9a233181b --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/api/services/LoanAccountsListService.java @@ -0,0 +1,17 @@ +package org.mifos.selfserviceapp.api.services; + +import org.mifos.selfserviceapp.api.model.ApiEndPoints; +import org.mifos.selfserviceapp.data.accounts.LoanAccount; + +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Path; + +/** + * Created by vjs3 on 23/6/16. + */ + +public interface LoanAccountsListService { + @GET(ApiEndPoints.CLIENTS + "/{clientId}/accounts?fields=loanAccounts") + Call getLoanAccountsList(@Path("clientId") int clientId); +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/api/services/SavingAccountsListService.java b/app/src/main/java/org/mifos/selfserviceapp/api/services/SavingAccountsListService.java new file mode 100644 index 000000000..8c506d24a --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/api/services/SavingAccountsListService.java @@ -0,0 +1,17 @@ +package org.mifos.selfserviceapp.api.services; + +import org.mifos.selfserviceapp.api.model.ApiEndPoints; +import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.data.accounts.SavingAccount; + +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Path; + +/** + * Created by vjs3 on 21/6/16. + */ +public interface SavingAccountsListService { + @GET(ApiEndPoints.CLIENTS + "/{clientId}/accounts?fields=savingsAccounts") + Call getSavingAccountsList(@Path("clientId") int clientId); +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/data/Client.java b/app/src/main/java/org/mifos/selfserviceapp/data/Client.java new file mode 100644 index 000000000..3071c0f75 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/data/Client.java @@ -0,0 +1,117 @@ +package org.mifos.selfserviceapp.data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Vishwajeet + * @since 20/06/16 + */ +public class Client { + + private int id; + private String accountNo; + private List activationDate = new ArrayList(); + private List dobDate = new ArrayList(); + private String firstname; + private String middlename; + private String lastname; + private String displayName; + private String fullname; + private List pageItems = new ArrayList(); + + public List getPageItems() { + return pageItems; + } + + public void setPageItems(List pageItems) { + this.pageItems = pageItems; + } + + public List getDobDate() { + return dobDate; + } + + public void setDobDate(List dobDate) { + this.dobDate = dobDate; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getAccountNo() { + return accountNo; + } + + public void setAccountNo(String accountNo) { + this.accountNo = accountNo; + } + + public List getActivationDate() { + return activationDate; + } + + public void setActivationDate(List activationDate) { + this.activationDate = activationDate; + } + + public String getFirstname() { + return firstname; + } + + public void setFirstname(String firstname) { + this.firstname = firstname; + } + + public String getMiddlename() { + return middlename; + } + + public void setMiddlename(String middlename) { + this.middlename = middlename; + } + + public String getLastname() { + return lastname; + } + + public void setLastname(String lastname) { + this.lastname = lastname; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getFullname() { + return fullname; + } + + public void setFullname(String fullname) { + this.fullname = fullname; + } + + @Override + public String toString() { + return "Client{" + + "id=" + id + + ", accountNo='" + accountNo + '\'' + + ", activationDate=" + activationDate + + ", firstname='" + firstname + '\'' + + ", middlename='" + middlename + '\'' + + ", lastname='" + lastname + '\'' + + ", displayName='" + displayName + '\'' + + ", fullname='" + fullname + '\'' + + '}'; + } + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/data/User.java b/app/src/main/java/org/mifos/selfserviceapp/data/User.java new file mode 100644 index 000000000..fef393e5f --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/data/User.java @@ -0,0 +1,70 @@ +package org.mifos.selfserviceapp.data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Vishwajeet + * @since 12/06/16 + */ + +public class User { + + private String username; + private int userId; + private String base64EncodedAuthenticationKey; + private boolean authenticated; + private List permissions = new ArrayList(); + + public String getUserName() { + return username; + } + + public void setUserName(String username) { + this.username = username; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public boolean isAuthenticated() { + return authenticated; + } + + public void setAuthenticated(boolean authenticated) { + this.authenticated = authenticated; + } + + + public String getBase64EncodedAuthenticationKey() { + return base64EncodedAuthenticationKey; + } + + public void setBase64EncodedAuthenticationKey(String base64EncodedAuthenticationKey) { + this.base64EncodedAuthenticationKey = base64EncodedAuthenticationKey; + } + + public List getPermissions() { + return permissions; + } + + public void setPermissions(List permissions) { + this.permissions = permissions; + } + + @Override + public String toString() { + return "User{" + + "username='" + username + '\'' + + ", userId=" + userId + + ", base64EncodedAuthenticationKey='" + base64EncodedAuthenticationKey + '\'' + + ", authenticated=" + authenticated + + ", permissions=" + permissions + + '}'; + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/data/accounts/LoanAccount.java b/app/src/main/java/org/mifos/selfserviceapp/data/accounts/LoanAccount.java new file mode 100644 index 000000000..753ec6848 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/data/accounts/LoanAccount.java @@ -0,0 +1,47 @@ +package org.mifos.selfserviceapp.data.accounts; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Vishwajeet + * @since 22/06/16. + */ +public class LoanAccount { + private int id; + private String accountNo; + private String productName; + private List loanAccounts = new ArrayList(); + + public List getLoanAccounts() { + return loanAccounts; + } + + public void setLoanAccounts(List loanAccounts) { + this.loanAccounts = loanAccounts; + } + + public String getAccountNo() { + return accountNo; + } + + public void setAccountNo(String accountNo) { + this.accountNo = accountNo; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/data/accounts/SavingAccount.java b/app/src/main/java/org/mifos/selfserviceapp/data/accounts/SavingAccount.java new file mode 100644 index 000000000..094d683be --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/data/accounts/SavingAccount.java @@ -0,0 +1,48 @@ +package org.mifos.selfserviceapp.data.accounts; + +import java.util.ArrayList; +import java.util.List; + +/** + *@author Vishwajeet + * @since 22/06/16 + */ + +public class SavingAccount { + private int id; + private String accountNo; + private String productName; + private List savingsAccounts = new ArrayList(); + + public List getSavingsAccounts() { + return savingsAccounts; + } + + public void setSavingsAccounts(List savingsAccounts) { + this.savingsAccounts = savingsAccounts; + } + + public String getAccountNo() { + return accountNo; + } + + public void setAccountNo(String accountNo) { + this.accountNo = accountNo; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/ClientAccountsActivity.java b/app/src/main/java/org/mifos/selfserviceapp/home/ClientAccountsActivity.java new file mode 100644 index 000000000..dc0c58fb7 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/ClientAccountsActivity.java @@ -0,0 +1,43 @@ +package org.mifos.selfserviceapp.home; + +import android.os.Bundle; +import android.support.design.widget.TabLayout; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.adapters.ViewPagerAdapter; +import org.mifos.selfserviceapp.utils.Constants; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * @author Vishwajeet + * @since 21/6/16. + */ +public class ClientAccountsActivity extends AppCompatActivity{ + + @BindView(R.id.viewpager) + ViewPager viewPager; + @BindView(R.id.tabs) + TabLayout tabLayout; + private int clientId; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_client_accounts); + ButterKnife.bind(this); + clientId = getIntent().getExtras().getInt(Constants.CLIENT_ID); + setupViewPager(viewPager); + tabLayout.setupWithViewPager(viewPager); + } + + private void setupViewPager(ViewPager viewPager) { + ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager()); + viewPagerAdapter.addFragment(SavingAccountsListFragment.newInstance(clientId), getString(R.string.saving_accounts)); + viewPagerAdapter.addFragment(LoanAccountsListFragment.newInstance(clientId), getString(R.string.loan_accounts)); + viewPager.setAdapter(viewPagerAdapter); + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/ClientListFragment.java b/app/src/main/java/org/mifos/selfserviceapp/home/ClientListFragment.java new file mode 100644 index 000000000..ff8ea0271 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/ClientListFragment.java @@ -0,0 +1,146 @@ +package org.mifos.selfserviceapp.home; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.adapters.ClientListAdapter; +import org.mifos.selfserviceapp.api.BaseApiManager; +import org.mifos.selfserviceapp.api.DataManager; +import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.utils.Constants; +import org.mifos.selfserviceapp.utils.RecyclerItemClickListener; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import retrofit2.Response; + +/** + * @author Vishwajeet + * @since 19/06/16 + */ + +public class ClientListFragment extends Fragment implements RecyclerItemClickListener.OnItemClickListener, ClientListMvpView { + + @BindView(R.id.rv_clients) + RecyclerView rv_clients; + @BindView(R.id.swipe_container) + SwipeRefreshLayout swipeRefreshLayout; + + ClientListAdapter clientListAdapter; + ClientListPresenter mClientListPresenter; + private View rootView; + private List clientList = new ArrayList<>(); + private LinearLayoutManager layoutManager; + private DataManager mDataManager; + private BaseApiManager mBaseApiManager; + private ProgressDialog progress; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle + savedInstanceState) { + rootView = inflater.inflate(R.layout.fragment_client_list, container, false); + setHasOptionsMenu(true); + getActivity().setTitle(getResources().getString(R.string.clients)); + ButterKnife.bind(this, rootView); + + mBaseApiManager = new BaseApiManager(getActivity()); + mDataManager = new DataManager(mBaseApiManager); + mClientListPresenter = new ClientListPresenter(mDataManager); + mClientListPresenter.attachView(this); + + layoutManager = new LinearLayoutManager(getActivity()); + layoutManager.setOrientation(LinearLayoutManager.VERTICAL); + rv_clients.setLayoutManager(layoutManager); + rv_clients.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), this)); + rv_clients.setHasFixedSize(true); + + swipeRefreshLayout.setColorSchemeResources(R.color.blue_light, R.color.green_light, R + .color.orange_light, R.color.red_light); + swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + fetchClientList(); + } + }); + + fetchClientList(); + + return rootView; + } + + private void fetchClientList() { + mClientListPresenter.loadClients(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + mClientListPresenter.detachView(); + } + + @Override + public void onItemClick(View childView, int position) { + Intent clientActivityIntent = new Intent(getActivity(), ClientAccountsActivity.class); + clientActivityIntent.putExtra(Constants.CLIENT_ID, clientList.get(position).getId()); + startActivity(clientActivityIntent); + } + + @Override + public void onItemLongPress(View childView, int position) { + + } + + @Override + public void showProgress() { + if (progress == null) { + progress = new ProgressDialog(getActivity(), ProgressDialog.STYLE_SPINNER); + progress.setCancelable(false); + } + progress.setMessage(getResources().getText(R.string.progress_message_loading)); + progress.show(); + } + + @Override + public void hideProgress() { + if (progress != null && progress.isShowing()) + progress.dismiss(); + } + + @Override + public void showClients(Response response) { + clientList = response.body().getPageItems(); + inflateClientList(); + if (swipeRefreshLayout.isRefreshing()) + swipeRefreshLayout.setRefreshing(false); + } + + private void inflateClientList() { + clientListAdapter = new ClientListAdapter(getContext(), clientList); + rv_clients.setAdapter(clientListAdapter); + } + + @Override + public void showErrorFetchingClients(String message) { + + //TODO: Handle this error properly + Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show(); + } + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/ClientListMvpView.java b/app/src/main/java/org/mifos/selfserviceapp/home/ClientListMvpView.java new file mode 100644 index 000000000..975b0f38a --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/ClientListMvpView.java @@ -0,0 +1,22 @@ +package org.mifos.selfserviceapp.home; + +import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.ui.views.base.MVPView; + +import retrofit2.Response; + +/** + * @author Vishwajeet + * @since 20/6/16. + */ +public interface ClientListMvpView extends MVPView { + + void showClients(Response response); + + void showErrorFetchingClients(String message); + + void showProgress(); + + void hideProgress(); + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/ClientListPresenter.java b/app/src/main/java/org/mifos/selfserviceapp/home/ClientListPresenter.java new file mode 100644 index 000000000..22505f4e2 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/ClientListPresenter.java @@ -0,0 +1,44 @@ +package org.mifos.selfserviceapp.home; + +import android.util.Log; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.api.DataManager; +import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.presenters.BasePresenter; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +/** + * @author Vishwajeet + * @since 19/06/16 + */ + +public class ClientListPresenter extends BasePresenter{ + + DataManager mDataManager; + + public ClientListPresenter(DataManager dataManager) { + mDataManager = dataManager; + } + + public void loadClients() { + Call call = mDataManager.getClients(); + getMvpView().showProgress(); + call.enqueue(new Callback() { + @Override + public void onResponse(Response response) { + getMvpView().hideProgress(); + getMvpView().showClients(response); + } + + @Override + public void onFailure(Throwable t) { + getMvpView().hideProgress(); + getMvpView().showErrorFetchingClients(context.getString(R.string.error_fetching_client_list)); + Log.e("Error",context.getString(R.string.error_message_server)); + } + }); + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/HomeActivity.java b/app/src/main/java/org/mifos/selfserviceapp/home/HomeActivity.java new file mode 100644 index 000000000..e5c4492b4 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/HomeActivity.java @@ -0,0 +1,161 @@ +package org.mifos.selfserviceapp.home; + +import android.content.Intent; +import android.os.Bundle; +import android.support.design.widget.NavigationView; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.MenuItem; +import android.view.View; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.api.BaseApiManager; +import org.mifos.selfserviceapp.api.DataManager; +import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.utils.Constants; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * @author Vishwajeet + * @since 16/06/16 + */ +public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { + + private NavigationView mNavigationView; + private DrawerLayout mDrawerLayout; + + @BindView(R.id.toolbar) + Toolbar toolbar; + private DataManager mDataManager; + private Intent clientActivityIntent; + private List clientList = new ArrayList<>(); + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_home); + BaseApiManager baseApiManager = new BaseApiManager(this); + mDataManager = new DataManager(baseApiManager); + ButterKnife.bind(this); + + if (toolbar != null) { + setSupportActionBar(toolbar); + toolbar.setTitle(getString(R.string.home)); + } + + loadClientDetails(); + //replaceFragment(new ClientListFragment(), false, R.id.container); + // setup navigation drawer + setupNavigationBar(); + } + + //TODO For testing purpose only, convert it to MVP + private void loadClientDetails() { + Call call = mDataManager.getClients(); + call.enqueue(new Callback() { + @Override + public void onResponse(Response response) { + if(response.body().getPageItems().size()==1) { + /*clientList = response.body().getPageItems();*/ + clientActivityIntent = new Intent(getParent(), ClientAccountsActivity.class); + clientActivityIntent.putExtra(Constants.CLIENT_ID, response.body().getId()); + startActivity(clientActivityIntent); + } + else { + replaceFragment(new ClientListFragment(), false, R.id.container); + } + } + + @Override + public void onFailure(Throwable t) { + + } + }); + } + + @Override + public boolean onNavigationItemSelected(MenuItem item) { + // ignore the current selected item + if (item.isChecked()) { + mDrawerLayout.closeDrawer(GravityCompat.START); + return false; + } + + // select which item to open + switch (item.getItemId()) { + case R.id.item_clients: + replaceFragment(new ClientListFragment(), false, R.id.container); + break; + case R.id.item_accounts: + break; + case R.id.item_funds_transfer: + break; + case R.id.item_recent_transactions: + break; + case R.id.item_questionnaire: + break; + case R.id.item_about_us: + break; + } + + // close the drawer + mDrawerLayout.closeDrawer(GravityCompat.START); + mNavigationView.setCheckedItem(R.id.item_clients); + return true; + } + + protected void setupNavigationBar() { + + // setup navigation view + mNavigationView = (NavigationView) findViewById(R.id.navigation_view); + mNavigationView.setNavigationItemSelectedListener(this); + + // setup drawer layout and sync to toolbar + mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer); + ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, + mDrawerLayout, toolbar, R.string.open_drawer, R.string.close_drawer) { + + @Override + public void onDrawerClosed(View drawerView) { + super.onDrawerClosed(drawerView); + } + + @Override + public void onDrawerOpened(View drawerView) { + super.onDrawerOpened(drawerView); + } + }; + mDrawerLayout.addDrawerListener(actionBarDrawerToggle); + actionBarDrawerToggle.syncState(); + } + + public void replaceFragment(Fragment fragment, boolean addToBackStack, int containerId) { + invalidateOptionsMenu(); + String backStateName = fragment.getClass().getName(); + boolean fragmentPopped = getSupportFragmentManager().popBackStackImmediate(backStateName, + 0); + + if (!fragmentPopped && getSupportFragmentManager().findFragmentByTag(backStateName) == + null) { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.replace(containerId, fragment, backStateName); + if (addToBackStack) { + transaction.addToBackStack(backStateName); + } + transaction.commit(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListFragment.java b/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListFragment.java new file mode 100644 index 000000000..1d94157a6 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListFragment.java @@ -0,0 +1,143 @@ +package org.mifos.selfserviceapp.home; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.adapters.LoanAccountsListAdapter; +import org.mifos.selfserviceapp.adapters.SavingAccountsListAdapter; +import org.mifos.selfserviceapp.api.BaseApiManager; +import org.mifos.selfserviceapp.api.DataManager; +import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.data.accounts.LoanAccount; +import org.mifos.selfserviceapp.data.accounts.SavingAccount; +import org.mifos.selfserviceapp.utils.Constants; +import org.mifos.selfserviceapp.utils.RecyclerItemClickListener; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import retrofit2.Response; + +/** + * @author Vishwajeet + * @since 21/06/16 + */ +public class LoanAccountsListFragment extends Fragment implements RecyclerItemClickListener.OnItemClickListener, LoanAccountsListView { + + @BindView(R.id.rv_loan_accounts_list) + RecyclerView rvLoanAccounts; + @BindView(R.id.swipe_loan_container) + SwipeRefreshLayout swipeLoanContainer; + + public int clientId; + private View rootView; + LoanAccountsListPresenter mLoanAccountsListPresenter; + private LinearLayoutManager linearLayoutManager; + private ProgressDialog progress; + private List loanAccountList = new ArrayList<>(); + private LoanAccountsListAdapter loanAccountsListAdapter; + private BaseApiManager mBaseApiManager; + private DataManager mDataManager; + + public static LoanAccountsListFragment newInstance(int clientId) { + LoanAccountsListFragment fragment = new LoanAccountsListFragment(); + Bundle args = new Bundle(); + args.putInt(Constants.CLIENT_ID, clientId); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) + clientId = getArguments().getInt(Constants.CLIENT_ID); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle + savedInstanceState) { + rootView = inflater.inflate(R.layout.fragment_loan_accounts_list, container, false); + ButterKnife.bind(this, rootView); + mBaseApiManager = new BaseApiManager(getActivity()); + mDataManager = new DataManager(mBaseApiManager); + mLoanAccountsListPresenter = new LoanAccountsListPresenter(mDataManager); + mLoanAccountsListPresenter.attachView(this); + linearLayoutManager = new LinearLayoutManager(getActivity()); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + rvLoanAccounts.setLayoutManager(linearLayoutManager); + rvLoanAccounts.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), this)); + rvLoanAccounts.setHasFixedSize(true); + + swipeLoanContainer.setColorSchemeResources(R.color.blue_light, R.color.green_light, R + .color.orange_light, R.color.red_light); + swipeLoanContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + fetchLoanAccountsList(); + } + }); + fetchLoanAccountsList(); + return rootView; + } + + private void fetchLoanAccountsList() { + mLoanAccountsListPresenter.fetchLoanAccounts(clientId); + } + + @Override + public void onItemClick(View childView, int position) { + + } + + @Override + public void onItemLongPress(View childView, int position) { + + } + + @Override + public void showLoanAccounts(Response response) { + loanAccountList = response.body().getLoanAccounts(); + inflateLoanAccountsList(); + if (swipeLoanContainer.isRefreshing()) + swipeLoanContainer.setRefreshing(false); + } + + @Override + public void showErrorFetchingLoanAccounts(String string) { + + } + + private void inflateLoanAccountsList() { + loanAccountsListAdapter = new LoanAccountsListAdapter(getContext(), loanAccountList); + rvLoanAccounts.setAdapter(loanAccountsListAdapter); + } + + @Override + public void showProgress() { + if (progress == null) { + progress = new ProgressDialog(getActivity(), ProgressDialog.STYLE_SPINNER); + progress.setCancelable(false); + } + progress.setMessage(getResources().getText(R.string.progress_message_loading)); + progress.show(); + } + + @Override + public void hideProgress() { + if (progress != null && progress.isShowing()) + progress.dismiss(); + } + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListPresenter.java b/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListPresenter.java new file mode 100644 index 000000000..8ec67ab9c --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListPresenter.java @@ -0,0 +1,46 @@ +package org.mifos.selfserviceapp.home; + +import android.util.Log; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.api.DataManager; +import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.data.accounts.LoanAccount; +import org.mifos.selfserviceapp.data.accounts.SavingAccount; +import org.mifos.selfserviceapp.presenters.BasePresenter; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * @author Vishwajeet + * @since 21/6/16. + */ + +public class LoanAccountsListPresenter extends BasePresenter{ + DataManager mDataManager; + + protected LoanAccountsListPresenter(DataManager dataManager) { + mDataManager = dataManager; + } + + public void fetchLoanAccounts(int id) { + Call call = mDataManager.getLoanAccounts(id); + getMvpView().showProgress(); + call.enqueue(new Callback() { + @Override + public void onResponse(Response response) { + getMvpView().hideProgress(); + getMvpView().showLoanAccounts(response); + } + + @Override + public void onFailure(Throwable t) { + getMvpView().hideProgress(); + getMvpView().showErrorFetchingLoanAccounts(context.getString(R.string.error_fetching_loan_accounts_list)); + Log.e("Error",context.getString(R.string.error_message_server)); + } + }); + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListView.java b/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListView.java new file mode 100644 index 000000000..734d95a9f --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListView.java @@ -0,0 +1,21 @@ +package org.mifos.selfserviceapp.home; + +import org.mifos.selfserviceapp.data.accounts.LoanAccount; +import org.mifos.selfserviceapp.ui.views.base.MVPView; + +import retrofit2.Response; + +/** + * Created by vjs3 on 23/6/16. + */ + +public interface LoanAccountsListView extends MVPView { + + void showLoanAccounts(Response response); + + void showErrorFetchingLoanAccounts(String string); + + void showProgress(); + + void hideProgress(); +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListFragment.java b/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListFragment.java new file mode 100644 index 000000000..b8a307c42 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListFragment.java @@ -0,0 +1,142 @@ +package org.mifos.selfserviceapp.home; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.adapters.SavingAccountsListAdapter; +import org.mifos.selfserviceapp.api.BaseApiManager; +import org.mifos.selfserviceapp.api.DataManager; +import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.data.accounts.SavingAccount; +import org.mifos.selfserviceapp.utils.Constants; +import org.mifos.selfserviceapp.utils.RecyclerItemClickListener; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import retrofit2.Response; + +/** + * @author Vishwajeet + * @since 21/06/16 + */ + +public class SavingAccountsListFragment extends Fragment implements RecyclerItemClickListener.OnItemClickListener, SavingAccountsListView { + + @BindView(R.id.rv_saving_accounts_list) + RecyclerView rv_SavingAccounts; + @BindView(R.id.swipe_savings_container) + SwipeRefreshLayout swipeSavingsContainer; + + public int clientId; + private View rootView; + SavingAccountsListPresenter mSavingAccountsListPresenter; + private LinearLayoutManager linearLayoutManager; + private ProgressDialog progress; + private List savingAccountsList = new ArrayList<>(); + private SavingAccountsListAdapter savingAccountsListAdapter; + private BaseApiManager mBaseApiManager; + private DataManager mDataManager; + + public static SavingAccountsListFragment newInstance(int clientId) { + SavingAccountsListFragment fragment = new SavingAccountsListFragment(); + Bundle args = new Bundle(); + args.putInt(Constants.CLIENT_ID, clientId); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) + clientId = getArguments().getInt(Constants.CLIENT_ID); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle + savedInstanceState) { + rootView = inflater.inflate(R.layout.fragment_saving_accounts_list, container, false); + ButterKnife.bind(this, rootView); + mBaseApiManager = new BaseApiManager(getActivity()); + mDataManager = new DataManager(mBaseApiManager); + mSavingAccountsListPresenter = new SavingAccountsListPresenter(mDataManager); + mSavingAccountsListPresenter.attachView(this); + linearLayoutManager = new LinearLayoutManager(getActivity()); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + rv_SavingAccounts.setLayoutManager(linearLayoutManager); + rv_SavingAccounts.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), this)); + rv_SavingAccounts.setHasFixedSize(true); + + swipeSavingsContainer.setColorSchemeResources(R.color.blue_light, R.color.green_light, R + .color.orange_light, R.color.red_light); + swipeSavingsContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + fetchSavingAccountsList(); + } + }); + fetchSavingAccountsList(); + return rootView; + } + + private void fetchSavingAccountsList() { + mSavingAccountsListPresenter.fetchSavingAccounts(clientId); + } + + @Override + public void onItemClick(View childView, int position) { + + } + + @Override + public void onItemLongPress(View childView, int position) { + + } + + @Override + public void showSavingAccounts(Response response) { + savingAccountsList = response.body().getSavingsAccounts(); + inflateSavingAccountsList(); + if (swipeSavingsContainer.isRefreshing()) + swipeSavingsContainer.setRefreshing(false); + } + + private void inflateSavingAccountsList() { + savingAccountsListAdapter = new SavingAccountsListAdapter(getContext(), savingAccountsList); + rv_SavingAccounts.setAdapter(savingAccountsListAdapter); + } + + @Override + public void showErrorFetchingSavingAccounts(String string) { + + } + + @Override + public void showProgress() { + if (progress == null) { + progress = new ProgressDialog(getActivity(), ProgressDialog.STYLE_SPINNER); + progress.setCancelable(false); + } + progress.setMessage(getResources().getText(R.string.progress_message_loading)); + progress.show(); + } + + @Override + public void hideProgress() { + if (progress != null && progress.isShowing()) + progress.dismiss(); + } + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListPresenter.java b/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListPresenter.java new file mode 100644 index 000000000..f1ca50d3f --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListPresenter.java @@ -0,0 +1,44 @@ +package org.mifos.selfserviceapp.home; + +import android.util.Log; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.api.DataManager; +import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.data.accounts.SavingAccount; +import org.mifos.selfserviceapp.presenters.BasePresenter; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * @author Vishwajeet + * @since 21/6/16. + */ +public class SavingAccountsListPresenter extends BasePresenter{ + DataManager mDataManager; + + protected SavingAccountsListPresenter(DataManager dataManager) { + mDataManager = dataManager; + } + + public void fetchSavingAccounts(int id) { + Call call = mDataManager.getSavingAccounts(id); + getMvpView().showProgress(); + call.enqueue(new Callback() { + @Override + public void onResponse(Response response) { + getMvpView().hideProgress(); + getMvpView().showSavingAccounts(response); + } + + @Override + public void onFailure(Throwable t) { + getMvpView().hideProgress(); + getMvpView().showErrorFetchingSavingAccounts(context.getString(R.string.error_fetching_saving_accounts_list)); + Log.e("Error",context.getString(R.string.error_message_server)); + } + }); + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListView.java b/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListView.java new file mode 100644 index 000000000..f2dd45496 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListView.java @@ -0,0 +1,21 @@ +package org.mifos.selfserviceapp.home; + +import org.mifos.selfserviceapp.data.accounts.SavingAccount; +import org.mifos.selfserviceapp.ui.views.base.MVPView; + +import retrofit2.Response; + +/** + * Created by vjs3 on 21/6/16. + */ +public interface SavingAccountsListView extends MVPView{ + + void showSavingAccounts(Response response); + + void showErrorFetchingSavingAccounts(String string); + + void showProgress(); + + void hideProgress(); + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/login/LoginActivity.java b/app/src/main/java/org/mifos/selfserviceapp/login/LoginActivity.java new file mode 100644 index 000000000..374a85101 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/login/LoginActivity.java @@ -0,0 +1,122 @@ +package org.mifos.selfserviceapp.login; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; + +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.AppCompatButton; +import android.widget.EditText; +import android.widget.Toast; + +import org.mifos.selfserviceapp.data.User; +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.api.BaseApiManager; +import org.mifos.selfserviceapp.api.DataManager; +import org.mifos.selfserviceapp.home.HomeActivity; +import org.mifos.selfserviceapp.utils.PrefManager; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import retrofit2.Response; + +/** + * @author Vishwajeet + * @since 05/06/16 + */ + +public class LoginActivity extends AppCompatActivity implements LoginView{ + + private LoginPresenter mLoginPresenter; + private DataManager mDataManager; + private BaseApiManager mBaseApiManager; + private ProgressDialog progress; + private PrefManager prefManager; + + @BindView(R.id.btn_login) + AppCompatButton btnLogin; + @BindView(R.id.et_username) + EditText etUsername; + @BindView(R.id.et_password) + EditText etPassword; + + private String username; + private String password; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + ButterKnife.bind(this); + + mBaseApiManager = new BaseApiManager(getApplicationContext()); + mDataManager = new DataManager(mBaseApiManager); + mLoginPresenter = new LoginPresenter(mDataManager); + prefManager = PrefManager.getInstance(getApplicationContext()); + mLoginPresenter.attachView(this); + } + + public boolean validateUserInputs() { + username = etUsername.getEditableText().toString(); + if (username.length() < 5) { + Toast.makeText(this, R.string.invalid_username, Toast.LENGTH_LONG); + return false; + } + password = etPassword.getEditableText().toString(); + if (password.length() < 6) { + Toast.makeText(this, R.string.invalid_password, Toast.LENGTH_LONG); + return false; + } + return true; + } + @Override + public void onLoginSuccessful(String userName) { + + Toast.makeText(this, getString(R.string.toast_welcome) + " " + +userName, Toast.LENGTH_LONG).show(); + + mLoginPresenter.setPref(prefManager); + startActivity(new Intent(this, HomeActivity.class)); + finish(); + } + + @Override + public void onLoginError(Throwable throwable) { + + //TODO: Handle this error properly + Toast.makeText(this, R.string.unable_to_connect, Toast.LENGTH_LONG).show(); + + } + + @Override + public void showProgress() { + if (progress == null) { + progress = new ProgressDialog(this, ProgressDialog.STYLE_SPINNER); + progress.setCancelable(false); + } + progress.setMessage(getResources().getText(R.string.progress_message_login)); + progress.show(); + } + + @Override + public void hideProgress() { + if (progress != null && progress.isShowing()) + progress.dismiss(); + } + + @OnClick(R.id.btn_login) + public void loginClick(){ + if (!validateUserInputs()) + return; + + mLoginPresenter.login(username, password); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mLoginPresenter.detachView(); + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/login/LoginPresenter.java b/app/src/main/java/org/mifos/selfserviceapp/login/LoginPresenter.java new file mode 100644 index 000000000..1249e2108 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/login/LoginPresenter.java @@ -0,0 +1,62 @@ +package org.mifos.selfserviceapp.login; + +import android.util.Log; + +import org.mifos.selfserviceapp.R; +import org.mifos.selfserviceapp.data.User; +import org.mifos.selfserviceapp.api.DataManager; +import org.mifos.selfserviceapp.presenters.BasePresenter; +import org.mifos.selfserviceapp.utils.PrefManager; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * @author Vishwajeet + * @since 05/06/16 + */ +public class LoginPresenter extends BasePresenter { + + DataManager mDataManager; + PrefManager prefManager; + + protected LoginPresenter(DataManager dataManager) { + mDataManager = dataManager; + } + + public void login(String username, String password) { + Call call = mDataManager.login(username, password); + getMvpView().showProgress(); + call.enqueue(new Callback() { + @Override + public void onResponse(Response response) { + getMvpView().hideProgress(); + getMvpView().onLoginSuccessful(response.body().getUserName()); + setUserInfo(response); + } + + @Override + public void onFailure(Throwable t) { + getMvpView().hideProgress(); + getMvpView().onLoginError(t); + Log.e("Error",context.getString(R.string.error_message_server)); + } + }); + } + + public void setUserInfo(Response response) { + // Saving userID + getPref().setUserId(response.body().getUserId()); + // Saving user's token + getPref().saveToken("Basic "+ response.body().getBase64EncodedAuthenticationKey()); + } + + public void setPref(PrefManager prefManager) { + this.prefManager = prefManager; + } + + public PrefManager getPref() { + return prefManager; + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/login/LoginView.java b/app/src/main/java/org/mifos/selfserviceapp/login/LoginView.java new file mode 100644 index 000000000..b9fb572b4 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/login/LoginView.java @@ -0,0 +1,23 @@ +package org.mifos.selfserviceapp.login; + +import org.mifos.selfserviceapp.data.User; +import org.mifos.selfserviceapp.ui.views.base.MVPView; + +import retrofit2.Response; + +/** + * @author Vishwajeet + * @since 05/06/16 + */ + +public interface LoginView extends MVPView { + + void onLoginSuccessful(String userName); + + void onLoginError(Throwable throwable); + + void showProgress(); + + void hideProgress(); + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/presenters/BasePresenter.java b/app/src/main/java/org/mifos/selfserviceapp/presenters/BasePresenter.java index 7cd8673b7..0b1c57727 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/presenters/BasePresenter.java +++ b/app/src/main/java/org/mifos/selfserviceapp/presenters/BasePresenter.java @@ -14,9 +14,9 @@ public class BasePresenter implements Presenter { protected Context context; - protected BasePresenter(Context context) { + /*protected BasePresenter(Context context) { this.context = context; - } + }*/ @Override public void attachView(T mvpView) { diff --git a/app/src/main/java/org/mifos/selfserviceapp/utils/Constants.java b/app/src/main/java/org/mifos/selfserviceapp/utils/Constants.java new file mode 100644 index 000000000..044af0ebb --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/utils/Constants.java @@ -0,0 +1,14 @@ +package org.mifos.selfserviceapp.utils; + +/** + * @author Vishwajeet + * @since 21/06/16. + */ + +public class Constants { + + public static final String CLIENT_NAME = "clientName"; + + public static final String CLIENT_ID = "clientId"; + +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/utils/PrefManager.java b/app/src/main/java/org/mifos/selfserviceapp/utils/PrefManager.java new file mode 100644 index 000000000..66cc9fd70 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/utils/PrefManager.java @@ -0,0 +1,85 @@ +package org.mifos.selfserviceapp.utils; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.text.TextUtils; +import android.util.Log; + +/** + * @author Vishwajeet + * @since 07/06/16 + */ + +public class PrefManager { + private static final String USER_ID = "preferences_user_id"; + private static final String TOKEN = "preferences_token"; + private static final String TENANT = "preferences_tenant"; + private Context context; + + private static PrefManager instance = null; + + private PrefManager(Context context) { + this.context = context; + } + + public SharedPreferences getPreferences() { + return PreferenceManager.getDefaultSharedPreferences(context); + } + + public static PrefManager getInstance(Context context){ + if (instance == null) { + instance = new PrefManager(context); + } + return instance; + } + + public int getInt(String preferenceKey, int preferenceDefaultValue) { + return getPreferences().getInt(preferenceKey, preferenceDefaultValue); + } + + public void putInt(String preferenceKey, int preferenceValue) { + getPreferences().edit().putInt(preferenceKey, preferenceValue).commit(); + } + + public String getString(String preferenceKey, String preferenceDefaultValue) { + return getPreferences().getString(preferenceKey, preferenceDefaultValue); + } + + public void putString(String preferenceKey, String preferenceValue) { + getPreferences().edit().putString(preferenceKey, preferenceValue).commit(); + } + + public void saveToken(String token) { + putString(TOKEN, token); + } + + public void clearToken() { + putString(TOKEN, ""); + } + + public String getToken() { + return getString(TOKEN, ""); + } + + public boolean isAuthenticated() { + return !TextUtils.isEmpty(getToken()); + } + + public int getUserId() { + return getInt(USER_ID, -1); + } + + public void setUserId(int id) { + putInt(USER_ID, id); + } + + public String getTenant() { + return getString(TENANT, "default"); + } + + public void setTenant(String tenant) { + if (!TextUtils.isEmpty(tenant)) + putString(TENANT, tenant); + } +} diff --git a/app/src/main/java/org/mifos/selfserviceapp/utils/RecyclerItemClickListener.java b/app/src/main/java/org/mifos/selfserviceapp/utils/RecyclerItemClickListener.java new file mode 100644 index 000000000..ede5576e6 --- /dev/null +++ b/app/src/main/java/org/mifos/selfserviceapp/utils/RecyclerItemClickListener.java @@ -0,0 +1,125 @@ +package org.mifos.selfserviceapp.utils; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; + +/** + * Created by vjs3 on 20/6/16. + */ + + public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener { + + protected OnItemClickListener listener; + + private GestureDetector gestureDetector; + + @Nullable + private View childView; + + private int childViewPosition; + + public RecyclerItemClickListener(Context context, OnItemClickListener listener) { + this.gestureDetector = new GestureDetector(context, new GestureListener()); + this.listener = listener; + } + + @Override + public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent event) { + childView = view.findChildViewUnder(event.getX(), event.getY()); + childViewPosition = view.getChildAdapterPosition(childView); + + return childView != null && gestureDetector.onTouchEvent(event); + } + + @Override + public void onTouchEvent(RecyclerView view, MotionEvent event) { + // Not needed. + } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + + } + + /** + * A click listener for items. + */ + public interface OnItemClickListener { + + /** + * Called when an item is clicked. + * + * @param childView View of the item that was clicked. + * @param position Position of the item that was clicked. + */ + public void onItemClick(View childView, int position); + + /** + * Called when an item is long pressed. + * + * @param childView View of the item that was long pressed. + * @param position Position of the item that was long pressed. + */ + public void onItemLongPress(View childView, int position); + + } + + /** + * A simple click listener whose methods can be overridden one by one. + */ + public abstract static class SimpleOnItemClickListener implements OnItemClickListener { + + /** + * Called when an item is clicked. The default implementation is a no-op. + * + * @param childView View of the item that was clicked. + * @param position Position of the item that was clicked. + */ + public void onItemClick(View childView, int position) { + // Do nothing. + } + + /** + * Called when an item is long pressed. The default implementation is a no-op. + * + * @param childView View of the item that was long pressed. + * @param position Position of the item that was long pressed. + */ + public void onItemLongPress(View childView, int position) { + // Do nothing. + } + + } + + protected class GestureListener extends GestureDetector.SimpleOnGestureListener { + + @Override + public boolean onSingleTapUp(MotionEvent event) { + if (childView != null) { + listener.onItemClick(childView, childViewPosition); + } + + return true; + } + + @Override + public void onLongPress(MotionEvent event) { + if (childView != null) { + listener.onItemLongPress(childView, childViewPosition); + } + } + + @Override + public boolean onDown(MotionEvent event) { + // Best practice to always return true here. + // http://developer.android.com/training/gestures/detector.html#detect + return true; + } + + } + +} diff --git a/app/src/main/res/layout/activity_client_accounts.xml b/app/src/main/res/layout/activity_client_accounts.xml new file mode 100644 index 000000000..623a9af52 --- /dev/null +++ b/app/src/main/res/layout/activity_client_accounts.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + \ 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 000000000..44ba2ab7d --- /dev/null +++ b/app/src/main/res/layout/activity_home.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + \ 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 new file mode 100644 index 000000000..2fe2f56dc --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_client_list.xml b/app/src/main/res/layout/fragment_client_list.xml new file mode 100644 index 000000000..d57ecb6a0 --- /dev/null +++ b/app/src/main/res/layout/fragment_client_list.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_loan_accounts_list.xml b/app/src/main/res/layout/fragment_loan_accounts_list.xml new file mode 100644 index 000000000..ec46d0b60 --- /dev/null +++ b/app/src/main/res/layout/fragment_loan_accounts_list.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_saving_accounts_list.xml b/app/src/main/res/layout/fragment_saving_accounts_list.xml new file mode 100644 index 000000000..64a52f82a --- /dev/null +++ b/app/src/main/res/layout/fragment_saving_accounts_list.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/nav_drawer_header.xml b/app/src/main/res/layout/nav_drawer_header.xml new file mode 100644 index 000000000..23d7a9790 --- /dev/null +++ b/app/src/main/res/layout/nav_drawer_header.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/row_client_name.xml b/app/src/main/res/layout/row_client_name.xml new file mode 100644 index 000000000..c6d5d6093 --- /dev/null +++ b/app/src/main/res/layout/row_client_name.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/row_loan_account.xml b/app/src/main/res/layout/row_loan_account.xml new file mode 100644 index 000000000..6633a5043 --- /dev/null +++ b/app/src/main/res/layout/row_loan_account.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/row_saving_account.xml b/app/src/main/res/layout/row_saving_account.xml new file mode 100644 index 000000000..70fd5a020 --- /dev/null +++ b/app/src/main/res/layout/row_saving_account.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/toolbar.xml b/app/src/main/res/layout/toolbar.xml new file mode 100644 index 000000000..da239d2ee --- /dev/null +++ b/app/src/main/res/layout/toolbar.xml @@ -0,0 +1,8 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_nav_drawer.xml b/app/src/main/res/menu/menu_nav_drawer.xml new file mode 100644 index 000000000..0496445ae --- /dev/null +++ b/app/src/main/res/menu/menu_nav_drawer.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_clients.png b/app/src/main/res/mipmap-hdpi/ic_clients.png new file mode 100644 index 0000000000000000000000000000000000000000..5a39aa03041fd8daadc66eb45ba9c646e67b7d46 GIT binary patch literal 1001 zcmVg1rc{wK}3B}N>G$Eb0@Vz-*jOY{{T_2z7^~? znWRBcg6M;a2-Y8n;BQ6PcKfiRFXFGRU@C>Sxn~(k@n_7P%%skixvz81x!=$Io}A2F z!USD3LAels{okAo919%t$q59l=o2HfWmL_vTrL;R=kx0TY$c+f0L(0^dcn-M0i20M zB0bS)bXZ%hgTShQb#-+u6ha&zqD=s5OXwM4=JQIa{VgpmeGW8hg?bK_PN#on=A!`S zYbgNwiD-{u7*{ppwZc3F>+bGeQYaKI0GO?{`-h-sp-^aJb93_}hj}H#Jq5EYD+NGS zD9(~nnib}Lk>(j#DwS#^q87IZwGo{n%O8|a#DeAIe80(3MUDojiESt?v8XXz?k`n zX`1`o)ELY4WO&%cGMUV3rPM_LlPVPUP6)9f9*^IsFuywEzSxe(0qm$y*a^chc6!l< zo{jr45X-Vw0yqbt!6Dph0Gp+hw;bk;&nuO^OEQ_9c}B9S<+8Lt)Q z*>CLQ-7=ZXa-~!|fHeR_2_*`^bs@yQcszbjORa;Ts(=-zWJCzD1;93DUh(mVCK25M za9SyK)-=t$1HIazRRhyjP^G{CtV#!4wX%U@PL4L4&CVDe9{z!dW)aae01*J;Vh#IN zD$mRV%=|nY4nK*-VlSQ4*NJuQST2{V8yp;53Sb!#{m9G<0n7z3;~S%XOq)IOZK%gY z)W^&Z0o<>zuYVAYMu&6&O2t$R*4f$FP+MEOz4!{XN&`Yyrww}(z=@HOk&~^ht@c}q zOb%M5^HQp#6OQXPR6FKqqUV+&o*Z!mR!y1rMmi>^`b!-5@R6kGw_*Y6< z_K*XxiR#!t0H*k)72ilH=ati<)r#ec`0;rF=0{h)r73VMaLgws5VWFCjL?=bVIBJq X)gc>3?NoX`00000NkvXXu0mjfT%6Ii literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/mifos_logo.jpg b/app/src/main/res/mipmap-hdpi/mifos_logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a067a3c8edb0f19925c7f9ad7c5a72b27b5e5150 GIT binary patch literal 75684 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%0A9SW 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 - #3F51B5 - #303F9F - #FF4081 - + #ffffffff + #000000 + #ff14c416 + #ff8bf98a + #fff9ac06 + #FF87DBF9 + #fff9393c + #ffd1d1d1 + #8ad3da44 + #8ada6134 + #ff003fff + #FF0000 + + + #ff33b5e5 + + #33999999 + + #BB666666 + + #ff99cc00 + + #ffff4444 + + #ff0099cc + + #ff669900 + + #ffcc0000 + + #ffaa66cc + + #ffffbb33 + + #ffff8800 + + #ff00ddff + + #33CCCCCC + + + + #3F51B5 + #303F9F + #BBDEFB + #03A9F4 + #212121 + #727272 + #FFFFFF + #B6B6B6 + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 000000000..f9b56df01 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml new file mode 100644 index 000000000..f76ac19fe --- /dev/null +++ b/app/src/main/res/values/ids.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bc250c368..d0b056ba1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,32 @@ Self Service App + Login + Welcome + Not connected to internet + Basic + Invalid username + Invalid password + Logging In + Loading + Password + Email + Error loading response from server + Accounts + Clients + Funds Transfer + Recent Transactions + Questionnaire + About Us + Open Drawer + Close Drawer + Home + Medium Text + Small Text + There was some error in fetching client list + There was some error in fetching saving accounts list + There was some error in fetching loan accounts list + Client Accounts + Splash + Saving Accounts + Loan Accounts diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 5885930df..eb8fd1762 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -3,9 +3,25 @@ + + + + + diff --git a/app/src/main/res/values/styles_frame.xml b/app/src/main/res/values/styles_frame.xml new file mode 100644 index 000000000..4c2c04a80 --- /dev/null +++ b/app/src/main/res/values/styles_frame.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles_linear.xml b/app/src/main/res/values/styles_linear.xml new file mode 100644 index 000000000..e4eff4eb6 --- /dev/null +++ b/app/src/main/res/values/styles_linear.xml @@ -0,0 +1,23 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles_toolbar.xml b/app/src/main/res/values/styles_toolbar.xml new file mode 100644 index 000000000..fded91963 --- /dev/null +++ b/app/src/main/res/values/styles_toolbar.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 03bced9f3..cc19335cd 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From 36c51e17d8ebfdd316192e2f4c9af829e2a16fba Mon Sep 17 00:00:00 2001 From: Vishwajeet Srivastava Date: Tue, 5 Jul 2016 12:52:15 +0530 Subject: [PATCH 2/2] Combined all the presenters, views, activities into one. --- app/src/main/AndroidManifest.xml | 6 +++--- .../{home => presenters}/ClientListPresenter.java | 4 ++-- .../{home => presenters}/LoanAccountsListPresenter.java | 8 +++----- .../{login => presenters}/LoginPresenter.java | 6 +++--- .../SavingAccountsListPresenter.java | 7 +++---- .../{home => ui/activities}/ClientAccountsActivity.java | 4 +++- .../{home => ui/activities}/HomeActivity.java | 3 ++- .../{login => ui/activities}/LoginActivity.java | 9 ++++----- .../{home => ui/fragments}/ClientListFragment.java | 5 ++++- .../{home => ui/fragments}/LoanAccountsListFragment.java | 7 +++---- .../fragments}/SavingAccountsListFragment.java | 5 +++-- .../{home => ui/views}/ClientListMvpView.java | 2 +- .../{home => ui/views}/LoanAccountsListView.java | 2 +- .../selfserviceapp/{login => ui/views}/LoginView.java | 5 +---- .../{home => ui/views}/SavingAccountsListView.java | 2 +- 15 files changed, 37 insertions(+), 38 deletions(-) rename app/src/main/java/org/mifos/selfserviceapp/{home => presenters}/ClientListPresenter.java (91%) rename app/src/main/java/org/mifos/selfserviceapp/{home => presenters}/LoanAccountsListPresenter.java (81%) rename app/src/main/java/org/mifos/selfserviceapp/{login => presenters}/LoginPresenter.java (91%) rename app/src/main/java/org/mifos/selfserviceapp/{home => presenters}/SavingAccountsListPresenter.java (85%) rename app/src/main/java/org/mifos/selfserviceapp/{home => ui/activities}/ClientAccountsActivity.java (88%) rename app/src/main/java/org/mifos/selfserviceapp/{home => ui/activities}/HomeActivity.java (98%) rename app/src/main/java/org/mifos/selfserviceapp/{login => ui/activities}/LoginActivity.java (95%) rename app/src/main/java/org/mifos/selfserviceapp/{home => ui/fragments}/ClientListFragment.java (95%) rename app/src/main/java/org/mifos/selfserviceapp/{home => ui/fragments}/LoanAccountsListFragment.java (95%) rename app/src/main/java/org/mifos/selfserviceapp/{home => ui/fragments}/SavingAccountsListFragment.java (96%) rename app/src/main/java/org/mifos/selfserviceapp/{home => ui/views}/ClientListMvpView.java (90%) rename app/src/main/java/org/mifos/selfserviceapp/{home => ui/views}/LoanAccountsListView.java (90%) rename app/src/main/java/org/mifos/selfserviceapp/{login => ui/views}/LoginView.java (72%) rename app/src/main/java/org/mifos/selfserviceapp/{home => ui/views}/SavingAccountsListView.java (90%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6fea96192..79ba97c5a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,7 +10,7 @@ android:supportsRtl="true" android:theme="@style/MaterialAppTheme"> @@ -20,11 +20,11 @@ diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/ClientListPresenter.java b/app/src/main/java/org/mifos/selfserviceapp/presenters/ClientListPresenter.java similarity index 91% rename from app/src/main/java/org/mifos/selfserviceapp/home/ClientListPresenter.java rename to app/src/main/java/org/mifos/selfserviceapp/presenters/ClientListPresenter.java index 22505f4e2..8e39fca22 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/ClientListPresenter.java +++ b/app/src/main/java/org/mifos/selfserviceapp/presenters/ClientListPresenter.java @@ -1,11 +1,11 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.presenters; import android.util.Log; import org.mifos.selfserviceapp.R; import org.mifos.selfserviceapp.api.DataManager; import org.mifos.selfserviceapp.data.Client; -import org.mifos.selfserviceapp.presenters.BasePresenter; +import org.mifos.selfserviceapp.ui.views.ClientListMvpView; import retrofit2.Call; import retrofit2.Callback; diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListPresenter.java b/app/src/main/java/org/mifos/selfserviceapp/presenters/LoanAccountsListPresenter.java similarity index 81% rename from app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListPresenter.java rename to app/src/main/java/org/mifos/selfserviceapp/presenters/LoanAccountsListPresenter.java index 8ec67ab9c..c2d0f8236 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListPresenter.java +++ b/app/src/main/java/org/mifos/selfserviceapp/presenters/LoanAccountsListPresenter.java @@ -1,13 +1,11 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.presenters; import android.util.Log; import org.mifos.selfserviceapp.R; import org.mifos.selfserviceapp.api.DataManager; -import org.mifos.selfserviceapp.data.Client; import org.mifos.selfserviceapp.data.accounts.LoanAccount; -import org.mifos.selfserviceapp.data.accounts.SavingAccount; -import org.mifos.selfserviceapp.presenters.BasePresenter; +import org.mifos.selfserviceapp.ui.views.LoanAccountsListView; import retrofit2.Call; import retrofit2.Callback; @@ -21,7 +19,7 @@ public class LoanAccountsListPresenter extends BasePresenter{ DataManager mDataManager; - protected LoanAccountsListPresenter(DataManager dataManager) { + public LoanAccountsListPresenter(DataManager dataManager) { mDataManager = dataManager; } diff --git a/app/src/main/java/org/mifos/selfserviceapp/login/LoginPresenter.java b/app/src/main/java/org/mifos/selfserviceapp/presenters/LoginPresenter.java similarity index 91% rename from app/src/main/java/org/mifos/selfserviceapp/login/LoginPresenter.java rename to app/src/main/java/org/mifos/selfserviceapp/presenters/LoginPresenter.java index 1249e2108..bc0d30363 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/login/LoginPresenter.java +++ b/app/src/main/java/org/mifos/selfserviceapp/presenters/LoginPresenter.java @@ -1,11 +1,11 @@ -package org.mifos.selfserviceapp.login; +package org.mifos.selfserviceapp.presenters; import android.util.Log; import org.mifos.selfserviceapp.R; import org.mifos.selfserviceapp.data.User; import org.mifos.selfserviceapp.api.DataManager; -import org.mifos.selfserviceapp.presenters.BasePresenter; +import org.mifos.selfserviceapp.ui.views.LoginView; import org.mifos.selfserviceapp.utils.PrefManager; import retrofit2.Call; @@ -21,7 +21,7 @@ public class LoginPresenter extends BasePresenter { DataManager mDataManager; PrefManager prefManager; - protected LoginPresenter(DataManager dataManager) { + public LoginPresenter(DataManager dataManager) { mDataManager = dataManager; } diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListPresenter.java b/app/src/main/java/org/mifos/selfserviceapp/presenters/SavingAccountsListPresenter.java similarity index 85% rename from app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListPresenter.java rename to app/src/main/java/org/mifos/selfserviceapp/presenters/SavingAccountsListPresenter.java index f1ca50d3f..ac4fbb675 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListPresenter.java +++ b/app/src/main/java/org/mifos/selfserviceapp/presenters/SavingAccountsListPresenter.java @@ -1,12 +1,11 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.presenters; import android.util.Log; import org.mifos.selfserviceapp.R; import org.mifos.selfserviceapp.api.DataManager; -import org.mifos.selfserviceapp.data.Client; import org.mifos.selfserviceapp.data.accounts.SavingAccount; -import org.mifos.selfserviceapp.presenters.BasePresenter; +import org.mifos.selfserviceapp.ui.views.SavingAccountsListView; import retrofit2.Call; import retrofit2.Callback; @@ -19,7 +18,7 @@ public class SavingAccountsListPresenter extends BasePresenter{ DataManager mDataManager; - protected SavingAccountsListPresenter(DataManager dataManager) { + public SavingAccountsListPresenter(DataManager dataManager) { mDataManager = dataManager; } diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/ClientAccountsActivity.java b/app/src/main/java/org/mifos/selfserviceapp/ui/activities/ClientAccountsActivity.java similarity index 88% rename from app/src/main/java/org/mifos/selfserviceapp/home/ClientAccountsActivity.java rename to app/src/main/java/org/mifos/selfserviceapp/ui/activities/ClientAccountsActivity.java index dc0c58fb7..2358fb4d9 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/ClientAccountsActivity.java +++ b/app/src/main/java/org/mifos/selfserviceapp/ui/activities/ClientAccountsActivity.java @@ -1,4 +1,4 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.ui.activities; import android.os.Bundle; import android.support.design.widget.TabLayout; @@ -7,6 +7,8 @@ import org.mifos.selfserviceapp.R; import org.mifos.selfserviceapp.adapters.ViewPagerAdapter; +import org.mifos.selfserviceapp.ui.fragments.LoanAccountsListFragment; +import org.mifos.selfserviceapp.ui.fragments.SavingAccountsListFragment; import org.mifos.selfserviceapp.utils.Constants; import butterknife.BindView; diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/HomeActivity.java b/app/src/main/java/org/mifos/selfserviceapp/ui/activities/HomeActivity.java similarity index 98% rename from app/src/main/java/org/mifos/selfserviceapp/home/HomeActivity.java rename to app/src/main/java/org/mifos/selfserviceapp/ui/activities/HomeActivity.java index e5c4492b4..ed19bf2b9 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/HomeActivity.java +++ b/app/src/main/java/org/mifos/selfserviceapp/ui/activities/HomeActivity.java @@ -1,4 +1,4 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.ui.activities; import android.content.Intent; import android.os.Bundle; @@ -19,6 +19,7 @@ import org.mifos.selfserviceapp.api.DataManager; import org.mifos.selfserviceapp.data.Client; import org.mifos.selfserviceapp.utils.Constants; +import org.mifos.selfserviceapp.ui.fragments.ClientListFragment; import java.util.ArrayList; import java.util.List; diff --git a/app/src/main/java/org/mifos/selfserviceapp/login/LoginActivity.java b/app/src/main/java/org/mifos/selfserviceapp/ui/activities/LoginActivity.java similarity index 95% rename from app/src/main/java/org/mifos/selfserviceapp/login/LoginActivity.java rename to app/src/main/java/org/mifos/selfserviceapp/ui/activities/LoginActivity.java index 374a85101..97c0b5427 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/login/LoginActivity.java +++ b/app/src/main/java/org/mifos/selfserviceapp/ui/activities/LoginActivity.java @@ -1,8 +1,7 @@ -package org.mifos.selfserviceapp.login; +package org.mifos.selfserviceapp.ui.activities; import android.app.ProgressDialog; import android.content.Intent; -import android.content.SharedPreferences; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; @@ -10,24 +9,24 @@ import android.widget.EditText; import android.widget.Toast; -import org.mifos.selfserviceapp.data.User; import org.mifos.selfserviceapp.R; import org.mifos.selfserviceapp.api.BaseApiManager; import org.mifos.selfserviceapp.api.DataManager; import org.mifos.selfserviceapp.home.HomeActivity; +import org.mifos.selfserviceapp.presenters.LoginPresenter; +import org.mifos.selfserviceapp.ui.views.LoginView; import org.mifos.selfserviceapp.utils.PrefManager; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; -import retrofit2.Response; /** * @author Vishwajeet * @since 05/06/16 */ -public class LoginActivity extends AppCompatActivity implements LoginView{ +public class LoginActivity extends AppCompatActivity implements LoginView { private LoginPresenter mLoginPresenter; private DataManager mDataManager; diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/ClientListFragment.java b/app/src/main/java/org/mifos/selfserviceapp/ui/fragments/ClientListFragment.java similarity index 95% rename from app/src/main/java/org/mifos/selfserviceapp/home/ClientListFragment.java rename to app/src/main/java/org/mifos/selfserviceapp/ui/fragments/ClientListFragment.java index ff8ea0271..77a57b8aa 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/ClientListFragment.java +++ b/app/src/main/java/org/mifos/selfserviceapp/ui/fragments/ClientListFragment.java @@ -1,4 +1,4 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.ui.fragments; import android.app.ProgressDialog; import android.content.Intent; @@ -17,6 +17,9 @@ import org.mifos.selfserviceapp.api.BaseApiManager; import org.mifos.selfserviceapp.api.DataManager; import org.mifos.selfserviceapp.data.Client; +import org.mifos.selfserviceapp.presenters.ClientListPresenter; +import org.mifos.selfserviceapp.ui.views.ClientListMvpView; +import org.mifos.selfserviceapp.ui.activities.ClientAccountsActivity; import org.mifos.selfserviceapp.utils.Constants; import org.mifos.selfserviceapp.utils.RecyclerItemClickListener; diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListFragment.java b/app/src/main/java/org/mifos/selfserviceapp/ui/fragments/LoanAccountsListFragment.java similarity index 95% rename from app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListFragment.java rename to app/src/main/java/org/mifos/selfserviceapp/ui/fragments/LoanAccountsListFragment.java index 1d94157a6..732758112 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListFragment.java +++ b/app/src/main/java/org/mifos/selfserviceapp/ui/fragments/LoanAccountsListFragment.java @@ -1,4 +1,4 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.ui.fragments; import android.app.ProgressDialog; import android.os.Bundle; @@ -12,12 +12,11 @@ import org.mifos.selfserviceapp.R; import org.mifos.selfserviceapp.adapters.LoanAccountsListAdapter; -import org.mifos.selfserviceapp.adapters.SavingAccountsListAdapter; import org.mifos.selfserviceapp.api.BaseApiManager; import org.mifos.selfserviceapp.api.DataManager; -import org.mifos.selfserviceapp.data.Client; import org.mifos.selfserviceapp.data.accounts.LoanAccount; -import org.mifos.selfserviceapp.data.accounts.SavingAccount; +import org.mifos.selfserviceapp.presenters.LoanAccountsListPresenter; +import org.mifos.selfserviceapp.ui.views.LoanAccountsListView; import org.mifos.selfserviceapp.utils.Constants; import org.mifos.selfserviceapp.utils.RecyclerItemClickListener; diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListFragment.java b/app/src/main/java/org/mifos/selfserviceapp/ui/fragments/SavingAccountsListFragment.java similarity index 96% rename from app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListFragment.java rename to app/src/main/java/org/mifos/selfserviceapp/ui/fragments/SavingAccountsListFragment.java index b8a307c42..952f845b4 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListFragment.java +++ b/app/src/main/java/org/mifos/selfserviceapp/ui/fragments/SavingAccountsListFragment.java @@ -1,4 +1,4 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.ui.fragments; import android.app.ProgressDialog; import android.os.Bundle; @@ -14,8 +14,9 @@ import org.mifos.selfserviceapp.adapters.SavingAccountsListAdapter; import org.mifos.selfserviceapp.api.BaseApiManager; import org.mifos.selfserviceapp.api.DataManager; -import org.mifos.selfserviceapp.data.Client; import org.mifos.selfserviceapp.data.accounts.SavingAccount; +import org.mifos.selfserviceapp.presenters.SavingAccountsListPresenter; +import org.mifos.selfserviceapp.ui.views.SavingAccountsListView; import org.mifos.selfserviceapp.utils.Constants; import org.mifos.selfserviceapp.utils.RecyclerItemClickListener; diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/ClientListMvpView.java b/app/src/main/java/org/mifos/selfserviceapp/ui/views/ClientListMvpView.java similarity index 90% rename from app/src/main/java/org/mifos/selfserviceapp/home/ClientListMvpView.java rename to app/src/main/java/org/mifos/selfserviceapp/ui/views/ClientListMvpView.java index 975b0f38a..139c48f68 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/ClientListMvpView.java +++ b/app/src/main/java/org/mifos/selfserviceapp/ui/views/ClientListMvpView.java @@ -1,4 +1,4 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.ui.views; import org.mifos.selfserviceapp.data.Client; import org.mifos.selfserviceapp.ui.views.base.MVPView; diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListView.java b/app/src/main/java/org/mifos/selfserviceapp/ui/views/LoanAccountsListView.java similarity index 90% rename from app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListView.java rename to app/src/main/java/org/mifos/selfserviceapp/ui/views/LoanAccountsListView.java index 734d95a9f..2b9c479fa 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/LoanAccountsListView.java +++ b/app/src/main/java/org/mifos/selfserviceapp/ui/views/LoanAccountsListView.java @@ -1,4 +1,4 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.ui.views; import org.mifos.selfserviceapp.data.accounts.LoanAccount; import org.mifos.selfserviceapp.ui.views.base.MVPView; diff --git a/app/src/main/java/org/mifos/selfserviceapp/login/LoginView.java b/app/src/main/java/org/mifos/selfserviceapp/ui/views/LoginView.java similarity index 72% rename from app/src/main/java/org/mifos/selfserviceapp/login/LoginView.java rename to app/src/main/java/org/mifos/selfserviceapp/ui/views/LoginView.java index b9fb572b4..9224bf015 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/login/LoginView.java +++ b/app/src/main/java/org/mifos/selfserviceapp/ui/views/LoginView.java @@ -1,10 +1,7 @@ -package org.mifos.selfserviceapp.login; +package org.mifos.selfserviceapp.ui.views; -import org.mifos.selfserviceapp.data.User; import org.mifos.selfserviceapp.ui.views.base.MVPView; -import retrofit2.Response; - /** * @author Vishwajeet * @since 05/06/16 diff --git a/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListView.java b/app/src/main/java/org/mifos/selfserviceapp/ui/views/SavingAccountsListView.java similarity index 90% rename from app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListView.java rename to app/src/main/java/org/mifos/selfserviceapp/ui/views/SavingAccountsListView.java index f2dd45496..63db89f66 100644 --- a/app/src/main/java/org/mifos/selfserviceapp/home/SavingAccountsListView.java +++ b/app/src/main/java/org/mifos/selfserviceapp/ui/views/SavingAccountsListView.java @@ -1,4 +1,4 @@ -package org.mifos.selfserviceapp.home; +package org.mifos.selfserviceapp.ui.views; import org.mifos.selfserviceapp.data.accounts.SavingAccount; import org.mifos.selfserviceapp.ui.views.base.MVPView;