From de42c3b1fcfd4502568f849887b59ce0b6db05d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o?= Date: Fri, 24 Apr 2020 10:34:57 -0300 Subject: [PATCH 01/11] adding the project --- .gitignore | 14 ++ .idea/codeStyles/Project.xml | 122 +++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/gradle.xml | 20 ++ .idea/misc.xml | 25 +++ .idea/runConfigurations.xml | 12 ++ .idea/vcs.xml | 6 + app/.gitignore | 1 + app/build.gradle | 49 +++++ app/proguard-rules.pro | 21 +++ app/src/main/AndroidManifest.xml | 26 +++ .../loginscreen/model/LoginResponseModel.kt | 8 + .../loginscreen/model/UserAccountModel.kt | 11 ++ .../loginscreen/service/LoginService.kt | 16 ++ .../view/activity/LoginActivity.kt | 113 ++++++++++++ .../mainscreen/model/StatementModel.kt | 10 + .../model/StatementsResponseModel.kt | 9 + .../mainscreen/service/StatementsService.kt | 10 + .../mainscreen/view/activity/MainActivity.kt | 129 +++++++++++++ .../view/adapter/StatementsAdapter.kt | 53 ++++++ .../util/retrofit/RetrofitInitializer.kt | 36 ++++ .../util/system/PreferencesHelper.kt | 29 +++ .../util/system/SnackbarHelper.kt | 14 ++ .../testeandroidv2/util/system/SystemUtil.kt | 18 ++ .../drawable-v24/ic_launcher_foreground.xml | 30 +++ .../res/drawable/ic_launcher_background.xml | 170 +++++++++++++++++ app/src/main/res/drawable/logo.png | Bin 0 -> 4662 bytes app/src/main/res/drawable/logout.png | Bin 0 -> 519 bytes app/src/main/res/layout/activity_login.xml | 103 +++++++++++ app/src/main/res/layout/activity_main.xml | 148 +++++++++++++++ app/src/main/res/layout/adapter_item_list.xml | 57 ++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3593 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5339 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2636 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3388 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4926 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7472 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7909 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 11873 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10652 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 16570 bytes app/src/main/res/values/colors.xml | 10 + app/src/main/res/values/strings.xml | 17 ++ app/src/main/res/values/styles.xml | 11 ++ .../testeandroidv2/ExampleUnitTest.kt | 17 ++ build.gradle | 29 +++ gradle.properties | 17 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 ++++++++++++++++++ gradlew.bat | 84 +++++++++ settings.gradle | 2 + 54 files changed, 1640 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 .idea/vcs.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/model/LoginResponseModel.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/model/UserAccountModel.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/service/LoginService.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/view/activity/LoginActivity.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/model/StatementModel.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/model/StatementsResponseModel.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/service/StatementsService.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/view/activity/MainActivity.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/view/adapter/StatementsAdapter.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/util/retrofit/RetrofitInitializer.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/util/system/PreferencesHelper.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/util/system/SnackbarHelper.kt create mode 100644 app/src/main/java/com/joaoneto/testeandroidv2/util/system/SystemUtil.kt create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/drawable/logo.png create mode 100644 app/src/main/res/drawable/logout.png create mode 100644 app/src/main/res/layout/activity_login.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/adapter_item_list.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 app/src/test/java/com/joaoneto/testeandroidv2/ExampleUnitTest.kt create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..603b14077 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 000000000..88ea3aa1e --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,122 @@ + + + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+ + +
+
\ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 000000000..79ee123c2 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 000000000..5cd135a06 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 000000000..0d40bc82d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + 1.8 + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 000000000..7f68460d8 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 000000000..41295f318 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,49 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.3" + + defaultConfig { + applicationId "com.joaoneto.testeandroidv2" + minSdkVersion 24 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.google.android.material:material:1.0.0' + testImplementation 'junit:junit:4.13' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + + //retrofit + implementation 'com.squareup.retrofit2:retrofit:2.5.0' + implementation 'com.squareup.retrofit2:converter-jackson:2.5.0' + implementation 'com.squareup.retrofit2:converter-gson:2.5.0' + implementation 'com.squareup.okhttp3:logging-interceptor:3.13.1' + +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 000000000..f1b424510 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..6340d136c --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/model/LoginResponseModel.kt b/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/model/LoginResponseModel.kt new file mode 100644 index 000000000..1e9c01bd8 --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/model/LoginResponseModel.kt @@ -0,0 +1,8 @@ +package com.joaoneto.testeandroidv2.loginscreen.model + +import java.io.Serializable + +class LoginResponseModel : Serializable { + var userAccount: UserAccountModel? = null + var error: Void? = null +} \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/model/UserAccountModel.kt b/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/model/UserAccountModel.kt new file mode 100644 index 000000000..e99249c10 --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/model/UserAccountModel.kt @@ -0,0 +1,11 @@ +package com.joaoneto.testeandroidv2.loginscreen.model + +import java.io.Serializable + +class UserAccountModel : Serializable { + var userId: Int? = null + var name: String? = null + var bankAccount: String? = null + var agency: String? = null + var balance: Double? = null +} \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/service/LoginService.kt b/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/service/LoginService.kt new file mode 100644 index 000000000..e2551f45a --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/service/LoginService.kt @@ -0,0 +1,16 @@ +package com.joaoneto.testeandroidv2.loginscreen.service + +import com.joaoneto.testeandroidv2.loginscreen.model.LoginResponseModel +import retrofit2.Call +import retrofit2.http.Field +import retrofit2.http.FormUrlEncoded +import retrofit2.http.POST + +interface LoginService { + @FormUrlEncoded + @POST("login") + fun signIn( + @Field("user") user: String, + @Field("password") password: String + ): Call +} \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/view/activity/LoginActivity.kt b/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/view/activity/LoginActivity.kt new file mode 100644 index 000000000..92455c376 --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/loginscreen/view/activity/LoginActivity.kt @@ -0,0 +1,113 @@ +package com.joaoneto.testeandroidv2.loginscreen.view.activity + +import android.content.Intent +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.text.Editable +import android.util.Log +import com.joaoneto.testeandroidv2.mainscreen.view.activity.MainActivity +import com.joaoneto.testeandroidv2.R +import com.joaoneto.testeandroidv2.loginscreen.model.LoginResponseModel +import com.joaoneto.testeandroidv2.util.system.PreferencesHelper +import com.joaoneto.testeandroidv2.util.retrofit.RetrofitInitializer +import com.joaoneto.testeandroidv2.util.system.SnackbarHelper +import kotlinx.android.synthetic.main.activity_login.* +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class LoginActivity : AppCompatActivity() { + + private val preferencesHelper: PreferencesHelper by lazy { + PreferencesHelper(this) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_login); + checkPreferences() + checkFields() + } + + private fun checkFields() { + + loginButton.setOnClickListener { + val user = inputEmail.text.toString() + val pass = inputPass.text.toString() + + if (user.isNotEmpty() && pass.isNotEmpty()) { + signIn(user, pass) + } else { + SnackbarHelper.message(loginConstraint, "Campos obrigatórios vazios") + } + } + + } + + private fun signIn(user: String, password: String) { + + RetrofitInitializer().loginService() + .signIn(user, password) + .enqueue(object : Callback { + override fun onFailure(call: Call, t: Throwable) { + + Log.i("--->", t.message!!) + SnackbarHelper.message( + loginConstraint, + "Erro ao acessar conta, verifique suas credenciais" + ) + } + + override fun onResponse( + call: Call, + response: Response + ) { + + if (response.code() == 200) { + + preferencesHelper.setUsername(user) + preferencesHelper.setPassword(password) + + Log.i("--->", response.message()) + Log.i("--->", response.code().toString()) + Log.i("--->", response.body()?.userAccount?.agency!!) + val userAccountModel = response.body()?.userAccount + + val intent = Intent(this@LoginActivity, MainActivity::class.java) + val bundle = Bundle() + bundle.putSerializable("userAccountData", userAccountModel) + intent.putExtras(bundle) + startActivity(intent) + finish() + + } else { + SnackbarHelper.message( + loginConstraint, + "Erro ao acessar conta, tente novamente" + ) + } + + } + + }) + + } + + private fun checkPreferences() { + if (preferencesHelper.getUsername().isNotEmpty()) { + inputEmail.text = + Editable.Factory.getInstance().newEditable(preferencesHelper.getUsername()) + + } else { + inputEmail.text = Editable.Factory.getInstance().newEditable("") + } + if (preferencesHelper.getPassword().isNotEmpty()) { + inputPass.text = + Editable.Factory.getInstance().newEditable(preferencesHelper.getPassword()) + } else { + inputPass.text = + Editable.Factory.getInstance().newEditable("") + } + } + +} diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/model/StatementModel.kt b/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/model/StatementModel.kt new file mode 100644 index 000000000..8400f7e47 --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/model/StatementModel.kt @@ -0,0 +1,10 @@ +package com.joaoneto.testeandroidv2.mainscreen.model + +import java.io.Serializable + +class StatementModel: Serializable { + var title: String? = null + var desc: String? = null + var date: String? = null + var value: Double? = null +} \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/model/StatementsResponseModel.kt b/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/model/StatementsResponseModel.kt new file mode 100644 index 000000000..6f3f7f7f8 --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/model/StatementsResponseModel.kt @@ -0,0 +1,9 @@ +package com.joaoneto.testeandroidv2.mainscreen.model + +import com.joaoneto.testeandroidv2.mainscreen.model.StatementModel +import java.io.Serializable + +class StatementsResponseModel : Serializable{ + var statementList: List? = null + var error: Void? = null +} \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/service/StatementsService.kt b/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/service/StatementsService.kt new file mode 100644 index 000000000..4ea5b3590 --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/service/StatementsService.kt @@ -0,0 +1,10 @@ +package com.joaoneto.testeandroidv2.mainscreen.service + +import com.joaoneto.testeandroidv2.mainscreen.model.StatementsResponseModel +import retrofit2.Call +import retrofit2.http.GET + +interface StatementsService { + @GET("statements/1") + fun getStatements(): Call +} \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/view/activity/MainActivity.kt b/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/view/activity/MainActivity.kt new file mode 100644 index 000000000..f174d715f --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/view/activity/MainActivity.kt @@ -0,0 +1,129 @@ +package com.joaoneto.testeandroidv2.mainscreen.view.activity + +import android.content.Intent +import android.os.Bundle +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.appbar.AppBarLayout +import com.joaoneto.testeandroidv2.R +import com.joaoneto.testeandroidv2.loginscreen.view.activity.LoginActivity +import com.joaoneto.testeandroidv2.loginscreen.model.UserAccountModel +import com.joaoneto.testeandroidv2.mainscreen.model.StatementModel +import com.joaoneto.testeandroidv2.mainscreen.model.StatementsResponseModel +import com.joaoneto.testeandroidv2.mainscreen.view.adapter.StatementsAdapter +import com.joaoneto.testeandroidv2.util.retrofit.RetrofitInitializer +import com.joaoneto.testeandroidv2.util.system.SnackbarHelper +import kotlinx.android.synthetic.main.activity_main.* +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import java.text.NumberFormat + +class MainActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + setUpAppBar() + setUpView() + getStatements() + } + + override fun onBackPressed() { + super.onBackPressed() + logout() + + } + + + private fun setUpView() { + + val account = intent.extras?.getSerializable("userAccountData") as UserAccountModel + val number = "${account.bankAccount}/${account.agency?.substring( + 0, + 7 + )}-${account.agency?.substring(8)}" + clientNameTextView.text = account.name + accountNumberTextView.text = number + accountMoneyValueTextView.text = NumberFormat.getCurrencyInstance().format(account.balance) + + logoutImageView.setOnClickListener { + logout() + } + + } + + private fun setUpAppBar() { + setSupportActionBar(toolbar) + supportActionBar!!.setDisplayHomeAsUpEnabled(false) + toolbar.setNavigationOnClickListener { + } + collapsingToolbar.setCollapsedTitleTextColor( + ContextCompat.getColor( + this, + R.color.colorWhite + ) + ) + appBar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOfSet -> + if (verticalOfSet == 0) { + appbarConstraint.visibility = View.VISIBLE + collapsingToolbar.title = " " + } else { + appbarConstraint.visibility = View.INVISIBLE + collapsingToolbar.title = "Bank" + + } + }) + } + + private fun setUpRecyclerView(statements: List) { + operationsRecyclerView.adapter = + StatementsAdapter( + statements + ) + operationsRecyclerView.layoutManager = + LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) + } + + private fun getStatements() { + listOfRecentOperationTextView.visibility = View.GONE + RetrofitInitializer().statementsService().getStatements() + .enqueue(object : Callback { + override fun onFailure(call: Call, t: Throwable) { + SnackbarHelper.message( + mainConstraint, + "Erro ao buscar as operações, tente novamente mais tarde." + ) + } + + override fun onResponse( + call: Call, + response: Response + ) { + if (response.code() == 200) { + listOfRecentOperationTextView.visibility = View.VISIBLE + + response.body()?.statementList?.let { setUpRecyclerView(it) } + + } else { + SnackbarHelper.message( + mainConstraint, + "Erro ao buscar as operações, tente novamente mais tarde." + ) + } + + } + + }) + } + + private fun logout() { + val intent = Intent(this, LoginActivity::class.java) + startActivity(intent) + finish() + } + + +} diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/view/adapter/StatementsAdapter.kt b/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/view/adapter/StatementsAdapter.kt new file mode 100644 index 000000000..071dc09a5 --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/mainscreen/view/adapter/StatementsAdapter.kt @@ -0,0 +1,53 @@ +package com.joaoneto.testeandroidv2.mainscreen.view.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.joaoneto.testeandroidv2.R +import com.joaoneto.testeandroidv2.mainscreen.model.StatementModel +import kotlinx.android.synthetic.main.adapter_item_list.view.* +import java.text.NumberFormat + +class StatementsAdapter(private val statements: List) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = + ViewHolder( + LayoutInflater.from(parent.context).inflate( + R.layout.adapter_item_list, + parent, + false + ) + ) + + override fun getItemCount(): Int = statements.size + + override fun onBindViewHolder(holder: ViewHolder, position: Int) = + holder.bindView(statements[position]) + + class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + private val operationTypeTextView = itemView.operationTypeTextView + private val operationDateTextView = itemView.operationDateTextView + private val operationValueTextView = itemView.operationValueTextView + private val operationDescriptionTextView = itemView.operationDescriptionTextView + + + fun bindView(statement: StatementModel) { + + val date = "${statement.date?.substring(8, 9)}/${statement.date?.substring( + 5, + 6 + )}/${statement.date?.substring(0, 3)}" + + operationDateTextView.text = date + + + operationDescriptionTextView.text = statement.desc + operationTypeTextView.text = statement.title + operationValueTextView.text = NumberFormat.getCurrencyInstance().format(statement.value) + + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/util/retrofit/RetrofitInitializer.kt b/app/src/main/java/com/joaoneto/testeandroidv2/util/retrofit/RetrofitInitializer.kt new file mode 100644 index 000000000..ff94e26e1 --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/util/retrofit/RetrofitInitializer.kt @@ -0,0 +1,36 @@ +package com.joaoneto.testeandroidv2.util.retrofit + +import com.joaoneto.testeandroidv2.loginscreen.service.LoginService +import com.joaoneto.testeandroidv2.mainscreen.service.StatementsService +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.converter.jackson.JacksonConverterFactory +import java.util.concurrent.TimeUnit + +class RetrofitInitializer { + private val retrofit: Retrofit + + init { + + val interceptor = HttpLoggingInterceptor() + interceptor.level = HttpLoggingInterceptor.Level.BODY + val client = OkHttpClient.Builder() + .readTimeout(60, TimeUnit.SECONDS) + .connectTimeout(60, TimeUnit.SECONDS) + .retryOnConnectionFailure(false) + .build() + + retrofit = Retrofit.Builder() + .baseUrl("https://bank-app-test.herokuapp.com/api/") + .addConverterFactory(JacksonConverterFactory.create()) + .client(client) + .build() + } + + fun loginService(): LoginService = retrofit.create( + LoginService::class.java) + + fun statementsService(): StatementsService = retrofit.create( + StatementsService::class.java) +} \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/util/system/PreferencesHelper.kt b/app/src/main/java/com/joaoneto/testeandroidv2/util/system/PreferencesHelper.kt new file mode 100644 index 000000000..5b95db479 --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/util/system/PreferencesHelper.kt @@ -0,0 +1,29 @@ +package com.joaoneto.testeandroidv2.util.system + +import android.content.Context +import android.content.SharedPreferences + +class PreferencesHelper(var context: Context) { + + private var preferences: SharedPreferences = + context.getSharedPreferences("testeAndroid2", Context.MODE_PRIVATE) + private var editor = preferences.edit() + + fun getUsername(): String { + return preferences.getString("username", "") as String + } + + fun setUsername(username: String) { + editor.putString("username", username) + editor.commit() + } + + fun getPassword(): String { + return preferences.getString("password", "") as String + } + + fun setPassword(password: String) { + editor.putString("password", password) + editor.commit() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/util/system/SnackbarHelper.kt b/app/src/main/java/com/joaoneto/testeandroidv2/util/system/SnackbarHelper.kt new file mode 100644 index 000000000..9c20d2296 --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/util/system/SnackbarHelper.kt @@ -0,0 +1,14 @@ +package com.joaoneto.testeandroidv2.util.system + +import android.view.View +import com.google.android.material.snackbar.Snackbar + + +class SnackbarHelper { + + companion object { + fun message(view: View, message: String) { + Snackbar.make(view, message, Snackbar.LENGTH_LONG).show() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/joaoneto/testeandroidv2/util/system/SystemUtil.kt b/app/src/main/java/com/joaoneto/testeandroidv2/util/system/SystemUtil.kt new file mode 100644 index 000000000..5bb76955c --- /dev/null +++ b/app/src/main/java/com/joaoneto/testeandroidv2/util/system/SystemUtil.kt @@ -0,0 +1,18 @@ +package com.joaoneto.testeandroidv2.util.system + +import android.app.Activity +import android.content.Context +import android.view.inputmethod.InputMethodManager + +class SystemUtil { + + companion object { + fun hideKeyboard(activity: Activity) { + val view = activity.currentFocus + if (view != null) { + val input = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + input.hideSoftInputFromWindow(view.windowToken, 0) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 000000000..2b068d114 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 000000000..07d5da9cb --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/logo.png b/app/src/main/res/drawable/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..66bdc8d5d4f72d641ee73093c3b1d8ff34506f41 GIT binary patch literal 4662 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/logout.png b/app/src/main/res/drawable/logout.png new file mode 100644 index 0000000000000000000000000000000000000000..de1e4ae3c001abc798483e59649cc97eb9661201 GIT binary patch literal 519 zcmV+i0{H!jP)Px$!AV3xR7efImcK6qK@`Vt&yOpJAaaRoh+Gu3D$TW8iAJdse}KjxK(rcBh=xul zAwh`5X@pLr5eZjF9Io*rVtwA46`P&C8*9c(J~z8>-n{S5%-gxmWR&^7pM?@^Kn3dA z4xMe`Sktyy0vVX4nSfQO!X+Go&RTGm;Z4`s(1+Lv+`yq+Hyn^QfaEz?fm`TLo5y6F zEME>r;R3F~nTeR}TLEgG=lRZ*NGxJv-dE%HHx#p?!k%|QF)5ilNtW}ZoK0DPBTS`Z-PCFK@Qk-CW24`lP_Y435&~E@Dm&wyf7;HNhSaQ002ov JPDHLkV1oP+;TQk_ literal 0 HcmV?d00001 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..dada0b904 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + +