diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f5e86c55731d3c9c6e2f943bc478d49712836e3a..84302700c51e5c7557df0320dea20105987ebdfa 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 { @@ -39,7 +40,12 @@ android { } dependencies { - + implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.3.1") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1") + implementation("androidx.core:core-ktx:1.7.0") + implementation("androidx.room:room-runtime:2.4.2") + kapt("androidx.room:room-compiler:2.4.2") + implementation("androidx.room:room-ktx:2.4.2") implementation("androidx.core:core-ktx:1.10.1") implementation("androidx.appcompat:appcompat:1.6.1") implementation("com.google.android.material:material:1.9.0") diff --git a/app/src/main/java/com/example/tubespbd/MainActivity.kt b/app/src/main/java/com/example/tubespbd/MainActivity.kt index 596c5d8b2189c18973f7bd11f973436a01773adb..7ea03587ed132bb21c8f13bc7a0ac5a1f1288d1c 100644 --- a/app/src/main/java/com/example/tubespbd/MainActivity.kt +++ b/app/src/main/java/com/example/tubespbd/MainActivity.kt @@ -12,16 +12,32 @@ import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController import com.google.android.material.bottomnavigation.BottomNavigationView +import androidx.room.Room +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +import com.example.tubespbd.database.* class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var locationManager: LocationManager private lateinit var transactionManager: TransactionManager + private lateinit var appDatabase: AppDatabase + private val transactionRepository by lazy { TransactionRepository(appDatabase.transactionDao()) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + // Room Database + appDatabase = Room.databaseBuilder( + applicationContext, + AppDatabase::class.java, "transaction.db" + ) + .fallbackToDestructiveMigration() + .build() + // Routing binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) @@ -49,21 +65,43 @@ class MainActivity : AppCompatActivity() { performDatabaseOperations() } - private fun performDatabaseOperations() { + private fun getLocationString(): String { + return transactionManager.getLocationString() + } + + private fun performDatabaseOperations() = CoroutineScope(Dispatchers.IO).launch { val locationString = if (hasLocationPermissions() && isLocationEnabled()) { - transactionManager.getLocationString() + getLocationString() } else { "none" } - val transactionId = transactionManager.insertTransaction("Mi Ayam", "Pembelian", 15000, locationString) + // Insert a transaction + val transaction = Transaction(title = "Mi Ayam", category = "Pembelian", amount = 15000f, location = locationString, tanggal = "2023-02-01 12:00:00") + val transactionId = transactionRepository.insertTransaction(transaction) println("Inserted transaction with ID: $transactionId") // Retrieve all transactions - val transactions = transactionManager.getAllTransactions() + val transactions = transactionRepository.getAllTransactions() transactions.forEach { transaction -> - println("Transaction ID: ${transaction.id}, Title: ${transaction.title}, Amount: ${transaction.amount}, Location: ${transaction.location}, Date: ${transaction.tanggal}") + println("Transaction ID: ${transaction.id}, Title: ${transaction.title}, Category: ${transaction.category}, Amount: ${transaction.amount}, Location: ${transaction.location}, Date: ${transaction.tanggal}") } + + // Update last transaction + val lastTransaction = transactions.last() + val updatedTransaction = lastTransaction.copy(title = "Nasi Goreng") + transactionRepository.updateTransaction(updatedTransaction) + println("Updated transaction with ID: ${updatedTransaction.id}") + + // Retrieve all transactions after update + val afterUpdateTransactions = transactionRepository.getAllTransactions() + afterUpdateTransactions.forEach { transaction -> + println("Transaction ID: ${transaction.id}, Title: ${transaction.title}, Category: ${transaction.category}, Amount: ${transaction.amount}, Location: ${transaction.location}, Date: ${transaction.tanggal}") + } + + // Delete the last transaction + transactionRepository.deleteTransaction(lastTransaction) + println("Deleted transaction with ID: ${lastTransaction.id}") } private fun isLocationEnabled(): Boolean { @@ -105,4 +143,4 @@ class MainActivity : AppCompatActivity() { companion object { private const val REQUEST_LOCATION_PERMISSION = 100 } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/example/tubespbd/TransactionManager.kt b/app/src/main/java/com/example/tubespbd/TransactionManager.kt index 94b495fdf3cb260d4219c030fabfcdc553424c7a..a277a87eb1574333cd9c99b8803ab4e186bd29f8 100644 --- a/app/src/main/java/com/example/tubespbd/TransactionManager.kt +++ b/app/src/main/java/com/example/tubespbd/TransactionManager.kt @@ -5,30 +5,8 @@ import android.location.LocationManager import androidx.core.app.ActivityCompat import android.Manifest import android.content.pm.PackageManager -import com.example.tubespbd.database.MyDBHelper -import com.example.tubespbd.database.MyDBHelper.Transaction class TransactionManager(private val context: Context, private val locationManager: LocationManager) { - - private val dbHelper = MyDBHelper(context) - - fun insertTransaction(title: String, type: String, amount: Int, locationString: String): Long { - val locationString = getLocationString() - return dbHelper.insertTransaction(title, type, amount, locationString) - } - - fun getAllTransactions(): List<Transaction> { - return dbHelper.getAllTransactions() - } - - fun updateTransaction(id: Int, title: String, type: String, amount: Int, location: String): Int { - return dbHelper.updateTransaction(id, title, type, amount, location) - } - - fun deleteTransaction(id: Int): Int { - return dbHelper.deleteTransaction(id) - } - fun getLocationString(): String { if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { @@ -42,4 +20,4 @@ class TransactionManager(private val context: Context, private val locationManag "Location not available" } } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/example/tubespbd/database/AppDatabase.kt b/app/src/main/java/com/example/tubespbd/database/AppDatabase.kt new file mode 100644 index 0000000000000000000000000000000000000000..f57c547ec8d2c6edcda25c692f31205dda74cdbf --- /dev/null +++ b/app/src/main/java/com/example/tubespbd/database/AppDatabase.kt @@ -0,0 +1,9 @@ +package com.example.tubespbd.database + +import androidx.room.Database +import androidx.room.RoomDatabase + +@Database(entities = [Transaction::class], version = 2) +abstract class AppDatabase : RoomDatabase() { + abstract fun transactionDao(): TransactionDao +} \ No newline at end of file diff --git a/app/src/main/java/com/example/tubespbd/database/MyDBHelper.kt b/app/src/main/java/com/example/tubespbd/database/MyDBHelper.kt deleted file mode 100644 index fed31afbaf94659770fbb66807eb1d3d64f4cdac..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/tubespbd/database/MyDBHelper.kt +++ /dev/null @@ -1,142 +0,0 @@ - package com.example.tubespbd.database - - import android.content.ContentValues - import android.content.Context - import android.database.sqlite.SQLiteDatabase - import android.database.sqlite.SQLiteOpenHelper - import android.location.Location - import android.location.LocationManager - import android.Manifest - import androidx.core.app.ActivityCompat - - import android.content.pm.PackageManager - import java.text.SimpleDateFormat - import java.util.* - - class MyDBHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { - private val context: Context = context - data class Transaction( - val id: Int, - val title: String, - val category: String, - val amount: Int, - val location: String, - val tanggal: String // Add tanggal attribute - ) - - companion object { - private const val DATABASE_NAME = "transaction.db" - private const val DATABASE_VERSION = 1 - - private const val TABLE_NAME = "transactions" - private const val COLUMN_ID = "id" - private const val COLUMN_TITLE = "title" - private const val COLUMN_CATEGORY = "category" - private const val COLUMN_AMOUNT = "amount" - private const val COLUMN_LOCATION = "location" - private const val COLUMN_TANGGAL = "tanggal" // Define the column name for tanggal - } - - private val CREATE_TABLE = - "CREATE TABLE $TABLE_NAME ($COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT, " + - "$COLUMN_TITLE TEXT, $COLUMN_CATEGORY TEXT, $COLUMN_AMOUNT REAL, $COLUMN_LOCATION TEXT, $COLUMN_TANGGAL TEXT)" // Add COLUMN_TANGGAL to create table statement - - override fun onCreate(db: SQLiteDatabase) { - db.execSQL(CREATE_TABLE) - } - - override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { - db.execSQL("DROP TABLE IF EXISTS $TABLE_NAME") - onCreate(db) - } - - fun insertTransaction(title: String, category: String, amount: Int, location: String): Long { - val db = this.writableDatabase - val tanggal = getCurrentDateTime() - val values = ContentValues().apply { - put(COLUMN_TITLE, title) - put(COLUMN_CATEGORY, category) - put(COLUMN_AMOUNT, amount) - put(COLUMN_LOCATION, location) - put(COLUMN_TANGGAL, tanggal) - } - return db.insert(TABLE_NAME, null, values) - } - - // Function to get current date and time in a specific format - private fun getCurrentDateTime(): String { - val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) - val date = Date() - return dateFormat.format(date) - } - private fun getUserLocation(locationManager: LocationManager): String { - // Check if the location permission is granted - if (ActivityCompat.checkSelfPermission( - context, - Manifest.permission.ACCESS_FINE_LOCATION - ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( - context, - Manifest.permission.ACCESS_COARSE_LOCATION - ) != PackageManager.PERMISSION_GRANTED - ) { - // Handle the case where location permission is not granted - return "Location permission not granted" - } - - // Location permission is granted, proceed with getting the location - val location: Location? = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) - return if (location != null) { - "${location.latitude}, ${location.longitude}" - } else { - "Location not available" - } - } - - - fun getAllTransactions(): ArrayList<Transaction> { - val transactionList = ArrayList<Transaction>() - val selectQuery = "SELECT * FROM $TABLE_NAME" - val db = this.readableDatabase - val cursor = db.rawQuery(selectQuery, null) - cursor?.use { - while (cursor.moveToNext()) { - val idIndex = cursor.getColumnIndex(COLUMN_ID) - val titleIndex = cursor.getColumnIndex(COLUMN_TITLE) - val categoryIndex = cursor.getColumnIndex(COLUMN_CATEGORY) - val amountIndex = cursor.getColumnIndex(COLUMN_AMOUNT) - val locationIndex = cursor.getColumnIndex(COLUMN_LOCATION) - val tanggalIndex = cursor.getColumnIndex(COLUMN_TANGGAL) - // Check if the column exists before accessing its index - if (idIndex != -1 && titleIndex != -1 && categoryIndex != -1 && amountIndex != -1 && locationIndex != -1) { - val id = cursor.getInt(idIndex) - val title = cursor.getString(titleIndex) - val category = cursor.getString(categoryIndex) - val amount = cursor.getInt(amountIndex) - val location = cursor.getString(locationIndex) - val tanggal = cursor.getString(tanggalIndex) - val transaction = Transaction(id, title, category, amount, location, tanggal) - transactionList.add(transaction) - } else { - - } - } - } - return transactionList - } - - fun updateTransaction(id: Int, title: String, category: String, amount: Int, location: String): Int { - val db = this.writableDatabase - val values = ContentValues().apply { - put(COLUMN_TITLE, title) - put(COLUMN_CATEGORY, category) - put(COLUMN_AMOUNT, amount) - put(COLUMN_LOCATION, location) - } - return db.update(TABLE_NAME, values, "$COLUMN_ID = ?", arrayOf(id.toString())) - } - - fun deleteTransaction(id: Int): Int { - val db = this.writableDatabase - return db.delete(TABLE_NAME, "$COLUMN_ID = ?", arrayOf(id.toString())) - } - } \ No newline at end of file diff --git a/app/src/main/java/com/example/tubespbd/database/Transaction.kt b/app/src/main/java/com/example/tubespbd/database/Transaction.kt new file mode 100644 index 0000000000000000000000000000000000000000..5e13329d8f6f5c64393851c103aa108a962c364a --- /dev/null +++ b/app/src/main/java/com/example/tubespbd/database/Transaction.kt @@ -0,0 +1,14 @@ +package com.example.tubespbd.database + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "transactions") +data class Transaction( + @PrimaryKey(autoGenerate = true) val id: Int = 0, + val title: String?, + val category: String?, + val amount: Float?, + val location: String?, + val tanggal: String? +) \ No newline at end of file diff --git a/app/src/main/java/com/example/tubespbd/database/TransactionDAO.kt b/app/src/main/java/com/example/tubespbd/database/TransactionDAO.kt new file mode 100644 index 0000000000000000000000000000000000000000..22fd7547cd4a226b5f83fb10cd233bf4856bb7c7 --- /dev/null +++ b/app/src/main/java/com/example/tubespbd/database/TransactionDAO.kt @@ -0,0 +1,22 @@ +package com.example.tubespbd.database + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Query +import androidx.room.Update + +@Dao +interface TransactionDao { + @Query("SELECT * FROM transactions") + fun getAllTransactions(): List<Transaction> + + @Insert + fun insertTransaction(transaction: Transaction): Long + + @Delete + fun deleteTransaction(transaction: Transaction): Int + + @Update + fun updateTransaction(transaction: Transaction): Int +} \ No newline at end of file diff --git a/app/src/main/java/com/example/tubespbd/database/TransactionRepository.kt b/app/src/main/java/com/example/tubespbd/database/TransactionRepository.kt new file mode 100644 index 0000000000000000000000000000000000000000..1c8f8b658099e645ab492cdf738f6a69b9e91ec0 --- /dev/null +++ b/app/src/main/java/com/example/tubespbd/database/TransactionRepository.kt @@ -0,0 +1,20 @@ +package com.example.tubespbd.database + +class TransactionRepository(private val transactionDao: TransactionDao) { + + fun getAllTransactions(): List<Transaction> { + return transactionDao.getAllTransactions() + } + + fun insertTransaction(transaction: Transaction): Long { + return transactionDao.insertTransaction(transaction) + } + + fun deleteTransaction(transaction: Transaction): Int { + return transactionDao.deleteTransaction(transaction) + } + + fun updateTransaction(transaction: Transaction): Int { + return transactionDao.updateTransaction(transaction) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/tubespbd/database/TransactionViewModel.kt b/app/src/main/java/com/example/tubespbd/database/TransactionViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..1effce60a1909ca7966cc07a2a795685cb6571f1 --- /dev/null +++ b/app/src/main/java/com/example/tubespbd/database/TransactionViewModel.kt @@ -0,0 +1,22 @@ +//package com.example.tubespbd.database +// +//import androidx.lifecycle.ViewModel +//import androidx.lifecycle.viewModelScope +//import kotlinx.coroutines.launch +// +//class TransactionViewModel(private val repository: TransactionRepository) : ViewModel() { +// +// fun getAllTransactions() = repository.getAllTransactions() +// +// fun insert(transaction: Transaction) = viewModelScope.launch { +// repository.insertTransaction(transaction) +// } +// +// fun delete(transaction: Transaction) = viewModelScope.launch { +// repository.deleteTransaction(transaction) +// } +// +// fun update(transaction: Transaction) = viewModelScope.launch { +// repository.updateTransaction(transaction) +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/example/tubespbd/database/TransactionViewModelFactory.kt b/app/src/main/java/com/example/tubespbd/database/TransactionViewModelFactory.kt new file mode 100644 index 0000000000000000000000000000000000000000..2a5e0cc96d50523389a841701113edb7fb615370 --- /dev/null +++ b/app/src/main/java/com/example/tubespbd/database/TransactionViewModelFactory.kt @@ -0,0 +1,14 @@ +//import androidx.lifecycle.ViewModel +//import androidx.lifecycle.ViewModelProvider +//import com.example.tubespbd.database.TransactionRepository +//import com.example.tubespbd.database.TransactionViewModel +// +//class TransactionViewModelFactory(private val repository: TransactionRepository) : ViewModelProvider.Factory { +// override fun <T : ViewModel?> create(modelClass: Class<T>): T { +// if (modelClass.isAssignableFrom(TransactionViewModel::class.java)) { +// @Suppress("UNCHECKED_CAST") +// return TransactionViewModel(repository) as T +// } +// throw IllegalArgumentException("Unknown ViewModel class") +// } +//} \ No newline at end of file