mirror of
https://github.com/shaulascr/ecommerce_serang.git
synced 2025-08-10 09:22:21 +00:00
fix order wholesale
This commit is contained in:
@ -9,3 +9,4 @@ data class CartItem (
|
||||
@SerializedName("quantity")
|
||||
val quantity: Int
|
||||
)
|
||||
|
||||
|
@ -12,5 +12,6 @@ data class CheckoutData(
|
||||
val sellerId: Int = 0,
|
||||
val quantity: Int = 1,
|
||||
val isBuyNow: Boolean = false,
|
||||
val cartItems: List<CartItemsItem> = emptyList()
|
||||
val cartItems: List<CartItemsItem> = emptyList(),
|
||||
val cartItemWholesaleMap: Map<Int, Boolean> = emptyMap()
|
||||
)
|
@ -25,5 +25,8 @@ data class OrderRequest (
|
||||
val cartItemId: List<Int>,
|
||||
|
||||
@SerializedName("ship_etd")
|
||||
val shipEtd: String
|
||||
)
|
||||
val shipEtd: String,
|
||||
|
||||
@SerializedName("is_reseller")
|
||||
val isReseller: Boolean
|
||||
)
|
@ -27,7 +27,10 @@ data class OrderRequestBuy (
|
||||
@SerializedName("quantity")
|
||||
val quantity : Int,
|
||||
|
||||
|
||||
@SerializedName("ship_etd")
|
||||
val shipEtd: String
|
||||
val shipEtd: String,
|
||||
|
||||
@SerializedName("is_reseller")
|
||||
val isReseller: Boolean
|
||||
|
||||
)
|
@ -11,6 +11,12 @@ data class ProductsItem(
|
||||
@field:SerializedName("image")
|
||||
val image: String,
|
||||
|
||||
@field:SerializedName("is_wholesale")
|
||||
val isWholesale: Boolean,
|
||||
|
||||
@field:SerializedName("sppirt")
|
||||
val sppirt: String? = null,
|
||||
|
||||
@field:SerializedName("rating")
|
||||
val rating: String,
|
||||
|
||||
@ -23,6 +29,9 @@ data class ProductsItem(
|
||||
@field:SerializedName("is_pre_order")
|
||||
val isPreOrder: Boolean,
|
||||
|
||||
@field:SerializedName("condition")
|
||||
val condition: String? = null,
|
||||
|
||||
@field:SerializedName("category_id")
|
||||
val categoryId: Int,
|
||||
|
||||
@ -32,6 +41,9 @@ data class ProductsItem(
|
||||
@field:SerializedName("name")
|
||||
val name: String,
|
||||
|
||||
@field:SerializedName("halal")
|
||||
val halal: String?= null,
|
||||
|
||||
@field:SerializedName("id")
|
||||
val id: Int,
|
||||
|
||||
|
@ -4,16 +4,16 @@ import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class CreateOrderResponse(
|
||||
|
||||
@field:SerializedName("shipping")
|
||||
@field:SerializedName("shipping")
|
||||
val shipping: Shipping,
|
||||
|
||||
@field:SerializedName("order_item")
|
||||
@field:SerializedName("order_item")
|
||||
val orderItem: List<OrderItemItem>,
|
||||
|
||||
@field:SerializedName("message")
|
||||
@field:SerializedName("message")
|
||||
val message: String,
|
||||
|
||||
@field:SerializedName("order")
|
||||
@field:SerializedName("order")
|
||||
val order: Order
|
||||
)
|
||||
|
||||
@ -47,34 +47,10 @@ data class Shipping(
|
||||
val status: String
|
||||
)
|
||||
|
||||
data class OrderItemItem(
|
||||
|
||||
@field:SerializedName("quantity")
|
||||
val quantity: Int,
|
||||
|
||||
@field:SerializedName("price")
|
||||
val price: String,
|
||||
|
||||
@field:SerializedName("subtotal")
|
||||
val subtotal: String,
|
||||
|
||||
@field:SerializedName("product_id")
|
||||
val productId: Int,
|
||||
|
||||
@field:SerializedName("id")
|
||||
val id: Int,
|
||||
|
||||
@field:SerializedName("order_id")
|
||||
val orderId: Int
|
||||
)
|
||||
|
||||
data class Order(
|
||||
|
||||
@field:SerializedName("payment_info_id")
|
||||
val paymentMethodId: Int,
|
||||
|
||||
@field:SerializedName("auto_completed_at")
|
||||
val autoCompletedAt: String? = null,
|
||||
val autoCompletedAt: String,
|
||||
|
||||
@field:SerializedName("updated_at")
|
||||
val updatedAt: String,
|
||||
@ -97,9 +73,33 @@ data class Order(
|
||||
@field:SerializedName("voucher_id")
|
||||
val voucherId: String? = null,
|
||||
|
||||
@field:SerializedName("payment_info_id")
|
||||
val paymentInfoId: Int,
|
||||
|
||||
@field:SerializedName("id")
|
||||
val id: Int,
|
||||
|
||||
@field:SerializedName("status")
|
||||
val status: String
|
||||
)
|
||||
|
||||
data class OrderItemItem(
|
||||
|
||||
@field:SerializedName("quantity")
|
||||
val quantity: Int,
|
||||
|
||||
@field:SerializedName("price")
|
||||
val price: String,
|
||||
|
||||
@field:SerializedName("subtotal")
|
||||
val subtotal: String,
|
||||
|
||||
@field:SerializedName("product_id")
|
||||
val productId: Int,
|
||||
|
||||
@field:SerializedName("id")
|
||||
val id: Int,
|
||||
|
||||
@field:SerializedName("order_id")
|
||||
val orderId: Int
|
||||
)
|
||||
|
@ -12,4 +12,3 @@ data class AllProductResponse(
|
||||
val products: List<ProductsItem>
|
||||
)
|
||||
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
package com.alya.ecommerce_serang.data.api.response.customer.product
|
||||
|
||||
import com.alya.ecommerce_serang.data.api.response.customer.cart.CartItemsItem
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class ProductResponse(
|
||||
|
||||
@field:SerializedName("product")
|
||||
@field:SerializedName("product")
|
||||
val product: Product,
|
||||
|
||||
@field:SerializedName("message")
|
||||
@field:SerializedName("message")
|
||||
val message: String
|
||||
)
|
||||
|
||||
@ -17,7 +18,13 @@ data class Product(
|
||||
val storeId: Int,
|
||||
|
||||
@field:SerializedName("image")
|
||||
val image: String? = null,
|
||||
val image: String,
|
||||
|
||||
@field:SerializedName("is_wholesale")
|
||||
val isWholesale: Boolean? = false,
|
||||
|
||||
@field:SerializedName("sppirt")
|
||||
val sppirt: String? = null,
|
||||
|
||||
@field:SerializedName("rating")
|
||||
val rating: String,
|
||||
@ -34,8 +41,8 @@ data class Product(
|
||||
@field:SerializedName("is_pre_order")
|
||||
val isPreOrder: Boolean,
|
||||
|
||||
@field:SerializedName("duration")
|
||||
val duration: Any?,
|
||||
@field:SerializedName("condition")
|
||||
val condition: String? = null,
|
||||
|
||||
@field:SerializedName("category_id")
|
||||
val categoryId: Int,
|
||||
@ -46,6 +53,15 @@ data class Product(
|
||||
@field:SerializedName("product_id")
|
||||
val productId: Int,
|
||||
|
||||
@field:SerializedName("wholesale_price")
|
||||
val wholesalePrice: String? = null,
|
||||
|
||||
@field:SerializedName("halal")
|
||||
val halal: String? = null,
|
||||
|
||||
@field:SerializedName("wholesale_min_item")
|
||||
val wholesaleMinItem: Int? = null,
|
||||
|
||||
@field:SerializedName("min_order")
|
||||
val minOrder: Int,
|
||||
|
||||
@ -56,5 +72,19 @@ data class Product(
|
||||
val stock: Int,
|
||||
|
||||
@field:SerializedName("product_category")
|
||||
val productCategory: String
|
||||
val productCategory: String,
|
||||
|
||||
@field:SerializedName("preorder_duration")
|
||||
val preorderDuration: String? = null
|
||||
)
|
||||
|
||||
data class CartItemWholesaleInfo(
|
||||
val cartItemId: Int,
|
||||
val isWholesale: Boolean,
|
||||
val wholesalePrice: Double? = null
|
||||
)
|
||||
|
||||
data class CartItemCheckoutInfo(
|
||||
val cartItem: CartItemsItem,
|
||||
val isWholesale: Boolean
|
||||
)
|
||||
|
@ -12,6 +12,7 @@ import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.alya.ecommerce_serang.R
|
||||
import com.alya.ecommerce_serang.data.api.response.customer.product.CartItemCheckoutInfo
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
|
||||
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
|
||||
import com.alya.ecommerce_serang.data.repository.OrderRepository
|
||||
@ -103,9 +104,8 @@ class CartActivity : AppCompatActivity() {
|
||||
// Check if all items are from the same store
|
||||
val storeId = viewModel.activeStoreId.value
|
||||
if (storeId != null) {
|
||||
// Get cart item ids to pass to checkout
|
||||
val cartItemIds = selectedItems.map { it.cartItemId }
|
||||
CheckoutActivity.startForCart(this, cartItemIds)
|
||||
// Start checkout with the prepared items
|
||||
startCheckoutWithWholesaleInfo(selectedItems)
|
||||
} else {
|
||||
Toast.makeText(this, "Please select items from a single store only", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
@ -122,6 +122,15 @@ class CartActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun startCheckoutWithWholesaleInfo(checkoutItems: List<CartItemCheckoutInfo>) {
|
||||
// Extract cart item IDs and wholesale status
|
||||
val cartItemIds = checkoutItems.map { it.cartItem.cartItemId }
|
||||
val wholesaleArray = checkoutItems.map { it.isWholesale }.toBooleanArray()
|
||||
|
||||
// Start checkout activity with the cart items and wholesale info
|
||||
CheckoutActivity.startForCart(this, cartItemIds, wholesaleArray)
|
||||
}
|
||||
|
||||
private fun observeViewModel() {
|
||||
viewModel.cartItems.observe(this) { cartItems ->
|
||||
if (cartItems.isNullOrEmpty()) {
|
||||
|
@ -1,12 +1,13 @@
|
||||
package com.alya.ecommerce_serang.ui.cart
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.alya.ecommerce_serang.data.api.dto.UpdateCart
|
||||
import com.alya.ecommerce_serang.data.api.response.customer.cart.CartItemsItem
|
||||
import com.alya.ecommerce_serang.data.api.response.customer.cart.DataItemCart
|
||||
import com.alya.ecommerce_serang.data.api.response.customer.product.CartItemCheckoutInfo
|
||||
import com.alya.ecommerce_serang.data.repository.OrderRepository
|
||||
import com.alya.ecommerce_serang.data.repository.Result
|
||||
import kotlinx.coroutines.launch
|
||||
@ -42,17 +43,26 @@ class CartViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
private val _allSelected = MutableLiveData<Boolean>(false)
|
||||
val allSelected: LiveData<Boolean> = _allSelected
|
||||
|
||||
private val _cartItemWholesaleStatus = MutableLiveData<Map<Int, Boolean>>(mapOf())
|
||||
val cartItemWholesaleStatus: LiveData<Map<Int, Boolean>> = _cartItemWholesaleStatus
|
||||
|
||||
private val _cartItemWholesalePrice = MutableLiveData<Map<Int, Double>>(mapOf())
|
||||
val cartItemWholesalePrice: LiveData<Map<Int, Double>> = _cartItemWholesalePrice
|
||||
|
||||
fun getCart() {
|
||||
_isLoading.value = true
|
||||
_errorMessage.value = null
|
||||
|
||||
viewModelScope.launch {
|
||||
when (val result = repository.getCart()) {
|
||||
is com.alya.ecommerce_serang.data.repository.Result.Success -> {
|
||||
is Result.Success -> {
|
||||
_cartItems.value = result.data
|
||||
_isLoading.value = false
|
||||
|
||||
// After loading cart items, check wholesale status
|
||||
checkWholesaleStatus()
|
||||
}
|
||||
is com.alya.ecommerce_serang.data.repository.Result.Error -> {
|
||||
is Result.Error -> {
|
||||
_errorMessage.value = result.exception.message
|
||||
_isLoading.value = false
|
||||
}
|
||||
@ -245,12 +255,22 @@ class CartViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
|
||||
private fun calculateTotalPrice() {
|
||||
val selectedItems = _selectedItems.value ?: HashSet()
|
||||
val wholesaleStatus = _cartItemWholesaleStatus.value ?: mapOf()
|
||||
val wholesalePrices = _cartItemWholesalePrice.value ?: mapOf()
|
||||
var total = 0
|
||||
|
||||
_cartItems.value?.forEach { dataItem ->
|
||||
dataItem.cartItems.forEach { cartItem ->
|
||||
if (selectedItems.contains(cartItem.cartItemId)) {
|
||||
total += cartItem.price * cartItem.quantity
|
||||
// Check if this item qualifies for wholesale pricing
|
||||
if (wholesaleStatus[cartItem.cartItemId] == true &&
|
||||
wholesalePrices.containsKey(cartItem.cartItemId)) {
|
||||
// Use wholesale price
|
||||
total += (wholesalePrices[cartItem.cartItemId]!!.toInt() * cartItem.quantity)
|
||||
} else {
|
||||
// Use regular price
|
||||
total += cartItem.price * cartItem.quantity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -281,15 +301,24 @@ class CartViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
_allSelected.value = isAllSelected
|
||||
}
|
||||
|
||||
fun prepareCheckout(): List<CartItemsItem> {
|
||||
fun prepareCheckout(): List<CartItemCheckoutInfo> {
|
||||
val selectedItemsIds = _selectedItems.value ?: HashSet()
|
||||
val result = mutableListOf<CartItemsItem>()
|
||||
val wholesaleStatus = _cartItemWholesaleStatus.value ?: mapOf()
|
||||
val result = mutableListOf<CartItemCheckoutInfo>()
|
||||
|
||||
if (activeStoreId != null){
|
||||
if (_activeStoreId.value != null) {
|
||||
_cartItems.value?.forEach { dataItem ->
|
||||
dataItem.cartItems.forEach { cartItem ->
|
||||
if (selectedItemsIds.contains(cartItem.cartItemId)) {
|
||||
result.add(cartItem)
|
||||
// Check wholesale status for this cart item
|
||||
val isWholesale = wholesaleStatus[cartItem.cartItemId] ?: false
|
||||
|
||||
result.add(
|
||||
CartItemCheckoutInfo(
|
||||
cartItem = cartItem,
|
||||
isWholesale = isWholesale
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -297,4 +326,57 @@ class CartViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun checkWholesaleStatus() {
|
||||
viewModelScope.launch {
|
||||
val cartItems = _cartItems.value ?: return@launch
|
||||
val wholesaleStatusMap = mutableMapOf<Int, Boolean>()
|
||||
val wholesalePriceMap = mutableMapOf<Int, Double>()
|
||||
|
||||
// Process each cart item
|
||||
for (store in cartItems) {
|
||||
for (item in store.cartItems) {
|
||||
try {
|
||||
// Fetch product details to get wholesale information
|
||||
val productResponse = repository.fetchProductDetail(item.productId)
|
||||
|
||||
if (productResponse != null) {
|
||||
val product = productResponse.product
|
||||
|
||||
// Check if wholesale is available and if quantity meets minimum
|
||||
val isWholesale = product.isWholesale == true &&
|
||||
product.wholesaleMinItem != null &&
|
||||
item.quantity >= product.wholesaleMinItem
|
||||
|
||||
wholesaleStatusMap[item.cartItemId] = isWholesale
|
||||
|
||||
// If wholesale applies, store the wholesale price
|
||||
if (isWholesale && product.wholesalePrice != null) {
|
||||
wholesalePriceMap[item.cartItemId] = product.wholesalePrice.toDouble()
|
||||
}
|
||||
|
||||
Log.d("CartViewModel", "Cart item ${item.cartItemId}: isWholesale=$isWholesale, min=${product.wholesaleMinItem}, qty=${item.quantity}")
|
||||
} else {
|
||||
// If product details couldn't be fetched, default to non-wholesale
|
||||
Log.e("CartViewModel", "Failed to fetch product details for ID: ${item.productId}")
|
||||
wholesaleStatusMap[item.cartItemId] = false
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// If we can't determine wholesale status, default to false
|
||||
Log.e("CartViewModel", "Exception checking wholesale status: ${e.message}")
|
||||
wholesaleStatusMap[item.cartItemId] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.d("CartViewModel", "Wholesale status map: $wholesaleStatusMap")
|
||||
Log.d("CartViewModel", "Wholesale price map: $wholesalePriceMap")
|
||||
|
||||
_cartItemWholesaleStatus.value = wholesaleStatusMap
|
||||
_cartItemWholesalePrice.value = wholesalePriceMap
|
||||
|
||||
// Recalculate total price to account for wholesale prices
|
||||
calculateTotalPrice()
|
||||
}
|
||||
}
|
||||
}
|
@ -77,6 +77,7 @@ class CheckoutActivity : AppCompatActivity() {
|
||||
private fun processIntentData() {
|
||||
// Determine if this is Buy Now or Cart checkout
|
||||
val isBuyNow = intent.hasExtra(EXTRA_PRODUCT_ID) && !intent.hasExtra(EXTRA_CART_ITEM_IDS)
|
||||
val isWholesaleNow = intent.getBooleanExtra(EXTRA_ISWHOLESALE, false)
|
||||
|
||||
if (isBuyNow) {
|
||||
// Process Buy Now flow
|
||||
@ -87,13 +88,23 @@ class CheckoutActivity : AppCompatActivity() {
|
||||
productName = intent.getStringExtra(EXTRA_PRODUCT_NAME),
|
||||
productImage = intent.getStringExtra(EXTRA_PRODUCT_IMAGE),
|
||||
quantity = intent.getIntExtra(EXTRA_QUANTITY, 1),
|
||||
price = intent.getDoubleExtra(EXTRA_PRICE, 0.0)
|
||||
price = intent.getDoubleExtra(EXTRA_PRICE, 0.0),
|
||||
isWholesale = isWholesaleNow
|
||||
)
|
||||
} else {
|
||||
// Process Cart checkout flow
|
||||
val cartItemIds = intent.getIntArrayExtra(EXTRA_CART_ITEM_IDS)?.toList() ?: emptyList()
|
||||
val isWholesaleArray = intent.getBooleanArrayExtra(EXTRA_CART_ITEM_WHOLESALE)
|
||||
|
||||
if (cartItemIds.isNotEmpty()) {
|
||||
viewModel.initializeFromCart(cartItemIds)
|
||||
// Create a map of cart item IDs to wholesale status if available
|
||||
val wholesaleMap = if (isWholesaleArray != null && isWholesaleArray.size == cartItemIds.size) {
|
||||
cartItemIds.mapIndexed { index, id -> id to isWholesaleArray[index] }.toMap()
|
||||
} else {
|
||||
emptyMap()
|
||||
}
|
||||
|
||||
viewModel.initializeFromCart(cartItemIds, wholesaleMap)
|
||||
} else {
|
||||
Toast.makeText(this, "Error: No cart items specified", Toast.LENGTH_SHORT).show()
|
||||
finish()
|
||||
@ -403,9 +414,12 @@ class CheckoutActivity : AppCompatActivity() {
|
||||
const val EXTRA_PRODUCT_IMAGE = "PRODUCT_IMAGE"
|
||||
const val EXTRA_QUANTITY = "QUANTITY"
|
||||
const val EXTRA_PRICE = "PRICE"
|
||||
const val EXTRA_ISWHOLESALE = "ISWHOLESALE"
|
||||
const val EXTRA_CART_ITEM_WHOLESALE = "EXTRA_CART_ITEM_WHOLESALE"
|
||||
|
||||
// Helper methods for starting activity
|
||||
|
||||
// TO DO: delete iswholesale klo ngga dibuthin
|
||||
// For Buy Now
|
||||
fun startForBuyNow(
|
||||
context: Context,
|
||||
@ -415,7 +429,8 @@ class CheckoutActivity : AppCompatActivity() {
|
||||
productName: String?,
|
||||
productImage: String?,
|
||||
quantity: Int,
|
||||
price: Double
|
||||
price: Double,
|
||||
isWholesale: Boolean
|
||||
) {
|
||||
val intent = Intent(context, CheckoutActivity::class.java).apply {
|
||||
putExtra(EXTRA_STORE_ID, storeId)
|
||||
@ -425,6 +440,7 @@ class CheckoutActivity : AppCompatActivity() {
|
||||
putExtra(EXTRA_PRODUCT_IMAGE, productImage)
|
||||
putExtra(EXTRA_QUANTITY, quantity)
|
||||
putExtra(EXTRA_PRICE, price)
|
||||
putExtra(EXTRA_ISWHOLESALE, isWholesale)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
@ -432,10 +448,14 @@ class CheckoutActivity : AppCompatActivity() {
|
||||
// For Cart checkout
|
||||
fun startForCart(
|
||||
context: Context,
|
||||
cartItemIds: List<Int>
|
||||
cartItemIds: List<Int>,
|
||||
isWholesaleArray: BooleanArray? = null
|
||||
) {
|
||||
val intent = Intent(context, CheckoutActivity::class.java).apply {
|
||||
putExtra(EXTRA_CART_ITEM_IDS, cartItemIds.toIntArray())
|
||||
if (isWholesaleArray != null) {
|
||||
putExtra(EXTRA_CART_ITEM_WHOLESALE, isWholesaleArray)
|
||||
}
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
private val _orderCreated = MutableLiveData<Boolean>()
|
||||
val orderCreated: LiveData<Boolean> = _orderCreated
|
||||
|
||||
|
||||
|
||||
// Initialize "Buy Now" checkout
|
||||
fun initializeBuyNow(
|
||||
storeId: Int,
|
||||
@ -48,7 +50,8 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
productName: String?,
|
||||
productImage: String?,
|
||||
quantity: Int,
|
||||
price: Double
|
||||
price: Double,
|
||||
isWholesale: Boolean
|
||||
) {
|
||||
viewModelScope.launch {
|
||||
_isLoading.value = true
|
||||
@ -64,7 +67,8 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
isNego = false, // Default value
|
||||
productId = productId,
|
||||
quantity = quantity,
|
||||
shipEtd = ""
|
||||
shipEtd = "",
|
||||
isReseller = isWholesale
|
||||
)
|
||||
|
||||
// Create checkout data
|
||||
@ -89,7 +93,7 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
}
|
||||
|
||||
// Initialize checkout from cart
|
||||
fun initializeFromCart(cartItemIds: List<Int>) {
|
||||
fun initializeFromCart(cartItemIds: List<Int>, isWholesaleMap: Map<Int, Boolean> = emptyMap()) {
|
||||
viewModelScope.launch {
|
||||
_isLoading.value = true
|
||||
|
||||
@ -112,20 +116,18 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
}
|
||||
|
||||
if (matchingItems.isNotEmpty() && storeData != null) {
|
||||
if (matchingItems.size != cartItemIds.size) {
|
||||
Log.w(TAG, "Not all requested cart items were found. Found ${matchingItems.size} out of ${cartItemIds.size}")
|
||||
// Consider showing a warning or adjusting the list
|
||||
}
|
||||
// Create initial OrderRequest object
|
||||
val orderRequest = OrderRequest(
|
||||
addressId = 0, // Will be set when user selects address
|
||||
paymentMethodId = 0, // Will be set when user selects payment
|
||||
shipPrice = 0, // Will be set when user selects shipping
|
||||
addressId = 0,
|
||||
paymentMethodId = 0,
|
||||
shipPrice = 0,
|
||||
shipName = "",
|
||||
shipService = "",
|
||||
isNego = false,
|
||||
cartItemId = cartItemIds,
|
||||
shipEtd = ""
|
||||
shipEtd = "",
|
||||
// Add a list tracking which items are wholesale
|
||||
isReseller = isWholesaleMap.any { it.value } // Set true if any item is wholesale
|
||||
)
|
||||
|
||||
// Create checkout data
|
||||
@ -135,9 +137,9 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
sellerName = storeData.storeName,
|
||||
sellerId = storeData.storeId,
|
||||
isBuyNow = false,
|
||||
cartItems = matchingItems
|
||||
cartItems = matchingItems,
|
||||
cartItemWholesaleMap = isWholesaleMap // Store the wholesale map
|
||||
)
|
||||
Log.d(TAG, "Setting sellerId to: ${storeData.storeId}")
|
||||
|
||||
calculateSubtotal()
|
||||
calculateTotal()
|
||||
@ -148,7 +150,6 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
_errorMessage.value = "Failed to fetch cart items: ${cartResult.exception.message}"
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error initializing cart checkout", e)
|
||||
_errorMessage.value = "Error: ${e.message}"
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
@ -404,6 +405,8 @@ class CheckoutViewModel(private val repository: OrderRepository) : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
companion object {
|
||||
private const val TAG = "CheckoutViewModel"
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.alya.ecommerce_serang.R
|
||||
import com.alya.ecommerce_serang.data.api.response.customer.order.OrderListItemsItem
|
||||
import com.bumptech.glide.Glide
|
||||
import java.text.NumberFormat
|
||||
import java.util.Locale
|
||||
|
||||
class DetailOrderItemsAdapter : RecyclerView.Adapter<DetailOrderItemsAdapter.DetailOrderItemViewHolder>() {
|
||||
|
||||
@ -46,9 +48,16 @@ class DetailOrderItemsAdapter : RecyclerView.Adapter<DetailOrderItemsAdapter.Det
|
||||
.error(R.drawable.placeholder_image)
|
||||
.into(ivProduct)
|
||||
|
||||
val newPrice = formatCurrency(item.price.toDouble())
|
||||
|
||||
tvProductName.text = item.productName
|
||||
tvQuantity.text = "${item.quantity} buah"
|
||||
tvPrice.text = "Rp${item.price}"
|
||||
tvPrice.text = "Rp${newPrice}"
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatCurrency(amount: Double): String {
|
||||
val formatter = NumberFormat.getCurrencyInstance(Locale("in", "ID"))
|
||||
return formatter.format(amount).replace(",00", "")
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ import android.widget.Toast
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.SwitchCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
@ -46,6 +47,9 @@ class DetailProductActivity : AppCompatActivity() {
|
||||
private var productAdapter: HorizontalProductAdapter? = null
|
||||
private var reviewsAdapter: ReviewsAdapter? = null
|
||||
private var currentQuantity = 1
|
||||
private var isWholesaleAvailable: Boolean = false
|
||||
private var isWholesaleSelected: Boolean = false
|
||||
private var minOrder: Int = 0
|
||||
|
||||
private val viewModel: ProductUserViewModel by viewModels {
|
||||
BaseViewModelFactory {
|
||||
@ -194,17 +198,7 @@ class DetailProductActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
binding.btnBuyNow.setOnClickListener {
|
||||
viewModel.productDetail.value?.productId?.let { id ->
|
||||
showBuyNowPopup(id)
|
||||
}
|
||||
}
|
||||
|
||||
binding.btnAddToCart.setOnClickListener {
|
||||
viewModel.productDetail.value?.productId?.let { id ->
|
||||
showAddToCartPopup(id)
|
||||
}
|
||||
}
|
||||
|
||||
val searchContainerView = binding.searchContainer
|
||||
searchContainerView.btnCart.setOnClickListener{
|
||||
@ -221,19 +215,41 @@ class DetailProductActivity : AppCompatActivity() {
|
||||
|
||||
private fun updateUI(product: Product){
|
||||
binding.tvProductName.text = product.productName
|
||||
binding.tvPrice.text = formatCurrency(product.price.toDouble())
|
||||
binding.tvSold.text = product.totalSold.toString()
|
||||
binding.tvPrice.text = "Rp${formatCurrency(product.price.toDouble())}"
|
||||
binding.tvSold.text = "Terjual ${product.totalSold} buah"
|
||||
binding.tvRating.text = product.rating
|
||||
binding.tvWeight.text = product.weight.toString()
|
||||
binding.tvStock.text = product.stock.toString()
|
||||
binding.tvWeight.text = "${product.weight} gram"
|
||||
binding.tvStock.text = "${product.stock} buah"
|
||||
binding.tvCategory.text = product.productCategory
|
||||
binding.tvDescription.text = product.description
|
||||
|
||||
minOrder = product.wholesaleMinItem ?: 1
|
||||
isWholesaleAvailable = product.isWholesale ?: false
|
||||
isWholesaleSelected = false // Default to regular pricing
|
||||
if (isWholesaleAvailable) {
|
||||
binding.containerWholesale.visibility = View.VISIBLE
|
||||
binding.tvPriceWholesale.text = "Rp${formatCurrency(product.wholesalePrice!!.toDouble())}"
|
||||
binding.descMinOrder.text = "Minimal pembelian ${minOrder}"
|
||||
} else {
|
||||
binding.containerWholesale.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.btnChat.setOnClickListener{
|
||||
navigateToChat()
|
||||
}
|
||||
|
||||
binding.btnBuyNow.setOnClickListener {
|
||||
viewModel.productDetail.value?.productId?.let { id ->
|
||||
showBuyNowPopup(id)
|
||||
}
|
||||
}
|
||||
|
||||
binding.btnAddToCart.setOnClickListener {
|
||||
viewModel.productDetail.value?.productId?.let { id ->
|
||||
showAddToCartPopup(id)
|
||||
}
|
||||
}
|
||||
|
||||
val fullImageUrl = when (val img = product.image) {
|
||||
is String -> {
|
||||
if (img.startsWith("/")) BASE_URL + img.substring(1) else img
|
||||
@ -315,26 +331,53 @@ class DetailProductActivity : AppCompatActivity() {
|
||||
val view = layoutInflater.inflate(R.layout.dialog_count_buy, null)
|
||||
bottomSheetDialog.setContentView(view)
|
||||
|
||||
val btnDecrease = view.findViewById<Button>(R.id.btnDecrease)
|
||||
val btnIncrease = view.findViewById<Button>(R.id.btnIncrease)
|
||||
val btnDecrease = view.findViewById<ImageButton>(R.id.btnDecrease)
|
||||
val btnIncrease = view.findViewById<ImageButton>(R.id.btnIncrease)
|
||||
|
||||
val tvQuantity = view.findViewById<TextView>(R.id.tvQuantity)
|
||||
val btnBuyNow = view.findViewById<Button>(R.id.btnBuyNow)
|
||||
val btnClose = view.findViewById<ImageButton>(R.id.btnCloseDialog)
|
||||
|
||||
// Set button text based on action
|
||||
val switchWholesale = view.findViewById<SwitchCompat>(R.id.switch_price)
|
||||
|
||||
if (!isBuyNow) {
|
||||
btnBuyNow.setText(R.string.add_to_cart)
|
||||
}
|
||||
|
||||
currentQuantity = 1
|
||||
switchWholesale.isEnabled = isWholesaleAvailable
|
||||
switchWholesale.isChecked = isWholesaleSelected
|
||||
|
||||
// Set initial quantity based on current selection
|
||||
currentQuantity = if (isWholesaleSelected) minOrder else 1
|
||||
tvQuantity.text = currentQuantity.toString()
|
||||
|
||||
switchWholesale.setOnCheckedChangeListener { _, isChecked ->
|
||||
isWholesaleSelected = isChecked
|
||||
|
||||
// Reset quantity when switching between retail and wholesale
|
||||
if (isChecked) {
|
||||
currentQuantity = minOrder
|
||||
} else {
|
||||
currentQuantity = 1
|
||||
}
|
||||
tvQuantity.text = currentQuantity.toString()
|
||||
}
|
||||
|
||||
val maxStock = viewModel.productDetail.value?.stock ?: 1
|
||||
|
||||
btnDecrease.setOnClickListener {
|
||||
if (currentQuantity > 1) {
|
||||
currentQuantity--
|
||||
tvQuantity.text = currentQuantity.toString()
|
||||
if (isWholesaleSelected) {
|
||||
if (currentQuantity > minOrder) {
|
||||
currentQuantity--
|
||||
tvQuantity.text = currentQuantity.toString()
|
||||
} else {
|
||||
Toast.makeText(this, "Sudah mencapai jumlah minimum", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} else {
|
||||
if (currentQuantity > 1) {
|
||||
currentQuantity--
|
||||
tvQuantity.text = currentQuantity.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,7 +386,7 @@ class DetailProductActivity : AppCompatActivity() {
|
||||
currentQuantity++
|
||||
tvQuantity.text = currentQuantity.toString()
|
||||
} else {
|
||||
Toast.makeText(this, "Maximum stock reached", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, "Sudah mencapai jumlah maksimum", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,10 +394,8 @@ class DetailProductActivity : AppCompatActivity() {
|
||||
bottomSheetDialog.dismiss()
|
||||
|
||||
if (isBuyNow) {
|
||||
// If it's Buy Now, navigate directly to checkout without adding to cart
|
||||
navigateToCheckout()
|
||||
} else {
|
||||
// If it's Add to Cart, add the item to the cart
|
||||
val cartItem = CartItem(
|
||||
productId = productId,
|
||||
quantity = currentQuantity
|
||||
@ -384,17 +425,34 @@ class DetailProductActivity : AppCompatActivity() {
|
||||
return
|
||||
}
|
||||
|
||||
// Start checkout activity with buy now flow
|
||||
CheckoutActivity.startForBuyNow(
|
||||
context = this,
|
||||
storeId = productDetail.storeId,
|
||||
storeName = storeDetail.data.storeName,
|
||||
productId = productDetail.productId,
|
||||
productName = productDetail.productName,
|
||||
productImage = productDetail.image,
|
||||
quantity = currentQuantity,
|
||||
price = productDetail.price.toDouble()
|
||||
)
|
||||
if (isWholesaleSelected) {
|
||||
// Start checkout activity with buy now flow
|
||||
//checkout klo grosiran
|
||||
CheckoutActivity.startForBuyNow(
|
||||
context = this,
|
||||
storeId = productDetail.storeId,
|
||||
storeName = storeDetail.data.storeName,
|
||||
productId = productDetail.productId,
|
||||
productName = productDetail.productName,
|
||||
productImage = productDetail.image,
|
||||
quantity = currentQuantity,
|
||||
price = productDetail.wholesalePrice!!.toDouble(),
|
||||
isWholesale = true
|
||||
)
|
||||
} else {
|
||||
//checkout klo direct buy normal price
|
||||
CheckoutActivity.startForBuyNow(
|
||||
context = this,
|
||||
storeId = productDetail.storeId,
|
||||
storeName = storeDetail.data.storeName,
|
||||
productId = productDetail.productId,
|
||||
productName = productDetail.productName,
|
||||
productImage = productDetail.image,
|
||||
quantity = currentQuantity,
|
||||
price = productDetail.price.toDouble(),
|
||||
isWholesale = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToChat(){
|
||||
|
@ -37,6 +37,49 @@
|
||||
android:contentDescription="@string/product_image"
|
||||
tools:src="@drawable/placeholder_image" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/container_wholesale"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:backgroundTint="@color/blue_50"
|
||||
android:visibility="gone"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:fontFamily="@font/dmsans_semibold"
|
||||
android:text="Harga Grosir"/>
|
||||
<TextView
|
||||
android:id="@+id/tvPriceWholesale"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/blue_500"
|
||||
android:text="Rp50.000"
|
||||
android:fontFamily="@font/dmsans_semibold"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/desc_min_order"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fontFamily="@font/dmsans_mediumitalic"
|
||||
android:textColor="@color/black_300"
|
||||
android:text="Minimal pembelian 10 buah"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Product Price and Name -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
@ -58,6 +101,50 @@
|
||||
android:textStyle="bold"
|
||||
tools:text="Rp65.000" />
|
||||
|
||||
<!-- <androidx.cardview.widget.CardView-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:backgroundTint="@color/blue_50"-->
|
||||
<!-- app:cardElevation="0dp">-->
|
||||
|
||||
<!-- <LinearLayout-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:paddingStart="16dp"-->
|
||||
<!-- android:paddingVertical="4dp"-->
|
||||
<!-- android:orientation="vertical">-->
|
||||
<!-- <LinearLayout-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:orientation="horizontal">-->
|
||||
<!-- <TextView-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginEnd="8dp"-->
|
||||
<!-- android:fontFamily="@font/dmsans_semibold"-->
|
||||
<!-- android:text="Harga Grosir"/>-->
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/tvPriceWholesale"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:textColor="@color/blue_500"-->
|
||||
<!-- android:text="Rp50.000"-->
|
||||
<!-- android:fontFamily="@font/dmsans_semibold"/>-->
|
||||
<!-- </LinearLayout>-->
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/desc_min_order"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="match_parent"-->
|
||||
<!-- android:fontFamily="@font/dmsans_mediumitalic"-->
|
||||
<!-- android:textColor="@color/black_300"-->
|
||||
<!-- android:text="Minimal pembelian 10 buah"/>-->
|
||||
<!-- </LinearLayout>-->
|
||||
|
||||
|
||||
<!-- </androidx.cardview.widget.CardView>-->
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvProductName"
|
||||
android:layout_width="wrap_content"
|
||||
@ -67,6 +154,7 @@
|
||||
android:textSize="16sp"
|
||||
tools:text="Keripik Ikan Tenggiri" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -91,7 +179,7 @@
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:contentDescription="@string/rating"
|
||||
android:src="@drawable/baseline_star_24"/>
|
||||
android:src="@drawable/baseline_star_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvRating"
|
||||
@ -103,10 +191,14 @@
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Buyer Reviews Section -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
|
@ -2,6 +2,7 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="@drawable/bg_popup_count"
|
||||
android:padding="16dp">
|
||||
|
||||
@ -10,49 +11,103 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingTop="32dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvQuantityTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Jumlah Produk"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingBottom="16dp" />
|
||||
|
||||
<LinearLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnDecrease"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="-" />
|
||||
|
||||
android:gravity="center">
|
||||
<TextView
|
||||
android:id="@+id/tvQuantity"
|
||||
android:id="@+id/tv_active_wholesale"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:text="1"
|
||||
android:textSize="18sp" />
|
||||
android:text="Beli Harga Grosir"
|
||||
android:textSize="16sp"
|
||||
android:fontFamily="@font/dmsans_semibold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnIncrease"
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/switch_price"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="+" />
|
||||
</LinearLayout>
|
||||
android:padding="4dp"
|
||||
android:buttonTint="@color/blue_500"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Minimal pembelian 10 buah untuk harga grosir"
|
||||
android:fontFamily="@font/dmsans_mediumitalic"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/black_300"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/container_count"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center">
|
||||
<TextView
|
||||
android:id="@+id/tvQuantityTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Jumlah Produk"
|
||||
android:fontFamily="@font/dmsans_semibold"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="4dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnDecrease"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:background="@drawable/bg_button_filled"
|
||||
android:src="@drawable/baseline_add_24"
|
||||
app:tint="@color/white"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvQuantity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:text="1"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnIncrease"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:background="@drawable/bg_button_filled"
|
||||
android:src="@drawable/baseline_add_24"
|
||||
app:tint="@color/white" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnBuyNow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Beli Sekarang"
|
||||
android:fontFamily="@font/dmsans_semibold"
|
||||
android:layout_marginTop="24dp"
|
||||
android:backgroundTint="@color/blue_500"
|
||||
android:textColor="@android:color/white" />
|
||||
|
Reference in New Issue
Block a user