diff --git a/app/src/main/java/com/example/pbd_jwr/MainActivity.kt b/app/src/main/java/com/example/pbd_jwr/MainActivity.kt
index 149cf8c73f358145f5fd5d0a6455b7ce4c6becfc..f2fb8e02a71bb37cb299847227fe809934aa06d2 100644
--- a/app/src/main/java/com/example/pbd_jwr/MainActivity.kt
+++ b/app/src/main/java/com/example/pbd_jwr/MainActivity.kt
@@ -29,9 +29,6 @@ import com.example.pbd_jwr.encryptedSharedPref.EncryptedSharedPref
 import com.example.pbd_jwr.network.NetworkCallbackImplementation
 import com.example.pbd_jwr.ui.transaction.TransactionViewModel
 import com.google.android.material.floatingactionbutton.FloatingActionButton
-import org.json.JSONObject
-import java.util.Date
-import kotlin.math.roundToInt
 
 class MainActivity : AppCompatActivity() {
 
@@ -74,14 +71,15 @@ class MainActivity : AppCompatActivity() {
         )
         setupActionBarWithNavController(navController, appBarConfiguration)
         navView.setupWithNavController(navController)
+
         val fab: FloatingActionButton = binding.fabScan
         fab.setOnClickListener {
             // Start ScanActivity
-            val intent = Intent(this, ScanActivity::class.java)
-            startScanActivityForResult.launch(intent)
+            navController.navigate(R.id.navigation_scan)
         }
         navView.setOnItemSelectedListener { menuItem ->
             when (menuItem.itemId) {
+
                 R.id.navigation_transaction -> {
                     // Handle transaction navigation
                     navController.navigate(R.id.navigation_transaction)
@@ -191,40 +189,6 @@ class MainActivity : AppCompatActivity() {
         connectivityManager.unregisterNetworkCallback(networkCallback)
     }
 
-    private val startScanActivityForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
-        if (result.resultCode == Activity.RESULT_OK) {
-
-            sharedPreferences = EncryptedSharedPref.create(applicationContext, "login")
-            val currentUserEmail = sharedPreferences.getString("email", "") ?: ""
-
-            val data = result.data
-            val transactionDummyData = data?.getStringExtra("transactionDummyData")
-
-            transactionDummyData?.let {
-
-                val jsonObject = JSONObject(transactionDummyData)
-                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 category = Category.EXPENSE
-                    val price = itemObject.getDouble("price")
-                    val qty = itemObject.getInt("qty")
-                    val amount = (qty * price * 1000).roundToInt() / 1000.0
-                    val latitude = 6.8915
-                    val longitude = 107.6107
-                    val location = "Latitude: $latitude, Longitude: $longitude"
-                    val date = Date().time
-
-                    mTransactionViewModel.addTransaction(Transaction(email = currentUserEmail, title = name, category = category, amount = amount, latitude = latitude, longitude = longitude, date = date))
-                }
-
-
-            }
-        }
-    }
-
     companion object {
         private const val LOCATION_PERMISSION_REQUEST_CODE = 1001
     }
diff --git a/app/src/main/java/com/example/pbd_jwr/ScanActivity.kt b/app/src/main/java/com/example/pbd_jwr/ScanActivity.kt
deleted file mode 100644
index c69d98b06f12a0c3f4ac0d2bc8ca969da9597be8..0000000000000000000000000000000000000000
--- a/app/src/main/java/com/example/pbd_jwr/ScanActivity.kt
+++ /dev/null
@@ -1,366 +0,0 @@
-package com.example.pbd_jwr
-
-import android.content.Intent
-import android.graphics.Bitmap
-import android.os.Bundle
-import android.provider.MediaStore
-import android.widget.Button
-import android.widget.ImageView
-import androidx.appcompat.app.AppCompatActivity
-import android.content.pm.PackageManager
-import androidx.core.app.ActivityCompat
-import androidx.core.content.ContextCompat
-import android.Manifest
-import android.annotation.SuppressLint
-import android.app.Activity
-import android.app.AlertDialog
-import android.content.Context
-import android.content.SharedPreferences
-import android.graphics.BitmapFactory
-import android.net.Uri
-import android.widget.Toast
-import okhttp3.*
-import okhttp3.MediaType.Companion.toMediaTypeOrNull
-import java.io.File
-import java.io.IOException
-import android.os.Environment
-import android.util.Log
-import android.view.LayoutInflater
-import android.widget.ListView
-import androidx.core.content.FileProvider
-import com.example.pbd_jwr.databinding.ActivityMainBinding
-import com.example.pbd_jwr.databinding.ActivityScanBinding
-import com.example.pbd_jwr.encryptedSharedPref.EncryptedSharedPref
-import com.example.pbd_jwr.ui.transaction.TransactionDummyAdapter
-import okhttp3.RequestBody.Companion.asRequestBody
-import org.json.JSONObject
-import java.io.FileOutputStream
-import java.text.SimpleDateFormat
-import java.util.Date
-import java.util.Locale
-
-
-class ScanActivity : AppCompatActivity() {
-
-    private var imageUri: Uri? = null
-    private var currentPhotoPath: String = ""
-    private lateinit var sharedPreferences: SharedPreferences
-    var transactionDummyData: String = ""
-    private lateinit var binding: ActivityScanBinding
-    companion object {
-        const val REQUEST_IMAGE_CAPTURE = 1
-        const val REQUEST_CAMERA_PERMISSION = 2
-        const val PICK_IMAGE = 3
-        const val REQUEST_STORAGE_PERMISSION = 4
-    }
-
-    data class TransactionDummy(
-        val name: String,
-        val qty: Int,
-        val price: Double
-    )
-
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_scan)
-        binding = ActivityScanBinding.inflate(layoutInflater)
-        setContentView(binding.root)
-        sharedPreferences = EncryptedSharedPref.create(applicationContext,"login")
-
-        val scanButton: Button = binding.scanBtn
-        val galleryBtn: Button = binding.galleryBtn
-        val uploadButton: Button = binding.uploadBtn
-        val saveBtn: Button = binding.saveTransactionsBtn
-
-        val placeholderImage: ImageView = binding.imageView
-        placeholderImage.setImageResource(R.drawable.baseline_insert_photo_24)
-        addDummyTransactions("{\"items\":{\"items\":[{\"name\":\"none\",\"qty\":0,\"price\":0}]}}")
-
-        scanButton.setOnClickListener {
-            checkAndRequestPermissions()
-        }
-
-        galleryBtn.setOnClickListener {
-            openGallery()
-        }
-
-        uploadButton.setOnClickListener {
-            if (imageUri != null) {
-                uploadImage(imageUri!!)
-            } else {
-                Toast.makeText(this, "No image selected or taken", Toast.LENGTH_SHORT).show()
-            }
-        }
-
-
-        saveBtn.setOnClickListener {
-            handleSave()
-        }
-    }
-
-    private fun checkAndRequestPermissions() {
-        val permissionsNeeded = mutableListOf<String>()
-
-        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
-            permissionsNeeded.add(Manifest.permission.CAMERA)
-        }
-
-        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
-            permissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE)
-        }
-
-        if (permissionsNeeded.isNotEmpty()) {
-            ActivityCompat.requestPermissions(this, permissionsNeeded.toTypedArray(), REQUEST_STORAGE_PERMISSION)
-        } else {
-            // Semua izin sudah diberikan
-            openCamera()
-        }
-    }
-
-    @SuppressLint("InflateParams")
-    private fun handleSave() {
-        if (transactionDummyData == "") {
-            Toast.makeText(this, "No transactions read", Toast.LENGTH_SHORT).show()
-        } else {
-            val dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_confirm_transaction, null)
-            val dialogBuilder = AlertDialog.Builder(this).apply {
-                setView(dialogView)
-                setCancelable(true) // Memungkinkan dialog untuk dibatalkan dengan tombol back atau mengetuk di luar
-            }
-            val dialog = dialogBuilder.create()
-
-            dialogView.findViewById<Button>(R.id.btnCancel).setOnClickListener {
-                dialog.dismiss()
-            }
-
-            dialogView.findViewById<Button>(R.id.btnOkay).setOnClickListener {
-                val resultIntent = Intent()
-                resultIntent.putExtra("transactionDummyData", transactionDummyData)
-                setResult(Activity.RESULT_OK, resultIntent)
-                dialog.dismiss()
-
-
-                finish()
-            }
-
-            dialog.show()
-        }
-    }
-
-    private fun openCamera() {
-        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
-            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
-        } else  {
-            Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
-                takePictureIntent.resolveActivity(packageManager)?.also {
-
-                    val photoFile: File? = try {
-                        createImageFile()
-                    } catch (ex: IOException) {
-                        // Error occurred while creating the File
-                        null
-                    }
-
-                    photoFile?.also {
-                        val photoURI: Uri = FileProvider.getUriForFile(
-                            this,
-                            "JWR.provider",
-                            it
-                        )
-                        Log.d("ScanActivity", "Uri: $photoURI")
-                        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
-                        imageUri = photoURI // Simpan Uri untuk digunakan nanti
-                        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
-                    }
-                }
-            }
-        }
-    }
-
-    private fun startCameraIntent() {
-        Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
-            takePictureIntent.resolveActivity(packageManager)?.also {
-                startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
-            }
-        }
-    }
-
-    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
-        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
-        when (requestCode) {
-            REQUEST_STORAGE_PERMISSION -> {
-                if (grantResults.isNotEmpty() && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
-                    openCamera()
-                } else {
-                    Toast.makeText(this, "Storage permission is required", Toast.LENGTH_SHORT).show()
-                }
-            }
-            REQUEST_CAMERA_PERMISSION -> {
-                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
-                    startCameraIntent()
-                } else {
-                    Toast.makeText(this, "Camera permission is required", Toast.LENGTH_SHORT).show()
-                }
-            }
-        }
-    }
-
-    private fun openGallery() {
-        val intent = Intent(Intent.ACTION_PICK)
-        intent.type = "image/*"
-        startActivityForResult(intent, PICK_IMAGE)
-    }
-
-    private fun getBitmapFromUri(uri: Uri, context: Context): Bitmap? {
-        val inputStream = context.contentResolver.openInputStream(uri)
-        return BitmapFactory.decodeStream(inputStream)
-    }
-
-    private fun compressAndSaveBitmap(bitmap: Bitmap, context: Context): File {
-        // Membuat file output di direktori cache eksternal
-        val compressedFile = File(context.externalCacheDir, "compressed_${System.currentTimeMillis()}.jpg")
-
-        FileOutputStream(compressedFile).use { outStream ->
-            // Kompres bitmap ke format JPEG dengan kualitas 75% (sesuaikan sesuai kebutuhan)
-            bitmap.compress(Bitmap.CompressFormat.JPEG, 75, outStream)
-            outStream.flush()
-        }
-
-        return compressedFile
-    }
-
-    @SuppressLint("Recycle")
-    private fun uploadImage(imageUri: Uri) {
-        val token = sharedPreferences.getString("token", null)
-        if (token.isNullOrEmpty()) {
-            runOnUiThread {
-                Toast.makeText(this, "Token not found.", Toast.LENGTH_SHORT).show()
-            }
-            return
-        }
-
-        val bitmap = getBitmapFromUri(imageUri, this)
-        if (bitmap != null) {
-            // Kompres dan simpan bitmap ke file baru
-            val compressedFile = compressAndSaveBitmap(bitmap, this)
-
-            val requestBody = MultipartBody.Builder()
-                .setType(MultipartBody.FORM)
-                .addFormDataPart("file", compressedFile.name, compressedFile.asRequestBody("image/jpeg".toMediaTypeOrNull()))
-                .build()
-
-            val request = Request.Builder()
-                .url("https://pbd-backend-2024.vercel.app/api/bill/upload")
-                .addHeader("Authorization", "Bearer $token")
-                .post(requestBody)
-                .build()
-
-            OkHttpClient().newCall(request).enqueue(object : Callback {
-                override fun onFailure(call: Call, e: IOException) {
-                    runOnUiThread { Toast.makeText(this@ScanActivity, "Failed to upload image", Toast.LENGTH_SHORT).show() }
-                }
-
-                override fun onResponse(call: Call, response: Response) {
-                    runOnUiThread {
-                        if (response.isSuccessful) {
-                            val responseBody = response.body?.string()
-
-                            Log.d("Response", "response body: $responseBody")
-
-                            if (responseBody != null) {
-                                transactionDummyData = responseBody
-                                addDummyTransactions(responseBody)
-                                Log.d("Response", "transactionDummyData: $transactionDummyData")
-                            }
-
-                            Toast.makeText(this@ScanActivity, "Image uploaded successfully", Toast.LENGTH_SHORT).show()
-                        } else {
-                            Toast.makeText(this@ScanActivity, "Server error: ${response.code}", Toast.LENGTH_SHORT).show()
-                        }
-                    }
-                }
-            })
-
-        } else {
-            Toast.makeText(this, "Failed to read image", Toast.LENGTH_SHORT).show()
-        }
-    }
-
-    @Throws(IOException::class)
-    private fun createImageFile(): File {
-        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
-        val storageDir: File = getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!
-        return File.createTempFile("JPEG_${timeStamp}_", ".jpg", storageDir).apply {
-            currentPhotoPath = absolutePath
-        }
-    }
-
-    private fun addDummyTransactions(response: String) {
-        val transactions = parseTransactions(response)
-
-        // Tampilkan data transaksi pada ListView
-        val listView: ListView = findViewById(R.id.listDummyTransaction)
-        val adapter = TransactionDummyAdapter(this, transactions)
-        listView.adapter = adapter
-    }
-
-    private fun parseTransactions(responseBody: String): MutableList<TransactionDummy> {
-        val transactions = mutableListOf<TransactionDummy>()
-        responseBody.let {
-            val jsonObject = JSONObject(it)
-            val itemsObject = jsonObject.getJSONObject("items")
-            val itemsArray = itemsObject.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")
-                val transaction = TransactionDummy(name, qty, price)
-                transactions.add(transaction)
-            }
-        }
-        return transactions
-    }
-
-    private fun deleteImageFile() {
-        imageUri?.let { uri ->
-            try {
-                val contentResolver = applicationContext.contentResolver
-                val deleteSuccess = contentResolver.delete(uri, null, null) > 0
-                if (deleteSuccess) {
-                    Log.d("ScanActivity", "Image deleted successfully.")
-                } else {
-                    Log.d("ScanActivity", "Failed to delete image.")
-                }
-            } catch (e: Exception) {
-                Log.e("ScanActivity", "Error deleting image", e)
-            }
-        }
-    }
-
-
-    override fun finish() {
-        deleteImageFile()
-        super.finish()
-    }
-
-    @Deprecated("Deprecated in Java")
-    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
-        super.onActivityResult(requestCode, resultCode, data)
-
-        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
-            val imageUri = Uri.parse(currentPhotoPath)
-            imageUri?.let {
-                findViewById<ImageView>(R.id.imageView).setImageURI(it)
-            }
-        } else if (requestCode == PICK_IMAGE && resultCode == RESULT_OK) {
-            data?.data?.let { uri ->
-                findViewById<ImageView>(R.id.imageView).setImageURI(uri)
-                this.imageUri = uri // Simpan Uri dari gambar yang dipilih
-            }
-        }
-    }
-}
-
diff --git a/app/src/main/java/com/example/pbd_jwr/ui/scan/ScanFragment.kt b/app/src/main/java/com/example/pbd_jwr/ui/scan/ScanFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8bc6e6e52693832c9ab2dc835c2bbdfb5fffb122
--- /dev/null
+++ b/app/src/main/java/com/example/pbd_jwr/ui/scan/ScanFragment.kt
@@ -0,0 +1,348 @@
+package com.example.pbd_jwr.ui.scan
+
+import android.Manifest
+import android.annotation.SuppressLint
+import android.app.Activity.RESULT_OK
+import android.app.AlertDialog
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
+import android.content.pm.PackageManager
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.net.Uri
+import android.os.Bundle
+import android.os.Environment
+import android.provider.MediaStore
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.ListView
+import android.widget.Toast
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.core.content.ContextCompat
+import androidx.core.content.FileProvider
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.example.pbd_jwr.R
+import com.example.pbd_jwr.data.entity.Transaction
+import com.example.pbd_jwr.data.model.Category
+//import com.example.pbd_jwr.ScanActivity
+import com.example.pbd_jwr.databinding.FragmentScanBinding
+import com.example.pbd_jwr.encryptedSharedPref.EncryptedSharedPref
+import com.example.pbd_jwr.ui.transaction.TransactionDummyAdapter
+import com.example.pbd_jwr.ui.transaction.TransactionViewModel
+import okhttp3.*
+import okhttp3.MediaType.Companion.toMediaTypeOrNull
+import okhttp3.RequestBody.Companion.asRequestBody
+import org.json.JSONObject
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.text.SimpleDateFormat
+import java.util.*
+import kotlin.math.roundToInt
+
+class ScanFragment : Fragment() {
+
+    private var imageUri: Uri? = null
+    private var currentPhotoPath: String = ""
+    private lateinit var sharedPreferences: SharedPreferences
+    var transactionDummyData: String = ""
+    private var _binding: FragmentScanBinding? = null
+    private lateinit var mTransactionViewModel: TransactionViewModel
+
+
+    private val binding get() = _binding!!
+
+    companion object {
+        const val REQUEST_CAMERA_PERMISSION = 101
+        const val REQUEST_STORAGE_PERMISSION = 102
+        const val REQUEST_IMAGE_CAPTURE = 1
+        const val PICK_IMAGE = 3
+    }
+
+    data class TransactionDummy(
+        val name: String,
+        val qty: Int,
+        val price: Double
+    )
+
+    private val startCamera = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+        if (result.resultCode == RESULT_OK) {
+            val imageUri = Uri.parse(currentPhotoPath)
+            binding.imageView.setImageURI(imageUri)
+            binding.uploadBtn.isEnabled = true
+        }
+    }
+
+    private val pickImage = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
+        uri?.let {
+            binding.imageView.setImageURI(it)
+            imageUri = it
+            binding.uploadBtn.isEnabled = true
+        }
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+        _binding = FragmentScanBinding.inflate(inflater, container, false)
+        return binding.root
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        binding.uploadBtn.isEnabled = false
+        binding.saveTransactionsBtn.isEnabled = false
+
+        mTransactionViewModel = ViewModelProvider(this)[TransactionViewModel::class.java]
+        sharedPreferences = EncryptedSharedPref.create(requireContext(), "login")
+        resetTransaction()
+
+        binding.scanBtn.setOnClickListener {
+            checkAndRequestPermissions(Manifest.permission.CAMERA, REQUEST_CAMERA_PERMISSION) {
+                openCamera()
+            }
+        }
+
+        binding.galleryBtn.setOnClickListener {
+            pickImage.launch("image/*")
+        }
+
+        binding.uploadBtn.setOnClickListener {
+            imageUri?.let { uri ->
+                uploadImage(uri)
+            } ?: run {
+                Toast.makeText(context, "No image selected or taken", Toast.LENGTH_SHORT).show()
+            }
+        }
+
+        binding.saveTransactionsBtn.setOnClickListener {
+            handleSave()
+        }
+    }
+
+    private fun checkAndRequestPermissions(permission: String, requestCode: Int, grantedAction: () -> Unit) {
+        when {
+            ContextCompat.checkSelfPermission(requireContext(), permission) != PackageManager.PERMISSION_GRANTED -> {
+                requestPermissions(arrayOf(permission), requestCode)
+            }
+            else -> grantedAction()
+        }
+    }
+
+    @Deprecated("Deprecated in Java")
+    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+            when (requestCode) {
+                REQUEST_CAMERA_PERMISSION -> openCamera()
+                // Handle other permissions if necessary
+            }
+        } else {
+            Toast.makeText(context, "Permission denied", Toast.LENGTH_SHORT).show()
+        }
+    }
+
+    private fun openCamera() {
+        val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
+        activity?.packageManager?.let { packageManager ->
+            takePictureIntent.resolveActivity(packageManager)?.also {
+                val photoFile: File? = try {
+                    createImageFile()
+                } catch (ex: IOException) {
+                    // Error occurred while creating the File
+                    null
+                }
+                photoFile?.also {
+                    val photoURI: Uri = FileProvider.getUriForFile(requireContext(), "JWR.provider", it)
+                    startCamera.launch(Intent(takePictureIntent).apply {
+                        putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
+                    })
+                    imageUri = photoURI
+                }
+            }
+        }
+    }
+
+    private fun openGallery() {
+        val intent = Intent(Intent.ACTION_PICK)
+        intent.type = "image/*"
+        startActivityForResult(intent, PICK_IMAGE)
+    }
+
+    private fun uploadImage(imageUri: Uri) {
+        val token = sharedPreferences.getString("token", null)
+        if (token.isNullOrEmpty()) {
+            activity?.runOnUiThread {
+                Toast.makeText(requireContext(), "Token not found.", Toast.LENGTH_SHORT).show()
+            }
+            return
+        }
+
+        val bitmap = getBitmapFromUri(imageUri, requireContext())
+        if (bitmap != null) {
+            val compressedFile = compressAndSaveBitmap(bitmap, requireContext())
+
+            // Setup request with OkHttpClient as before
+            val requestBody = MultipartBody.Builder()
+                .setType(MultipartBody.FORM)
+                .addFormDataPart("file", compressedFile.name, compressedFile.asRequestBody("image/jpeg".toMediaTypeOrNull()))
+                .build()
+
+            val request = Request.Builder()
+                .url("https://pbd-backend-2024.vercel.app/api/bill/upload")
+                .addHeader("Authorization", "Bearer $token")
+                .post(requestBody)
+                .build()
+
+            OkHttpClient().newCall(request).enqueue(object : Callback {
+                override fun onFailure(call: Call, e: IOException) {
+                    activity?.runOnUiThread {
+                        Toast.makeText(requireContext(), "Failed to upload image", Toast.LENGTH_SHORT).show()
+                    }
+                }
+
+                override fun onResponse(call: Call, response: Response) {
+                    activity?.runOnUiThread {
+                        if (response.isSuccessful) {
+                            val responseBody = response.body?.string()
+//
+                            Log.d("Response", "response body: $responseBody")
+
+                            if (responseBody != null) {
+                                transactionDummyData = responseBody
+                                addDummyTransactions(transactionDummyData)
+                                Log.d("Response", "transactionDummyData: $transactionDummyData")
+                            }
+
+                            binding.saveTransactionsBtn.isEnabled = true
+                            binding.uploadBtn.isEnabled = false
+
+                            Toast.makeText(requireContext(), "Image uploaded successfully", Toast.LENGTH_SHORT).show()
+                        } else {
+                            Toast.makeText(requireContext(), "Server error: ${response.code}", Toast.LENGTH_SHORT).show()
+                        }
+                    }
+                }
+            })
+        } else {
+            Toast.makeText(requireContext(), "Failed to read image", Toast.LENGTH_SHORT).show()
+        }
+    }
+
+    @SuppressLint("InflateParams")
+    private fun handleSave() {
+        if (transactionDummyData.isEmpty()) {
+            Toast.makeText(context, "No transactions read", Toast.LENGTH_SHORT).show()
+        } else {
+            // Inflate the dialog layout
+            val dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_confirm_transaction, null)
+            val dialogBuilder = AlertDialog.Builder(requireContext()).apply {
+                setView(dialogView)
+                setCancelable(true) // Allows dialog to be canceled with back button or by tapping outside
+            }
+
+            val dialog = dialogBuilder.create()
+
+            dialogView.findViewById<Button>(R.id.btnCancel).setOnClickListener {
+                dialog.dismiss()
+            }
+
+            dialogView.findViewById<Button>(R.id.btnOkay).setOnClickListener {
+
+                val jsonObject = JSONObject(transactionDummyData)
+                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 category = Category.EXPENSE
+                    val price = itemObject.getDouble("price")
+                    val qty = itemObject.getInt("qty")
+                    val amount = (qty * price * 1000).roundToInt() / 1000.0
+                    val latitude = 6.8915
+                    val longitude = 107.6107
+                    val currentUserEmail = sharedPreferences.getString("email", "") ?: ""
+                    val date = Date().time
+
+                    mTransactionViewModel.addTransaction(Transaction(email = currentUserEmail, title = name, category = category, amount = amount, latitude = latitude, longitude = longitude, date = date))
+                }
+                dialog.dismiss()
+                resetTransaction()
+                Toast.makeText(context, "Transactions saved", Toast.LENGTH_SHORT).show()
+            }
+
+            dialog.show()
+        }
+    }
+
+    private fun resetTransaction() {
+        binding.uploadBtn.isEnabled = false
+        binding.saveTransactionsBtn.isEnabled = false
+
+        binding.imageView.setImageResource(R.drawable.baseline_insert_photo_24)
+        addDummyTransactions("{\"items\":{\"items\":[{\"name\":\"none\",\"qty\":0,\"price\":0}]}}")
+    }
+
+
+    private fun getBitmapFromUri(uri: Uri, context: Context): Bitmap? {
+        val inputStream = context.contentResolver.openInputStream(uri)
+        return BitmapFactory.decodeStream(inputStream)
+    }
+    private fun compressAndSaveBitmap(bitmap: Bitmap, context: Context): File {
+        val compressedFile = File(context.externalCacheDir, "compressed_${System.currentTimeMillis()}.jpg")
+        FileOutputStream(compressedFile).use { outStream ->
+            bitmap.compress(Bitmap.CompressFormat.JPEG, 75, outStream)
+            outStream.flush()
+        }
+        return compressedFile
+    }
+    @Throws(IOException::class)
+    private fun createImageFile(): File {
+        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
+        val storageDir: File? = requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES)
+        return File.createTempFile(
+            "JPEG_${timeStamp}_", /* prefix */
+            ".jpg", /* suffix */
+            storageDir /* directory */
+        ).also {
+            currentPhotoPath = it.absolutePath
+        }
+    }
+
+
+    private fun addDummyTransactions(response: String) {
+        val transactions = parseTransactions(response)
+
+        // Pastikan view sudah dibuat dan context tersedia sebelum mengakses binding atau requireContext()
+        val adapter = TransactionDummyAdapter(requireContext(), transactions)
+
+        // Gunakan binding untuk mengakses ListView dan menetapkan adapter
+        binding.listDummyTransaction.adapter = adapter
+    }
+
+
+    private fun parseTransactions(responseBody: String): MutableList<TransactionDummy> {
+        val transactions = mutableListOf<TransactionDummy>()
+        responseBody.let {
+            val jsonObject = JSONObject(it)
+            val itemsObject = jsonObject.getJSONObject("items")
+            val itemsArray = itemsObject.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")
+                val transaction = TransactionDummy(name, qty, price)
+                transactions.add(transaction)
+            }
+        }
+        return transactions
+    }
+
+}
diff --git a/app/src/main/java/com/example/pbd_jwr/ui/scan/ScanViewModel.kt b/app/src/main/java/com/example/pbd_jwr/ui/scan/ScanViewModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..953040d873de54d9a54ae31cef5e5d1a321550e8
--- /dev/null
+++ b/app/src/main/java/com/example/pbd_jwr/ui/scan/ScanViewModel.kt
@@ -0,0 +1,13 @@
+package com.example.pbd_jwr.ui.scan
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+
+class ScanViewModel : ViewModel() {
+
+    private val _text = MutableLiveData<String>().apply {
+        value = "This is scan Fragment"
+    }
+    val text: LiveData<String> = _text
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pbd_jwr/ui/transaction/TransactionDummyAdapter.kt b/app/src/main/java/com/example/pbd_jwr/ui/transaction/TransactionDummyAdapter.kt
index 7de77e9eb4d4fd0e397a3c786628fe8ce9dd85c7..529ccd7ef8017a0bba59cbf2a1b75e2e2b3d465d 100644
--- a/app/src/main/java/com/example/pbd_jwr/ui/transaction/TransactionDummyAdapter.kt
+++ b/app/src/main/java/com/example/pbd_jwr/ui/transaction/TransactionDummyAdapter.kt
@@ -7,11 +7,11 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.widget.ArrayAdapter
-import com.example.pbd_jwr.ScanActivity
+import com.example.pbd_jwr.ui.scan.ScanFragment
 import com.example.pbd_jwr.databinding.TransactionDummyDetailBinding
 
-class TransactionDummyAdapter(context: Context, transactions: List<ScanActivity.TransactionDummy>) :
-    ArrayAdapter<ScanActivity.TransactionDummy>(context, 0, transactions) {
+class TransactionDummyAdapter(context: Context, transactions: List<ScanFragment.TransactionDummy>) :
+    ArrayAdapter<ScanFragment.TransactionDummy>(context, 0, transactions) {
 
     @SuppressLint("SetTextI18n")
     override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
diff --git a/app/src/main/res/layout/activity_scan.xml b/app/src/main/res/layout/fragment_scan.xml
similarity index 90%
rename from app/src/main/res/layout/activity_scan.xml
rename to app/src/main/res/layout/fragment_scan.xml
index f0d80f9714fcb9f8ee4b6b7aeda59983a71e348c..eec985485c17768e71b95b7e28f15a2d4d629d81 100644
--- a/app/src/main/res/layout/activity_scan.xml
+++ b/app/src/main/res/layout/fragment_scan.xml
@@ -4,7 +4,7 @@
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:context=".ScanActivity">
+    tools:context=".ui.scan.ScanFragment">
 
     <Button
         android:id="@+id/scanBtn"
@@ -46,7 +46,6 @@
         android:layout_width="335dp"
         android:layout_height="335dp"
         android:contentDescription="PreviewImg"
-        app:layout_constraintBottom_toTopOf="@+id/listDummyTransaction"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
@@ -67,13 +66,13 @@
 
     <ListView
         android:id="@+id/listDummyTransaction"
-        android:layout_width="324dp"
-        android:layout_height="211dp"
-        android:layout_marginBottom="16dp"
+        android:layout_width="323dp"
+        android:layout_height="193dp"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintHorizontal_bias="0.494"
-        app:layout_constraintStart_toStartOf="parent" />
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/imageView" />
 
     <TextView
         android:id="@+id/textView"
@@ -84,6 +83,7 @@
         app:layout_constraintBottom_toTopOf="@+id/listDummyTransaction"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintHorizontal_bias="0.165"
-        app:layout_constraintStart_toStartOf="parent" />
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/scanBtn" />
 
 </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 db2ab3746d4aa4c81ab8ac39740aa1b3e2aab492..b9e8c3324b7b853f56c54c6e248ac8744411e821 100644
--- a/app/src/main/res/navigation/mobile_navigation.xml
+++ b/app/src/main/res/navigation/mobile_navigation.xml
@@ -51,7 +51,11 @@
             tools:layout="@layout/fragment_dashboard" />
 
 
-
+    <fragment
+        android:id="@+id/navigation_scan"
+        android:name="com.example.pbd_jwr.ui.scan.ScanFragment"
+        android:label="@string/title_scan"
+        tools:layout="@layout/fragment_scan" />
 
 
     <fragment