sells detail

This commit is contained in:
Gracia Hotmauli
2025-06-03 00:23:19 +07:00
parent d642505e2f
commit 51882ff634
21 changed files with 722 additions and 52 deletions

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.store.orders
package com.alya.ecommerce_serang.data.api.response.store.sells
import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.store.orders
package com.alya.ecommerce_serang.data.api.response.store.sells
import com.alya.ecommerce_serang.data.api.dto.UpdatedOrder
import com.google.gson.annotations.SerializedName

View File

@ -0,0 +1,129 @@
package com.alya.ecommerce_serang.data.api.response.store.sells
import com.google.gson.annotations.SerializedName
data class OrderDetailResponse(
@field:SerializedName("orders")
val orders: Orders? = null,
@field:SerializedName("message")
val message: String? = null
)
data class Orders(
@field:SerializedName("receipt_num")
val receiptNum: Any? = null,
@field:SerializedName("payment_upload_at")
val paymentUploadAt: Any? = null,
@field:SerializedName("latitude")
val latitude: Any? = null,
@field:SerializedName("pay_info_name")
val payInfoName: String? = null,
@field:SerializedName("created_at")
val createdAt: String? = null,
@field:SerializedName("voucher_code")
val voucherCode: Any? = null,
@field:SerializedName("order_status")
val orderStatus: String? = null,
@field:SerializedName("updated_at")
val updatedAt: String? = null,
@field:SerializedName("etd")
val etd: String? = null,
@field:SerializedName("street")
val street: String? = null,
@field:SerializedName("cancel_date")
val cancelDate: Any? = null,
@field:SerializedName("payment_evidence")
val paymentEvidence: Any? = null,
@field:SerializedName("longitude")
val longitude: Any? = null,
@field:SerializedName("shipment_status")
val shipmentStatus: String? = null,
@field:SerializedName("order_items")
val orderItems: List<OrderItemsItem?>? = null,
@field:SerializedName("auto_completed_at")
val autoCompletedAt: Any? = null,
@field:SerializedName("is_store_location")
val isStoreLocation: Boolean? = null,
@field:SerializedName("qris_image")
val qrisImage: String? = null,
@field:SerializedName("voucher_name")
val voucherName: Any? = null,
@field:SerializedName("payment_status")
val paymentStatus: Any? = null,
@field:SerializedName("address_id")
val addressId: Int? = null,
@field:SerializedName("payment_amount")
val paymentAmount: Any? = null,
@field:SerializedName("cancel_reason")
val cancelReason: Any? = null,
@field:SerializedName("total_amount")
val totalAmount: String? = null,
@field:SerializedName("user_id")
val userId: Int? = null,
@field:SerializedName("province_id")
val provinceId: Int? = null,
@field:SerializedName("courier")
val courier: String? = null,
@field:SerializedName("subdistrict")
val subdistrict: String? = null,
@field:SerializedName("service")
val service: String? = null,
@field:SerializedName("pay_info_num")
val payInfoNum: String? = null,
@field:SerializedName("shipment_price")
val shipmentPrice: String? = null,
@field:SerializedName("voucher_id")
val voucherId: Any? = null,
@field:SerializedName("payment_info_id")
val paymentInfoId: Int? = null,
@field:SerializedName("detail")
val detail: String? = null,
@field:SerializedName("postal_code")
val postalCode: String? = null,
@field:SerializedName("order_id")
val orderId: Int? = null,
@field:SerializedName("username")
val username: String? = null,
@field:SerializedName("city_id")
val cityId: Int? = null
)

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.store.orders
package com.alya.ecommerce_serang.data.api.response.store.sells
import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.store.orders
package com.alya.ecommerce_serang.data.api.response.store.sells
import com.google.gson.annotations.SerializedName

View File

@ -1,4 +1,4 @@
package com.alya.ecommerce_serang.data.api.response.store.orders
package com.alya.ecommerce_serang.data.api.response.store.sells
import com.google.gson.annotations.SerializedName

View File

@ -66,7 +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.sells.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
@ -325,7 +325,7 @@ interface ApiService {
@GET("mystore/orders/{status}")
suspend fun getSellList(
@Path("status") status: String
): Response<com.alya.ecommerce_serang.data.api.response.store.orders.OrderListResponse>
): Response<com.alya.ecommerce_serang.data.api.response.store.sells.OrderListResponse>
@PUT("store/order/update")
suspend fun confirmOrder(
@ -336,7 +336,7 @@ interface ApiService {
suspend fun updateOrder(
@Query("order_id") orderId: Int?,
@Query("status") status: String
): Response<com.alya.ecommerce_serang.data.api.response.store.orders.UpdateOrderItemResponse>
): Response<com.alya.ecommerce_serang.data.api.response.store.sells.UpdateOrderItemResponse>
@Multipart
@POST("addcomplaint")

View File

@ -2,8 +2,8 @@ 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.response.store.sells.OrderListResponse
import com.alya.ecommerce_serang.data.api.response.store.sells.PaymentConfirmationResponse
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
class SellsRepository(private val apiService: ApiService) {

View File

@ -48,6 +48,13 @@ class MyStoreActivity : AppCompatActivity() {
enableEdgeToEdge()
binding.header.headerTitle.text = "Toko Saya"
binding.header.headerLeftIcon.setOnClickListener {
onBackPressed()
finish()
}
viewModel.loadMyStore()
viewModel.myStoreProfile.observe(this){ user ->

View File

@ -0,0 +1,129 @@
package com.alya.ecommerce_serang.ui.profile.mystore.sells
import android.os.Bundle
import android.util.Log
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
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.ActivityDetailSellsBinding
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 java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import java.util.TimeZone
import kotlin.getValue
class DetailSellsActivity : AppCompatActivity() {
private lateinit var binding: ActivityDetailSellsBinding
private lateinit var sessionManager: SessionManager
private var sells: Orders? = null
private lateinit var productAdapter: SellsProductAdapter
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 = ActivityDetailSellsBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.header.headerTitle.text = "Detail Pesanan"
binding.header.headerLeftIcon.setOnClickListener {
onBackPressed()
finish()
}
productAdapter = SellsProductAdapter()
binding.rvProductItems.apply {
adapter = productAdapter
layoutManager = LinearLayoutManager(this@DetailSellsActivity)
}
val sellsJson = intent.getStringExtra("sells")
if (sellsJson != null) {
try {
sells = Gson().fromJson(sellsJson, Orders::class.java)
showOrderDetails()
} catch (e: Exception) {
Log.e("DetailSellsActivity", "Failed to parse order data", e)
}
} else {
Log.e("DetailSellsActivity", "Order data is missing")
}
}
private fun showOrderDetails() {
sells?.let { sell ->
when (sell.orderStatus) {
"pending", "unpaid" -> {
binding.tvOrderSellsTitle.text = "Pesanan Belum Dibayar"
}
"shipped" -> {
binding.tvOrderSellsTitle.text = "Pesanan Telah Dikirim"
}
"delivered" -> {
binding.tvOrderSellsTitle.text = "Pesanan Telah Sampai"
}
"completed" -> {
binding.tvOrderSellsTitle.text = "Pesanan Selesai"
}
"canceled" -> {
binding.tvOrderSellsTitle.text = "Pesanan Dibatalkan"
}
}
binding.tvOrderNumber.text = sell.orderId.toString()
binding.tvOrderCustomer.text = sell.username
binding.tvOrderDate.text = formatDate(sell.updatedAt.toString())
binding.tvOrderTotalProduct.text = "(${sell.orderItems?.size} Barang)"
binding.tvOrderSubtotal.text = formatPrice(sell.totalAmount.toString())
binding.tvOrderShipPrice.text = formatPrice(sell.shipmentPrice.toString())
binding.tvOrderPrice.text = formatPrice(sell.totalAmount.toString())
binding.tvOrderRecipient.text = sell.username
binding.tvOrderRecipientNum.text = sell.receiptNum.toString()
sell.orderItems?.let {
productAdapter.submitList(it.filterNotNull())
}
}
}
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 MMM yyyy, HH.mm", Locale("id", "ID"))
val date = inputFormat.parse(dateString)
date?.let {
val calendar = Calendar.getInstance()
calendar.time = it
outputFormat.format(calendar.time)
} ?: dateString
} catch (e: Exception) {
Log.e("DateFormatting", "Error formatting date: ${e.message}")
dateString
}
}
private fun formatPrice(price: String): String {
val priceDouble = price.toDoubleOrNull() ?: 0.0
val formattedPrice = String.format(Locale("id", "ID"), "Rp%,.0f", priceDouble)
return formattedPrice
}
}

View File

@ -11,12 +11,11 @@ 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.store.orders.OrdersItem
import com.alya.ecommerce_serang.data.api.response.store.sells.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
@ -67,9 +66,9 @@ class SellsAdapter(
private val layoutPayments: View = itemView.findViewById(R.id.layout_payments)
private val layoutShipments: View = itemView.findViewById(R.id.layout_shipments)
private var tvSellsTitle: TextView = itemView.findViewById(R.id.tv_payment_title)
private var tvSellsTitle: TextView = itemView.findViewById(R.id.tv_order_sells_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 tvSellsDueDesc: TextView = itemView.findViewById(R.id.tv_order_sells_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)

View File

@ -1,5 +1,6 @@
package com.alya.ecommerce_serang.ui.profile.mystore.sells
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
@ -9,15 +10,18 @@ import android.widget.Toast
import androidx.fragment.app.Fragment
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.response.store.sells.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
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.BaseViewModelFactory
import com.alya.ecommerce_serang.utils.SessionManager
import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel
import com.google.gson.Gson
class SellsListFragment : Fragment() {
@ -169,9 +173,14 @@ class SellsListFragment : Fragment() {
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()
val context = requireContext()
val intent = when (status) {
"paid" -> Intent(context, DetailPaymentActivity::class.java)
"processed" -> Intent(context, DetailShipmentActivity::class.java)
else -> Intent(context, DetailSellsActivity::class.java)
}
intent.putExtra("sells_data", Gson().toJson(order))
context.startActivity(intent)
}
override fun onDestroyView() {

View File

@ -7,8 +7,9 @@ import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.response.store.orders.OrderItemsItem
import com.alya.ecommerce_serang.data.api.response.store.sells.OrderItemsItem
import com.bumptech.glide.Glide
import java.util.Locale
class SellsProductAdapter : RecyclerView.Adapter<SellsProductAdapter.ProductViewHolder>() {
@ -30,9 +31,8 @@ class SellsProductAdapter : RecyclerView.Adapter<SellsProductAdapter.ProductView
fun bind(item: OrderItemsItem) {
tvName.text = item.productName
tvQty.text = "${item.quantity} x "
tvPrice.text = "Rp${item.price}"
val total = (item.quantity ?: 1) * (item.price ?: 0)
tvTotal.text = "Rp$total"
tvPrice.text = formatPrice(item.price.toString())
tvTotal.text = formatPrice(item.subtotal.toString())
Glide.with(ivProduct.context)
.load(item.productImage)
.placeholder(R.drawable.placeholder_image)
@ -51,4 +51,10 @@ class SellsProductAdapter : RecyclerView.Adapter<SellsProductAdapter.ProductView
override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
items[position]?.let { holder.bind(it) }
}
private fun formatPrice(price: String): String {
val priceDouble = price.toDoubleOrNull() ?: 0.0
val formattedPrice = String.format(Locale("id", "ID"), "Rp%,.0f", priceDouble)
return formattedPrice
}
}

View File

@ -18,7 +18,7 @@ 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.response.store.sells.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
@ -106,7 +106,7 @@ class DetailPaymentActivity : AppCompatActivity() {
}
private fun setupPaymentEvidenceViewer() {
binding.tvPaymentDueDesc.setOnClickListener {
binding.tvOrderSellsDesc.setOnClickListener {
val paymentEvidence = sells.paymentEvidence
if (!paymentEvidence.isNullOrEmpty()) {
showPaymentEvidenceDialog(paymentEvidence)

View File

@ -3,7 +3,7 @@ package com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.alya.ecommerce_serang.data.api.response.store.orders.OrdersItem
import com.alya.ecommerce_serang.data.api.response.store.sells.OrdersItem
import com.alya.ecommerce_serang.databinding.ActivityDetailShipmentBinding
import com.alya.ecommerce_serang.ui.profile.mystore.sells.SellsProductAdapter
import com.google.gson.Gson

View File

@ -6,8 +6,8 @@ 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.api.response.store.sells.OrdersItem
import com.alya.ecommerce_serang.data.api.response.store.sells.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