fix sell order and confirm payment in detailpayment

This commit is contained in:
shaulascr
2025-05-30 05:19:11 +07:00
parent e51e753a04
commit 0d2edb7ea2
20 changed files with 900 additions and 1180 deletions

View File

@ -0,0 +1,12 @@
package com.alya.ecommerce_serang.data.api.dto
import com.google.gson.annotations.SerializedName
data class PaymentConfirmRequest (
@SerializedName("order_id")
val orderId : Int,
@SerializedName("status")
val status: String
)

View File

@ -77,7 +77,7 @@ data class OrdersItem(
val cancelDate: String? = null,
@field:SerializedName("payment_evidence")
val paymentEvidence: Any? = null,
val paymentEvidence: String,
@field:SerializedName("longitude")
val longitude: String? = null,
@ -152,7 +152,7 @@ data class OrdersItem(
val postalCode: String? = null,
@field:SerializedName("order_id")
val orderId: Int? = null,
val orderId: Int,
@field:SerializedName("username")
val username: String? = null,

View File

@ -5,5 +5,5 @@ import com.google.gson.annotations.SerializedName
data class PaymentConfirmationResponse(
@field:SerializedName("message")
val message: String? = null
val message: String
)

View File

@ -14,6 +14,7 @@ import com.alya.ecommerce_serang.data.api.dto.LoginRequest
import com.alya.ecommerce_serang.data.api.dto.OrderRequest
import com.alya.ecommerce_serang.data.api.dto.OrderRequestBuy
import com.alya.ecommerce_serang.data.api.dto.OtpRequest
import com.alya.ecommerce_serang.data.api.dto.PaymentConfirmRequest
import com.alya.ecommerce_serang.data.api.dto.ProvinceResponse
import com.alya.ecommerce_serang.data.api.dto.RegisterRequest
import com.alya.ecommerce_serang.data.api.dto.ReviewProductItem
@ -65,6 +66,7 @@ import com.alya.ecommerce_serang.data.api.response.order.ComplaintResponse
import com.alya.ecommerce_serang.data.api.response.order.CompletedOrderResponse
import com.alya.ecommerce_serang.data.api.response.product.CreateSearchResponse
import com.alya.ecommerce_serang.data.api.response.product.SearchHistoryResponse
import com.alya.ecommerce_serang.data.api.response.store.orders.PaymentConfirmationResponse
import com.alya.ecommerce_serang.data.api.response.store.product.CreateProductResponse
import com.alya.ecommerce_serang.data.api.response.store.product.DeleteProductResponse
import com.alya.ecommerce_serang.data.api.response.store.product.UpdateProductResponse
@ -366,6 +368,11 @@ interface ApiService {
@Part("bank_num") bankNum: RequestBody
): Response<BalanceTopUpResponse>
@PUT("store/payment/update")
suspend fun paymentConfirmation(
@Body confirmPaymentReq : PaymentConfirmRequest
): Response<PaymentConfirmationResponse>
@Multipart
@PUT("mystore/edit")
suspend fun updateStoreProfileMultipart(

View File

@ -1,7 +1,9 @@
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.orders.OrderListResponse
import com.alya.ecommerce_serang.data.api.response.store.orders.PaymentConfirmationResponse
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
class SellsRepository(private val apiService: ApiService) {
@ -42,4 +44,28 @@ class SellsRepository(private val apiService: ApiService) {
Log.e("SellsRepository", "Exception updating order status", e)
}
}
suspend fun confirmPaymentStore(request: PaymentConfirmRequest): Result<PaymentConfirmationResponse> {
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)
}
}
}

View File

@ -63,7 +63,7 @@ class HistoryActivity : AppCompatActivity() {
supportActionBar?.setDisplayShowTitleEnabled(false)
binding.btnBack.setOnClickListener {
onBackPressed()
// onBackPressed()
finish()
}
}

View File

@ -6,10 +6,10 @@ import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.BuildConfig.BASE_URL
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderItemsItem
import com.bumptech.glide.Glide
import com.google.android.material.button.MaterialButton
class OrderProductAdapter : RecyclerView.Adapter<OrderProductAdapter.ProductViewHolder>() {
@ -48,9 +48,15 @@ class OrderProductAdapter : RecyclerView.Adapter<OrderProductAdapter.ProductView
// Set price with currency format
tvProductPrice.text = formatCurrency(product.price)
val fullImageUrl = when (val img = product.productImage) {
is String -> {
if (img.startsWith("/")) BASE_URL + img.substring(1) else img
}
else -> R.drawable.placeholder_image // Default image for null
}
// Load product image using Glide
Glide.with(itemView.context)
.load(product.productImage)
.load(fullImageUrl)
.placeholder(R.drawable.placeholder_image)
// .error(R.drawable.error_image)
.into(ivProductImage)

View File

@ -1,8 +1,13 @@
package com.alya.ecommerce_serang.ui.profile.mystore.sells
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.commit
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
@ -31,12 +36,28 @@ class SellsActivity : AppCompatActivity() {
sessionManager = SessionManager(this)
WindowCompat.setDecorFitsSystemWindows(window, false)
enableEdgeToEdge()
// Apply insets to your root layout
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
val systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(
systemBars.left,
systemBars.top,
systemBars.right,
systemBars.bottom
)
windowInsets
}
Log.d("SellsActivity", "SellsActivity started")
setupHeader()
if (savedInstanceState == null) {
supportFragmentManager.commit {
replace(R.id.fragment_container_sells, SellsFragment())
}
showSellsFragment()
}
}
@ -44,7 +65,14 @@ class SellsActivity : AppCompatActivity() {
binding.header.headerTitle.text = "Penjualan Saya"
binding.header.headerLeftIcon.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
onBackPressed()
finish()
}
}
private fun showSellsFragment() {
supportFragmentManager.commit {
replace(R.id.fragment_container_sells, SellsFragment())
}
}
}

View File

@ -5,16 +5,15 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.response.store.orders.OrdersItem
import com.alya.ecommerce_serang.ui.profile.mystore.sells.payment.DetailPaymentActivity
import com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment.DetailShipmentActivity
import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel
import com.bumptech.glide.Glide
import com.google.android.material.button.MaterialButton
import com.google.gson.Gson
import java.text.SimpleDateFormat
import java.util.Calendar
@ -34,235 +33,310 @@ class SellsAdapter(
}
fun submitList(newSells: List<OrdersItem>) {
Log.d("SellsAdapter", "submitList called with ${newSells.size} items")
sells.clear()
sells.addAll(newSells)
notifyDataSetChanged()
Log.d("SellsAdapter", "Adapter updated. Current size: ${sells.size}")
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SellsViewHolder {
Log.d("SellsAdapter", "onCreateViewHolder called")
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_sells, parent, false)
Log.d("SellsAdapter", "View inflated successfully")
return SellsViewHolder(view)
}
override fun onBindViewHolder(holder: SellsViewHolder, position: Int) {
Log.d("SellsAdapter", "onBindViewHolder called for position: $position")
Log.d("SellsAdapter", "Total items in adapter: ${sells.size}")
if (position < sells.size) {
holder.bind(sells[position])
} else {
Log.e("SellsAdapter", "Position $position is out of bounds for size ${sells.size}")
}
}
override fun getItemCount(): Int = sells.size
inner class SellsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val layoutOrders: View = itemView.findViewById(R.id.layout_orders)
private val layoutPayments: View = itemView.findViewById(R.id.layout_payments)
private val layoutShipments: View = itemView.findViewById(R.id.layout_shipments)
private val tvStoreName: TextView = itemView.findViewById(R.id.tvUserName)
private val rvOrderItems: RecyclerView = itemView.findViewById(R.id.rvSellsItems)
private val tvShowMore: TextView = itemView.findViewById(R.id.tvShowMores)
private val tvTotalAmount: TextView = itemView.findViewById(R.id.tvTotalAmounts)
private val tvItemCountLabel: TextView = itemView.findViewById(R.id.tv_count_total_items)
private var tvSellsTitle: TextView = itemView.findViewById(R.id.tv_payment_title)
private var tvSellsNumber: TextView = itemView.findViewById(R.id.tv_payment_number)
private var tvSellsDueDesc: TextView = itemView.findViewById(R.id.tv_payment_due_desc)
private var tvSellsDue: TextView = itemView.findViewById(R.id.tv_payment_due)
private var tvSellsLocation: TextView = itemView.findViewById(R.id.tv_payment_location)
private var tvSellsCustomer: TextView = itemView.findViewById(R.id.tv_payment_customer)
private var ivSellsProduct: ImageView = itemView.findViewById(R.id.iv_payment_product)
private var tvSellsProductName: TextView = itemView.findViewById(R.id.tv_payment_product_name)
private var tvSellsProductQty: TextView = itemView.findViewById(R.id.tv_payment_product_qty)
private var tvSellsProductPrice: TextView = itemView.findViewById(R.id.tv_payment_product_price)
private var tvSeeMore: TextView = itemView.findViewById(R.id.tv_see_more_payment)
private var tvSellsQty: TextView = itemView.findViewById(R.id.tv_payment_qty)
private var tvSellsPrice: TextView = itemView.findViewById(R.id.tv_payment_price)
private val btnConfirmPayment: Button = itemView.findViewById(R.id.btn_confirm_payment)
private val btnConfirmShipment: Button = itemView.findViewById(R.id.btn_confirm_shipment)
fun bind(order: OrdersItem) {
Log.d("SellsAdapter", "=== ViewHolder.bind() called ===")
Log.d("SellsAdapter", "Binding order: ${order.orderId} with status: ${order.status}")
fun bind(sells: OrdersItem) {
// Show customer/buyer name (seller's perspective)
tvStoreName.text = order.username ?: "Unknown Customer"
Log.d("SellsAdapter", "Customer name set: ${order.username}")
tvSellsNumber.text = "No. Pesanan: ${sells.orderId}"
tvSellsLocation.text = sells.subdistrict
tvSellsCustomer.text = sells.username
// Set total amount
tvTotalAmount.text = "Rp${order.totalAmount}"
Log.d("SellsAdapter", "Total amount set: ${order.totalAmount}")
val product = sells.orderItems?.get(0)
product?.let {
tvSellsProductName.text = it.productName
tvSellsProductQty.text = "x${it.quantity}"
tvSellsProductPrice.text = "Rp${it.price}"
// Set item count
val itemCount = order.orderItems?.size ?: 0
tvItemCountLabel.text = itemView.context.getString(R.string.item_count_prod, itemCount)
Log.d("SellsAdapter", "Item count set: $itemCount")
Glide.with(itemView.context)
.load(it.productImage)
.placeholder(R.drawable.placeholder_image)
.into(ivSellsProduct)
// Set up the order items RecyclerView
val productAdapter = SellsProductAdapter()
rvOrderItems.apply {
layoutManager = LinearLayoutManager(itemView.context)
adapter = productAdapter
}
Log.d("SellsAdapter", "Product RecyclerView configured")
sells.orderItems?.size?.let {
if (it > 1) {
tvSeeMore.visibility = View.VISIBLE
tvSeeMore.text = "Lihat ${it.minus(1)} produk lainnya"
// Display only the first product and show "View more" for the rest
order.orderItems?.let { items ->
if (items.isNotEmpty()) {
productAdapter.submitList(items.take(1))
Log.d("SellsAdapter", "Product list submitted: ${items.size} items")
// Show or hide the "View more" text based on number of items
if (items.size > 1) {
val itemString = items.size - 1
tvShowMore.visibility = View.VISIBLE
tvShowMore.text = itemView.context.getString(R.string.show_more_product, itemString)
Log.d("SellsAdapter", "Show more visible: $itemString more items")
} else {
tvSeeMore.visibility = View.GONE
tvShowMore.visibility = View.GONE
Log.d("SellsAdapter", "Show more hidden: only 1 item")
}
} else {
tvShowMore.visibility = View.GONE
Log.w("SellsAdapter", "Order has no items!")
}
} ?: run {
tvShowMore.visibility = View.GONE
Log.w("SellsAdapter", "Order items is null!")
}
tvSellsQty.text = "${sells.orderItems?.size} produk"
tvSellsPrice.text = "Rp${sells.totalAmount}"
//
// itemView.setOnClickListener {
// onOrderClickListener(sells)
// }
adjustDisplay(fragmentStatus, sells)
// Set click listener for the entire order item
itemView.setOnClickListener {
onOrderClickListener(order)
}
private fun adjustDisplay(status: String, sells: OrdersItem) {
Log.d("SellsAdapter", "Adjusting display for status: $status")
val actualStatus = if (fragmentStatus == "all") order.status ?: "" else fragmentStatus
Log.d("SellsAdapter", "Adjusting UI for status: '$actualStatus' (fragmentStatus: '$fragmentStatus')")
adjustButtonsAndText(actualStatus, order)
Log.d("SellsAdapter", "=== ViewHolder.bind() completed ===")
}
private fun adjustButtonsAndText(status: String, order: OrdersItem) {
Log.d("SellsAdapter", "Adjusting buttons for status: $status")
// Get references to buttons and status views
val btnLeft = itemView.findViewById<MaterialButton>(R.id.btn_left)
val btnRight = itemView.findViewById<MaterialButton>(R.id.btn_right)
val statusOrder = itemView.findViewById<TextView>(R.id.tvOrderStatus)
val deadlineLabel = itemView.findViewById<TextView>(R.id.tvDeadlineLabel)
val deadlineDate = itemView.findViewById<TextView>(R.id.tvDeadlineDate)
// Reset visibility
btnLeft.visibility = View.GONE
btnRight.visibility = View.GONE
statusOrder.visibility = View.GONE
deadlineLabel.visibility = View.GONE
deadlineDate.visibility = View.GONE
when (status) {
"pending", "unpaid" -> {
layoutOrders.visibility = View.VISIBLE
layoutPayments.visibility = View.GONE
layoutShipments.visibility = View.GONE
tvSellsTitle = itemView.findViewById(R.id.tv_order_title)
tvSellsNumber = itemView.findViewById(R.id.tv_order_number)
tvSellsDue = itemView.findViewById(R.id.tv_order_due)
tvSellsCustomer = itemView.findViewById(R.id.tv_order_customer)
tvSellsProductName = itemView.findViewById(R.id.tv_order_product_name)
tvSellsProductQty = itemView.findViewById(R.id.tv_order_product_qty)
tvSellsProductPrice = itemView.findViewById(R.id.tv_order_product_price)
tvSeeMore = itemView.findViewById(R.id.tv_see_more_order)
tvSellsQty = itemView.findViewById(R.id.tv_order_qty)
tvSellsPrice = itemView.findViewById(R.id.tv_order_price)
tvSellsDue.text = formatDueDate(sells.updatedAt.toString(), 1)
val product = sells.orderItems?.get(0)
product?.let {
tvSellsProductName.text = it.productName
tvSellsProductQty.text = "x${it.quantity}"
tvSellsProductPrice.text = "Rp${it.price}"
Glide.with(itemView.context)
.load(it.productImage)
.placeholder(R.drawable.placeholder_image)
.into(ivSellsProduct)
"pending" -> {
statusOrder.apply {
visibility = View.VISIBLE
text = "Menunggu Tagihan"
}
tvSellsQty.text = "${sells.orderItems?.size} produk"
tvSellsPrice.text = "Rp${sells.totalAmount}"
deadlineLabel.apply {
visibility = View.VISIBLE
text = "Batas waktu konfirmasi:"
}
"paid" -> {
layoutOrders.visibility = View.GONE
layoutPayments.visibility = View.VISIBLE
layoutShipments.visibility = View.GONE
tvSellsDue.text = formatDueDate(sells.updatedAt.toString(), 2)
btnConfirmPayment.setOnClickListener {
val context = itemView.context
val intent = Intent(context, DetailPaymentActivity::class.java)
intent.putExtra("sells_data", Gson().toJson(sells))
context.startActivity(intent)
deadlineDate.apply {
visibility = View.VISIBLE
text = formatDate(order.createdAt ?: "")
}
btnLeft.apply {
visibility = View.VISIBLE
text = "Tolak Pesanan"
setOnClickListener {
// Handle reject order
viewModel.updateOrderStatus(order.orderId, "canceled")
viewModel.refreshOrders()
}
tvSellsTitle.text = "Pesanan Telah Dibayar"
tvSellsDueDesc.text = "Konfirmasi pembayaran sebelum:"
tvSellsDue.text = formatDueDate(sells.updatedAt.toString(), 2)
}
"processed" -> {
layoutOrders.visibility = View.GONE
layoutPayments.visibility = View.GONE
layoutShipments.visibility = View.VISIBLE
tvSellsTitle = itemView.findViewById(R.id.tv_shipment_title)
tvSellsNumber = itemView.findViewById(R.id.tv_shipment_number)
tvSellsDue = itemView.findViewById(R.id.tv_shipment_due)
tvSellsLocation = itemView.findViewById(R.id.tv_shipment_location)
tvSellsCustomer = itemView.findViewById(R.id.tv_shipment_customer)
tvSellsProductName = itemView.findViewById(R.id.tv_shipment_product_name)
tvSellsProductQty = itemView.findViewById(R.id.tv_shipment_product_qty)
tvSeeMore = itemView.findViewById(R.id.tv_see_more_shipment)
tvSellsDue.text = formatDueDate(sells.updatedAt.toString(), 2)
btnConfirmShipment.setOnClickListener {
btnRight.apply {
visibility = View.VISIBLE
text = "Terima Pesanan"
setOnClickListener {
// Handle accept order
viewModel.updateOrderStatus(order.orderId, "unpaid")
viewModel.refreshOrders()
}
}
}
"unpaid" -> {
statusOrder.apply {
visibility = View.VISIBLE
text = "Konfirmasi Bayar"
}
deadlineLabel.apply {
visibility = View.VISIBLE
text = "Batas pembayaran:"
}
deadlineDate.apply {
visibility = View.VISIBLE
text = formatDatePay(order.updatedAt ?: "")
}
btnLeft.apply {
visibility = View.VISIBLE
text = "Batalkan"
setOnClickListener {
viewModel.updateOrderStatus(order.orderId, "canceled")
viewModel.refreshOrders()
}
}
}
"paid" -> {
statusOrder.apply {
visibility = View.VISIBLE
text = "Sudah Dibayar"
}
deadlineLabel.apply {
visibility = View.VISIBLE
text = "Konfirmasi pembayaran sebelum:"
}
deadlineDate.apply {
visibility = View.VISIBLE
text = formatDatePay(order.updatedAt ?: "")
}
btnRight.apply {
visibility = View.VISIBLE
text = "Konfirmasi Pembayaran"
setOnClickListener {
val context = itemView.context
val intent = Intent(context, DetailShipmentActivity::class.java)
intent.putExtra("sells_data", Gson().toJson(sells))
val intent = Intent(context, DetailPaymentActivity::class.java)
intent.putExtra("sells_data", Gson().toJson(order))
context.startActivity(intent)
}
tvSellsTitle.text = "Pesanan Perlu Dikirim"
tvSellsNumber.text = "No. Pesanan: ${sells.orderId}"
tvSellsLocation.text = sells.subdistrict
tvSellsCustomer.text = sells.username
tvSellsDue.text = formatDueDate(sells.updatedAt.toString(), 2)
}
}
"processed" -> {
statusOrder.apply {
visibility = View.VISIBLE
text = "Diproses"
}
deadlineLabel.apply {
visibility = View.VISIBLE
text = "Kirim sebelum:"
}
deadlineDate.apply {
visibility = View.VISIBLE
text = formatDatePay(order.updatedAt ?: "")
}
btnRight.apply {
visibility = View.VISIBLE
text = "Kirim Pesanan"
setOnClickListener {
val context = itemView.context
val intent = Intent(context, DetailShipmentActivity::class.java)
intent.putExtra("sells_data", Gson().toJson(order))
context.startActivity(intent)
}
}
}
"shipped" -> {
layoutOrders.visibility = View.GONE
layoutPayments.visibility = View.VISIBLE
layoutShipments.visibility = View.GONE
tvSellsTitle.text = "Pesanan Telah Dikirim"
tvSellsDueDesc.text = "Dikirimkan pada"
tvSellsDue.text = formatDueDate(sells.updatedAt.toString(), 0)
tvSellsDue.background = itemView.context.getDrawable(R.drawable.bg_product_inactive)
btnConfirmPayment.visibility = View.GONE
statusOrder.apply {
visibility = View.VISIBLE
text = "Dikirim"
}
deadlineLabel.apply {
visibility = View.VISIBLE
text = "Dikirimkan pada:"
}
deadlineDate.apply {
visibility = View.VISIBLE
text = formatDate(order.updatedAt ?: "")
}
"delivered" -> {
layoutOrders.visibility = View.GONE
layoutPayments.visibility = View.VISIBLE
layoutShipments.visibility = View.GONE
tvSellsTitle.text = "Pesanan Telah Dikirim"
tvSellsDueDesc.text = "Dikirimkan pada"
tvSellsDue.text = formatDueDate(sells.updatedAt.toString(), 0)
tvSellsDue.background = itemView.context.getDrawable(R.drawable.bg_product_inactive)
btnConfirmPayment.visibility = View.GONE
}
"completed" -> {
layoutOrders.visibility = View.GONE
layoutPayments.visibility = View.VISIBLE
layoutShipments.visibility = View.GONE
tvSellsTitle.text = "Pesanan Selesai"
tvSellsDueDesc.text = "Selesai pada"
tvSellsDue.text = formatDueDate(sells.updatedAt.toString(), 0)
tvSellsDue.background = itemView.context.getDrawable(R.drawable.bg_product_inactive)
btnConfirmPayment.visibility = View.GONE
statusOrder.apply {
visibility = View.VISIBLE
text = "Selesai"
}
deadlineLabel.apply {
visibility = View.VISIBLE
text = "Selesai pada:"
}
deadlineDate.apply {
visibility = View.VISIBLE
text = formatDate(order.updatedAt ?: "")
}
}
"canceled" -> {
layoutOrders.visibility = View.GONE
layoutPayments.visibility = View.VISIBLE
layoutShipments.visibility = View.GONE
tvSellsTitle.text = "Pesanan Dibatalkan"
tvSellsDueDesc.text = "Dibatalkan pada"
tvSellsDue.text = formatDueDate(sells.updatedAt.toString(), 0)
tvSellsDue.background = itemView.context.getDrawable(R.drawable.bg_product_inactive)
btnConfirmPayment.visibility = View.GONE
statusOrder.apply {
visibility = View.VISIBLE
text = "Dibatalkan"
}
deadlineLabel.apply {
visibility = View.VISIBLE
text = "Dibatalkan pada:"
}
deadlineDate.apply {
visibility = View.VISIBLE
text = formatDate(order.cancelDate ?: "")
}
}
}
}
private fun formatDueDate(date: String, dueDay: Int): String {
private fun formatDate(dateString: String): String {
return try {
val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
inputFormat.timeZone = TimeZone.getTimeZone("UTC")
val outputFormat = SimpleDateFormat("dd MM; HH.mm", Locale("id", "ID"))
val outputFormat = SimpleDateFormat("HH:mm dd MMMM yyyy", Locale("id", "ID"))
val date = inputFormat.parse(date)
val date = inputFormat.parse(dateString)
date?.let {
val calendar = Calendar.getInstance()
calendar.time = it
calendar.add(Calendar.DATE, dueDay)
calendar.set(Calendar.HOUR_OF_DAY, 23)
calendar.set(Calendar.MINUTE, 59)
outputFormat.format(calendar.time)
} ?: date
} ?: dateString
} catch (e: Exception) {
Log.e("DueDateFormatting", "Error formatting date: ${e.message}")
date
}.toString()
Log.e("DateFormatting", "Error formatting date: ${e.message}")
dateString
}
}
private fun formatDatePay(dateString: String): String {
return try {
// Parse the ISO 8601 date
val isoDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
isoDateFormat.timeZone = TimeZone.getTimeZone("UTC")
val createdDate = isoDateFormat.parse(dateString)
// Add 24 hours to get due date
val calendar = Calendar.getInstance()
calendar.time = createdDate
calendar.add(Calendar.HOUR, 24)
// Format due date for display
val dueDateFormat = SimpleDateFormat("dd MMM yyyy", Locale.getDefault())
dueDateFormat.format(calendar.time)
} catch (e: Exception) {
Log.e("DateFormatting", "Error formatting date: ${e.message}")
dateString
}
}
}
}

View File

@ -1,12 +1,10 @@
package com.alya.ecommerce_serang.ui.profile.mystore.sells
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.viewpager2.widget.ViewPager2
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.databinding.FragmentSellsBinding
import com.alya.ecommerce_serang.utils.SessionManager
@ -21,9 +19,10 @@ class SellsFragment : Fragment() {
private lateinit var viewPagerAdapter: SellsViewPagerAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
): View {
_binding = FragmentSellsBinding.inflate(inflater, container, false)
return binding.root
}
@ -36,58 +35,28 @@ class SellsFragment : Fragment() {
}
private fun setupViewPager() {
// Initialize the ViewPager adapter
viewPagerAdapter = SellsViewPagerAdapter(requireActivity())
binding.viewPagerSells.adapter = viewPagerAdapter
TabLayoutMediator(binding.tabLayoutSells, binding.viewPagerSells) {tab, position ->
tab.text = when(position){
0 -> getString(R.string.all_orders)
1 -> getString(R.string.pending_orders)
2 -> getString(R.string.unpaid_orders)
3 -> getString(R.string.processed_orders)
4 -> getString(R.string.paid_orders)
5 -> getString(R.string.shipped_orders)
6 -> getString(R.string.completed_orders)
7 -> getString(R.string.canceled_orders)
// Connect TabLayout with ViewPager2
TabLayoutMediator(binding.tabLayoutSells, binding.viewPagerSells) { tab, position ->
tab.text = when (position) {
0 -> getString(R.string.all_orders) // "Semua Pesanan"
1 -> getString(R.string.pending_orders) // "Menunggu Tagihan"
2 -> getString(R.string.unpaid_orders) // "Konfirmasi Bayar"
3 -> getString(R.string.paid_orders) // "Diproses"
4 -> getString(R.string.processed_orders) // "Sudah Dibayar"
5 -> getString(R.string.shipped_orders) // "Dikirim"
6 -> getString(R.string.completed_orders) // "Selesai"
7 -> getString(R.string.canceled_orders) // "Dibatalkan"
else -> "Tab $position"
}
}.attach()
binding.viewPagerSells.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
val statusList = listOf("all", "pending", "unpaid", "processed", "paid", "shipped", "completed", "canceled")
val selectedStatus = statusList.getOrNull(position) ?: "unknown"
val tabText = when(position) {
0 -> getString(R.string.all_orders)
1 -> getString(R.string.pending_orders)
2 -> getString(R.string.unpaid_orders)
3 -> getString(R.string.processed_orders)
4 -> getString(R.string.paid_orders)
5 -> getString(R.string.shipped_orders)
6 -> getString(R.string.completed_orders)
7 -> getString(R.string.canceled_orders)
else -> "Tab $position"
}
Log.d(TAG, "🔄 *** TAB SWITCHED ***")
Log.d(TAG, "Selected position: $position")
Log.d(TAG, "Tab text: '$tabText'")
Log.d(TAG, "Status for this tab: '$selectedStatus'")
Log.d(TAG, "*** This should trigger SellsListFragment for '$selectedStatus' ***")
}
})
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
companion object {
private const val TAG = "SellsListFragment"
}
}

View File

@ -11,6 +11,7 @@ import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.alya.ecommerce_serang.data.api.response.store.orders.OrdersItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.repository.Result
import com.alya.ecommerce_serang.data.repository.SellsRepository
import com.alya.ecommerce_serang.databinding.FragmentSellsListBinding
import com.alya.ecommerce_serang.ui.order.address.ViewState
@ -31,39 +32,45 @@ class SellsListFragment : Fragment() {
SellsViewModel(sellsRepository)
}
}
private lateinit var sellsAdapter: SellsAdapter
private var status: String = "all"
companion object {
private const val TAG = "SellsListFragment"
private const val ARG_STATUS = "status"
fun newInstance(status: String): SellsListFragment {
Log.d(TAG, "=== Creating new instance ===")
Log.d(TAG, "Status: '$status'")
Log.d(TAG, "Creating new instance with status: '$status'")
return SellsListFragment().apply {
arguments = Bundle().apply {
putString(ARG_STATUS, status)
}
Log.d(TAG, "Fragment instance created with status: '$status'")
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate called")
sessionManager = SessionManager(requireContext())
arguments?.let {
status = it.getString(ARG_STATUS) ?: "all"
}
Log.d(TAG, "Fragment status set to: '$status'")
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
): View {
Log.d(TAG, "onCreateView called")
_binding = FragmentSellsListBinding.inflate(inflater, container, false)
return binding.root
}
@ -73,90 +80,104 @@ class SellsListFragment : Fragment() {
setupRecyclerView()
observeSellsList()
observePaymentConfirmation()
loadSells()
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun setupRecyclerView() {
Log.d(TAG, "Setting up RecyclerView")
sellsAdapter = SellsAdapter(
onOrderClickListener = { sells ->
Log.d(TAG, "Order clicked: ${sells.orderId} in status '$status'")
navigateToSellsDetail(sells)
onOrderClickListener = { order ->
Log.d(TAG, "Order clicked: ${order.orderId}")
navigateToSellsDetail(order)
},
viewModel = viewModel
)
Log.d(TAG, "Setting adapter fragment status to: '$status'")
sellsAdapter.setFragmentStatus(status)
Log.d(TAG, "Adapter fragment status set to: '$status'")
binding.rvSells.apply {
layoutManager = LinearLayoutManager(requireContext())
adapter = sellsAdapter
Log.d(TAG, "RecyclerView configured with LinearLayoutManager and adapter")
}
// Log RecyclerView visibility and properties
Log.d(TAG, "RecyclerView visibility: ${binding.rvSells.visibility}")
Log.d(TAG, "RecyclerView parent: ${binding.rvSells.parent}")
Log.d(TAG, "RecyclerView configured")
}
private fun observeSellsList() {
Log.d(TAG, "Setting up sells list observer")
viewModel.sells.observe(viewLifecycleOwner) { result ->
Log.d(TAG, "Sells list observer triggered with result: ${result.javaClass.simpleName}")
when (result) {
is ViewState.Success -> {
binding.progressBar.visibility = View.GONE
Log.d(TAG, "Data received: ${result.data?.size ?: 0} items")
if (result.data.isNullOrEmpty()) {
binding.tvEmptyState.visibility = View.VISIBLE
binding.rvSells.visibility = View.GONE
Log.d(TAG, "Showing empty state")
} else {
Log.d(TAG, "✅ Data is available: ${result.data.size} items")
binding.tvEmptyState.visibility = View.GONE
binding.rvSells.visibility = View.VISIBLE
result.data.forEachIndexed { index, order ->
Log.d(TAG, "Order $index:")
Log.d(TAG, " - ID: ${order.orderId}")
Log.d(TAG, " - Status: ${order.status}")
Log.d(TAG, " - Customer: ${order.username}")
Log.d(TAG, " - Total: ${order.totalAmount}")
Log.d(TAG, " - Items: ${order.orderItems?.size ?: 0}")
// Log first few items for debugging
result.data.take(3).forEachIndexed { index, order ->
Log.d(TAG, "Order ${index + 1}: ID=${order.orderId}, Status=${order.status}, Customer=${order.username}")
}
sellsAdapter.submitList(result.data)
Log.d(TAG, "Final UI state:")
Log.d(TAG, " - ProgressBar visibility: ${binding.progressBar.visibility}")
Log.d(TAG, " - EmptyState visibility: ${binding.tvEmptyState.visibility}")
Log.d(TAG, " - RecyclerView visibility: ${binding.rvSells.visibility}")
Log.d(TAG, " - Adapter item count: ${sellsAdapter.itemCount}")
}
sellsAdapter.submitList(result.data)
Log.d(TAG, "Data submitted to adapter")
Log.d(TAG, "Adapter item count: ${sellsAdapter.itemCount}") }
}
is ViewState.Error -> {
Log.e(TAG, "❌ ViewState.Error received: ${result.message}")
binding.progressBar.visibility = View.GONE
binding.tvEmptyState.visibility = View.VISIBLE
Toast.makeText(requireContext(), result.message, Toast.LENGTH_SHORT).show()
}
is ViewState.Loading -> {
binding.progressBar.visibility = View.VISIBLE
binding.rvSells.visibility = View.GONE
binding.tvEmptyState.visibility = View.GONE
}
}
}
}
private fun observePaymentConfirmation() {
viewModel.confirmPaymentStore.observe(viewLifecycleOwner) { result ->
when (result) {
is Result.Loading -> {
// Handle loading state if needed
}
is Result.Success -> {
Toast.makeText(requireContext(), "Payment confirmed successfully!", Toast.LENGTH_SHORT).show()
loadSells()
}
is Result.Error -> {
Toast.makeText(requireContext(), "Failed to payment confirm order: ${result.exception.message}", Toast.LENGTH_SHORT).show()
}
}
}
}
private fun loadSells() {
Log.d(TAG, "Calling viewModel.getSellList('$status')")
Log.d(TAG, "Loading sells with status: '$status'")
viewModel.getSellList(status)
Log.d(TAG, "getSellList called")
}
private fun navigateToSellsDetail(sells: OrdersItem) {
// In a real app, you would navigate to sells detail screen
// For example: findNavController().navigate(SellsListFragmentDirections.actionToSellsDetail(sells.orderId))
Toast.makeText(requireContext(), "Order ID: ${sells.orderId}", Toast.LENGTH_SHORT).show()
private fun navigateToSellsDetail(order: OrdersItem) {
Log.d(TAG, "Navigating to sells detail for order: ${order.orderId}")
// Navigate to order detail from seller's perspective
// Seller views customer's order details to manage fulfillment
Toast.makeText(requireContext(), "Customer Order ID: ${order.orderId}", Toast.LENGTH_SHORT).show()
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -10,9 +10,15 @@ import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.response.store.orders.OrderItemsItem
import com.bumptech.glide.Glide
class SellsProductAdapter(
private val items: List<OrderItemsItem?>
) : RecyclerView.Adapter<SellsProductAdapter.ProductViewHolder>() {
class SellsProductAdapter : RecyclerView.Adapter<SellsProductAdapter.ProductViewHolder>() {
private val items = mutableListOf<OrderItemsItem?>()
fun submitList(newItems: List<OrderItemsItem?>) {
items.clear()
items.addAll(newItems)
notifyDataSetChanged()
}
inner class ProductViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val ivProduct: ImageView = view.findViewById(R.id.iv_order_product)

View File

@ -1,14 +1,14 @@
package com.alya.ecommerce_serang.ui.profile.mystore.sells
import android.util.Log
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import io.ktor.client.utils.EmptyContent.status
class SellsViewPagerAdapter(fragmentActivity: FragmentActivity)
: FragmentStateAdapter(fragmentActivity) {
class SellsViewPagerAdapter(
fragmentActivity: FragmentActivity
) : FragmentStateAdapter(fragmentActivity) {
// Define all possible sells statuses - keeping your original list
private val sellsStatuses = listOf(
"all", // Position 0: "Semua Pesanan"
"pending", // Position 1: "Menunggu Tagihan"
@ -20,34 +20,10 @@ class SellsViewPagerAdapter(fragmentActivity: FragmentActivity)
"canceled" // Position 7: "Dibatalkan"
)
init {
Log.d(TAG, "=== ViewPager Status Mapping ===")
sellsStatuses.forEachIndexed { index, status ->
val tabText = when(index) {
0 -> "Semua Pesanan"
1 -> "Menunggu Tagihan"
2 -> "Konfirmasi Bayar"
3 -> "Diproses"
4 -> "Sudah Dibayar"
5 -> "Dikirim"
6 -> "Selesai"
7 -> "Dibatalkan"
else -> "Tab $index"
}
Log.d(TAG, "Position $index: '$tabText' → Status: '$status'")
}
Log.d(TAG, "=== End Mapping ===")
}
override fun getItemCount(): Int = sellsStatuses.size
override fun createFragment(position: Int): Fragment {
Log.d(TAG, "Creating fragment for position $position with status: '$status'")
// Create a new instance of SellsListFragment with the appropriate status
return SellsListFragment.newInstance(sellsStatuses[position])
}
companion object {
private const val TAG = "SellsViewPagerAdapter"
}
}

View File

@ -1,11 +1,34 @@
package com.alya.ecommerce_serang.ui.profile.mystore.sells.payment
import android.app.Dialog
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.ProgressBar
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.orders.OrdersItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
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.utils.BaseViewModelFactory
import com.alya.ecommerce_serang.utils.SessionManager
import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.target.CustomTarget
import com.google.gson.Gson
import java.text.SimpleDateFormat
import java.util.Locale
@ -15,17 +38,37 @@ class DetailPaymentActivity : AppCompatActivity() {
private lateinit var binding: ActivityDetailPaymentBinding
private lateinit var sells: OrdersItem
private lateinit var productAdapter: SellsProductAdapter
private lateinit var sessionManager: SessionManager
private val viewModel: SellsViewModel by viewModels {
BaseViewModelFactory {
val apiService = ApiConfig.getApiService(sessionManager)
val sellsRepository = SellsRepository(apiService)
SellsViewModel(sellsRepository)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDetailPaymentBinding.inflate(layoutInflater)
setContentView(binding.root)
sessionManager = SessionManager(this)
val orderJson = intent.getStringExtra("sells_data")
sells = Gson().fromJson(orderJson, OrdersItem::class.java)
bindOrderDetails()
binding.header.headerLeftIcon.setOnClickListener {
// onBackPressed()
finish()
}
setupRecyclerView()
bindOrderDetails()
setupPaymentEvidenceViewer()
}
private fun bindOrderDetails() = with(binding) {
@ -42,14 +85,106 @@ class DetailPaymentActivity : AppCompatActivity() {
tvOrderRecipient.text = sells.username
// tvOrderRecipientNum.text = sells.phone
tvOrderRecipientAddress.text = sells.street
// sells.paymentEvidence
binding.btnConfirmPayment.setOnClickListener{
viewModel.confirmPayment(sells.orderId, "confirmed")
finish()
}
}
private fun setupRecyclerView() {
productAdapter = SellsProductAdapter()
binding.rvProductItems.apply {
layoutManager = LinearLayoutManager(this@DetailPaymentActivity)
adapter = SellsProductAdapter(sells.orderItems ?: emptyList())
adapter = productAdapter
}
// Submit the order items to the adapter
productAdapter.submitList(sells.orderItems ?: emptyList())
}
private fun setupPaymentEvidenceViewer() {
binding.tvPaymentDueDesc.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)
dialog.setContentView(R.layout.dialog_image_viewer)
dialog.setCancelable(true)
// Set dialog to fullscreen
val window = dialog.window
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
window?.setBackgroundDrawable(ColorDrawable(Color.BLACK))
// Get views from dialog
val imageView = dialog.findViewById<ImageView>(R.id.iv_payment_evidence)
val btnClose = dialog.findViewById<ImageButton>(R.id.btn_close)
val tvTitle = dialog.findViewById<TextView>(R.id.tv_title)
val progressBar = dialog.findViewById<ProgressBar>(R.id.progress_bar)
// Set title
tvTitle.text = "Bukti Pembayaran"
// 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)
.error(R.drawable.placeholder_image)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(object : CustomTarget<Drawable>() {
override fun onResourceReady(resource: Drawable, transition: com.bumptech.glide.request.transition.Transition<in Drawable>?) {
progressBar.visibility = View.GONE
imageView.setImageDrawable(resource)
}
override fun onLoadCleared(placeholder: Drawable?) {
progressBar.visibility = View.GONE
imageView.setImageDrawable(placeholder)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
progressBar.visibility = View.GONE
imageView.setImageDrawable(errorDrawable)
Toast.makeText(this@DetailPaymentActivity, "Gagal memuat gambar", Toast.LENGTH_SHORT).show()
}
})
// Close button click listener
btnClose.setOnClickListener {
dialog.dismiss()
}
// Click outside to close
imageView.setOnClickListener {
dialog.dismiss()
}
dialog.show()
}
private fun formatDate(dateStr: String?): String {
return try {

View File

@ -15,17 +15,18 @@ class DetailShipmentActivity : AppCompatActivity() {
private lateinit var binding: ActivityDetailShipmentBinding
private lateinit var sells: OrdersItem
private lateinit var productAdapter: SellsProductAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDetailShipmentBinding.inflate(layoutInflater)
setContentView(binding.root)
val orderJson = intent.getStringExtra("order_data")
val orderJson = intent.getStringExtra("sells_data")
sells = Gson().fromJson(orderJson, OrdersItem::class.java)
bindOrderDetails()
setupRecyclerView()
bindOrderDetails()
}
private fun bindOrderDetails() = with(binding) {
@ -45,10 +46,15 @@ class DetailShipmentActivity : AppCompatActivity() {
}
private fun setupRecyclerView() {
productAdapter = SellsProductAdapter()
binding.rvProductItems.apply {
layoutManager = LinearLayoutManager(this@DetailShipmentActivity)
adapter = SellsProductAdapter(sells.orderItems ?: emptyList())
adapter = productAdapter
}
// Submit the order items to the adapter
productAdapter.submitList(sells.orderItems ?: emptyList())
}
private fun formatDate(dateStr: String?): String {

View File

@ -5,7 +5,9 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.dto.PaymentConfirmRequest
import com.alya.ecommerce_serang.data.api.response.store.orders.OrdersItem
import com.alya.ecommerce_serang.data.api.response.store.orders.PaymentConfirmationResponse
import com.alya.ecommerce_serang.data.repository.Result
import com.alya.ecommerce_serang.data.repository.SellsRepository
import com.alya.ecommerce_serang.ui.order.address.ViewState
@ -20,66 +22,159 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() {
private val _sells = MutableLiveData<ViewState<List<OrdersItem>>>()
val sells: LiveData<ViewState<List<OrdersItem>>> = _sells
private val _confirmPaymentStore = MutableLiveData<Result<PaymentConfirmationResponse>>()
val confirmPaymentStore: LiveData<Result<PaymentConfirmationResponse>> = _confirmPaymentStore
fun getSellList(status: String) {
Log.d(TAG, "========== Starting getSellList ==========")
Log.d(TAG, "Requested status: '$status'")
Log.d(TAG, "Repository instance: ${repository.javaClass.simpleName}")
_sells.value = ViewState.Loading
Log.d(TAG, "ViewState set to Loading")
viewModelScope.launch {
_sells.value = ViewState.Loading
Log.d(TAG, "Coroutine launched successfully")
try {
Log.d(TAG, "Calling repository.getSellList(status='$status')")
val startTime = System.currentTimeMillis()
when (val result = repository.getSellList(status)) {
is Result.Success -> {
val endTime = System.currentTimeMillis()
Log.d(TAG, "Repository call completed in ${endTime - startTime}ms")
Log.d(TAG, "Result.Success received from repository")
// Log the entire result data structure
Log.d(TAG, "Raw result data: ${result.data}")
Log.d(TAG, "Result data class: ${result.data?.javaClass?.simpleName}")
val orders = result.data.orders
Log.d(TAG, "Orders list: $orders")
Log.d(TAG, "Extracted orders list: $orders")
Log.d(TAG, "Orders list class: ${orders?.javaClass?.simpleName}")
Log.d(TAG, "Orders count: ${orders?.size ?: 0}")
// Log individual order details
orders?.forEachIndexed { index, order ->
Log.d(TAG, "Order $index:")
Log.d(TAG, " - ID: ${order.orderId}")
Log.d(TAG, " - Status: ${order.status}")
Log.d(TAG, " - Customer: ${order.username}")
Log.d(TAG, " - Total: ${order.totalAmount}")
Log.d(TAG, " - Items count: ${order.orderItems?.size ?: 0}")
Log.d(TAG, " - Updated at: ${order.updatedAt}")
// Check if orders list is null or empty
if (orders == null) {
Log.w(TAG, "⚠️ Orders list is NULL")
} else if (orders.isEmpty()) {
Log.w(TAG, "⚠️ Orders list is EMPTY")
} else {
Log.d(TAG, "✅ Orders list contains ${orders.size} items")
// Log individual order details with more comprehensive info
orders.forEachIndexed { index, order ->
Log.d(TAG, "--- Order ${index + 1}/${orders.size} ---")
Log.d(TAG, " Order object: $order")
Log.d(TAG, " Order class: ${order?.javaClass?.simpleName}")
Log.d(TAG, " - ID: ${order?.orderId}")
Log.d(TAG, " - Status: '${order?.status}'")
Log.d(TAG, " - Customer: '${order?.username}'")
Log.d(TAG, " - Total: ${order?.totalAmount}")
Log.d(TAG, " - Items count: ${order?.orderItems?.size ?: 0}")
Log.d(TAG, " - Created at: ${order?.createdAt}")
Log.d(TAG, " - Updated at: ${order?.updatedAt}")
// Log order items if available
order?.orderItems?.let { items ->
Log.d(TAG, " Order items:")
items.forEachIndexed { itemIndex, item ->
Log.d(TAG, " Item ${itemIndex + 1}: ${item?.productName} (Qty: ${item?.quantity})")
}
_sells.value = ViewState.Success(result.data.orders)
Log.d("SellsViewModel", "Sells loaded successfully: ${result.data.orders?.size} items")
}
}
}
// Set the ViewState to Success
_sells.value = ViewState.Success(orders ?: emptyList())
Log.d(TAG, "✅ ViewState.Success set with ${orders?.size ?: 0} orders")
}
is Result.Error -> {
_sells.value = ViewState.Error(result.exception.message ?: "Unknown error occurred")
Log.e("SellsViewModel", "Error loading sells", result.exception)
val endTime = System.currentTimeMillis()
Log.e(TAG, "Repository call failed in ${endTime - startTime}ms")
Log.e(TAG, "❌ Result.Error received from repository")
Log.e(TAG, "Error message: ${result.exception.message}")
Log.e(TAG, "Exception type: ${result.exception.javaClass.simpleName}")
Log.e(TAG, "Exception stack trace:", result.exception)
val errorMessage = result.exception.message ?: "Unknown error occurred"
_sells.value = ViewState.Error(errorMessage)
Log.d(TAG, "ViewState.Error set with message: '$errorMessage'")
}
is Result.Loading -> {
null
Log.d(TAG, "Result.Loading received from repository (this is unusual)")
// Keep the current loading state
}
}
} catch (e: Exception) {
_sells.value = ViewState.Error("An unexpected error occurred: ${e.message}")
Log.e("SellsViewModel", "Exception in getOrderList", e)
Log.e(TAG, "❌ Exception caught in getSellList")
Log.e(TAG, "Exception type: ${e.javaClass.simpleName}")
Log.e(TAG, "Exception message: ${e.message}")
Log.e(TAG, "Exception stack trace:", e)
val errorMessage = "An unexpected error occurred: ${e.message}"
_sells.value = ViewState.Error(errorMessage)
Log.d(TAG, "ViewState.Error set due to exception: '$errorMessage'")
}
}
Log.d(TAG, "========== getSellList method completed ==========")
}
fun updateOrderStatus(orderId: Int?, status: String) {
Log.d(TAG, "Updating order status: orderId=$orderId, status=$status")
Log.d(TAG, "========== Starting updateOrderStatus ==========")
Log.d(TAG, "Updating order status: orderId=$orderId, status='$status'")
viewModelScope.launch {
try {
Log.d(TAG, "Calling repository.updateOrderStatus")
val startTime = System.currentTimeMillis()
repository.updateOrderStatus(orderId, status)
Log.d(TAG, "Order status updated successfully: orderId=$orderId, status=$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'")
} catch (e: Exception) {
Log.e(TAG, "Error updating order status", e)
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.d(TAG, "========== updateOrderStatus method completed ==========")
}
fun confirmPayment(orderId: Int, status: String) {
Log.d(TAG, "Confirming order completed: orderId=$orderId, status=$status")
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
}
}
fun refreshOrders(status: String = "all") {
Log.d(TAG, "Refreshing orders with status: $status")
Log.d(TAG, "========== Starting refreshOrders ==========")
Log.d(TAG, "Refreshing orders with status: '$status'")
// Clear current orders before fetching new ones
_sells.value = ViewState.Loading
Log.d(TAG, "ViewState set to Loading for refresh")
// Re-fetch the orders with the current status
getSellList(status)
Log.d(TAG, "========== refreshOrders method completed ==========")
}
}

View File

@ -0,0 +1,65 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<!-- Header with title and close button -->
<LinearLayout
android:id="@+id/header_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:gravity="center_vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Bukti Pembayaran"
android:textColor="@android:color/white"
android:textSize="18sp"
android:textStyle="bold" />
<ImageButton
android:id="@+id/btn_close"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_close"
android:contentDescription="Close"
app:tint="@android:color/white" />
</LinearLayout>
<!-- Progress bar for loading -->
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<!-- Main image view -->
<ImageView
android:id="@+id/iv_payment_evidence"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="16dp"
android:scaleType="centerInside"
android:contentDescription="Payment Evidence"
app:layout_constraintTop_toBottomOf="@+id/header_layout"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
<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"
@ -9,7 +9,7 @@
tools:context=".ui.profile.mystore.sells.SellsFragment">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout_sells"
android:id="@+id/tabLayoutSells"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"
@ -19,12 +19,14 @@
app:tabSelectedTextColor="@color/blue_500"
app:tabTextColor="@color/black_300"
app:tabBackground="@color/white"
app:tabPadding="13dp"/>
app:tabPadding="13dp"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager_sells"
android:id="@+id/viewPagerSells"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tabLayoutSells" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<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:layout_width="match_parent"
@ -7,14 +7,16 @@
tools:context=".ui.profile.mystore.sells.SellsListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_sells"
android:id="@+id/rvSells"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:padding="8dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_sells" />
<TextView
android:id="@+id/tv_empty_state"
android:id="@+id/tvEmptyState"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TIdak ada penjualan"
@ -26,7 +28,7 @@
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="@+id/progress_bar"
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
@ -35,4 +37,4 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,873 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.cardview.widget.CardView 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="wrap_content"
android:orientation="vertical">
android:layout_marginBottom="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="2dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_orders"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingTop="16dp">
android:padding="16dp">
<!-- Order Header -->
<View
android:id="@+id/shape_order_title"
android:layout_width="4dp"
android:layout_height="48dp"
android:background="@drawable/shape_sells_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="@+id/layout_order_header"
android:layout_width="220dp"
<TextView
android:id="@+id/tvUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
app:layout_constraintStart_toStartOf="@id/shape_order_title"
android:textColor="@android:color/black"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical">
tools:text="Customer Name" />
<TextView
android:id="@+id/tv_order_title"
style="@style/label_medium_prominent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Pesanan Belum Dibayar"/>
<TextView
android:id="@+id/tv_order_number"
style="@style/label_small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="@color/black_300"
android:text="No. Pesanan: 123456789"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_person"/>
<TextView
android:id="@+id/tv_order_customer"
style="@style/label_small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:layout_marginStart="4dp"
android:textColor="@color/black_300"
android:text="Gracia Hotmauli"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/tvOrderStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical"
android:layout_marginEnd="16dp"
android:gravity="end">
<TextView
android:layout_width="150dp"
android:layout_height="wrap_content"
android:maxLines="1"
style="@style/label_small"
android:textAlignment="textEnd"
android:text="Batas waktu pembayaran:"
android:textColor="@color/black_300" />
<TextView
android:id="@+id/tv_order_due"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25 Okt; 23.59"
style="@style/label_small"
android:paddingHorizontal="4dp"
android:textColor="@color/darkblue_500"
android:background="@drawable/bg_product_active" />
</LinearLayout>
<!-- Order Detail -->
<LinearLayout
android:id="@+id/layout_order_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/layout_order_header"
android:paddingHorizontal="16dp"
android:layout_marginTop="8dp"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black_50"/>
<!-- Product Detail -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_order_product_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="12dp">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/iv_order_product"
android:layout_width="95dp"
android:layout_height="64dp"
android:src="@drawable/placeholder_image"
android:scaleType="centerCrop"
android:contentDescription="Order Product Image"
app:shapeAppearanceOverlay="@style/store_product_image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="13dp"
app:layout_constraintStart_toEndOf="@id/iv_order_product"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_order_product_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Jaket Pink Fuschia"
style="@style/label_medium_prominent"/>
<!-- <TextView-->
<!-- android:id="@+id/tv_order_product_variant"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:maxLines="1"-->
<!-- android:text="S"-->
<!-- style="@style/label_medium"-->
<!-- android:textColor="@color/black_300"/>-->
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="13dp"
android:gravity="end"
app:layout_constraintStart_toEndOf="@id/iv_order_product"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@id/iv_order_product">
<TextView
android:id="@+id/tv_order_product_qty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="x2"
style="@style/label_medium"
android:textColor="@color/black_300"
android:textAlignment="textEnd"/>
<TextView
android:id="@+id/tv_order_product_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Rp150.000"
style="@style/label_medium"
android:textAlignment="textEnd"/>
</LinearLayout>
<TextView
android:id="@+id/tv_see_more_order"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:text="Lihat 3 produk lainnya"
android:gravity="center"
style="@style/label_small"
android:fontFamily="@font/dmsans_italic"
android:textColor="@color/black_300"
app:layout_constraintTop_toBottomOf="@id/iv_order_product"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginVertical="8dp"
android:clickable="true"
android:visibility="gone"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black_50"/>
<!-- Total Price -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="8dp">
<TextView
android:id="@+id/tv_order_qty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2 produk"
style="@style/label_large"
android:layout_alignParentStart="true"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentEnd="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Total:"
style="@style/label_large_prominent"
android:textAlignment="textEnd"/>
<TextView
android:id="@+id/tv_order_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rp300.000"
style="@style/label_large_prominent"
android:textColor="@color/blue_500"
android:layout_marginStart="5dp"
android:textAlignment="textEnd"/>
</LinearLayout>
</RelativeLayout>
<!-- <View-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="1dp"-->
<!-- android:background="@color/black_50"/>-->
<!-- -->
<!-- &lt;!&ndash; Action Buttons &ndash;&gt;-->
<!-- -->
<!-- <LinearLayout-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginTop="13dp"-->
<!-- android:orientation="horizontal">-->
<!-- -->
<!-- <Button-->
<!-- android:id="@+id/btn_edit_order"-->
<!-- style="@style/button.small.secondary.medium"-->
<!-- android:text="Ubah Tagihan"-->
<!-- android:layout_marginEnd="10dp"/>-->
<!-- -->
<!-- <Button-->
<!-- android:id="@+id/btn_confirm_order"-->
<!-- style="@style/button.small.active.medium"-->
<!-- android:text="Konfirmasi Tagihan" />-->
<!-- -->
<!-- </LinearLayout>-->
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="8dp"
android:background="@color/black_50"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/layout_order_detail"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_payments"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingTop="16dp">
<!-- Payment Header -->
<View
android:id="@+id/shape_payment_order_title"
android:layout_width="4dp"
android:layout_height="32dp"
android:background="@drawable/shape_sells_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="@+id/layout_payment_order_header"
android:layout_width="220dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
app:layout_constraintStart_toStartOf="@id/shape_payment_order_title"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_payment_title"
style="@style/label_medium_prominent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Pesanan Telah Dibayar"/>
<TextView
android:id="@+id/tv_payment_number"
style="@style/label_small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="@color/black_300"
android:text="No. Pesanan: 123456789"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical"
android:layout_marginEnd="16dp"
android:gravity="end">
android:visibility="gone"
tools:text="Menunggu Tagihan" />
<TextView
android:id="@+id/tv_payment_due_desc"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:maxLines="1"
style="@style/label_small"
android:textAlignment="textEnd"
android:text="Konfirmasi pembayaran sebelum:"
android:textColor="@color/black_300" />
<TextView
android:id="@+id/tv_payment_due"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25 Okt; 23.59"
style="@style/label_small"
android:paddingHorizontal="4dp"
android:textColor="@color/darkblue_500"
android:background="@drawable/bg_product_active" />
</LinearLayout>
<!-- Order Detail -->
<LinearLayout
android:id="@+id/layout_payment_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/layout_payment_order_header"
android:paddingHorizontal="16dp"
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:orientation="vertical">
android:background="#E0E0E0"
app:layout_constraintTop_toBottomOf="@+id/tvUserName" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black_50"/>
<!-- Product Detail -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_payment_product_detail"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvSellsItems"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="12dp">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/iv_payment_product"
android:layout_width="95dp"
android:layout_height="64dp"
android:src="@drawable/placeholder_image"
android:scaleType="centerCrop"
android:contentDescription="Payment Product Image"
app:shapeAppearanceOverlay="@style/store_product_image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="13dp"
app:layout_constraintStart_toEndOf="@id/iv_payment_product"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_payment_product_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Jaket Pink Fuschia"
style="@style/label_medium_prominent"/>
<!-- <TextView-->
<!-- android:id="@+id/tv_payment_product_variant"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:maxLines="1"-->
<!-- android:text="S"-->
<!-- style="@style/label_medium"-->
<!-- android:textColor="@color/black_300"/>-->
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="13dp"
android:gravity="end"
app:layout_constraintStart_toEndOf="@id/iv_payment_product"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@id/iv_payment_product">
<TextView
android:id="@+id/tv_payment_product_qty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="x2"
style="@style/label_medium"
android:textColor="@color/black_300"
android:textAlignment="textEnd"/>
<TextView
android:id="@+id/tv_payment_product_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Rp150.000"
style="@style/label_medium"
android:textAlignment="textEnd"/>
</LinearLayout>
<TextView
android:id="@+id/tv_see_more_payment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:text="Lihat 3 produk lainnya"
android:gravity="center"
style="@style/label_small"
android:fontFamily="@font/dmsans_italic"
android:textColor="@color/black_300"
app:layout_constraintTop_toBottomOf="@id/iv_payment_product"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginVertical="8dp"
android:clickable="true"
android:visibility="gone"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black_50"/>
<!-- Total Price -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="8dp">
<TextView
android:id="@+id/tv_payment_qty"
style="@style/label_large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:text="2 produk" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentEnd="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Total:"
style="@style/label_large_prominent"
android:textAlignment="textEnd"/>
<TextView
android:id="@+id/tv_payment_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rp300.000"
style="@style/label_large_prominent"
android:textColor="@color/blue_500"
android:layout_marginStart="5dp"
android:textAlignment="textEnd"/>
</LinearLayout>
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black_50"/>
<!-- Action Buttons -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="13dp"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="158dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentStart="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_person"
app:tint="@color/black_500" />
<TextView
android:id="@+id/tv_payment_customer"
style="@style/label_small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:layout_marginStart="4dp"
android:textColor="@color/black_500"
android:text="Gracia Hotmauli"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_location" />
<TextView
android:id="@+id/tv_payment_location"
style="@style/label_small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:layout_marginStart="4dp"
android:textColor="@color/black_500"
android:text="Serang"/>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/btn_confirm_payment"
style="@style/button.small.active.medium"
android:text="Konfirmasi Pembayaran"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="8dp"
android:background="@color/black_50"
android:layout_marginTop="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/layout_payment_detail"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_shipments"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingTop="16dp">
<!-- Shipment Header -->
<View
android:id="@+id/shape_shipment_order_title"
android:layout_width="4dp"
android:layout_height="32dp"
android:background="@drawable/shape_sells_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="@+id/layout_shipment_order_header"
android:layout_width="220dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
app:layout_constraintStart_toStartOf="@id/shape_shipment_order_title"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_shipment_title"
style="@style/label_medium_prominent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Pesanan Perlu Dikirim"/>
<TextView
android:id="@+id/tv_shipment_number"
style="@style/label_small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="@color/black_300"
android:text="No. Pesanan: 123456789"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical"
android:layout_marginEnd="16dp"
android:gravity="end">
<TextView
android:layout_width="150dp"
android:layout_height="wrap_content"
android:maxLines="1"
style="@style/label_small"
android:textAlignment="textEnd"
android:text="Kirim sebelum:"
android:textColor="@color/black_300" />
<TextView
android:id="@+id/tv_shipment_due"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25 Okt; 23.59"
style="@style/label_small"
android:paddingHorizontal="4dp"
android:textColor="@color/darkblue_500"
android:background="@drawable/bg_product_active" />
</LinearLayout>
<!-- Order Detail -->
<LinearLayout
android:id="@+id/layout_shipment_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/layout_shipment_order_header"
android:paddingHorizontal="16dp"
android:layout_marginTop="8dp"
android:orientation="vertical">
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toBottomOf="@+id/divider"
tools:itemCount="1"
tools:listitem="@layout/item_order_product" />
<TextView
android:id="@+id/tvShowMores"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center_vertical"
android:textColor="@android:color/darker_gray"
android:textSize="14sp"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rvSellsItems"
app:layout_constraintEnd_toEndOf="parent"
tools:text="@string/show_more_product" />
<View
android:id="@+id/divider2"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black_50"/>
android:layout_marginTop="8dp"
android:background="#E0E0E0"
app:layout_constraintTop_toBottomOf="@+id/tvShowMores" />
<!-- Product Detail -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_shipment_product_detail"
android:layout_width="match_parent"
<TextView
android:id="@+id/tv_count_total_items"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingVertical="12dp">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/iv_shipment_product"
android:layout_width="95dp"
android:layout_height="48dp"
android:src="@drawable/placeholder_image"
android:scaleType="centerCrop"
android:contentDescription="Shipment Product Image"
app:shapeAppearanceOverlay="@style/store_product_image"
android:layout_marginTop="8dp"
android:text="@string/item_count_prod"
android:textSize="14sp"
android:fontFamily="@font/dmsans_bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
app:layout_constraintTop_toBottomOf="@+id/divider2" />
<LinearLayout
android:layout_width="0dp"
<TextView
android:id="@+id/tvTotalLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="13dp"
app:layout_constraintStart_toEndOf="@id/iv_shipment_product"
android:layout_marginTop="8dp"
android:text="@string/total_order"
android:textColor="@android:color/black"
android:textSize="14sp"
android:fontFamily="@font/dmsans_bold"
app:layout_constraintEnd_toStartOf="@+id/tvTotalAmounts"
app:layout_constraintTop_toBottomOf="@+id/divider2"/>
<TextView
android:id="@+id/tvTotalAmounts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@android:color/black"
android:textSize="14sp"
android:fontFamily="@font/dmsans_semibold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
app:layout_constraintTop_toBottomOf="@+id/divider2"
tools:text="Rp500.000" />
<TextView
android:id="@+id/tv_shipment_product_name"
android:layout_width="match_parent"
android:id="@+id/tvDeadlineLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Jaket Pink Fuschia"
style="@style/label_medium_prominent"/>
<!-- <TextView-->
<!-- android:id="@+id/tv_shipment_product_variant"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:maxLines="1"-->
<!-- android:text="S"-->
<!-- style="@style/label_medium"-->
<!-- android:textColor="@color/black_300"/>-->
</LinearLayout>
<TextView
android:id="@+id/tv_shipment_product_qty"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="x2"
style="@style/label_medium"
android:layout_marginStart="13dp"
android:gravity="end"
android:textAlignment="textEnd"
app:layout_constraintStart_toEndOf="@id/iv_shipment_product"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@id/iv_shipment_product"/>
<TextView
android:id="@+id/tv_see_more_shipment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:text="Lihat 3 produk lainnya"
android:gravity="center"
style="@style/label_small"
android:fontFamily="@font/dmsans_italic"
android:textColor="@color/black_300"
app:layout_constraintTop_toBottomOf="@id/iv_shipment_product"
android:layout_marginTop="8dp"
android:text="@string/batas_tagihan"
android:textSize="14sp"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_count_total_items" />
<TextView
android:id="@+id/tvDeadlineDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginTop="8dp"
android:textColor="@android:color/black"
android:textSize="14sp"
android:visibility="gone"
app:layout_constraintStart_toEndOf="@+id/tvDeadlineLabel"
app:layout_constraintTop_toBottomOf="@+id/tv_count_total_items"
tools:text="28 Oktober 2024" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_button_outline"
android:backgroundTint="@color/white"
android:visibility="gone"
android:text="Tolak"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvDeadlineDate"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="8dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_button_filled"
android:visibility="gone"
android:text="Terima"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvDeadlineDate"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginVertical="8dp"
android:clickable="true"
android:visibility="gone"/>
android:layout_marginTop="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/black_50"/>
<!-- Action Buttons -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="13dp"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="158dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentStart="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_person"
app:tint="@color/black_500" />
<TextView
android:id="@+id/tv_shipment_customer"
style="@style/label_small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:layout_marginStart="4dp"
android:textColor="@color/black_500"
android:text="Gracia Hotmauli"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_location" />
<TextView
android:id="@+id/tv_shipment_location"
style="@style/label_small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:layout_marginStart="4dp"
android:textColor="@color/black_500"
android:text="Serang"/>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/btn_confirm_shipment"
style="@style/button.small.active.medium"
android:text="Kirim Pesanan"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="8dp"
android:background="@color/black_50"
android:layout_marginTop="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/layout_shipment_detail"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>