From 4de7143c5190c7bd9459a7d746757c10c0c8b022 Mon Sep 17 00:00:00 2001
From: 0xzre <alilo.ghazali@gmail.com>
Date: Fri, 15 Mar 2024 14:40:26 +0700
Subject: [PATCH] feat login n jwt checker bg

---
 app/build.gradle.kts                          |   2 +
 app/src/main/AndroidManifest.xml              |  11 +-
 .../java/com/atm/bondowowo/BondowowoApp.kt    |  41 +++++++
 .../java/com/atm/bondowowo/LoginActivity.kt   | 107 ++++++++++++++++++
 .../java/com/atm/bondowowo/MainActivity.kt    |  65 +++++++++--
 .../atm/bondowowo/data/model/LoginRequest.kt  |   6 +
 .../atm/bondowowo/data/model/LoginResponse.kt |   5 +
 .../bondowowo/data/model/VerifyResponse.kt    |   7 ++
 .../atm/bondowowo/data/remote/ApiService.kt   |  17 +++
 .../utils/BackgroundJWTCheckerUtil.kt         |  50 ++++++++
 .../com/atm/bondowowo/utils/NetworkUtils.kt   |  16 +++
 .../main/res/color/bottom_nav_icon_color.xml  |   5 +
 .../main/res/color/bottom_nav_text_color.xml  |   5 +
 app/src/main/res/drawable/ic_logo.png         | Bin 0 -> 15652 bytes
 app/src/main/res/drawable/ic_scan.png         | Bin 586 -> 849 bytes
 app/src/main/res/layout/activity_login.xml    |  66 +++++++++++
 .../res/layout/bottom_navigation_layout.xml   |   7 +-
 app/src/main/res/values/colors.xml            |   6 +
 app/src/main/res/values/styles.xml            |  14 +++
 19 files changed, 414 insertions(+), 16 deletions(-)
 create mode 100644 app/src/main/java/com/atm/bondowowo/BondowowoApp.kt
 create mode 100644 app/src/main/java/com/atm/bondowowo/LoginActivity.kt
 create mode 100644 app/src/main/java/com/atm/bondowowo/data/model/LoginRequest.kt
 create mode 100644 app/src/main/java/com/atm/bondowowo/data/model/LoginResponse.kt
 create mode 100644 app/src/main/java/com/atm/bondowowo/data/model/VerifyResponse.kt
 create mode 100644 app/src/main/java/com/atm/bondowowo/data/remote/ApiService.kt
 create mode 100644 app/src/main/java/com/atm/bondowowo/utils/BackgroundJWTCheckerUtil.kt
 create mode 100644 app/src/main/java/com/atm/bondowowo/utils/NetworkUtils.kt
 create mode 100644 app/src/main/res/color/bottom_nav_icon_color.xml
 create mode 100644 app/src/main/res/color/bottom_nav_text_color.xml
 create mode 100644 app/src/main/res/drawable/ic_logo.png
 create mode 100644 app/src/main/res/layout/activity_login.xml
 create mode 100644 app/src/main/res/values/styles.xml

diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 9adfcd8..1c1e372 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -48,6 +48,8 @@ dependencies {
     implementation("androidx.navigation:navigation-fragment-ktx:$navVersion")
     implementation("androidx.navigation:navigation-ui-ktx:$navVersion")
     implementation("com.google.android.material:material:1.9.0")
+    implementation("com.squareup.retrofit2:retrofit:2.9.0")
+    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
     testImplementation("junit:junit:4.13.2")
     androidTestImplementation("androidx.test.ext:junit:1.1.5")
     androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e105b0d..8beb467 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,7 +2,10 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools">
 
+    <uses-permission android:name="android.permission.INTERNET" />
+
     <application
+        android:name=".BondowowoApp"
         android:allowBackup="true"
         android:dataExtractionRules="@xml/data_extraction_rules"
         android:fullBackupContent="@xml/backup_rules"
@@ -14,8 +17,12 @@
         tools:targetApi="31">
         <activity
             android:name=".MainActivity"
-            android:label="@string/app_name"
-            android:exported="true">
+            android:exported="false"
+            android:theme="@style/AppTheme.NoActionBar"/>
+        <activity
+            android:name=".LoginActivity"
+            android:exported="true"
+            android:theme="@style/AppTheme.NoActionBar">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/app/src/main/java/com/atm/bondowowo/BondowowoApp.kt b/app/src/main/java/com/atm/bondowowo/BondowowoApp.kt
new file mode 100644
index 0000000..c52591a
--- /dev/null
+++ b/app/src/main/java/com/atm/bondowowo/BondowowoApp.kt
@@ -0,0 +1,41 @@
+package com.atm.bondowowo;
+
+import android.app.Activity
+import android.app.Application
+import android.content.Context
+import android.content.Intent
+import com.atm.bondowowo.utils.BackgroundJWTChecker
+
+class BondowowoApp : Application() {
+
+    private var jwtChecker: BackgroundJWTChecker? = null
+
+    override fun onCreate() {
+        super.onCreate()
+        initBackgroundJWTChecker(this)
+    }
+
+    private fun initBackgroundJWTChecker(context: Context) {
+        jwtChecker = BackgroundJWTChecker()
+        jwtChecker?.startChecking(context, object : BackgroundJWTChecker.Callback {
+            override fun onTokenVerified() {
+                // Continu app
+            }
+
+            override fun onTokenInvalid() {
+                val intent = Intent(context, LoginActivity::class.java)
+                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+                context.startActivity(intent)
+                if (context is Activity) {
+                    context.finish()
+                }
+            }
+
+            override fun onNetworkError() {
+                // Harusnya ini coba cek isi JWT pake library
+            }
+        })
+    }
+
+
+}
diff --git a/app/src/main/java/com/atm/bondowowo/LoginActivity.kt b/app/src/main/java/com/atm/bondowowo/LoginActivity.kt
new file mode 100644
index 0000000..bdb2521
--- /dev/null
+++ b/app/src/main/java/com/atm/bondowowo/LoginActivity.kt
@@ -0,0 +1,107 @@
+package com.atm.bondowowo
+
+import android.content.Intent
+import android.os.Bundle
+import android.widget.Button
+import android.widget.EditText
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import com.atm.bondowowo.data.model.LoginRequest
+import com.atm.bondowowo.utils.NetworkUtils.apiService
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class LoginActivity : AppCompatActivity() {
+
+    private lateinit var etUsername: EditText
+    private lateinit var etPassword: EditText
+    private lateinit var btnLogin: Button
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_login)
+
+        CoroutineScope(Dispatchers.Main).launch {
+            if (isUserAuthenticated()) {
+                navigateToMainActivity()
+            } else {
+                etUsername = findViewById(R.id.etUsername)
+                etPassword = findViewById(R.id.etPassword)
+                btnLogin = findViewById(R.id.btnLogin)
+
+                btnLogin.setOnClickListener {
+                    performLogin()
+                }
+            }
+        }
+    }
+
+    private fun performLogin() {
+        val email = etUsername.text.toString()
+        val password = etPassword.text.toString()
+
+        val loginRequest = LoginRequest(email, password)
+
+        CoroutineScope(Dispatchers.IO).launch {
+            try {
+                val response = apiService.login(loginRequest)
+                if (response.isSuccessful) {
+                    val loginResponse = response.body()
+                    val token = loginResponse?.token
+
+                    saveTokenSecurely(token)
+
+                    startActivity(Intent(this@LoginActivity, MainActivity::class.java))
+                    finish()
+                } else {
+                    withContext(Dispatchers.Main) {
+                        Toast.makeText(this@LoginActivity, "Invalid Credentials", Toast.LENGTH_SHORT)
+                            .show()
+                    }
+                }
+            } catch (e: Exception) {
+                withContext(Dispatchers.Main) {
+                    Toast.makeText(this@LoginActivity, "An error occurred", Toast.LENGTH_SHORT)
+                        .show()
+                }
+            }
+        }
+    }
+
+    private fun saveTokenSecurely(token: String?) {
+        val sharedPreferences = getSharedPreferences("AUTH_PREFS", MODE_PRIVATE)
+        val editor = sharedPreferences.edit()
+        editor.putString("JWT_TOKEN", token)
+        editor.apply()
+    }
+
+    private suspend fun isUserAuthenticated(): Boolean {
+        val sharedPreferences = getSharedPreferences("AUTH_PREFS", MODE_PRIVATE)
+        val token = sharedPreferences.getString("JWT_TOKEN", null)
+        val isValid = token?.let { isTokenValid(it) }
+
+        return token != null && isValid == true
+    }
+
+    private fun navigateToMainActivity() {
+        startActivity(Intent(this, MainActivity::class.java))
+        finish()
+    }
+
+    private suspend fun isTokenValid(token: String): Boolean {
+        return try {
+            val response = apiService.verifyToken("Bearer $token")
+            if (response.isSuccessful) {
+                val responseBody = response.body()
+                val isString = responseBody is String
+                return !isString
+            } else {
+                false
+            }
+        } catch (e: Exception) {
+            false
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/atm/bondowowo/MainActivity.kt b/app/src/main/java/com/atm/bondowowo/MainActivity.kt
index 2a4bb99..8c31aac 100644
--- a/app/src/main/java/com/atm/bondowowo/MainActivity.kt
+++ b/app/src/main/java/com/atm/bondowowo/MainActivity.kt
@@ -1,13 +1,17 @@
 package com.atm.bondowowo
 
+import android.content.Intent
 import android.os.Bundle
+import android.widget.Toast
 import androidx.appcompat.app.AppCompatActivity
 import androidx.navigation.findNavController
 import androidx.navigation.fragment.NavHostFragment
-import androidx.navigation.ui.AppBarConfiguration
-import androidx.navigation.ui.setupActionBarWithNavController
 import androidx.navigation.ui.setupWithNavController
 import com.atm.bondowowo.databinding.ActivityMainBinding
+import com.atm.bondowowo.utils.NetworkUtils
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
 
 class MainActivity : AppCompatActivity() {
 
@@ -18,20 +22,57 @@ class MainActivity : AppCompatActivity() {
         binding = ActivityMainBinding.inflate(layoutInflater)
         setContentView(binding.root)
 
-        // Navigation Component
-        val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
-        val navController = navHostFragment.navController
-        val appBarConfiguration = AppBarConfiguration(
-            setOf(
-                R.id.transactionFragment, R.id.scanFragment, R.id.graphFragment, R.id.settingsFragment
-            )
-        )
-        setupActionBarWithNavController(navController, appBarConfiguration)
-        binding.bottomNavLayout.bottomNavigation.setupWithNavController(navController)
+        CoroutineScope(Dispatchers.Main).launch {
+            if (!isUserAuthenticated()) {
+                navigateToLoginActivity()
+            } else {
+                val navHostFragment =
+                    supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
+                val navController = navHostFragment.navController
+                binding.bottomNavLayout.bottomNavigation.setupWithNavController(navController)
+            }
+        }
     }
 
     override fun onSupportNavigateUp(): Boolean {
         val navController = findNavController(R.id.nav_host_fragment)
         return navController.navigateUp() || super.onSupportNavigateUp()
     }
+
+    private suspend fun isUserAuthenticated(): Boolean {
+        val sharedPreferences = getSharedPreferences("AUTH_PREFS", MODE_PRIVATE)
+        val token = sharedPreferences.getString("JWT_TOKEN", null)
+
+        return token != null && isTokenValid(token)
+    }
+
+    private fun navigateToLoginActivity() {
+        startActivity(Intent(this, LoginActivity::class.java))
+        finish()
+    }
+
+    private suspend fun isTokenValid(token: String): Boolean {
+        return try {
+            val response = NetworkUtils.apiService.verifyToken("Bearer $token")
+            if (response.isSuccessful) {
+                val responseBody = response.body()
+                val isString = responseBody is String
+                return !isString
+            } else {
+                Toast.makeText(
+                    this@MainActivity,
+                    "Session Expired, Please Re login",
+                    Toast.LENGTH_SHORT
+                ).show()
+                false
+            }
+        } catch (e: Exception) {
+            Toast.makeText(
+                this@MainActivity,
+                "An error occurred, Please Re login",
+                Toast.LENGTH_SHORT
+            ).show()
+            false
+        }
+    }
 }
diff --git a/app/src/main/java/com/atm/bondowowo/data/model/LoginRequest.kt b/app/src/main/java/com/atm/bondowowo/data/model/LoginRequest.kt
new file mode 100644
index 0000000..f3aedb6
--- /dev/null
+++ b/app/src/main/java/com/atm/bondowowo/data/model/LoginRequest.kt
@@ -0,0 +1,6 @@
+package com.atm.bondowowo.data.model
+
+data class LoginRequest(
+    val email: String,
+    val password: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/atm/bondowowo/data/model/LoginResponse.kt b/app/src/main/java/com/atm/bondowowo/data/model/LoginResponse.kt
new file mode 100644
index 0000000..4d9a220
--- /dev/null
+++ b/app/src/main/java/com/atm/bondowowo/data/model/LoginResponse.kt
@@ -0,0 +1,5 @@
+package com.atm.bondowowo.data.model
+
+data class LoginResponse(
+    val token: String // JWT
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/atm/bondowowo/data/model/VerifyResponse.kt b/app/src/main/java/com/atm/bondowowo/data/model/VerifyResponse.kt
new file mode 100644
index 0000000..7d5e964
--- /dev/null
+++ b/app/src/main/java/com/atm/bondowowo/data/model/VerifyResponse.kt
@@ -0,0 +1,7 @@
+package com.atm.bondowowo.data.model
+
+data class VerifyResponse(
+    val nim: String,
+    val iat: Int,
+    val exp: Int
+)
diff --git a/app/src/main/java/com/atm/bondowowo/data/remote/ApiService.kt b/app/src/main/java/com/atm/bondowowo/data/remote/ApiService.kt
new file mode 100644
index 0000000..a1a5440
--- /dev/null
+++ b/app/src/main/java/com/atm/bondowowo/data/remote/ApiService.kt
@@ -0,0 +1,17 @@
+package com.atm.bondowowo.data.remote
+
+import com.atm.bondowowo.data.model.LoginRequest
+import com.atm.bondowowo.data.model.LoginResponse
+import com.atm.bondowowo.data.model.VerifyResponse
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.Header
+import retrofit2.http.POST
+
+interface ApiService {
+    @POST("api/auth/login")
+    suspend fun login(@Body loginRequest: LoginRequest): Response<LoginResponse>
+
+    @POST("api/auth/token")
+    suspend fun verifyToken(@Header("Authorization") jwtToken: String): Response<Any>
+}
diff --git a/app/src/main/java/com/atm/bondowowo/utils/BackgroundJWTCheckerUtil.kt b/app/src/main/java/com/atm/bondowowo/utils/BackgroundJWTCheckerUtil.kt
new file mode 100644
index 0000000..5af4f8c
--- /dev/null
+++ b/app/src/main/java/com/atm/bondowowo/utils/BackgroundJWTCheckerUtil.kt
@@ -0,0 +1,50 @@
+package com.atm.bondowowo.utils
+
+import androidx.appcompat.app.AppCompatActivity
+import android.content.Context
+import kotlinx.coroutines.*
+
+class BackgroundJWTChecker {
+
+    private var job: Job? = null
+
+    interface Callback {
+        fun onTokenVerified()
+        fun onTokenInvalid()
+        fun onNetworkError()
+    }
+
+    @OptIn(DelicateCoroutinesApi::class)
+    fun startChecking(context: Context, callback: Callback) {
+        job = GlobalScope.launch(Dispatchers.IO) {
+            while (isActive) {
+                val sharedPreferences = context.getSharedPreferences(
+                    "AUTH_PREFS",
+                    AppCompatActivity.MODE_PRIVATE
+                )
+                val token = sharedPreferences.getString("JWT_TOKEN", null)
+                if (token != null) {
+                    verifyToken(token, callback)
+                } else {
+                    callback.onTokenInvalid()
+                }
+                delay(3 * 60 * 1000)
+            }
+        }
+    }
+
+
+    private suspend fun verifyToken(token: String, callback: Callback) {
+        try {
+            val response = NetworkUtils.apiService.verifyToken("Bearer $token")
+            if (response.isSuccessful && response.body() !is String) {
+                callback.onTokenVerified()
+            } else {
+                callback.onTokenInvalid()
+            }
+        } catch (e: Exception) {
+            callback.onNetworkError()
+        }
+    }
+
+}
diff --git a/app/src/main/java/com/atm/bondowowo/utils/NetworkUtils.kt b/app/src/main/java/com/atm/bondowowo/utils/NetworkUtils.kt
new file mode 100644
index 0000000..41395da
--- /dev/null
+++ b/app/src/main/java/com/atm/bondowowo/utils/NetworkUtils.kt
@@ -0,0 +1,16 @@
+package com.atm.bondowowo.utils
+
+// NetworkUtils.kt
+
+import com.atm.bondowowo.data.remote.ApiService
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+
+object NetworkUtils {
+    private val retrofit = Retrofit.Builder()
+        .baseUrl("https://pbd-backend-2024.vercel.app/")
+        .addConverterFactory(GsonConverterFactory.create())
+        .build()
+
+    val apiService: ApiService = retrofit.create(ApiService::class.java)
+}
diff --git a/app/src/main/res/color/bottom_nav_icon_color.xml b/app/src/main/res/color/bottom_nav_icon_color.xml
new file mode 100644
index 0000000..ce755c1
--- /dev/null
+++ b/app/src/main/res/color/bottom_nav_icon_color.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/black" android:state_checked="true" />
+    <item android:color="@color/grey" android:state_checked="false" />
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/color/bottom_nav_text_color.xml b/app/src/main/res/color/bottom_nav_text_color.xml
new file mode 100644
index 0000000..ce755c1
--- /dev/null
+++ b/app/src/main/res/color/bottom_nav_text_color.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/black" android:state_checked="true" />
+    <item android:color="@color/grey" android:state_checked="false" />
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_logo.png b/app/src/main/res/drawable/ic_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..ec727bb458122581b1579079bc02db305b2a7492
GIT binary patch
literal 15652
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

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable/ic_scan.png b/app/src/main/res/drawable/ic_scan.png
index 5bc7a45d202c7b5f24ea36464b312bfd8d1eb3d1..cc17501d3eeb34b3eaf3cbd12d48561aa0145290 100644
GIT binary patch
delta 812
zcmV+{1JnG<1knZ|iBL{Q4GJ0x0000DNk~Le0000U0000U2nGNE06Q?QqLCpqe*)%7
zL_t(|0qvJdPZLoT$N%Sc(6SLEVIeVs3865QhcTfKCGZhgxFQ-|xNxa_0NeTnU~OFM
z#zfud!UcwB!5A>m7K}zJh=z@gaUqZ1<Cy|&XIhI57B>8nxpU{<GxvXI&Y8LA5(L#A
zxXXkP7`1S~n);BK8bdjFeVwG$e+&q2TRY(^X*|^N=?8`~1NRw-h-iwL$3c|NsUjuH
zUr;W(dV^^*>TD)W9wv^UE%1}5J+LYY2JdWM#`4@cDv9Sx0~tDIRh1m)<%yRnE^4tn
zxelfUsnr^PH8Ooy<>fSIuQlFaDY}AEv;<mVus>5L@g}D~BR)HBvmws7f3m2s@&?1=
z?~tw0g}3r%dQbwYq9=0d&Na9|W-y}TQ(>oVp|C_`MwAg_@YCENc#Q*K(2xXUU-lMK
z0}@OjwDdf~huQabVa9J6G=JW8yMu^mJQ_wh#3o0j9L-L|^ouxkL8-HOvrAce63uBp
zT<HxQ5v=(hs%XS;zJiLge;c4Hg+4ai^Sre+Ayb>hp`n+|=(2=x!f|2!t6#~v6-Nkx
zqK160DcC>ciX#Dc1}7XJt^OtnxFpQrbsQEmc#YbFb1(yS&MsA8Y@kWX3$g$=<IrfY
zgi<#&cNWTY1p2Ve$paVp|3zExIa%B56<L{u!U&ECQag_cJJH=me}Yhx>pJxb*tXWu
zo02^=?zd{@7f4J$FEyw#{dc7F?O#h0(7#t*u^BR|3s<Mbu~qi^Bg7Pv8*gQ2O6Zo<
zr=&1L4N6YcYinZ;7jt9rWN$GV=4Rg`xbu>|U+#Gvfc%keK=H-QMLMlvoL<1f#E)XO
z#@<w21w9{U)}&lRe>o(kl2RuB#nk$oQsU1JcrG=d(pVAA<dNDMLH13uL=4Mge-}?K
zIc-^Q4I=UG8_L1@2`L(upv~KhS-CEESo<?^NytEKdPIV$MuO?K^!D3TB?Hw)z0}GR
quA)ZS01Ut}SZ03)9+K>J_z!9P4E^-_I6?pb002ovPDHLk0$_qz?sSU)

delta 546
zcmV+-0^R-52Fe5>iBL{Q4GJ0x0000DNk~Le0000o0000o2nGNE03JVxv5_G(e*xb~
zL_t(|0qvSSO9Md=hF?EWk%)!%2DP`cu=0wO78W*kb|Qk7A_P)vA!;F7+KCAMfLH{v
zv#_udqS0PRG&X`?Gu+8-F5a!KXeMMHcwsI#+1*Lzc5m($P?SHRE#`BNG*22Qbs(7v
zX_vGIH<n1tq;`v6l~g3{kWTOof3l?aAF2#@9v%A2+8WI`G|D=JJ9)=GJ+qN$Y8{iN
z1N(-wLb^vX52OqHj!DF)`6nsT7HK#*J|NA;IbR}-cnb2EK{&pmc_Mm&r40KC@-VZb
zW)iZ^6itH$A`J~h8X8E0c#g5_$iZK1?nvE`M?a|qe~cS8=b_*WQt2h7f1xN!YZ5JH
zc*a_V%&FIei@8nGZJfgy+{(^Is9+8}y0X8ZdFV6`qN$Z8%|Sl=kL)8MwG>5ZA;w4p
zkPDX>6E-I<R(NVFL1s<T1Hb6wG3JsSuMn=B)~FkRhj4r)^F(xI?=o!Z_ggjSQxs`v
zAkxr4q!A6|)vyO4k3Pe$c$z0VBaY{!k-%Pu|9rKIWZp=paEE_PzAdudN$?N5W*lE9
zIeT!cpYw3%$g$6itznl90~NSacIdBe!$91-ZH{)4G>Y0cy<fqp#qYnj;RbINS%5vY
k`1<A4=dB_ID9Zov0r@o8pmxTXt^fc407*qoM6N<$f=>MNCjbBd

diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
new file mode 100644
index 0000000..f4c3510
--- /dev/null
+++ b/app/src/main/res/layout/activity_login.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="23dp">
+
+    <ImageView
+        android:id="@+id/ivLogo"
+        android:layout_width="350dp"
+        android:layout_height="150dp"
+        android:layout_marginTop="80dp"
+        android:src="@drawable/ic_logo"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0.466"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        android:contentDescription="Logo" />
+
+    <EditText
+        android:id="@+id/etUsername"
+        android:layout_width="0dp"
+        android:layout_height="60dp"
+        android:layout_marginTop="84dp"
+        android:hint="Enter your email"
+        android:inputType="text"
+        android:background="@color/textfield"
+        android:paddingStart="20dp"
+        android:paddingEnd="20dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0.0"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/ivLogo"
+        android:autofillHints="emailAddress" />
+
+    <EditText
+        android:id="@+id/etPassword"
+        android:layout_width="0dp"
+        android:layout_height="75dp"
+        android:layout_marginTop="16dp"
+        android:hint="Enter your password"
+        android:inputType="textPassword"
+        android:background="@color/textfield"
+        android:paddingStart="20dp"
+        android:paddingEnd="20dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/etUsername"
+        android:autofillHints="password" />
+
+    <Button
+        android:id="@+id/btnLogin"
+        android:layout_width="0dp"
+        android:layout_height="70dp"
+        android:layout_marginTop="104dp"
+        android:backgroundTint="@color/primary1"
+
+        android:text="Login"
+        android:textAllCaps="false"
+        android:textColor="#FFFFFF"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0.0"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/etPassword" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/bottom_navigation_layout.xml b/app/src/main/res/layout/bottom_navigation_layout.xml
index c31cae3..ea6f4c7 100644
--- a/app/src/main/res/layout/bottom_navigation_layout.xml
+++ b/app/src/main/res/layout/bottom_navigation_layout.xml
@@ -3,5 +3,8 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/bottomNavigation"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    app:menu="@menu/bottom_navigation_menu" />
\ No newline at end of file
+    android:layout_height="70dp"
+    android:background="@color/white"
+    app:itemIconTint="@color/bottom_nav_icon_color"
+    app:itemTextColor="@color/bottom_nav_text_color"
+    app:menu="@menu/bottom_navigation_menu" />
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index f8c6127..14750cd 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -7,4 +7,10 @@
     <color name="teal_700">#FF018786</color>
     <color name="black">#FF000000</color>
     <color name="white">#FFFFFFFF</color>
+    <color name="grey">#808080</color>
+    <color name="primary1">#012B39</color>
+    <color name="primary2">#1F7A8C</color>
+    <color name="primary3">#C0DBF8</color>
+    <color name="textfield">#F7F8F9</color>
+
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..9c62daf
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
+    </style>
+
+    <style name="AppTheme.NoActionBar">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+        <item name="colorPrimary">@color/white</item>
+        <item name="colorPrimaryDark">@color/primary1</item>
+        <item name="colorAccent">@color/primary2</item>
+    </style>
+</resources>
\ No newline at end of file
-- 
GitLab