product create, update, delete

This commit is contained in:
Gracia Hotmauli
2025-05-25 17:31:07 +07:00
parent 59e2e6a43b
commit e9b4d7a8f1
4 changed files with 89 additions and 52 deletions

View File

@ -274,10 +274,13 @@ interface ApiService {
@Part halal: MultipartBody.Part?
): Response<CreateProductResponse>
@PUT("store/editproduct/{id}")
@Multipart
@PUT("store/editproduct")
suspend fun updateProduct(
@Path("id") productId: Int?,
@Body updatedProduct: Map<String, Any?>
@PartMap data: Map<String, @JvmSuppressWildcards RequestBody>,
@Part productImage: MultipartBody.Part?,
@Part halal: MultipartBody.Part?,
@Part sppirt: MultipartBody.Part?
): Response<UpdateProductResponse>
@DELETE("store/deleteproduct/{id}")

View File

@ -12,10 +12,8 @@ import com.alya.ecommerce_serang.data.api.response.customer.cart.AddCartResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.ProductResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.ReviewsItem
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreProduct
import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse
import com.alya.ecommerce_serang.data.api.response.product.Search
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.utils.SessionManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
@ -267,16 +265,13 @@ class ProductRepository(private val apiService: ApiService) {
}
}
suspend fun updateProduct(productId: Int?, updatedProduct: Map<String, Any?>) : UpdateProductResponse {
// Build the request with the updated fields
val response = apiService.updateProduct(productId, updatedProduct)
if (response.isSuccessful) {
return response.body()!!
} else {
throw Exception("Gagal memperbarui produk: ${response.code()}")
}
}
suspend fun updateProduct(
productId: Int?,
data: Map<String, RequestBody>,
image: MultipartBody.Part?,
halal: MultipartBody.Part?,
sppirt: MultipartBody.Part?
) = apiService.updateProduct(data, image, halal, sppirt)
suspend fun deleteProduct(productId: Int): Result<Unit> {
return withContext(Dispatchers.IO) {

View File

@ -110,17 +110,6 @@ class DetailStoreProductActivity : AppCompatActivity() {
adapterCondition.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
binding.spinnerKondisiProduk.adapter = adapterCondition
// Setup Pre-Order visibility
binding.switchIsPreOrder.setOnCheckedChangeListener { _, isChecked ->
togglePreOrderVisibility(isChecked)
validateForm()
}
binding.switchIsWholesale.setOnCheckedChangeListener { _, isChecked ->
toggleWholesaleVisibility(isChecked)
validateForm()
}
with(binding) {
edtNamaProduk.doAfterTextChanged { validateForm() }
edtDeskripsiProduk.doAfterTextChanged { validateForm() }
@ -131,8 +120,14 @@ class DetailStoreProductActivity : AppCompatActivity() {
edtDurasi.doAfterTextChanged { validateForm() }
edtMinPesanGrosir.doAfterTextChanged { validateForm() }
edtHargaGrosir.doAfterTextChanged { validateForm() }
switchIsPreOrder.setOnCheckedChangeListener { _, _ -> validateForm() }
switchIsWholesale.setOnCheckedChangeListener { _, _ -> validateForm() }
switchIsPreOrder.setOnCheckedChangeListener { _, isChecked ->
togglePreOrderVisibility(isChecked)
validateForm()
}
switchIsWholesale.setOnCheckedChangeListener { _, isChecked ->
toggleWholesaleVisibility(isChecked)
validateForm()
}
}
validateForm()
@ -424,27 +419,61 @@ class DetailStoreProductActivity : AppCompatActivity() {
}
private fun updateProduct(productId: Int?) {
val updatedProduct = mapOf(
"name" to binding.edtNamaProduk.text.toString(),
"description" to binding.edtDeskripsiProduk.text.toString(),
"price" to binding.edtHargaProduk.text.toString(),
"stock" to binding.edtStokProduk.text.toString().toInt(),
"min_order" to binding.edtMinOrder.text.toString().toInt(),
"weight" to binding.edtBeratProduk.text.toString().toInt(),
"is_pre_order" to binding.switchIsPreOrder.isChecked,
"duration" to (binding.edtDurasi.text.toString().toIntOrNull() ?: 0),
"is_wholesale" to binding.switchIsWholesale.isChecked,
"wholesale_min_item" to (binding.edtMinPesanGrosir.text.toString().toIntOrNull() ?: 0),
"wholesale_price" to (binding.edtHargaGrosir.text.toString().toIntOrNull() ?: 0),
"category_id" to categoryList[binding.spinnerKategoriProduk.selectedItemPosition].id,
"status" to if (binding.switchIsActive.isChecked) "active" else "inactive",
"condition" to binding.spinnerKondisiProduk.selectedItem.toString(),
"productimg" to imageUri?.path,
"sppirt" to sppirtUri?.path,
"halal" to halalUri?.path
if (productId == null) return
val imageFile = imageUri?.let { uriToNamedFile(it, this, "productimg") }
val sppirtFile = sppirtUri?.let { uriToNamedFile(it, this, "sppirt") }
val halalFile = halalUri?.let { uriToNamedFile(it, this, "halal") }
val imagePart = createPartFromFile("productimg", imageFile)
val sppirtPart = createPartFromFile("sppirt", sppirtFile)
val halalPart = createPartFromFile("halal", halalFile)
val data = mutableMapOf<String, RequestBody>(
"product_id" to toRequestBody(productId.toString()),
"name" to toRequestBody(binding.edtNamaProduk.text.toString()),
"description" to toRequestBody(binding.edtDeskripsiProduk.text.toString()),
"price" to toRequestBody(binding.edtHargaProduk.text.toString()),
"stock" to toRequestBody(binding.edtStokProduk.text.toString()),
"min_order" to toRequestBody(binding.edtMinOrder.text.toString()),
"weight" to toRequestBody(binding.edtBeratProduk.text.toString()),
"is_pre_order" to toRequestBody(binding.switchIsPreOrder.isChecked.toString()),
"preorder_duration" to toRequestBody(
if (binding.switchIsPreOrder.isChecked)
binding.edtDurasi.text.toString()
else
"0"
),
"is_wholesale" to toRequestBody(binding.switchIsWholesale.isChecked.toString()),
"wholesale_min_item" to toRequestBody(
if (binding.switchIsWholesale.isChecked)
binding.edtMinPesanGrosir.text.toString()
else
"0"
),
"wholesale_price" to toRequestBody(
if (binding.switchIsWholesale.isChecked)
binding.edtHargaGrosir.text.toString()
else
"0"
),
"category_id" to toRequestBody(
categoryList[binding.spinnerKategoriProduk.selectedItemPosition].id.toString()
),
"status" to toRequestBody(
if (binding.switchIsActive.isChecked) "active" else "inactive"
),
"condition" to toRequestBody(binding.spinnerKondisiProduk.selectedItem.toString())
)
viewModel.updateProduct(
productId,
data,
imagePart,
halalPart,
sppirtPart
)
viewModel.updateProduct(productId, updatedProduct)
viewModel.productUpdateResult.observe(this) { result ->
when (result) {
is Result.Loading -> binding.btnSaveProduct.isEnabled = false
@ -461,4 +490,7 @@ class DetailStoreProductActivity : AppCompatActivity() {
}
}
}
private fun toRequestBody(value: String): RequestBody =
RequestBody.create("text/plain".toMediaTypeOrNull(), value)
}

View File

@ -17,6 +17,7 @@ import com.alya.ecommerce_serang.data.repository.ProductRepository
import com.alya.ecommerce_serang.data.repository.Result
import kotlinx.coroutines.launch
import okhttp3.MultipartBody
import okhttp3.RequestBody
class ProductViewModel(private val repository: ProductRepository) : ViewModel() {
@ -107,14 +108,20 @@ class ProductViewModel(private val repository: ProductRepository) : ViewModel()
}
}
fun updateProduct(productId: Int?, updatedProduct: Map<String, Any?>) {
_productUpdateResult.value = Result.Loading
fun updateProduct(
productId: Int?,
data: Map<String, RequestBody>,
image: MultipartBody.Part?,
halal: MultipartBody.Part?,
sppirt: MultipartBody.Part?
) {
viewModelScope.launch {
_productUpdateResult.postValue(Result.Loading)
try {
val response = repository.updateProduct(productId, updatedProduct)
_productUpdateResult.value = Result.Success(response)
val response = repository.updateProduct(productId, data, image, halal, sppirt)
_productUpdateResult.postValue(Result.Success(response.body()!!))
} catch (e: Exception) {
_productUpdateResult.value = Result.Error(e)
_productUpdateResult.postValue(Result.Error(e))
}
}
}