From 73e6a9f3fc76cc8debf265e0e8aebf9c552884ea Mon Sep 17 00:00:00 2001 From: AdityaGaikwad Date: Wed, 31 Jul 2024 20:52:15 +0530 Subject: [PATCH] RnD for caching cart and also adding items to cart locally. Integrated product view api for viewing product. Added removing cart item functionality from product view fragment. Added callback to listen removal changes when gone to cart from product view fragment. Debugged crash with configuration changes with multiple fragments in an activity with no public constructor. And issue with no saved state when configuration is changed. Understood and integrated navigation-safe-args in ShopActivity. --- app/build.gradle | 1 + .../com/woka/home/fragments/MyListFragment.kt | 2 +- .../main/java/com/woka/shop/ShopApiService.kt | 4 + .../main/java/com/woka/shop/ShopRepository.kt | 10 + .../com/woka/shop/adapters/CategoryAdapter.kt | 6 +- .../shop/adapters/ProductImagesAdapter.kt | 12 +- .../woka/shop/adapters/ShopProductAdapter.kt | 6 +- .../models/productlisting/ProductCategory.kt | 10 + .../shop/models/productlisting/ShopProduct.kt | 6 +- .../com/woka/shop/viewmodels/CartViewModel.kt | 3 - .../com/woka/shop/viewmodels/ShopViewModel.kt | 40 ++-- .../java/com/woka/shop/views/CartActivity.kt | 2 +- .../java/com/woka/shop/views/ShopActivity.kt | 35 ++- .../shop/views/fragments/cart/CartFragment.kt | 17 +- .../views/fragments/shop/ProductFragment.kt | 168 +++++++++----- .../views/fragments/shop/ShopFragment1.kt | 12 +- .../views/fragments/shop/ShopFragment2.kt | 26 ++- .../views/fragments/shop/ShopFragment3.kt | 25 +-- app/src/main/res/layout/activity_shop.xml | 12 +- app/src/main/res/layout/fragment_my_list.xml | 34 ++- app/src/main/res/layout/fragment_product.xml | 208 ++++++++++++++---- app/src/main/res/layout/fragment_shop1.xml | 2 +- app/src/main/res/layout/fragment_shop3.xml | 2 +- .../main/res/navigation/nav_graph_shop.xml | 42 ++++ app/src/main/res/values/strings.xml | 1 + build.gradle | 3 +- gradle/libs.versions.toml | 3 +- 27 files changed, 489 insertions(+), 203 deletions(-) create mode 100644 app/src/main/java/com/woka/shop/models/productlisting/ProductCategory.kt create mode 100644 app/src/main/res/navigation/nav_graph_shop.xml diff --git a/app/build.gradle b/app/build.gradle index a2cb117..bcab98a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,6 +2,7 @@ plugins { alias(libs.plugins.androidApplication) alias(libs.plugins.jetbrainsKotlinAndroid) id("kotlin-parcelize") + alias(libs.plugins.navigationSafeArgs) } android { diff --git a/app/src/main/java/com/woka/home/fragments/MyListFragment.kt b/app/src/main/java/com/woka/home/fragments/MyListFragment.kt index 26bab22..f107436 100644 --- a/app/src/main/java/com/woka/home/fragments/MyListFragment.kt +++ b/app/src/main/java/com/woka/home/fragments/MyListFragment.kt @@ -180,7 +180,7 @@ class MyListFragment : Fragment() { karaokeTxt.text = getString(R.string.karaoke) gamesTxt.text = getString(R.string.games) - noData.text = getString(R.string.no_favorites_added) + noDataTxt.text = getString(R.string.no_favorites_added) if (webSeriesEAdapter.currentList.isNotEmpty()){ webSeriesEAdapter.notifyItemRangeChanged(0, webSeriesEAdapter.currentList.size) diff --git a/app/src/main/java/com/woka/shop/ShopApiService.kt b/app/src/main/java/com/woka/shop/ShopApiService.kt index 1274002..65d90f4 100644 --- a/app/src/main/java/com/woka/shop/ShopApiService.kt +++ b/app/src/main/java/com/woka/shop/ShopApiService.kt @@ -12,6 +12,7 @@ import com.woka.shop.models.createorder.CreateOrderRequestData import com.woka.shop.models.createorder.CreateOrderResponse import com.woka.shop.models.edd.EDDResponse import com.woka.shop.models.productlisting.ProductListingResponse +import com.woka.shop.models.productlisting.ShopProduct import com.woka.shop.models.subcategorylisting.SubCategoryResponse import com.woka.shop.models.superlisting.SuperCategoryResponse import okhttp3.FormBody @@ -35,6 +36,9 @@ interface ShopApiService { @POST("v2/shop_product_listing") suspend fun productListing(@Body formBody: FormBody): Response> + @POST("shop_product_view") + suspend fun productView(@Body formBody: FormBody): Response>> + // cart @GET("cart_listing") suspend fun cartListing(): Response> diff --git a/app/src/main/java/com/woka/shop/ShopRepository.kt b/app/src/main/java/com/woka/shop/ShopRepository.kt index 9ed633e..941d119 100644 --- a/app/src/main/java/com/woka/shop/ShopRepository.kt +++ b/app/src/main/java/com/woka/shop/ShopRepository.kt @@ -75,6 +75,16 @@ object ShopRepository { } } + suspend fun getProductData(id: Int): ApiResult> { + return handleApiCall { + apiService.productView( + FormBody.Builder() + .add("product_id", "$id") + .build() + ) + } + } + // cart listing with loose caching private var cartResponse: CartResponse? = null diff --git a/app/src/main/java/com/woka/shop/adapters/CategoryAdapter.kt b/app/src/main/java/com/woka/shop/adapters/CategoryAdapter.kt index bba91d6..3b7f1f9 100644 --- a/app/src/main/java/com/woka/shop/adapters/CategoryAdapter.kt +++ b/app/src/main/java/com/woka/shop/adapters/CategoryAdapter.kt @@ -32,7 +32,7 @@ class CategoryAdapter: inner class CategoryViewHolder(val binding: CategoryViweHolderBinding) : ViewHolder(binding.root) - var onCategoryClickListener: ((BaseCategory) -> Unit)? = null + var onCategoryClickListener: ((Int) -> Unit)? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryViewHolder { return CategoryViewHolder( @@ -52,7 +52,9 @@ class CategoryAdapter: title.text = category.title holder.binding.root.setOnClickListener { - onCategoryClickListener?.invoke(category) + category.id?.let { + onCategoryClickListener?.invoke(it) + } } } } diff --git a/app/src/main/java/com/woka/shop/adapters/ProductImagesAdapter.kt b/app/src/main/java/com/woka/shop/adapters/ProductImagesAdapter.kt index 36eb340..1a9b754 100644 --- a/app/src/main/java/com/woka/shop/adapters/ProductImagesAdapter.kt +++ b/app/src/main/java/com/woka/shop/adapters/ProductImagesAdapter.kt @@ -7,12 +7,18 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder import com.bumptech.glide.Glide import com.woka.databinding.ProductImageViewHolderBinding -class ProductImagesAdapter( - private val imageList: ArrayList -) : RecyclerView.Adapter(){ +class ProductImagesAdapter: RecyclerView.Adapter(){ inner class ImageViewHolder(val binding: ProductImageViewHolderBinding): ViewHolder(binding.root) + private val imageList: ArrayList = ArrayList() + + fun submitList(imageList: ArrayList){ + this.imageList.clear() + this.imageList.addAll(imageList) + notifyItemRangeChanged(0, imageList.size) + } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder { return ImageViewHolder( ProductImageViewHolderBinding.inflate( diff --git a/app/src/main/java/com/woka/shop/adapters/ShopProductAdapter.kt b/app/src/main/java/com/woka/shop/adapters/ShopProductAdapter.kt index cff5ae9..d9c9903 100644 --- a/app/src/main/java/com/woka/shop/adapters/ShopProductAdapter.kt +++ b/app/src/main/java/com/woka/shop/adapters/ShopProductAdapter.kt @@ -24,7 +24,7 @@ class ShopProductAdapter: ListAdapter Unit)? = null + var onProductClicked: ((Int) -> Unit)? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder { return ProductViewHolder( @@ -52,7 +52,9 @@ class ShopProductAdapter: ListAdapter() - // cart - val removedProducts = ArrayList() - // data callbacks private val repository = ShopRepository diff --git a/app/src/main/java/com/woka/shop/viewmodels/ShopViewModel.kt b/app/src/main/java/com/woka/shop/viewmodels/ShopViewModel.kt index 6de2fba..ce02ac0 100644 --- a/app/src/main/java/com/woka/shop/viewmodels/ShopViewModel.kt +++ b/app/src/main/java/com/woka/shop/viewmodels/ShopViewModel.kt @@ -1,6 +1,5 @@ package com.woka.shop.viewmodels -import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -12,9 +11,7 @@ import com.woka.shop.models.productlisting.ShopProduct import com.woka.shop.models.subcategorylisting.SubCategoryData import com.woka.shop.models.superlisting.SuperCategory import com.woka.utils.PagingData -import com.woka.utils.TAG import kotlinx.coroutines.launch -import kotlin.collections.HashSet class ShopViewModel: ViewModel() { @@ -122,11 +119,11 @@ class ShopViewModel: ViewModel() { if (productDataMap.containsKey(key) && productDataMap[key]?.isNotEmpty() == true) { _productListingLiveData.postValue(ApiResult.Success(productDataMap[key])) } else { - loadMoreEpisodes(superCategoryId, categoryId, subCategoryId) + loadMoreProducts(superCategoryId, categoryId, subCategoryId) } } - fun loadMoreEpisodes(superCategoryId: String, categoryId: String, subCategoryId: String?) { + fun loadMoreProducts(superCategoryId: String, categoryId: String, subCategoryId: String?) { viewModelScope.launch { _productListingLiveData.postValue(ApiResult.Loading()) @@ -176,30 +173,23 @@ class ShopViewModel: ViewModel() { } } - fun removeProductsFromCart(products: List){ - val toBeReplaced = mutableSetOf() - - for (productSet in productDataMap.values){ - - toBeReplaced.clear() - - for (product in products){ - if (productSet.contains(product)){ - toBeReplaced.add(product) - } - } - - productSet.removeAll(toBeReplaced) - productSet.addAll(toBeReplaced) - } - - _productListingLiveData.postValue(ApiResult.Success(productDataMap[""])) + suspend fun loadProductData(id: Int): ApiResult> { + return repository.getProductData(id) } fun clearProductListingLiveData() { _productListingLiveData.postValue(ApiResult.Loading()) } + // product view + var currentProductRemovedListener: (() -> Unit)? = null + var currentProductId: Int = -1 + + fun clearCurrentProductCallbacks(){ + currentProductRemovedListener = null + currentProductId = -1 + } + // cart val cartCountLivedata: LiveData get() { @@ -211,4 +201,8 @@ class ShopViewModel: ViewModel() { suspend fun addToCart(shopProduct: ShopProduct): ApiResult { return repository.addToCart(shopProduct) } + + suspend fun removeFromCart(id: Int): ApiResult { + return repository.removeCartItem(id) + } } \ 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 index cabfad3..0654d77 100644 --- a/app/src/main/java/com/woka/shop/views/CartActivity.kt +++ b/app/src/main/java/com/woka/shop/views/CartActivity.kt @@ -12,7 +12,7 @@ import com.woka.utils.WokaBaseActivity class CartActivity : WokaBaseActivity() { companion object{ - const val EXTRA_REMOVED_CART_ITEMS = "extra_removed_cart_items" + const val EXTRA_CURRENT_PRODUCT = "extra_current_product" } private lateinit var binding: ActivityCartBinding 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 ef2f6bf..2cd8d77 100644 --- a/app/src/main/java/com/woka/shop/views/ShopActivity.kt +++ b/app/src/main/java/com/woka/shop/views/ShopActivity.kt @@ -3,14 +3,17 @@ package com.woka.shop.views import android.content.Intent import android.os.Bundle import androidx.activity.enableEdgeToEdge +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.lifecycle.ViewModelProvider import com.woka.R import com.woka.databinding.ActivityShopBinding import com.woka.shop.viewmodels.ShopViewModel -import com.woka.shop.views.fragments.shop.ShopFragment1 +import com.woka.shop.views.CartActivity.Companion.EXTRA_CURRENT_PRODUCT import com.woka.utils.WokaBaseActivity +import com.woka.utils.lightStatusBar import com.woka.utils.setVisibility class ShopActivity : WokaBaseActivity() { @@ -18,6 +21,8 @@ class ShopActivity : WokaBaseActivity() { private lateinit var binding: ActivityShopBinding private lateinit var viewModel: ShopViewModel + private lateinit var cartLauncher: ActivityResultLauncher + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() @@ -32,40 +37,48 @@ class ShopActivity : WokaBaseActivity() { viewModel = ViewModelProvider(this)[ShopViewModel::class.java] window.navigationBarColor = getColor(R.color.orders_bg) - - supportFragmentManager.beginTransaction() - .add(R.id.fcv_shop, ShopFragment1.newInstance()) - .commit() + window.lightStatusBar(false) initViews() clickEvents() setObservers() + + registerLaunchers() } - private fun initViews(){ + private fun initViews() { binding.apply { title.text = getString(R.string.shop) } } - private fun clickEvents(){ + private fun clickEvents() { binding.apply { backBtn.setOnClickListener { onBackPressedDispatcher.onBackPressed() } cart.setOnClickListener { - startActivity( - Intent(this@ShopActivity, CartActivity::class.java) - ) + cartLauncher.launch(Intent(this@ShopActivity, CartActivity::class.java).apply { + putExtra(EXTRA_CURRENT_PRODUCT, viewModel.currentProductId) + }) } } } + private fun registerLaunchers() { + cartLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult -> + if (activityResult.resultCode == RESULT_OK) { + viewModel.currentProductRemovedListener?.invoke() + } + } + } + private fun setObservers() { - viewModel.cartCountLivedata.observe(this){ + viewModel.cartCountLivedata.observe(this) { binding.cartCount.text = "$it" binding.cartCountView.setVisibility(it > 0) } diff --git a/app/src/main/java/com/woka/shop/views/fragments/cart/CartFragment.kt b/app/src/main/java/com/woka/shop/views/fragments/cart/CartFragment.kt index 6d0fa07..1cb395e 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/cart/CartFragment.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/cart/CartFragment.kt @@ -2,6 +2,7 @@ package com.woka.shop.views.fragments.cart import android.content.Intent import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -14,10 +15,10 @@ import com.woka.R import com.woka.databinding.FragmentCartBinding import com.woka.networking.ApiResult import com.woka.shop.adapters.CartAdapter -import com.woka.shop.models.productlisting.ShopProduct import com.woka.shop.viewmodels.CartViewModel -import com.woka.shop.views.CartActivity +import com.woka.shop.views.CartActivity.Companion.EXTRA_CURRENT_PRODUCT import com.woka.utils.ProgressView +import com.woka.utils.TAG import com.woka.utils.hide import com.woka.utils.show import com.woka.utils.toast @@ -32,6 +33,8 @@ class CartFragment: Fragment() { private lateinit var progressDialog: ProgressView + private var currentProductId: Int? = null + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -42,6 +45,9 @@ class CartFragment: Fragment() { adapter = CartAdapter() progressDialog = ProgressView(requireContext()) + currentProductId = requireActivity().intent.getIntExtra(EXTRA_CURRENT_PRODUCT, -1) + Log.d(TAG, "onCreateView: $currentProductId") + return binding.root } @@ -101,10 +107,9 @@ class CartFragment: Fragment() { } } - viewModel.removedProducts.add(ShopProduct(cartItem, false)) - activity?.setResult(AppCompatActivity.RESULT_OK, Intent().apply { - putParcelableArrayListExtra(CartActivity.EXTRA_REMOVED_CART_ITEMS, viewModel.removedProducts) - }) + if (cartItem.id == currentProductId){ + activity?.setResult(AppCompatActivity.RESULT_OK, Intent()) + } } } } diff --git a/app/src/main/java/com/woka/shop/views/fragments/shop/ProductFragment.kt b/app/src/main/java/com/woka/shop/views/fragments/shop/ProductFragment.kt index 31a917b..3341b28 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/shop/ProductFragment.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/shop/ProductFragment.kt @@ -1,14 +1,10 @@ package com.woka.shop.views.fragments.shop -import android.app.Activity.RESULT_OK -import android.content.Intent import android.os.Bundle import android.text.Html import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope @@ -19,19 +15,24 @@ import com.woka.networking.ApiResult import com.woka.shop.adapters.ProductImagesAdapter import com.woka.shop.models.productlisting.ShopProduct import com.woka.shop.viewmodels.ShopViewModel -import com.woka.shop.views.CartActivity 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 ProductFragment private constructor( - private val shopProduct: ShopProduct, - private val category: String -): Fragment() { +private const val ARG_PRODUCT_ID = "arg_product_id" + +class ProductFragment : Fragment() { companion object { @JvmStatic - fun newInstance(shopProduct: ShopProduct, categoryName: String) = ProductFragment(shopProduct, categoryName) + fun newInstance(productId: Int) = + ProductFragment().apply { + arguments = Bundle().apply { + putInt(ARG_PRODUCT_ID, productId) + } + } } private lateinit var binding: FragmentProductBinding @@ -39,7 +40,14 @@ class ProductFragment private constructor( private lateinit var imageAdapter: ProductImagesAdapter private lateinit var progressView: ProgressView - private lateinit var cartLauncher: ActivityResultLauncher + private var mShopProduct: ShopProduct? = null + + private var productId: Int = -1 + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + productId = arguments?.getInt(ARG_PRODUCT_ID, -1)?:-1 + } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -49,11 +57,7 @@ class ProductFragment private constructor( viewModel = ViewModelProvider(requireActivity())[ShopViewModel::class.java] progressView = ProgressView(requireContext(), getString(R.string.please_wait)) - val imageList = ArrayList() - shopProduct.shop_image?.filterNotNull()?.let { - imageList.addAll(it) - } - imageAdapter = ProductImagesAdapter(imageList) + imageAdapter = ProductImagesAdapter() return binding.root } @@ -61,90 +65,152 @@ class ProductFragment private constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + viewModel.currentProductId = productId + initViews() clickEvents() - registerLaunchers() + loadProductData() + setObservers() + + } + + override fun onDestroyView() { + super.onDestroyView() + viewModel.clearCurrentProductCallbacks() } private fun initViews() { binding.apply { - vpImages.adapter = imageAdapter + TabLayoutMediator(tabLayout, vpImages) { _, _ -> }.attach() + } + } - TabLayoutMediator(tabLayout, vpImages){_, _ -> }.attach() + private fun clickEvents() { + binding.apply { + retryBtn.setOnClickListener { + loadProductData() + } + } + } - categoryName.text = category + private fun loadProductData() { + lifecycleScope.launch { + binding.apply { + shimmer.show() + noData.hide() + productView.hide() + when (val response = viewModel.loadProductData(productId)) { + is ApiResult.Error -> { + shimmer.hide() + noData.show() + productView.hide() + } + + is ApiResult.Loading -> {} + is ApiResult.Success -> { + response.data?.first()?.let { + shimmer.hide() + noData.hide() + productView.show() + + displayProductData(it) + } + } + } + } + } + } + + private fun displayProductData(shopProduct: ShopProduct) { + mShopProduct = shopProduct + binding.apply { + + val imageList = ArrayList() + shopProduct.shop_image?.filterNotNull()?.let { + imageList.addAll(it) + } + + imageAdapter.submitList(imageList) + + categoryName.text = shopProduct.category?.category_name skuId.text = shopProduct.sku_id price.text = shopProduct.product_price - addToCart.text = if (shopProduct.added_to_cart == true){ - getString(R.string.view_cart) - }else{ + addToCart.text = if (shopProduct.added_to_cart == true) { + getString(R.string.remove_from_cart) + } else { getString(R.string.add_to_cart) } - if (shopProduct.sub_category_master_id == 12){ + if (shopProduct.sub_category_master_id == 12) { title.text = shopProduct.shop_master_detail?.product_name_english description.text = Html.fromHtml( shopProduct.shop_master_detail?.description_english, Html.FROM_HTML_MODE_LEGACY ) - }else{ + } else { title.text = shopProduct.shop_master_detail?.product_name_hindi description.text = Html.fromHtml( shopProduct.shop_master_detail?.description_hindi, Html.FROM_HTML_MODE_LEGACY ) } - } - } - private fun clickEvents(){ - binding.apply { addToCart.setOnClickListener { - if (shopProduct.added_to_cart == false){ - lifecycleScope.launch { - progressView.show() - when (val response = viewModel.addToCart(shopProduct)){ + lifecycleScope.launch { + progressView.show() + + if (shopProduct.added_to_cart == false) { + when (val response = viewModel.addToCart(shopProduct)) { is ApiResult.Error -> { progressView.hide() toast(response.errorMessage) } + is ApiResult.Loading -> {} is ApiResult.Success -> { progressView.hide() toast(response.message) shopProduct.added_to_cart = true - addToCart.text = getString(R.string.view_cart) + addToCart.text = getString(R.string.remove_from_cart) + } + } + } else { + when (val response = viewModel.removeFromCart(productId)) { + is ApiResult.Error -> { + progressView.hide() + toast(response.errorMessage) + } + + is ApiResult.Loading -> {} + is ApiResult.Success -> { + progressView.hide() + toast(response.message) + + shopProduct.added_to_cart = false + addToCart.text = getString(R.string.add_to_cart) } } - } - }else{ - activity?.let { - cartLauncher.launch(Intent(it, CartActivity::class.java)) } } } } } - private fun registerLaunchers(){ - cartLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ activityResult -> - if (activityResult.resultCode == RESULT_OK){ - @Suppress("DEPRECATION") - activityResult.data?.getParcelableArrayListExtra(CartActivity.EXTRA_REMOVED_CART_ITEMS)?.let { - viewModel.removeProductsFromCart(it) - if (it.toSet().contains(shopProduct)){ - binding.addToCart.text = if (shopProduct.added_to_cart == true){ - getString(R.string.view_cart) - }else{ - getString(R.string.add_to_cart) - } - } + private fun setObservers() { + viewModel.currentProductRemovedListener = { + binding.apply { + mShopProduct?.added_to_cart = mShopProduct?.added_to_cart == false + + addToCart.text = if (mShopProduct?.added_to_cart == true) { + getString(R.string.remove_from_cart) + } else { + getString(R.string.add_to_cart) } } } diff --git a/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment1.kt b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment1.kt index 150f094..85eefc6 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment1.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment1.kt @@ -6,7 +6,7 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider -import com.woka.R +import androidx.navigation.fragment.findNavController import com.woka.databinding.FragmentShop1Binding import com.woka.networking.ApiResult import com.woka.shop.adapters.CategoryAdapter @@ -15,7 +15,7 @@ import com.woka.shop.viewmodels.ShopViewModel import com.woka.utils.hide import com.woka.utils.show -class ShopFragment1 private constructor(): Fragment() { +class ShopFragment1 : Fragment() { private lateinit var binding: FragmentShop1Binding private lateinit var viewModel: ShopViewModel @@ -41,7 +41,8 @@ class ShopFragment1 private constructor(): Fragment() { setObservers() if (!viewModel.superCategoryLiveData.isInitialized || - viewModel.superCategoryLiveData.value !is ApiResult.Success) { + viewModel.superCategoryLiveData.value !is ApiResult.Success + ) { viewModel.loadSuperCategories() } @@ -60,10 +61,7 @@ class ShopFragment1 private constructor(): Fragment() { } adapter.onCategoryClickListener = { - parentFragmentManager.beginTransaction() - .replace(R.id.fcv_shop, ShopFragment2.newInstance("${it.id}")) - .addToBackStack(null) - .commitAllowingStateLoss() + findNavController().navigate(ShopFragment1Directions.actionShopFragment1ToShopFragment2(it)) } } } diff --git a/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment2.kt b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment2.kt index 7c81051..f849a86 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment2.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment2.kt @@ -6,7 +6,8 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider -import com.woka.R +import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs import com.woka.databinding.FragmentShop2Binding import com.woka.networking.ApiResult import com.woka.shop.adapters.CategoryAdapter @@ -15,12 +16,18 @@ import com.woka.shop.viewmodels.ShopViewModel import com.woka.utils.hide import com.woka.utils.show -class ShopFragment2 private constructor(private val superCategoryId: String): Fragment() { +class ShopFragment2 : Fragment() { private lateinit var binding: FragmentShop2Binding private lateinit var viewModel: ShopViewModel private lateinit var adapter: CategoryAdapter + private val args: ShopFragment2Args by navArgs() + + private val superCategoryId: String by lazy { + "${args.superCategoryId}" + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -61,10 +68,12 @@ class ShopFragment2 private constructor(private val superCategoryId: String): Fr } adapter.onCategoryClickListener = { - parentFragmentManager.beginTransaction() - .replace(R.id.fcv_shop, ShopFragment3.newInstance(superCategoryId, "${it.id}", "${it.title}")) - .addToBackStack(null) - .commitAllowingStateLoss() + findNavController().navigate( + ShopFragment2Directions.actionShopFragment2ToShopFragment3( + superCategoryId, + "$it" + ) + ) } } } @@ -106,9 +115,4 @@ class ShopFragment2 private constructor(private val superCategoryId: String): Fr } } } - - companion object { - @JvmStatic - fun newInstance(superCategoryId: String) = ShopFragment2(superCategoryId) - } } \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment3.kt b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment3.kt index aed02f7..4473755 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment3.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment3.kt @@ -6,6 +6,7 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider +import androidx.navigation.fragment.navArgs import com.google.android.material.tabs.TabLayout import com.woka.R import com.woka.databinding.FragmentShop3Binding @@ -16,22 +17,17 @@ import com.woka.utils.hide import com.woka.utils.setVisibility import com.woka.utils.show -class ShopFragment3 private constructor( - private val superCategoryId: String, - private val categoryId: String, - private val categoryName: String -) : Fragment(), TabLayout.OnTabSelectedListener { - - companion object { - @JvmStatic - fun newInstance(superCategoryId: String, categoryId: String, categoryName: String) = - ShopFragment3(superCategoryId, categoryId, categoryName) - } +class ShopFragment3 : Fragment(), TabLayout.OnTabSelectedListener { private lateinit var binding: FragmentShop3Binding private lateinit var viewModel: ShopViewModel private lateinit var productAdapter: ShopProductAdapter + private val args: ShopFragment3Args by navArgs() + + private val superCategoryId: String by lazy { args.superCategoryId } + private val categoryId: String by lazy { args.categoryId } + private var loadMoreProducts = false override fun onCreateView( @@ -80,14 +76,11 @@ class ShopFragment3 private constructor( prodLoadMoreBtn.setOnClickListener { loadMoreProducts = true val subCategoryId = categoryTabs.getTabAt(categoryTabs.selectedTabPosition)?.tag?.toString() - viewModel.loadMoreEpisodes(superCategoryId, categoryId, subCategoryId) + viewModel.loadMoreProducts(superCategoryId, categoryId, subCategoryId) } productAdapter.onProductClicked = { - parentFragmentManager.beginTransaction() - .add(R.id.fcv_shop, ProductFragment.newInstance(it, categoryName)) - .addToBackStack(null) - .commit() + } } } diff --git a/app/src/main/res/layout/activity_shop.xml b/app/src/main/res/layout/activity_shop.xml index 9cc207b..c5b3aa6 100644 --- a/app/src/main/res/layout/activity_shop.xml +++ b/app/src/main/res/layout/activity_shop.xml @@ -102,15 +102,11 @@ + app:defaultNavHost="true" + app:navGraph="@navigation/nav_graph_shop" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_my_list.xml b/app/src/main/res/layout/fragment_my_list.xml index 158e803..74d230a 100644 --- a/app/src/main/res/layout/fragment_my_list.xml +++ b/app/src/main/res/layout/fragment_my_list.xml @@ -263,23 +263,41 @@ - - /> + + + + + @@ -12,40 +12,162 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" - app:layout_constraintGuide_percent="0.7" - /> + app:layout_constraintGuide_percent="0.7" /> + app:layout_constraintTop_toBottomOf="@id/g1" /> - + android:layout_height="match_parent" + app:shimmer_auto_start="true" + app:shimmer_duration="1500" + app:shimmer_highlight_alpha="0.5"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -53,25 +175,23 @@ android:id="@+id/vp_images" android:layout_width="match_parent" android:layout_height="@dimen/_120sdp" - android:layout_marginTop="15dp" - /> + android:layout_marginTop="15dp" /> + app:tabRippleColor="@android:color/transparent" /> @@ -115,8 +235,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/sku_id" android:fontFamily="@font/exo_2_bold" + android:text="@string/sku_id" android:textColor="@color/color_primary" android:textSize="@dimen/_12ssp" @@ -127,12 +247,12 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" - tools:text="This is a random text for preview" + android:layout_marginStart="5dp" android:fontFamily="@font/exo_2" android:textColor="@color/color_primary" android:textSize="@dimen/_12ssp" - android:layout_marginStart="5dp" + tools:text="This is a random text for preview" /> @@ -148,17 +268,17 @@ android:layout_width="0dp" android:layout_height="wrap_content" - tools:text="$ 200" android:fontFamily="@font/exo_2_bold" + android:maxLines="1" android:textColor="@color/color_primary" android:textSize="@dimen/_16ssp" - android:maxLines="1" - - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/addToCart" - app:layout_constraintTop_toTopOf="@id/addToCart" app:layout_constraintBottom_toBottomOf="@id/addToCart" + app:layout_constraintEnd_toStartOf="@id/addToCart" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="@id/addToCart" + tools:text="$ 200" + />