diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 9cb72b9f3f1dc65ba40ac5437a881f1d8bf7e239..4efe4428e03b11a08b97f6e7e4cdb673a9813256 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -53,6 +53,12 @@ dependencies {
     implementation("androidx.constraintlayout:constraintlayout:2.1.4")
     implementation("com.google.android.gms:play-services-maps:18.2.0")
     implementation("com.google.android.gms:play-services-location:21.2.0")
+    implementation("androidx.camera:camera-core:1.3.2")
+    implementation("androidx.camera:camera-camera2:1.3.2")
+    implementation("androidx.camera:camera-lifecycle:1.3.2")
+    implementation("androidx.camera:camera-view:1.3.2")
+    implementation("androidx.exifinterface:exifinterface:1.3.7")
+    implementation("com.squareup.okhttp3:okhttp:4.9.3")
     testImplementation("junit:junit:4.13.2")
     androidTestImplementation("androidx.test.ext:junit:1.1.5")
     androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
@@ -92,8 +98,8 @@ dependencies {
 
     // Kotlin components
     implementation ("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.20")
-    api ("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
-    api ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1")
+    api ("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
+    api ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
 
     // POI: excel
     implementation ("org.apache.poi:poi:5.0.0")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index be7d3d82f7d11567fd5de6b97e21e8e5d6f85500..b178ced007c8bd0cb61ff60377acf662ad7a7f03 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,6 +5,10 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-feature android:name="android.hardware.camera.any" />
+
     <application
         android:allowBackup="true"
         android:icon="@mipmap/ic_primary_logo"
diff --git a/app/src/main/java/com/example/nerbos/data/TransactionDao.kt b/app/src/main/java/com/example/nerbos/data/TransactionDao.kt
index ce1a9db3b911612993363e6d50492612ee2c2712..29683aee64443d98d4a9bfd898ca249449efe82b 100644
--- a/app/src/main/java/com/example/nerbos/data/TransactionDao.kt
+++ b/app/src/main/java/com/example/nerbos/data/TransactionDao.kt
@@ -8,6 +8,7 @@ import androidx.room.OnConflictStrategy
 import androidx.room.Query
 import androidx.room.Update
 import com.example.nerbos.model.Transaction
+import com.example.nerbos.model.TransactionCategory
 
 @Dao
 interface TransactionDao {
@@ -22,4 +23,8 @@ interface TransactionDao {
 
     @Delete
     suspend fun deleteTransation(transaction: Transaction)
+
+    @Query("SELECT SUM(nominal) FROM transaction_table WHERE userID = :userID AND category = :category")
+    fun getSum(userID: Int, category: TransactionCategory): LiveData<Float>
+
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/example/nerbos/fragments/scan/ScanFragment.kt b/app/src/main/java/com/example/nerbos/fragments/scan/ScanFragment.kt
index 7161de166dfce509711fa63ec72839a9684b2105..a47dea4cf9aba8010a01534612431e3c9afd6cb6 100644
--- a/app/src/main/java/com/example/nerbos/fragments/scan/ScanFragment.kt
+++ b/app/src/main/java/com/example/nerbos/fragments/scan/ScanFragment.kt
@@ -1,33 +1,86 @@
 package com.example.nerbos.fragments.scan
 
+import android.Manifest
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Matrix
+import android.location.Geocoder
 import android.os.Bundle
-import androidx.fragment.app.Fragment
+import android.os.Handler
+import android.os.Looper
+import android.provider.MediaStore
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.widget.EditText
+import android.widget.ImageButton
+import android.widget.ImageView
+import android.widget.RadioGroup
+import android.widget.Toast
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AlertDialog
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.ImageCapture
+import androidx.camera.core.ImageCaptureException
+import androidx.camera.core.Preview
+import androidx.camera.lifecycle.ProcessCameraProvider
+import androidx.camera.view.PreviewView
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+import androidx.core.net.toUri
+import androidx.exifinterface.media.ExifInterface
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
 import com.example.nerbos.R
+import com.example.nerbos.model.Transaction
+import com.example.nerbos.model.TransactionCategory
+import com.example.nerbos.service.Authentication
+import com.example.nerbos.viewmodel.TransactionViewModel
+import com.google.android.gms.location.FusedLocationProviderClient
+import com.google.android.gms.location.LocationServices
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import okhttp3.Call
+import okhttp3.Callback
+import okhttp3.MediaType.Companion.toMediaTypeOrNull
+import okhttp3.MultipartBody
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import okhttp3.RequestBody.Companion.asRequestBody
+import okhttp3.Response
+import org.json.JSONException
+import org.json.JSONObject
+import java.io.File
+import java.io.IOException
+import java.util.Locale
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
 
-// TODO: Rename parameter arguments, choose names that match
-// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
-private const val ARG_PARAM1 = "param1"
-private const val ARG_PARAM2 = "param2"
-
-/**
- * A simple [Fragment] subclass.
- * Use the [ScanFragment.newInstance] factory method to
- * create an instance of this fragment.
- */
 class ScanFragment : Fragment() {
-    // TODO: Rename and change types of parameters
-    private var param1: String? = null
-    private var param2: String? = null
 
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        arguments?.let {
-            param1 = it.getString(ARG_PARAM1)
-            param2 = it.getString(ARG_PARAM2)
-        }
+    private lateinit var previewView: PreviewView
+    private lateinit var cameraExecutor: ExecutorService
+    private lateinit var imageCapture: ImageCapture
+    private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
+    private lateinit var geocoder: Geocoder
+    private var fragmentContext: Context? = null
+
+    private val requestCameraPermissionCode = Manifest.permission.CAMERA
+    private val uploadURL: String by lazy {
+        requireContext().getString(R.string.backend_api_scan)
+    }
+
+    override fun onAttach(context: Context) {
+        super.onAttach(context)
+        fragmentContext = context
+    }
+
+    override fun onDetach() {
+        super.onDetach()
+        fragmentContext = null
     }
 
     override fun onCreateView(
@@ -35,26 +88,370 @@ class ScanFragment : Fragment() {
         savedInstanceState: Bundle?
     ): View? {
         // Inflate the layout for this fragment
-        return inflater.inflate(R.layout.fragment_scan, container, false)
-    }
-
-    companion object {
-        /**
-         * Use this factory method to create a new instance of
-         * this fragment using the provided parameters.
-         *
-         * @param param1 Parameter 1.
-         * @param param2 Parameter 2.
-         * @return A new instance of fragment Scan.
-         */
-        // TODO: Rename and change types and number of parameters
-        @JvmStatic
-        fun newInstance(param1: String, param2: String) =
-            ScanFragment().apply {
-                arguments = Bundle().apply {
-                    putString(ARG_PARAM1, param1)
-                    putString(ARG_PARAM2, param2)
+        val view = inflater.inflate(R.layout.fragment_scan, container, false)
+        previewView = view.findViewById(R.id.previewView)
+        return view
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+        cameraExecutor = Executors.newSingleThreadExecutor()
+        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(requireContext())
+        geocoder = Geocoder(requireContext(), Locale.getDefault())
+
+        if (allPermissionsGranted()) {
+            startCamera()
+        } else {
+            requestCameraPermission.launch(requestCameraPermissionCode)
+        }
+
+        view.findViewById<ImageButton>(R.id.captureButton).setOnClickListener {
+            takePicture()
+        }
+
+        view.findViewById<ImageButton>(R.id.galleryButton).setOnClickListener {
+            dispatchGalleryIntent()
+        }
+    }
+
+    private fun allPermissionsGranted() = ContextCompat.checkSelfPermission(
+        requireContext(),
+        Manifest.permission.CAMERA
+    ) == PackageManager.PERMISSION_GRANTED
+
+    private fun startCamera() {
+        val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
+
+        cameraProviderFuture.addListener({
+            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
+
+            val preview = Preview.Builder()
+                .build()
+                .also {
+                    it.setSurfaceProvider(previewView.surfaceProvider)
+                }
+
+            imageCapture = ImageCapture.Builder().build()
+
+            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
+
+            try {
+                cameraProvider.unbindAll()
+                cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)
+            } catch (e: Exception) {
+                e.printStackTrace()
+            }
+
+        }, ContextCompat.getMainExecutor(requireContext()))
+    }
+
+    private fun takePicture() {
+        val imageCapture = imageCapture
+
+        // Create output file to hold the captured image
+        val externalFilesDirs = requireContext().getExternalFilesDirs(null)
+        val photoFile = File(externalFilesDirs.firstOrNull(), "${System.currentTimeMillis()}.jpg")
+
+        // Setup image capture metadata
+        val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
+
+        // Capture the image
+        imageCapture.takePicture(
+            outputOptions,
+            ContextCompat.getMainExecutor(requireContext()),
+            object : ImageCapture.OnImageSavedCallback {
+                override fun onError(exc: ImageCaptureException) {
+                    Toast.makeText(requireContext(), "Error capturing image: ${exc.message}", Toast.LENGTH_SHORT).show()
+                }
+
+                override fun onImageSaved(output: ImageCapture.OutputFileResults) {
+                    // Image captured successfully, read orientation metadata
+                    val savedUri = photoFile.toUri()
+                    val imageBitmap = BitmapFactory.decodeFile(savedUri.path)
+                    val rotatedBitmap = savedUri.path?.let {
+                        rotateImageIfRequired(imageBitmap,
+                            it
+                        )
+                    }
+                    showImagePopup(rotatedBitmap)
+                }
+            })
+    }
+
+    private fun rotateImageIfRequired(bitmap: Bitmap, path: String): Bitmap {
+        val ei = ExifInterface(path)
+        val orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
+
+        return when (orientation) {
+            ExifInterface.ORIENTATION_ROTATE_90 -> rotateImage(bitmap, 90f)
+            ExifInterface.ORIENTATION_ROTATE_180 -> rotateImage(bitmap, 180f)
+            ExifInterface.ORIENTATION_ROTATE_270 -> rotateImage(bitmap, 270f)
+            else -> bitmap
+        }
+    }
+
+    private fun rotateImage(source: Bitmap, angle: Float): Bitmap {
+        val matrix = Matrix()
+        matrix.postRotate(angle)
+        return Bitmap.createBitmap(source, 0, 0, source.width, source.height, matrix, true)
+    }
+
+    private fun dispatchGalleryIntent() {
+        val galleryIntent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
+        requestGallery.launch(galleryIntent)
+    }
+
+    private fun showImagePopup(imageBitmap: Bitmap?) {
+        if (imageBitmap != null) {
+            MaterialAlertDialogBuilder(requireContext())
+                .setTitle("Use this picture?")
+                .setPositiveButton("Yes") { dialog, _ ->
+                    val imageFile = File.createTempFile("image", ".jpg", requireContext().cacheDir)
+                    imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageFile.outputStream())
+                    uploadImageToServer(imageFile) { success, message ->
+                        if (success) {
+                            showToastOnUIThread(message.toString())
+                        } else {
+                            showToastOnUIThread(message.toString())
+                        }
+                    }
+                    dialog.dismiss()
+                }
+                .setNegativeButton("No") { dialog, _ ->
+                    showToastOnUIThread("Scan cancelled")
+                    dialog.dismiss()
+                }
+                .setView(ImageView(requireContext()).apply {
+                    setImageBitmap(imageBitmap)
+                    adjustViewBounds = true
+                })
+                .show()
+                .apply {
+                    getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(ContextCompat.getColor(requireContext(), R.color.white))
+                    getButton(AlertDialog.BUTTON_NEGATIVE)?.setTextColor(ContextCompat.getColor(requireContext(), R.color.white))
+                }
+        } else {
+            Toast.makeText(requireContext(), "Failed to load image", Toast.LENGTH_SHORT).show()
+        }
+    }
+
+    @Suppress("DEPRECATION")
+    private fun showTransactionInputDialog(callback: (String, String, String) -> Unit) {
+        val dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.add_scan_transaction, null)
+        val nameInput = dialogView.findViewById<EditText>(R.id.nameInput)
+        val locationInput = dialogView.findViewById<EditText>(R.id.locationInput)
+        val transactionTypeRadioGroup = dialogView.findViewById<RadioGroup>(R.id.transactionTypeRadioGroup)
+        val mapButton = dialogView.findViewById<ImageButton>(R.id.mapButton)
+
+        transactionTypeRadioGroup.check(R.id.incomeRadioButton)
+        mapButton.setOnClickListener {
+            if (ActivityCompat.checkSelfPermission(
+                    requireContext(),
+                    Manifest.permission.ACCESS_FINE_LOCATION
+                ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
+                    requireContext(),
+                    Manifest.permission.ACCESS_COARSE_LOCATION
+                ) != PackageManager.PERMISSION_GRANTED
+            ) {
+                ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1)
+                return@setOnClickListener
+            }
+            fusedLocationProviderClient.lastLocation.addOnSuccessListener (requireActivity()){
+                    location ->
+                if (location != null) {
+                    val address = geocoder.getFromLocation(location.latitude, location.longitude, 1)
+                    locationInput.setText(address!![0].getAddressLine(0))
+                } else {
+                    Toast.makeText(requireContext(), "Failed to get location", Toast.LENGTH_SHORT)
+                        .show()
+                }
+            }
+        }
+
+        val dialog = AlertDialog.Builder(requireContext())
+            .setTitle("Transaction Input")
+            .setView(dialogView)
+            .setPositiveButton("OK") { _, _ ->
+                val name = nameInput.text.toString()
+                val location = locationInput.text.toString()
+                val transactionType = when (transactionTypeRadioGroup.checkedRadioButtonId) {
+                    R.id.incomeRadioButton -> "Income"
+                    R.id.outcomeRadioButton -> "Outcome"
+                    else -> ""
+                }
+                if (name.isNotEmpty() && location.isNotEmpty() && transactionType.isNotEmpty()) {
+                    callback(name, location, transactionType)
+                } else {
+                    // Display error message if any field is empty
+                    Toast.makeText(requireContext(), "Please fill in all fields", Toast.LENGTH_SHORT).show()
+                    // Show the dialog again to allow the user to fill in missing fields
+                    showTransactionInputDialog(callback)
+                }
+            }
+            .setNegativeButton("Cancel") { dialog, _ ->
+                dialog.dismiss()
+            }
+            .create()
+
+        dialog.show()
+
+        dialog.getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(ContextCompat.getColor(requireContext(), R.color.white))
+        dialog.getButton(AlertDialog.BUTTON_NEGATIVE)?.setTextColor(ContextCompat.getColor(requireContext(), R.color.white))
+    }
+
+    private fun showTransactionConfirmationDialog(responseBody: String?, transactionName: String, selectedTransactionType: String, totalNominal: Float, location: String, callback: (Boolean) -> Unit) {
+        val builder = AlertDialog.Builder(requireContext())
+        builder.setTitle("Confirm Transaction Details")
+
+        // Parse the JSON response body to extract item details
+        val itemDetails = StringBuilder()
+        calculateTotalNominal(responseBody)?.let {
+            try {
+                val jsonObject = JSONObject(responseBody.toString())
+                val itemsArray = jsonObject.getJSONObject("items").getJSONArray("items")
+                for (i in 0 until itemsArray.length()) {
+                    val itemObject = itemsArray.getJSONObject(i)
+                    val name = itemObject.getString("name")
+                    val qty = itemObject.getInt("qty")
+                    val price = itemObject.getDouble("price").toFloat()
+                    itemDetails.append("$name: $qty x $price\n")
                 }
+            } catch (e: JSONException) {
+                e.printStackTrace()
             }
+        }
+
+        val transactionTypeMessage = if (selectedTransactionType == "Income") "income" else "outcome"
+        val message = "Transaction Name: $transactionName\n\n$itemDetails\nTotal Nominal: $totalNominal\n\nThis transaction will be added as an $transactionTypeMessage with location: $location.\n\nDo you want to proceed?"
+        builder.setMessage(message)
+
+        builder.setPositiveButton("Yes") { dialog, _ ->
+            callback(true)
+            dialog.dismiss()
+        }
+
+        builder.setNegativeButton("No") { dialog, _ ->
+            callback(false)
+            dialog.dismiss()
+        }
+
+        val dialog = builder.create()
+        dialog.show()
+
+        dialog.getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(ContextCompat.getColor(requireContext(), R.color.white))
+        dialog.getButton(AlertDialog.BUTTON_NEGATIVE)?.setTextColor(ContextCompat.getColor(requireContext(), R.color.white))
+    }
+
+    private fun uploadImageToServer(imageFile: File, callback: (Boolean, String?) -> Unit) {
+        showTransactionInputDialog { name, location, transactionType ->
+            val authentication = Authentication(requireContext())
+            val token = authentication.getToken()
+            val client = OkHttpClient()
+
+            val requestBody = MultipartBody.Builder()
+                .setType(MultipartBody.FORM)
+                .addFormDataPart("file", imageFile.name, imageFile.asRequestBody("image/*".toMediaTypeOrNull()))
+                .build()
+
+            val request = Request.Builder()
+                .url(uploadURL)
+                .header("Authorization", "Bearer $token")
+                .post(requestBody)
+                .build()
+
+            client.newCall(request).enqueue(object : Callback {
+                override fun onResponse(call: Call, response: Response) {
+                    if (response.isSuccessful) {
+                        // Parse the response body to extract transaction items and calculate total nominal
+                        val responseBody = response.body?.string()
+                        val totalNominal = calculateTotalNominal(responseBody)
+
+                        // Run on UI thread to show transaction confirmation dialog
+                        requireActivity().runOnUiThread {
+                            showTransactionConfirmationDialog(responseBody, name, transactionType, totalNominal ?: 0f, location) { confirmed ->
+                                if (confirmed) {
+                                    // Create a single transaction and add it to the database
+                                    totalNominal?.let { nominal ->
+                                        val transaction = Transaction(
+                                            userID = authentication.getNim(),
+                                            name = name,
+                                            category = if (transactionType == "Income") TransactionCategory.INCOME else TransactionCategory.OUTCOME,
+                                            nominal = nominal,
+                                            location = location
+                                        )
+                                        addTransactionToDatabase(transaction)
+                                        callback(true, "Transaction added successfully")
+                                    } ?: run {
+                                        callback(false, "Failed to calculate total nominal")
+                                    }
+                                } else {
+                                    callback(false, "Transaction cancelled")
+                                }
+                            }
+                        }
+                    } else {
+                        callback(false, "Failed to upload image. Please try again later.")
+                    }
+                }
+
+                override fun onFailure(call: Call, e: IOException) {
+                    showToastOnUIThread("Failed to upload image: ${e.message}")
+                    callback(false, e.message)
+                }
+            })
+        }
+    }
+
+    private fun calculateTotalNominal(responseBody: String?): Float? {
+        var totalNominal: Float? = null
+        try {
+            val jsonObject = JSONObject(responseBody.toString())
+            val itemsArray = jsonObject.getJSONObject("items").getJSONArray("items")
+            totalNominal = 0f
+            for (i in 0 until itemsArray.length()) {
+                val itemObject = itemsArray.getJSONObject(i)
+                val qty = itemObject.getInt("qty")
+                val price = itemObject.getDouble("price").toFloat()
+                totalNominal += qty * price
+            }
+        } catch (e: JSONException) {
+            e.printStackTrace()
+        }
+        return totalNominal
+    }
+
+    private fun addTransactionToDatabase(transaction: Transaction) {
+        val transactionViewModel = ViewModelProvider(requireActivity())[TransactionViewModel::class.java]
+        transactionViewModel.addTransaction(transaction)
+    }
+
+    private fun showToastOnUIThread(message: String) {
+        Handler(Looper.getMainLooper()).post {
+            Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
+        }
+    }
+
+    private val requestCameraPermission =
+        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
+            if (isGranted) {
+                startCamera()
+            } else {
+                // Handle the case where the user denied the permission
+                Toast.makeText(requireContext(), "Camera permission denied", Toast.LENGTH_SHORT).show()
+            }
+        }
+
+    private val requestGallery = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+        if (result.resultCode == Activity.RESULT_OK) {
+            val imageUri = result.data?.data
+            val inputStream = requireContext().contentResolver.openInputStream(imageUri!!)
+            val imageBitmap = BitmapFactory.decodeStream(inputStream)
+            showImagePopup(imageBitmap)
+        }
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        cameraExecutor.shutdown()
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/example/nerbos/fragments/statistic/StatisticFragment.kt b/app/src/main/java/com/example/nerbos/fragments/statistic/StatisticFragment.kt
index 8eba3594b4d5a3cf449300f8a316cc6119c0ae5c..df203cb4033c734c10f9e352516adedef5014e70 100644
--- a/app/src/main/java/com/example/nerbos/fragments/statistic/StatisticFragment.kt
+++ b/app/src/main/java/com/example/nerbos/fragments/statistic/StatisticFragment.kt
@@ -3,12 +3,14 @@ package com.example.nerbos.fragments.statistic
 import android.graphics.Color
 import android.graphics.Typeface
 import android.os.Bundle
-import android.util.Log
 import androidx.fragment.app.Fragment
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import androidx.lifecycle.MediatorLiveData
+import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.lifecycleScope
 import com.example.nerbos.R
 import com.example.nerbos.databinding.FragmentStatisticBinding
 import com.example.nerbos.model.TransactionCategory
@@ -21,17 +23,17 @@ import com.github.mikephil.charting.data.PieDataSet
 import com.github.mikephil.charting.data.PieEntry
 import com.github.mikephil.charting.formatter.PercentFormatter
 import com.github.mikephil.charting.utils.MPPointF
+import kotlinx.coroutines.launch
+import java.text.NumberFormat
+import java.util.Locale
 
-/**
- * A simple [Fragment] subclass.
- * Use the [StatisticFragment.newInstance] factory method to
- * create an instance of this fragment.
- */
 class StatisticFragment : Fragment() {
 
     private lateinit var transactionViewModel: TransactionViewModel
     private lateinit var authentication: Authentication
     private lateinit var pieChart: PieChart
+    private lateinit var binding: FragmentStatisticBinding
+    private val liveDataReady = MutableLiveData<Boolean>()
     private var sumIncome: Float = 0.0f
     private var sumOutcome : Float = 0.0f
 
@@ -47,38 +49,134 @@ class StatisticFragment : Fragment() {
         savedInstanceState: Bundle?
     ): View {
         // Inflate the layout for this fragment
-        val binding = FragmentStatisticBinding.inflate(inflater, container, false)
+        binding = FragmentStatisticBinding.inflate(inflater, container, false)
         pieChart = binding.pieChart
 
         // Create an authentication object
         authentication = Authentication(requireContext())
         // Set the view model for the transaction and set the user id
         transactionViewModel = ViewModelProvider(this)[TransactionViewModel::class.java]
-        transactionViewModel.setReadDataUserId(authentication.getNim())
-
-        // log all the transactions
-        transactionViewModel.readAllData!!.observe(viewLifecycleOwner) { transactions ->
-            transactions.forEach {
-                Log.d("Transaction", it.toString())
-                if (it.category == TransactionCategory.INCOME) {
-                    sumIncome += it.nominal
-                } else {
-                    sumOutcome += it.nominal
-                }
-            }
-        }
+
+        // Get the data from the database
+        getData()
 
         // Set up the pie chart
         pieChartSetup()
 
-
+        // Display the pie chart
+        displayPieChart()
 
         return binding.root
     }
 
+    private fun getData() {
+        lifecycleScope.launch {
+            // Get the sum of income and outcome
+            val nim = authentication.getNim()
+            val income = transactionViewModel.getSums(nim, TransactionCategory.INCOME)
+            val outcome = transactionViewModel.getSums(nim, TransactionCategory.OUTCOME)
+
+            // Use MediatorLiveData to observe both income and outcome
+            val result = MediatorLiveData<Float>().apply {
+                addSource(income) { value -> setValue(value) }
+                addSource(outcome) { value -> setValue(value) }
+            }
+
+            // Observing the result
+            result.observe(viewLifecycleOwner) {
+                if (income.value != null && outcome.value != null) {
+                    sumIncome = income.value!!
+                    sumOutcome = outcome.value!!
+                    liveDataReady.postValue(true)
+                }
+            }
+        }
+    }
+
     // Display a pie chart of the income and outcome
     private fun pieChartSetup() {
+        // Set the pie chart: percentage, description, extra offsets
+        pieChart.setUsePercentValues(true)
+        pieChart.description.isEnabled = false
+        pieChart.setExtraOffsets(5f, 10f, 5f, 5f)
+
+        // Set the pie chart: drag deceleration, hole, hole color
+        pieChart.setDragDecelerationFrictionCoef(0.95f)
+        pieChart.isDrawHoleEnabled = true
+        pieChart.setHoleColor(requireContext().getColor(R.color.primary_bg))
+
+        // Set the pie chart: transparent circle, hole color, hole radius, draw center text
+        pieChart.setTransparentCircleColor(requireContext().getColor(R.color.primary_bg))
+        pieChart.setTransparentCircleAlpha(110)
+        pieChart.holeRadius = 42f
+        pieChart.transparentCircleRadius = 48f
+        pieChart.setDrawCenterText(true)
 
+        // Set the pie chart: legend and entry label
+        pieChart.legend.isEnabled = false
+        pieChart.setEntryLabelColor(Color.BLACK)
+        pieChart.setEntryLabelTextSize(12f)
+
+        // Set the pie chart: rotation and highlight
+        pieChart.setRotationAngle(0f)
+        pieChart.isRotationEnabled = true
+        pieChart.isHighlightPerTapEnabled = true
+    }
+
+    private fun setPieData(){
+        // Set the pie chart: animation
+        pieChart.animateY(1400, Easing.EaseInOutQuad)
+
+        // Set the pie chart: data
+        val entries: ArrayList<PieEntry> = ArrayList()
+        entries.add(PieEntry(sumIncome, resources.getString(R.string.income)))
+        entries.add(PieEntry(sumOutcome, resources.getString(R.string.outcome)))
+
+        // Create a pie data set
+        val dataSet = PieDataSet(entries, resources.getString(R.string.pie_chart_title))
+
+        // Set the pie data set properties
+        dataSet.setDrawIcons(false)
+        dataSet.sliceSpace = 3f
+        dataSet.iconsOffset = MPPointF(0f, 40f)
+        dataSet.selectionShift = 5f
+
+        // Set the pie data set: colors
+        val colors: ArrayList<Int> = ArrayList()
+        colors.add(requireContext().getColor(R.color.purple_200))
+        colors.add(requireContext().getColor(R.color.red))
+        dataSet.colors = colors
+
+        // Set the pie data set: text size, text color, text typeface
+        val data = PieData(dataSet)
+        data.setValueFormatter(PercentFormatter())
+        data.setValueTextSize(15f)
+        data.setValueTypeface(Typeface.DEFAULT_BOLD)
+        data.setValueTextColor(Color.BLACK)
+        pieChart.setData(data)
+        pieChart.highlightValues(null)
+    }
+
+    private fun displayPieChart() {
+        // wait until the income and outcome are calculated
+        // Observe the LiveData object to update the pie chart when the data is ready
+        liveDataReady.observe(viewLifecycleOwner) { dataReady ->
+            if (dataReady) {
+                // Set the pie data
+                setPieData()
+
+                // Invalidate the pie chart (refresh)
+                pieChart.invalidate()
+
+                // Reset the sum of income and outcome
+                val incomeNumber = binding.totalIncomeNumber
+                val outcomeNumber = binding.totalOutcomeNumber
+
+                // Update the text views with the formatted values
+                incomeNumber.text = NumberFormat.getCurrencyInstance(Locale(resources.getString(R.string.language_code), resources.getString(R.string.country_code))).format(sumIncome)
+                outcomeNumber.text = NumberFormat.getCurrencyInstance(Locale(resources.getString(R.string.language_code), resources.getString(R.string.country_code))).format(sumOutcome)
+            }
+        }
     }
 
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/example/nerbos/repository/TransactionRepository.kt b/app/src/main/java/com/example/nerbos/repository/TransactionRepository.kt
index 167b34ac67800ba787e7192bab4421ad3152a1f9..378a6f2e1af9fda80cf7a9e5d2f51c5367ce8c23 100644
--- a/app/src/main/java/com/example/nerbos/repository/TransactionRepository.kt
+++ b/app/src/main/java/com/example/nerbos/repository/TransactionRepository.kt
@@ -3,6 +3,7 @@ package com.example.nerbos.repository
 import androidx.lifecycle.LiveData
 import com.example.nerbos.model.Transaction
 import com.example.nerbos.data.TransactionDao
+import com.example.nerbos.model.TransactionCategory
 import com.example.nerbos.service.Authentication
 
 class TransactionRepository(private val transactionDao: TransactionDao) {
@@ -22,4 +23,8 @@ class TransactionRepository(private val transactionDao: TransactionDao) {
     fun setReadAllDataUserId(userID: Int){
         readAllData = transactionDao.readAllData(userID)
     }
+
+    fun getSum(userID: Int, category: TransactionCategory): LiveData<Float>{
+        return transactionDao.getSum(userID, category)
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/example/nerbos/service/Authentication.kt b/app/src/main/java/com/example/nerbos/service/Authentication.kt
index 62cde4837bfdccf20a592ff3b52445bf623e1450..ca362b71f0e9ecefbb3d227e2b12bc23aaee4016 100644
--- a/app/src/main/java/com/example/nerbos/service/Authentication.kt
+++ b/app/src/main/java/com/example/nerbos/service/Authentication.kt
@@ -84,7 +84,7 @@ class Authentication(private val context: Context) {
         return email.toInt()
     }
 
-    private fun getToken(): String {
+    internal fun getToken(): String {
         val sharedPreferences : SharedPreferences =
             context.getSharedPreferences(context.getString(R.string.preferences), Context.MODE_PRIVATE)
         return sharedPreferences.getString(context.getString(R.string.token), "") ?: ""
diff --git a/app/src/main/java/com/example/nerbos/viewmodel/TransactionViewModel.kt b/app/src/main/java/com/example/nerbos/viewmodel/TransactionViewModel.kt
index 50081922b59de5349c14327404e84efdf8e8cca5..ed27c0a71f60129bf3fdd5443f84a60a97dac15a 100644
--- a/app/src/main/java/com/example/nerbos/viewmodel/TransactionViewModel.kt
+++ b/app/src/main/java/com/example/nerbos/viewmodel/TransactionViewModel.kt
@@ -6,6 +6,7 @@ import androidx.lifecycle.LiveData
 import androidx.lifecycle.viewModelScope
 import com.example.nerbos.model.Transaction
 import com.example.nerbos.data.TransactionDatabase
+import com.example.nerbos.model.TransactionCategory
 import com.example.nerbos.repository.TransactionRepository
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
@@ -41,4 +42,8 @@ class TransactionViewModel(application: Application): AndroidViewModel(applicati
         repository.setReadAllDataUserId(userId)
         readAllData = repository.readAllData
     }
+
+    fun getSums(userId: Int, category: TransactionCategory): LiveData<Float>{
+        return repository.getSum(userId, category)
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml
index 8a9966c9694727aa195f1036c7838296f313ff57..f2c30fb6f6ed0c1150c1c9546eae3ec31f650df6 100644
--- a/app/src/main/res/layout-land/activity_main.xml
+++ b/app/src/main/res/layout-land/activity_main.xml
@@ -11,7 +11,6 @@
         android:id="@+id/appBarLayout"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:background="@color/primary_bg"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent">
@@ -45,16 +44,13 @@
         android:layout_width="78dp"
         android:layout_height="0dp"
 
-        android:background="@color/primary_bg"
+        android:background="@color/navbar_bg"
         app:elevation="1dp"
         app:itemBackground="@color/navbar_bg"
         app:itemIconTint="@color/navbar_icon"
-        app:itemTextColor="@color/navbar_icon"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintHorizontal_bias="1.0"
         app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
-        app:layout_constraintVertical_bias="1.0"
         app:menu="@menu/bottom_navbar">
 
     </com.google.android.material.navigation.NavigationView>
diff --git a/app/src/main/res/layout-land/fragment_statistic.xml b/app/src/main/res/layout-land/fragment_statistic.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b810818485e21b56567ea789c689b1d4130f0717
--- /dev/null
+++ b/app/src/main/res/layout-land/fragment_statistic.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout
+    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:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true"
+    android:background="@color/primary_bg"
+    tools:context=".fragments.statistic.StatisticFragment">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <TextView
+            android:id="@+id/titleChart"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="44dp"
+            android:gravity="center"
+            android:padding="10dp"
+            android:text="@string/pie_chart_title"
+            android:textAlignment="center"
+            android:textColor="@color/chart_title"
+            android:textSize="24sp"
+            android:textStyle="bold"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0.5"
+            app:layout_constraintStart_toEndOf="@+id/pieChart"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <com.github.mikephil.charting.charts.PieChart
+            android:id="@+id/pieChart"
+            android:layout_width="300dp"
+            android:layout_height="300dp"
+            android:layout_marginStart="52dp"
+            android:layout_weight="1"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintVertical_bias="0.5" />
+
+        <TextView
+            android:id="@+id/totalIncome"
+            android:layout_width="100dp"
+            android:layout_height="wrap_content"
+            android:layout_margin="3dp"
+            android:layout_marginStart="8dp"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:padding="4dp"
+            android:text="@string/income"
+            android:textAlignment="center"
+            android:textColor="@color/chart_title"
+            app:drawableLeftCompat="@drawable/ic_circle"
+            app:drawableTint="@color/purple_200"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@+id/totalOutcome"
+            app:layout_constraintHorizontal_bias="0.5"
+            app:layout_constraintStart_toEndOf="@+id/pieChart"
+            app:layout_constraintTop_toBottomOf="@+id/titleChart"
+            app:layout_constraintVertical_bias="0.2" />
+
+        <TextView
+            android:id="@+id/totalOutcome"
+            android:layout_width="100dp"
+            android:layout_height="wrap_content"
+            android:layout_margin="3dp"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:padding="4dp"
+            android:text="@string/outcome"
+            android:textAlignment="center"
+            android:textColor="@color/chart_title"
+            app:drawableLeftCompat="@drawable/ic_circle"
+            app:drawableTint="@color/red"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0.5"
+            app:layout_constraintStart_toEndOf="@+id/totalIncome"
+            app:layout_constraintTop_toBottomOf="@+id/titleChart"
+            app:layout_constraintVertical_bias="0.2" />
+
+        <TextView
+            android:id="@+id/totalIncomeNumber"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_margin="3dp"
+            android:layout_marginStart="20dp"
+            android:layout_marginTop="16dp"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:padding="4dp"
+            android:text="@string/income"
+            android:textAlignment="center"
+            android:textColor="@color/chart_title"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@+id/totalOutcomeNumber"
+            app:layout_constraintHorizontal_bias="0.5"
+            app:layout_constraintStart_toEndOf="@+id/pieChart"
+            app:layout_constraintTop_toBottomOf="@+id/totalIncome"
+            app:layout_constraintVertical_bias="0.2" />
+
+        <TextView
+            android:id="@+id/totalOutcomeNumber"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_margin="3dp"
+            android:layout_marginTop="24dp"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:padding="4dp"
+            android:text="@string/outcome"
+            android:textAlignment="center"
+            android:textColor="@color/chart_title"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0.5"
+            app:layout_constraintStart_toEndOf="@+id/totalIncomeNumber"
+            app:layout_constraintTop_toBottomOf="@+id/totalOutcome"
+            app:layout_constraintVertical_bias="0.200" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout-land/fragment_user.xml b/app/src/main/res/layout-land/fragment_user.xml
new file mode 100644
index 0000000000000000000000000000000000000000..05f64b5008a810ea923ad11127399d146e39a86d
--- /dev/null
+++ b/app/src/main/res/layout-land/fragment_user.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout 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:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".fragments.user.UserFragment"
+    android:background="@color/primary_bg">
+
+    <!-- TODO: Update blank fragment layout -->
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/primary_bg">
+
+        <androidx.cardview.widget.CardView
+            android:id="@+id/logoutCard"
+            android:layout_width="400dp"
+            android:layout_height="310dp"
+            app:cardBackgroundColor="@color/login_card_bg"
+            app:cardCornerRadius="20dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent">
+
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:padding="4dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintHorizontal_bias="0.5"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintVertical_bias="0.5">
+
+                <TextView
+                    android:id="@+id/logoutTitle"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="15dp"
+                    android:gravity="center_horizontal"
+                    android:text="@string/welcome"
+                    android:textColor="@color/white"
+                    android:textSize="40sp"
+                    android:visibility="visible"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
+
+                <TextView
+                    android:id="@+id/logoutDescription"
+                    android:layout_width="341dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="5dp"
+                    android:gravity="center_horizontal"
+                    android:text="@string/app_name_full"
+                    android:textColor="@color/text_secondary"
+                    android:textSize="20sp"
+                    android:visibility="visible"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/logoutTitle" />
+
+                <androidx.cardview.widget.CardView
+                    android:id="@+id/cardView4"
+                    android:layout_width="330dp"
+                    android:layout_height="50dp"
+                    android:layout_gravity="center_horizontal"
+                    app:cardBackgroundColor="@color/login_input_field"
+                    app:cardCornerRadius="20dp"
+                    app:layout_constraintBottom_toTopOf="@+id/cardView5"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintHorizontal_bias="0.548"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/logoutDescription"
+                    app:layout_constraintVertical_bias="0.361">
+
+                    <TextView
+                        android:id="@+id/textViewUser"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="center"
+                        android:text=""
+                        android:textColor="@color/white"
+                        android:textSize="20sp" />
+
+                </androidx.cardview.widget.CardView>
+
+                <androidx.cardview.widget.CardView
+                    android:id="@+id/cardView5"
+                    android:layout_width="330dp"
+                    android:layout_height="50dp"
+                    android:layout_gravity="center_horizontal"
+                    android:layout_marginTop="75dp"
+                    app:cardBackgroundColor="@color/login_input_field"
+                    app:cardCornerRadius="20dp"
+                    app:layout_constraintBottom_toTopOf="@+id/button"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintHorizontal_bias="0.548"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/logoutDescription"
+                    app:layout_constraintVertical_bias="0.0">
+
+                    <TextView
+                        android:id="@+id/textViewEmail"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="center"
+                        android:text=""
+                        android:textColor="@color/white"
+                        android:textSize="20sp" />
+
+                </androidx.cardview.widget.CardView>
+
+                <Button
+                    android:id="@+id/button"
+                    android:layout_width="130dp"
+                    android:layout_height="55dp"
+                    android:layout_gravity="center_horizontal"
+                    android:layout_marginTop="135dp"
+                    android:labelFor="@id/button"
+                    android:text="@string/logout_title"
+                    android:textColor="@color/white"
+                    android:textSize="20sp"
+                    app:backgroundTint="@color/dark_red"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintHorizontal_bias="0.497"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/logoutDescription"
+                    app:layout_constraintVertical_bias="0.1" />
+
+            </androidx.constraintlayout.widget.ConstraintLayout>
+
+        </androidx.cardview.widget.CardView>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/add_scan_transaction.xml b/app/src/main/res/layout/add_scan_transaction.xml
new file mode 100644
index 0000000000000000000000000000000000000000..520807875ceb101da97dbe6549a6fc14b4f58ee0
--- /dev/null
+++ b/app/src/main/res/layout/add_scan_transaction.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout 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:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:padding="16dp">
+
+    <EditText
+        android:id="@+id/nameInput"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="@string/name"
+        android:inputType="text"
+        android:autofillHints="Transaction Name" />
+
+    <RadioGroup
+        android:id="@+id/transactionTypeRadioGroup"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:orientation="horizontal">
+
+        <RadioButton
+            android:id="@+id/incomeRadioButton"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="@string/income" />
+
+        <RadioButton
+            android:id="@+id/outcomeRadioButton"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="@string/outcome" />
+
+    </RadioGroup>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+
+        <EditText
+            android:id="@+id/locationInput"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:autofillHints="Location Name"
+            android:hint="@string/location"
+            android:inputType="text"
+            android:layout_marginEnd="20dp"
+            tools:ignore="NestedWeights" />
+
+        <ImageButton
+            android:id="@+id/mapButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:contentDescription="@string/maps"
+            android:background="@color/transparent"
+            app:srcCompat="@android:drawable/ic_dialog_map" />
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_scan.xml b/app/src/main/res/layout/fragment_scan.xml
index 193a7384f6056c7253520fb441d76721006f1626..3d5bb3139356fbef43e87b7008307190a98e0070 100644
--- a/app/src/main/res/layout/fragment_scan.xml
+++ b/app/src/main/res/layout/fragment_scan.xml
@@ -3,14 +3,66 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:background="@color/primary_bg"
     tools:context=".fragments.scan.ScanFragment">
 
-    <!-- TODO: Update blank fragment layout -->
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="Scan Fragment"
-        android:textSize="26dp"
-        android:layout_gravity="center" />
+    <LinearLayout
+        android:id="@+id/scanVerticalLayout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        tools:ignore="UselessParent">
+
+        <Space
+            android:layout_width="match_parent"
+            android:layout_height="50dp" />
+
+        <androidx.camera.view.PreviewView
+            android:id="@+id/previewView"
+            android:layout_width="300dp"
+            android:layout_height="400dp"
+            android:layout_gravity="center" />
+
+        <LinearLayout
+            android:id="@+id/scanHorizontalLayout"
+            android:layout_width="300dp"
+            android:layout_height="160dp"
+            android:layout_gravity="center"
+            android:orientation="horizontal">
+
+            <ImageButton
+                android:id="@+id/captureButton"
+                android:layout_width="75dp"
+                android:layout_height="75dp"
+                android:layout_gravity="center"
+                android:background="@drawable/round_corner_button_weak"
+                android:contentDescription="@string/capture_button"
+                android:scaleType="fitCenter"
+                android:src="@android:drawable/ic_menu_camera"
+                tools:ignore="RedundantDescriptionCheck" />
+
+            <Space
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1" />
+
+            <ImageButton
+                android:id="@+id/galleryButton"
+                android:layout_width="75dp"
+                android:layout_height="75dp"
+                android:layout_gravity="center"
+                android:background="@drawable/round_corner_button_weak"
+                android:contentDescription="@string/gallery_button"
+                android:scaleType="fitCenter"
+                android:src="@android:drawable/ic_menu_gallery"
+                tools:ignore="RedundantDescriptionCheck" />
+
+        </LinearLayout>
+
+        <Space
+            android:layout_width="match_parent"
+            android:layout_height="125dp" />
+
+    </LinearLayout>
 
 </FrameLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_statistic.xml b/app/src/main/res/layout/fragment_statistic.xml
index 7e562b036d83f4113f8e311614cc3b505f9b8d82..ba705c87f7af0ed44241908f4128ca57beb58cb8 100644
--- a/app/src/main/res/layout/fragment_statistic.xml
+++ b/app/src/main/res/layout/fragment_statistic.xml
@@ -11,8 +11,9 @@
 
     <RelativeLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginTop="20dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="0dp"
+        android:layout_gravity="center"
         tools:ignore="UselessParent">
 
         <TextView
@@ -21,7 +22,7 @@
             android:layout_height="wrap_content"
             android:gravity="center"
             android:padding="10dp"
-            android:text="@string/pie_chart"
+            android:text="@string/pie_chart_title"
             android:textAlignment="center"
             android:textColor="@color/chart_title"
             android:textSize="25sp"
@@ -40,6 +41,7 @@
             android:layout_marginBottom="5dp" />
 
         <LinearLayout
+            android:id="@+id/totalIncomeOutcome"
             android:layout_width="300dp"
             android:layout_height="wrap_content"
             android:layout_below="@+id/pieChart"
@@ -58,7 +60,7 @@
                 android:padding="4dp"
                 android:text="@string/income"
                 android:textAlignment="center"
-                android:textColor="@color/white"
+                android:textColor="@color/chart_title"
                 app:drawableTint="@color/purple_200"
                 app:drawableLeftCompat="@drawable/ic_circle" />
 
@@ -72,11 +74,47 @@
                 android:padding="4dp"
                 android:text="@string/outcome"
                 android:textAlignment="center"
-                android:textColor="@color/white"
+                android:textColor="@color/chart_title"
                 app:drawableLeftCompat="@drawable/ic_circle"
                 app:drawableTint="@color/red" />
         </LinearLayout>
 
+        <LinearLayout
+            android:id="@+id/totalIncomeOutcomeNumber"
+            android:layout_width="300dp"
+            android:layout_height="wrap_content"
+            android:layout_below="@+id/totalIncomeOutcome"
+            android:layout_marginTop="15dp"
+            android:orientation="horizontal"
+            android:layout_centerHorizontal="true"
+            android:weightSum="2">
+
+            <TextView
+                android:id="@+id/totalIncomeNumber"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_margin="3dp"
+                android:layout_weight="1"
+                android:gravity="center"
+                android:padding="4dp"
+                android:text="@string/income"
+                android:textAlignment="center"
+                android:textColor="@color/chart_title" />
+
+            <TextView
+                android:id="@+id/totalOutcomeNumber"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_margin="3dp"
+                android:layout_weight="1"
+                android:gravity="center"
+                android:padding="4dp"
+                android:text="@string/outcome"
+                android:textAlignment="center"
+                android:textColor="@color/chart_title" />
+
+        </LinearLayout>
+
     </RelativeLayout>
 
 </FrameLayout>
\ 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 b9f39245f02ffbfb7aeeb029d7e07b644c1fc3ca..e702056a76d75222618a58d672ef2d14ae8feead 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -29,6 +29,6 @@
     <color name="grey">#aaa</color>
     <color name="button_color">#1E573B</color>
     <color name="yellow">#FFEB3B</color>
-    <color name="chart_title">#AEACCC</color>
+    <color name="chart_title">#EAE9F6</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 061b12919ebc31c8e00eac86151769fbbea4474c..6508694d49a0ec60ef0ac02c5fd2ba041cf820ab 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -23,6 +23,7 @@
 
     <string name="backend_api_login">https://pbd-backend-2024.vercel.app/api/auth/login</string>
     <string name="backend_api_token">https://pbd-backend-2024.vercel.app/api/auth/token</string>
+    <string name="backend_api_scan">https://pbd-backend-2024.vercel.app/api/bill/upload</string>
 
     <string name="ok">OK</string>
     <string name="welcome">Welcome!</string>
@@ -58,5 +59,11 @@
     <string name="send_transactions_button">Send Transactions Button</string>
     <string name="xls">.xls</string>
     <string name="xlsx">.xlsx</string>
+    <string name="pie_chart_title">Income vs Outcome Chart</string>
+    <string name="language_code">id</string>
+    <string name="country_code">ID</string>
+    <string name="capture_button">Capture Button</string>
+    <string name="gallery_button">Gallery Button</string>
+
 
 </resources>
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 3c5031eb7d63f785752b1914cc8692a453d1cc63..2e7e7ed807f16f684be27f3b0959e2342e346381 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -20,4 +20,5 @@ kotlin.code.style=official
 # Enables namespacing of each library's R class so that its R class includes only the
 # resources declared in the library itself and none from the library's dependencies,
 # thereby reducing the size of the R class for that library
-android.nonTransitiveRClass=true
\ No newline at end of file
+android.nonTransitiveRClass=true
+org.gradle.configuration-cache=true
\ No newline at end of file