diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..293d9aeac --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.idea +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..1d233faca --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Mohanraj K.M. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. 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/README.md b/app/README.md new file mode 100644 index 000000000..19a14cbe9 --- /dev/null +++ b/app/README.md @@ -0,0 +1,9 @@ +Para executar o projeto basta clonar esse repositório, da seguinte forma: + +1. Execute o GitBash na basta destino e digite o comando : git clone https://github.com/netogdn999/TesteAndroidv2.git + +2. Sincronize o gradle para baixar as dependencias + +3. Caso deseje executar os testes unitários, clique com o botão direito do mouse em cima do diretório de teste: com.example.testeandroidv2, em seguida clique em: 'Run Tests in 'com.example.testeandroidv2'' with Covarage + +4. Execute o projeto no emulador ou em um dispositivo do seu desejo, clicando em 'Run' ou Shift+f10 (caso esteja utilizando o windows) diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 000000000..54e573d53 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,57 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + buildToolsVersion '29.0.2' + + defaultConfig { + applicationId "com.testeandroidv2" + minSdkVersion 19 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + vectorDrawables.useSupportLibrary = true + testInstrumentationRunner 'org.robolectric.RobolectricTestRunner' + testFunctionalTest true + } + configurations { + cleanedAnnotations + compile.exclude group: 'org.jetbrains' , module:'annotations' + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + compileOptions{ + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + testOptions { + unitTests { + includeAndroidResources true + returnDefaultValues true + } + } + + buildFeatures { + dataBinding true + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + testImplementation 'junit:junit:4.13' + testImplementation "androidx.test:core:1.2.0" + implementation 'com.squareup.retrofit:retrofit:2.0.0-beta2' + implementation 'com.squareup.retrofit:converter-gson:2.0.0-beta2' + implementation 'com.squareup.okhttp3:logging-interceptor:4.7.2' + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta7' + implementation 'org.jetbrains:annotations-java5:15.0' + implementation 'androidx.recyclerview:recyclerview:1.1.0' + testImplementation 'org.robolectric:robolectric:4.3.1' +} + diff --git a/app/gradle/wrapper/gradle-wrapper.jar b/app/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..f6b961fd5 Binary files /dev/null and b/app/gradle/wrapper/gradle-wrapper.jar differ diff --git a/app/gradle/wrapper/gradle-wrapper.properties b/app/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..23ff7e2cd --- /dev/null +++ b/app/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Jun 17 14:37:35 GFT 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/app/gradlew b/app/gradlew new file mode 100644 index 000000000..cccdd3d51 --- /dev/null +++ b/app/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/app/gradlew.bat b/app/gradlew.bat new file mode 100644 index 000000000..f9553162f --- /dev/null +++ b/app/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/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /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 \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..4d22b773f --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/testeandroidv2/Service/Api.java b/app/src/main/java/com/example/testeandroidv2/Service/Api.java new file mode 100644 index 000000000..69bd7ab76 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/Service/Api.java @@ -0,0 +1,16 @@ +package com.example.testeandroidv2.Service; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import retrofit.GsonConverterFactory; +import retrofit.Retrofit; + +public class Api { + + public static Retrofit getRetrofitInstance(String path){ + return new Retrofit.Builder().baseUrl(path) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + } +} diff --git a/app/src/main/java/com/example/testeandroidv2/Service/LoginService.java b/app/src/main/java/com/example/testeandroidv2/Service/LoginService.java new file mode 100644 index 000000000..65260dfc2 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/Service/LoginService.java @@ -0,0 +1,15 @@ +package com.example.testeandroidv2.Service; + +import com.google.gson.JsonObject; + +import retrofit.Call; +import retrofit.http.Field; +import retrofit.http.FormUrlEncoded; +import retrofit.http.POST; + +public interface LoginService { + + @FormUrlEncoded + @POST("login") + Call authentication(@Field("user") String user, @Field("password") String password); +} diff --git a/app/src/main/java/com/example/testeandroidv2/Service/StatementService.java b/app/src/main/java/com/example/testeandroidv2/Service/StatementService.java new file mode 100644 index 000000000..4607f6db1 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/Service/StatementService.java @@ -0,0 +1,16 @@ +package com.example.testeandroidv2.Service; + +import com.google.gson.JsonObject; + +import java.util.List; + +import retrofit.Call; +import retrofit.http.FormUrlEncoded; +import retrofit.http.GET; +import retrofit.http.Path; + +public interface StatementService { + + @GET("statements/{id}") + Call getStatements(@Path("id") int userId); +} diff --git a/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginActivity.java b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginActivity.java new file mode 100644 index 000000000..3222c18c0 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginActivity.java @@ -0,0 +1,83 @@ +package com.example.testeandroidv2.loginScreen; + +import android.content.SharedPreferences; +import android.os.Bundle; +import com.example.testeandroidv2.R; +import com.example.testeandroidv2.databinding.LoginScreenBinding; +import com.google.gson.Gson; + +import java.util.ArrayList; +import java.util.List; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.databinding.DataBindingUtil; + +interface LoginActivityInput { + void displayLoginData(UserViewModel userViewModel); + void displayLoginErro(Object erro); +} + +public class LoginActivity extends AppCompatActivity implements LoginActivityInput { + + LoginInteractorInput output; + List listOfLoginViewModel = new ArrayList<>(); + LoginRouter router; + Object error; + LoginModel login = new LoginModel("", ""); + + private LoginScreenBinding binding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = DataBindingUtil.setContentView(this, R.layout.login_screen); + binding.setActivity(this); + + binding.setLogin(login); + setIsErroVisible(false); + + LoginConfigurator.INSTANCE.configure(this); + UserViewModel userViewModel = checkSharedPreferences(); + if(userViewModel != null) + displayLoginData(userViewModel); + } + + private void setIsErroVisible(Boolean isVisible){ + binding.setIsErroVisible(isVisible); + } + + public void login(){ + setIsErroVisible(false); + binding.setBtnText(getString(R.string.loginScreenBtnWaitMessage)); + fetchMetaData(); + } + + public void fetchMetaData(){ + LoginRequest aLoginRequest = new LoginRequest(); + aLoginRequest.user = login.login; + aLoginRequest.password = login.password; + output.fetchLoginData(aLoginRequest); + } + + @Override + public void displayLoginData(UserViewModel userViewModel) { + listOfLoginViewModel.add(userViewModel); + router.onItemClick(null, null, 0, 0); + } + + @Override + public void displayLoginErro(Object erro){ + this.error = erro; + binding.setErroMessage(this.error.toString()); + binding.setBtnText(null); + setIsErroVisible(true); + } + + private UserViewModel checkSharedPreferences(){ + SharedPreferences preferences = getSharedPreferences("user_preferences", MODE_PRIVATE); + String jsonUserModel = preferences.getString("user_login", null); + if(jsonUserModel != null) + return new Gson().fromJson(jsonUserModel, UserViewModel.class); + return null; + } +} diff --git a/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginConfigurator.java b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginConfigurator.java new file mode 100644 index 000000000..9f9aa4afa --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginConfigurator.java @@ -0,0 +1,27 @@ +package com.example.testeandroidv2.loginScreen; + +import java.lang.ref.WeakReference; + + +public enum LoginConfigurator { + INSTANCE; + + public void configure(LoginActivity activity) { + + LoginRouter router = new LoginRouter(); + router.activity = new WeakReference<>(activity); + + LoginPresenter presenter = new LoginPresenter(); + presenter.output = new WeakReference<>(activity); + + LoginInteractor interactor = new LoginInteractor(); + interactor.output = presenter; + + if (activity.output == null) { + activity.output = interactor; + } + if (activity.router == null) { + activity.router = router; + } + } +} diff --git a/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginInteractor.java b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginInteractor.java new file mode 100644 index 000000000..6c0f55437 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginInteractor.java @@ -0,0 +1,90 @@ +package com.example.testeandroidv2.loginScreen; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import org.jetbrains.annotations.NotNull; + +import java.util.regex.Pattern; + +import retrofit.Callback; +import retrofit.Response; +import retrofit.Retrofit; + +interface LoginInteractorInput { + void fetchLoginData(LoginRequest request); +} + +public class LoginInteractor implements LoginInteractorInput { + + LoginPresenterInput output; + private LoginWorkerInput aLoginWorkerInput; + + Callback callback = new Callback() { + LoginResponse loginResponse; + @Override + public void onResponse(Response response, Retrofit retrofit) { + loginResponse = new Gson().fromJson(response.body(), LoginResponse.class); + response(loginResponse); + } + + @Override + public void onFailure(Throwable t) { + loginResponse.error = t; + response(loginResponse); + } + }; + + private LoginWorkerInput getLoginWorkerInput() { + if (aLoginWorkerInput == null) return new LoginWorker(); + return aLoginWorkerInput; + } + + void setLoginWorkerInput(LoginWorkerInput aLoginWorkerInput) { + this.aLoginWorkerInput = aLoginWorkerInput; + } + + @Override + public void fetchLoginData(@NotNull LoginRequest request) { + aLoginWorkerInput = getLoginWorkerInput(); + LoginResponse loginResponse = new LoginResponse(); + + if(isCpf(request.user) || isEmail(request.user)) { + if(isPasswordValid(request.password)) { + aLoginWorkerInput.buildRequest(request); + loginResponse = aLoginWorkerInput.getLoginResponse(callback); + if(loginResponse != null) response(loginResponse); + }else{ + loginResponse.error = "A senha deve ter uma letra maiuscula, um caracter especial e um caracter alfanumérico"; + response(loginResponse); + } + }else{ + loginResponse.error = "Por favor digite um CPF ou E-mail válido"; + response(loginResponse); + } + } + + private void response(LoginResponse response){ + output.presentLoginData(response); + } + + @NotNull + private Boolean isCpf(String user){ + Pattern pattern = Pattern.compile("(^(\\d{3}.\\d{3}.\\d{3}-\\d{2})|(\\d{11})$)"); + return pattern.matcher(user).find(); + } + + @NotNull + private Boolean isEmail(String user){ + Pattern pattern = Pattern.compile("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)])"); + return pattern.matcher(user).find(); + } + + @NotNull + private Boolean isPasswordValid(String password){ + Pattern patternUppercase = Pattern.compile("[A-Z]+"); + Pattern patternSpecialChar = Pattern.compile("\\W+"); + Pattern patternAlphanumericChar = Pattern.compile("\\w+"); + return patternUppercase.matcher(password).find() && patternSpecialChar.matcher(password).find() && patternAlphanumericChar.matcher(password).find(); + } +} diff --git a/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginModel.java b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginModel.java new file mode 100644 index 000000000..7dfdd901f --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginModel.java @@ -0,0 +1,81 @@ +package com.example.testeandroidv2.loginScreen; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +public class LoginModel { + String login; + String password; + + public LoginModel(String login, String password) { + this.login = login; + this.password = password; + } + + @NonNull + @Override + public String toString() { + return "{\n\tlogin: "+login+",\n\tpassword: "+password+"\n}"; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} + +class LoginViewModel implements Parcelable { + String login; + String password; + + protected LoginViewModel(Parcel in) { + login = in.readString(); + password = in.readString(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(login); + dest.writeString(password); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator CREATOR = new Creator() { + @Override + public LoginViewModel createFromParcel(Parcel in) { + return new LoginViewModel(in); + } + + @Override + public LoginViewModel[] newArray(int size) { + return new LoginViewModel[size]; + } + }; +} + +class LoginRequest { + String user; + String password; +} + +class LoginResponse { + UserModel userAccount; + Object error; +} diff --git a/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginPresenter.java b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginPresenter.java new file mode 100644 index 000000000..146d653b9 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginPresenter.java @@ -0,0 +1,33 @@ +package com.example.testeandroidv2.loginScreen; + +import java.lang.ref.WeakReference; + +interface LoginPresenterInput { + void presentLoginData(LoginResponse response); +} + + +public class LoginPresenter implements LoginPresenterInput { + + public WeakReference output; + + @Override + public void presentLoginData(LoginResponse response) { + if(response.userAccount != null) { + UserModel userModel = response.userAccount; + output.get().displayLoginData(getUserViewModel(userModel)); + }else{ + output.get().displayLoginErro(response.error); + } + } + + private UserViewModel getUserViewModel(UserModel userModel){ + UserViewModel userViewModel = new UserViewModel(); + userViewModel.name = userModel.name; + userViewModel.agency = userModel.agency; + userViewModel.bankAccount = userModel.bankAccount; + userViewModel.balance = userModel.balance; + return userViewModel; + } + +} diff --git a/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginRouter.java b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginRouter.java new file mode 100644 index 000000000..13c100b43 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginRouter.java @@ -0,0 +1,53 @@ +package com.example.testeandroidv2.loginScreen; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.view.View; +import android.widget.AdapterView; + +import com.example.testeandroidv2.statementScreen.StatementActivity; +import com.google.gson.Gson; + +import java.lang.ref.WeakReference; + +import androidx.annotation.NonNull; + +interface LoginRouterInput { + Intent navigateToSomeWhere(int position); + void passDataToNextScene(int position, Intent intent); +} + +public class LoginRouter implements LoginRouterInput, AdapterView.OnItemClickListener { + + WeakReference activity; + + @NonNull + @Override + public Intent navigateToSomeWhere(int position) { + return new Intent(activity.get(), StatementActivity.class); + } + + @Override + public void passDataToNextScene(int position, Intent intent) { + UserViewModel user = activity.get().listOfLoginViewModel.get(position); + intent.putExtra("user",user); + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + Intent intent = navigateToSomeWhere(position); + passDataToNextScene(position, intent); + safeLoginOnSharedPreferences(); + activity.get().startActivity(intent); + } + + private void safeLoginOnSharedPreferences(){ + String jsonLogin = new Gson().toJson(activity.get().listOfLoginViewModel.get(0)); + SharedPreferences preferences = activity.get().getSharedPreferences("user_preferences", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = preferences.edit(); + editor.putString("user_login",jsonLogin); + editor.apply(); + } + +} diff --git a/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginWorker.java b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginWorker.java new file mode 100644 index 000000000..69bf2d947 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/loginScreen/LoginWorker.java @@ -0,0 +1,42 @@ +package com.example.testeandroidv2.loginScreen; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.example.testeandroidv2.Service.Api; +import com.example.testeandroidv2.Service.LoginService; + +import java.io.IOException; + +import retrofit.Call; +import retrofit.Callback; +import retrofit.Retrofit; + +interface LoginWorkerInput { + void buildRequest(LoginRequest request); + LoginResponse getLoginResponse(Callback callback); +} + +public class LoginWorker implements LoginWorkerInput { + + private Call call; + + @Override + public void buildRequest(LoginRequest request) { + Retrofit api = Api.getRetrofitInstance("https://bank-app-test.herokuapp.com/api/"); + LoginService loginService = api.create(LoginService.class); + call = loginService.authentication(request.user, request.password); + } + + @Override + public LoginResponse getLoginResponse(Callback callback) { + try { + if(callback == null) + return new Gson().fromJson(call.execute().body(), LoginResponse.class); + else + call.enqueue(callback); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/app/src/main/java/com/example/testeandroidv2/loginScreen/UserModel.java b/app/src/main/java/com/example/testeandroidv2/loginScreen/UserModel.java new file mode 100644 index 000000000..346f529ba --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/loginScreen/UserModel.java @@ -0,0 +1,96 @@ +package com.example.testeandroidv2.loginScreen; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +public class UserModel { + int userId; + String name; + String bankAccount; + String agency; + double balance; + + public UserModel(int userId, String name, String bankAccount, String agency, double balance) { + this.userId = userId; + this.name = name; + this.bankAccount = bankAccount; + this.agency = agency; + this.balance = balance; + } + + @NonNull + @Override + public String toString() { + return "{\n\tuserId: "+userId+",\n\tname: "+name+",\n\tbankAccount: "+bankAccount+",\n\tagency: "+agency+",\n\tbalance: "+balance+"\n}"; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String getName() { + return name; + } + + public String getBankAccount() { + return bankAccount; + } + + public String getAgency() { + return agency; + } + + public double getBalance() { + return balance; + } +} + +class UserViewModel implements Parcelable { + private int userId; + String name; + String bankAccount; + String agency; + double balance; + + public UserViewModel(){ } + + protected UserViewModel(Parcel in) { + userId = in.readInt(); + name = in.readString(); + bankAccount = in.readString(); + agency = in.readString(); + balance = in.readDouble(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public UserViewModel createFromParcel(Parcel in) { + return new UserViewModel(in); + } + + @Override + public UserViewModel[] newArray(int size) { + return new UserViewModel[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeInt(userId); + parcel.writeString(name); + parcel.writeString(bankAccount); + parcel.writeString(agency); + parcel.writeDouble(balance); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/testeandroidv2/statementScreen/ClientModel.java b/app/src/main/java/com/example/testeandroidv2/statementScreen/ClientModel.java new file mode 100644 index 000000000..94558824c --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/statementScreen/ClientModel.java @@ -0,0 +1,99 @@ +package com.example.testeandroidv2.statementScreen; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +import com.example.testeandroidv2.loginScreen.UserModel; + +public class ClientModel { + String name; + String account; + String balance; + + public ClientModel(){ + super(); + } + + public ClientModel(String name, String account, String balance) { + this.name = name; + this.account = account; + this.balance = balance; + } + + @NonNull + @Override + public String toString() { + return "{\n\tname: "+name+",\n\taccount: "+account+",\n\tbalance: "+balance+"\n}"; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getBalance() { + return balance; + } + + public void setBalance(String balance) { + this.balance = balance; + } +} + +class ClientViewModel implements Parcelable { + String name; + String account; + String balance; + + protected ClientViewModel(Parcel in) { + name = in.readString(); + account = in.readString(); + balance = in.readString(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(name); + dest.writeString(account); + dest.writeString(balance); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator CREATOR = new Creator() { + @Override + public ClientViewModel createFromParcel(Parcel in) { + return new ClientViewModel(in); + } + + @Override + public ClientViewModel[] newArray(int size) { + return new ClientViewModel[size]; + } + }; +} + +class ClientRequest { + UserModel userModel; +} + +class ClientResponse{ + UserModel userModel; + Object error; +} \ No newline at end of file diff --git a/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementActivity.java b/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementActivity.java new file mode 100644 index 000000000..66dfe8daf --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementActivity.java @@ -0,0 +1,101 @@ +package com.example.testeandroidv2.statementScreen; + +import android.os.Bundle; + +import com.example.testeandroidv2.loginScreen.UserModel; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.example.testeandroidv2.R; +import com.example.testeandroidv2.databinding.StatementScreenBinding; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.databinding.DataBindingUtil; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; + +interface StatementActivityInput { + void displayStatementData(List statementModels); + void displayStatementError(Object error); + void displayClientData(ClientModel clientModel); + void displayClientError(Object error); +} + +public class StatementActivity extends AppCompatActivity implements StatementActivityInput { + +// public static String TAG = StatementActivity.class.getSimpleName(); + private StatementScreenBinding binding; + private TransactionHistoryAdapter adapter; + StatementInteractorInput output; + UserModel userModel; + List statementModelList = new ArrayList<>(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = DataBindingUtil.setContentView(this, R.layout.statement_screen); + binding.setActivity(this); + toggleLoading(true); + + StatementConfigurator.INSTANCE.configure(this); + Bundle bundle = getIntent().getExtras(); + if(bundle != null) { + JsonObject object = new Gson().toJsonTree(bundle.get("user")).getAsJsonObject(); + userModel = new Gson().fromJson(object, UserModel.class); + } + + RecyclerView rv = findViewById(R.id.transactionHistory); + adapter = new TransactionHistoryAdapter(statementModelList); + rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + rv.setHasFixedSize(true); + rv.setAdapter(adapter); + } + + @Override + protected void onResume() { + super.onResume(); + fetchMetaData(); + } + + public void fetchMetaData(){ + ClientRequest clientRequest = new ClientRequest(); + StatementRequest statementRequest = new StatementRequest(); + clientRequest.userModel = userModel; + statementRequest.user = userModel; + if(clientRequest.userModel != null) { + output.fetchClientData(clientRequest); + output.fetchStatementData(statementRequest); + } + } + + private void toggleLoading(Boolean isVisible){ + binding.setLoadingIsVisible(isVisible); + } + + @Override + public void displayStatementData(List statementModels) { + toggleLoading(false); + adapter.setListOfStatement(statementModels); + } + + @Override + public void displayStatementError(Object error) { + + } + + @Override + public void displayClientData(ClientModel clientModel) { + binding.setClient(clientModel); + } + + @Override + public void displayClientError(Object error) { + + } + + public void logout(){ + finish(); + } +} diff --git a/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementConfigurator.java b/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementConfigurator.java new file mode 100644 index 000000000..446be05bc --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementConfigurator.java @@ -0,0 +1,19 @@ +package com.example.testeandroidv2.statementScreen; + +import java.lang.ref.WeakReference; + +public enum StatementConfigurator { + INSTANCE; + + public void configure(StatementActivity activity) { + StatementPresenter presenter = new StatementPresenter(); + presenter.output = new WeakReference<>(activity); + + StatementInteractor interactor = new StatementInteractor(); + interactor.output = presenter; + + if (activity.output == null) { + activity.output = interactor; + } + } +} diff --git a/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementInteractor.java b/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementInteractor.java new file mode 100644 index 000000000..f24936585 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementInteractor.java @@ -0,0 +1,73 @@ +package com.example.testeandroidv2.statementScreen; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import retrofit.Callback; +import retrofit.Response; +import retrofit.Retrofit; + +interface StatementInteractorInput { + void fetchStatementData(StatementRequest request); + void fetchClientData(ClientRequest clientRequest); +} + +public class StatementInteractor implements StatementInteractorInput { + + StatementPresenterInput output; + private StatementWorkerInput aStatementWorkerInput; + + Callback callback = new Callback() { + StatementResponse statementResponse; + @Override + public void onResponse(Response response, Retrofit retrofit) { + statementResponse = new Gson().fromJson(response.body(), StatementResponse.class); + response(statementResponse); + } + + @Override + public void onFailure(Throwable t) { + statementResponse.error = t; + response(statementResponse); + } + }; + + private StatementWorkerInput getStatementWorkerInput() { + if (aStatementWorkerInput == null) return new StatementWorker(); + return aStatementWorkerInput; + } + + void setStatementWorkerInput(StatementWorkerInput aStatementWorkerInput) { + this.aStatementWorkerInput = aStatementWorkerInput; + } + + @Override + public void fetchStatementData(StatementRequest request) { + StatementResponse statementResponse = new StatementResponse(); + aStatementWorkerInput = getStatementWorkerInput(); + if(request.user != null) { + aStatementWorkerInput.buildRequest(request); + statementResponse = aStatementWorkerInput.getStatementsResponse(callback); + if(statementResponse != null && statementResponse.statementList != null && !statementResponse.statementList.isEmpty()) + response(statementResponse); + }else{ + statementResponse.error = "Erro interno, usuário não logado"; + response(statementResponse); + } + } + + @Override + public void fetchClientData(ClientRequest clientRequest) { + ClientResponse clientResponse = new ClientResponse(); + if(clientRequest.userModel != null) { + clientResponse.userModel = clientRequest.userModel; + }else{ + clientResponse.error = "Erro interno, usuário não logado"; + } + output.presentClientData(clientResponse); + } + + private void response(StatementResponse statementResponse){ + output.presentStatementData(statementResponse); + } +} diff --git a/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementModel.java b/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementModel.java new file mode 100644 index 000000000..ec53b67ec --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementModel.java @@ -0,0 +1,110 @@ +package com.example.testeandroidv2.statementScreen; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.List; + +import androidx.annotation.NonNull; + +import com.example.testeandroidv2.loginScreen.UserModel; + +public class StatementModel { + String title; + String desc; + String date; + String value; + + public StatementModel(String title, String desc, String date, String value) { + this.title = title; + this.desc = desc; + this.date = date; + this.value = value; + } + + @NonNull + @Override + public String toString() { + return "{\n\ttitle: "+title+",\n\tdesc: "+desc+",\n\tdate: "+date+",\n\tvalue: "+value+"\n}"; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} + +class StatementViewModel implements Parcelable { + String title; + String desc; + String date; + String value; + + protected StatementViewModel(Parcel in) { + title = in.readString(); + desc = in.readString(); + date = in.readString(); + value = in.readString(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(title); + dest.writeString(desc); + dest.writeString(date); + dest.writeString(value); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator CREATOR = new Creator() { + @Override + public StatementViewModel createFromParcel(Parcel in) { + return new StatementViewModel(in); + } + + @Override + public StatementViewModel[] newArray(int size) { + return new StatementViewModel[size]; + } + }; +} + +class StatementRequest { + UserModel user; +} + +class StatementResponse { + List statementList; + Object error; +} diff --git a/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementPresenter.java b/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementPresenter.java new file mode 100644 index 000000000..e21f92de9 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/statementScreen/StatementPresenter.java @@ -0,0 +1,74 @@ +package com.example.testeandroidv2.statementScreen; + +import com.example.testeandroidv2.loginScreen.UserModel; + +import java.lang.ref.WeakReference; +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +interface StatementPresenterInput { + void presentStatementData(StatementResponse response); + void presentClientData(ClientResponse response); +} + +public class StatementPresenter implements StatementPresenterInput { + + public WeakReference output; + + @Override + public void presentStatementData(StatementResponse response) { + if(response.statementList != null && !response.statementList.isEmpty()){ + for(int i=0; i callback); +} + +public class StatementWorker implements StatementWorkerInput { + + private Call call; + + @Override + public void buildRequest(StatementRequest request) { + Retrofit api = Api.getRetrofitInstance("https://bank-app-test.herokuapp.com/api/"); + StatementService statementService = api.create(StatementService.class); + call = statementService.getStatements(request.user.getUserId()); + } + + @Override + public StatementResponse getStatementsResponse(Callback callback) { + try { + if(callback == null){ + return new Gson().fromJson(call.execute().body(), StatementResponse.class); + }else { + call.enqueue(callback); + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/app/src/main/java/com/example/testeandroidv2/statementScreen/TransactionHistoryAdapter.java b/app/src/main/java/com/example/testeandroidv2/statementScreen/TransactionHistoryAdapter.java new file mode 100644 index 000000000..1623b72c9 --- /dev/null +++ b/app/src/main/java/com/example/testeandroidv2/statementScreen/TransactionHistoryAdapter.java @@ -0,0 +1,57 @@ +package com.example.testeandroidv2.statementScreen; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.example.testeandroidv2.R; +import com.example.testeandroidv2.databinding.TransactionHistoryItemBinding; + +import java.util.List; + +import androidx.annotation.NonNull; +import androidx.databinding.DataBindingUtil; +import androidx.recyclerview.widget.RecyclerView; + +public class TransactionHistoryAdapter extends RecyclerView.Adapter { + private List listOfStatement; + + public TransactionHistoryAdapter(List listOfStatement){ + this.listOfStatement = listOfStatement; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.transaction_history_item, viewGroup, false)); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) { + viewHolder.bind(listOfStatement.get(i)); + } + + @Override + public int getItemCount() { + return listOfStatement.size(); + } + + public void setListOfStatement(List listOfStatement){ + this.listOfStatement = listOfStatement; + notifyDataSetChanged(); + } +} + +class ViewHolder extends RecyclerView.ViewHolder{ + + private final TransactionHistoryItemBinding binding; + + ViewHolder(@NonNull View itemView) { + super(itemView); + binding = DataBindingUtil.bind(itemView); + } + + void bind(StatementModel statement){ + binding.setStatement(statement); + } +} 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/custom_edit_text_bg.xml b/app/src/main/res/drawable/custom_edit_text_bg.xml new file mode 100644 index 000000000..3419eb92f --- /dev/null +++ b/app/src/main/res/drawable/custom_edit_text_bg.xml @@ -0,0 +1,8 @@ + + + + + + \ 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/login_button_bg.xml b/app/src/main/res/drawable/login_button_bg.xml new file mode 100644 index 000000000..34070d4cb --- /dev/null +++ b/app/src/main/res/drawable/login_button_bg.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/logo.png b/app/src/main/res/drawable/logo.png new file mode 100644 index 000000000..66bdc8d5d Binary files /dev/null and b/app/src/main/res/drawable/logo.png differ diff --git a/app/src/main/res/drawable/logout.png b/app/src/main/res/drawable/logout.png new file mode 100644 index 000000000..de1e4ae3c Binary files /dev/null and b/app/src/main/res/drawable/logout.png differ diff --git a/app/src/main/res/drawable/message_erro_bg.xml b/app/src/main/res/drawable/message_erro_bg.xml new file mode 100644 index 000000000..e05ca46da --- /dev/null +++ b/app/src/main/res/drawable/message_erro_bg.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/transaction_history_item_bg.xml b/app/src/main/res/drawable/transaction_history_item_bg.xml new file mode 100644 index 000000000..8d25dd4cd --- /dev/null +++ b/app/src/main/res/drawable/transaction_history_item_bg.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/font/helveticaneue.ttf b/app/src/main/res/font/helveticaneue.ttf new file mode 100644 index 000000000..cac3b75d8 Binary files /dev/null and b/app/src/main/res/font/helveticaneue.ttf differ diff --git a/app/src/main/res/layout/login_screen.xml b/app/src/main/res/layout/login_screen.xml new file mode 100644 index 000000000..d561943c7 --- /dev/null +++ b/app/src/main/res/layout/login_screen.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + +