diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index cf07133..65fef7f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -17,9 +17,15 @@
android:supportsRtl="true"
android:theme="@style/Theme.Woka"
tools:targetApi="31">
+
+ android:exported="false"
+ android:screenOrientation="portrait" />
>
+
+ @GET("cart_listing")
+ suspend fun cartListing(): Response>
+
+ @POST("remove_cart")
+ suspend fun removeCartItem(@Body formBody: FormBody): Response>
+
+ @GET("coupon_listing")
+ suspend fun couponsListing(): Response>
}
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/ShopRepository.kt b/app/src/main/java/com/woka/shop/ShopRepository.kt
index 58e09e2..52af212 100644
--- a/app/src/main/java/com/woka/shop/ShopRepository.kt
+++ b/app/src/main/java/com/woka/shop/ShopRepository.kt
@@ -3,7 +3,9 @@ package com.woka.shop
import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import com.woka.networking.RetrofitHelper.handleApiCall
+import com.woka.shop.models.cartlisting.CartResponse
import com.woka.shop.models.categorylisting.CategoryResponse
+import com.woka.shop.models.couponlisting.CouponsResponse
import com.woka.shop.models.subcategorylisting.SubCategoryResponse
import com.woka.shop.models.superlisting.SuperCategoryResponse
import okhttp3.FormBody
@@ -12,7 +14,7 @@ object ShopRepository {
private val apiService = RetrofitHelper.getRetrofit().create(ShopApiService::class.java)
suspend fun superCategoryListing(): ApiResult {
- return handleApiCall{
+ return handleApiCall {
apiService.superCategoryListing(
FormBody.Builder()
.add("module_id", "5")
@@ -22,7 +24,7 @@ object ShopRepository {
}
suspend fun categoryListing(superCategoryId: String): ApiResult {
- return handleApiCall{
+ return handleApiCall {
apiService.categoryListing(
FormBody.Builder()
.add("module_id", "5")
@@ -33,7 +35,7 @@ object ShopRepository {
}
suspend fun subCategoryListing(categoryId: String): ApiResult {
- return handleApiCall{
+ return handleApiCall {
apiService.subcategoryListing(
FormBody.Builder()
.add("category_id", categoryId)
@@ -41,4 +43,67 @@ object ShopRepository {
)
}
}
+
+ // cart listing with loose caching
+ private var cartResponse: CartResponse? = null
+
+ suspend fun cartListing(): ApiResult {
+ if (cartResponse != null) {
+ return ApiResult.Success(cartResponse)
+ }
+
+ val response = handleApiCall {
+ apiService.cartListing()
+ }
+
+ when (response) {
+ is ApiResult.Error -> {}
+ is ApiResult.Loading -> {}
+ is ApiResult.Success -> {
+ cartResponse = response.data
+ }
+ }
+
+ return response
+ }
+
+ suspend fun removeCartItem(id: Int): ApiResult {
+ val response = handleApiCall {
+ apiService.removeCartItem(
+ FormBody.Builder()
+ .add("shop_master_id", "$id")
+ .build()
+ )
+ }
+
+ when (response) {
+ is ApiResult.Error -> {
+ return ApiResult.Error(response.errorMessage, response.error)
+ }
+ is ApiResult.Loading -> {
+ return ApiResult.Loading()
+ }
+ is ApiResult.Success -> {
+ // removing from cache
+ cartResponse?.let { cartData ->
+ cartData.result?.let { cartItems ->
+ cartItems.find { it?.id == id }?.let {item ->
+ val remainingAmount = (cartData.total_amount?:0.0) - (item.product_final_price?:0.0)
+ cartData.total_amount = maxOf(0.0, remainingAmount)
+ }
+
+ cartItems.removeIf { it?.id == id }
+ }
+ }
+
+ return ApiResult.Success(cartResponse?.total_amount, response.message)
+ }
+ }
+ }
+
+ suspend fun couponsListing(): ApiResult {
+ return handleApiCall {
+ apiService.couponsListing()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/adapters/CartAdapter.kt b/app/src/main/java/com/woka/shop/adapters/CartAdapter.kt
new file mode 100644
index 0000000..5a83e06
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/adapters/CartAdapter.kt
@@ -0,0 +1,65 @@
+package com.woka.shop.adapters
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.AsyncDifferConfig
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import com.woka.databinding.CartItemViewHolderBinding
+import com.woka.shop.models.cartlisting.CartItem
+import com.woka.utils.show
+import java.util.concurrent.Executors
+
+class CartAdapter(private val showFullData: Boolean = true): ListAdapter(ASYNC_DIFF_UTIL) {
+
+ companion object{
+ private val DIFF_UTIL = object :DiffUtil.ItemCallback(){
+ override fun areItemsTheSame(oldItem: CartItem, newItem: CartItem): Boolean = oldItem.id == newItem.id
+ override fun areContentsTheSame(oldItem: CartItem, newItem: CartItem): Boolean = oldItem == newItem
+ }
+
+ private val ASYNC_DIFF_UTIL = AsyncDifferConfig.Builder(DIFF_UTIL)
+ .setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
+ .build()
+ }
+
+ inner class CartViewHolder(val binding: CartItemViewHolderBinding): ViewHolder(binding.root)
+
+ var onCartItemDeleteListener: ((Int, Int) -> Unit)? = null
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CartViewHolder {
+ return CartViewHolder(
+ CartItemViewHolderBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )
+ )
+ }
+
+ override fun onBindViewHolder(holder: CartViewHolder, position: Int) {
+ val cartItem = getItem(holder.absoluteAdapterPosition)
+
+ with(holder.binding){
+ if (cartItem.shop_image?.isNotEmpty() == true)
+ image.loadImage(cartItem.shop_image.first())
+
+ title.text = cartItem.product_name
+ price.text = "${cartItem.product_price}"
+
+ if (showFullData){
+ quantityTag.show()
+ quantity.text = "${cartItem.product_quantity}"
+
+ statusTag.show()
+ status.text = "${cartItem.stock_status}"
+
+ delete.show()
+ delete.setOnClickListener {
+ cartItem.id?.let { id -> onCartItemDeleteListener?.invoke(id, holder.absoluteAdapterPosition) }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/adapters/CouponAdapter.kt b/app/src/main/java/com/woka/shop/adapters/CouponAdapter.kt
new file mode 100644
index 0000000..3cb3c25
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/adapters/CouponAdapter.kt
@@ -0,0 +1,52 @@
+package com.woka.shop.adapters
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.AsyncDifferConfig
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import com.woka.databinding.CouponViewHolderrBinding
+import com.woka.shop.models.couponlisting.CouponData
+import java.util.concurrent.Executors
+
+class CouponAdapter : ListAdapter(DIFF_CONFIG) {
+
+ companion object {
+ private val DIFF_UTIL = object : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: CouponData, newItem: CouponData): Boolean =
+ oldItem.id == newItem.id
+
+ override fun areContentsTheSame(oldItem: CouponData, newItem: CouponData): Boolean =
+ oldItem == newItem
+ }
+
+ private val DIFF_CONFIG = AsyncDifferConfig.Builder(DIFF_UTIL)
+ .setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
+ .build()
+ }
+
+ inner class CouponViewHolder(val binding: CouponViewHolderrBinding) : ViewHolder(binding.root)
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CouponViewHolder {
+ return CouponViewHolder(
+ CouponViewHolderrBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )
+ )
+ }
+
+ override fun onBindViewHolder(holder: CouponViewHolder, position: Int) {
+ val coupon = getItem(holder.absoluteAdapterPosition)
+
+ holder.binding.apply {
+ val off = if (coupon.discount_type == 1) "${coupon.discount_value}%"
+ else "Rs. ${coupon.discount_value}"
+
+ val finalTxt = "$off OFF with coupon code ${coupon.coupon_code}"
+ textView.text = finalTxt
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/models/cartlisting/CartItem.kt b/app/src/main/java/com/woka/shop/models/cartlisting/CartItem.kt
new file mode 100644
index 0000000..7f403b3
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/models/cartlisting/CartItem.kt
@@ -0,0 +1,18 @@
+package com.woka.shop.models.cartlisting
+
+data class CartItem(
+ val category_master_id: Int?,
+ val id: Int?,
+ val product_name: String?,
+ val product_price: String?,
+ var product_final_price: Double?,
+ val product_quantity: Int?,
+ val remain_stock_quantity: Int?,
+ val shop_image: List?,
+ val shop_master_detail: ShopMasterDetail?,
+ val sku_id: String?,
+ val stock_status: String?,
+ val sub_category_master_id: Int?,
+ val tax_category: Any?,
+ val tax_value: String?
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/models/cartlisting/CartResponse.kt b/app/src/main/java/com/woka/shop/models/cartlisting/CartResponse.kt
new file mode 100644
index 0000000..0affb63
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/models/cartlisting/CartResponse.kt
@@ -0,0 +1,11 @@
+package com.woka.shop.models.cartlisting
+
+data class CartResponse(
+ val address_available: Boolean?,
+ val cart_quantity: Int?,
+ val cart_total_amount: String?,
+ val result: MutableList?,
+ var total_amount: Double?,
+ val total_records: Int?,
+ val user_type: String?
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/models/cartlisting/ShopMasterDetail.kt b/app/src/main/java/com/woka/shop/models/cartlisting/ShopMasterDetail.kt
new file mode 100644
index 0000000..75a1a6b
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/models/cartlisting/ShopMasterDetail.kt
@@ -0,0 +1,10 @@
+package com.woka.shop.models.cartlisting
+
+data class ShopMasterDetail(
+ val description_english: String?,
+ val description_hindi: String?,
+ val id: Int?,
+ val product_id: Int?,
+ val product_name_english: String?,
+ val product_name_hindi: String?
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/models/couponlisting/Category.kt b/app/src/main/java/com/woka/shop/models/couponlisting/Category.kt
new file mode 100644
index 0000000..29074b8
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/models/couponlisting/Category.kt
@@ -0,0 +1,6 @@
+package com.woka.shop.models.couponlisting
+
+data class Category(
+ val category_name: String?,
+ val id: Int?
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/models/couponlisting/CouponData.kt b/app/src/main/java/com/woka/shop/models/couponlisting/CouponData.kt
new file mode 100644
index 0000000..0a1a044
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/models/couponlisting/CouponData.kt
@@ -0,0 +1,13 @@
+package com.woka.shop.models.couponlisting
+
+data class CouponData(
+ val category: Category?,
+ val category_master_id: Int?,
+ val coupon_code: String?,
+ val discount_type: Int?,
+ val discount_value: String?,
+ val end_date: String?,
+ val id: Int?,
+ val start_from: String?,
+ val usage_limit: Int?
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/models/couponlisting/CouponsResponse.kt b/app/src/main/java/com/woka/shop/models/couponlisting/CouponsResponse.kt
new file mode 100644
index 0000000..8358e34
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/models/couponlisting/CouponsResponse.kt
@@ -0,0 +1,6 @@
+package com.woka.shop.models.couponlisting
+
+data class CouponsResponse(
+ val result: List?,
+ val total_records: Int?
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/viewmodels/CartViewModel.kt b/app/src/main/java/com/woka/shop/viewmodels/CartViewModel.kt
new file mode 100644
index 0000000..7379ddb
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/viewmodels/CartViewModel.kt
@@ -0,0 +1,39 @@
+package com.woka.shop.viewmodels
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.woka.networking.ApiResult
+import com.woka.shop.ShopRepository
+import com.woka.shop.models.cartlisting.CartResponse
+import com.woka.shop.models.couponlisting.CouponsResponse
+import kotlinx.coroutines.launch
+
+class CartViewModel: ViewModel() {
+
+ // ui callbacks
+ var onToolBarTitleChange: ((String) -> Unit)? = null
+
+ // data callbacks
+ private val repository = ShopRepository
+
+ private val _cartListLiveData = MutableLiveData>()
+ val cartListLiveData: LiveData>
+ get() = _cartListLiveData
+
+ fun loadCartList(){
+ viewModelScope.launch {
+ _cartListLiveData.postValue(ApiResult.Loading())
+ _cartListLiveData.postValue(repository.cartListing())
+ }
+ }
+
+ suspend fun removeItem(id: Int): ApiResult {
+ return repository.removeCartItem(id)
+ }
+
+ suspend fun loadCoupons(): ApiResult{
+ return repository.couponsListing()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/views/CartActivity.kt b/app/src/main/java/com/woka/shop/views/CartActivity.kt
new file mode 100644
index 0000000..1da950c
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/views/CartActivity.kt
@@ -0,0 +1,48 @@
+package com.woka.shop.views
+
+import android.os.Bundle
+import androidx.activity.enableEdgeToEdge
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.lifecycle.ViewModelProvider
+import com.woka.databinding.ActivityCartBinding
+import com.woka.shop.viewmodels.CartViewModel
+import com.woka.utils.WokaBaseActivity
+
+class CartActivity : WokaBaseActivity() {
+
+ private lateinit var binding: ActivityCartBinding
+ private lateinit var viewModel: CartViewModel
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ binding = ActivityCartBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
+ val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
+ insets
+ }
+
+ viewModel = ViewModelProvider(this)[CartViewModel::class.java]
+
+ clickEvents()
+
+ setObservers()
+ }
+
+ private fun clickEvents() {
+ binding.apply {
+ toolbar.backBtn.setOnClickListener {
+ onBackPressedDispatcher.onBackPressed()
+ }
+ }
+ }
+
+ private fun setObservers(){
+ viewModel.onToolBarTitleChange = {
+ binding.toolbar.title.text = it
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/views/ShopActivity.kt b/app/src/main/java/com/woka/shop/views/ShopActivity.kt
index 9eafc58..28dfb36 100644
--- a/app/src/main/java/com/woka/shop/views/ShopActivity.kt
+++ b/app/src/main/java/com/woka/shop/views/ShopActivity.kt
@@ -1,5 +1,6 @@
package com.woka.shop.views
+import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.core.view.ViewCompat
@@ -46,6 +47,12 @@ class ShopActivity : WokaBaseActivity() {
backBtn.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
+
+ cart.setOnClickListener {
+ startActivity(
+ Intent(this@ShopActivity, CartActivity::class.java)
+ )
+ }
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/views/fragments/CartFragment.kt b/app/src/main/java/com/woka/shop/views/fragments/CartFragment.kt
new file mode 100644
index 0000000..6fc8a57
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/views/fragments/CartFragment.kt
@@ -0,0 +1,156 @@
+package com.woka.shop.views.fragments
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.lifecycleScope
+import androidx.navigation.fragment.findNavController
+import com.woka.R
+import com.woka.databinding.FragmentCartBinding
+import com.woka.networking.ApiResult
+import com.woka.shop.adapters.CartAdapter
+import com.woka.shop.viewmodels.CartViewModel
+import com.woka.utils.ProgressView
+import com.woka.utils.hide
+import com.woka.utils.show
+import com.woka.utils.toast
+import kotlinx.coroutines.launch
+
+class CartFragment: Fragment() {
+
+ private lateinit var binding: FragmentCartBinding
+
+ private lateinit var adapter: CartAdapter
+ private lateinit var viewModel: CartViewModel
+
+ private lateinit var progressDialog: ProgressView
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentCartBinding.inflate(inflater, container, false)
+
+ viewModel = ViewModelProvider(requireActivity())[CartViewModel::class.java]
+ adapter = CartAdapter()
+ progressDialog = ProgressView(requireContext())
+
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ initViews()
+
+ clickEvents()
+
+ setObservers()
+
+ if (!viewModel.cartListLiveData.isInitialized || viewModel.cartListLiveData.value !is ApiResult.Success){
+ viewModel.loadCartList()
+ }
+ }
+
+ private fun initViews() {
+ binding.apply {
+ viewModel.onToolBarTitleChange?.invoke(getString(R.string.shop))
+ rvCart.adapter = adapter
+ }
+ }
+
+ private fun clickEvents() {
+ binding.apply {
+
+ adapter.onCartItemDeleteListener = {id, position ->
+ lifecycleScope.launch {
+ progressDialog.show(getString(R.string.removing_item))
+
+ when (val response = viewModel.removeItem(id)){
+ is ApiResult.Error -> {
+ progressDialog.hide()
+ toast(response.errorMessage)
+ }
+ is ApiResult.Loading -> {}
+ is ApiResult.Success -> {
+ progressDialog.hide()
+ toast(response.message)
+
+ try {
+ adapter.notifyItemRemoved(position)
+ } finally {
+ response.data?.let {cartValue ->
+ if (cartValue > 0){
+ val finalAmount = "₹ $cartValue"
+ totalAmount.text = finalAmount
+ }else{
+ rvCart.hide()
+ progressView.hide()
+ checkoutView.hide()
+
+ noDataView.show()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ binding.checkout.setOnClickListener {
+ findNavController().navigate(R.id.action_cartFragment_to_orderSummaryFragment)
+ }
+ }
+ }
+
+ private fun setObservers(){
+ viewModel.cartListLiveData.observe(viewLifecycleOwner){
+ binding.apply {
+ when (it){
+ is ApiResult.Error -> {
+ rvCart.hide()
+ progressView.hide()
+ checkoutView.hide()
+
+ noDataView.show()
+ }
+ is ApiResult.Loading -> {
+ rvCart.hide()
+ progressView.show()
+ checkoutView.hide()
+ noDataView.hide()
+ }
+ is ApiResult.Success -> {
+ it.data?.let {cartData ->
+ cartData.result?.let {cartList ->
+ if (cartList.isNotEmpty()){
+ adapter.submitList(cartList){
+ progressView.hide()
+ noDataView.hide()
+
+ rvCart.show()
+
+ val finalAmount = "₹ ${cartData.total_amount}"
+ totalAmount.text = finalAmount
+
+ checkoutView.show()
+ }
+ }else{
+ // cart is empty
+ rvCart.hide()
+ progressView.hide()
+ checkoutView.hide()
+
+ noDataView.show()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/woka/shop/views/fragments/OrderSummaryFragment.kt b/app/src/main/java/com/woka/shop/views/fragments/OrderSummaryFragment.kt
new file mode 100644
index 0000000..fbef976
--- /dev/null
+++ b/app/src/main/java/com/woka/shop/views/fragments/OrderSummaryFragment.kt
@@ -0,0 +1,102 @@
+package com.woka.shop.views.fragments
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.lifecycleScope
+import com.woka.R
+import com.woka.databinding.FragmentOrderSummaryBinding
+import com.woka.networking.ApiResult
+import com.woka.shop.adapters.CartAdapter
+import com.woka.shop.adapters.CouponAdapter
+import com.woka.shop.viewmodels.CartViewModel
+import com.woka.utils.hide
+import com.woka.utils.show
+import kotlinx.coroutines.launch
+
+class OrderSummaryFragment : Fragment() {
+
+ private lateinit var binding: FragmentOrderSummaryBinding
+ private lateinit var viewModel: CartViewModel
+ private lateinit var adapter: CartAdapter
+ private lateinit var couponAdapter: CouponAdapter
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentOrderSummaryBinding.inflate(inflater, container, false)
+
+ viewModel = ViewModelProvider(requireActivity())[CartViewModel::class.java]
+ adapter = CartAdapter(false)
+ couponAdapter = CouponAdapter()
+
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ initViews()
+
+ setObservers()
+
+ loadCoupons()
+ }
+
+ private fun initViews(){
+ binding.apply {
+ viewModel.onToolBarTitleChange?.invoke(getString(R.string.payment_options))
+
+ rvCart.adapter = adapter
+ rvCoupons.adapter = couponAdapter
+ }
+ }
+
+ private fun loadCoupons(){
+ lifecycleScope.launch {
+ when (val response = viewModel.loadCoupons()){
+ is ApiResult.Error -> {}
+ is ApiResult.Loading -> {}
+ is ApiResult.Success -> {
+ response.data?.result?.filterNotNull()?.let {
+ couponAdapter.submitList(it)
+ }
+ }
+ }
+ }
+ }
+
+ private fun setObservers() {
+ viewModel.cartListLiveData.observe(viewLifecycleOwner){
+ binding.apply {
+ when (it){
+ is ApiResult.Error -> {
+ rvCart.hide()
+ }
+ is ApiResult.Loading -> {
+ rvCart.hide()
+ }
+ is ApiResult.Success -> {
+ it.data?.let {cartData ->
+ cartData.result?.let {cartList ->
+ if (cartList.isNotEmpty()){
+ mainLayout.show()
+ adapter.submitList(cartList){
+ rvCart.show()
+ }
+ }else{
+ // cart is empty
+ rvCart.hide()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml
new file mode 100644
index 0000000..cdc2f86
--- /dev/null
+++ b/app/src/main/res/drawable/ic_delete.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_cart.xml b/app/src/main/res/layout/activity_cart.xml
new file mode 100644
index 0000000..d1ccd9a
--- /dev/null
+++ b/app/src/main/res/layout/activity_cart.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/cart_item_view_holder.xml b/app/src/main/res/layout/cart_item_view_holder.xml
new file mode 100644
index 0000000..910afeb
--- /dev/null
+++ b/app/src/main/res/layout/cart_item_view_holder.xml
@@ -0,0 +1,154 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/coupon_view_holderr.xml b/app/src/main/res/layout/coupon_view_holderr.xml
new file mode 100644
index 0000000..0a83a16
--- /dev/null
+++ b/app/src/main/res/layout/coupon_view_holderr.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_cart.xml b/app/src/main/res/layout/fragment_cart.xml
new file mode 100644
index 0000000..bb5e577
--- /dev/null
+++ b/app/src/main/res/layout/fragment_cart.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_order_summary.xml b/app/src/main/res/layout/fragment_order_summary.xml
new file mode 100644
index 0000000..f2d07cc
--- /dev/null
+++ b/app/src/main/res/layout/fragment_order_summary.xml
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph_shop_cart.xml b/app/src/main/res/navigation/nav_graph_shop_cart.xml
new file mode 100644
index 0000000..d72b2e4
--- /dev/null
+++ b/app/src/main/res/navigation/nav_graph_shop_cart.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b67159a..48f580d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -223,4 +223,15 @@
Continue to WOKA
To continue, please sign in for more adventures and features...
Free Sign In
+ Product Status:
+ Quantity:
+ CHECKOUT
+ Total:
+ No items added to cart
+ Removing item
+ PAYMENT OPTIONS
+ Order Summary
+ Enter a coupon code
+ Apply
+
\ No newline at end of file