diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2df39f1240544c6d3460e77341b980cf2048d9c4..7d760a5e0cb43c980fe1c071a02760b50157b7ba 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -41,13 +41,29 @@ dependencies {
     implementation("androidx.appcompat:appcompat:1.5.1")
     implementation("com.google.android.material:material:1.9.0")
     implementation("androidx.constraintlayout:constraintlayout:2.1.4")
+
     implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.5.1")
     implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1")
+
     implementation("androidx.navigation:navigation-fragment-ktx:2.5.3")
     implementation("androidx.navigation:navigation-ui-ktx:2.5.3")
+
     implementation("androidx.legacy:legacy-support-v4:1.0.0")
+
     implementation("androidx.fragment:fragment-ktx:1.5.7")
     implementation("androidx.annotation:annotation:1.6.0")
+
+    implementation("com.squareup.retrofit2:retrofit:2.9.0")
+
+    implementation(platform("com.squareup.okhttp3:okhttp-bom:4.12.0"))
+    implementation("com.squareup.okhttp3:okhttp")
+    implementation("com.squareup.okhttp3:logging-interceptor")
+
+    implementation("com.squareup.moshi:moshi:1.15.0")
+    implementation("com.squareup.moshi:moshi-kotlin:1.15.0")
+    implementation("com.squareup.retrofit2:converter-moshi:2.9.0")
+    implementation("androidx.preference:preference:1.2.1")
+
     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 4190e448b161c2f9bcf48d3b2a49d372657c9b1a..d03d4fa9d491bbdeb66240931f2e94074a13a73e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,8 @@
 <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:allowBackup="true"
         android:dataExtractionRules="@xml/data_extraction_rules"
@@ -13,15 +15,19 @@
         android:theme="@style/Theme.BondoYap"
         tools:targetApi="31">
         <activity
-            android:name=".MainActivity"
-            android:exported="true"
-            android:label="@string/app_name">
+            android:name=".ui.login.LoginActivity"
+            android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <activity
+            android:name=".MainActivity"
+            android:exported="true">
+        </activity>
+
     </application>
 
 </manifest>
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ApiClient.kt b/app/src/main/java/com/example/bondoyap/ApiClient.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d1858bc3d5c3c4d5ec7b2a3de8f17f3427e5f6eb
--- /dev/null
+++ b/app/src/main/java/com/example/bondoyap/ApiClient.kt
@@ -0,0 +1,41 @@
+package com.example.bondoyap
+
+import retrofit2.Call
+import retrofit2.http.Body
+import retrofit2.http.POST
+
+
+object Constants {
+    const val BASE_URL: String = "https://pbd-backend-2024.vercel.app/api/"
+    const val SHARED_PREFS_NAME = "Prefs"
+}
+
+interface ApiClient{
+    @POST("auth/login")
+    fun login(
+        @Body loginRequest: LoginRequest
+    ): Call<LoginResponse>
+
+    @POST("auth/token")
+    fun verifyToken(
+    ): Call<TokenResponse>
+
+    @POST("bill/upload")
+    fun uploadPicture(
+    )
+}
+
+data class LoginRequest(
+    val email: String,
+    val password: String
+)
+
+data class LoginResponse(
+    val token: String
+)
+
+data class TokenResponse(
+    val nim: String,
+    val iat: Number,
+    val exp: Number
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/MainActivity.kt b/app/src/main/java/com/example/bondoyap/MainActivity.kt
index 1517b69c822338dbbd87d5d5c06398ab414e484b..7002b983d3102e2c405b8e123671fa18da86b984 100644
--- a/app/src/main/java/com/example/bondoyap/MainActivity.kt
+++ b/app/src/main/java/com/example/bondoyap/MainActivity.kt
@@ -1,6 +1,7 @@
 package com.example.bondoyap
 
 import android.content.Context
+import android.content.Intent
 import android.content.SharedPreferences
 import android.os.Bundle
 import com.google.android.material.bottomnavigation.BottomNavigationView
@@ -9,17 +10,25 @@ import androidx.navigation.findNavController
 import androidx.navigation.ui.AppBarConfiguration
 import androidx.navigation.ui.setupActionBarWithNavController
 import androidx.navigation.ui.setupWithNavController
+import com.example.bondoyap.Constants.SHARED_PREFS_NAME
 import com.example.bondoyap.databinding.ActivityMainBinding
+import com.example.bondoyap.ui.login.LoginActivity
 
 class MainActivity : AppCompatActivity() {
 
     private lateinit var binding: ActivityMainBinding
     private lateinit var sharedPreferences: SharedPreferences
 
-
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
 
+        sharedPreferences = getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
+
+        if (!isLoggedIn()) {
+            val intent = Intent(this, LoginActivity::class.java)
+            startActivity(intent)
+            finish()
+        }
         binding = ActivityMainBinding.inflate(layoutInflater)
         setContentView(binding.root)
 
@@ -27,29 +36,14 @@ class MainActivity : AppCompatActivity() {
 
         val navController = findNavController(R.id.nav_host_fragment_activity_main)
 
-        sharedPreferences = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
-
-        if (!isLoggedIn()) {
-            navController.navigate(R.id.navigation_login)
-        }
         val appBarConfiguration = AppBarConfiguration(setOf(
                 R.id.navigation_settings, R.id.navigation_transactions, R.id.navigation_scanner,
-                R.id.navigation_graph, R.id.navigation_login))
+                R.id.navigation_graph))
 
         setupActionBarWithNavController(navController, appBarConfiguration)
 
         navView.setupWithNavController(navController)
-
-        navController.addOnDestinationChangedListener { _, destination, _ ->
-            // Disable bottom navigation when on the login screen
-            if (destination.id == R.id.navigation_login) {
-                navView.visibility = BottomNavigationView.GONE
-            } else {
-                navView.visibility = BottomNavigationView.VISIBLE
-            }
-        }
     }
-
     private fun isLoggedIn(): Boolean {
         return sharedPreferences.getBoolean("isLoggedIn", false)
     }
diff --git a/app/src/main/java/com/example/bondoyap/ui/login/LoggedInUserView.kt b/app/src/main/java/com/example/bondoyap/ui/login/LoggedInUserView.kt
index 127052153ac667ee17007bf12a87861dfd93308f..106a5999d4bc31f2babf13d5b526b17ff648626e 100644
--- a/app/src/main/java/com/example/bondoyap/ui/login/LoggedInUserView.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/login/LoggedInUserView.kt
@@ -4,6 +4,6 @@ package com.example.bondoyap.ui.login
  * User details post authentication that is exposed to the UI
  */
 data class LoggedInUserView(
-    val displayName: String
+    val email: String
     //... other data fields that may be accessible to the UI
 )
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ui/login/LoginActivity.kt b/app/src/main/java/com/example/bondoyap/ui/login/LoginActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..dc379ed4e8b62e97c645bf7be327eab0c35480ad
--- /dev/null
+++ b/app/src/main/java/com/example/bondoyap/ui/login/LoginActivity.kt
@@ -0,0 +1,157 @@
+package com.example.bondoyap.ui.login
+
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProvider
+import androidx.annotation.StringRes
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
+import android.view.View
+import android.view.inputmethod.EditorInfo
+import android.widget.EditText
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import com.example.bondoyap.Constants.SHARED_PREFS_NAME
+import com.example.bondoyap.MainActivity
+import com.example.bondoyap.R
+import com.example.bondoyap.databinding.ActivityLoginBinding
+
+class LoginActivity : AppCompatActivity() {
+
+    private lateinit var loginViewModel: LoginViewModel
+    private lateinit var binding: ActivityLoginBinding
+    private lateinit var sharedPreferences: SharedPreferences
+
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        sharedPreferences = getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
+
+
+
+        if (isLoggedIn()) {
+            navigateToMainActivity()
+            finish()
+        } else {
+            binding = ActivityLoginBinding.inflate(layoutInflater)
+            setContentView(binding.root)
+
+            val emailEditText = binding.email
+            val passwordEditText = binding.password
+            val loginButton = binding.login
+            val loadingProgressBar = binding.loading
+
+            val factory = LoginViewModelFactory(this)
+            loginViewModel = ViewModelProvider(this, factory)[LoginViewModel::class.java]
+
+            // skip login
+
+            loginViewModel.loginFormState.observe(this@LoginActivity, Observer {
+                val loginState = it ?: return@Observer
+
+                // disable login button unless both username / password is valid
+                loginButton.isEnabled = loginState.isDataValid
+
+                if (loginState.emailError != null) {
+                    emailEditText.error = getString(loginState.emailError)
+                }
+                if (loginState.passwordError != null) {
+                    passwordEditText.error = getString(loginState.passwordError)
+                }
+            })
+
+            loginViewModel.loginResult.observe(this@LoginActivity, Observer {
+                val loginResult = it ?: return@Observer
+
+                loadingProgressBar.visibility = View.GONE
+                if (loginResult.error != null) {
+                    showLoginFailed(loginResult.error)
+                }
+                if (loginResult.success != null) {
+                    updateUiWithUser(loginResult.success)
+                    setResult(RESULT_OK)
+                    finish()
+                }
+            })
+
+            emailEditText.afterTextChanged {
+                loginViewModel.loginDataChanged(
+                    emailEditText.text.toString(),
+                    passwordEditText.text.toString()
+                )
+            }
+
+            passwordEditText.apply {
+                afterTextChanged {
+                    loginViewModel.loginDataChanged(
+                        emailEditText.text.toString(),
+                        passwordEditText.text.toString()
+                    )
+                }
+
+                setOnEditorActionListener { _, actionId, _ ->
+                    when (actionId) {
+                        EditorInfo.IME_ACTION_DONE ->
+                            loginViewModel.login(
+                                emailEditText.text.toString(),
+                                passwordEditText.text.toString()
+                            )
+                    }
+                    false
+                }
+
+                loginButton.setOnClickListener {
+                    loadingProgressBar.visibility = View.VISIBLE
+                    loginViewModel.login(
+                        emailEditText.text.toString(),
+                        passwordEditText.text.toString()
+                    )
+                }
+            }
+        }
+    }
+
+    private fun updateUiWithUser(model: LoggedInUserView) {
+        val welcome = getString(R.string.welcome) + "\n" + model.email
+        // TODO : initiate successful logged in experience
+        Toast.makeText(
+            applicationContext,
+            welcome,
+            Toast.LENGTH_SHORT
+        ).show()
+        navigateToMainActivity()
+    }
+
+    private fun showLoginFailed(@StringRes errorString: Int) {
+        Toast.makeText(applicationContext, errorString, Toast.LENGTH_SHORT).show()
+    }
+
+    private fun navigateToMainActivity() {
+        val intent = Intent(this, MainActivity::class.java)
+        startActivity(intent)
+        finish()
+    }
+
+    private fun isLoggedIn(): Boolean {
+        return sharedPreferences.getBoolean("isLoggedIn", false)
+    }
+}
+
+/**
+ * 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) {}
+    })
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ui/login/LoginFragment.kt b/app/src/main/java/com/example/bondoyap/ui/login/LoginFragment.kt
deleted file mode 100644
index 2fa73d7b619d82ec9bcd99dd44731ea250e8830a..0000000000000000000000000000000000000000
--- a/app/src/main/java/com/example/bondoyap/ui/login/LoginFragment.kt
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.example.bondoyap.ui.login
-
-import androidx.lifecycle.Observer
-import androidx.lifecycle.ViewModelProvider
-import androidx.annotation.StringRes
-import androidx.fragment.app.Fragment
-import android.os.Bundle
-import android.text.Editable
-import android.text.TextWatcher
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.view.inputmethod.EditorInfo
-import android.widget.Toast
-import androidx.navigation.fragment.findNavController
-import com.example.bondoyap.R
-import com.example.bondoyap.databinding.FragmentLoginBinding
-
-class LoginFragment : Fragment() {
-
-    private lateinit var loginViewModel: LoginViewModel
-    private var _binding: FragmentLoginBinding? = null
-
-    // This property is only valid between onCreateView and
-    // onDestroyView.
-    private val binding get() = _binding!!
-
-    override fun onCreateView(
-        inflater: LayoutInflater,
-        container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View? {
-
-        _binding = FragmentLoginBinding.inflate(inflater, container, false)
-        return binding.root
-
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-        loginViewModel = ViewModelProvider(this, LoginViewModelFactory())
-            .get(LoginViewModel::class.java)
-
-        val emailEditText = binding.email
-        val passwordEditText = binding.password
-        val loginButton = binding.login
-        val loadingProgressBar = binding.loading
-
-        loginViewModel.loginFormState.observe(viewLifecycleOwner,
-            Observer { loginFormState ->
-                if (loginFormState == null) {
-                    return@Observer
-                }
-                loginButton.isEnabled = loginFormState.isDataValid
-                loginFormState.emailError?.let {
-                    emailEditText.error = getString(it)
-                }
-                loginFormState.passwordError?.let {
-                    passwordEditText.error = getString(it)
-                }
-            })
-
-        loginViewModel.loginResult.observe(viewLifecycleOwner,
-            Observer { loginResult ->
-                loginResult ?: return@Observer
-                loadingProgressBar.visibility = View.GONE
-                loginResult.error?.let {
-                    showLoginFailed(it)
-                }
-                loginResult.success?.let {
-                    updateUiWithUser(it)
-                    requireActivity().actionBar?.setDisplayHomeAsUpEnabled(false)
-                    navigateToTransactionFragment()
-                }
-            })
-
-        val afterTextChangedListener = object : TextWatcher {
-            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
-                // ignore
-            }
-
-            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
-                // ignore
-            }
-
-            override fun afterTextChanged(s: Editable) {
-                loginViewModel.loginDataChanged(
-                    emailEditText.text.toString(),
-                    passwordEditText.text.toString()
-                )
-            }
-        }
-        emailEditText.addTextChangedListener(afterTextChangedListener)
-        passwordEditText.addTextChangedListener(afterTextChangedListener)
-        passwordEditText.setOnEditorActionListener { _, actionId, _ ->
-            if (actionId == EditorInfo.IME_ACTION_DONE) {
-                loginViewModel.login(
-                    emailEditText.text.toString(),
-                    passwordEditText.text.toString()
-                )
-            }
-            false
-        }
-
-        loginButton.setOnClickListener {
-            loadingProgressBar.visibility = View.VISIBLE
-            loginViewModel.login(
-                emailEditText.text.toString(),
-                passwordEditText.text.toString()
-            )
-        }
-    }
-
-    private fun updateUiWithUser(model: LoggedInUserView) {
-        val welcome = getString(R.string.welcome) + model.displayName
-        // TODO : initiate successful logged in experience
-        val appContext = context?.applicationContext ?: return
-        Toast.makeText(appContext, welcome, Toast.LENGTH_LONG).show()
-    }
-
-    private fun showLoginFailed(@StringRes errorString: Int) {
-        val appContext = context?.applicationContext ?: return
-        Toast.makeText(appContext, errorString, Toast.LENGTH_LONG).show()
-    }
-
-    override fun onDestroyView() {
-        super.onDestroyView()
-        _binding = null
-    }
-
-    private fun navigateToTransactionFragment() {
-        findNavController().navigate(R.id.navigation_transactions)
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ui/login/LoginViewModel.kt b/app/src/main/java/com/example/bondoyap/ui/login/LoginViewModel.kt
index 11feb87bc1487a0f9624658311d6fe0bfc11b1c6..fedbf7d9cd2c6686bf8dc47cdf25d6cf84422a40 100644
--- a/app/src/main/java/com/example/bondoyap/ui/login/LoginViewModel.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/login/LoginViewModel.kt
@@ -4,9 +4,11 @@ import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import android.util.Patterns
+import androidx.lifecycle.viewModelScope
 import com.example.bondoyap.R
 import com.example.bondoyap.ui.login.data.LoginRepository
 import com.example.bondoyap.ui.login.data.Result
+import kotlinx.coroutines.launch
 
 class LoginViewModel(private val loginRepository: LoginRepository) : ViewModel() {
 
@@ -17,13 +19,14 @@ class LoginViewModel(private val loginRepository: LoginRepository) : ViewModel()
     val loginResult: LiveData<LoginResult> = _loginResult
 
     fun login(email: String, password: String) {
-        val result = loginRepository.login(email, password)
-
-        if (result is Result.Success) {
-            _loginResult.value =
-                LoginResult(success = LoggedInUserView(displayName = result.data.displayName))
-        } else {
-            _loginResult.value = LoginResult(error = R.string.login_failed)
+        viewModelScope.launch {
+            val result = loginRepository.login(email, password)
+            if (result is Result.Success) {
+                _loginResult.value =
+                    LoginResult(success = LoggedInUserView(email = result.data.email))
+            } else {
+                _loginResult.value = LoginResult(error = R.string.login_failed)
+            }
         }
     }
 
diff --git a/app/src/main/java/com/example/bondoyap/ui/login/LoginViewModelFactory.kt b/app/src/main/java/com/example/bondoyap/ui/login/LoginViewModelFactory.kt
index de741ade55806d4f3612cf2ef705e3d13874dc9d..b0e9039da4e6694319d086bdc6fca269138c6c17 100644
--- a/app/src/main/java/com/example/bondoyap/ui/login/LoginViewModelFactory.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/login/LoginViewModelFactory.kt
@@ -1,22 +1,21 @@
 package com.example.bondoyap.ui.login
 
+import android.content.Context
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import com.example.bondoyap.ui.login.data.LoginDataSource
 import com.example.bondoyap.ui.login.data.LoginRepository
 
-/**
- * ViewModel provider factory to instantiate LoginViewModel.
- * Required given LoginViewModel has a non-empty constructor
- */
-class LoginViewModelFactory : ViewModelProvider.Factory {
+class LoginViewModelFactory(private val context: Context) : ViewModelProvider.Factory {
 
     @Suppress("UNCHECKED_CAST")
     override fun <T : ViewModel> create(modelClass: Class<T>): T {
         if (modelClass.isAssignableFrom(LoginViewModel::class.java)) {
             return LoginViewModel(
                 loginRepository = LoginRepository(
-                    dataSource = LoginDataSource()
+                    dataSource = LoginDataSource(),
+                    context = context
+
                 )
             ) as T
         }
diff --git a/app/src/main/java/com/example/bondoyap/ui/login/data/LoginDataSource.kt b/app/src/main/java/com/example/bondoyap/ui/login/data/LoginDataSource.kt
index 3e221c0a19f9dc26f316fee64c9cfae5734e84f1..cf54c3009a664f4756b194be6d01189ef6d85582 100644
--- a/app/src/main/java/com/example/bondoyap/ui/login/data/LoginDataSource.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/login/data/LoginDataSource.kt
@@ -1,6 +1,15 @@
 package com.example.bondoyap.ui.login.data
 
+import com.example.bondoyap.ApiClient
+import com.example.bondoyap.Constants
+import com.example.bondoyap.LoginRequest
 import com.example.bondoyap.ui.login.data.model.LoggedInUser
+import com.squareup.moshi.Moshi
+import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import retrofit2.Retrofit
+import retrofit2.converter.moshi.MoshiConverterFactory
 import java.io.IOException
 
 /**
@@ -8,17 +17,49 @@ import java.io.IOException
  */
 class LoginDataSource {
 
-    fun login(email: String, password: String): Result<LoggedInUser> {
+    suspend fun login(email: String, password: String): Result<LoggedInUser> {
         return try {
-            // TODO: handle loggedInUser authentication
-            val fakeUser = LoggedInUser(java.util.UUID.randomUUID().toString(), "Jane Doe")
-            Result.Success(fakeUser)
+
+            val token = postLogin(email, password)
+
+            val parts = email.split("@")
+            val nim = parts[0]
+
+            val user = LoggedInUser(nim, email, token)
+
+            Result.Success(user)
         } catch (e: Throwable) {
             Result.Error(IOException("Error logging in", e))
         }
     }
 
-    fun logout() {
-        // TODO: revoke authentication
+    private suspend fun postLogin(email: String, password: String):String {
+
+        val moshi = Moshi.Builder()
+            .add(KotlinJsonAdapterFactory())
+            .build()
+
+        val api = Retrofit.Builder()
+            .baseUrl(Constants.BASE_URL)
+            .addConverterFactory(MoshiConverterFactory.create(moshi))
+            .build()
+
+        val apiClient = api.create(ApiClient::class.java)
+
+        return withContext(Dispatchers.IO) {
+            try {
+                val loginRequest = LoginRequest(email, password)
+                val response = apiClient.login(loginRequest).execute()
+
+                if (response.isSuccessful) {
+                    val loginResponse = response.body()
+                    loginResponse?.token ?: throw IOException("Token not received")
+                } else {
+                    throw IOException("${response.code()} ${response.message()}")
+                }
+            } catch (e: Exception) {
+                throw IOException("Login failed: ${e.message}")
+            }
+        }
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ui/login/data/LoginRepository.kt b/app/src/main/java/com/example/bondoyap/ui/login/data/LoginRepository.kt
index 840ffe51ce4b5e3a307ad9c7c0442c11d14642ee..bcc2777cdcfc8f2fb2f901308341f767067d0a7b 100644
--- a/app/src/main/java/com/example/bondoyap/ui/login/data/LoginRepository.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/login/data/LoginRepository.kt
@@ -1,34 +1,29 @@
 package com.example.bondoyap.ui.login.data
 
 import com.example.bondoyap.ui.login.data.model.LoggedInUser
+import android.content.Context
+import android.content.SharedPreferences
+import com.squareup.moshi.JsonAdapter
+import com.squareup.moshi.Moshi
+import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
 
 /**
  * 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) {
+class LoginRepository(val dataSource: LoginDataSource, context: Context) {
 
-    // in-memory cache of the loggedInUser object
-    var user: LoggedInUser? = null
-        private set
+    private val sharedPreferences: SharedPreferences = context.getSharedPreferences("Prefs", Context.MODE_PRIVATE)
+    private val editor: SharedPreferences.Editor = sharedPreferences.edit()
 
-    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
-    }
+    private val moshi: Moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
+    private val userAdapter: JsonAdapter<LoggedInUser> = moshi.adapter(LoggedInUser::class.java)
 
-    fun logout() {
-        user = null
-        dataSource.logout()
-    }
+    val isLoggedIn: Boolean
+        get() = sharedPreferences.getBoolean("isLoggedIn", false)
 
-    fun login(email: String, password: String): Result<LoggedInUser> {
-        // handle login
+    suspend fun login(email: String, password: String): Result<LoggedInUser> {
         val result = dataSource.login(email, password)
 
         if (result is Result.Success) {
@@ -38,8 +33,22 @@ class LoginRepository(val dataSource: LoginDataSource) {
         return result
     }
 
+    fun logout(){
+        editor.clear()
+        editor.apply()
+    }
+
+    fun getUser(): LoggedInUser? {
+        val userJson = sharedPreferences.getString("loggedInUser", null)
+        return userJson?.let {
+            userAdapter.fromJson(it)
+        }
+    }
+
     private fun setLoggedInUser(loggedInUser: LoggedInUser) {
-        this.user = loggedInUser
+        val userJson = userAdapter.toJson(loggedInUser)
+        editor.putString("loggedInUser", userJson).apply()
+        editor.putBoolean("isLoggedIn", true).apply()
         // 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/app/src/main/java/com/example/bondoyap/ui/login/data/model/LoggedInUser.kt b/app/src/main/java/com/example/bondoyap/ui/login/data/model/LoggedInUser.kt
index 10a9aa93f64d280b3861bd282307ab0213e011df..78d7e033176d0673dfb6016ebacf1d2c54c256e0 100644
--- a/app/src/main/java/com/example/bondoyap/ui/login/data/model/LoggedInUser.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/login/data/model/LoggedInUser.kt
@@ -5,5 +5,6 @@ package com.example.bondoyap.ui.login.data.model
  */
 data class LoggedInUser(
     val userId: String,
-    val displayName: String
+    val email: String,
+    val token: String
 )
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt b/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt
index 9433c1071c0e9bc4cd8fcac9326e5c7b3acc43cc..8018684cc1dabee268479d5c16e1e2029ee1dba6 100644
--- a/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt
@@ -1,38 +1,78 @@
 package com.example.bondoyap.ui.settings
 
+import android.content.Intent
 import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
-import android.widget.TextView
+import android.widget.Toast
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.ViewModelProvider
 import com.example.bondoyap.databinding.FragmentSettingsBinding
+import com.example.bondoyap.ui.login.LoginActivity
 
 class SettingsFragment : Fragment() {
 
     private var _binding: FragmentSettingsBinding? = null
-
-    // This property is only valid between onCreateView and
-    // onDestroyView.
     private val binding get() = _binding!!
+    private lateinit var settingsViewModel: SettingsViewModel
 
     override fun onCreateView(
-            inflater: LayoutInflater,
-            container: ViewGroup?,
-            savedInstanceState: Bundle?
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
     ): View {
-        val settingsViewModel =
-                ViewModelProvider(this).get(SettingsViewModel::class.java)
-
         _binding = FragmentSettingsBinding.inflate(inflater, container, false)
-        val root: View = binding.root
+        return binding.root
+    }
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        val factory = context?.let { SettingsViewModelFactory(it) }
+        if (factory != null) {
+            settingsViewModel = ViewModelProvider(this, factory)[SettingsViewModel::class.java]
+        } else {
+            throw IllegalStateException("Context is null. Cannot create SettingsViewModelFactory.")
+        }
+        val textView = binding.textSettings
+        val logoutButton = binding.logoutButton
+        val randomButton = binding.randomTransactions
+        val saveButton = binding.saveTransactions
+        val sendButton = binding.sendTransactions
+
+        settingsViewModel.getUser()?.let { user ->
+            val loggedInUserText = "Masuk dengan akun:\n ${user.email}"
+            textView.text = loggedInUserText
+        }
+        val appContext = context?.applicationContext
+
+        logoutButton.setOnClickListener {
+            settingsViewModel.getUser()
+            settingsViewModel.logout()
+//            findNavController().navigate(R.id.navigation_login)
 
-        val textView: TextView = binding.textSettings
-        settingsViewModel.text.observe(viewLifecycleOwner) {
-            textView.text = it
+            val activity = requireActivity()
+            val intent = Intent(activity, LoginActivity::class.java)
+            Toast.makeText(appContext, "Logout Sukses!", Toast.LENGTH_SHORT).show()
+            activity.startActivity(intent)
+            activity.finish()
         }
-        return root
+
+        randomButton.setOnClickListener {
+            Toast.makeText(appContext, "Membuat transaksi random ...", Toast.LENGTH_SHORT).show()
+            //todo
+        }
+
+        saveButton.setOnClickListener{
+            Toast.makeText(appContext, "Menyimpan transaksi...", Toast.LENGTH_SHORT).show()
+            //todo
+        }
+
+        sendButton.setOnClickListener{
+            Toast.makeText(appContext, "Mengirimkan transaksi ...", Toast.LENGTH_SHORT).show()
+            //todo
+        }
+
     }
 
     override fun onDestroyView() {
diff --git a/app/src/main/java/com/example/bondoyap/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/example/bondoyap/ui/settings/SettingsViewModel.kt
index 02f1e625446ea7b7ced397b4d01dea34bc08185c..6038adcbe40a12ade0663f68d32d295401f2690a 100644
--- a/app/src/main/java/com/example/bondoyap/ui/settings/SettingsViewModel.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/settings/SettingsViewModel.kt
@@ -3,11 +3,21 @@ package com.example.bondoyap.ui.settings
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
+import com.example.bondoyap.ui.login.data.LoginRepository
+import com.example.bondoyap.ui.login.data.model.LoggedInUser
 
-class SettingsViewModel : ViewModel() {
+class SettingsViewModel(private val loginRepository: LoginRepository) : ViewModel() {
 
     private val _text = MutableLiveData<String>().apply {
         value = "This is Settings Fragment"
     }
     val text: LiveData<String> = _text
+
+    fun logout(){
+        loginRepository.logout()
+    }
+
+    fun getUser(): LoggedInUser? {
+        return loginRepository.getUser()
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ui/settings/SettingsViewModelFactory.kt b/app/src/main/java/com/example/bondoyap/ui/settings/SettingsViewModelFactory.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b3b7f9747a79b29fc94a46c775d0ee604a767c45
--- /dev/null
+++ b/app/src/main/java/com/example/bondoyap/ui/settings/SettingsViewModelFactory.kt
@@ -0,0 +1,23 @@
+package com.example.bondoyap.ui.settings
+
+import android.content.Context
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.example.bondoyap.ui.login.data.LoginDataSource
+import com.example.bondoyap.ui.login.data.LoginRepository
+
+class SettingsViewModelFactory(private val context: Context) : ViewModelProvider.Factory {
+
+    @Suppress("UNCHECKED_CAST")
+    override fun <T : ViewModel> create(modelClass: Class<T>): T {
+        if (modelClass.isAssignableFrom(SettingsViewModel::class.java)) {
+            return SettingsViewModel(
+                loginRepository = LoginRepository(
+                    dataSource = LoginDataSource(),
+                    context = context
+                )
+            ) as T
+        }
+        throw IllegalArgumentException("Unknown ViewModel class")
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ui/transactions/Transactions.kt b/app/src/main/java/com/example/bondoyap/ui/transactions/Transactions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..152e4636c4a171aecc4e5ee1c76438ab253c8e97
--- /dev/null
+++ b/app/src/main/java/com/example/bondoyap/ui/transactions/Transactions.kt
@@ -0,0 +1,21 @@
+package com.example.bondoyap.ui.transactions
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "transactions")
+data class Transactions(
+    @ColumnInfo(name = "judul")
+    val judul: String,
+
+    @ColumnInfo(name = "nominal")
+    val nominal: Double,
+
+    @ColumnInfo(name = "is_pemasukan")
+    val isPemasukan: Boolean,
+
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = "id")
+    val id: Int = 0
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsDao.kt b/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsDao.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3e38008bd4e23137e0fe1a42b11a3c7a4b97c06e
--- /dev/null
+++ b/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsDao.kt
@@ -0,0 +1,23 @@
+package com.example.bondoyap.ui.transactions
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Query
+import androidx.room.Upsert
+
+@Dao
+interface TransactionsDao {
+
+    @Upsert
+    suspend fun upsertTransaction(transaksi: Transactions)
+
+    @Delete
+    suspend fun deleteTransaction(transaksi: Transactions)
+
+    @Query("SELECT * FROM transactions")
+    fun getTransaction(): LiveData<List<Transactions>>
+
+    @Query("SELECT * FROM transactions WHERE transactions.id == :transactionsId")
+    fun getTransactionById(transactionsId: Int): Transactions
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsDatabase.kt b/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsDatabase.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3eed5518b23481bcfd4f01339fdc67a25b5aeb55
--- /dev/null
+++ b/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsDatabase.kt
@@ -0,0 +1,13 @@
+package com.example.bondoyap.ui.transactions
+
+import androidx.room.Database
+import androidx.room.RoomDatabase
+
+@Database(
+    entities = [Transactions::class],
+    version = 1
+)
+abstract class TransactionsDatabase: RoomDatabase() {
+
+    abstract val dao: TransactionsDao
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsFragment.kt b/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsFragment.kt
index dbce163a4779b3b0d8184a624dd5c233ded521a3..d3ae405e2a6d4269a8a55df39b32bbc1baee418f 100644
--- a/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsFragment.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsFragment.kt
@@ -7,8 +7,11 @@ import android.view.View
 import android.view.ViewGroup
 import android.widget.ArrayAdapter
 import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
 import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.viewModelScope
 import com.example.bondoyap.databinding.FragmentTransactionsBinding
+import kotlinx.coroutines.launch
 
 class TransactionsFragment : Fragment() {
 
@@ -23,9 +26,6 @@ class TransactionsFragment : Fragment() {
             container: ViewGroup?,
             savedInstanceState: Bundle?
     ): View {
-        val transactionsViewModel =
-                ViewModelProvider(this).get(TransactionsViewModel::class.java)
-
         _binding = FragmentTransactionsBinding.inflate(inflater, container, false)
 
         val categories = arrayOf("Pemasukan", "Pengeluaran")
@@ -34,6 +34,20 @@ class TransactionsFragment : Fragment() {
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
         binding.spinnerKategori.adapter = adapter
 
+        binding.buttonSimpan.setOnClickListener {
+            val judul: String = binding.editTextJudul.text.toString()
+            val nominal: Double? = binding.editTextNominal.text.toString().toDoubleOrNull()
+            val isPemasukan: Boolean = binding.spinnerKategori.selectedItemPosition == 0
+
+            viewModel.viewModelScope.launch {
+                viewModel.onSaveButtonClicked(judul, nominal, isPemasukan)
+            }
+
+            binding.editTextJudul.text.clear()
+            binding.editTextNominal.text.clear()
+            binding.spinnerKategori.setSelection(0)
+        }
+
         return binding.root
     }
 
diff --git a/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsViewModel.kt b/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsViewModel.kt
index 1a790c6f8709dc3c2f42d091b860cde6389501c3..123d0ef560874a060b9099916c2a741dcb65ce91 100644
--- a/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsViewModel.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/transactions/TransactionsViewModel.kt
@@ -1,13 +1,31 @@
 package com.example.bondoyap.ui.transactions
 
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.update
 
-class TransactionsViewModel : ViewModel() {
+class TransactionsViewModel(
+    private val dao: TransactionsDao
+): ViewModel() {
+    suspend fun onSaveButtonClicked(
+        judul: String = "",
+        nominal: Double? = 0.0,
+        isPemasukan: Boolean = true
+    ) {
+        if(nominal == null) {
+            return
+        }
+        if(judul.isBlank() || nominal.isNaN()) {
+            return
+        }
 
-    private val _text = MutableLiveData<String>().apply {
-        value = "This is Transactions Fragment"
+        val transaction = Transactions(
+            judul = judul,
+            nominal = nominal,
+            isPemasukan = isPemasukan
+        )
+
+        dao.upsertTransaction(transaction)
     }
-    val text: LiveData<String> = _text
+
 }
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout-w1240dp/activity_login.xml
similarity index 81%
rename from app/src/main/res/layout/fragment_login.xml
rename to app/src/main/res/layout-w1240dp/activity_login.xml
index 3835370f0dd243f7d2448961484710a245cdf4d5..cf194090807d97abade273046c604fba5498297e 100644
--- a/app/src/main/res/layout/fragment_login.xml
+++ b/app/src/main/res/layout-w1240dp/activity_login.xml
@@ -2,21 +2,20 @@
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:paddingLeft="@dimen/fragment_horizontal_margin"
-    android:paddingTop="@dimen/fragment_vertical_margin"
-    android:paddingRight="@dimen/fragment_horizontal_margin"
-    android:paddingBottom="@dimen/fragment_vertical_margin"
-    tools:context=".ui.login.LoginFragment">
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    tools:context=".ui.login.LoginActivity">
 
     <EditText
         android:id="@+id/email"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="24dp"
         android:layout_marginTop="96dp"
-        android:layout_marginEnd="24dp"
         android:autofillHints="@string/prompt_email"
         android:hint="@string/prompt_email"
         android:inputType="textEmailAddress"
@@ -29,9 +28,7 @@
         android:id="@+id/password"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="24dp"
         android:layout_marginTop="8dp"
-        android:layout_marginEnd="24dp"
         android:autofillHints="@string/prompt_password"
         android:hint="@string/prompt_password"
         android:imeActionLabel="@string/action_sign_in_short"
@@ -47,9 +44,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="start"
-        android:layout_marginStart="48dp"
         android:layout_marginTop="16dp"
-        android:layout_marginEnd="48dp"
         android:layout_marginBottom="64dp"
         android:enabled="false"
         android:text="@string/action_sign_in"
@@ -64,9 +59,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
-        android:layout_marginStart="32dp"
         android:layout_marginTop="64dp"
-        android:layout_marginEnd="32dp"
         android:layout_marginBottom="64dp"
         android:visibility="gone"
         app:layout_constraintBottom_toBottomOf="parent"
@@ -74,4 +67,5 @@
         app:layout_constraintStart_toStartOf="@+id/password"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintVertical_bias="0.3" />
+
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout-w936dp/activity_login.xml b/app/src/main/res/layout-w936dp/activity_login.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0b647885c5c88180f2fe880b915c8bf1214a9911
--- /dev/null
+++ b/app/src/main/res/layout-w936dp/activity_login.xml
@@ -0,0 +1,78 @@
+<?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"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    tools:context=".ui.login.LoginActivity">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="840dp"
+        android:layout_height="match_parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent">
+
+        <EditText
+            android:id="@+id/email"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="96dp"
+            android:autofillHints="@string/prompt_email"
+            android:hint="@string/prompt_email"
+            android:inputType="textEmailAddress"
+            android:selectAllOnFocus="true"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <EditText
+            android:id="@+id/password"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:autofillHints="@string/prompt_password"
+            android:hint="@string/prompt_password"
+            android:imeActionLabel="@string/action_sign_in_short"
+            android:imeOptions="actionDone"
+            android:inputType="textPassword"
+            android:selectAllOnFocus="true"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/email" />
+
+        <Button
+            android:id="@+id/login"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start"
+            android:layout_marginTop="16dp"
+            android:layout_marginBottom="64dp"
+            android:enabled="false"
+            android:text="@string/action_sign_in"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/password"
+            app:layout_constraintVertical_bias="0.2" />
+
+        <ProgressBar
+            android:id="@+id/loading"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:layout_marginTop="64dp"
+            android:layout_marginBottom="64dp"
+            android:visibility="gone"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="@+id/password"
+            app:layout_constraintStart_toStartOf="@+id/password"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintVertical_bias="0.3" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cf194090807d97abade273046c604fba5498297e
--- /dev/null
+++ b/app/src/main/res/layout/activity_login.xml
@@ -0,0 +1,71 @@
+<?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"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    tools:context=".ui.login.LoginActivity">
+
+    <EditText
+        android:id="@+id/email"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="96dp"
+        android:autofillHints="@string/prompt_email"
+        android:hint="@string/prompt_email"
+        android:inputType="textEmailAddress"
+        android:selectAllOnFocus="true"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <EditText
+        android:id="@+id/password"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:autofillHints="@string/prompt_password"
+        android:hint="@string/prompt_password"
+        android:imeActionLabel="@string/action_sign_in_short"
+        android:imeOptions="actionDone"
+        android:inputType="textPassword"
+        android:selectAllOnFocus="true"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/email" />
+
+    <Button
+        android:id="@+id/login"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="start"
+        android:layout_marginTop="16dp"
+        android:layout_marginBottom="64dp"
+        android:enabled="false"
+        android:text="@string/action_sign_in"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/password"
+        app:layout_constraintVertical_bias="0.2" />
+
+    <ProgressBar
+        android:id="@+id/loading"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_marginTop="64dp"
+        android:layout_marginBottom="64dp"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="@+id/password"
+        app:layout_constraintStart_toStartOf="@+id/password"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintVertical_bias="0.3" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml
index 5f90bc6adda3319a6073dd79512e10f163e686f2..9689b01e558f04f59984c293faac2e1e771ad55c 100644
--- a/app/src/main/res/layout/fragment_settings.xml
+++ b/app/src/main/res/layout/fragment_settings.xml
@@ -15,8 +15,51 @@
         android:layout_marginEnd="8dp"
         android:textAlignment="center"
         android:textSize="20sp"
-        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <Button
+        android:id="@+id/random_transactions"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/random_transactions"
+        app:layout_constraintTop_toBottomOf="@+id/text_settings"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginTop="16dp"
+        />
+
+    <Button
+        android:id="@+id/save_transactions"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/save_transactions"
+        app:layout_constraintTop_toBottomOf="@+id/random_transactions"
+        app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginTop="16dp"
+        />
+
+    <Button
+        android:id="@+id/send_transactions"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/send_transactions"
+        app:layout_constraintTop_toBottomOf="@+id/save_transactions"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginTop="16dp"
+        />
+
+    <Button
+        android:id="@+id/logout_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/logout"
+        app:layout_constraintTop_toBottomOf="@+id/send_transactions"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
+        app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginTop="16dp"/>
+
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml
index efa5003d6cdb2778fc6190e8d2ef6edc22bf9d79..4412b02a53bd550175ae936468dceed611158b3d 100644
--- a/app/src/main/res/navigation/mobile_navigation.xml
+++ b/app/src/main/res/navigation/mobile_navigation.xml
@@ -5,11 +5,11 @@
     android:id="@+id/mobile_navigation"
     app:startDestination="@+id/navigation_transactions">
 
-    <fragment
-        android:id="@+id/navigation_login"
-        android:name="com.example.bondoyap.ui.login.LoginFragment"
-        android:label="@string/title_login"
-        tools:layout="@layout/fragment_transactions" />
+<!--    <fragment-->
+<!--        android:id="@+id/navigation_login"-->
+<!--        android:name="com.example.bondoyap.ui.login.LoginActivity"-->
+<!--        android:label="@string/title_login"-->
+<!--        tools:layout="@layout/fragment_transactions" />-->
 
     <fragment
         android:id="@+id/navigation_transactions"
diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5f681ae11694396c167bee5b520246962495c34d
--- /dev/null
+++ b/app/src/main/res/values-land/dimens.xml
@@ -0,0 +1,3 @@
+<resources>
+    <dimen name="activity_horizontal_margin">48dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/app/src/main/res/values-w1240dp/dimens.xml b/app/src/main/res/values-w1240dp/dimens.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7e065116699dfedbfa503eb28fe432bf1447dd73
--- /dev/null
+++ b/app/src/main/res/values-w1240dp/dimens.xml
@@ -0,0 +1,3 @@
+<resources>
+    <dimen name="activity_horizontal_margin">200dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5f681ae11694396c167bee5b520246962495c34d
--- /dev/null
+++ b/app/src/main/res/values-w600dp/dimens.xml
@@ -0,0 +1,3 @@
+<resources>
+    <dimen name="activity_horizontal_margin">48dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index f8c6127d327620c93d2b2d00342a68e97b98a48d..4ee6d8ffce1e4f269fc67238f23da6eb0a022be2 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -7,4 +7,5 @@
     <color name="teal_700">#FF018786</color>
     <color name="black">#FF000000</color>
     <color name="white">#FFFFFFFF</color>
+    <color name="red">#FF0000</color>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a238740602ff63a2bf9ab121221d1f8573851554..4522aea76e6192deae69830c132b1819180725df 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -4,17 +4,24 @@
     <string name="title_scanner">Scanner</string>
     <string name="title_graph">Graph</string>
     <string name="title_settings">Pengaturan</string>
-    <!-- Strings related to login -->
+
     <string name="title_login">Login</string>
     <string name="prompt_email">Email</string>
     <string name="prompt_password">Password</string>
     <string name="action_sign_in">Sign in</string>
     <string name="action_sign_in_short">Sign in</string>
-    <string name="welcome">"Welcome!"</string>
-    <string name="invalid_username">Not a valid email</string>
-    <string name="invalid_password">Password must be >5 characters</string>
-    <string name="login_failed">"Login failed"</string>
-    <!-- Strings related to transaction -->
+    <string name="welcome">"Selamat Datang!"</string>
+    <string name="logged_in">Masuk dengan akun:</string>
+    <string name="invalid_username">Bukan email yang valid</string>
+    <string name="invalid_password">Password tidak boleh kosong</string>
+    <string name="login_failed">"Login gagal"</string>
+    <string name="logout">Logout</string>
+    <string name="title_activity_login">Login</string>
+    
+    <string name="random_transactions">Membuat transaksi random</string>
+    <string name="save_transactions">Simpan daftar transaksi</string>
+    <string name="send_transactions">Kirim daftar transaksi</string>
+
     <string name="textfield_label_judul">Judul</string>
     <string name="textfield_label_nominal">Nominal</string>
     <string name="textfield_label_kategori">Kategori</string>
@@ -24,4 +31,6 @@
     <string name="hint_nominal">Enter Nominal</string>
     <string name="hint_kategori">Enter Kategori</string>
     <string name="hint_lokasi">Enter Lokasi</string>
+    <string name="pembelian">Pembelian</string>
+    <string name="pengeluaran">Pengeluaran</string>
 </resources>
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 31ed43cc99341f5b95f5b15fd54f84d14a585002..96e26d4e6b245ef5a2d5b0bba7d68c7d716a61d4 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,4 +2,5 @@
 plugins {
     id("com.android.application") version "8.3.0" apply false
     id("org.jetbrains.kotlin.android") version "1.9.22" apply false
+    id("com.google.devtools.ksp") version "1.9.22-1.0.17" apply false
 }
\ No newline at end of file