diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 0c0c3383890637b4721df1f49d0b229e55c0f361..38151702dfe5d0cf31af0007d37328c974b40bce 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -3,7 +3,20 @@ <component name="deploymentTargetDropDown"> <value> <entry key="app"> - <State /> + <State> + <runningDeviceTargetSelectedWithDropDown> + <Target> + <type value="RUNNING_DEVICE_TARGET" /> + <deviceKey> + <Key> + <type value="SERIAL_NUMBER" /> + <value value="emulator-5554" /> + </Key> + </deviceKey> + </Target> + </runningDeviceTargetSelectedWithDropDown> + <timeTargetWasSelectedWithDropDown value="2024-04-03T17:57:13.057353Z" /> + </State> </entry> </value> </component> diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b810d65626beaa16386a569ce39357a6c67f3e42..7714d078ffff2f403f0dcddadce95ec2ec457157 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("com.android.application") id("org.jetbrains.kotlin.android") + id("kotlin-kapt") } android { @@ -46,6 +47,7 @@ dependencies { implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation("org.apache.poi:poi:5.2.4") implementation("org.apache.poi:poi-ooxml:5.2.4") + implementation("com.google.android.gms:play-services-location:21.2.0") testImplementation("junit:junit:4.13.2") implementation("androidx.navigation:navigation-fragment-ktx:2.7.7") implementation("androidx.navigation:navigation-ui-ktx:2.7.7") @@ -59,5 +61,8 @@ dependencies { // coroutines implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + implementation("androidx.room:room-runtime:2.6.1") + annotationProcessor("androidx.room:room-compiler:2.6.1") + kapt("androidx.room:room-compiler:2.6.1") } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7233d89a5bff4ee6ac34466d30169f361d4c3dfb..5a9ffda85b35ad0056fad0c47b9ba1de951c6788 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,10 +6,12 @@ android:name="android.hardware.camera" android:required="false" /> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.CAMERA" /> - <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/> - <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> - <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.INTERNET" /> + <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" @@ -20,10 +22,13 @@ android:supportsRtl="true" android:theme="@style/Theme.Bondoman" tools:targetApi="31"> + <activity + android:name=".ContainerActivity" + android:exported="false" /> <activity android:name=".LoginActivity" android:exported="false" - android:screenOrientation="portrait"/> + android:screenOrientation="portrait" /> <activity android:name=".MainActivity" android:exported="false" @@ -38,9 +43,11 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <activity android:name=".ScanActivity" + <activity + android:name=".ScanActivity" android:exported="false" - android:screenOrientation="portrait"/> + android:screenOrientation="portrait" /> + <service android:name=".services.JWTExpiry" android:enabled="true" diff --git a/app/src/main/java/com/example/bondoman/AddTransactionFragment.kt b/app/src/main/java/com/example/bondoman/AddTransactionFragment.kt index 8529fe2af352a3079d49a5ceff5a2e873e9aa6c3..d61f6c81464fbe7de3e0eb9d736dc1d19164bacf 100644 --- a/app/src/main/java/com/example/bondoman/AddTransactionFragment.kt +++ b/app/src/main/java/com/example/bondoman/AddTransactionFragment.kt @@ -1,22 +1,170 @@ package com.example.bondoman +import android.content.pm.PackageManager 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.databinding.FragmentAddTransactionBinding +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationServices +import android.location.Geocoder +import android.util.Log +import android.widget.Toast +import androidx.core.content.ContextCompat +import com.example.bondoman.retrofit.data.TransactionDB +import com.example.bondoman.retrofit.data.entity.Category +import com.example.bondoman.retrofit.data.entity.TransactionEntity +import java.util.Date +import java.util.Locale +import android.widget.ArrayAdapter +import android.widget.Spinner +import androidx.core.app.ActivityCompat +import java.text.SimpleDateFormat + + class AddTransactionFragment : Fragment() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + private lateinit var binding: FragmentAddTransactionBinding + private lateinit var geocoder: Geocoder + private lateinit var fusedLocationClient: FusedLocationProviderClient + private var address : String? = null + private var isFetched : Boolean = false + private lateinit var db: TransactionDB + companion object { + private const val LOCATION_PERMISSION_REQUEST_CODE = 1001 } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_add_transaction, container, false) + binding = FragmentAddTransactionBinding.inflate(inflater, container, false) + geocoder = Geocoder(requireContext(), Locale.getDefault()) + fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity()) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + db = TransactionDB.getInstance(requireContext()) + + val categorySpinner: Spinner = binding.addCategoryField + val categories = resources.getStringArray(R.array.category_array) + val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, categories) + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + categorySpinner.adapter = adapter + + + if (ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED + && ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + Log.e("fetchLocation", "Both fine and coarse location permissions granted") + fetchLocation { fetchedAddress -> + address = fetchedAddress + } + } else { + Log.e("fetchLocation", "Requesting permissions for fine and coarse location") + ActivityCompat.requestPermissions(requireActivity(), arrayOf( + android.Manifest.permission.ACCESS_FINE_LOCATION, + android.Manifest.permission.ACCESS_COARSE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE) + } + + binding.addButton.setOnClickListener { + fetchLocation { fetchedAddress -> + address = fetchedAddress + } + // Retrieve values from other fields + val name = binding.addNameField.text.toString() + val amountText = binding.addPriceField.text.toString() + val currentDate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date()) + // Retrieve selected category from the Spinner + val category = categorySpinner.selectedItem.toString() + + Log.d("addTransactionWoi", "Button clicked") + + + val amount: Int + try { + amount = amountText.toInt() + } catch (e: NumberFormatException) { + Toast.makeText(requireContext(), "Amount must be a valid number", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + + + val location = if (address != null) { + address + } else { + binding.addLocationField.text.toString() + } + + Log.d("addTransactionWoi", "the location is $location") + + val newTransaction = TransactionEntity( + name = name, + category = Category.valueOf(category), + date = currentDate, + price = amount, + location = location ?: "" + ) + db.transactionDao().insertAll(newTransaction) + requireActivity().onBackPressed() + } + + } + + private fun fetchLocation(callback: (String) -> Unit) { + var address = "Unknown" + + if (ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED + && ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + fusedLocationClient.lastLocation.addOnSuccessListener { location -> + location?.let { + Log.e("fetchLocation", "Fetching location") + val latitude = location.latitude + val longitude = location.longitude + address = getAddress(latitude, longitude) + callback(address) + } + }.addOnFailureListener { e -> + Log.e("fetchLocation", "Failed to fetch location: ${e.message}") + Toast.makeText(requireContext(), "Failed to fetch location", Toast.LENGTH_SHORT).show() + callback(address) + } + } else { + ActivityCompat.requestPermissions(requireActivity(), arrayOf( + android.Manifest.permission.ACCESS_FINE_LOCATION, + android.Manifest.permission.ACCESS_COARSE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE) + callback(address) + } + } + + + + private fun getAddress(latitude: Double, longitude: Double): String { + val addresses = geocoder.getFromLocation(latitude, longitude, 1) + return if (!addresses.isNullOrEmpty()) { + val address = addresses[0] + "${address.getAddressLine(0)}, ${address.locality}, ${address.adminArea}, ${address.countryName}" + } else { + "Unknown Location" + } + } + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Log.e("fetchLocation", "Location permission granted") + fetchLocation { fetchedAddress -> + address = fetchedAddress + } + isFetched = true + } else { + Log.e("fetchLocation", "Location permission denied") + Toast.makeText(requireContext(), "Location permission denied", Toast.LENGTH_SHORT).show() + } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/ContainerActivity.kt b/app/src/main/java/com/example/bondoman/ContainerActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..513b6a152f7db934ab01a5dcebb06a22256987fe --- /dev/null +++ b/app/src/main/java/com/example/bondoman/ContainerActivity.kt @@ -0,0 +1,37 @@ +package com.example.bondoman + +import android.os.Bundle +import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat + +class ContainerActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_container) + + if (savedInstanceState == null) { + // Check if intent contains transaction ID + val transactionId = intent.getIntExtra("transactionId", -1) + if (transactionId != -1) { + // Start the EditTransactionFragment +// val fragment = EditTransactionFragment.newInstance(transactionId) +// supportFragmentManager.beginTransaction() +// .replace(R.id.fragment_container, fragment) +// .commit() + } else { + // Start the AddTransactionFragment + supportFragmentManager.beginTransaction() + .replace(R.id.fragment_container, AddTransactionFragment()) + .commit() + } + } + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container) + fragment?.onRequestPermissionsResult(requestCode, permissions, grantResults) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/SettingFragment.kt b/app/src/main/java/com/example/bondoman/SettingFragment.kt index 84a8b4f65fd57a88006748174aedc7dc7922eb5d..943f9a77fc6c14e4434dc861ab22a84da6590d9a 100644 --- a/app/src/main/java/com/example/bondoman/SettingFragment.kt +++ b/app/src/main/java/com/example/bondoman/SettingFragment.kt @@ -13,7 +13,6 @@ import androidx.navigation.fragment.findNavController import com.example.bondoman.databinding.FragmentSettingBinding import com.example.bondoman.helper.Xls import com.example.bondoman.models.SqlTransaction -import com.example.bondoman.sql.TransactionSQL class SettingFragment: Fragment() { private lateinit var binding : FragmentSettingBinding @@ -45,19 +44,19 @@ class SettingFragment: Fragment() { binding.saveButton.setOnClickListener{ // Retrieve transactions from the database - val dbTransaction = TransactionSQL(requireContext()) - dbTransaction.open() - val listTransaction = dbTransaction.findAll() - - if (listTransaction.isNotEmpty()) { - // If there are transactions, show the format selection dialog - showFormatSelectionDialog(listTransaction) - } else { - // Handle case when there are no transactions in the database - Toast.makeText(requireContext(), "No transactions found in the database", Toast.LENGTH_SHORT).show() - } +// val dbTransaction = TransactionSQL(requireContext()) +// dbTransaction.open() +// val listTransaction = dbTransaction.findAll() + +// if (listTransaction.isNotEmpty()) { +// // If there are transactions, show the format selection dialog +// showFormatSelectionDialog(listTransaction) +// } else { +// // Handle case when there are no transactions in the database +// Toast.makeText(requireContext(), "No transactions found in the database", Toast.LENGTH_SHORT).show() +// } } - +// binding.sendEmailButton.setOnClickListener { sendEmail() } @@ -70,35 +69,35 @@ class SettingFragment: Fragment() { } } - private fun showFormatSelectionDialog(listTransaction: List<SqlTransaction>) { - val formatOptions = arrayOf("XLS", "XLSX") - - val builder = AlertDialog.Builder(requireContext()) - builder.setTitle("Select File Format") - .setItems(formatOptions) { dialog, which -> - val fileFormat = if (which == 0) "xls" else "xlsx" - savedFilePath = Xls.saveXls(requireContext(), listTransaction, fileFormat) - showMassage("File has been saved successfully") - dialog.dismiss() - } - .setNegativeButton("Cancel") { dialog, _ -> - dialog.dismiss() - } - val dialog = builder.create() - dialog.show() - } - - private fun showMassage(message: String) { - val alertDialogBuilder = AlertDialog.Builder(requireContext()) - alertDialogBuilder - .setMessage(message) - .setPositiveButton("OK") { dialog, _ -> - // Do something when OK button is clicked - dialog.dismiss() - } - .create() - .show() - } +// private fun showFormatSelectionDialog(listTransaction: List<SqlTransaction>) { +// val formatOptions = arrayOf("XLS", "XLSX") +// +// val builder = AlertDialog.Builder(requireContext()) +// builder.setTitle("Select File Format") +// .setItems(formatOptions) { dialog, which -> +// val fileFormat = if (which == 0) "xls" else "xlsx" +// savedFilePath = Xls.saveXls(requireContext(), listTransaction, fileFormat) +// showMassage("File has been saved successfully") +// dialog.dismiss() +// } +// .setNegativeButton("Cancel") { dialog, _ -> +// dialog.dismiss() +// } +// val dialog = builder.create() +// dialog.show() +// } +// +// private fun showMassage(message: String) { +// val alertDialogBuilder = AlertDialog.Builder(requireContext()) +// alertDialogBuilder +// .setMessage(message) +// .setPositiveButton("OK") { dialog, _ -> +// // Do something when OK button is clicked +// dialog.dismiss() +// } +// .create() +// .show() +// } private fun sendEmail() { // Create an intent to send an email diff --git a/app/src/main/java/com/example/bondoman/TambahTransaksi.kt b/app/src/main/java/com/example/bondoman/TambahTransaksi.kt deleted file mode 100644 index 5669ca670c1eca97b7b2dbb4eab21eb3f36d9540..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/TambahTransaksi.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.example.bondoman - -import android.os.Bundle -import androidx.fragment.app.Fragment -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.EditText -import java.time.LocalDate -import java.time.format.DateTimeFormatter - -class TambahTransaksi : Fragment() { - private lateinit var nama: EditText - private lateinit var kategori: EditText - private lateinit var date: EditText - private lateinit var nominal: EditText - private lateinit var lokasi: EditText - private lateinit var save: EditText - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_tambah_transaksi, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - val currentDate = LocalDate.now() - val formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy") - val formattedDate = currentDate.format(formatter) - date.setText(formattedDate) - nama = view.findViewById(R.id.NamaTransaksi) - kategori = view.findViewById(R.id.KategoriTransaksi) - date = view.findViewById(R.id.TanggalTransaksi) - nominal = view.findViewById(R.id.NominalTransaksi) - lokasi = view.findViewById(R.id.LokasiTransaksi) - save = view.findViewById(R.id.SimpanTransaksi) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/TransactionFragment.kt b/app/src/main/java/com/example/bondoman/TransactionFragment.kt index d7b1fbf814558e5296e75b69e07cfe1343bdad83..83a6326e9fa2b82f56020eb999eb83079e17472d 100644 --- a/app/src/main/java/com/example/bondoman/TransactionFragment.kt +++ b/app/src/main/java/com/example/bondoman/TransactionFragment.kt @@ -1,29 +1,31 @@ package com.example.bondoman -import android.content.ContentValues +import android.content.Intent import android.os.Bundle -import android.text.Editable -import android.text.TextWatcher import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.example.bondoman.retrofit.data.TransactionDB import com.example.bondoman.databinding.FragmentTransaksiBinding -import com.example.bondoman.retrofit.data.Transaction -import com.example.bondoman.helper.Xls -import com.example.bondoman.models.SqlTransaction -import com.example.bondoman.sql.Kontraktor -import com.example.bondoman.sql.TransactionSQL +import com.example.bondoman.retrofit.data.entity.TransactionEntity +import com.example.bondoman.retrofit.adapter.TransactionAdapter class TransactionFragment : Fragment() { - private lateinit var binding : FragmentTransaksiBinding - private lateinit var transactionData : RecyclerView - private val listTransaction= ArrayList<Transaction>() + private lateinit var binding: FragmentTransaksiBinding + private lateinit var transactionData: RecyclerView + private val listTransaction = ArrayList<TransactionEntity>() private lateinit var searchBar: TextView - private lateinit var dbTransaction: TransactionSQL + lateinit var adapter: TransactionAdapter + private lateinit var database: TransactionDB +// private lateinit var dbTransaction: DbTransaction + +// private var receiver = TransactionRandomizerReceiver() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -35,124 +37,230 @@ class TransactionFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - dbTransaction = TransactionSQL(requireContext()) - dbTransaction.open() -// // Delete all data -// dbTransaction.deleteAll() -// -// // Dummy data insertion -// insertDummyTransactions() + database = TransactionDB.getInstance(requireContext()) - transactionData = binding.itemTransaction - transactionData.setHasFixedSize(true) - transactionData.layoutManager = LinearLayoutManager(requireContext()) - loadDatas(view) -// listTransaction.add(Transaction("Semen Tiga Roda","22 Maret 2024", "Pengeluaran", 200000, "Jakarta")) -// listTransaction.add(Transaction("Semen Tiga Roda","22 Maret 2024", "Pengeluaran", 300000, "Jakarta")) -// listTransaction.add(Transaction("Semen Tiga Roda","22 Maret 2024", "Pengeluaran", 300000, "Jakarta")) -// listTransaction.add(Transaction("Mapel Sirup","22 Maret 2024", "Pengeluaran", 100000, "Jakarta")) -// listTransaction.add(Transaction("Jeruks","22 Maret 2024", "Pengeluaran", 200000, "Jakarta")) -// listTransaction.add(Transaction("Apel","22 Maret 2024", "Pengeluaran", 300000, "Jakarta")) - - - val filteredList: ArrayList<Transaction> = ArrayList(listTransaction) - var transactionAdapter = TransactionAdapter(filteredList) - transactionData.adapter = transactionAdapter - - searchBar = binding.searchBar - - searchBar.addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { - // Not used - } - - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { - // Update the filteredList based on the search text - val searchText = s.toString().trim() - filteredList.clear() - - if (searchText.isEmpty()) { - // If search text is empty, show all items - filteredList.addAll(listTransaction) - } else { - // Filter the list based on the search text - filteredList.addAll(listTransaction.filter { transaction -> - transaction.name != null && transaction.name.contains(searchText, ignoreCase = true) - }) - } - - // Notify the adapter about the updated list - transactionAdapter = TransactionAdapter(filteredList) - transactionData.adapter = transactionAdapter - } - - override fun afterTextChanged(s: Editable?) { - // Not used - } - }) +// val filter = IntentFilter("itb.bos.bondoman.ACTION_RANDOMIZE_TRANSACTION") +// requireContext().registerReceiver(receiver, filter) +// dbTransaction = DbTransaction(requireContext()) +// dbTransaction.open() - } +// dbTransaction.deleteAll() + adapter = TransactionAdapter(listTransaction) - private fun insertDummyTransactions() { - val dummyTransaction1 = ContentValues().apply { - put(Kontraktor.TransactionTable.NAME, "Transaction 1") - put(Kontraktor.TransactionTable.CATEGORY, "Category 1") - put(Kontraktor.TransactionTable.DATE, "2024-04-01") - put(Kontraktor.TransactionTable.PRICE, 100) - put(Kontraktor.TransactionTable.LOCATION, "Location 1") - } + transactionData = binding.itemTransaction + transactionData.adapter = adapter + transactionData.layoutManager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false) + transactionData.addItemDecoration(DividerItemDecoration(requireContext(), RecyclerView.VERTICAL)) - val dummyTransaction2 = ContentValues().apply { - put(Kontraktor.TransactionTable.NAME, "Transaction 2") - put(Kontraktor.TransactionTable.CATEGORY, "Category 2") - put(Kontraktor.TransactionTable.DATE, "2024-04-02") - put(Kontraktor.TransactionTable.PRICE, 200) - put(Kontraktor.TransactionTable.LOCATION, "Location 2") - } - val dummyTransaction3 = ContentValues().apply { - put(Kontraktor.TransactionTable.NAME, "Transaction 3") - put(Kontraktor.TransactionTable.CATEGORY, "Category 3") - put(Kontraktor.TransactionTable.DATE, "2024-04-03") - put(Kontraktor.TransactionTable.PRICE, 300) - put(Kontraktor.TransactionTable.LOCATION, "Location 3") + binding.addButton.setOnClickListener { + val intent = Intent(requireContext(), ContainerActivity::class.java) + startActivity(intent) } +// transactionData.setHasFixedSize(true) +// transactionData.layoutManager = LinearLayoutManager(requireContext()) +// loadDatas() - val dummyTransaction4 = ContentValues().apply { - put(Kontraktor.TransactionTable.NAME, "Transaction 4") - put(Kontraktor.TransactionTable.CATEGORY, "Category 4") - put(Kontraktor.TransactionTable.DATE, "2024-04-04") - put(Kontraktor.TransactionTable.PRICE, 400) - put(Kontraktor.TransactionTable.LOCATION, "Location 4") - } +// val filteredList: ArrayList<SqlTransaction> = ArrayList(listTransaction) +// var transactionAdapter = TransactionAdapter(filteredList) +// transactionData.adapter = transactionAdapter - val dummyTransaction5 = ContentValues().apply { - put(Kontraktor.TransactionTable.NAME, "Transaction 5") - put(Kontraktor.TransactionTable.CATEGORY, "Category 5") - put(Kontraktor.TransactionTable.DATE, "2024-04-05") - put(Kontraktor.TransactionTable.PRICE, 500) - put(Kontraktor.TransactionTable.LOCATION, "Location 5") - } +// searchBar = binding.searchBar +// +// searchBar.addTextChangedListener(object : TextWatcher { +// override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { +// // Not used +// } +// +// override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { +// // Update the filteredList based on the search text +// val searchText = s.toString().trim() +// filteredList.clear() +// +// if (searchText.isEmpty()) { +// // If search text is empty, show all items +// filteredList.addAll(listTransaction) +// } else { +// // Filter the list based on the search text +// filteredList.addAll(listTransaction.filter { transaction -> +// transaction.name != null && transaction.name!!.contains(searchText, ignoreCase = true) +// }) +// } +// +// // Notify the adapter about the updated list +// transactionAdapter = TransactionAdapter(filteredList) +// transactionData.adapter = transactionAdapter +// } +// +// override fun afterTextChanged(s: Editable?) { +// // Not used +// } +// }) + } - // Insert dummy transactions into the database - dbTransaction.insert(dummyTransaction1) - dbTransaction.insert(dummyTransaction2) - dbTransaction.insert(dummyTransaction3) - dbTransaction.insert(dummyTransaction4) - dbTransaction.insert(dummyTransaction5) + override fun onDestroyView() { + super.onDestroyView() + // Unregister the BroadcastReceiver when the fragment's view is destroyed +// requireContext().unregisterReceiver(receiver) + database.close() + } + override fun onResume() { + super.onResume() + loadDatas() } - fun loadDatas(view: View) { + private fun loadDatas() { + listTransaction.clear() - insertDummyTransactions() - val datas = dbTransaction.findAll() + listTransaction.addAll(database.transactionDao().getAll()) + adapter.notifyDataSetChanged() - datas.forEach { - item -> - listTransaction.add(Transaction(item.id,item.name,item.date,item.category, item.price,item.location)) - } +// val datas = dbTransaction.findAll() +// +// datas.forEach { item -> +// val categoryString = item.category?.toString() ?: "PENGELUARAN" +// val category = TransactionCategory.valueOf(categoryString) +// val transaction = SqlTransaction(item.id, item.name, category, item.date, item.price, item.location) +// listTransaction.add(transaction) +// } } +// private lateinit var binding : FragmentTransaksiBinding +// private lateinit var transactionData : RecyclerView +// private val listTransaction= ArrayList<Transaction>() +// private lateinit var searchBar: TextView +// private lateinit var dbTransaction: TransactionSQL +// override fun onCreateView( +// inflater: LayoutInflater, +// container: ViewGroup?, +// savedInstanceState: Bundle? +// ): View { +// binding = FragmentTransaksiBinding.inflate(inflater, container, false) +// return binding.root +// } +// +// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +// super.onViewCreated(view, savedInstanceState) +// dbTransaction = TransactionSQL(requireContext()) +// dbTransaction.open() +// +//// // Delete all data +//// dbTransaction.deleteAll() +//// +//// // Dummy data insertion +//// insertDummyTransactions() +// +// transactionData = binding.itemTransaction +// transactionData.setHasFixedSize(true) +// transactionData.layoutManager = LinearLayoutManager(requireContext()) +// loadDatas(view) +//// listTransaction.add(Transaction("Semen Tiga Roda","22 Maret 2024", "Pengeluaran", 200000, "Jakarta")) +//// listTransaction.add(Transaction("Semen Tiga Roda","22 Maret 2024", "Pengeluaran", 300000, "Jakarta")) +//// listTransaction.add(Transaction("Semen Tiga Roda","22 Maret 2024", "Pengeluaran", 300000, "Jakarta")) +//// listTransaction.add(Transaction("Mapel Sirup","22 Maret 2024", "Pengeluaran", 100000, "Jakarta")) +//// listTransaction.add(Transaction("Jeruks","22 Maret 2024", "Pengeluaran", 200000, "Jakarta")) +//// listTransaction.add(Transaction("Apel","22 Maret 2024", "Pengeluaran", 300000, "Jakarta")) +// +// +// val filteredList: ArrayList<Transaction> = ArrayList(listTransaction) +// var transactionAdapter = TransactionAdapter(filteredList) +// transactionData.adapter = transactionAdapter +// +// searchBar = binding.searchBar +// +// searchBar.addTextChangedListener(object : TextWatcher { +// override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { +// // Not used +// } +// +// override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { +// // Update the filteredList based on the search text +// val searchText = s.toString().trim() +// filteredList.clear() +// +// if (searchText.isEmpty()) { +// // If search text is empty, show all items +// filteredList.addAll(listTransaction) +// } else { +// // Filter the list based on the search text +// filteredList.addAll(listTransaction.filter { transaction -> +// transaction.name != null && transaction.name.contains(searchText, ignoreCase = true) +// }) +// } +// +// // Notify the adapter about the updated list +// transactionAdapter = TransactionAdapter(filteredList) +// transactionData.adapter = transactionAdapter +// } +// +// override fun afterTextChanged(s: Editable?) { +// // Not used +// } +// }) +// +// +// } +// +// private fun insertDummyTransactions() { +// val dummyTransaction1 = ContentValues().apply { +// put(Kontraktor.TransactionTable.NAME, "Transaction 1") +// put(Kontraktor.TransactionTable.CATEGORY, "Category 1") +// put(Kontraktor.TransactionTable.DATE, "2024-04-01") +// put(Kontraktor.TransactionTable.PRICE, 100) +// put(Kontraktor.TransactionTable.LOCATION, "Location 1") +// } +// +// val dummyTransaction2 = ContentValues().apply { +// put(Kontraktor.TransactionTable.NAME, "Transaction 2") +// put(Kontraktor.TransactionTable.CATEGORY, "Category 2") +// put(Kontraktor.TransactionTable.DATE, "2024-04-02") +// put(Kontraktor.TransactionTable.PRICE, 200) +// put(Kontraktor.TransactionTable.LOCATION, "Location 2") +// } +// +// val dummyTransaction3 = ContentValues().apply { +// put(Kontraktor.TransactionTable.NAME, "Transaction 3") +// put(Kontraktor.TransactionTable.CATEGORY, "Category 3") +// put(Kontraktor.TransactionTable.DATE, "2024-04-03") +// put(Kontraktor.TransactionTable.PRICE, 300) +// put(Kontraktor.TransactionTable.LOCATION, "Location 3") +// } +// +// val dummyTransaction4 = ContentValues().apply { +// put(Kontraktor.TransactionTable.NAME, "Transaction 4") +// put(Kontraktor.TransactionTable.CATEGORY, "Category 4") +// put(Kontraktor.TransactionTable.DATE, "2024-04-04") +// put(Kontraktor.TransactionTable.PRICE, 400) +// put(Kontraktor.TransactionTable.LOCATION, "Location 4") +// } +// +// val dummyTransaction5 = ContentValues().apply { +// put(Kontraktor.TransactionTable.NAME, "Transaction 5") +// put(Kontraktor.TransactionTable.CATEGORY, "Category 5") +// put(Kontraktor.TransactionTable.DATE, "2024-04-05") +// put(Kontraktor.TransactionTable.PRICE, 500) +// put(Kontraktor.TransactionTable.LOCATION, "Location 5") +// } +// +// // Insert dummy transactions into the database +// dbTransaction.insert(dummyTransaction1) +// dbTransaction.insert(dummyTransaction2) +// dbTransaction.insert(dummyTransaction3) +// dbTransaction.insert(dummyTransaction4) +// dbTransaction.insert(dummyTransaction5) +// +// } +// +// fun loadDatas(view: View) { +// +// insertDummyTransactions() +// val datas = dbTransaction.findAll() +// +// datas.forEach { +// item -> +// listTransaction.add(Transaction(item.id,item.name,item.date,item.category, item.price,item.location)) +// } +// } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/retrofit/adapter/TransactionAdapter.kt b/app/src/main/java/com/example/bondoman/retrofit/adapter/TransactionAdapter.kt index 6fe800aca54681f366097b5fb594548d4a804908..dda3a8b507ebced4d82ae30f2137b943ac2a8336 100644 --- a/app/src/main/java/com/example/bondoman/retrofit/adapter/TransactionAdapter.kt +++ b/app/src/main/java/com/example/bondoman/retrofit/adapter/TransactionAdapter.kt @@ -8,22 +8,23 @@ import android.view.ViewGroup import android.widget.TextView import android.widget.Toast import androidx.recyclerview.widget.RecyclerView +import com.example.bondoman.ContainerActivity import com.example.bondoman.R import com.example.bondoman.retrofit.data.entity.TransactionEntity -class TransactionAdapter(private val listData: ArrayList<TransactionEntity>): RecyclerView.Adapter<TransactionAdapter.ViewHolder>(){ +class TransactionAdapter(private val list: ArrayList<TransactionEntity>): RecyclerView.Adapter<TransactionAdapter.ViewHolder>(){ - override fun onBindViewHolder(holder: com.example.bondoman.TransactionAdapter.DataViewHolder, position: Int) { - val currentData = listData[position] - holder.txtName.text = currentData.name - holder.txtCategory.text = currentData.category.toString() - val temp = "IDR " + currentData.price.toString() - holder.txtPrice.text = temp - holder.txtLocation.text = currentData.location - holder.txtDate.text = currentData.date + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val currentData = list[position] + holder.name.text = currentData.name + holder.kategori.text = currentData.category.toString() + val tmp = "IDR " + currentData.price.toString() + holder.nominal.text = tmp + holder.lokasi.text = currentData.location + holder.tgl.text = currentData.date // Set click listener for itemLocation TextView - holder.txtLocation.setOnClickListener { + holder.lokasi.setOnClickListener { val context = holder.itemView.context // Check if the location is not "Unknown" and not empty before opening Google Maps if (currentData.location != null && currentData.location != "Unknown" && currentData.location!!.isNotBlank()) { @@ -46,7 +47,7 @@ class TransactionAdapter(private val listData: ArrayList<TransactionEntity>): Re val toastMessage = "Clicked item: ${currentData.name} with id ${currentData.id}" Toast.makeText(holder.itemView.context, toastMessage, Toast.LENGTH_SHORT).show() - val intent = Intent(holder.itemView.context, AddTransactionActivity::class.java) + val intent = Intent(holder.itemView.context, ContainerActivity::class.java) // Optionally, pass data to the AddTransactionActivity intent.putExtra("transactionId", currentData.id) @@ -56,23 +57,19 @@ class TransactionAdapter(private val listData: ArrayList<TransactionEntity>): Re } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): com.example.bondoman.TransactionAdapter.ViewHolder { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view: View = LayoutInflater.from(parent.context).inflate(R.layout.row_data,parent,false) - return com.example.bondoman.TransactionAdapter.ViewHolder(view) - } - - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - TODO("Not yet implemented") + return ViewHolder(view) } override fun getItemCount(): Int { - return listData.count() + return list.count() } class ViewHolder(item: View) : RecyclerView.ViewHolder(item) { - val txtName: TextView = item.findViewById(R.id.itemName) - val txtCategory:TextView= item.findViewById(R.id.category) - val txtDate: TextView= item.findViewById(R.id.itemDate) - val txtPrice : TextView= item.findViewById(R.id.itemPrice) - val txtLocation : TextView = item.findViewById(R.id.itemLocation) + val name: TextView = item.findViewById(R.id.NamaTransaksi) + val kategori:TextView= item.findViewById(R.id.KategoriTransaksi) + val tgl: TextView= item.findViewById(R.id.TanggalTransaksi) + val nominal : TextView= item.findViewById(R.id.NominalTransaksi) + val lokasi : TextView = item.findViewById(R.id.LokasiTransaksi) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/retrofit/data/entity/TransactionEntitiy.kt b/app/src/main/java/com/example/bondoman/retrofit/data/entity/TransactionEntitiy.kt index ba0328edb120115b631262197d7e8ee9f0bb5887..1e443c958adf95089bcb29cce44f94b56eb4cde4 100644 --- a/app/src/main/java/com/example/bondoman/retrofit/data/entity/TransactionEntitiy.kt +++ b/app/src/main/java/com/example/bondoman/retrofit/data/entity/TransactionEntitiy.kt @@ -4,16 +4,16 @@ import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey -enum class TransactionCategory { - PEMASUKAN, - PENGELUARAN +enum class Category { + Pemasukan, + Pengeluaran } @Entity data class TransactionEntity( @PrimaryKey(autoGenerate = true) var id: Int? = null, @ColumnInfo(name = "name") var name: String? = null, - @ColumnInfo(name = "category") var category: TransactionCategory? = null, + @ColumnInfo(name = "category") var category: Category? = null, @ColumnInfo(name = "date") var date: String? = null, @ColumnInfo(name = "price") var price: Int? = null, @ColumnInfo(name = "location") var location: String? = null diff --git a/app/src/main/java/com/example/bondoman/sql/Helper.kt b/app/src/main/java/com/example/bondoman/sql/Helper.kt deleted file mode 100644 index 12130b5e00a23c80d7c4e662cfb62eb13792d639..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/sql/Helper.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.example.bondoman.sql - -import android.content.Context -import android.database.sqlite.SQLiteDatabase -import android.database.sqlite.SQLiteOpenHelper - -class Helper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { - companion object { - private const val DATABASE_NAME = "bondoman" - private const val DATABASE_VERSION = 1 - - private const val SQL_CREATE = "CREATE TABLE ${Kontraktor.TransactionTable.TABLE_NAME} " + - "(${Kontraktor.TransactionTable._ID} INTEGER PRIMARY KEY AUTOINCREMENT, " + - "${Kontraktor.TransactionTable.NAME} TEXT NOT NULL, " + - "${Kontraktor.TransactionTable.CATEGORY} TEXT NOT NULL, " + - "${Kontraktor.TransactionTable.DATE} TEXT NOT NULL, " + - "${Kontraktor.TransactionTable.PRICE} INTEGER NOT NULL, " + - "${Kontraktor.TransactionTable.LOCATION} TEXT NOT NULL)" - } - - override fun onCreate(db: SQLiteDatabase) { - db.execSQL(SQL_CREATE) - } - - override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { - db.execSQL("DROP TABLE IF EXISTS ${Kontraktor.TransactionTable.TABLE_NAME}") - onCreate(db) - } -} diff --git a/app/src/main/java/com/example/bondoman/sql/Kontraktor.kt b/app/src/main/java/com/example/bondoman/sql/Kontraktor.kt deleted file mode 100644 index 58f4ec7c5fdf179c26f6f5c95abde9a4764a0603..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/sql/Kontraktor.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.bondoman.sql - -import android.provider.BaseColumns - -internal class Kontraktor { - internal class TransactionTable : BaseColumns { - companion object { - const val TABLE_NAME = "transactions" - const val _ID = "_id" - const val NAME = "name" - const val CATEGORY = "category" - const val DATE = "date" - const val PRICE = "price" - const val LOCATION = "location" - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/sql/TransactionSQL.kt b/app/src/main/java/com/example/bondoman/sql/TransactionSQL.kt deleted file mode 100644 index 4d05a63bd509bf420e92e7e13a2e5c0544caf446..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/sql/TransactionSQL.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.example.bondoman.sql - -import android.content.ContentValues -import android.content.Context -import android.database.sqlite.SQLiteDatabase -import com.example.bondoman.models.SqlTransaction -import com.example.bondoman.sql.Kontraktor.TransactionTable.Companion.CATEGORY -import com.example.bondoman.sql.Kontraktor.TransactionTable.Companion.DATE -import com.example.bondoman.sql.Kontraktor.TransactionTable.Companion.LOCATION -import com.example.bondoman.sql.Kontraktor.TransactionTable.Companion.NAME -import com.example.bondoman.sql.Kontraktor.TransactionTable.Companion.PRICE -import com.example.bondoman.sql.Kontraktor.TransactionTable.Companion.TABLE_NAME -import com.example.bondoman.sql.Kontraktor.TransactionTable.Companion._ID -import java.sql.SQLException - -class TransactionSQL(context: Context) { - private var dbHelper: Helper = Helper(context) - private lateinit var database: SQLiteDatabase - - companion object { - private const val DATABASE_TABLE = TABLE_NAME - - private val INSTANCE: TransactionSQL? = null - fun getInstance(context: Context) : TransactionSQL = INSTANCE ?: synchronized(this) { - INSTANCE ?: TransactionSQL(context) - } - } - - @Throws(SQLException::class) - fun open() { - database = dbHelper.writableDatabase - } - - fun close() { - dbHelper.close() - if (database.isOpen) { - database.close() - } - } - - fun findAll():List<SqlTransaction> { - val cursor = database.query( - DATABASE_TABLE, - null,null,null,null,null,"$_ID ASC" - ) - - val listData = mutableListOf<SqlTransaction>() - - with(cursor) { - while (moveToNext()) { - val id = getInt(getColumnIndexOrThrow(_ID)) - val name = getString(getColumnIndexOrThrow(NAME)) - val category = getString(getColumnIndexOrThrow(CATEGORY)) - val date = getString(getColumnIndexOrThrow(DATE)) - val price = getInt(getColumnIndexOrThrow(PRICE)) - val location = getString(getColumnIndexOrThrow(LOCATION)) - - listData.add(SqlTransaction(id,name,category,date,price,location)) - } - cursor.close() - } - return listData - } - - fun insert(values: ContentValues?): Long { - return database.insert(DATABASE_TABLE, null, values) - } - - fun update(id: String, values: ContentValues?): Int { - return database.update(DATABASE_TABLE, values, "$_ID = ?", arrayOf(id)) - } - - fun delete(id: String): Int { - return database.delete(DATABASE_TABLE, "$_ID = '$id'", null) - } - - fun deleteAll() { - database.delete(DATABASE_TABLE, null, null) - } - -} diff --git a/app/src/main/res/layout/activity_container.xml b/app/src/main/res/layout/activity_container.xml new file mode 100644 index 0000000000000000000000000000000000000000..4cddab99c4c0d0b75deb782dc1ea978f4bd20666 --- /dev/null +++ b/app/src/main/res/layout/activity_container.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/main" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".ContainerActivity"> + <androidx.fragment.app.FragmentContainerView + android:id="@+id/fragment_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + /> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_add_transaction.xml b/app/src/main/res/layout/fragment_add_transaction.xml index cbbbce3463e51ed579bd67ab49ddb6ffa1cd2d38..d4f5d88cea2873a3c098490165c34d1a5d1f6b5e 100644 --- a/app/src/main/res/layout/fragment_add_transaction.xml +++ b/app/src/main/res/layout/fragment_add_transaction.xml @@ -37,6 +37,7 @@ /> <EditText + android:id="@+id/add_name_field" android:layout_width="match_parent" android:layout_height="48dp" android:layout_marginTop="8dp" @@ -56,6 +57,7 @@ /> <EditText + android:id="@+id/add_price_field" android:layout_width="match_parent" android:layout_marginTop="8dp" android:layout_height="48dp" @@ -75,6 +77,7 @@ /> <EditText + android:id="@+id/add_location_field" android:layout_width="match_parent" android:layout_marginTop="8dp" android:layout_height="48dp" @@ -93,7 +96,8 @@ android:textColor="@color/dark_grey" /> - <EditText + <Spinner + android:id="@+id/add_category_field" android:layout_width="match_parent" android:layout_marginTop="8dp" android:layout_height="48dp" @@ -101,8 +105,7 @@ android:textColor="@color/grey" android:paddingHorizontal="20dp" android:textSize="16sp" - android:background="@drawable/cornered_add" - /> + android:background="@drawable/cornered_add" /> <LinearLayout android:layout_width="match_parent" @@ -110,6 +113,7 @@ android:layout_weight="1" > <Button + android:id="@+id/add_button" android:layout_width="match_parent" android:layout_height="56dp" android:layout_gravity="bottom" diff --git a/app/src/main/res/layout/fragment_transaksi.xml b/app/src/main/res/layout/fragment_transaksi.xml index c6130c515d9a4d535e6f9fe56f97a1b19fcbbce5..a8f594f80e7b8cc99c8e1dc0022f0e02df2f488c 100644 --- a/app/src/main/res/layout/fragment_transaksi.xml +++ b/app/src/main/res/layout/fragment_transaksi.xml @@ -59,6 +59,7 @@ </LinearLayout> <ImageView + android:id="@+id/filterButton" android:layout_width="50dp" android:layout_height="50dp" android:layout_weight="1" @@ -67,13 +68,30 @@ </LinearLayout> - <androidx.recyclerview.widget.RecyclerView - android:id="@+id/itemTransaction" + <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginTop="100dp" - android:layout_marginHorizontal="20dp" - tools:listitem="@layout/list_transaction" /> + android:layout_height="match_parent"> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/itemTransaction" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginTop="100dp" + android:layout_marginHorizontal="20dp" + > + </androidx.recyclerview.widget.RecyclerView> + + <com.google.android.material.floatingactionbutton.FloatingActionButton + android:id="@+id/addButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@color/purple" + android:src="@drawable/baseline_add_24" + android:layout_marginHorizontal="315dp" + android:layout_marginTop="440dp"/> + </RelativeLayout> </LinearLayout> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 37f46e19b42db3f1dbcf837c28f0ac1cae876963..6e8065f365353a550f8c0dbdb94b4d38316e599a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -13,6 +13,9 @@ <string name="confirm_button_description">Konfirmasi</string> <!-- TODO: Remove or change this placeholder text --> <string name="hello_blank_fragment">Hello blank fragment</string> - + <string-array name="category_array"> + <item>Pemasukan</item> + <item>Pengeluaran</item> + </string-array> </resources> \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 53f4a67287fcc572dab6ad907bddc40aa4efbfa6..8682e0c766dc2c3e54a3eb2a3ecb894de78bfda1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,4 +2,5 @@ plugins { id("com.android.application") version "8.2.2" apply false id("org.jetbrains.kotlin.android") version "1.9.22" apply false + } \ No newline at end of file