diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b27415d983e652133d2a97e1589f5466b2f0139c..1121e4ea78df542ef5edbb42ab0a8284fdfefa78 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -132,4 +132,7 @@ dependencies { implementation("androidx.camera:camera-video:$cameraxVersion") implementation("androidx.camera:camera-view:$cameraxVersion") implementation("androidx.camera:camera-extensions:$cameraxVersion") + + implementation("com.google.android.gms:play-services-location:17.0.0") + } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0105dde7a17b5881fa13bfc0fb72289e6bdaba37..dd0109049113a2495ced8eb1ae9dce4735bb56e5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,26 +6,33 @@ <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" /> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> + <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> + <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" - android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.BondoMan" tools:targetApi="31"> <activity android:name=".activities.LoginActivity" - android:exported="true"> <!-- Make sure to set exported="true" --> + android:exported="true" + android:windowSoftInputMode="adjustResize"> <!-- Make sure to set exported="true" --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <activity android:name=".activities.AddTransaction" /> - <activity android:name=".activities.EditTransaction" /> + <activity + android:name=".activities.AddTransaction" + android:theme="@style/Theme.BondoMan.ActionBar"/> + <activity + android:name=".activities.EditTransaction" + android:theme="@style/Theme.BondoMan.ActionBar"/> <activity android:name=".activities.MainActivity" android:exported="true" diff --git a/app/src/main/java/com/example/bondoman/activities/AddTransaction.kt b/app/src/main/java/com/example/bondoman/activities/AddTransaction.kt index 5b757bf5961186fdb4df2eb2f85a4963e9bd8323..1d3779673f07b82b4a606adf69711f9114ecebbc 100644 --- a/app/src/main/java/com/example/bondoman/activities/AddTransaction.kt +++ b/app/src/main/java/com/example/bondoman/activities/AddTransaction.kt @@ -1,20 +1,63 @@ package com.example.bondoman.activities +import android.Manifest import android.app.Activity import android.content.Intent import android.os.Bundle +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.content.pm.PackageManager +import android.location.Geocoder +import android.location.Location +import android.os.Bundle +import android.text.TextUtils +import android.util.Log import android.widget.ArrayAdapter import android.widget.Button import android.widget.EditText +import android.widget.Spinner import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat import com.example.bondoman.R -import android.widget.Spinner +import com.example.bondoman.services.TokenCheckService +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationServices +import java.io.IOException +import java.util.Locale class AddTransaction : AppCompatActivity() { + private lateinit var tokenExpiredReceiver: BroadcastReceiver + private lateinit var tokenServiceIntent : Intent + private var isReceiverRegistered = false + private lateinit var fusedLocationClient: FusedLocationProviderClient + private lateinit var locationText : EditText override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_add_transaksi) + tokenServiceIntent= Intent(this, TokenCheckService::class.java) + startService(tokenServiceIntent) + fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) + + tokenExpiredReceiver = object : BroadcastReceiver(){ + override fun onReceive(context: Context?, intent: Intent?) { + if(intent != null && intent.action != null){ + Log.e("Receive", intent.action.toString()) + } + if(intent?.action == "com.example.bondoman.TOKEN_EXPIRED"){ + val loginIntent = Intent(this@AddTransaction, LoginActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + } + stopService(tokenServiceIntent) + startActivity(loginIntent) + finish() + } + } + + } supportActionBar?.title = "Add Transaction" val editTextTitle = findViewById<EditText>(R.id.editTextTitle) @@ -35,11 +78,14 @@ class AddTransaction : AppCompatActivity() { spinnerCategory.adapter = adapter val submitButton : Button = findViewById(R.id.buttonSubmit) + locationText = findViewById(R.id.editTextLocation) submitButton.setOnClickListener { val title = editTextTitle.text.toString() val category = spinnerCategory.selectedItem.toString() val amount = editTextAmount.text.toString().toFloatOrNull() ?: 0f val location = editTextLocation.text.toString() + val amount = findViewById<EditText>(R.id.editTextAmount).text.toString().toFloatOrNull() ?: 0f + val location = locationText.text.toString() val replyIntent = Intent() if (title.isEmpty()) { @@ -53,14 +99,77 @@ class AddTransaction : AppCompatActivity() { } finish() } + getLastLocation() + } + + override fun onBackPressed() { + super.onBackPressed() + finish() + } + override fun onStart() { + super.onStart() + val filter = IntentFilter("com.example.bondoman.TOKEN_EXPIRED") + registerReceiver(tokenExpiredReceiver, filter) + isReceiverRegistered = true } + override fun onStop() { + super.onStop() + if (isReceiverRegistered) { + unregisterReceiver(tokenExpiredReceiver) + isReceiverRegistered = false + } + } + + override fun onDestroy() { + super.onDestroy() + if(isReceiverRegistered){ + unregisterReceiver(tokenExpiredReceiver) + stopService(tokenServiceIntent) + isReceiverRegistered = false + } + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + if (requestCode == REQUEST_LOCATION_PERMISSION) { + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + getLastLocation() + } + } + } + private fun getLastLocation() { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? -> + location?.let { + updateLocationEditTextWithPlaceName(location.latitude, location.longitude) + } + } + }else { + ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION_PERMISSION) + } + } + private fun updateLocationEditTextWithPlaceName(latitude: Double, longitude: Double) { + val geocoder = Geocoder(this, Locale.getDefault()) + try { + val addresses = geocoder.getFromLocation(latitude, longitude, 1) + if (addresses != null && addresses.isNotEmpty()) { + val address = addresses[0] + locationText.setText(address.getAddressLine(0).toString()) + } else { + locationText.setText("${latitude}, ${longitude}") + } + } catch (e: IOException) { + Log.e("Location", "Service Not Available", e) + } + } companion object { const val TITLE = "TITLE" const val TYPE = "TYPE" const val AMOUNT = "AMOUNT" const val LOCATION = "LOCATION" - } + const val REQUEST_LOCATION_PERMISSION = 1 // Define the constant here + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/activities/EditTransaction.kt b/app/src/main/java/com/example/bondoman/activities/EditTransaction.kt index c7ebc7d0e80ca7501904dad7efc568e5fe1b9864..ca10024840556fb159f2170f8efe56d482afa613 100644 --- a/app/src/main/java/com/example/bondoman/activities/EditTransaction.kt +++ b/app/src/main/java/com/example/bondoman/activities/EditTransaction.kt @@ -1,34 +1,55 @@ package com.example.bondoman.activities import android.app.Activity -import android.app.DatePickerDialog +import android.content.BroadcastReceiver +import android.content.Context import android.content.Intent -import android.graphics.Color +import android.content.IntentFilter +import android.net.Uri import android.os.Bundle -import android.view.View -import android.widget.ArrayAdapter +import android.util.Log import android.widget.Button -import android.widget.DatePicker import android.widget.EditText +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import com.example.bondoman.R -import android.widget.Spinner -import android.widget.TextView -import java.util.Calendar - +import com.example.bondoman.services.TokenCheckService class EditTransaction() : AppCompatActivity() { + private lateinit var tokenExpiredReceiver: BroadcastReceiver + private lateinit var tokenServiceIntent : Intent + private var isReceiverRegistered = false + private lateinit var location : EditText override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_edit_transaksi) + tokenServiceIntent= Intent(this, TokenCheckService::class.java) + startService(tokenServiceIntent) + + tokenExpiredReceiver = object : BroadcastReceiver(){ + override fun onReceive(context: Context?, intent: Intent?) { + if(intent != null && intent.action != null){ + Log.e("Receive", intent.action.toString()) + } + if(intent?.action == "com.example.bondoman.TOKEN_EXPIRED"){ + val loginIntent = Intent(this@EditTransaction, LoginActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + } + stopService(tokenServiceIntent) + startActivity(loginIntent) + finish() + } + } + + } supportActionBar?.title = "Edit Transaction" val date : TextView = findViewById(R.id.editTextDate) val type : TextView = findViewById(R.id.editTextType) val title : EditText = findViewById(R.id.editTextTitle) val amount : EditText = findViewById(R.id.editTextAmount) - val location : EditText = findViewById(R.id.editTextLocation) - + location = findViewById(R.id.editTextLocation) + val seeLocationText : TextView = findViewById(R.id.textViewSeeLocationLabel) val intentData = intent title.setText(intentData?.getStringExtra("title") ?: "") @@ -65,6 +86,45 @@ class EditTransaction() : AppCompatActivity() { } finish() } + seeLocationText.setOnClickListener { + seeLocation() + } + } + + override fun onBackPressed() { + super.onBackPressed() + finish() + } + + override fun onStart() { + super.onStart() + val filter = IntentFilter("com.example.bondoman.TOKEN_EXPIRED") + registerReceiver(tokenExpiredReceiver, filter) + isReceiverRegistered = true + } + + override fun onStop() { + super.onStop() + if (isReceiverRegistered) { + unregisterReceiver(tokenExpiredReceiver) + isReceiverRegistered = false + } + } + + override fun onDestroy() { + super.onDestroy() + if(isReceiverRegistered){ + unregisterReceiver(tokenExpiredReceiver) + stopService(tokenServiceIntent) + isReceiverRegistered = false + } + } + private fun seeLocation(){ + val locationText = location.text.toString() + val gmmIntentUri = Uri.parse("geo:0,0?q=$locationText") + val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri) + mapIntent.setPackage("com.google.android.apps.maps") + startActivity(mapIntent) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/activities/LoginActivity.kt b/app/src/main/java/com/example/bondoman/activities/LoginActivity.kt index bf4a9d2737e7144514241de446ac8403fb484bb1..2c8e505e2c9468c16d6986719898abb10f1b2ea9 100644 --- a/app/src/main/java/com/example/bondoman/activities/LoginActivity.kt +++ b/app/src/main/java/com/example/bondoman/activities/LoginActivity.kt @@ -1,47 +1,115 @@ package com.example.bondoman.activities +import android.animation.ObjectAnimator +import android.app.Dialog import android.content.Intent -import androidx.appcompat.app.AppCompatActivity +import android.graphics.Color +import android.graphics.drawable.ColorDrawable import android.os.Bundle +import android.os.Handler +import android.util.DisplayMetrics +import android.view.animation.Animation +import android.view.animation.AnimationUtils +import android.view.animation.TranslateAnimation +import android.util.Log import android.widget.Button import android.widget.EditText +import android.widget.ImageView import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.cardview.widget.CardView import androidx.lifecycle.lifecycleScope import com.example.bondoman.R -import com.example.bondoman.apiServices.IAuthService import com.example.bondoman.lib.SecurePreferences -import com.example.bondoman.repositories.LoginRepository -import com.example.bondoman.retrofits.Retro +import com.example.bondoman.repositories.AuthRepository import kotlinx.coroutines.launch +import kotlin.math.log class LoginActivity : AppCompatActivity() { private lateinit var email : EditText private lateinit var password : EditText private lateinit var loginButton: Button - private lateinit var loginRepository: LoginRepository + private lateinit var loginRepository: AuthRepository + private var loadingDialog: Dialog? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) - val authService = Retro().getRetroClientInstance().create(IAuthService::class.java) - val securePreferences = SecurePreferences(this) + Handler().postDelayed({ + // Transition to the login screen after SPLASH_DURATION + val cardLogin = findViewById<CardView>(R.id.login_card) + val logo = findViewById<ImageView>(R.id.imageView) + + val slideUpAnimation = AnimationUtils.loadAnimation(this@LoginActivity, R.anim.slide_up) + val finalY = cardLogin.y + (cardLogin.height - logo.height) / 2 + + val animatorY = ObjectAnimator.ofFloat(logo, "translationY", 0f + logo.height, finalY) + animatorY.duration = 600 + + animatorY.start() + cardLogin.startAnimation(slideUpAnimation) + cardLogin.visibility = CardView.VISIBLE + }, 1000) + + + Handler().postDelayed({ + // Transition to the login screen after SPLASH_DURATION + val cardLogin = findViewById<CardView>(R.id.login_card) + val logo = findViewById<ImageView>(R.id.imageView) + + val slideUpAnimation = AnimationUtils.loadAnimation(this@LoginActivity, R.anim.slide_up) + val finalY = cardLogin.y + (cardLogin.height - logo.height) / 2 + + val animatorY = ObjectAnimator.ofFloat(logo, "translationY", 0f + logo.height, finalY) + animatorY.duration = 600 - loginRepository = LoginRepository(authService, securePreferences) + animatorY.start() + cardLogin.startAnimation(slideUpAnimation) + cardLogin.visibility = CardView.VISIBLE + }, 1000) + + val securePreferences = SecurePreferences(this) + loginRepository = AuthRepository(securePreferences) + if(securePreferences.getToken() != null){ + val intent = Intent(this@LoginActivity, MainActivity::class.java) + startActivity(intent) + finish() + } email = findViewById(R.id.email) password = findViewById(R.id.password) loginButton = findViewById<Button>(R.id.login_button) loginButton.setOnClickListener{ lifecycleScope.launch { - val result = loginRepository.login(email.text.toString(), password.text.toString()) - if(result.isSuccess){ - val intent = Intent(this@LoginActivity, MainActivity::class.java) - startActivity(intent) - }else{ - val message = result.exceptionOrNull()?.message ?: "Login failed!" - Toast.makeText(this@LoginActivity, message, Toast.LENGTH_LONG).show() - } + login(email.text.toString(), password.text.toString()) } } } + + private suspend fun login(email : String, password : String){ + showLoadingDialog() + val result = loginRepository.login(email, password) + hideLoadingDialog() + if(result.isSuccess){ + val intent = Intent(this@LoginActivity, MainActivity::class.java) + startActivity(intent) + finish() + }else{ + val message = result.exceptionOrNull()?.message ?: "Login failed!" + Toast.makeText(this@LoginActivity, message, Toast.LENGTH_LONG).show() + } + } + private fun showLoadingDialog() { + loadingDialog = Dialog(this).apply { + setContentView(R.layout.loading) + setCancelable(false) + window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + show() + } + } + + private fun hideLoadingDialog() { + loadingDialog?.dismiss() + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/activities/MainActivity.kt b/app/src/main/java/com/example/bondoman/activities/MainActivity.kt index 56ee2a9ed2b49925f97bf5a4c0fece86c4ecdf8b..362f4d80ac01afe2260371c9d12f1515352a3642 100644 --- a/app/src/main/java/com/example/bondoman/activities/MainActivity.kt +++ b/app/src/main/java/com/example/bondoman/activities/MainActivity.kt @@ -32,7 +32,9 @@ class MainActivity : AppCompatActivity() { Log.e("Receive", intent.action.toString()) } if(intent?.action == "com.example.bondoman.TOKEN_EXPIRED"){ - val loginIntent = Intent(this@MainActivity, LoginActivity::class.java) + val loginIntent = Intent(this@MainActivity, LoginActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + } stopService(tokenServiceIntent) startActivity(loginIntent) finish() @@ -78,7 +80,6 @@ class MainActivity : AppCompatActivity() { } } - override fun onDestroy() { super.onDestroy() if(isReceiverRegistered){ diff --git a/app/src/main/java/com/example/bondoman/adapter/RecyclerViewAdapter.kt b/app/src/main/java/com/example/bondoman/adapter/RecyclerViewAdapter.kt index c579deb752c851a599164a896d57af4ee392a36d..f902d359ea6774fb28232564d0ce48dca4bdd2df 100644 --- a/app/src/main/java/com/example/bondoman/adapter/RecyclerViewAdapter.kt +++ b/app/src/main/java/com/example/bondoman/adapter/RecyclerViewAdapter.kt @@ -4,10 +4,7 @@ import android.content.Intent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.Button -import android.widget.TextView import androidx.cardview.widget.CardView -import androidx.core.content.ContextCompat.startActivity import androidx.lifecycle.LiveData import androidx.recyclerview.widget.RecyclerView import com.example.bondoman.R diff --git a/app/src/main/java/com/example/bondoman/adapter/TransactionListAdapter.kt b/app/src/main/java/com/example/bondoman/adapter/TransactionListAdapter.kt index e37a2be9ad8340150ce60768fbc2e38e4104e2f0..81dbe187d02afcea8788ffa240d159765a87f347 100644 --- a/app/src/main/java/com/example/bondoman/adapter/TransactionListAdapter.kt +++ b/app/src/main/java/com/example/bondoman/adapter/TransactionListAdapter.kt @@ -6,20 +6,19 @@ import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.cardview.widget.CardView -import androidx.lifecycle.LiveData import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.example.bondoman.R import com.example.bondoman.activities.EditTransaction import com.example.bondoman.entities.Transaction +import com.example.bondoman.lib.SecurePreferences import com.example.bondoman.viewModels.TransactionsViewModel -import java.text.SimpleDateFormat import java.time.LocalDate import java.time.format.DateTimeFormatter import java.util.Locale -class TransactionListAdapter(private val transactions : TransactionsViewModel, private val startEditIntent: (Intent) -> Unit) : ListAdapter<Transaction, TransactionListAdapter.TransactionViewHolder>(TransactionComparator()) { +class TransactionListAdapter(private val transactions : TransactionsViewModel, private val startEditIntent: (Intent) -> Unit, securePreferences: SecurePreferences) : ListAdapter<Transaction, TransactionListAdapter.TransactionViewHolder>(TransactionComparator()) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionViewHolder { return TransactionViewHolder.create(parent, transactions, startEditIntent) diff --git a/app/src/main/java/com/example/bondoman/apiServices/IAuthService.kt b/app/src/main/java/com/example/bondoman/apiServices/IAuthService.kt index 9112f0914cc5e33a9a6c2572a9499121eacdbf37..172847f50a5d6a714e14a4476d4b1e2dc0a53c27 100644 --- a/app/src/main/java/com/example/bondoman/apiServices/IAuthService.kt +++ b/app/src/main/java/com/example/bondoman/apiServices/IAuthService.kt @@ -1,6 +1,5 @@ package com.example.bondoman.apiServices -import retrofit2.Call import retrofit2.http.Body import retrofit2.http.Header import retrofit2.http.POST diff --git a/app/src/main/java/com/example/bondoman/fragments/GrafFragment.kt b/app/src/main/java/com/example/bondoman/fragments/GrafFragment.kt index caeb1bd6a6915ba89bce214f23d152a369b8e0ed..c81b5a2e52e0a29d08cb39b127ef2a50e77f48e5 100644 --- a/app/src/main/java/com/example/bondoman/fragments/GrafFragment.kt +++ b/app/src/main/java/com/example/bondoman/fragments/GrafFragment.kt @@ -11,6 +11,7 @@ import com.example.bondoman.database.TransactionDatabase import com.example.bondoman.databinding.FragmentGrafBinding import com.example.bondoman.entities.Transaction import com.example.bondoman.lib.ITransactionGraphAdapter +import com.example.bondoman.lib.SecurePreferences import com.example.bondoman.lib.TransactionPieChartAdapter import com.example.bondoman.repositories.TransactionRepository import com.example.bondoman.viewModels.TransactionViewModelFactory @@ -23,13 +24,14 @@ class GrafFragment : Fragment() { private var _binding: FragmentGrafBinding? = null private val binding get() = _binding!! private lateinit var graphAdapter: ITransactionGraphAdapter<PieChart> + private lateinit var securePreferences: SecurePreferences private val transactionViewModel: TransactionsViewModel by viewModels { TransactionViewModelFactory( TransactionRepository( TransactionDatabase.getInstance(requireContext(), CoroutineScope( SupervisorJob() ) - ).transactionDao()) + ).transactionDao(), securePreferences) ) } private lateinit var transactions: List<Transaction> @@ -37,6 +39,8 @@ class GrafFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) graphAdapter = TransactionPieChartAdapter() + securePreferences = SecurePreferences(requireContext()) + Log.i("EMAIL", securePreferences.getEmail() ?: "KOSONG") transactionViewModel.allTransaction.observe(this) { transactions = it } diff --git a/app/src/main/java/com/example/bondoman/fragments/LoginFragment.kt b/app/src/main/java/com/example/bondoman/fragments/LoginFragment.kt deleted file mode 100644 index 6b675b758f5f98858c81107c008f023111b5bb3b..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/fragments/LoginFragment.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.bondoman.fragments - -import android.os.Bundle -import androidx.fragment.app.Fragment -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.example.bondoman.R - -class LoginFragment : Fragment() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - } - - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_login, container, false) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/fragments/ScanFragment.kt b/app/src/main/java/com/example/bondoman/fragments/ScanFragment.kt index e3b6b0bb39b8af2d1bc669fd9803005b2e669a4e..d565eb2215871a2db1d0506260902d5cf3a65b36 100644 --- a/app/src/main/java/com/example/bondoman/fragments/ScanFragment.kt +++ b/app/src/main/java/com/example/bondoman/fragments/ScanFragment.kt @@ -19,7 +19,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button -import android.widget.ListView import android.widget.TextView import android.widget.Toast import androidx.camera.core.CameraSelector @@ -29,9 +28,7 @@ import androidx.camera.core.ImageProxy 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.content.FileProvider import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope @@ -45,7 +42,6 @@ import com.example.bondoman.viewModels.TransactionViewModelFactory import com.example.bondoman.viewModels.TransactionsViewModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -64,7 +60,7 @@ class ScanFragment : Fragment() { TransactionDatabase.getInstance(requireContext(), CoroutineScope( SupervisorJob() ) - ).transactionDao()) + ).transactionDao(), securePreferences) ) } private var loadingDialog: Dialog? = null @@ -253,7 +249,7 @@ class ScanFragment : Fragment() { } private fun showLoadingDialog() { loadingDialog = Dialog(requireContext()).apply { - setContentView(R.layout.loading_upload) + setContentView(R.layout.loading) setCancelable(false) window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) show() @@ -294,7 +290,6 @@ class ScanFragment : Fragment() { return imageFile } - companion object { private const val REQUEST_CODE_PERMISSIONS = 10 private val REQUIRED_PERMISSIONS = diff --git a/app/src/main/java/com/example/bondoman/fragments/SettingsFragment.kt b/app/src/main/java/com/example/bondoman/fragments/SettingsFragment.kt index 7075f070133f6a846cf35185a9d073c1921a47be..b3fef09cf849add6a337c936ecb780d8c9d94ef6 100644 --- a/app/src/main/java/com/example/bondoman/fragments/SettingsFragment.kt +++ b/app/src/main/java/com/example/bondoman/fragments/SettingsFragment.kt @@ -2,19 +2,23 @@ package com.example.bondoman.fragments import android.content.Intent + import android.net.Uri import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.TextView +import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.core.content.FileProvider -import androidx.core.net.toUri import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope +import com.example.bondoman.R +import com.example.bondoman.activities.LoginActivity import com.example.bondoman.database.TransactionDatabase import com.example.bondoman.databinding.FragmentSettingsBinding import com.example.bondoman.entities.Transaction @@ -22,6 +26,7 @@ import com.example.bondoman.lib.ITransactionFileAdapter import com.example.bondoman.lib.SecurePreferences import com.example.bondoman.lib.TransactionDownloader import com.example.bondoman.lib.TransactionExcelAdapter +import com.example.bondoman.repositories.AuthRepository import com.example.bondoman.repositories.TransactionRepository import com.example.bondoman.viewModels.TransactionViewModelFactory import com.example.bondoman.viewModels.TransactionsViewModel @@ -31,6 +36,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.async import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.File import java.io.FileOutputStream import java.text.SimpleDateFormat @@ -41,6 +47,7 @@ import kotlin.random.Random class SettingsFragment : Fragment() { private var _binding: FragmentSettingsBinding? = null private val binding get() = _binding!! + private lateinit var securePreferences: SecurePreferences private val transactionViewModel: TransactionsViewModel by viewModels { TransactionViewModelFactory( TransactionRepository( @@ -49,25 +56,27 @@ class SettingsFragment : Fragment() { CoroutineScope( SupervisorJob() ) - ).transactionDao() + ).transactionDao(), securePreferences ) ) } + private lateinit var authRepository: AuthRepository private lateinit var transactions: List<Transaction> private lateinit var transactionFileAdapter: ITransactionFileAdapter private lateinit var transactionDownloader: TransactionDownloader - private lateinit var securePreferences: SecurePreferences private val XLSX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" private val XLS_MIME_TYPE = "application/vnd.ms-excel" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + securePreferences = SecurePreferences(requireContext()) transactionViewModel.allTransaction.observe(this) { transactions = it } transactionFileAdapter = TransactionExcelAdapter() transactionDownloader = TransactionDownloader() - securePreferences = SecurePreferences(requireContext()) + authRepository = AuthRepository(SecurePreferences(requireContext())) + } override fun onCreateView( @@ -89,9 +98,36 @@ class SettingsFragment : Fragment() { } binding.randomizeButton.setOnClickListener { broadcastRandomizeTransaction() + binding.logoutButton.setOnClickListener{ + lifecycleScope.launch { + showLoading() + logout() + hideLoading() + } } } + private suspend fun logout() { + val response = authRepository.logout() + if (response.isSuccess) { + val intent = Intent(requireActivity(), LoginActivity::class.java) + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + startActivity(intent) + requireActivity().finish() + }else{ + withContext(Dispatchers.Main) { + val layoutInflater = LayoutInflater.from(requireContext()) + val view = layoutInflater.inflate(R.layout.custom_toast, null) + val textView = view.findViewById<TextView>(R.id.customToastText) + textView.text = "Logout failed, please try again!" + with (Toast(requireContext())) { + duration = Toast.LENGTH_LONG + setView(view) + show() + } + } + } + } private fun showLoading() { binding.loadingAnimation.isVisible = true } diff --git a/app/src/main/java/com/example/bondoman/fragments/TransaksiFragment.kt b/app/src/main/java/com/example/bondoman/fragments/TransaksiFragment.kt index 01244ec2ef1814a277bcf9a211784ff33584bb4f..c62887fd669ca369a7933b385c8d784adc43ade0 100644 --- a/app/src/main/java/com/example/bondoman/fragments/TransaksiFragment.kt +++ b/app/src/main/java/com/example/bondoman/fragments/TransaksiFragment.kt @@ -7,17 +7,16 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.Toast import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.example.bondoman.R import com.example.bondoman.activities.AddTransaction -import com.example.bondoman.activities.EditTransaction import com.example.bondoman.adapter.TransactionListAdapter import com.example.bondoman.database.TransactionDatabase import com.example.bondoman.entities.Transaction +import com.example.bondoman.lib.SecurePreferences import com.example.bondoman.repositories.TransactionRepository import com.example.bondoman.viewModels.TransactionViewModelFactory import com.example.bondoman.viewModels.TransactionsViewModel @@ -30,30 +29,29 @@ class TransaksiFragment : Fragment() { private lateinit var adapter: TransactionListAdapter private val newTransactionRequestCode = 1 private val editTransactionRequestCode = 2 + private lateinit var securePreferences: SecurePreferences private val wordViewModel: TransactionsViewModel by viewModels { TransactionViewModelFactory( TransactionRepository( TransactionDatabase.getInstance(requireContext(), CoroutineScope( SupervisorJob() ) - ).transactionDao()) + ).transactionDao(), securePreferences) ) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + securePreferences = SecurePreferences(requireContext()) } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_transaksi, container, false) - - val recyclerView: RecyclerView = view.findViewById(R.id.recycler_view) - adapter = TransactionListAdapter(wordViewModel, ::itemEditRequest) + adapter = TransactionListAdapter(wordViewModel, ::itemEditRequest, securePreferences) recyclerView.layoutManager = LinearLayoutManager(requireContext()) recyclerView.adapter = adapter @@ -76,8 +74,6 @@ class TransaksiFragment : Fragment() { override fun onActivityResult(requestCode: Int, resultCode: Int, intentData: Intent?) { super.onActivityResult(requestCode, resultCode, intentData) - Log.i("Masuk", "Masuk") - if (requestCode == newTransactionRequestCode && resultCode == Activity.RESULT_OK) { val title = intentData?.getStringExtra(AddTransaction.TITLE) ?: "" val amount = intentData?.getFloatExtra(AddTransaction.AMOUNT, 0.0f) ?: 0.0f @@ -91,7 +87,7 @@ class TransaksiFragment : Fragment() { amount = amount, location = location, date = Date(), - userEmail = "testing" + userEmail = securePreferences.getEmail() ?: "" ) wordViewModel.insert(transaction) } else if (requestCode == editTransactionRequestCode && resultCode == Activity.RESULT_OK) { diff --git a/app/src/main/java/com/example/bondoman/fragments/TwibbonFragment.kt b/app/src/main/java/com/example/bondoman/fragments/TwibbonFragment.kt index 186730e5ed5fbb0bf0d5d7213371f969ebaa5fb7..a69442a1dce9773f2d8a187dc44c084ad07dfa2c 100644 --- a/app/src/main/java/com/example/bondoman/fragments/TwibbonFragment.kt +++ b/app/src/main/java/com/example/bondoman/fragments/TwibbonFragment.kt @@ -4,10 +4,7 @@ import android.Manifest import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.BitmapFactory -import android.graphics.ImageFormat import android.graphics.Matrix -import android.graphics.Rect -import android.graphics.YuvImage import android.hardware.camera2.CameraCharacteristics import android.media.ExifInterface import android.media.Image @@ -34,7 +31,6 @@ import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import com.example.bondoman.R import java.io.ByteArrayInputStream -import java.io.ByteArrayOutputStream import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -186,7 +182,7 @@ class TwibbonFragment : Fragment() { val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) // Rotate the bitmap if necessary - return rotateBitmap(bitmap, 90f, true) + return rotateBitmap(bitmap, 0f, true) } diff --git a/app/src/main/java/com/example/bondoman/interfaces/ITransactionDao.kt b/app/src/main/java/com/example/bondoman/interfaces/ITransactionDao.kt index a7502af0b3eb7bd154f2e6f7a16e8d73ba4e9a10..4c21ee91af898bd67eeba11bcd7192607811cf8c 100644 --- a/app/src/main/java/com/example/bondoman/interfaces/ITransactionDao.kt +++ b/app/src/main/java/com/example/bondoman/interfaces/ITransactionDao.kt @@ -13,7 +13,7 @@ import kotlinx.coroutines.flow.Flow @Dao interface ITransactionDao { - @Query("SELECT * FROM transactions WHERE userEmail = :userEmail OR userEmail != :userEmail ORDER BY date DESC") + @Query("SELECT * FROM transactions WHERE userEmail = :userEmail ORDER BY date DESC") fun getAll(userEmail : String): Flow<List<Transaction>> @Insert(onConflict = OnConflictStrategy.IGNORE) suspend fun insert(transaction: Transaction) diff --git a/app/src/main/java/com/example/bondoman/repositories/LoginRepository.kt b/app/src/main/java/com/example/bondoman/repositories/AuthRepository.kt similarity index 69% rename from app/src/main/java/com/example/bondoman/repositories/LoginRepository.kt rename to app/src/main/java/com/example/bondoman/repositories/AuthRepository.kt index 82998c5f4beec7491f7253c01d8150931988a50b..5192451aed57d31f4e931e2d2897d8ba7a52de2d 100644 --- a/app/src/main/java/com/example/bondoman/repositories/LoginRepository.kt +++ b/app/src/main/java/com/example/bondoman/repositories/AuthRepository.kt @@ -4,10 +4,12 @@ import android.util.Log import com.example.bondoman.apiServices.IAuthService import com.example.bondoman.apiServices.LoginRequest import com.example.bondoman.lib.SecurePreferences +import com.example.bondoman.retrofits.Retro -class LoginRepository(private val authService: IAuthService, private val securePreferences : SecurePreferences) { +class AuthRepository(private val securePreferences : SecurePreferences) { suspend fun login(email: String, password: String) : Result<String>{ + val authService = Retro().getRetroClientInstance().create(IAuthService::class.java) val request = LoginRequest().apply { this.email = email.trim() this.password = password @@ -29,4 +31,12 @@ class LoginRepository(private val authService: IAuthService, private val secureP Result.failure(e) } } + suspend fun logout() : Result<String>{ + return try { + securePreferences.clear() + Result.success("succes logout") + }catch (e : Exception){ + Result.failure(e) + } + } } diff --git a/app/src/main/java/com/example/bondoman/repositories/ScanRepository.kt b/app/src/main/java/com/example/bondoman/repositories/ScanRepository.kt index 414331bd0da6892bb5100b4a81ab9e5d7400b65a..c0de84668cb5d2de36e62eed625968507043ca4b 100644 --- a/app/src/main/java/com/example/bondoman/repositories/ScanRepository.kt +++ b/app/src/main/java/com/example/bondoman/repositories/ScanRepository.kt @@ -17,10 +17,8 @@ class ScanRepository(private val context : Context) { val requestFile = file.asRequestBody("image/jpg".toMediaTypeOrNull()) val body = MultipartBody.Part.createFormData("file", file.name, requestFile) val token = SecurePreferences(context).getToken() - Log.d("Token", "Bearer $token") - val response = Retro().getRetroClientInstance().create(IScanService::class.java).scan("Bearer $token", body) - Log.d("Response", response.toString()) - return response + val response = Retro().getRetroClientInstance().create(IScanService::class.java) + return response.scan("Bearer $token", body) } catch (e: Exception) { Log.e("UploadPhoto", "Error uploading photo", e) throw e // Re-throw if you want to handle it in the calling code diff --git a/app/src/main/java/com/example/bondoman/repositories/TransactionRepository.kt b/app/src/main/java/com/example/bondoman/repositories/TransactionRepository.kt index f6d0e13f6a8398012bd0f97d05ba03fd092afa1d..2ee2b3dbfb4a0412d887d8103e3cce9141ba1f8a 100644 --- a/app/src/main/java/com/example/bondoman/repositories/TransactionRepository.kt +++ b/app/src/main/java/com/example/bondoman/repositories/TransactionRepository.kt @@ -3,10 +3,11 @@ package com.example.bondoman.repositories import androidx.annotation.WorkerThread import com.example.bondoman.entities.Transaction import com.example.bondoman.interfaces.ITransactionDao +import com.example.bondoman.lib.SecurePreferences import kotlinx.coroutines.flow.Flow -class TransactionRepository(private val transactionDao: ITransactionDao) { - val allTransaction : Flow<List<Transaction>> = transactionDao.getAll("testing") +class TransactionRepository(private val transactionDao: ITransactionDao, securePreferences: SecurePreferences) { + val allTransaction : Flow<List<Transaction>> = transactionDao.getAll(securePreferences.getEmail() ?: "") @Suppress("RedundantSuspendModifier") @WorkerThread diff --git a/app/src/main/res/anim/slide_down.xml b/app/src/main/res/anim/slide_down.xml new file mode 100644 index 0000000000000000000000000000000000000000..dd5f914d5569462d0cd3e7633f937fb00e294322 --- /dev/null +++ b/app/src/main/res/anim/slide_down.xml @@ -0,0 +1,10 @@ +<!-- slide_up.xml --> +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:fillAfter="true" + android:interpolator="@android:anim/accelerate_interpolator"> + + <translate + android:fromYDelta="100%p" + android:toYDelta="0" + android:duration="500" /> +</set> \ No newline at end of file diff --git a/app/src/main/res/anim/slide_morph.xml b/app/src/main/res/anim/slide_morph.xml new file mode 100644 index 0000000000000000000000000000000000000000..96353fd82b58e719905de0262feb6666889a831c --- /dev/null +++ b/app/src/main/res/anim/slide_morph.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate + android:fromYDelta="50%p" + android:toYDelta="0" + android:duration="500" /> +</set> \ No newline at end of file diff --git a/app/src/main/res/anim/slide_up.xml b/app/src/main/res/anim/slide_up.xml new file mode 100644 index 0000000000000000000000000000000000000000..22dbcee13e1cfad038b8039dbae7bf6144398c68 --- /dev/null +++ b/app/src/main/res/anim/slide_up.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate + android:fromYDelta="100%p" + android:toYDelta="0" + android:duration="500"/> +</set> \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000000000000000000000000000000000000..d52a85d7b663e9a892310ff7faccf2bd6157f31e --- /dev/null +++ b/app/src/main/res/drawable/ic_search.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#000000" + android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zm-6,0C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/> +</vector> diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 4bf4fb7b3ad9a0a5d0a6cd6e6b96f2d5e47c5945..115690c103b163558e111b8c5ab9e9073f9b0792 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -6,126 +6,130 @@ android:layout_height="match_parent" tools:context=".activities.LoginActivity" android:paddingHorizontal="20dp" + android:layout_gravity="center" > - - <ImageView - android:id="@+id/imageView" - android:layout_width="266dp" - android:layout_height="94dp" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.496" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintVertical_bias="0.262" - app:srcCompat="@drawable/bondoman" - /> - - <androidx.cardview.widget.CardView + <LinearLayout android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginHorizontal="40dp" - android:layout_marginEnd="8dp" - app:cardCornerRadius="30dp" - app:cardElevation="4dp" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toBottomOf="@+id/imageView" - app:layout_constraintVertical_bias="0.1" - app:cardBackgroundColor="@color/white"> + android:layout_height="match_parent" + android:orientation="vertical" + android:gravity="center"> + <ImageView + android:id="@+id/imageView" + android:layout_width="266dp" + android:layout_height="94dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/bondoman" + /> - <LinearLayout + <androidx.cardview.widget.CardView + android:visibility="gone" + android:id="@+id/login_card" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginHorizontal="20dp" - android:layout_marginVertical="30dp" - android:orientation="vertical" - > - <TextView - android:id="@+id/textView" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:fontFamily="@font/montserrat_600" - android:text="Masuk" - android:textAlignment="center" - android:textColor="@color/black" - android:textColorHint="@color/black" - android:textSize="24sp" - android:textStyle="bold" /> + android:layout_marginHorizontal="40dp" + android:layout_marginEnd="8dp" + app:cardCornerRadius="30dp" + app:cardElevation="4dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/imageView" + app:layout_constraintVertical_bias="0.1" + app:cardBackgroundColor="@color/white"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginHorizontal="20dp" + android:layout_marginVertical="30dp" android:orientation="vertical" - android:layout_marginTop="12dp" > - <TextView + android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="10dp" - android:fontFamily="@font/montserrat_500" - android:text="Email" + android:fontFamily="@font/montserrat_600" + android:text="Masuk" + android:textAlignment="center" android:textColor="@color/black" - android:textSize="14sp" /> - <EditText - android:layout_width="match_parent" - android:layout_height="40dp" - android:id="@+id/email" - android:background="@drawable/input_bg" - android:layout_marginTop="10dp" - android:paddingHorizontal="15dp" - /> - </LinearLayout> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:layout_marginTop="15dp" - > - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="10dp" - android:fontFamily="@font/montserrat_500" - android:text="Password" - android:textColor="@color/black" - android:textSize="14sp" /> - <com.google.android.material.textfield.TextInputLayout + android:textColorHint="@color/black" + android:textSize="24sp" + android:textStyle="bold" /> + + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - app:passwordToggleEnabled="true" + android:orientation="vertical" + android:layout_marginTop="12dp" > + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:fontFamily="@font/montserrat_500" + android:text="Email" + android:textColor="@color/black" + android:textSize="14sp" /> <EditText android:layout_width="match_parent" android:layout_height="40dp" - android:id="@+id/password" + android:id="@+id/email" + android:inputType="textEmailAddress" android:background="@drawable/input_bg" android:layout_marginTop="10dp" android:paddingHorizontal="15dp" - android:inputType="textPassword" /> - </com.google.android.material.textfield.TextInputLayout> - - </LinearLayout> - - <Button - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:id="@+id/login_button" - android:fontFamily="@font/montserrat_700" - android:background="@drawable/rounded_button" - android:text="Masuk" - android:layout_marginTop="20dp" - android:layout_gravity="center_horizontal" - android:textColor="@color/white" - android:paddingHorizontal="15dp" - /> - </LinearLayout> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_marginTop="15dp" + > + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:fontFamily="@font/montserrat_500" + android:text="Password" + android:textColor="@color/black" + android:textSize="14sp" /> + <com.google.android.material.textfield.TextInputLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + app:passwordToggleEnabled="true" + > + <EditText + android:layout_width="match_parent" + android:layout_height="40dp" + android:id="@+id/password" + android:background="@drawable/input_bg" + android:layout_marginTop="10dp" + android:paddingHorizontal="15dp" + android:inputType="textPassword" + /> + </com.google.android.material.textfield.TextInputLayout> + </LinearLayout> - </androidx.cardview.widget.CardView> + <Button + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/login_button" + android:fontFamily="@font/montserrat_700" + android:background="@drawable/rounded_button" + android:text="Masuk" + android:layout_marginTop="20dp" + android:layout_gravity="center_horizontal" + android:textColor="@color/white" + android:paddingHorizontal="15dp" + /> + </LinearLayout> + </androidx.cardview.widget.CardView> + </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout/fragment_login.xml deleted file mode 100644 index 251d39abf35242a9e567456828093131d873dc21..0000000000000000000000000000000000000000 --- a/app/src/main/res/layout/fragment_login.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?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.LoginFragment"> - - <!-- TODO: Update blank fragment layout --> - - <androidx.constraintlayout.widget.ConstraintLayout - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <TextView - android:layout_width="208dp" - android:layout_height="47dp" - android:text="@string/hello_blank_fragment" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> - </androidx.constraintlayout.widget.ConstraintLayout> - -</FrameLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/loading_upload.xml b/app/src/main/res/layout/loading.xml similarity index 67% rename from app/src/main/res/layout/loading_upload.xml rename to app/src/main/res/layout/loading.xml index b3a7629f21bae074144cb04a9ac4328cd5b0f68a..cd4a2cfa9d47365470d0ddefaac4aa4075863165 100644 --- a/app/src/main/res/layout/loading_upload.xml +++ b/app/src/main/res/layout/loading.xml @@ -11,11 +11,4 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="Uploading..." - android:layout_marginTop="10dp" - android:textColor="@android:color/white" /> - </LinearLayout> diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000000000000000000000000000000000..90f958096f81d050d55c085b7c3bad49456f9673 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@mipmap/ic_launcher_adaptive_back"/> + <foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/> +</adaptive-icon> \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/app/src/main/res/mipmap-anydpi/ic_launcher.xml deleted file mode 100644 index 6f3b755bf50c6b03d8714a9c6184705e6a08389f..0000000000000000000000000000000000000000 --- a/app/src/main/res/mipmap-anydpi/ic_launcher.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@drawable/ic_launcher_background" /> - <foreground android:drawable="@drawable/ic_launcher_foreground" /> - <monochrome android:drawable="@drawable/ic_launcher_foreground" /> -</adaptive-icon> \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml deleted file mode 100644 index 6f3b755bf50c6b03d8714a9c6184705e6a08389f..0000000000000000000000000000000000000000 --- a/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@drawable/ic_launcher_background" /> - <foreground android:drawable="@drawable/ic_launcher_foreground" /> - <monochrome android:drawable="@drawable/ic_launcher_foreground" /> -</adaptive-icon> \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..c4b29d827ca1033d90d44872f9134c146d605eae Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78ecd372343283f4157dcfd918ec5165bb3..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000000000000000000000000000000000000..19669488f1b2f9321fa4d25c1334bc323c92fbb2 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000000000000000000000000000000000000..a0de360d45608e70289265ebc229028aa7047297 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a061eafe1075fd0ce86c875dd61d61375edee560 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d64e58ba64d180ce43ee13bf9a17835fbca..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000000000000000000000000000000000000..75025cfd5ccc1702d5ada42072626e319bca6cbe Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000000000000000000000000000000000000..c9ef358ef5cc02ae9058edd28fe0cb95da624b8c Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index 62b611da081676d42f6c3f78a2c91e7bcedddedb..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..5cb1e77b57a7749de1c599d29d2925a900f0e4a7 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 948a3070fe34c611c42c0d3ad3013a0dce358be0..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000000000000000000000000000000000000..9784f16c882653abeb055d62e5e36fc0fa0da47d Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000000000000000000000000000000000000..e0fb2bad6c415c6ef100993417cd6976abeb1dda Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp deleted file mode 100644 index 1b9a6956b3acdc11f40ce2bb3f6efbd845cc243f..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..306bee97676b123152540ca62099e8cab4e35c77 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 28d4b77f9f036a47549d47db79c16788749dca10..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000000000000000000000000000000000000..04ef206c8607696ac2bb082bb1b46afe648f59f7 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000000000000000000000000000000000000..af76f857184b1b9875b027d8012f2bd5316ebf22 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9287f5083623b375139afb391af71cc533a7dd37..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2b4c57c762057a25c07099f9fc0705b5b70acdae Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index aa7d6427e6fa1074b79ccd52ef67ac15c5637e85..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000000000000000000000000000000000000..66a5487a223c9db9c415a840b4451379ec15b214 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000000000000000000000000000000000000..d05040e94bdcfe478b88f41ecd5433c5687c7750 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9126ae37cbc3587421d6889eadd1d91fbf1994d4..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 0f58d9d89d1ed0969f99d10b31a2628e187e3a66..04865af38fac53187201993dccead8bd2a3bd570 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -3,13 +3,8 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph" - app:startDestination="@id/loginFragment"> + app:startDestination="@id/transaksiFragment"> - <fragment - android:id="@+id/loginFragment" - android:name="com.example.bondoman.fragments.LoginFragment" - android:label="fragment_login" - tools:layout="@layout/fragment_login" /> <fragment android:id="@+id/transaksiFragment" android:name="com.example.bondoman.fragments.TransaksiFragment"