fix order wholesale

This commit is contained in:
shaulascr
2025-05-21 12:03:46 +07:00
parent b5e47050b9
commit 02b7d7559a
16 changed files with 513 additions and 136 deletions

View File

@ -9,3 +9,4 @@ data class CartItem (
@SerializedName("quantity")
val quantity: Int
)

View File

@ -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()
)

View File

@ -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
)

View File

@ -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
)

View File

@ -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,

View File

@ -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
)

View File

@ -12,4 +12,3 @@ data class AllProductResponse(
val products: List<ProductsItem>
)

View File

@ -1,5 +1,6 @@
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(
@ -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
)

View File

@ -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()) {

View File

@ -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,15 +255,25 @@ 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)) {
// 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
}
}
}
}
_totalPrice.value = total
}
@ -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()
}
}
}

View File

@ -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)
}

View File

@ -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"
}

View File

@ -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", "")
}
}

View File

@ -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,35 +331,62 @@ 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 (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()
}
}
}
btnIncrease.setOnClickListener {
if (currentQuantity < maxStock) {
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,7 +425,9 @@ class DetailProductActivity : AppCompatActivity() {
return
}
if (isWholesaleSelected) {
// Start checkout activity with buy now flow
//checkout klo grosiran
CheckoutActivity.startForBuyNow(
context = this,
storeId = productDetail.storeId,
@ -393,8 +436,23 @@ class DetailProductActivity : AppCompatActivity() {
productName = productDetail.productName,
productImage = productDetail.image,
quantity = currentQuantity,
price = productDetail.price.toDouble()
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(){

View File

@ -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"
@ -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"

View File

@ -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,28 +11,76 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:paddingHorizontal="8dp"
android:paddingTop="32dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:id="@+id/tv_active_wholesale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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"/>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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:textSize="18sp"
android:textStyle="bold"
android:paddingBottom="16dp" />
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="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"
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"
@ -39,20 +88,26 @@
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:text="1"
android:textSize="18sp" />
android:textSize="16sp" />
<Button
<ImageButton
android:id="@+id/btnIncrease"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+" />
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" />