diff --git a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/customer/product/ProductResponse.kt b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/customer/product/ProductResponse.kt index 1a389dd..efc26fc 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/data/api/response/customer/product/ProductResponse.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/data/api/response/customer/product/ProductResponse.kt @@ -78,13 +78,16 @@ data class Product( 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 ) + + +data class CartItemWholesaleInfo( + val cartItemId: Int, + val isWholesale: Boolean, + val wholesalePrice: Double? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt index 7d4782d..fdf0597 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartActivity.kt @@ -91,7 +91,6 @@ class CartActivity : AppCompatActivity() { adapter = storeAdapter } } - private fun setupListeners() { binding.cbSelectAll.setOnCheckedChangeListener { _, _ -> viewModel.toggleSelectAll() @@ -99,16 +98,20 @@ class CartActivity : AppCompatActivity() { binding.btnCheckout.setOnClickListener { if (viewModel.totalSelectedCount.value ?: 0 > 0) { - val selectedItems = viewModel.prepareCheckout() - if (selectedItems.isNotEmpty()) { - // Check if all items are from the same store - val storeId = viewModel.activeStoreId.value - if (storeId != null) { - // Start checkout with the prepared items - startCheckoutWithWholesaleInfo(selectedItems) - } else { - Toast.makeText(this, "Please select items from a single store only", Toast.LENGTH_SHORT).show() + if (viewModel.hasConsistentWholesaleStatus.value == true) { + val selectedItems = viewModel.prepareCheckout() + if (selectedItems.isNotEmpty()) { + // Check if all items are from the same store + val storeId = viewModel.activeStoreId.value + if (storeId != null) { + // Start checkout with the prepared items + startCheckoutWithWholesaleInfo(selectedItems) + } else { + Toast.makeText(this, "Please select items from a single store only", Toast.LENGTH_SHORT).show() + } } + } else { + Toast.makeText(this, "Tidak dapat checkout produk grosir dan retail sekaligus", Toast.LENGTH_LONG).show() } } else { Toast.makeText(this, "Pilih produk terlebih dahulu", Toast.LENGTH_SHORT).show() @@ -176,6 +179,30 @@ class CartActivity : AppCompatActivity() { viewModel.toggleSelectAll() } } + + viewModel.hasConsistentWholesaleStatus.observe(this) { isConsistent -> + if (!isConsistent && (viewModel.totalSelectedCount.value ?: 0) > 1) { + binding.btnCheckout.isEnabled = false + // Show an error message or indicator + binding.tvWholesaleWarning.visibility = View.VISIBLE + binding.tvWholesaleWarning.text = "Tidak dapat checkout produk grosir dan retail sekaligus" + } else { + binding.btnCheckout.isEnabled = true + binding.tvWholesaleWarning.visibility = View.GONE + } + } + + viewModel.cartItemWholesaleStatus.observe(this) { wholesaleStatusMap -> + viewModel.cartItemWholesalePrice.value?.let { wholesalePriceMap -> + storeAdapter.updateWholesaleStatus(wholesaleStatusMap, wholesalePriceMap) + } + } + + viewModel.cartItemWholesalePrice.observe(this) { wholesalePriceMap -> + viewModel.cartItemWholesaleStatus.value?.let { wholesaleStatusMap -> + storeAdapter.updateWholesaleStatus(wholesaleStatusMap, wholesalePriceMap) + } + } } private fun showEmptyState(isEmpty: Boolean) { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartViewModel.kt index 54917c4..2554cd1 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/cart/CartViewModel.kt @@ -49,6 +49,9 @@ class CartViewModel(private val repository: OrderRepository) : ViewModel() { private val _cartItemWholesalePrice = MutableLiveData>(mapOf()) val cartItemWholesalePrice: LiveData> = _cartItemWholesalePrice + private val _hasConsistentWholesaleStatus = MutableLiveData(true) + val hasConsistentWholesaleStatus: LiveData = _hasConsistentWholesaleStatus + fun getCart() { _isLoading.value = true _errorMessage.value = null @@ -379,4 +382,26 @@ class CartViewModel(private val repository: OrderRepository) : ViewModel() { calculateTotalPrice() } } + + private fun checkWholesaleConsistency() { + val selectedItemIds = _selectedItems.value ?: HashSet() + val wholesaleStatus = _cartItemWholesaleStatus.value ?: mapOf() + + if (selectedItemIds.isEmpty()) { + _hasConsistentWholesaleStatus.value = true + return + } + + // Get the wholesale status of the first selected item + val firstSelectedId = selectedItemIds.first() + val firstStatus = wholesaleStatus[firstSelectedId] ?: false + + // Check if all other selected items have the same wholesale status + val allSameStatus = selectedItemIds.all { itemId -> + val itemStatus = wholesaleStatus[itemId] ?: false + itemStatus == firstStatus + } + + _hasConsistentWholesaleStatus.value = allSameStatus + } } \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/cart/StoreAdapter.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/cart/StoreAdapter.kt index 6cfeb79..9460c03 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/cart/StoreAdapter.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/cart/StoreAdapter.kt @@ -28,6 +28,8 @@ class StoreAdapter( private var selectedItems = HashSet() private var selectedStores = HashSet() private var activeStoreId: Int? = null + private var wholesaleStatusMap: Map = mapOf() + private var wholesalePriceMap: Map = mapOf() companion object { private const val VIEW_TYPE_STORE = 0 @@ -70,6 +72,27 @@ class StoreAdapter( return count } + private fun isItemSelectable(cartItemId: Int): Boolean { + // If no items are selected, any item can be selected + if (selectedItems.isEmpty()) return true + + // Get wholesale status of this item + val thisItemWholesale = wholesaleStatusMap[cartItemId] ?: false + + // Get wholesale status of first selected item + val firstSelectedId = selectedItems.first() + val firstSelectedWholesale = wholesaleStatusMap[firstSelectedId] ?: false + + // Item can be selected if its wholesale status matches the first selected item + return thisItemWholesale == firstSelectedWholesale + } + + fun updateWholesaleStatus(wholesaleStatusMap: Map, wholesalePriceMap: Map) { + this.wholesaleStatusMap = wholesaleStatusMap + this.wholesalePriceMap = wholesalePriceMap + notifyDataSetChanged() + } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { VIEW_TYPE_STORE -> { @@ -100,11 +123,16 @@ class StoreAdapter( val cartItem = store.cartItems[itemIndex] val isSelected = selectedItems.contains(cartItem.cartItemId) val isEnabled = activeStoreId == null || activeStoreId == store.storeId + val isItemWholesale = wholesaleStatusMap[cartItem.cartItemId] ?: false + val wholesalePrice = wholesalePriceMap[cartItem.cartItemId] + val isSelectable = isItemSelectable(cartItem.cartItemId) holder.bind( cartItem, isSelected, - isEnabled, + isEnabled && isSelectable, + isItemWholesale, + wholesalePrice, { isChecked -> onItemCheckChanged(cartItem.cartItemId, store.storeId, isChecked) }, { quantity -> onItemQuantityChanged(cartItem.cartItemId, quantity) }, { onItemDeleted(cartItem.cartItemId) } @@ -158,20 +186,67 @@ class StoreAdapter( private val btnMinus: ImageButton = itemView.findViewById(R.id.btnMinus) private val tvQuantity: TextView = itemView.findViewById(R.id.tvQuantity) private val btnPlus: ImageButton = itemView.findViewById(R.id.btnPlus) + private val tvWholesaleIndicator : TextView = itemView.findViewById((R.id.tvWholesaleIndicator)) private val quantityController: ConstraintLayout = itemView.findViewById(R.id.quantityController) fun bind( cartItem: CartItemsItem, - isChecked: Boolean, + isSelected: Boolean, isEnabled: Boolean, + isWholesale: Boolean, + wholesalePrice: Double?, onCheckedChange: (Boolean) -> Unit, onQuantityChanged: (Int) -> Unit, onDelete: () -> Unit ) { + // Set product name tvProductName.text = cartItem.productName - tvPrice.text = formatCurrency(cartItem.price) + + // Set price based on wholesale status + if (isWholesale && wholesalePrice != null) { + tvPrice.text = formatCurrency(wholesalePrice.toInt()) + // Show wholesale indicator if available + tvWholesaleIndicator?.visibility = View.VISIBLE + tvWholesaleIndicator?.text = "Harga Grosir" + } else { + tvPrice.text = formatCurrency(cartItem.price) + tvWholesaleIndicator?.visibility = View.GONE + } + + // Set quantity tvQuantity.text = cartItem.quantity.toString() + // Visual indication for wholesale items +// if (isWholesale) { +// // You can add a background or border to indicate wholesale items +// // For example: +//// itemView.setBackgroundResource(R.drawable.bg_wholesale_item) +// // If you don't have this drawable, you can use a simple color tint instead: +// itemView.setBackgroundColor(ContextCompat.getColor(itemView.context, R.color.wholesale_item_bg)) +// } else { +// // Reset to default background +//// itemView.setBackgroundResource(R.drawable.bg_normal_item) +// // Or if you don't have this drawable: +// itemView.setBackgroundColor(ContextCompat.getColor(itemView.context, R.color.normal_item_bg)) +// } + + // Set checkbox state without triggering listener + cbItem.setOnCheckedChangeListener(null) + cbItem.isChecked = isSelected + cbItem.isEnabled = isEnabled + + // If not enabled, visually indicate this item can't be selected + if (!isEnabled) { + itemView.alpha = 0.5f + } else { + itemView.alpha = 1.0f + } + + // Set checkbox listener + cbItem.setOnCheckedChangeListener { _, isChecked -> + onCheckedChange(isChecked) + } + // Load product image Glide.with(itemView.context) .load("https://example.com/images/${cartItem.productId}.jpg") // Assume image URL based on product ID @@ -179,15 +254,6 @@ class StoreAdapter( .error(R.drawable.placeholder_image) .into(ivProduct) - // Set checkbox state without triggering listener - cbItem.setOnCheckedChangeListener(null) - cbItem.isChecked = isChecked - cbItem.isEnabled = isEnabled - - cbItem.setOnCheckedChangeListener { _, isChecked -> - onCheckedChange(isChecked) - } - // Quantity control btnMinus.setOnClickListener { val currentQty = tvQuantity.text.toString().toInt() diff --git a/app/src/main/res/drawable/btn_minus_24dp.xml b/app/src/main/res/drawable/btn_minus_24dp.xml new file mode 100644 index 0000000..f07a9ab --- /dev/null +++ b/app/src/main/res/drawable/btn_minus_24dp.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/layout/activity_cart.xml b/app/src/main/res/layout/activity_cart.xml index 22692f8..973c8a1 100644 --- a/app/src/main/res/layout/activity_cart.xml +++ b/app/src/main/res/layout/activity_cart.xml @@ -21,6 +21,16 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/header"/> + + + +