diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/store/profile/GenericResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/store/GenericResponse.kt similarity index 74% rename from app/src/main/java/com/alya/ecommerce_serang/data/api/response/store/profile/GenericResponse.kt rename to app/src/main/java/com/alya/ecommerce_serang/data/api/response/store/GenericResponse.kt index 6a665b5..102ef2d 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/store/profile/GenericResponse.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/store/GenericResponse.kt @@ -1,4 +1,4 @@ -package com.alya.ecommerce_serang.data.api.response.store.profile +package com.alya.ecommerce_serang.data.api.response.store import com.google.gson.annotations.SerializedName @@ -8,4 +8,4 @@ data class GenericResponse( @SerializedName("success") val success: Boolean = true -) +) \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt index 7265b5f..f9a1ec7 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/retrofit/ApiService.kt @@ -71,7 +71,7 @@ import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductRe import com.alya.ecommerce_serang.data.api.response.store.product.DeleteProductResponse import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse import com.alya.ecommerce_serang.data.api.response.store.product.ViewStoreProductsResponse -import com.alya.ecommerce_serang.data.api.response.store.profile.GenericResponse +import com.alya.ecommerce_serang.data.api.response.store.GenericResponse import com.alya.ecommerce_serang.data.api.response.store.profile.StoreDataResponse import com.alya.ecommerce_serang.data.api.response.store.topup.BalanceTopUpResponse import com.alya.ecommerce_serang.data.api.response.store.topup.TopUpResponse @@ -339,10 +339,22 @@ interface ApiService { @PUT("store/order/update") suspend fun updateOrder( - @Query("order_id") orderId: Int?, - @Query("status") status: String + @Part("order_id") orderId: Int?, + @Part("status") status: String ): Response + @PUT("store/payment/update") + suspend fun confirmPayment( + @Part("order_id") orderId: Int?, + @Part("status") status: String + ): Response + + @PUT("store/shipping/receiptnum") + suspend fun confirmShipment( + @Part("receipt_num") receiptNum: String, + @Part("order_id") orderId: Int? + ): Response + @Multipart @POST("addcomplaint") suspend fun addComplaint( diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/repository/SellsRepository.kt b/app/src/main/java/com/alya/ecommerce_serang/data/repository/SellsRepository.kt index 2b9df12..e2313b6 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/data/repository/SellsRepository.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/data/repository/SellsRepository.kt @@ -2,10 +2,12 @@ package com.alya.ecommerce_serang.data.repository import android.util.Log import com.alya.ecommerce_serang.data.api.dto.PaymentConfirmRequest +import com.alya.ecommerce_serang.data.api.response.store.GenericResponse import com.alya.ecommerce_serang.data.api.response.store.sells.OrderDetailResponse import com.alya.ecommerce_serang.data.api.response.store.sells.OrderListResponse import com.alya.ecommerce_serang.data.api.response.store.sells.PaymentConfirmationResponse import com.alya.ecommerce_serang.data.api.retrofit.ApiService +import retrofit2.Response class SellsRepository(private val apiService: ApiService) { suspend fun getSellList(status: String): Result { @@ -43,40 +45,25 @@ class SellsRepository(private val apiService: ApiService) { } } - suspend fun updateOrderStatus(orderId: Int?, status: String) { - try { - val response = apiService.updateOrder(orderId, status) - if (response.isSuccessful) { - Log.d("SellsRepository", "Order status updated successfully: orderId=$orderId, status=$status") - } else { - Log.e("SellsRepository", "Error updating order status: orderId=$orderId, status=$status") - } - } catch (e: Exception) { - Log.e("SellsRepository", "Exception updating order status", e) - } - } - - suspend fun confirmPaymentStore(request: PaymentConfirmRequest): Result { + suspend fun confirmPayment(orderId: Int, status: String): Response { return try { - Log.d("SellsRepository", "Conforming order request completed: $request") - val response = apiService.paymentConfirmation(request) - - if(response.isSuccessful) { - val paymentConfirmResponse = response.body() - if (paymentConfirmResponse != null) { - Log.d("SellsRepository", "Order confirmed successfully: ${paymentConfirmResponse.message}") - Result.Success(paymentConfirmResponse) - } else { - Log.e("SellsRepository", "Response body was null") - Result.Error(Exception("Empty response from server")) - } - } else { - val errorBody = response.errorBody()?.string() ?: "Unknown Error" - Log.e("SellsRepository", "Error confirming order: $errorBody") - Result.Error(Exception(errorBody)) - } - } catch (e: Exception){ - Result.Error(e) + Log.d("SellsRepository", "Calling confirmPayment with orderId=$orderId, status=$status") + apiService.confirmPayment(orderId, status) + } catch (e: Exception) { + Log.e("SellsRepository", "Error during confirmPayment", e) + throw e } } + + suspend fun confirmShipment(orderId: Int, receiptNum: String): Response { + return try { + apiService.confirmShipment( + receiptNum = receiptNum, + orderId = orderId + ) + } catch (e: Exception) { + throw e + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/payment/DetailPaymentActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/payment/DetailPaymentActivity.kt index 2673b32..36679ae 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/payment/DetailPaymentActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/payment/DetailPaymentActivity.kt @@ -16,7 +16,6 @@ import android.widget.TextView import android.widget.Toast import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.recyclerview.widget.LinearLayoutManager import com.alya.ecommerce_serang.BuildConfig.BASE_URL import com.alya.ecommerce_serang.R import com.alya.ecommerce_serang.data.api.response.store.sells.Orders @@ -26,7 +25,6 @@ import com.alya.ecommerce_serang.data.repository.AddressRepository import com.alya.ecommerce_serang.data.repository.SellsRepository import com.alya.ecommerce_serang.databinding.ActivityDetailPaymentBinding import com.alya.ecommerce_serang.ui.profile.mystore.sells.SellsProductAdapter -import com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment.DetailShipmentActivity import com.alya.ecommerce_serang.utils.BaseViewModelFactory import com.alya.ecommerce_serang.utils.SessionManager import com.alya.ecommerce_serang.utils.viewmodel.AddressViewModel @@ -40,6 +38,7 @@ import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale import java.util.TimeZone +import androidx.core.graphics.drawable.toDrawable class DetailPaymentActivity : AppCompatActivity() { @@ -84,6 +83,32 @@ class DetailPaymentActivity : AppCompatActivity() { observeOrderDetails() + binding.tvOrderSellsDesc.setOnClickListener { + val paymentEvidence = sells?.paymentEvidence + if (!paymentEvidence.isNullOrEmpty()) { + showPaymentEvidenceDialog(paymentEvidence) + } else { + Toast.makeText(this, "Bukti pembayaran tidak tersedia", Toast.LENGTH_SHORT).show() + } + } + + binding.btnHoldPayment.setOnClickListener { + sells?.orderId?.let { + viewModel.confirmPayment(it, "onhold") + Toast.makeText(this, "Otomatis pembayaran dinonaktifkan", Toast.LENGTH_SHORT).show() + } ?: run { + Log.e("DetailPaymentActivity", "No order passed in intent") + } + } + + binding.btnConfirmPayment.setOnClickListener { + sells?.orderId?.let { + viewModel.confirmPayment(it, "confirmed") + Toast.makeText(this, "Pembayaran dikonfirmasi", Toast.LENGTH_SHORT).show() + } ?: run { + Log.e("DetailPaymentActivity", "No order passed in intent") + } + } } private fun observeOrderDetails() { @@ -173,17 +198,6 @@ class DetailPaymentActivity : AppCompatActivity() { return String.format(Locale("id", "ID"), "Rp%,.0f", priceDouble) } - private fun setupPaymentEvidenceViewer() { - binding.tvOrderSellsDesc.setOnClickListener { - val paymentEvidence = sells?.paymentEvidence - if (!paymentEvidence.isNullOrEmpty()) { - showPaymentEvidenceDialog(paymentEvidence) - } else { - Toast.makeText(this, "Bukti pembayaran tidak tersedia", Toast.LENGTH_SHORT).show() - } - } - } - private fun showPaymentEvidenceDialog(paymentEvidence: String) { val dialog = Dialog(this) dialog.requestWindowFeature(Window.FEATURE_NO_TITLE) @@ -193,7 +207,7 @@ class DetailPaymentActivity : AppCompatActivity() { // Set dialog to fullscreen val window = dialog.window window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) - window?.setBackgroundDrawable(ColorDrawable(Color.BLACK)) + window?.setBackgroundDrawable(Color.WHITE.toDrawable()) // Get views from dialog val imageView = dialog.findViewById(R.id.iv_payment_evidence) @@ -201,21 +215,13 @@ class DetailPaymentActivity : AppCompatActivity() { val tvTitle = dialog.findViewById(R.id.tv_title) val progressBar = dialog.findViewById(R.id.progress_bar) - // Set title tvTitle.text = "Bukti Pembayaran" + val fullImageUrl = + if (paymentEvidence.startsWith("/")) BASE_URL + paymentEvidence.substring(1) + else paymentEvidence - // Build image URL - val fullImageUrl = when (val img = paymentEvidence) { - is String -> { - if (img.startsWith("/")) BASE_URL + img.substring(1) else img - } - else -> R.drawable.placeholder_image // Default image for null - } - - // Show progress bar while loading progressBar.visibility = View.VISIBLE - // Load image with Glide Glide.with(this) .load(fullImageUrl) .placeholder(R.drawable.placeholder_image) @@ -239,16 +245,8 @@ class DetailPaymentActivity : AppCompatActivity() { } }) - - // Close button click listener - btnClose.setOnClickListener { - dialog.dismiss() - } - - // Click outside to close - imageView.setOnClickListener { - dialog.dismiss() - } + btnClose.setOnClickListener { dialog.dismiss() } + imageView.setOnClickListener { dialog.dismiss() } dialog.show() } diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/DetailShipmentActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/DetailShipmentActivity.kt index fd5329d..9ca1b03 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/DetailShipmentActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/DetailShipmentActivity.kt @@ -1,7 +1,9 @@ package com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment +import android.content.Intent import android.os.Bundle import android.util.Log +import android.widget.Toast import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import com.alya.ecommerce_serang.data.api.response.store.sells.Orders @@ -64,6 +66,16 @@ class DetailShipmentActivity : AppCompatActivity() { } observeOrderDetails() + + binding.btnConfirmShipment.setOnClickListener { + sells?.let { + val intent = Intent(this, ShipmentConfirmationActivity::class.java) + intent.putExtra("sells_data", Gson().toJson(it)) + startActivity(intent) + } ?: run { + Toast.makeText(this, "Data pesanan tidak tersedia", Toast.LENGTH_SHORT).show() + } + } } private fun observeOrderDetails() { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/ShipmentConfirmationActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/ShipmentConfirmationActivity.kt index f05c51c..2cc4b28 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/ShipmentConfirmationActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/sells/shipment/ShipmentConfirmationActivity.kt @@ -1,21 +1,71 @@ package com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment import android.os.Bundle -import androidx.activity.enableEdgeToEdge +import android.widget.Toast +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import com.alya.ecommerce_serang.R +import com.alya.ecommerce_serang.data.api.response.store.sells.Orders +import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig +import com.alya.ecommerce_serang.data.repository.SellsRepository +import com.alya.ecommerce_serang.databinding.ActivityShipmentConfirmationBinding +import com.alya.ecommerce_serang.utils.BaseViewModelFactory +import com.alya.ecommerce_serang.utils.SessionManager +import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel +import com.google.gson.Gson +import kotlin.getValue class ShipmentConfirmationActivity : AppCompatActivity() { + private lateinit var binding: ActivityShipmentConfirmationBinding + private var sells: Orders? = null + private lateinit var sessionManager: SessionManager + + private val viewModel: SellsViewModel by viewModels { + BaseViewModelFactory { + sessionManager = SessionManager(this) + val apiService = ApiConfig.getApiService(sessionManager) + val sellsRepository = SellsRepository(apiService) + SellsViewModel(sellsRepository) + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContentView(R.layout.activity_shipment_confirmation) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets + binding = ActivityShipmentConfirmationBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.header.headerTitle.text = "Konfirmasi Pengiriman" + binding.header.headerLeftIcon.setOnClickListener { + onBackPressed() + finish() + } + + val sellsJson = intent.getStringExtra("sells_data") + sells = Gson().fromJson(sellsJson, Orders::class.java) + + // Pre-fill fields + binding.edtNoPesanan.setText(sells?.orderId?.toString()) + binding.edtKurir.setText(sells?.courier ?: "") + binding.edtLayananKirim.setText(sells?.service ?: "") + + binding.btnConfirm.setOnClickListener { + val receiptNum = binding.edtNoResi.text.toString().trim() + val orderId = sells?.orderId + + if (receiptNum.isEmpty()) { + Toast.makeText(this, "Nomor resi tidak boleh kosong", Toast.LENGTH_SHORT).show() + } else if (orderId == null) { + Toast.makeText(this, "Order ID tidak ditemukan", Toast.LENGTH_SHORT).show() + } else { + viewModel.confirmShipment(orderId, receiptNum) + } + } + + viewModel.message.observe(this) { + Toast.makeText(this, it, Toast.LENGTH_SHORT).show() + } + + viewModel.isSuccess.observe(this) { success -> + if (success) finish() } } } \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/SellsViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/SellsViewModel.kt index 101ff93..5b8c0f4 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/SellsViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/SellsViewModel.kt @@ -169,42 +169,53 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() { } } - fun updateOrderStatus(orderId: Int?, status: String) { - Log.d(TAG, "========== Starting updateOrderStatus ==========") - Log.d(TAG, "Updating order status: orderId=$orderId, status='$status'") + fun confirmPayment(orderId: Int, status: String) { + Log.d(TAG, "Confirming order completed: orderId=$orderId, status=$status") + _isLoading.value = true viewModelScope.launch { try { - Log.d(TAG, "Calling repository.updateOrderStatus") - val startTime = System.currentTimeMillis() - - repository.updateOrderStatus(orderId, status) - - val endTime = System.currentTimeMillis() - Log.d(TAG, "✅ Order status updated successfully in ${endTime - startTime}ms") - Log.d(TAG, "Updated orderId=$orderId to status='$status'") - + val response = repository.confirmPayment(orderId, status) + if (response.isSuccessful) { + val body = response.body() + Log.d(TAG, "confirmPayment success: ${body?.message}") + _message.value = body?.message ?: "Status berhasil diperbarui" + _isSuccess.value = true + } else { + val errorMsg = response.errorBody()?.string() ?: "Unknown error" + Log.e(TAG, "confirmPayment failed: $errorMsg") + _error.value = "Gagal memperbarui status: $errorMsg" + _isSuccess.value = false + } } catch (e: Exception) { - Log.e(TAG, "❌ Error updating order status") - Log.e(TAG, "Exception type: ${e.javaClass.simpleName}") - Log.e(TAG, "Exception message: ${e.message}") - Log.e(TAG, "Exception stack trace:", e) + Log.e(TAG, "Exception in confirmPayment", e) + _error.value = "Terjadi kesalahan: ${e.message}" + _isSuccess.value = false + } finally { + _isLoading.value = false } } - - Log.d(TAG, "========== updateOrderStatus method completed ==========") } - fun confirmPayment(orderId: Int, status: String) { - Log.d(TAG, "Confirming order completed: orderId=$orderId, status=$status") + fun confirmShipment(orderId: Int, receiptNum: String) { + _isLoading.value = true viewModelScope.launch { - _confirmPaymentStore.value = Result.Loading - val request = PaymentConfirmRequest(orderId, status) - - Log.d(TAG, "Sending order completion request: $request") - val result = repository.confirmPaymentStore(request) - Log.d(TAG, "Order completion result: $result") - _confirmPaymentStore.value = result + try { + val response = repository.confirmShipment(orderId, receiptNum) + if (response.isSuccessful) { + _message.value = response.body()?.message ?: "Berhasil mengonfirmasi pengiriman" + _isSuccess.value = true + } else { + val errorMsg = response.errorBody()?.string() ?: "Gagal konfirmasi pengiriman" + _error.value = errorMsg + _isSuccess.value = false + } + } catch (e: Exception) { + _error.value = "Terjadi kesalahan: ${e.message}" + _isSuccess.value = false + } finally { + _isLoading.value = false + } } } diff --git a/app/src/main/res/layout/activity_detail_shipment.xml b/app/src/main/res/layout/activity_detail_shipment.xml index 25f8710..c05337d 100644 --- a/app/src/main/res/layout/activity_detail_shipment.xml +++ b/app/src/main/res/layout/activity_detail_shipment.xml @@ -31,7 +31,7 @@ @@ -278,7 +278,7 @@ @@ -409,7 +409,7 @@ android:gravity="bottom">