diff --git a/README.md b/README.md
index bd73feb5f..63b0b078e 100644
--- a/README.md
+++ b/README.md
@@ -1,41 +1,68 @@
-# Show me the code
+### Estudo de Caso para uma tela de login de usuario e accesso a uma conta de um banco imaginario.
+
+#### Empresa R. M. Sistemas Web e Mobiles
+###### A pedido de: TCS Mobile hiring
+
+#### 1. - Analize do problema.
+1.1. - preparado a plataforma de trabalho para obter o acesso para a API.
+1.1.1. - Instalacao e configuracao do Postman.
+1.1.2. - Teste dos diversos snipets de requisicao para a API oferecidos pela Collection Mockada via Postmam.
+1.1.3. - Escolhido o Framework OkHttp Client como snipet para as requisicoes junto a API remota.
+
+#### 2. - Criacao de um prototipo inicial.
+2.1. - Escolhido o template "Login Activity" do Android Studio.
+2.2. - Escolhido o teste Espresso Unit Test (JUnit) por ja ser embutido no template do Android Studio e por ser
+ mais facil de manejar diretamente os dados da GUI.
+2.3. - Implementado o parser para receber os resultados da requisicao POST para a API.
+2.4. - Modificado a tela do template para parecer o maximo possivel ao do design proposto no estudo de caso.
+2.5. - Implementado o teste expresso para os diversos complentes clicaveis e editaveis da UI.
+2.6. - Implementado o metodo para a receber os dados da requsicao GET para a API.
+2.7. - Testado a requisicao remota.
+2.8. - Criado o lyout para receber os dados enviados pela API devidamente tratados e formatados.
+2.9. - Criado o adapter para exibir os referidos dados em uma lista conforme o design proposto no estudode caso.
+2.10. - Testado o envio da requiscao e os controles da UI.
+2.11. - Testes finalizados e todos funcionando a contento.
+
+#### 3. - Implementado e Melhorado a GUI
+3.1. - Melhorado a Vizualizacao dos dados na UI.
+3.2. - Criado uma versao em portugues do Brasil para as mensagens de tela que por padrao foram configuradas em ingles.
+3.3. - Criado uma simples tela de splash screen.
+3.4. - projeto postado no github como um pull request numa branch de nome "XYZBankApp".
+
+O projeto XYZBank foi desenvolvido em Kotlin versao "1.3.72" com Android Studio "4.2 Canary 7" e com a mais
+alta versao do gradle "build:gradle:4.2.0-alpha07".
+
+Estao sendo enviados como pull request, a pasta "XYZBank" contendo:
+ - arquivos de configuracao do Android Studio, um screencast video do programa em execucao;
+
+ - a pasta "app" contendo:
+ os fontes "*.kt" do pacote '../src/main/java/com.xyzbank.xyzbankapp/* e os testes
+ os arquivos de layout e resources de tela "*.xml", na pasta '../src/main/res/*';
+ os fontes "*.kt" dos testes nas saus respectivas pastas
+
+ - a pasta gradle para referencia local.
+
+ - a pasta 'outputs/apk/', com um pacote de bytecodes no formato "debug.apk"
+...
+XYZBank
+../app/*
+../gradle/*
+../outputs/apk/*
+../build.gradle
+../gradle.properties
+../gradlew
+../gradlew.bat
+../local.properties
+../README.md - this file
+../settings.gradle
+../XYZBank.webm
+...
+
+##### Conforme proposto no estudo de caso, o app foi criado para Android a partir da versao 4.4 (19 - KitKat)
+##### Para compilar uma versao desse app:
+ - atualize o Android Studio para a ultima versao.
+ - Atualize as entradas do Android SDK desde a versao 19 ate a "major" versao real: 30.
+ - Atualize o plugin do Kotlin para a ultima versao.
+ - Atualize o gradle no projeto para a ultima versao.
-Esse repositório contem todo o material necessário para realizar o teste:
-- A especificação do layout está na pasta 'bank_app_layout' abrindo o index.html, utilizar os Styles do Android
-
-- Os dados da Api estão mockados, os exemplos e a especificação dos serviços (login e statements) se encontram no arquivo BankApp.postman_collection.json ( é necessário instalar o postman e importar a colection https://www.getpostman.com/apps)
-
-
-
-### # DESAFIO:
-
-Na primeira tela teremos um formulario de login, o campo user deve aceitar email ou cpf,
-o campo password deve validar se a senha tem pelo menos uma letra maiuscula, um caracter especial e um caracter alfanumérico.
-Apos a validação, realizar o login no endpoint https://bank-app-test.herokuapp.com/api/login e exibir os dados de retorno na próxima tela.
-O ultimo usuário logado deve ser salvo de forma segura localmente, e exibido na tela de login se houver algum salvo.
-
-Na segunda tela será exibido os dados formatados do retorno do login e será necessário fazer um segundo request para obter os lançamentos do usuário, no endpoint https://bank-app-test.herokuapp.com/api/statements/{idUser} que retornará uma lista de lançamentos
-
-### # Avaliação
-
-Você será avaliado pela usabilidade, por respeitar o design e pela arquitetura do app. É esperado que você consiga explicar as decisões que tomou durante o desenvolvimento através de commits.
-
-Obrigatórios:
-
-* Java ou Kotlin
-* Material Design
-* O app deve funcionar a partir do android 4.4
-* Testes unitários, pode usar a ferramenta que você tem mais experiência, só nos explique o que ele tem de bom.
-* Arquitetura a ser utilizada: Android Clean Code (https://github.com/kmmraj/android-clean-code && https://medium.com/@kmmraj/android-clean-code-part-1-c66da6551d1)
-* Uso do git.
-
-### # Observações gerais
-
-Adicione um arquivo [README.md](http://README.md) com os procedimentos para executar o projeto.
-Pedimos que trabalhe sozinho e não divulgue o resultado na internet.
-
-Faça um fork desse desse repositório em seu Github e ao finalizar nos envie um Pull Request com o resultado, por favor informe por qual empresa você esta se candidatando.
-
-# Importante: não há prazo de entrega, faça com qualidade!
-
-# BOA SORTE!
+ {"statementList":[{"title":"Pagamento","desc":"Conta de luz","date":"2018-08-15","value":-50, ...}],"error":{}}
diff --git a/XYZBank/.DS_Store b/XYZBank/.DS_Store
new file mode 100644
index 000000000..ad7927d4d
Binary files /dev/null and b/XYZBank/.DS_Store differ
diff --git a/XYZBank/.gradle/6.5/executionHistory/executionHistory.bin b/XYZBank/.gradle/6.5/executionHistory/executionHistory.bin
new file mode 100644
index 000000000..87ddb89f5
Binary files /dev/null and b/XYZBank/.gradle/6.5/executionHistory/executionHistory.bin differ
diff --git a/XYZBank/.gradle/6.5/executionHistory/executionHistory.lock b/XYZBank/.gradle/6.5/executionHistory/executionHistory.lock
new file mode 100644
index 000000000..3fcf7bef4
Binary files /dev/null and b/XYZBank/.gradle/6.5/executionHistory/executionHistory.lock differ
diff --git a/XYZBank/.gradle/6.5/fileChanges/last-build.bin b/XYZBank/.gradle/6.5/fileChanges/last-build.bin
new file mode 100644
index 000000000..f76dd238a
Binary files /dev/null and b/XYZBank/.gradle/6.5/fileChanges/last-build.bin differ
diff --git a/XYZBank/.gradle/6.5/fileContent/fileContent.lock b/XYZBank/.gradle/6.5/fileContent/fileContent.lock
new file mode 100644
index 000000000..30a719243
Binary files /dev/null and b/XYZBank/.gradle/6.5/fileContent/fileContent.lock differ
diff --git a/XYZBank/.gradle/6.5/fileHashes/fileHashes.bin b/XYZBank/.gradle/6.5/fileHashes/fileHashes.bin
new file mode 100644
index 000000000..d2059088e
Binary files /dev/null and b/XYZBank/.gradle/6.5/fileHashes/fileHashes.bin differ
diff --git a/XYZBank/.gradle/6.5/fileHashes/fileHashes.lock b/XYZBank/.gradle/6.5/fileHashes/fileHashes.lock
new file mode 100644
index 000000000..ef5f22e5b
Binary files /dev/null and b/XYZBank/.gradle/6.5/fileHashes/fileHashes.lock differ
diff --git a/XYZBank/.gradle/6.5/fileHashes/resourceHashesCache.bin b/XYZBank/.gradle/6.5/fileHashes/resourceHashesCache.bin
new file mode 100644
index 000000000..19f94f2c8
Binary files /dev/null and b/XYZBank/.gradle/6.5/fileHashes/resourceHashesCache.bin differ
diff --git a/XYZBank/.gradle/6.5/gc.properties b/XYZBank/.gradle/6.5/gc.properties
new file mode 100644
index 000000000..e69de29bb
diff --git a/XYZBank/.gradle/6.5/javaCompile/classAnalysis.bin b/XYZBank/.gradle/6.5/javaCompile/classAnalysis.bin
new file mode 100644
index 000000000..ee3240992
Binary files /dev/null and b/XYZBank/.gradle/6.5/javaCompile/classAnalysis.bin differ
diff --git a/XYZBank/.gradle/6.5/javaCompile/jarAnalysis.bin b/XYZBank/.gradle/6.5/javaCompile/jarAnalysis.bin
new file mode 100644
index 000000000..88bcc5b63
Binary files /dev/null and b/XYZBank/.gradle/6.5/javaCompile/jarAnalysis.bin differ
diff --git a/XYZBank/.gradle/6.5/javaCompile/javaCompile.lock b/XYZBank/.gradle/6.5/javaCompile/javaCompile.lock
new file mode 100644
index 000000000..38b659cca
Binary files /dev/null and b/XYZBank/.gradle/6.5/javaCompile/javaCompile.lock differ
diff --git a/XYZBank/.gradle/6.5/javaCompile/taskHistory.bin b/XYZBank/.gradle/6.5/javaCompile/taskHistory.bin
new file mode 100644
index 000000000..280e4500c
Binary files /dev/null and b/XYZBank/.gradle/6.5/javaCompile/taskHistory.bin differ
diff --git a/XYZBank/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/XYZBank/.gradle/buildOutputCleanup/buildOutputCleanup.lock
new file mode 100644
index 000000000..755957125
Binary files /dev/null and b/XYZBank/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ
diff --git a/XYZBank/.gradle/buildOutputCleanup/cache.properties b/XYZBank/.gradle/buildOutputCleanup/cache.properties
new file mode 100644
index 000000000..e9880746c
--- /dev/null
+++ b/XYZBank/.gradle/buildOutputCleanup/cache.properties
@@ -0,0 +1,2 @@
+#Wed Aug 05 13:44:50 BRT 2020
+gradle.version=6.5
diff --git a/XYZBank/.gradle/buildOutputCleanup/outputFiles.bin b/XYZBank/.gradle/buildOutputCleanup/outputFiles.bin
new file mode 100644
index 000000000..4f819716e
Binary files /dev/null and b/XYZBank/.gradle/buildOutputCleanup/outputFiles.bin differ
diff --git a/XYZBank/.gradle/checksums/checksums.lock b/XYZBank/.gradle/checksums/checksums.lock
new file mode 100644
index 000000000..8bef2e7fb
Binary files /dev/null and b/XYZBank/.gradle/checksums/checksums.lock differ
diff --git a/XYZBank/.gradle/vcs-1/gc.properties b/XYZBank/.gradle/vcs-1/gc.properties
new file mode 100644
index 000000000..e69de29bb
diff --git a/XYZBank/README.md b/XYZBank/README.md
new file mode 100644
index 000000000..117d0f611
--- /dev/null
+++ b/XYZBank/README.md
@@ -0,0 +1,68 @@
+Estudo de Caso para uma tela de login de usuario e accesso a uma conta de um banco imaginario.
+
+Empresa R. M. Sistemas Web e Mobiles
+
+1 - Analize do problema.
+
+1.1 - preparado a plataforma de trabalho para obter o acesso para a API.
+1.1.1 - Instalacao e configuracao do Postman.
+1.1.2 - Teste dos diversos snipets de requisicao para a API oferecidos pela Collection Mockada via Postmam.
+1.1.3 - Escolhido o Framework OkHttp Client como snipet para as requisicoes junto a API remota.
+
+2 - Criacao de um prototipo inicial.
+
+2.1 - Escolhido o template "Login Activity" do Android Studio.
+2.2 - Escolhido o teste Espresso Unit Test (JUnit) por ja ser embutido no template do Android Studio e por ser
+ mais facil de manejar diretamente os dados da GUI.
+2.3 - Implementado o parser para receber os resultados da requisicao POST para a API.
+2.4 - Modificado a tela do template para parecer o maximo possivel ao do design proposto no estudo de caso.
+2.5 - Implementado o teste expresso para os diversos componentes clicaveis e editaveis da UI.
+2.6 - Implementado o metodo para a receber os dados da requsicao GET para a API.
+2.7 - Testado a requisicao remota.
+2.8 - Criado o lyout para receber os dados enviados pela API devidamente tratados e formatados.
+2.9 - Criado o adapter para exibir os referidos dados em uma lista conforme o design proposto no estudo de caso.
+2.10 - Testado o envio da requiscao e os controles da UI.
+2.11 - Testes finalizados e todos funcionando a contento.
+
+3 - Implementado e Melhorado a GUI
+
+3.1 - Melhorado a Vizualizacao dos dados na UI.
+3.2 - Criado uma versao em portugues do Brasil para as mensagens de tela que por padrao foram configuradas em ingles.
+3.3 - Criado uma simples tela de splash screen.
+3.4 - projeto postado no github como um pull request numa branch de nome "XYZBankApp".
+
+O projeto XYZBank foi desenvolvido em Kotlin versao "1.3.72" com Android Studio "4.2 Canary 7" e com a mais
+alta versao do gradle "build:gradle:4.2.0-alpha07".
+
+Estao sendo enviados como pull request, a pasta "XYZBank" contendo:
+ - arquivos de configuracao do Android Studio, um screencast video do programa em execucao;
+
+ - a pasta "app" contendo:
+ os fontes "*.kt" do pacote 'app./src/main/java/com.xyzbank.xyzbankapp/* e os testes
+ os arquivos de layout e resources de tela "*.xml", na pasta 'app/src/main/res/*';
+ os fontes "*.kt" dos testes nas saus respectivas pastas
+
+ - a pasta gradle para referencia local.
+
+ - a pasta 'outputs/apk/', com um pacote de bytecodes no formato "debug.apk"
+
+XYZBank/
+app/*
+gradle/*
+outputs/apk/*
+build.gradle
+gradle.properties
+gradlew
+gradlew.bat
+local.properties
+README.md - this file
+settings.gradle
+XYZBank.webm
+
+
+Conforme proposto no estudo de caso, o app foi criado para Android a partir da versao 4.4 (19 - KitKat)
+Para compilar uma versao desse app:
+ - atualize o Android Studio para a ultima versao.
+ - Atualize as entradas do Android SDK desde a versao 19 ate a "major" versao real: 30.
+ - Atualize oplugin do Kotlin para a ultima versao.
+ - Atualize o gradle no projeto para a ultima versao.
diff --git a/XYZBank/XYZBank.webm b/XYZBank/XYZBank.webm
new file mode 100644
index 000000000..2f6dafc76
Binary files /dev/null and b/XYZBank/XYZBank.webm differ
diff --git a/XYZBank/app/build.gradle b/XYZBank/app/build.gradle
new file mode 100644
index 000000000..2f2f1c9b6
--- /dev/null
+++ b/XYZBank/app/build.gradle
@@ -0,0 +1,59 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+}
+
+android {
+ compileSdkVersion 29
+ buildToolsVersion "30.0.1"
+
+ defaultConfig {
+ applicationId "com.xyzbank.xyzbankapp"
+ minSdkVersion 18
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+
+ vectorDrawables.useSupportLibrary = true
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ implementation 'androidx.core:core-ktx:1.3.1'
+ implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation 'com.google.android.material:material:1.1.0'
+ implementation 'androidx.annotation:annotation:1.1.0'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
+ implementation 'com.squareup.okhttp3:okhttp:3.12.0'
+ implementation 'com.intuit.ssp:ssp-android:1.0.6'
+ implementation 'com.intuit.sdp:sdp-android:1.0.6'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+ implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
+ implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
+
+ testImplementation 'junit:junit:4.13'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+ androidTestImplementation 'androidx.test:rules:1.3.0-rc02'
+ androidTestImplementation 'androidx.test.espresso:espresso-intents:3.2.0'
+}
diff --git a/XYZBank/app/proguard-rules.pro b/XYZBank/app/proguard-rules.pro
new file mode 100644
index 000000000..481bb4348
--- /dev/null
+++ b/XYZBank/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
\ No newline at end of file
diff --git a/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ExampleInstrumentedTest.kt b/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ExampleInstrumentedTest.kt
new file mode 100644
index 000000000..8783cb4eb
--- /dev/null
+++ b/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ExampleInstrumentedTest.kt
@@ -0,0 +1,22 @@
+package com.xyzbank.xyzbankapp
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.xyzbank.xyzbankapp", appContext.packageName)
+ }
+}
diff --git a/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ui/.DS_Store b/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ui/.DS_Store
new file mode 100644
index 000000000..dd91c52c0
Binary files /dev/null and b/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ui/.DS_Store differ
diff --git a/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ui/login/.DS_Store b/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ui/login/.DS_Store
new file mode 100644
index 000000000..5008ddfcf
Binary files /dev/null and b/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ui/login/.DS_Store differ
diff --git a/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ui/login/LoginActivityUITest.kt b/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ui/login/LoginActivityUITest.kt
new file mode 100644
index 000000000..31494f946
--- /dev/null
+++ b/XYZBank/app/src/androidTest/java/com/xyzbank/xyzbankapp/ui/login/LoginActivityUITest.kt
@@ -0,0 +1,78 @@
+package com.xyzbank.xyzbankapp.ui.login
+
+
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.action.ViewActions.*
+import androidx.test.espresso.assertion.ViewAssertions.matches
+import androidx.test.espresso.matcher.ViewMatchers.*
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.rule.ActivityTestRule
+import com.xyzbank.xyzbankapp.R
+import org.hamcrest.Matchers.allOf
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class LoginActivityUITest {
+
+ @Rule
+ @JvmField
+ var mActivityTestRule = ActivityTestRule(LoginActivity::class.java)
+
+ @Test
+ fun loginActivityUITest() {
+ val editText = onView(
+ allOf(
+ withId(R.id.username), withHint("User"),
+ withParent(
+ allOf(
+ withId(R.id.container),
+ withParent(withId(android.R.id.content))
+ )
+ ),
+ isDisplayed()
+ )
+ )
+
+ val editText2 = onView(
+ allOf(
+ withId(R.id.password),
+ withParent(
+ allOf(
+ withId(R.id.container),
+ withParent(withId(android.R.id.content))
+ )
+ ),
+ isDisplayed()
+ )
+ )
+
+ val button = onView(
+ allOf(
+ withId(R.id.login), withText("Login"),
+ withParent(
+ allOf(
+ withId(R.id.container),
+ withParent(withId(android.R.id.content))
+ )
+ ),
+ isDisplayed()
+ )
+ )
+ button.check(matches(isDisplayed()))
+
+// editText.perform(typeText("12345678901"), closeSoftKeyboard())
+// editText.check(matches(withText("12345678901")))
+// editText.perform(clearText(), closeSoftKeyboard())
+// editText.perform(typeText("test_user@msn.com"), closeSoftKeyboard())
+// editText.check(matches(withText("test_user@msn.com")))
+ editText2.perform(typeText("Test@1"), closeSoftKeyboard())
+ editText2.check(matches(withText("Test@1")))
+// editText.perform(clearText(), closeSoftKeyboard())
+ button.perform(click())
+
+ }
+}
diff --git a/XYZBank/app/src/main/AndroidManifest.xml b/XYZBank/app/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..f9e68480d
--- /dev/null
+++ b/XYZBank/app/src/main/AndroidManifest.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/.DS_Store b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/.DS_Store
new file mode 100644
index 000000000..5d47d2b3d
Binary files /dev/null and b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/.DS_Store differ
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/commons/BuilderHelper.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/commons/BuilderHelper.kt
new file mode 100644
index 000000000..bbaf16310
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/commons/BuilderHelper.kt
@@ -0,0 +1,42 @@
+package com.xyzbank.xyzbankapp.commons
+
+import android.content.Context
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities
+import android.os.Build
+
+class BuilderHelper() {
+ // getters and setters
+ val isNougat: Boolean
+ get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
+ //val isInternetConected: Boolean = CheckNetwork()
+
+
+ fun CheckNetwork(mContext: Context): Boolean {
+ var result = false
+ val cm = mContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
+ if (isNougat) {
+ cm?.run {
+ cm.getNetworkCapabilities(cm.activeNetwork)?.run {
+ result = when {
+ hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
+ hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
+ hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
+ else -> false
+ }
+ }
+ }
+ } else {
+ cm?.run {
+ cm.activeNetworkInfo?.run {
+ if (type == ConnectivityManager.TYPE_WIFI) {
+ result = true
+ } else if (type == ConnectivityManager.TYPE_MOBILE) {
+ result = true
+ }
+ }
+ }
+ }
+ return result
+ }
+}
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/commons/temp.html b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/commons/temp.html
new file mode 100644
index 000000000..72d9bcc95
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/commons/temp.html
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
XYZ Bank
+
+
User
+
Password
+
Login
+
Sign in
+
"Welcome !"
+
Not a valid username
+
Password must be >5 characters
+ \nAt last one capital letter
+ \nAt last one digit
+ \nAt last one symbol
+
"Login failed"
+
Welcome %s!\nGet read to your account
+
+
Hello blank fragment
+
Account
+
Balance
+
Recents
+
Your last successfully login: %s
+
Type your name and pasword to login
+
+
+
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/LoginDataSource.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/LoginDataSource.kt
new file mode 100644
index 000000000..59d067e32
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/LoginDataSource.kt
@@ -0,0 +1,24 @@
+package com.xyzbank.xyzbankapp.data
+
+import com.xyzbank.xyzbankapp.data.model.LoggedInUser
+import java.io.IOException
+
+/**
+ * Class that handles authentication w/ login credentials and retrieves user information.
+ */
+class LoginDataSource {
+
+ fun login(username: String, password: String): Result {
+ try {
+ // TODO: handle loggedInUser authentication
+ val fakeUser = LoggedInUser(java.util.UUID.randomUUID().toString(), "guest")
+ return Result.Success(fakeUser)
+ } catch (e: Throwable) {
+ return Result.Error(IOException("Error logging in", e))
+ }
+ }
+
+ fun logout() {
+ // TODO: revoke authentication
+ }
+}
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/LoginRepository.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/LoginRepository.kt
new file mode 100644
index 000000000..1f3a18922
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/LoginRepository.kt
@@ -0,0 +1,46 @@
+package com.xyzbank.xyzbankapp.data
+
+import com.xyzbank.xyzbankapp.data.model.LoggedInUser
+
+/**
+ * Class that requests authentication and user information from the remote data source and
+ * maintains an in-memory cache of login status and user credentials information.
+ */
+
+class LoginRepository(val dataSource: LoginDataSource) {
+
+ // in-memory cache of the loggedInUser object
+ var user: LoggedInUser? = null
+ private set
+
+ val isLoggedIn: Boolean
+ get() = user != null
+
+ init {
+ // If user credentials will be cached in local storage, it is recommended it be encrypted
+ // @see https://developer.android.com/training/articles/keystore
+ user = null
+ }
+
+ fun logout() {
+ user = null
+ dataSource.logout()
+ }
+
+ fun login(username: String, password: String): Result {
+ // handle login
+ val result = dataSource.login(username, password)
+
+ if (result is Result.Success) {
+ setLoggedInUser(result.data)
+ }
+
+ return result
+ }
+
+ private fun setLoggedInUser(loggedInUser: LoggedInUser) {
+ this.user = loggedInUser
+ // If user credentials will be cached in local storage, it is recommended it be encrypted
+ // @see https://developer.android.com/training/articles/keystore
+ }
+}
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/Result.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/Result.kt
new file mode 100644
index 000000000..57a294c37
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/Result.kt
@@ -0,0 +1,18 @@
+package com.xyzbank.xyzbankapp.data
+
+/**
+ * A generic class that holds a value with its loading status.
+ * @param
+ */
+sealed class Result {
+
+ data class Success(val data: T) : Result()
+ data class Error(val exception: Exception) : Result()
+
+ override fun toString(): String {
+ return when (this) {
+ is Success<*> -> "Success[data=$data]"
+ is Error -> "Error[exception=$exception]"
+ }
+ }
+}
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/AccountInfo.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/AccountInfo.kt
new file mode 100644
index 000000000..91f0ce9c0
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/AccountInfo.kt
@@ -0,0 +1,6 @@
+package com.xyzbank.xyzbankapp.data.model
+
+class AccountInfo(val title: String, val desc: String, val date: String, val value: Double) {
+
+}
+
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/JSONParser.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/JSONParser.kt
new file mode 100644
index 000000000..aac7076da
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/JSONParser.kt
@@ -0,0 +1,104 @@
+package com.xyzbank.xyzbankapp.data.model
+
+import com.xyzbank.bankapp.data.model.UserInfo
+import okhttp3.MediaType
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import okhttp3.RequestBody
+import org.json.JSONObject
+import java.io.IOException
+
+/*
+"statementList": [
+ {
+ "title": "Pagamento",
+ "desc": "Conta de luz",
+ "date": "2018-08-15",
+ "value": -50
+ }
+],
+"error": {}
+}
+*/
+
+/**
+ * object class that retrieve user information for logged in users from the API
+ */
+
+object JSONParser {
+ /**
+ * Function getUserAccount
+ *
+ * @param username: validated user name.
+ * @param password: a validated password.
+ * @return a filled user account class UserInfo from the above line
+ * {"userAccount":{"userId":1,"name":"xxx","bankAccount":"NNNN","agency":"NNNNNNNNN","balance":0.000},"error":{}}
+ */
+ @Throws(IOException::class)
+ fun getUserAccount(username: String, password: String): UserInfo {
+ val client = OkHttpClient().newBuilder()
+ .build()
+ val mediaType =
+ MediaType.parse("application/x-www-form-urlencoded")
+ //val body = RequestBody.create(mediaType, "user=test_user&password=Test@1")
+ val body = RequestBody.create(mediaType, "user=$username&password=$password")
+ val request = Request.Builder()
+ .url("https://bank-app-test.herokuapp.com/api/login")
+ .method("POST", body)
+ .addHeader("Content-Type", "application/x-www-form-urlencoded")
+ .build()
+ val response = client.newCall(request).execute()
+
+ // get JSONObject from JSON file
+ val obj = JSONObject(response.body()!!.string())
+ // fetch JSONObject named userAccount
+ val ru: JSONObject = obj.getJSONObject("userAccount")
+ return UserInfo(
+ ru.getInt("userId"),
+ ru.getString("name"),
+ ru.getString("bankAccount"),
+ ru.getString("agency"),
+ ru.getDouble("balance")
+ )
+ }
+
+ /**
+ * Function getAccountentries
+ *
+ * @param id: a real user id from the API.
+ * @return a filled list of each Account Entry, each one in a class: AccountEntries from the above line
+ * {"statementList":[{"title":"Pagamento","desc":"Conta de luz","date":"2018-08-15","value":-50, ...}],"error":{}}
+ */
+ @Throws(IOException::class)
+ fun getAccountEntries(id: String): ArrayList {
+ val client = OkHttpClient().newBuilder()
+ .build()
+ val request = Request.Builder()
+ .url("https://bank-app-test.herokuapp.com/api/statements/$id")
+ .method("GET", null)
+ .addHeader("Content-Type", "application/x-www-form-urlencoded")
+ .build()
+ val response = client.newCall(request).execute()
+
+ // get JSONObject from JSON file
+ val obj = JSONObject(response.body()!!.string())
+ // fetch JSONObject into a array of accounts entries
+ val jsonRoot = obj.getJSONArray("statementList")
+
+ val result: ArrayList = ArrayList()
+ for (i in 0 until jsonRoot.length()) {
+ val accountData = jsonRoot.getJSONObject(i)
+ var aci = AccountInfo("",",","",0.00)
+ for (j in 0 until accountData.length()) {
+ aci = AccountInfo(
+ accountData.getString("title"),
+ accountData.getString("desc"),
+ accountData.getString("date"),
+ accountData.getDouble("value")
+ )
+ }
+ result.add(aci)
+ }
+ return result
+ }
+}
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/LoggedInUser.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/LoggedInUser.kt
new file mode 100644
index 000000000..734be77f8
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/LoggedInUser.kt
@@ -0,0 +1,9 @@
+package com.xyzbank.xyzbankapp.data.model
+
+/**
+ * Data class that captures user information for logged in users retrieved from LoginRepository
+ */
+data class LoggedInUser(
+ val userId: String,
+ val displayName: String
+)
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/UserInfo.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/UserInfo.kt
new file mode 100644
index 000000000..01b6e41a0
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/data/model/UserInfo.kt
@@ -0,0 +1,10 @@
+package com.xyzbank.bankapp.data.model
+
+class UserInfo(
+ val userid: Int,
+ val name: String,
+ val bankaccount: String,
+ val agency: String,
+ val balance: Double) {
+
+}
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/.DS_Store b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/.DS_Store
new file mode 100644
index 000000000..d3860d201
Binary files /dev/null and b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/.DS_Store differ
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/SplashScreen.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/SplashScreen.kt
new file mode 100755
index 000000000..5f1422296
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/SplashScreen.kt
@@ -0,0 +1,109 @@
+package com.xyzbank.xyzbankapp.ui
+
+import android.content.Intent
+import android.os.AsyncTask
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.util.Log
+import android.widget.ImageView
+import androidx.appcompat.app.AppCompatActivity
+import com.xyzbank.xyzbankapp.R
+import com.xyzbank.xyzbankapp.ui.login.LoginActivity
+import java.util.*
+
+
+class SplashScreen : AppCompatActivity() {
+
+ private var animatedImgView: ImageView? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.splash_screen)
+
+ val lang = Locale.getDefault().language
+ animatedImgView = findViewById(R.id.logo)
+
+
+ splashScreenUseAsyncTask(lang)
+ }
+
+ // Show splash screen until network load data complete.
+ private fun splashScreenUseAsyncTask(lang: String) {
+ // Create a AsyncTask object.
+ val retrieveDateTask = RetrieveDateTask()
+ retrieveDateTask.execute(lang, "", "")
+ // Create a count down timer object.It will count down every 0.1 seconds and last for milliSeconds milliseconds..
+ var t = 0
+ var um = 0
+ val countDownTimer: CountDownTimer = object : CountDownTimer(9000, 100) {
+ override fun onTick(l: Long) {
+ if (um > 1)
+ when (t) {
+ in 0..48 -> animatedImgView!!.setImageResource(R.drawable.ic_menino_h)
+ in 48..62 -> animatedImgView!!.setImageResource(R.drawable.ic_menino_g)
+ in 62..64 -> animatedImgView!!.setImageResource(R.drawable.ic_menino_f)
+ in 64..66 -> animatedImgView!!.setImageResource(R.drawable.ic_menino_e)
+ in 66..68 -> animatedImgView!!.setImageResource(R.drawable.ic_menino_d)
+ in 68..70 -> animatedImgView!!.setImageResource(R.drawable.ic_menino_c)
+ in 70..72 -> animatedImgView!!.setImageResource(R.drawable.ic_menino_b)
+ in 72..89 -> animatedImgView!!.setImageResource(R.drawable.ic_menino_a)
+ }
+ t = (l / 100).toInt()
+ um++
+ }
+
+
+ override fun onFinish() {
+ if (!retrieveDateTask.isAsyncTaskComplete) {
+ start()
+ } else {
+ for (i in 0..50) {
+ animatedImgView!!.setImageResource(R.drawable.ic_menino_g)
+ animatedImgView!!.setImageResource(R.drawable.ic_menino_g)
+ animatedImgView!!.setImageResource(R.drawable.ic_menino_g)
+ animatedImgView!!.setImageResource(R.drawable.ic_menino_h)
+ animatedImgView!!.setImageResource(R.drawable.ic_menino_g)
+ animatedImgView!!.setImageResource(R.drawable.ic_menino_h)
+ }
+ val intent = Intent(this@SplashScreen, LoginActivity::class.java)
+ startActivity(intent)
+ finish()
+ }
+ }
+ }
+ // Start the count down timer.
+ countDownTimer.start()
+ }
+
+ // This is the async task class that get data from network.
+ private class RetrieveDateTask :
+ AsyncTask() {
+ // Indicate whether AsyncTask complete or not.
+ var isAsyncTaskComplete = false
+ private set
+
+ // This method will be called before AsyncTask run.
+ override fun onPreExecute() {
+ isAsyncTaskComplete = false
+ }
+
+ // This method will be called when AsyncTask run.
+ override fun doInBackground(vararg params: String?): String? {
+ val result: String?
+ try {
+ val lang = params[0]!!.substring(0, 2)
+ Log.d("temp", lang)
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ } finally {
+ result = null
+ }
+ return result
+ }
+
+ // This method will be called after AsyncTask run.
+ override fun onPostExecute(s: String?) {
+ isAsyncTaskComplete = true
+ }
+ }
+}
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/account/AccountActivity.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/account/AccountActivity.kt
new file mode 100644
index 000000000..1e357fd89
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/account/AccountActivity.kt
@@ -0,0 +1,139 @@
+package com.xyzbank.xyzbankapp.ui.account
+
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.os.AsyncTask
+import android.os.Bundle
+import android.util.Log
+import android.widget.ListView
+import android.widget.TextView
+import androidx.appcompat.app.AppCompatActivity
+import com.xyzbank.bankapp.data.model.UserInfo
+import com.xyzbank.xyzbankapp.R
+import com.xyzbank.xyzbankapp.commons.BuilderHelper
+import com.xyzbank.xyzbankapp.data.model.AccountInfo
+import com.xyzbank.xyzbankapp.data.model.JSONParser
+import java.text.DecimalFormat
+import java.text.SimpleDateFormat
+import java.util.*
+
+
+private const val PARAM_ID = "id"
+private const val PARAM_NAME = "name"
+private const val PARAM_ACCOUNT = "account"
+private const val PARAM_AGENCY = "agency"
+private const val PARAM_BALANCE = "balance"
+
+class AccountActivity : AppCompatActivity() {
+ private lateinit var currency: Currency
+ private lateinit var locale: Locale
+ private var mListView: ListView? = null
+ private lateinit var mAdapter: AcountEntriesAdapter
+ private lateinit var decFormat: DecimalFormat
+ private lateinit var dateFormat:SimpleDateFormat
+ // TODO: Rename and change types of parameters
+ private var userId: String? = null
+ private var name: String? = null
+ private var bankAccount: String? = null
+ private var agency: String? = null
+ private var balance: Double = 0.00
+
+
+ @SuppressLint("SetTextI18n")
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_account)
+ val extras = intent.extras
+ if (extras != null) {
+
+ userId = extras.getString(PARAM_ID)
+ name = extras.getString(PARAM_NAME)
+ bankAccount = extras.getString(PARAM_ACCOUNT)
+ agency = extras.getString(PARAM_AGENCY)
+ balance = extras.getDouble(PARAM_BALANCE)
+ }
+
+ locale = Locale.getDefault()
+
+ dateFormat = SimpleDateFormat("yyyy-MM-dd", locale)
+ currency = Currency.getInstance(locale)
+ mAdapter = AcountEntriesAdapter(this, locale, currency)
+
+ findViewById(R.id.tv_username).text = name
+ val al = agency!!.length
+ val fmtagency =
+ agency!!.substring(0,2)+"."+
+ agency!!.substring(2,al-1) + "-" +
+ agency!!.substring(al-1,al)
+ findViewById(R.id.tv_bankaccount).text = "$bankAccount / $fmtagency"
+ val bal = Formatter(locale).format("%.2f", balance)
+ findViewById(R.id.tv_balance).text = "${currency.getSymbol()} ${bal}"
+ mListView = findViewById(R.id.list_entries)
+ if (BuilderHelper().CheckNetwork(this))
+ LoadAccountEntries().execute(userId)
+ }
+
+ override fun onBackPressed() {
+ setResult(Activity.RESULT_OK)
+ finish()
+ return
+ }
+
+ /**
+ * Use this inner calss to send GET request to the API
+ * this fragment using the provided parameters.
+ * this does not retun any object, just wait for API result and
+ * create the GUI
+ */
+ inner class LoadAccountEntries : AsyncTask() {
+
+ private lateinit var userid: String
+
+ override fun onPreExecute() {
+ Log.d("temp", "temp")
+ }
+
+ override fun doInBackground(vararg voids: String?): Any {
+ userid = voids[0]!!
+ // get the user account
+ return JSONParser.getAccountEntries(userid)
+ }
+
+ override fun onPostExecute(results: Any?) {
+ if (results != null) {
+ // See Response in Logcat for understand JSON Results and make DeveloperList
+ var acl = results as ArrayList
+ for (c in acl) {
+ mAdapter.add(c)
+ }
+ mListView!!.adapter = mAdapter
+ }
+ }
+ } // end of inner class
+
+ companion object {
+ /**
+ * Use this factory method to create a new instance of
+ * this activity using the provided parameters.
+ *
+ * @param context: the login activity.
+ * @param userinfo: the user info for this account entries.
+ */
+ // DONE: Rename and change types and number of parameters
+ @JvmStatic
+ fun newInstance(context: Context, userinfo: UserInfo): Intent {
+ val detailIntent = Intent(context, AccountActivity::class.java)
+ var arguments = Bundle().apply {
+ putString(PARAM_ID, userinfo.userid.toString())
+ putString(PARAM_NAME, userinfo.name)
+ putString(PARAM_ACCOUNT, userinfo.bankaccount)
+ putString(PARAM_AGENCY, userinfo.agency)
+ putDouble(PARAM_BALANCE, userinfo.balance)
+ }
+ detailIntent.putExtras(arguments)
+ return detailIntent
+ }
+ }
+}
\ No newline at end of file
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/account/AcountEntriesAdapter.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/account/AcountEntriesAdapter.kt
new file mode 100644
index 000000000..c7fd49187
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/account/AcountEntriesAdapter.kt
@@ -0,0 +1,68 @@
+package com.xyzbank.xyzbankapp.ui.account
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.Color
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseAdapter
+import android.widget.TextView
+import androidx.cardview.widget.CardView
+import com.xyzbank.xyzbankapp.R
+import com.xyzbank.xyzbankapp.data.model.AccountInfo
+import java.util.*
+import kotlin.collections.ArrayList
+
+class AcountEntriesAdapter(val context: Context, val locale: Locale, val currency: Currency) : BaseAdapter() {
+ private val mItems = ArrayList()
+ private val inflater: LayoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
+ private var itemLayout: CardView? = null
+
+ //private var DB: AnotationsDBHelper = AnotationsDBHelper(context)
+
+ fun add(item: AccountInfo) {
+ mItems.add(item)
+ notifyDataSetChanged()
+ }
+
+ fun clear() {
+ mItems.clear()
+ notifyDataSetChanged()
+ }
+
+ override fun getItem(position: Int): Any {
+ return mItems[position]
+ }
+
+ override fun getItemId(position: Int): Long {
+ return position.toLong()
+ }
+
+ override fun getCount(): Int {
+ return mItems.size
+ }
+
+ @SuppressLint("ViewHolder", "SetTextI18n")
+ @Suppress("DEPRECATION")
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
+ val item = getItem(position) as AccountInfo
+
+ context.resources.displayMetrics
+
+ val root: ViewGroup? = null
+ itemLayout = inflater.inflate(R.layout.account_view, root) as CardView
+
+ itemLayout!!.findViewById(R.id.tv_title).text = item.title
+ itemLayout!!.findViewById(R.id.tv_date).text = item.date
+ itemLayout!!.findViewById(R.id.tv_desc).text = item.desc
+ val tvValue = itemLayout!!.findViewById(R.id.tv_value)
+ val bal = Formatter(locale).format("%.2f", item.value)
+ if (item.value < 0.00)
+ tvValue.setTextColor(Color.parseColor("#A5A5A5"))
+ tvValue.text = "${currency.symbol} $bal"
+
+
+ return itemLayout as CardView
+ }
+}
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoggedInUserView.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoggedInUserView.kt
new file mode 100644
index 000000000..96763555d
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoggedInUserView.kt
@@ -0,0 +1,10 @@
+package com.xyzbank.xyzbankapp.ui.login
+
+import com.xyzbank.bankapp.data.model.UserInfo
+
+/**
+ * User details post authentication that is exposed to the UI
+ */
+data class LoggedInUserView(
+ val accountInfo: UserInfo
+)
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginActivity.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginActivity.kt
new file mode 100644
index 000000000..b0baba7a5
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginActivity.kt
@@ -0,0 +1,193 @@
+package com.xyzbank.xyzbankapp.ui.login
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
+import android.view.View
+import android.view.inputmethod.EditorInfo
+import android.widget.*
+import androidx.annotation.StringRes
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProvider
+import com.xyzbank.xyzbankapp.R
+import com.xyzbank.xyzbankapp.commons.BuilderHelper
+import com.xyzbank.xyzbankapp.ui.account.AccountActivity
+import java.text.SimpleDateFormat
+import java.util.*
+
+
+class LoginActivity : AppCompatActivity() {
+
+ private lateinit var dateFormat: SimpleDateFormat
+ private lateinit var welcome: String
+ private val SUCCESSLOGGEDDATE: String = "successfully_login_date"
+ private val SUCCESSFULLYLOGGEDIN: String = "successfully_logged_in"
+ private var prefs: SharedPreferences? = null
+ private val ACCACT_REQUEST_CODE: Int = 1000
+ private var login: Button? = null
+ private var password: EditText? = null
+ private var username: EditText? = null
+ private var tv_message: TextView? = null
+ private lateinit var myAccount: LoggedInUserView
+ private lateinit var loginViewModel: LoginViewModel
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_login)
+
+ prefs = getSharedPreferences("${packageName}.user_settings", Context.MODE_PRIVATE)
+
+ dateFormat = SimpleDateFormat(getString(R.string.date_format_text), Locale.getDefault())
+
+ username = findViewById(R.id.username)
+ val lu = prefs!!.getString(SUCCESSFULLYLOGGEDIN, "")
+ password = findViewById(R.id.password)
+ if (lu != "") {
+ username!!.setText(lu)
+ username!!.setSelection(lu!!.length)
+ username!!.nextFocusDownId = R.id.password
+ password!!.requestFocus()
+ username!!.isEnabled = false
+ }
+ login = findViewById(R.id.login)
+ val loading = findViewById(R.id.loading)
+
+ loginViewModel = ViewModelProvider(this, LoginViewModelFactory())
+ .get(LoginViewModel::class.java)
+
+ loginViewModel.loginFormState.observe(this@LoginActivity, Observer {
+ val loginState = it ?: return@Observer
+
+ // disable login button unless both username / password is valid
+ login!!.isEnabled = loginState.isDataValid
+
+ if (loginState.usernameError != null) {
+ username!!.error = getString(loginState.usernameError)
+ }
+ if (loginState.passwordError != null) {
+ password!!.error = getString(loginState.passwordError)
+ }
+ })
+
+ loginViewModel.loginResult.observe(this@LoginActivity, Observer {
+ val loginResult = it ?: return@Observer
+
+ loading.visibility = View.GONE
+ if (loginResult.error != null) {
+ showLoginFailed(loginResult.error)
+ }
+ if (loginResult.success != null) {
+ updateUiWithUser(loginResult.success)
+ }
+
+ if (savedInstanceState == null) {
+ val accinf = AccountActivity.newInstance(this, myAccount.accountInfo)
+ startActivityForResult(accinf, ACCACT_REQUEST_CODE)
+ }
+ })
+
+ tv_message = findViewById(R.id.user_message)
+ welcome = getString(R.string.user_welcome_msg)
+ tv_message!!.text = getString(R.string.empty_user_msg)
+
+ username!!.afterTextChanged {
+ loginViewModel.loginDataChanged(
+ username!!.text.toString(),
+ password!!.text.toString()
+ )
+ }
+
+ password?.apply {
+ afterTextChanged {
+ loginViewModel.loginDataChanged(
+ username!!.text.toString(),
+ password!!.text.toString()
+ )
+ }
+
+ setOnEditorActionListener { _, actionId, _ ->
+ when (actionId) {
+ EditorInfo.IME_ACTION_DONE -> {
+ if (loginViewModel.verifyUser(username!!.text.toString(), password!!.text.toString())) {
+ password!!.requestFocus()
+ password!!.setSelection(password!!.text.toString().length)
+ tv_message!!.text = welcome.format(username!!.text.toString())
+ }
+ }
+ }
+ false
+ }
+
+ login!!.setOnClickListener {
+ loading.visibility = View.VISIBLE
+ doLogin(username!!.text.toString(), password!!.text.toString())
+ }
+ }
+ }
+
+ private fun doLogin(username: String, password: String) {
+ // verify if user name passed is email or number
+ val nm = if (username.contains("@"))
+ username.split("@")[0]
+ else
+ username
+ if (BuilderHelper().CheckNetwork(this@LoginActivity))
+ loginViewModel.login(nm, password)
+ }
+
+ private fun updateUiWithUser(model: LoggedInUserView) {
+ myAccount = model
+ tv_message!!.text = welcome.format(model.accountInfo.name)
+
+ val editor = prefs!!.edit()
+ editor.putString(SUCCESSFULLYLOGGEDIN, username!!.text.toString())
+ val c = Calendar.getInstance()
+ val date = c.time
+ editor.putString(SUCCESSLOGGEDDATE, dateFormat.format(date))
+ editor.apply()
+
+ username!!.isEnabled = false
+ password!!.isEnabled = false
+ login!!.isEnabled = false
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (requestCode == ACCACT_REQUEST_CODE) {
+ if (resultCode == Activity.RESULT_OK) {
+ username!!.isEnabled = true
+ username!!.setText(prefs!!.getString(SUCCESSFULLYLOGGEDIN, ""))
+ password!!.isEnabled = true
+ password!!.setText("")
+ password!!.requestFocus()
+ password!!.hasFocus()
+ tv_message!!.text = getString(R.string.last_successfully_login_msg).format(prefs!!.getString(SUCCESSLOGGEDDATE, ""))
+ login!!.isEnabled = false
+ }
+ }
+ }
+
+ private fun showLoginFailed(@StringRes errorString: Int) {
+ Toast.makeText(applicationContext, errorString, Toast.LENGTH_SHORT).show()
+ }
+}
+
+/**
+ * Extension function to simplify setting an afterTextChanged action to EditText components.
+ */
+fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
+ this.addTextChangedListener(object : TextWatcher {
+ override fun afterTextChanged(editable: Editable?) {
+ afterTextChanged.invoke(editable.toString())
+ }
+
+ override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
+
+ override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
+ })
+}
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginFormState.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginFormState.kt
new file mode 100644
index 000000000..0dd2f9736
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginFormState.kt
@@ -0,0 +1,8 @@
+package com.xyzbank.xyzbankapp.ui.login
+
+/**
+ * Data validation state of the login form.
+ */
+data class LoginFormState(val usernameError: Int? = null,
+ val passwordError: Int? = null,
+ val isDataValid: Boolean = false)
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginResult.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginResult.kt
new file mode 100644
index 000000000..93303e9a6
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginResult.kt
@@ -0,0 +1,9 @@
+package com.xyzbank.xyzbankapp.ui.login
+
+/**
+ * Authentication result : success (user details) or error message.
+ */
+data class LoginResult(
+ val success: LoggedInUserView? = null,
+ val error: Int? = null
+)
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginViewModel.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginViewModel.kt
new file mode 100644
index 000000000..5716fcb64
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginViewModel.kt
@@ -0,0 +1,162 @@
+package com.xyzbank.xyzbankapp.ui.login
+
+import android.os.AsyncTask
+import android.util.Log
+import android.util.Patterns
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.xyzbank.bankapp.data.model.UserInfo
+import com.xyzbank.xyzbankapp.R
+import com.xyzbank.xyzbankapp.data.LoginRepository
+import com.xyzbank.xyzbankapp.data.Result
+import com.xyzbank.xyzbankapp.data.model.JSONParser
+import java.util.regex.Matcher
+import java.util.regex.Pattern
+
+class LoginViewModel(private val loginRepository: LoginRepository) : ViewModel() {
+
+ private lateinit var myAccount: UserInfo
+ private val _loginForm = MutableLiveData()
+ val loginFormState: LiveData = _loginForm
+
+ private val _loginResult = MutableLiveData()
+ val loginResult: LiveData = _loginResult
+
+ enum class TypeOfTextInName {EMAIL, CPF}
+ private lateinit var typeName: TypeOfTextInName
+
+ fun verifyUser(username: String, password: String): Boolean {
+ // First - validate user from UI
+ val result = loginRepository.login(username, password)
+
+ if (result is Result.Error) {
+ _loginResult.value = LoginResult(error = R.string.login_failed)
+ return false
+ }
+ return true
+ }
+
+ fun login(username: String, password: String) {
+ // First - validate user from UI
+ val result = loginRepository.login(username, password)
+
+ if (result is Result.Success) {
+ // load user account
+ LoadUserAccount().execute("$username|$password")
+ } else {
+ _loginResult.value = LoginResult(error = R.string.login_failed)
+ }
+ }
+
+
+ /**
+ * Request data from the api using a thread.
+ *
+ * @param [String]: the user name and password.
+ * return true or false.
+ */
+ inner class LoadUserAccount : AsyncTask() {
+
+ private lateinit var password: String
+ private lateinit var username: String
+
+ override fun onPreExecute() {
+ Log.d("temp", "temp")
+ }
+
+ override fun doInBackground(vararg voids: String?): Any {
+ username = voids[0]!!.split("|")[0]
+ password = voids[0]!!.split("|")[1]
+ // get the user account
+ return JSONParser.getUserAccount(username, password)
+ }
+
+ override fun onPostExecute(results: Any?) {
+ if (results != null) {
+ // See Response in Logcat for understand JSON Results and make DeveloperList
+ Log.i("onPostExecute: ", (results as UserInfo).userid.toString())
+ myAccount = results
+ _loginResult.value = LoginResult(success = LoggedInUserView(accountInfo = myAccount))
+
+ }
+ }
+ } // end of inner class
+
+ fun loginDataChanged(username: String, password: String) {
+ if (!isUserNameValid(username)) {
+ _loginForm.value = LoginFormState(usernameError = R.string.invalid_username)
+ } else if (!isPasswordValid(password)) {
+ _loginForm.value = LoginFormState(passwordError = R.string.invalid_password)
+ } else {
+ _loginForm.value = LoginFormState(isDataValid = true)
+ }
+ }
+
+ // A placeholder username validation check
+ /**
+ * Verify the text typed in the name field is cpf or email based.
+ *
+ * @param text: the text typed in the name field.
+ * return true or false.
+ */
+ private fun isUserNameValid(text: String): Boolean {
+ var result = false
+ if (text.contains('@')) {
+ typeName = TypeOfTextInName.EMAIL
+ result = Patterns.EMAIL_ADDRESS.matcher(text).matches()
+ } else {
+ if (verifyCharInName(text)){
+ result = true
+ typeName = TypeOfTextInName.CPF
+ }
+ }
+ return result
+ }
+
+ /**
+ * Verify the text typed in the name field is digit based.
+ *
+ * @param text: the text typed in the name field.
+ * return true or false.
+ */
+ private fun verifyCharInName(text: String): Boolean {
+ val pDig = Pattern.compile("(.*\\d.*)")
+ val mdg: Matcher = pDig.matcher(text)
+ return (mdg.matches())
+ }
+
+ // A placeholder password validation check
+ /**
+ * Verify the text typed in the password field have
+ * - at last a capital letter
+ * - at last one digit
+ * - at lest one symbol
+ *
+ * @param text: the text typed in the password field.
+ * return true or false.
+ */
+ private fun isPasswordValid(password: String): Boolean {
+ val r = password.length > 5 && verifyCharInPassword(password)
+ return r
+ }
+
+ /**
+ * Verify password typed util.
+ *
+ * @param text: the text typed in the password field.
+ * return true or false.
+ */
+ private fun verifyCharInPassword(text: String): Boolean {
+ val pLow = Pattern.compile("(.*[a-z].*)")
+ val pUpp = Pattern.compile("(.*[A-Z].*)")
+ val pDig = Pattern.compile("(.*\\d.*)")
+ val pSym = Pattern.compile("(.*[:?!@#$%^&*()].*)")
+ val mlc: Matcher = pLow.matcher(text)
+ val muc: Matcher = pUpp.matcher(text)
+ val mdg: Matcher = pDig.matcher(text)
+ val msb: Matcher = pSym.matcher(text)
+
+ return mlc.matches() && muc.matches() && mdg.matches() && msb.matches()
+ }
+}
diff --git a/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginViewModelFactory.kt b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginViewModelFactory.kt
new file mode 100644
index 000000000..b27c49278
--- /dev/null
+++ b/XYZBank/app/src/main/java/com/xyzbank/xyzbankapp/ui/login/LoginViewModelFactory.kt
@@ -0,0 +1,25 @@
+package com.xyzbank.xyzbankapp.ui.login
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.xyzbank.xyzbankapp.data.LoginDataSource
+import com.xyzbank.xyzbankapp.data.LoginRepository
+
+/**
+ * ViewModel provider factory to instantiate LoginViewModel.
+ * Required given LoginViewModel has a non-empty constructor
+ */
+class LoginViewModelFactory : ViewModelProvider.Factory {
+
+ @Suppress("UNCHECKED_CAST")
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(LoginViewModel::class.java)) {
+ return LoginViewModel(
+ loginRepository = LoginRepository(
+ dataSource = LoginDataSource()
+ )
+ ) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
diff --git a/XYZBank/app/src/main/res/.DS_Store b/XYZBank/app/src/main/res/.DS_Store
new file mode 100644
index 000000000..46883b49e
Binary files /dev/null and b/XYZBank/app/src/main/res/.DS_Store differ
diff --git a/XYZBank/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/XYZBank/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 000000000..2b068d114
--- /dev/null
+++ b/XYZBank/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/drawable/.DS_Store b/XYZBank/app/src/main/res/drawable/.DS_Store
new file mode 100644
index 000000000..5008ddfcf
Binary files /dev/null and b/XYZBank/app/src/main/res/drawable/.DS_Store differ
diff --git a/XYZBank/app/src/main/res/drawable/cardview_background.xml b/XYZBank/app/src/main/res/drawable/cardview_background.xml
new file mode 100644
index 000000000..23405e73f
--- /dev/null
+++ b/XYZBank/app/src/main/res/drawable/cardview_background.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/drawable/ic_baseline_input_24.xml b/XYZBank/app/src/main/res/drawable/ic_baseline_input_24.xml
new file mode 100644
index 000000000..c0ce45c62
--- /dev/null
+++ b/XYZBank/app/src/main/res/drawable/ic_baseline_input_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/XYZBank/app/src/main/res/drawable/ic_launcher_background.xml b/XYZBank/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 000000000..07d5da9cb
--- /dev/null
+++ b/XYZBank/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/XYZBank/app/src/main/res/drawable/ic_menino.png b/XYZBank/app/src/main/res/drawable/ic_menino.png
new file mode 100755
index 000000000..b9b9646e8
Binary files /dev/null and b/XYZBank/app/src/main/res/drawable/ic_menino.png differ
diff --git a/XYZBank/app/src/main/res/drawable/ic_menino_a.png b/XYZBank/app/src/main/res/drawable/ic_menino_a.png
new file mode 100755
index 000000000..5cf7bf5d3
Binary files /dev/null and b/XYZBank/app/src/main/res/drawable/ic_menino_a.png differ
diff --git a/XYZBank/app/src/main/res/drawable/ic_menino_b.png b/XYZBank/app/src/main/res/drawable/ic_menino_b.png
new file mode 100755
index 000000000..1df51986f
Binary files /dev/null and b/XYZBank/app/src/main/res/drawable/ic_menino_b.png differ
diff --git a/XYZBank/app/src/main/res/drawable/ic_menino_c.png b/XYZBank/app/src/main/res/drawable/ic_menino_c.png
new file mode 100755
index 000000000..a64bbadad
Binary files /dev/null and b/XYZBank/app/src/main/res/drawable/ic_menino_c.png differ
diff --git a/XYZBank/app/src/main/res/drawable/ic_menino_d.png b/XYZBank/app/src/main/res/drawable/ic_menino_d.png
new file mode 100755
index 000000000..7050d1b45
Binary files /dev/null and b/XYZBank/app/src/main/res/drawable/ic_menino_d.png differ
diff --git a/XYZBank/app/src/main/res/drawable/ic_menino_e.png b/XYZBank/app/src/main/res/drawable/ic_menino_e.png
new file mode 100755
index 000000000..5930ad846
Binary files /dev/null and b/XYZBank/app/src/main/res/drawable/ic_menino_e.png differ
diff --git a/XYZBank/app/src/main/res/drawable/ic_menino_f.png b/XYZBank/app/src/main/res/drawable/ic_menino_f.png
new file mode 100755
index 000000000..d6b5c910d
Binary files /dev/null and b/XYZBank/app/src/main/res/drawable/ic_menino_f.png differ
diff --git a/XYZBank/app/src/main/res/drawable/ic_menino_g.png b/XYZBank/app/src/main/res/drawable/ic_menino_g.png
new file mode 100755
index 000000000..36daa824d
Binary files /dev/null and b/XYZBank/app/src/main/res/drawable/ic_menino_g.png differ
diff --git a/XYZBank/app/src/main/res/drawable/ic_menino_h.png b/XYZBank/app/src/main/res/drawable/ic_menino_h.png
new file mode 100755
index 000000000..b943c46c9
Binary files /dev/null and b/XYZBank/app/src/main/res/drawable/ic_menino_h.png differ
diff --git a/XYZBank/app/src/main/res/drawable/view_background.xml b/XYZBank/app/src/main/res/drawable/view_background.xml
new file mode 100644
index 000000000..d0f187693
--- /dev/null
+++ b/XYZBank/app/src/main/res/drawable/view_background.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/layout/account_view.xml b/XYZBank/app/src/main/res/layout/account_view.xml
new file mode 100644
index 000000000..bc2aef959
--- /dev/null
+++ b/XYZBank/app/src/main/res/layout/account_view.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/layout/activity_account.xml b/XYZBank/app/src/main/res/layout/activity_account.xml
new file mode 100644
index 000000000..aacb83dc6
--- /dev/null
+++ b/XYZBank/app/src/main/res/layout/activity_account.xml
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/layout/activity_login.xml b/XYZBank/app/src/main/res/layout/activity_login.xml
new file mode 100644
index 000000000..1349aeb79
--- /dev/null
+++ b/XYZBank/app/src/main/res/layout/activity_login.xml
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/layout/splash_screen.xml b/XYZBank/app/src/main/res/layout/splash_screen.xml
new file mode 100755
index 000000000..5d1b30ec1
--- /dev/null
+++ b/XYZBank/app/src/main/res/layout/splash_screen.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/XYZBank/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 000000000..eca70cfe5
--- /dev/null
+++ b/XYZBank/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/XYZBank/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 000000000..eca70cfe5
--- /dev/null
+++ b/XYZBank/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/mipmap-hdpi/ic_launcher.png b/XYZBank/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..a571e6009
Binary files /dev/null and b/XYZBank/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/XYZBank/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/XYZBank/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 000000000..61da551c5
Binary files /dev/null and b/XYZBank/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/XYZBank/app/src/main/res/mipmap-mdpi/ic_launcher.png b/XYZBank/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..c41dd2853
Binary files /dev/null and b/XYZBank/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/XYZBank/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/XYZBank/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 000000000..db5080a75
Binary files /dev/null and b/XYZBank/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/XYZBank/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/XYZBank/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..6dba46dab
Binary files /dev/null and b/XYZBank/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/XYZBank/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/XYZBank/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 000000000..da31a871c
Binary files /dev/null and b/XYZBank/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/XYZBank/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/XYZBank/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..15ac68172
Binary files /dev/null and b/XYZBank/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/XYZBank/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/XYZBank/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 000000000..b216f2d31
Binary files /dev/null and b/XYZBank/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/XYZBank/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/XYZBank/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000..f25a41974
Binary files /dev/null and b/XYZBank/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/XYZBank/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/XYZBank/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 000000000..e96783ccc
Binary files /dev/null and b/XYZBank/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/XYZBank/app/src/main/res/values-night/themes.xml b/XYZBank/app/src/main/res/values-night/themes.xml
new file mode 100644
index 000000000..36aa6bd33
--- /dev/null
+++ b/XYZBank/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/values-pt-rBR/strings.xml b/XYZBank/app/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 000000000..741751223
--- /dev/null
+++ b/XYZBank/app/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,21 @@
+
+
+ Banco XYZ
+
+ Usuário
+ Senha
+ Logar
+ "Bem-vindo !"
+ Assinar em
+ Não é um nome de usuário válido
+ A senha deve ser > que 5 caracteres\nAo menos uma letra maiúscula\nPelo menos um dígito\nPelo menos um símbolo
+ "Falha na Autenticação"
+ Bem-vindo, %s!\nAcesse sua conta
+
+ Conta
+ Saldo
+ Recentes
+ Seu último login com sucesso: %s
+ Digite seu nome e senha para fazer o login
+ dd/MM/yyyy
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/values/colors.xml b/XYZBank/app/src/main/res/values/colors.xml
new file mode 100644
index 000000000..f8c6127d3
--- /dev/null
+++ b/XYZBank/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/values/dimens.xml b/XYZBank/app/src/main/res/values/dimens.xml
new file mode 100644
index 000000000..e00c2dd14
--- /dev/null
+++ b/XYZBank/app/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/values/strings.xml b/XYZBank/app/src/main/res/values/strings.xml
new file mode 100644
index 000000000..595f44b6d
--- /dev/null
+++ b/XYZBank/app/src/main/res/values/strings.xml
@@ -0,0 +1,23 @@
+
+ XYZ Bank
+
+ User
+ Password
+ Login
+ Sign in
+ "Welcome !"
+ Not a valid username
+ Password must be >5 characters
+ \nAt last one capital letter
+ \nAt last one digit
+ \nAt last one symbol
+ "Login failed"
+ Welcome %s!\nGet read to your account
+
+ Account
+ Balance
+ Recents
+ Your last successfully login: %s
+ Type your name and pasword to login
+ yyyy-MM-dd
+
\ No newline at end of file
diff --git a/XYZBank/app/src/main/res/values/themes.xml b/XYZBank/app/src/main/res/values/themes.xml
new file mode 100644
index 000000000..9038aa94a
--- /dev/null
+++ b/XYZBank/app/src/main/res/values/themes.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/XYZBank/app/src/test/java/com/xyzbank/xyzbankapp/ExampleUnitTest.kt b/XYZBank/app/src/test/java/com/xyzbank/xyzbankapp/ExampleUnitTest.kt
new file mode 100644
index 000000000..86b0a441b
--- /dev/null
+++ b/XYZBank/app/src/test/java/com/xyzbank/xyzbankapp/ExampleUnitTest.kt
@@ -0,0 +1,16 @@
+package com.xyzbank.xyzbankapp
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
diff --git a/XYZBank/build.gradle b/XYZBank/build.gradle
new file mode 100644
index 000000000..718f5499c
--- /dev/null
+++ b/XYZBank/build.gradle
@@ -0,0 +1,26 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ ext.kotlin_version = "1.3.72"
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath "com.android.tools.build:gradle:4.2.0-alpha07"
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/XYZBank/gradle.properties b/XYZBank/gradle.properties
new file mode 100644
index 000000000..98bed167d
--- /dev/null
+++ b/XYZBank/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
\ No newline at end of file
diff --git a/XYZBank/gradle/wrapper/gradle-wrapper.jar b/XYZBank/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..f6b961fd5
Binary files /dev/null and b/XYZBank/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/XYZBank/gradle/wrapper/gradle-wrapper.properties b/XYZBank/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..13bf29d97
--- /dev/null
+++ b/XYZBank/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Aug 06 10:30:18 BRT 2020
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
diff --git a/XYZBank/gradlew b/XYZBank/gradlew
new file mode 100755
index 000000000..cccdd3d51
--- /dev/null
+++ b/XYZBank/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/XYZBank/gradlew.bat b/XYZBank/gradlew.bat
new file mode 100644
index 000000000..f9553162f
--- /dev/null
+++ b/XYZBank/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/XYZBank/local.properties b/XYZBank/local.properties
new file mode 100644
index 000000000..33d9e0d65
--- /dev/null
+++ b/XYZBank/local.properties
@@ -0,0 +1,10 @@
+## This file is automatically generated by Android Studio.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file should *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+#
+# Location of the SDK. This is only used by Gradle.
+# For customization when using a Version Control System, please read the
+# header note.
+sdk.dir=/Users/armando/Library/Android/sdk
\ No newline at end of file
diff --git a/XYZBank/outputs/apk/.DS_Store b/XYZBank/outputs/apk/.DS_Store
new file mode 100644
index 000000000..0747c4be6
Binary files /dev/null and b/XYZBank/outputs/apk/.DS_Store differ
diff --git a/XYZBank/outputs/app-debug.apk b/XYZBank/outputs/app-debug.apk
new file mode 100644
index 000000000..96e975f64
Binary files /dev/null and b/XYZBank/outputs/app-debug.apk differ
diff --git a/XYZBank/outputs/output-metadata.json b/XYZBank/outputs/output-metadata.json
new file mode 100644
index 000000000..ad2cc86f3
--- /dev/null
+++ b/XYZBank/outputs/output-metadata.json
@@ -0,0 +1,18 @@
+{
+ "version": 2,
+ "artifactType": {
+ "type": "APK",
+ "kind": "Directory"
+ },
+ "applicationId": "com.xyzbank.xyzbankapp",
+ "variantName": "debug",
+ "elements": [
+ {
+ "type": "SINGLE",
+ "filters": [],
+ "versionCode": 1,
+ "versionName": "1.0",
+ "outputFile": "app-debug.apk"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/XYZBank/settings.gradle b/XYZBank/settings.gradle
new file mode 100644
index 000000000..6612e54db
--- /dev/null
+++ b/XYZBank/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = "XYZ Bank"
+include ':app'