diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6f1fbb30dd43cbca91cda87605ae711aa385bd20..b2ac01d0113963cf6077f476521225553a028076 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -69,5 +69,15 @@ dependencies { debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-test-manifest") + // Retrofit + implementation("com.google.code.gson:gson:2.9.0") + implementation("com.squareup.retrofit2:retrofit:2.9.0") + implementation("com.squareup.retrofit2:converter-gson:2.9.0") + + // Room + implementation("androidx.room:room-runtime:2.5.0") + annotationProcessor("androidx.room:room-compiler:2.5.0") + implementation("androidx.room:room-ktx:2.5.0") + implementation ("net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC3") } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/adapters/TransaksiAdapter.kt b/app/src/main/java/com/example/bondoman/adapters/TransaksiAdapter.kt new file mode 100644 index 0000000000000000000000000000000000000000..ba4e5b7c733fed22d7c52d0c074b0e411bea1ac9 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/adapters/TransaksiAdapter.kt @@ -0,0 +1,66 @@ +package com.example.bondoman.adapters + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageButton +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.example.bondoman.R +import com.example.bondoman.domain.TransaksiItem +import com.example.bondoman.ui.theme.OnTransaksiUpdateListener + +class TransaksiAdapter ( + private var list: ArrayList<TransaksiItem> +) : RecyclerView.Adapter<TransaksiAdapter.TransaksiHolder>() { + + private lateinit var onTransaksiUpdateListener: OnTransaksiUpdateListener + + class TransaksiHolder(val view: View, private val onTransaksiUpdateListener: OnTransaksiUpdateListener) : RecyclerView.ViewHolder(view) { + private var transaksiNameTextView: TextView? = null + private var transaksiNominalTextView: TextView? = null + private var transaksiCategoryTextView: TextView? = null + private var transaksiLocationTextView: TextView? = null + private var transaksiAddButton: ImageButton? = null + + init { + transaksiNameTextView = view.findViewById(R.id.transaksiNameTextView) + transaksiNominalTextView = view.findViewById(R.id.transaksiNominalTextView) + transaksiCategoryTextView = view.findViewById(R.id.transaksiCategoryTextView) + transaksiLocationTextView = view.findViewById(R.id.transaksiLocationTextView) + transaksiAddButton = view.findViewById(R.id.transaksiAddButton) + } + + fun bind(data: TransaksiItem) { + transaksiNameTextView?.text = data.name + transaksiNominalTextView?.text = data.nominal.toString() + transaksiLocationTextView?.text = data.location + + transaksiAddButton?.setOnClickListener { + val pos = adapterPosition + if (pos != RecyclerView.NO_POSITION) { + onTransaksiUpdateListener.OnItemUpdated(data, pos) + } + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransaksiHolder { + return TransaksiHolder(LayoutInflater.from(parent.context).inflate(R.layout.transaksi_card, parent, false), onTransaksiUpdateListener) + } + + override fun onBindViewHolder(holder: TransaksiHolder, position: Int) { + holder.bind(list[position]) + } + + override fun getItemCount(): Int { + return list!!.size + } + + fun updateTransaksiList(transaksiList: ArrayList<TransaksiItem>, onTransaksiUpdateListener: OnTransaksiUpdateListener) { + list.clear() + list = transaksiList + this.onTransaksiUpdateListener = onTransaksiUpdateListener + notifyDataSetChanged() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/api/BondomanApi.kt b/app/src/main/java/com/example/bondoman/api/BondomanApi.kt new file mode 100644 index 0000000000000000000000000000000000000000..efdce03087d5bb15ad5d4c0b137cc418689186da --- /dev/null +++ b/app/src/main/java/com/example/bondoman/api/BondomanApi.kt @@ -0,0 +1,9 @@ +package com.example.bondoman.api + +import retrofit2.Response +import retrofit2.http.GET + +interface BondomanApi { + @GET("/v1/transaksi") + suspend fun getTransaksi(): Response<TransaksiResponse> +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/api/RetrofitInstance.kt b/app/src/main/java/com/example/bondoman/api/RetrofitInstance.kt new file mode 100644 index 0000000000000000000000000000000000000000..407948f8b5b7c9369cef302bfa3744d74d7ab314 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/api/RetrofitInstance.kt @@ -0,0 +1,17 @@ +package com.example.bondoman.api + +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +object RetrofitInstance { + private val retrofit by lazy { + Retrofit.Builder() + .baseUrl("http://192.168.18.30:3000/") + .addConverterFactory(GsonConverterFactory.create()) + .build() + } + + val api: BondomanApi by lazy { + retrofit.create(BondomanApi::class.java) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/api/TransaksiResponse.kt b/app/src/main/java/com/example/bondoman/api/TransaksiResponse.kt new file mode 100644 index 0000000000000000000000000000000000000000..1d2cbf310aec2c7df5df62dfe8eb067275eb31d1 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/api/TransaksiResponse.kt @@ -0,0 +1,12 @@ +package com.example.bondoman.api + +import com.example.bondoman.domain.TransaksiItem +import com.google.gson.annotations.SerializedName + +data class TransaksiResponse ( + @field:SerializedName("data") + val data: List<TransaksiItem>? = null, + + @field:SerializedName("size") + val size: Int? = null, +) \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/database/AppDatabase.kt b/app/src/main/java/com/example/bondoman/database/AppDatabase.kt new file mode 100644 index 0000000000000000000000000000000000000000..f32a25e4bd241ff12153442841dc87d92b956c27 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/database/AppDatabase.kt @@ -0,0 +1,31 @@ +package com.example.bondoman.database + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase + +@Database(entities = [Item:: class], version = 1) +abstract class AppDatabase : RoomDatabase() { + abstract fun getTransaksiDao() : TransaksiDao + + companion object { + @Volatile + private var instance : AppDatabase? = null + private val LOCK = Any() + + operator fun invoke(context: Context) = instance ?: synchronized(LOCK) { + instance ?: buildDatabase(context).also { + instance = it + } + } + + fun buildDatabase(context: Context) = Room.databaseBuilder( + context.applicationContext, + AppDatabase::class.java, + "bondoman-database" + ) + .allowMainThreadQueries() + .build() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/database/Item.kt b/app/src/main/java/com/example/bondoman/database/Item.kt new file mode 100644 index 0000000000000000000000000000000000000000..a782e05a62f93a5d147eadd81fe14d661ded8ba6 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/database/Item.kt @@ -0,0 +1,14 @@ +package com.example.bondoman.database + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "transaksi_table") +data class Item( + @PrimaryKey(autoGenerate = true) var id: Int, + @ColumnInfo(name = "name") val name: String, + @ColumnInfo(name = "nominal") val nominal: Int, + @ColumnInfo(name = "category") val category: String, + @ColumnInfo(name = "location") val location: String +) \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/database/TransaksiDao.kt b/app/src/main/java/com/example/bondoman/database/TransaksiDao.kt new file mode 100644 index 0000000000000000000000000000000000000000..4d2abf31b28dd3759a1b217c16fce0382fd73d11 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/database/TransaksiDao.kt @@ -0,0 +1,32 @@ +package com.example.bondoman.database + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Query +import androidx.room.Update + +@Dao +interface TransaksiDao { + @Insert + suspend fun addItem(item: Item) + + @Query("SELECT * FROM transaksi_table ORDER BY id ASC") + fun getAllItem(): LiveData<List<Item>> + + @Query("SELECT * FROM transaksi_table ORDER BY id ASC") + fun getAllItemSynchronous(): List<Item> + + @Update + suspend fun updateItem(item: Item) + + @Delete + suspend fun deleteItem(item: Item) + + @Query("DELETE FROM transaksi_table") + suspend fun deleteAllItems() + + @Query("SELECT * FROM transaksi_table WHERE name LIKE :nameQuery AND nominal = :nominalQuery LIMIT 1") + fun getByNameAndNominal(nameQuery: String, nominalQuery: Int): Item +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/domain/TransaksiItem.kt b/app/src/main/java/com/example/bondoman/domain/TransaksiItem.kt new file mode 100644 index 0000000000000000000000000000000000000000..913d14d312fd51da6536bd78664da8f144077b69 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/domain/TransaksiItem.kt @@ -0,0 +1,17 @@ +package com.example.bondoman.domain + +import com.google.gson.annotations.SerializedName + +data class TransaksiItem( + @field:SerializedName("name") + val name: String, + + @field:SerializedName("category") + val category: String, + + @field:SerializedName("nominal") + val nominal: Int, + + @field:SerializedName("location") + val location: String, +) \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/repository/TransaksiRepository.kt b/app/src/main/java/com/example/bondoman/repository/TransaksiRepository.kt new file mode 100644 index 0000000000000000000000000000000000000000..b4ae71fbfd34f3c85491a6c785d857c85d06f3ce --- /dev/null +++ b/app/src/main/java/com/example/bondoman/repository/TransaksiRepository.kt @@ -0,0 +1,33 @@ +package com.example.bondoman.repository + +import androidx.lifecycle.LiveData +import com.example.bondoman.database.Item +import com.example.bondoman.database.TransaksiDao + +class TransaksiRepository(private val transaksiDao: TransaksiDao) { + val getAllItem: LiveData<List<Item>> = transaksiDao.getAllItem() + + suspend fun getAllItemSynchronous(): List<Item> { + return transaksiDao.getAllItemSynchronous() + } + + suspend fun addItem(item: Item) { + transaksiDao.addItem(item) + } + + suspend fun updateItem(item: Item) { + transaksiDao.updateItem(item) + } + + suspend fun deleteItem(item: Item) { + transaksiDao.deleteItem(item) + } + + suspend fun deleteAllItem() { + transaksiDao.deleteAllItems() + } + + fun getByNameAndNominal(nameQuery: String, nominalQuery: Int) : Item { + return transaksiDao.getByNameAndNominal(nameQuery, nominalQuery) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/ui/theme/OnItemUpdateListener.kt b/app/src/main/java/com/example/bondoman/ui/theme/OnItemUpdateListener.kt new file mode 100644 index 0000000000000000000000000000000000000000..2f16f8043348c03b47a3d9584de5c0e3abf9261d --- /dev/null +++ b/app/src/main/java/com/example/bondoman/ui/theme/OnItemUpdateListener.kt @@ -0,0 +1,11 @@ +package com.example.bondoman.ui.theme + +import com.example.bondoman.database.Item + +interface OnItemUpdateListener { + + fun OnItemUpdated(item: Item, position: Int) + + fun onItemDecrease(item: Item, position: Int) + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/ui/theme/OnTransaksiUpdateListener.kt b/app/src/main/java/com/example/bondoman/ui/theme/OnTransaksiUpdateListener.kt new file mode 100644 index 0000000000000000000000000000000000000000..d875a3dac6fe94525686f556f5bcf06fc6c2d5e9 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/ui/theme/OnTransaksiUpdateListener.kt @@ -0,0 +1,9 @@ +package com.example.bondoman.ui.theme + +import com.example.bondoman.domain.TransaksiItem + +interface OnTransaksiUpdateListener { + fun OnItemUpdated(item: TransaksiItem, position: Int) + + fun onItemDecrease(item: TransaksiItem, position: Int) +} \ No newline at end of file diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml new file mode 100644 index 0000000000000000000000000000000000000000..29dd8e40568b5f4bf9c5f0f6a226d23907185dfc --- /dev/null +++ b/app/src/main/res/values/ids.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <item name="transaksiNameTextView" type="id" /> + <item name="transaksiNominalTextView" type="id" /> + <item name="transaksiCategoryTextView" type="id" /> + <item name="transaksiLocationTextView" type="id" /> + <item name="transaksiAddButton" type="id" /> +</resources> \ No newline at end of file