mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-10 09:22:21 +00:00
sells detail
This commit is contained in:
@ -0,0 +1,36 @@
|
||||
package com.alya.ecommerce_serang.data.api.dto
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class OrderItemsItem(
|
||||
|
||||
@field:SerializedName("order_item_id")
|
||||
val orderItemId: Int? = null,
|
||||
|
||||
@field:SerializedName("review_id")
|
||||
val reviewId: Int? = null,
|
||||
|
||||
@field:SerializedName("quantity")
|
||||
val quantity: Int? = null,
|
||||
|
||||
@field:SerializedName("price")
|
||||
val price: Int? = null,
|
||||
|
||||
@field:SerializedName("subtotal")
|
||||
val subtotal: Int? = null,
|
||||
|
||||
@field:SerializedName("product_image")
|
||||
val productImage: String? = null,
|
||||
|
||||
@field:SerializedName("product_id")
|
||||
val productId: Int? = null,
|
||||
|
||||
@field:SerializedName("store_name")
|
||||
val storeName: String? = null,
|
||||
|
||||
@field:SerializedName("product_price")
|
||||
val productPrice: Int? = null,
|
||||
|
||||
@field:SerializedName("product_name")
|
||||
val productName: String? = null
|
||||
)
|
@ -1,5 +1,6 @@
|
||||
package com.alya.ecommerce_serang.data.api.response.store.sells
|
||||
|
||||
import com.alya.ecommerce_serang.data.api.dto.OrderItemsItem
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class OrderDetailResponse(
|
||||
@ -17,7 +18,7 @@ data class Orders(
|
||||
val receiptNum: Any? = null,
|
||||
|
||||
@field:SerializedName("payment_upload_at")
|
||||
val paymentUploadAt: Any? = null,
|
||||
val paymentUploadAt: String? = null,
|
||||
|
||||
@field:SerializedName("latitude")
|
||||
val latitude: Any? = null,
|
||||
@ -44,10 +45,10 @@ data class Orders(
|
||||
val street: String? = null,
|
||||
|
||||
@field:SerializedName("cancel_date")
|
||||
val cancelDate: Any? = null,
|
||||
val cancelDate: String? = null,
|
||||
|
||||
@field:SerializedName("payment_evidence")
|
||||
val paymentEvidence: Any? = null,
|
||||
val paymentEvidence: String? = null,
|
||||
|
||||
@field:SerializedName("longitude")
|
||||
val longitude: Any? = null,
|
||||
@ -71,16 +72,16 @@ data class Orders(
|
||||
val voucherName: Any? = null,
|
||||
|
||||
@field:SerializedName("payment_status")
|
||||
val paymentStatus: Any? = null,
|
||||
val paymentStatus: String? = null,
|
||||
|
||||
@field:SerializedName("address_id")
|
||||
val addressId: Int? = null,
|
||||
|
||||
@field:SerializedName("payment_amount")
|
||||
val paymentAmount: Any? = null,
|
||||
val paymentAmount: String? = null,
|
||||
|
||||
@field:SerializedName("cancel_reason")
|
||||
val cancelReason: Any? = null,
|
||||
val cancelReason: String? = null,
|
||||
|
||||
@field:SerializedName("total_amount")
|
||||
val totalAmount: String? = null,
|
||||
@ -88,6 +89,9 @@ data class Orders(
|
||||
@field:SerializedName("user_id")
|
||||
val userId: Int? = null,
|
||||
|
||||
@field:SerializedName("phone")
|
||||
val phone: String? = null,
|
||||
|
||||
@field:SerializedName("province_id")
|
||||
val provinceId: Int? = null,
|
||||
|
||||
@ -103,6 +107,9 @@ data class Orders(
|
||||
@field:SerializedName("pay_info_num")
|
||||
val payInfoNum: String? = null,
|
||||
|
||||
@field:SerializedName("recipient")
|
||||
val recipient: String? = null,
|
||||
|
||||
@field:SerializedName("shipment_price")
|
||||
val shipmentPrice: String? = null,
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.alya.ecommerce_serang.data.api.response.store.sells
|
||||
|
||||
import com.alya.ecommerce_serang.data.api.dto.OrderItemsItem
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class OrderListResponse(
|
||||
@ -11,39 +12,6 @@ data class OrderListResponse(
|
||||
val message: String? = null
|
||||
)
|
||||
|
||||
data class OrderItemsItem(
|
||||
|
||||
@field:SerializedName("order_item_id")
|
||||
val orderItemId: Int? = null,
|
||||
|
||||
@field:SerializedName("review_id")
|
||||
val reviewId: Any? = null,
|
||||
|
||||
@field:SerializedName("quantity")
|
||||
val quantity: Int? = null,
|
||||
|
||||
@field:SerializedName("price")
|
||||
val price: Int? = null,
|
||||
|
||||
@field:SerializedName("subtotal")
|
||||
val subtotal: Int? = null,
|
||||
|
||||
@field:SerializedName("product_image")
|
||||
val productImage: String? = null,
|
||||
|
||||
@field:SerializedName("product_id")
|
||||
val productId: Int? = null,
|
||||
|
||||
@field:SerializedName("store_name")
|
||||
val storeName: String? = null,
|
||||
|
||||
@field:SerializedName("product_price")
|
||||
val productPrice: Int? = null,
|
||||
|
||||
@field:SerializedName("product_name")
|
||||
val productName: String? = null
|
||||
)
|
||||
|
||||
data class OrdersItem(
|
||||
|
||||
@field:SerializedName("receipt_num")
|
||||
|
@ -327,6 +327,11 @@ interface ApiService {
|
||||
@Path("status") status: String
|
||||
): Response<com.alya.ecommerce_serang.data.api.response.store.sells.OrderListResponse>
|
||||
|
||||
@GET("order/detail/{id}")
|
||||
suspend fun getSellDetail(
|
||||
@Path("id") orderId: Int
|
||||
): Response<com.alya.ecommerce_serang.data.api.response.store.sells.OrderDetailResponse>
|
||||
|
||||
@PUT("store/order/update")
|
||||
suspend fun confirmOrder(
|
||||
@Body confirmOrder : CompletedOrderRequest
|
||||
|
@ -2,6 +2,7 @@ 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.sells.OrderDetailResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.store.sells.OrderListResponse
|
||||
import com.alya.ecommerce_serang.data.api.response.store.sells.PaymentConfirmationResponse
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
||||
@ -32,6 +33,16 @@ class SellsRepository(private val apiService: ApiService) {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getSellDetails(orderId: Int): OrderDetailResponse? {
|
||||
return try {
|
||||
val response = apiService.getSellDetail(orderId)
|
||||
if (response.isSuccessful) response.body() else null
|
||||
} catch (e: Exception) {
|
||||
Log.e("SellsRepository", "Error getting order details", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateOrderStatus(orderId: Int?, status: String) {
|
||||
try {
|
||||
val response = apiService.updateOrder(orderId, status)
|
||||
|
@ -2,15 +2,20 @@ package com.alya.ecommerce_serang.ui.profile.mystore.sells
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
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.response.store.sells.OrdersItem
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||
import com.alya.ecommerce_serang.data.repository.AddressRepository
|
||||
import com.alya.ecommerce_serang.data.repository.SellsRepository
|
||||
import com.alya.ecommerce_serang.databinding.ActivityDetailSellsBinding
|
||||
import com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment.DetailShipmentActivity
|
||||
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||
import com.alya.ecommerce_serang.utils.SessionManager
|
||||
import com.alya.ecommerce_serang.utils.viewmodel.AddressViewModel
|
||||
import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel
|
||||
import com.google.gson.Gson
|
||||
import java.text.SimpleDateFormat
|
||||
@ -28,6 +33,7 @@ class DetailSellsActivity : AppCompatActivity() {
|
||||
|
||||
private val viewModel: SellsViewModel by viewModels {
|
||||
BaseViewModelFactory {
|
||||
sessionManager = SessionManager(this)
|
||||
val apiService = ApiConfig.getApiService(sessionManager)
|
||||
val sellsRepository = SellsRepository(apiService)
|
||||
SellsViewModel(sellsRepository)
|
||||
@ -51,48 +57,88 @@ class DetailSellsActivity : AppCompatActivity() {
|
||||
layoutManager = LinearLayoutManager(this@DetailSellsActivity)
|
||||
}
|
||||
|
||||
val sellsJson = intent.getStringExtra("sells")
|
||||
val sellsJson = intent.getStringExtra("sells_data")
|
||||
if (sellsJson != null) {
|
||||
try {
|
||||
sells = Gson().fromJson(sellsJson, Orders::class.java)
|
||||
showOrderDetails()
|
||||
val basicOrder = Gson().fromJson(sellsJson, OrdersItem::class.java)
|
||||
basicOrder.orderId.let {
|
||||
viewModel.getSellDetails(it)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("DetailSellsActivity", "Failed to parse order data", e)
|
||||
}
|
||||
} else {
|
||||
Log.e("DetailSellsActivity", "Order data is missing")
|
||||
Log.e("DetailSellsActivity", "No order passed in intent")
|
||||
}
|
||||
|
||||
observeOrderDetails()
|
||||
}
|
||||
|
||||
private fun observeOrderDetails() {
|
||||
viewModel.sellDetails.observe(this) { order ->
|
||||
if (order != null) {
|
||||
sells = order
|
||||
showOrderDetails()
|
||||
} else {
|
||||
Log.e("DetailSellsActivity", "❌ Failed to retrieve order details")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showOrderDetails() {
|
||||
private fun showOrderDetails() = with(binding) {
|
||||
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"
|
||||
}
|
||||
"pending", "unpaid" -> tvOrderSellsTitle.text = "Pesanan Belum Dibayar"
|
||||
"shipped" -> tvOrderSellsTitle.text = "Pesanan Telah Dikirim"
|
||||
"delivered" -> tvOrderSellsTitle.text = "Pesanan Telah Sampai"
|
||||
"completed" -> tvOrderSellsTitle.text = "Pesanan Selesai"
|
||||
"canceled" -> tvOrderSellsTitle.text = "Pesanan Dibatalkan"
|
||||
else -> tvOrderSellsTitle.text = "Status Tidak Diketahui"
|
||||
}
|
||||
|
||||
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()
|
||||
tvOrderNumber.text = sell.orderId.toString()
|
||||
tvOrderCustomer.text = sell.username
|
||||
tvOrderDate.text = formatDate(sell.updatedAt.toString())
|
||||
tvOrderTotalProduct.text = "(${sell.orderItems?.size ?: 0} Barang)"
|
||||
tvOrderSubtotal.text = formatPrice(sell.totalAmount.toString())
|
||||
tvOrderShipPrice.text = formatPrice(sell.shipmentPrice.toString())
|
||||
tvOrderPrice.text = formatPrice(sell.totalAmount.toString())
|
||||
tvOrderRecipient.text = sell.recipient ?: "-"
|
||||
tvOrderRecipientNum.text = sell.receiptNum?.toString() ?: "-"
|
||||
|
||||
val cityId = sell.cityId?.toString()
|
||||
val provinceId = sell.provinceId?.toString()
|
||||
|
||||
if (cityId != null && provinceId != null) {
|
||||
val viewModelAddress: AddressViewModel by viewModels {
|
||||
BaseViewModelFactory {
|
||||
val apiService = ApiConfig.getApiService(sessionManager)
|
||||
val addressRepository = AddressRepository(apiService)
|
||||
AddressViewModel(addressRepository)
|
||||
}
|
||||
}
|
||||
|
||||
viewModelAddress.fetchCities(provinceId)
|
||||
viewModelAddress.fetchProvinces()
|
||||
|
||||
viewModelAddress.cities.observe(this@DetailSellsActivity) { cities ->
|
||||
val cityName = cities.find { it.cityId == cityId }?.cityName
|
||||
viewModelAddress.provinces.observe(this@DetailSellsActivity) { provinces ->
|
||||
val provinceName = provinces.find { it.provinceId == provinceId }?.provinceName
|
||||
|
||||
val fullAddress = listOfNotNull(
|
||||
sell.street,
|
||||
sell.subdistrict,
|
||||
cityName,
|
||||
provinceName
|
||||
).joinToString(", ")
|
||||
|
||||
tvOrderRecipientAddress.text = fullAddress
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tvOrderRecipientAddress.text = "-"
|
||||
}
|
||||
|
||||
sell.orderItems?.let {
|
||||
productAdapter.submitList(it.filterNotNull())
|
||||
@ -106,13 +152,11 @@ class DetailSellsActivity : AppCompatActivity() {
|
||||
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) {
|
||||
@ -123,7 +167,6 @@ class DetailSellsActivity : AppCompatActivity() {
|
||||
|
||||
private fun formatPrice(price: String): String {
|
||||
val priceDouble = price.toDoubleOrNull() ?: 0.0
|
||||
val formattedPrice = String.format(Locale("id", "ID"), "Rp%,.0f", priceDouble)
|
||||
return formattedPrice
|
||||
return String.format(Locale("id", "ID"), "Rp%,.0f", priceDouble)
|
||||
}
|
||||
}
|
@ -6,8 +6,9 @@ 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.store.sells.OrderItemsItem
|
||||
import com.alya.ecommerce_serang.data.api.dto.OrderItemsItem
|
||||
import com.bumptech.glide.Glide
|
||||
import java.util.Locale
|
||||
|
||||
@ -33,9 +34,18 @@ class SellsProductAdapter : RecyclerView.Adapter<SellsProductAdapter.ProductView
|
||||
tvQty.text = "${item.quantity} x "
|
||||
tvPrice.text = formatPrice(item.price.toString())
|
||||
tvTotal.text = formatPrice(item.subtotal.toString())
|
||||
|
||||
val fullImageUrl = when (val img = item.productImage) {
|
||||
is String -> {
|
||||
if (img.startsWith("/")) BASE_URL + img.substring(1) else img
|
||||
}
|
||||
else -> R.drawable.placeholder_image
|
||||
}
|
||||
|
||||
Glide.with(ivProduct.context)
|
||||
.load(item.productImage)
|
||||
.load(fullImageUrl)
|
||||
.placeholder(R.drawable.placeholder_image)
|
||||
.error(R.drawable.placeholder_image)
|
||||
.into(ivProduct)
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
@ -18,32 +19,38 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.alya.ecommerce_serang.BuildConfig.BASE_URL
|
||||
import com.alya.ecommerce_serang.R
|
||||
import com.alya.ecommerce_serang.data.api.response.store.sells.Orders
|
||||
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.AddressRepository
|
||||
import com.alya.ecommerce_serang.data.repository.SellsRepository
|
||||
import com.alya.ecommerce_serang.databinding.ActivityDetailPaymentBinding
|
||||
import com.alya.ecommerce_serang.ui.profile.mystore.sells.SellsProductAdapter
|
||||
import com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment.DetailShipmentActivity
|
||||
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
|
||||
import com.alya.ecommerce_serang.utils.SessionManager
|
||||
import com.alya.ecommerce_serang.utils.viewmodel.AddressViewModel
|
||||
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.bumptech.glide.request.transition.Transition
|
||||
import com.google.gson.Gson
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
|
||||
class DetailPaymentActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityDetailPaymentBinding
|
||||
private lateinit var sells: OrdersItem
|
||||
private var sells: Orders? = null
|
||||
private lateinit var productAdapter: SellsProductAdapter
|
||||
private lateinit var sessionManager: SessionManager
|
||||
|
||||
|
||||
private val viewModel: SellsViewModel by viewModels {
|
||||
BaseViewModelFactory {
|
||||
sessionManager = SessionManager(this)
|
||||
val apiService = ApiConfig.getApiService(sessionManager)
|
||||
val sellsRepository = SellsRepository(apiService)
|
||||
SellsViewModel(sellsRepository)
|
||||
@ -55,59 +62,120 @@ class DetailPaymentActivity : AppCompatActivity() {
|
||||
binding = ActivityDetailPaymentBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
sessionManager = SessionManager(this)
|
||||
|
||||
val orderJson = intent.getStringExtra("sells_data")
|
||||
sells = Gson().fromJson(orderJson, OrdersItem::class.java)
|
||||
|
||||
binding.header.headerTitle.text = "Detail Pesanan"
|
||||
binding.header.headerLeftIcon.setOnClickListener {
|
||||
// onBackPressed()
|
||||
onBackPressed()
|
||||
finish()
|
||||
}
|
||||
|
||||
setupRecyclerView()
|
||||
bindOrderDetails()
|
||||
setupPaymentEvidenceViewer()
|
||||
val sellsJson = intent.getStringExtra("sells_data")
|
||||
if (sellsJson != null) {
|
||||
try {
|
||||
val basicOrder = Gson().fromJson(sellsJson, OrdersItem::class.java)
|
||||
basicOrder.orderId.let {
|
||||
viewModel.getSellDetails(it)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("DetailSellsActivity", "Failed to parse order data", e)
|
||||
}
|
||||
} else {
|
||||
Log.e("DetailSellsActivity", "No order passed in intent")
|
||||
}
|
||||
|
||||
observeOrderDetails()
|
||||
|
||||
}
|
||||
|
||||
private fun bindOrderDetails() = with(binding) {
|
||||
tvOrderNumber.text = sells.orderId.toString()
|
||||
tvOrderCustomer.text = sells.username
|
||||
tvOrderDate.text = formatDate(sells.createdAt)
|
||||
tvOrderDue.text = formatDate(sells.updatedAt)
|
||||
|
||||
tvOrderTotalProduct.text = "(${sells.orderItems?.size ?: 0} Barang)"
|
||||
tvOrderSubtotal.text = "Rp${sells.totalAmount}"
|
||||
tvOrderPrice.text = "Rp${sells.totalAmount}"
|
||||
tvOrderShipPrice.text = "Rp${sells.shipmentPrice}"
|
||||
|
||||
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 observeOrderDetails() {
|
||||
viewModel.sellDetails.observe(this) { order ->
|
||||
if (order != null) {
|
||||
sells = order
|
||||
showOrderDetails()
|
||||
} else {
|
||||
Log.e("DetailShipmentActivity", "❌ Failed to retrieve order details")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
productAdapter = SellsProductAdapter()
|
||||
private fun showOrderDetails() = with(binding) {
|
||||
sells?.let { sell ->
|
||||
tvOrderNumber.text = sell.orderId.toString()
|
||||
tvOrderCustomer.text = sell.username
|
||||
tvOrderDate.text = formatDate(sell.updatedAt.toString())
|
||||
tvOrderTotalProduct.text = "(${sell.orderItems?.size ?: 0} Barang)"
|
||||
tvOrderSubtotal.text = formatPrice(sell.totalAmount.toString())
|
||||
tvOrderShipPrice.text = formatPrice(sell.shipmentPrice.toString())
|
||||
tvOrderPrice.text = formatPrice(sell.totalAmount.toString())
|
||||
tvOrderRecipient.text = sell.recipient ?: "-"
|
||||
tvOrderRecipientNum.text = sell.receiptNum?.toString() ?: "-"
|
||||
|
||||
binding.rvProductItems.apply {
|
||||
layoutManager = LinearLayoutManager(this@DetailPaymentActivity)
|
||||
adapter = productAdapter
|
||||
val cityId = sell.cityId?.toString()
|
||||
val provinceId = sell.provinceId?.toString()
|
||||
|
||||
if (cityId != null && provinceId != null) {
|
||||
val viewModelAddress: AddressViewModel by viewModels {
|
||||
BaseViewModelFactory {
|
||||
val apiService = ApiConfig.getApiService(sessionManager)
|
||||
val addressRepository = AddressRepository(apiService)
|
||||
AddressViewModel(addressRepository)
|
||||
}
|
||||
}
|
||||
|
||||
viewModelAddress.fetchCities(provinceId)
|
||||
viewModelAddress.fetchProvinces()
|
||||
|
||||
viewModelAddress.cities.observe(this@DetailPaymentActivity) { cities ->
|
||||
val cityName = cities.find { it.cityId == cityId }?.cityName
|
||||
viewModelAddress.provinces.observe(this@DetailPaymentActivity) { provinces ->
|
||||
val provinceName = provinces.find { it.provinceId == provinceId }?.provinceName
|
||||
|
||||
val fullAddress = listOfNotNull(
|
||||
sell.street,
|
||||
sell.subdistrict,
|
||||
cityName,
|
||||
provinceName
|
||||
).joinToString(", ")
|
||||
|
||||
tvOrderRecipientAddress.text = fullAddress
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tvOrderRecipientAddress.text = "-"
|
||||
}
|
||||
|
||||
sell.orderItems?.let {
|
||||
productAdapter.submitList(it.filterNotNull())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Submit the order items to the adapter
|
||||
productAdapter.submitList(sells.orderItems ?: emptyList())
|
||||
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
|
||||
return String.format(Locale("id", "ID"), "Rp%,.0f", priceDouble)
|
||||
}
|
||||
|
||||
private fun setupPaymentEvidenceViewer() {
|
||||
binding.tvOrderSellsDesc.setOnClickListener {
|
||||
val paymentEvidence = sells.paymentEvidence
|
||||
val paymentEvidence = sells?.paymentEvidence
|
||||
if (!paymentEvidence.isNullOrEmpty()) {
|
||||
showPaymentEvidenceDialog(paymentEvidence)
|
||||
} else {
|
||||
@ -154,7 +222,7 @@ class DetailPaymentActivity : AppCompatActivity() {
|
||||
.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>?) {
|
||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
||||
progressBar.visibility = View.GONE
|
||||
imageView.setImageDrawable(resource)
|
||||
}
|
||||
@ -184,17 +252,4 @@ class DetailPaymentActivity : AppCompatActivity() {
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
|
||||
private fun formatDate(dateStr: 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(dateStr ?: "")
|
||||
outputFormat.format(date!!)
|
||||
} catch (e: Exception) {
|
||||
"-"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,71 +1,155 @@
|
||||
package com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment
|
||||
|
||||
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.response.store.sells.OrdersItem
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||
import com.alya.ecommerce_serang.data.repository.AddressRepository
|
||||
import com.alya.ecommerce_serang.data.repository.SellsRepository
|
||||
import com.alya.ecommerce_serang.databinding.ActivityDetailShipmentBinding
|
||||
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.AddressViewModel
|
||||
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 DetailShipmentActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityDetailShipmentBinding
|
||||
private lateinit var sells: OrdersItem
|
||||
private lateinit var sessionManager: SessionManager
|
||||
private var sells: Orders? = null
|
||||
private lateinit var productAdapter: SellsProductAdapter
|
||||
|
||||
private val viewModel: SellsViewModel by viewModels {
|
||||
BaseViewModelFactory {
|
||||
sessionManager = SessionManager(this)
|
||||
val apiService = ApiConfig.getApiService(sessionManager)
|
||||
val sellsRepository = SellsRepository(apiService)
|
||||
SellsViewModel(sellsRepository)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityDetailShipmentBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
val orderJson = intent.getStringExtra("sells_data")
|
||||
sells = Gson().fromJson(orderJson, OrdersItem::class.java)
|
||||
|
||||
setupRecyclerView()
|
||||
bindOrderDetails()
|
||||
}
|
||||
|
||||
private fun bindOrderDetails() = with(binding) {
|
||||
tvOrderNumber.text = sells.orderId.toString()
|
||||
tvOrderCustomer.text = sells.username
|
||||
tvOrderDate.text = formatDate(sells.createdAt)
|
||||
tvOrderDue.text = formatDate(sells.updatedAt)
|
||||
|
||||
tvOrderTotalProduct.text = "(${sells.orderItems?.size ?: 0} Barang)"
|
||||
tvOrderSubtotal.text = "Rp${sells.totalAmount}"
|
||||
tvOrderPrice.text = "Rp${sells.totalAmount}"
|
||||
tvOrderShipPrice.text = "Rp${sells.shipmentPrice}"
|
||||
|
||||
tvOrderRecipient.text = sells.username
|
||||
// tvOrderRecipientNum.text = sells.phone
|
||||
tvOrderRecipientAddress.text = sells.street
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
productAdapter = SellsProductAdapter()
|
||||
|
||||
binding.rvProductItems.apply {
|
||||
layoutManager = LinearLayoutManager(this@DetailShipmentActivity)
|
||||
adapter = productAdapter
|
||||
binding.header.headerTitle.text = "Detail Pesanan"
|
||||
binding.header.headerLeftIcon.setOnClickListener {
|
||||
onBackPressed()
|
||||
finish()
|
||||
}
|
||||
|
||||
// Submit the order items to the adapter
|
||||
productAdapter.submitList(sells.orderItems ?: emptyList())
|
||||
val sellsJson = intent.getStringExtra("sells_data")
|
||||
if (sellsJson != null) {
|
||||
try {
|
||||
val basicOrder = Gson().fromJson(sellsJson, OrdersItem::class.java)
|
||||
basicOrder.orderId.let {
|
||||
viewModel.getSellDetails(it)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("DetailSellsActivity", "Failed to parse order data", e)
|
||||
}
|
||||
} else {
|
||||
Log.e("DetailSellsActivity", "No order passed in intent")
|
||||
}
|
||||
|
||||
observeOrderDetails()
|
||||
}
|
||||
|
||||
private fun formatDate(dateStr: String?): String {
|
||||
private fun observeOrderDetails() {
|
||||
viewModel.sellDetails.observe(this) { order ->
|
||||
if (order != null) {
|
||||
sells = order
|
||||
showOrderDetails()
|
||||
} else {
|
||||
Log.e("DetailShipmentActivity", "❌ Failed to retrieve order details")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showOrderDetails() = with(binding) {
|
||||
sells?.let { sell ->
|
||||
tvOrderNumber.text = sell.orderId.toString()
|
||||
tvOrderCustomer.text = sell.username
|
||||
tvOrderDate.text = formatDate(sell.updatedAt.toString())
|
||||
tvOrderTotalProduct.text = "(${sell.orderItems?.size ?: 0} Barang)"
|
||||
tvOrderSubtotal.text = formatPrice(sell.totalAmount.toString())
|
||||
tvOrderShipPrice.text = formatPrice(sell.shipmentPrice.toString())
|
||||
tvOrderPrice.text = formatPrice(sell.totalAmount.toString())
|
||||
tvOrderRecipient.text = sell.recipient ?: "-"
|
||||
tvOrderRecipientNum.text = sell.receiptNum?.toString() ?: "-"
|
||||
|
||||
val cityId = sell.cityId?.toString()
|
||||
val provinceId = sell.provinceId?.toString()
|
||||
|
||||
if (cityId != null && provinceId != null) {
|
||||
val viewModelAddress: AddressViewModel by viewModels {
|
||||
BaseViewModelFactory {
|
||||
val apiService = ApiConfig.getApiService(sessionManager)
|
||||
val addressRepository = AddressRepository(apiService)
|
||||
AddressViewModel(addressRepository)
|
||||
}
|
||||
}
|
||||
|
||||
viewModelAddress.fetchCities(provinceId)
|
||||
viewModelAddress.fetchProvinces()
|
||||
|
||||
viewModelAddress.cities.observe(this@DetailShipmentActivity) { cities ->
|
||||
val cityName = cities.find { it.cityId == cityId }?.cityName
|
||||
viewModelAddress.provinces.observe(this@DetailShipmentActivity) { provinces ->
|
||||
val provinceName = provinces.find { it.provinceId == provinceId }?.provinceName
|
||||
|
||||
val fullAddress = listOfNotNull(
|
||||
sell.street,
|
||||
sell.subdistrict,
|
||||
cityName,
|
||||
provinceName
|
||||
).joinToString(", ")
|
||||
|
||||
tvOrderRecipientAddress.text = fullAddress
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tvOrderRecipientAddress.text = "-"
|
||||
}
|
||||
|
||||
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(dateStr ?: "")
|
||||
outputFormat.format(date!!)
|
||||
|
||||
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
|
||||
return String.format(Locale("id", "ID"), "Rp%,.0f", priceDouble)
|
||||
}
|
||||
}
|
@ -5,12 +5,15 @@ import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.alya.ecommerce_serang.data.api.dto.OrderItemsItem
|
||||
import com.alya.ecommerce_serang.data.api.dto.PaymentConfirmRequest
|
||||
import com.alya.ecommerce_serang.data.api.response.store.sells.Orders
|
||||
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
|
||||
import com.alya.ecommerce_serang.ui.order.history.HistoryViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SellsViewModel(private val repository: SellsRepository) : ViewModel() {
|
||||
@ -22,9 +25,28 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() {
|
||||
private val _sells = MutableLiveData<ViewState<List<OrdersItem>>>()
|
||||
val sells: LiveData<ViewState<List<OrdersItem>>> = _sells
|
||||
|
||||
private val _sellDetails = MutableLiveData<Orders?>()
|
||||
val sellDetails: LiveData<Orders?> get() = _sellDetails
|
||||
|
||||
private val _confirmPaymentStore = MutableLiveData<Result<PaymentConfirmationResponse>>()
|
||||
val confirmPaymentStore: LiveData<Result<PaymentConfirmationResponse>> = _confirmPaymentStore
|
||||
|
||||
// LiveData untuk OrderItems
|
||||
private val _orderItems = MutableLiveData<List<OrderItemsItem>?>()
|
||||
val orderItems: LiveData<List<OrderItemsItem>?> get() = _orderItems
|
||||
|
||||
private val _isLoading = MutableLiveData<Boolean>()
|
||||
val isLoading: LiveData<Boolean> = _isLoading
|
||||
|
||||
private val _message = MutableLiveData<String>()
|
||||
val message: LiveData<String> = _message
|
||||
|
||||
private val _isSuccess = MutableLiveData<Boolean>()
|
||||
val isSuccess: LiveData<Boolean> = _isSuccess
|
||||
|
||||
private val _error = MutableLiveData<String>()
|
||||
val error: LiveData<String> get() = _error
|
||||
|
||||
fun getSellList(status: String) {
|
||||
Log.d(TAG, "========== Starting getSellList ==========")
|
||||
Log.d(TAG, "Requested status: '$status'")
|
||||
@ -48,15 +70,15 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() {
|
||||
|
||||
// Log the entire result data structure
|
||||
Log.d(TAG, "Raw result data: ${result.data}")
|
||||
Log.d(TAG, "Result data class: ${result.data?.javaClass?.simpleName}")
|
||||
Log.d(TAG, "Result data class: ${result.data.javaClass.simpleName}")
|
||||
|
||||
val orders = result.data.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.d(TAG, "Orders list class: ${orders.javaClass.simpleName}")
|
||||
Log.d(TAG, "Orders count: ${orders.size}")
|
||||
|
||||
// Check if orders list is null or empty
|
||||
if (orders == null) {
|
||||
if (false) {
|
||||
Log.w(TAG, "⚠️ Orders list is NULL")
|
||||
} else if (orders.isEmpty()) {
|
||||
Log.w(TAG, "⚠️ Orders list is EMPTY")
|
||||
@ -67,17 +89,17 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() {
|
||||
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.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 ->
|
||||
order.orderItems?.let { items ->
|
||||
Log.d(TAG, " Order items:")
|
||||
items.forEachIndexed { itemIndex, item ->
|
||||
Log.d(TAG, " Item ${itemIndex + 1}: ${item?.productName} (Qty: ${item?.quantity})")
|
||||
@ -87,8 +109,8 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() {
|
||||
}
|
||||
|
||||
// Set the ViewState to Success
|
||||
_sells.value = ViewState.Success(orders ?: emptyList())
|
||||
Log.d(TAG, "✅ ViewState.Success set with ${orders?.size ?: 0} orders")
|
||||
_sells.value = ViewState.Success(orders)
|
||||
Log.d(TAG, "✅ ViewState.Success set with ${orders.size} orders")
|
||||
}
|
||||
|
||||
is Result.Error -> {
|
||||
@ -125,6 +147,28 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() {
|
||||
Log.d(TAG, "========== getSellList method completed ==========")
|
||||
}
|
||||
|
||||
fun getSellDetails(orderId: Int) {
|
||||
Log.d(TAG, "========== Starting getSellDetails ==========")
|
||||
Log.d(TAG, "Fetching details for order ID: $orderId")
|
||||
_isLoading.value = true
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val response = repository.getSellDetails(orderId)
|
||||
if (response != null) {
|
||||
_sellDetails.value = response.orders
|
||||
_orderItems.value = response.orders?.orderItems?.filterNotNull()
|
||||
} else {
|
||||
_error.value = "Gagal memuat detail pesanan"
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
_error.value = "Terjadi kesalahan: ${e.message}"
|
||||
Log.e(SellsViewModel.Companion.TAG, "Error fetching order details", e)
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateOrderStatus(orderId: Int?, status: String) {
|
||||
Log.d(TAG, "========== Starting updateOrderStatus ==========")
|
||||
Log.d(TAG, "Updating order status: orderId=$orderId, status='$status'")
|
||||
|
@ -46,8 +46,7 @@
|
||||
android:layout_marginStart="12dp"
|
||||
app:layout_constraintStart_toStartOf="@id/shape_payment_order_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:gravity="center">
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_order_sells_title"
|
||||
@ -70,7 +69,8 @@
|
||||
android:textAlignment="textEnd"
|
||||
android:textColor="@color/blue_500"
|
||||
android:clickable="true"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -377,19 +377,4 @@
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="bottom">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_confirm_payment"
|
||||
style="@style/button.large.active.long"
|
||||
android:text="Kirim Pesanan"
|
||||
android:layout_alignParentEnd="true"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
@ -2,6 +2,7 @@
|
||||
<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:fitsSystemWindows="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/white"
|
||||
|
@ -2,6 +2,7 @@
|
||||
<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:fitsSystemWindows="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/white"
|
||||
|
Reference in New Issue
Block a user