diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f063f1ceb837032872c0b40aa8d1b09c07596ea..bfacbd1d614984c5ebe50aa134ff479140f54db6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,14 +2,16 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools">
 
-
     <uses-feature
         android:name="android.hardware.camera"
         android:required="false" />
 
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+
     <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" />
 
@@ -53,8 +55,7 @@
             android:name=".service.jwt.JwtService"
             android:enabled="true"
             android:exported="true"
-            android:permission="android.permission.INTERNET">
-        </service>
+            android:permission="android.permission.INTERNET"></service>
 
         <receiver
             android:name=".ui.transactions.TransactionsBroadcastReceiver"
@@ -64,8 +65,8 @@
 
         <activity
             android:name=".ui.login.LoginActivity"
-            android:screenOrientation="portrait"
-            android:exported="true">
+            android:exported="true"
+            android:screenOrientation="portrait">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 
@@ -75,8 +76,7 @@
 
         <activity
             android:name=".MainActivity"
-            android:exported="true">
-        </activity>
+            android:exported="true"></activity>
 
     </application>
 
diff --git a/app/src/main/java/com/example/bondoyap/MainActivity.kt b/app/src/main/java/com/example/bondoyap/MainActivity.kt
index f99a955ca06223a0f5dc78aba72f6cc75a909984..5ac8d1fb73b41a0e5ace944a96de93b533fa7169 100644
--- a/app/src/main/java/com/example/bondoyap/MainActivity.kt
+++ b/app/src/main/java/com/example/bondoyap/MainActivity.kt
@@ -5,30 +5,31 @@ import android.content.Intent
 import android.content.IntentFilter
 import android.content.SharedPreferences
 import android.os.Bundle
+import android.widget.Toast
 import androidx.activity.viewModels
-import com.google.android.material.bottomnavigation.BottomNavigationView
 import androidx.appcompat.app.AppCompatActivity
-import androidx.core.content.ContentProviderCompat.requireContext
-import androidx.fragment.app.viewModels
 import androidx.localbroadcastmanager.content.LocalBroadcastManager
 import androidx.navigation.findNavController
 import androidx.navigation.ui.AppBarConfiguration
 import androidx.navigation.ui.setupActionBarWithNavController
 import androidx.navigation.ui.setupWithNavController
-import com.example.bondoyap.service.api.Constants.SHARED_PREFS_NAME
 import com.example.bondoyap.databinding.ActivityMainBinding
+import com.example.bondoyap.service.NetworkObserver
 import com.example.bondoyap.service.api.Constants
+import com.example.bondoyap.service.api.Constants.SHARED_PREFS_NAME
 import com.example.bondoyap.service.jwt.JwtService
 import com.example.bondoyap.ui.login.LoginActivity
 import com.example.bondoyap.ui.transactions.TransactionsApplication
 import com.example.bondoyap.ui.transactions.TransactionsBroadcastReceiver
 import com.example.bondoyap.ui.transactions.TransactionsViewModel
 import com.example.bondoyap.ui.transactions.TransactionsViewModelFactory
+import com.google.android.material.bottomnavigation.BottomNavigationView
 
 class MainActivity : AppCompatActivity() {
 
     private lateinit var binding: ActivityMainBinding
     private lateinit var sharedPreferences: SharedPreferences
+    private lateinit var networkObserver: NetworkObserver
     private lateinit var transactionsBroadcastReceiver: TransactionsBroadcastReceiver
 
     private val transactionsViewModel: TransactionsViewModel by viewModels {
@@ -40,6 +41,15 @@ class MainActivity : AppCompatActivity() {
 
         sharedPreferences = getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
 
+        networkObserver = NetworkObserver(applicationContext)
+        networkObserver.isConnected.observe(this) { isConnected ->
+            if (isConnected) {
+                Toast.makeText(this, "Koneksi terhubung", Toast.LENGTH_SHORT).show()
+            } else {
+                Toast.makeText(this, "Koneksi terputus", Toast.LENGTH_SHORT).show()
+            }
+        }
+
         if (!isLoggedIn()) {
             val intent = Intent(this, LoginActivity::class.java)
             startActivity(intent)
@@ -52,13 +62,17 @@ class MainActivity : AppCompatActivity() {
         binding = ActivityMainBinding.inflate(layoutInflater)
         setContentView(binding.root)
 
+
         val navView: BottomNavigationView = binding.navView
 
         val navController = findNavController(R.id.nav_host_fragment_activity_main)
 
-        val appBarConfiguration = AppBarConfiguration(setOf(
+        val appBarConfiguration = AppBarConfiguration(
+            setOf(
                 R.id.navigation_settings, R.id.navigation_transactions, R.id.navigation_scanner,
-                R.id.navigation_graph))
+                R.id.navigation_graph
+            )
+        )
 
         setupActionBarWithNavController(navController, appBarConfiguration)
 
@@ -66,13 +80,15 @@ class MainActivity : AppCompatActivity() {
 
         transactionsBroadcastReceiver = TransactionsBroadcastReceiver(transactionsViewModel)
         val filter = IntentFilter(Constants.ACTION_RANDOMIZE_TRANSACTIONS)
-        LocalBroadcastManager.getInstance(this).registerReceiver(transactionsBroadcastReceiver, filter)
+        LocalBroadcastManager.getInstance(this)
+            .registerReceiver(transactionsBroadcastReceiver, filter)
     }
 
     override fun onSupportNavigateUp(): Boolean {
         val navController = findNavController(R.id.nav_host_fragment_activity_main)
         return navController.navigateUp() || super.onSupportNavigateUp()
     }
+
     private fun isLoggedIn(): Boolean {
         return sharedPreferences.getBoolean("isLoggedIn", false)
     }
diff --git a/app/src/main/java/com/example/bondoyap/service/NetworkObserver.kt b/app/src/main/java/com/example/bondoyap/service/NetworkObserver.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d350eaa65f1d266a1d345290355340ba3c19f8b9
--- /dev/null
+++ b/app/src/main/java/com/example/bondoyap/service/NetworkObserver.kt
@@ -0,0 +1,28 @@
+package com.example.bondoyap.service
+
+import android.content.Context
+import android.net.ConnectivityManager
+import android.net.Network
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+
+class NetworkObserver(context: Context) {
+    private val connectivityManager =
+        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+
+    private val _isConnected = MutableLiveData<Boolean>()
+    val isConnected: LiveData<Boolean> = _isConnected
+
+    init {
+        connectivityManager.registerDefaultNetworkCallback(object :
+            ConnectivityManager.NetworkCallback() {
+            override fun onAvailable(network: Network) {
+                _isConnected.postValue(true)
+            }
+
+            override fun onLost(network: Network) {
+                _isConnected.postValue(false)
+            }
+        })
+    }
+}
diff --git a/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerFragment.kt b/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerFragment.kt
index 9d0ede0700d3679aa34b33f69bcffb9d5aa516fb..fb1c14b2dc93bc7534455625b9b5949a5e9bc338 100644
--- a/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerFragment.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerFragment.kt
@@ -11,6 +11,7 @@ import android.util.Log
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.widget.Toast
 import androidx.activity.result.ActivityResultLauncher
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.camera.core.CameraSelector
@@ -25,6 +26,7 @@ import androidx.navigation.NavController
 import androidx.navigation.fragment.findNavController
 import com.example.bondoyap.R
 import com.example.bondoyap.databinding.FragmentScannerBinding
+import com.example.bondoyap.service.NetworkObserver
 import com.example.bondoyap.service.api.ApiClient
 import com.example.bondoyap.service.api.data.BillResponse
 import com.example.bondoyap.service.api.data.Items
@@ -44,6 +46,7 @@ class ScannerFragment : Fragment() {
     private var _binding: FragmentScannerBinding? = null
     private val binding get() = _binding!!
     private lateinit var navController: NavController
+    private lateinit var networkObserver: NetworkObserver
 
     // Camera
     private var isBackCamera = true
@@ -71,6 +74,8 @@ class ScannerFragment : Fragment() {
         val root: View = binding.root
 
         navController = findNavController()
+        networkObserver = NetworkObserver(requireContext())
+
         cacheDir = requireContext().cacheDir
         contentResolver = requireContext().contentResolver
         apiClient = ApiClient()
@@ -86,7 +91,9 @@ class ScannerFragment : Fragment() {
         changeImage = registerForActivityResult(
             ActivityResultContracts.StartActivityForResult()
         ) {
-            if (it.resultCode == Activity.RESULT_OK) {
+            if (networkObserver.isConnected.value == false) {
+                Toast.makeText(requireContext(), "Tidak ada koneksi", Toast.LENGTH_SHORT).show()
+            } else if (it.resultCode == Activity.RESULT_OK) {
                 try {
                     val data = it.data
                     val imgUri = data?.data ?: throw Exception("Image Uri is null")
@@ -137,7 +144,11 @@ class ScannerFragment : Fragment() {
 
         binding.uploadButton.isClickable = false
         binding.uploadButton.setOnClickListener {
-            cameraImageFile?.let { it1 -> uploadPhoto(it1) }
+            if (networkObserver.isConnected.value == false) {
+                Toast.makeText(requireContext(), "Tidak ada koneksi", Toast.LENGTH_SHORT).show()
+            } else {
+                cameraImageFile?.let { it1 -> uploadPhoto(it1) }
+            }
         }
 
         return root
diff --git a/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt b/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt
index 5cef2c9ca4362d231fbfdf8fcfd4029621ae23f4..0e1b676e526758a09a346f67685df2147dcb20cd 100644
--- a/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt
+++ b/app/src/main/java/com/example/bondoyap/ui/settings/SettingsFragment.kt
@@ -1,11 +1,11 @@
 package com.example.bondoyap.ui.settings
 
+import EmailHelper
+import android.Manifest
 import android.app.AlertDialog
 import android.content.DialogInterface
 import android.content.Intent
 import android.content.pm.PackageManager
-import EmailHelper
-import android.content.Intent
 import android.net.Uri
 import android.os.Bundle
 import android.util.Log
@@ -21,19 +21,21 @@ import androidx.fragment.app.viewModels
 import androidx.lifecycle.ViewModelProvider
 import androidx.localbroadcastmanager.content.LocalBroadcastManager
 import com.example.bondoyap.databinding.FragmentSettingsBinding
+import com.example.bondoyap.service.NetworkObserver
 import com.example.bondoyap.service.api.Constants.ACTION_RANDOMIZE_TRANSACTIONS
 import com.example.bondoyap.ui.login.LoginActivity
 import com.example.bondoyap.ui.transactions.TransactionsApplication
 import com.example.bondoyap.ui.transactions.TransactionsViewModel
 import com.example.bondoyap.ui.transactions.TransactionsViewModelFactory
-import android.Manifest
 import java.io.File
 
 class SettingsFragment : Fragment() {
 
     private var _binding: FragmentSettingsBinding? = null
     private val binding get() = _binding!!
+
     private lateinit var settingsViewModel: SettingsViewModel
+    private lateinit var networkObserver: NetworkObserver
 
     private val transactionsViewModel: TransactionsViewModel by viewModels {
         TransactionsViewModelFactory((requireContext().applicationContext as TransactionsApplication).repository)
@@ -47,9 +49,18 @@ class SettingsFragment : Fragment() {
         savedInstanceState: Bundle?
     ): View {
         _binding = FragmentSettingsBinding.inflate(inflater, container, false)
-
-        if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
-            ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), PERMISSION_REQUEST_CODE)
+        networkObserver = NetworkObserver(requireContext())
+
+        if (ContextCompat.checkSelfPermission(
+                requireContext(),
+                Manifest.permission.WRITE_EXTERNAL_STORAGE
+            ) != PackageManager.PERMISSION_GRANTED
+        ) {
+            ActivityCompat.requestPermissions(
+                requireActivity(),
+                arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
+                PERMISSION_REQUEST_CODE
+            )
         }
 
         return binding.root
@@ -106,8 +117,16 @@ class SettingsFragment : Fragment() {
         // exporter = context?.let { TransactionsExporter(database, it) }!!
 
         saveButton.setOnClickListener {
-            if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
-                Toast.makeText(appContext, "Allow storage permission untuk menyimpan transaksi ke file xls/xlsx", Toast.LENGTH_SHORT).show()
+            if (ContextCompat.checkSelfPermission(
+                    requireContext(),
+                    Manifest.permission.WRITE_EXTERNAL_STORAGE
+                ) != PackageManager.PERMISSION_GRANTED
+            ) {
+                Toast.makeText(
+                    appContext,
+                    "Allow storage permission untuk menyimpan transaksi ke file xls/xlsx",
+                    Toast.LENGTH_SHORT
+                ).show()
             } else {
                 val formats = arrayOf("XLS", "XLSX")
                 val builder = AlertDialog.Builder(requireContext())
@@ -115,14 +134,31 @@ class SettingsFragment : Fragment() {
                 builder.setItems(formats) { dialog: DialogInterface, which: Int ->
                     when (which) {
                         0 -> {
-                            Toast.makeText(appContext, "Menyimpan transaksi ke xls...", Toast.LENGTH_SHORT).show()
+                            Toast.makeText(
+                                appContext,
+                                "Menyimpan transaksi ke xls...",
+                                Toast.LENGTH_SHORT
+                            ).show()
                             exporter.exportToXLS()
-                            Toast.makeText(appContext, "Penyimpanan xls pada folder Documents berhasil...", Toast.LENGTH_SHORT).show()
+                            Toast.makeText(
+                                appContext,
+                                "Penyimpanan xls pada folder Documents berhasil...",
+                                Toast.LENGTH_SHORT
+                            ).show()
                         }
+
                         1 -> {
-                            Toast.makeText(appContext, "Menyimpan transaksi ke xlsx...", Toast.LENGTH_SHORT).show()
+                            Toast.makeText(
+                                appContext,
+                                "Menyimpan transaksi ke xlsx...",
+                                Toast.LENGTH_SHORT
+                            ).show()
                             exporter.exportToXLSX()
-                            Toast.makeText(appContext, "Penyimpanan xlsx pada folder Documents berhasil...", Toast.LENGTH_SHORT).show()
+                            Toast.makeText(
+                                appContext,
+                                "Penyimpanan xlsx pada folder Documents berhasil...",
+                                Toast.LENGTH_SHORT
+                            ).show()
                         }
                     }
                     dialog.dismiss()
@@ -132,26 +168,38 @@ class SettingsFragment : Fragment() {
         }
 
         sendButton.setOnClickListener {
-            Toast.makeText(appContext, "Mengirimkan transaksi ...", Toast.LENGTH_SHORT).show()
-
-            var recipientEmail: String
-            val subject = "Transaksi Aplikasi Bondoman"
-            val message = "Halo, Berikut adalah detail transaksi aplikasi Bondoman.\n " +
-                    "File Transaksi terlampir."
-
-            settingsViewModel.getUser()?.let { user ->
-                recipientEmail = user.email
-                val attachment = getAttachmentUri("transactions.xls")
-                Log.d("Attachment", "Attachment URI: $attachment")
-                context?.let { EmailHelper(it) }?.sendGmail(recipientEmail, subject, message, attachment)
+            if (networkObserver.isConnected.value == false) {
+                Toast.makeText(requireContext(), "Tidak ada koneksi", Toast.LENGTH_SHORT).show()
+            } else {
+                Toast.makeText(appContext, "Mengirimkan transaksi ...", Toast.LENGTH_SHORT).show()
+
+                var recipientEmail: String
+                val subject = "Transaksi Aplikasi Bondoman"
+                val message = "Halo, Berikut adalah detail transaksi aplikasi Bondoman.\n " +
+                        "File Transaksi terlampir."
+
+                settingsViewModel.getUser()?.let { user ->
+                    recipientEmail = user.email
+                    val attachment = getAttachmentUri("transactions.xls")
+                    Log.d("Attachment", "Attachment URI: $attachment")
+                    context?.let { EmailHelper(it) }
+                        ?.sendGmail(recipientEmail, subject, message, attachment)
+                }
             }
         }
 
-        resetButton.setOnClickListener{
+        resetButton.setOnClickListener {
             Toast.makeText(appContext, "Transaksi di-reset ...", Toast.LENGTH_SHORT).show()
-            showConfirmationDialog("Reset", "Apakah Anda yakin ingin me-reset data transaksi?") {
+            showConfirmationDialog(
+                "Reset",
+                "Apakah Anda yakin ingin me-reset data transaksi?"
+            ) {
                 transactionsViewModel.deleteAllTransactions()
-                Toast.makeText(appContext, "Transaksi berhasil di-reset ...", Toast.LENGTH_SHORT).show()
+                Toast.makeText(
+                    appContext,
+                    "Transaksi berhasil di-reset ...",
+                    Toast.LENGTH_SHORT
+                ).show()
             }
         }
 
@@ -195,7 +243,11 @@ class SettingsFragment : Fragment() {
 
         Log.d("Attachment", "File path: ${fileCache.absolutePath}")
 
-        return FileProvider.getUriForFile(requireContext(), "${requireContext().packageName}.provider", fileCache)
+        return FileProvider.getUriForFile(
+            requireContext(),
+            "${requireContext().packageName}.provider",
+            fileCache
+        )
     }
 
     override fun onDestroyView() {