Cart Screen
Screen
Step 1: layouts
Cart list free-delivery card और price summary के साथ एक NestedScrollView में है, nestedScrollingEnabled="false" के साथ ताकि सब एक page की तरह scroll हो। Total और Checkout button नीचे fixed हैं।
<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:id="@+id/content"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/bottom_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="8dp">
<!-- Free delivery progress -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:background="@drawable/bg_offer_card"
android:orientation="vertical"
android:padding="12dp">
<TextView
android:id="@+id/free_delivery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:textColor="@color/text_primary"
android:textStyle="bold"
app:drawableStartCompat="@drawable/ic_truck"
app:drawableTint="@color/brand"
tools:text="Add ₹120 more for FREE delivery" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/free_delivery_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:max="100"
app:trackCornerRadius="4dp"
app:trackThickness="6dp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:nestedScrollingEnabled="false"
tools:itemCount="2"
tools:listitem="@layout/item_cart" />
<include
android:id="@+id/summary"
layout="@layout/layout_price_summary" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/updating"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/bottom_bar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/bg_bottom_bar"
android:elevation="8dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/text_primary"
android:textSize="20sp"
android:textStyle="bold"
tools:text="₹2,337" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/total_amount"
android:textColor="@color/text_secondary"
android:textSize="12sp" />
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/checkout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="@color/accent"
android:paddingStart="32dp"
android:paddingEnd="32dp"
android:text="@string/checkout"
android:textColor="@android:color/white" />
</LinearLayout>
<include
android:id="@+id/state"
layout="@layout/layout_state" />
</androidx.constraintlayout.widget.ConstraintLayout><?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView 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:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="6dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="12dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/image"
android:layout_width="88dp"
android:layout_height="88dp"
android:contentDescription="@string/product_image"
android:scaleType="centerCrop"
app:shapeAppearanceOverlay="@style/ShapeAppearance.KartEasy.Rounded" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:textColor="@color/text_primary"
tools:text="Smart Watch Pro" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:baselineAligned="true"
android:orientation="horizontal">
<TextView
android:id="@+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.KartEasy.Price"
tools:text="₹1,899" />
<TextView
android:id="@+id/mrp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textColor="@color/text_secondary"
android:textSize="12sp"
tools:text="₹4,999" />
</LinearLayout>
<TextView
android:id="@+id/warning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:textColor="@color/sale"
android:textSize="12sp"
android:textStyle="bold"
android:visibility="gone"
tools:text="Out of stock" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/minus"
style="@style/Widget.KartEasy.QtyButton"
android:layout_width="36dp"
android:layout_height="36dp"
android:contentDescription="@string/decrease"
android:text="−" />
<TextView
android:id="@+id/qty"
android:layout_width="36dp"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/text_primary"
android:textStyle="bold"
tools:text="2" />
<com.google.android.material.button.MaterialButton
android:id="@+id/plus"
style="@style/Widget.KartEasy.QtyButton"
android:layout_width="36dp"
android:layout_height="36dp"
android:contentDescription="@string/increase"
android:text="+" />
<TextView
android:id="@+id/line_total"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:textColor="@color/text_secondary"
android:textSize="13sp"
tools:text="Total: ₹3,798" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="10dp"
android:background="@color/divider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/save"
style="@style/Widget.Material3.Button.TextButton.Icon"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/save_for_later"
app:icon="@drawable/ic_heart_outline" />
<com.google.android.material.button.MaterialButton
android:id="@+id/remove"
style="@style/Widget.Material3.Button.TextButton.Icon"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/remove"
android:textColor="@color/sale"
app:icon="@drawable/ic_delete"
app:iconTint="@color/sale" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>Step 2: shared price summary
Cart और Checkout एक ही price box दिखाते हैं। यह एक layout है जो दोनों screens में include होता है, और एक extension function LayoutPriceSummaryBinding.bind(cart) उसे भरता है — "Price (3 items)" के लिए plurals और coupon row सिर्फ coupon लगने पर।
<?xml version="1.0" encoding="utf-8"?>
<!-- Price details card. Filled by PriceSummary.kt: binding.summary.bind(cart) -->
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
style="@style/KartEasy.CardTitle"
android:text="@string/price_details" />
<LinearLayout style="@style/KartEasy.SummaryRow">
<TextView
android:id="@+id/items_label"
style="@style/KartEasy.SummaryLabel"
tools:text="Price (3 items)" />
<TextView
android:id="@+id/mrp_value"
style="@style/KartEasy.SummaryValue"
tools:text="₹5,997" />
</LinearLayout>
<LinearLayout style="@style/KartEasy.SummaryRow">
<TextView
style="@style/KartEasy.SummaryLabel"
android:text="@string/product_discount" />
<TextView
android:id="@+id/product_discount_value"
style="@style/KartEasy.SummaryValue"
android:textColor="@color/success"
tools:text="− ₹3,400" />
</LinearLayout>
<LinearLayout
android:id="@+id/coupon_row"
style="@style/KartEasy.SummaryRow"
android:visibility="gone">
<TextView
android:id="@+id/coupon_label"
style="@style/KartEasy.SummaryLabel"
tools:text="Coupon (SAVE10)" />
<TextView
android:id="@+id/coupon_value"
style="@style/KartEasy.SummaryValue"
android:textColor="@color/success"
tools:text="− ₹259.70" />
</LinearLayout>
<LinearLayout style="@style/KartEasy.SummaryRow">
<TextView
style="@style/KartEasy.SummaryLabel"
android:text="@string/delivery_charges" />
<TextView
android:id="@+id/delivery_value"
style="@style/KartEasy.SummaryValue"
tools:text="FREE" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@color/divider" />
<LinearLayout style="@style/KartEasy.SummaryRow">
<TextView
style="@style/KartEasy.SummaryLabel"
android:text="@string/total_amount"
android:textColor="@color/text_primary"
android:textStyle="bold" />
<TextView
android:id="@+id/total_value"
style="@style/KartEasy.SummaryValue"
android:textStyle="bold"
tools:text="₹2,337.30" />
</LinearLayout>
<TextView
android:id="@+id/savings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@color/success"
android:textStyle="bold"
tools:text="You save ₹3,659.70 on this order" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>package com.codingeasily.karteasy.ui.cart
import com.codingeasily.karteasy.R
import com.codingeasily.karteasy.data.model.Cart
import com.codingeasily.karteasy.databinding.LayoutPriceSummaryBinding
import com.codingeasily.karteasy.util.Format
import com.codingeasily.karteasy.util.visibleIf
/** Fills layout_price_summary.xml. Used by both Cart and Checkout. */
fun LayoutPriceSummaryBinding.bind(cart: Cart) {
val ctx = root.context
itemsLabel.text = ctx.resources.getQuantityString(R.plurals.price_items, cart.itemCount, cart.itemCount)
mrpValue.text = Format.price(cart.mrpTotal)
productDiscountValue.text = ctx.getString(R.string.minus_amount, Format.price(cart.mrpTotal - cart.subtotal))
couponRow.visibleIf(cart.discount > 0)
couponLabel.text = ctx.getString(R.string.coupon_label, cart.couponCode ?: "")
couponValue.text = ctx.getString(R.string.minus_amount, Format.price(cart.discount))
deliveryValue.text = if (cart.deliveryFee > 0) Format.price(cart.deliveryFee) else ctx.getString(R.string.free)
totalValue.text = Format.price(cart.total)
savings.visibleIf(cart.youSave > 0)
savings.text = ctx.getString(R.string.you_save, Format.price(cart.youSave))
}Step 3: CartAdapter
Minus button 1 पर disabled (वहाँ Remove use करें), plus button stock या 10 पर। Unavailable items 60% fade होते हैं और red warning दिखाते हैं।
package com.codingeasily.karteasy.ui.cart
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.codingeasily.karteasy.R
import com.codingeasily.karteasy.data.model.CartItem
import com.codingeasily.karteasy.databinding.ItemCartBinding
import com.codingeasily.karteasy.util.Format
import com.codingeasily.karteasy.util.load
import com.codingeasily.karteasy.util.strike
import com.codingeasily.karteasy.util.visibleIf
class CartAdapter(
private val onQty: (CartItem, Int) -> Unit,
private val onRemove: (CartItem) -> Unit,
private val onSave: (CartItem) -> Unit,
private val onOpen: (CartItem) -> Unit
) : ListAdapter<CartItem, CartAdapter.Holder>(DIFF) {
inner class Holder(val b: ItemCartBinding) : RecyclerView.ViewHolder(b.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
Holder(ItemCartBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun onBindViewHolder(holder: Holder, position: Int) {
val item = getItem(position)
val b = holder.b
val ctx = b.root.context
b.image.load(item.image)
b.name.text = item.name
b.price.text = Format.price(item.price)
b.mrp.strike(Format.price(item.mrp))
b.mrp.visibleIf(item.mrp > item.price)
b.qty.text = item.qty.toString()
b.lineTotal.text = ctx.getString(R.string.line_total, Format.price(item.lineTotal))
b.minus.isEnabled = item.qty > 1
b.plus.isEnabled = item.qty < minOf(10, item.stock)
b.warning.visibleIf(!item.available)
b.warning.text = if (item.stock <= 0) ctx.getString(R.string.out_of_stock)
else ctx.getString(R.string.only_left, item.stock)
b.root.alpha = if (item.available) 1f else 0.6f
b.minus.setOnClickListener { onQty(item, -1) }
b.plus.setOnClickListener { onQty(item, +1) }
b.remove.setOnClickListener { onRemove(item) }
b.save.setOnClickListener { onSave(item) }
b.image.setOnClickListener { onOpen(item) }
b.name.setOnClickListener { onOpen(item) }
}
companion object {
val DIFF = object : DiffUtil.ItemCallback<CartItem>() {
override fun areItemsTheSame(a: CartItem, b: CartItem) = a.productId == b.productId
override fun areContentsTheSame(a: CartItem, b: CartItem) = a == b
}
}
}Step 4: CartViewModel
हर action (− / +, remove, undo, wishlist में move) update() से जाता है: request चलते समय taps ignore करता है (busy) और पूरा cart server के जवाब से बदल देता है। Screen कभी ऐसे totals नहीं दिखा सकती जो server ने calculate न किए हों।
package com.codingeasily.karteasy.ui.cart
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.codingeasily.karteasy.data.api.Result
import com.codingeasily.karteasy.data.api.UiState
import com.codingeasily.karteasy.data.model.Cart
import com.codingeasily.karteasy.data.model.CartItem
import com.codingeasily.karteasy.util.kartApp
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class CartViewModel(app: Application) : AndroidViewModel(app) {
private val repo = app.kartApp.repository
private val _state = MutableStateFlow<UiState<Cart>>(UiState.Loading)
val state: StateFlow<UiState<Cart>> = _state
private val _busy = MutableStateFlow(false)
val busy: StateFlow<Boolean> = _busy
private val _messages = MutableSharedFlow<String>()
val messages: SharedFlow<String> = _messages
fun load() {
viewModelScope.launch {
if (_state.value !is UiState.Success) _state.value = UiState.Loading
_state.value = when (val r = repo.cart()) {
is Result.Success -> UiState.Success(r.data)
is Result.Error -> UiState.Error(r.message)
}
}
}
fun changeQty(item: CartItem, delta: Int) = update { repo.updateCart(item.productId, item.qty + delta) }
fun remove(item: CartItem) = update { repo.removeFromCart(item.productId) }
/** Undo for the "Item removed" snackbar. */
fun restore(item: CartItem) = update { repo.addToCart(item.productId, item.qty) }
fun moveToWishlist(item: CartItem) {
viewModelScope.launch {
val r = repo.toggleWishlist(item.productId)
if (r is Result.Success && !r.data.inWishlist) repo.toggleWishlist(item.productId) // was already there
update { repo.removeFromCart(item.productId) }
_messages.emit("Moved to wishlist.")
}
}
/** Every cart call returns the full new cart, so the screen simply shows that. */
private fun update(call: suspend () -> Result<Cart>) {
if (_busy.value) return
_busy.value = true
viewModelScope.launch {
when (val r = call()) {
is Result.Success -> _state.value = UiState.Success(r.data)
is Result.Error -> _messages.emit(r.message)
}
_busy.value = false
}
}
}Step 5: CartFragment
Items न हों तो fragment "Start shopping" वाला empty state दिखाता है, वरना list, summary, नीचे total और free-delivery card।
package com.codingeasily.karteasy.ui.cart
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.codingeasily.karteasy.R
import com.codingeasily.karteasy.data.api.UiState
import com.codingeasily.karteasy.data.model.CartItem
import com.codingeasily.karteasy.databinding.FragmentCartBinding
import com.codingeasily.karteasy.ui.product.ProductDetailFragment
import com.codingeasily.karteasy.util.Format
import com.codingeasily.karteasy.util.collectWhenStarted
import com.codingeasily.karteasy.util.done
import com.codingeasily.karteasy.util.empty
import com.codingeasily.karteasy.util.error
import com.codingeasily.karteasy.util.hide
import com.codingeasily.karteasy.util.loading
import com.codingeasily.karteasy.util.show
import com.codingeasily.karteasy.util.snack
import com.google.android.material.snackbar.Snackbar
class CartFragment : Fragment() {
companion object {
/** Must match FREE_DELIVERY_ABOVE in the PHP config. */
const val FREE_DELIVERY_ABOVE = 499.0
}
private var _binding: FragmentCartBinding? = null
private val binding get() = _binding!!
private val vm: CartViewModel by viewModels()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentCartBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val adapter = CartAdapter(
onQty = { item, d -> vm.changeQty(item, d) },
onRemove = ::removeWithUndo,
onSave = { vm.moveToWishlist(it) },
onOpen = { findNavController().navigate(R.id.productDetailFragment, bundleOf(ProductDetailFragment.ARG_PRODUCT_ID to it.productId)) }
)
binding.list.layoutManager = LinearLayoutManager(requireContext())
binding.list.adapter = adapter
// Swipe left or right to remove an item.
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
override fun onMove(rv: RecyclerView, vh: RecyclerView.ViewHolder, t: RecyclerView.ViewHolder) = false
override fun onSwiped(vh: RecyclerView.ViewHolder, direction: Int) {
val pos = vh.bindingAdapterPosition
adapter.notifyItemChanged(pos) // put the row back; the new cart list removes it
removeWithUndo(adapter.currentList[pos])
}
}).attachToRecyclerView(binding.list)
binding.checkout.setOnClickListener { findNavController().navigate(R.id.action_cart_to_checkout) }
collectWhenStarted(vm.state) { state ->
when (state) {
is UiState.Loading -> { binding.content.hide(); binding.bottomBar.hide(); binding.state.loading() }
is UiState.Error -> { binding.content.hide(); binding.bottomBar.hide(); binding.state.error(state.message) { vm.load() } }
is UiState.Success -> {
val cart = state.data
adapter.submitList(cart.items)
if (cart.items.isEmpty()) {
binding.content.hide(); binding.bottomBar.hide()
binding.state.empty(R.drawable.ic_cart_empty, R.string.cart_empty, R.string.start_shopping) {
findNavController().navigate(R.id.homeFragment)
}
return@collectWhenStarted
}
binding.state.done(); binding.content.show(); binding.bottomBar.show()
binding.summary.bind(cart)
binding.total.text = Format.price(cart.total)
binding.checkout.isEnabled = cart.itemCount > 0
// "Add ₹120 more for FREE delivery" + progress bar
val left = FREE_DELIVERY_ABOVE - cart.subtotal
if (left > 0) {
binding.freeDelivery.text = getString(R.string.free_delivery_left, Format.price(left))
binding.freeDeliveryBar.progress = ((cart.subtotal / FREE_DELIVERY_ABOVE) * 100).toInt()
binding.freeDeliveryBar.show()
} else {
binding.freeDelivery.setText(R.string.free_delivery_unlocked)
binding.freeDeliveryBar.hide()
}
}
}
}
collectWhenStarted(vm.busy) { binding.updating.visibility = if (it) View.VISIBLE else View.INVISIBLE }
collectWhenStarted(vm.messages) { snack(it) }
}
override fun onResume() {
super.onResume()
vm.load() // the cart may have changed on another screen
}
private fun removeWithUndo(item: CartItem) {
vm.remove(item)
Snackbar.make(binding.root, getString(R.string.removed_item, item.name), Snackbar.LENGTH_LONG)
.setAction(R.string.undo) { vm.restore(item) }
.setAnchorView(binding.bottomBar)
.show()
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}Swipe से remove + Undo
ItemTouchHelper left या right swipe पहचानता है। हम तुरंत API से item हटवाते हैं और Undo वाला Snackbar दिखाते हैं; Undo वही product और quantity वापस जोड़ देता है। Snackbar bottom bar के ऊपर anchored है ताकि Checkout button न ढके।
Cart badge
Cart tab पर number एक Material BadgeDrawable है। यह repository.cartCount follow करता है, जिसे हर cart call update करती है — इसलिए Home, Detail या Wishlist से add करने पर badge तुरंत बदलता है।
// MainActivity.kt – the repository's cartCount drives the badge on the Cart tab
launch {
app.repository.cartCount.collect { count ->
val badge = binding.bottomNav.getOrCreateBadge(R.id.cartFragment)
badge.isVisible = count > 0
badge.number = count
badge.backgroundColor = ContextCompat.getColor(this@MainActivity, R.color.sale)
}
}