diff --git a/app/src/main/java/com/woka/home/fragments/Home2Fragment.kt b/app/src/main/java/com/woka/home/fragments/Home2Fragment.kt index 5556ea6..101bac3 100644 --- a/app/src/main/java/com/woka/home/fragments/Home2Fragment.kt +++ b/app/src/main/java/com/woka/home/fragments/Home2Fragment.kt @@ -7,6 +7,7 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider +import com.jwplayer.pub.api.media.playlists.PlaylistItem import com.woka.R import com.woka.WokaApp import com.woka.audiobooks.views.AudioBooksActivity @@ -15,7 +16,9 @@ import com.woka.home.viewmodels.HomeViewModel import com.woka.home.views.FMActivity import com.woka.karaoke.views.KaraokeActivity import com.woka.networking.ApiResult +import com.woka.players.models.VideoPlayList import com.woka.players.views.LiveStreamPlayerActivity +import com.woka.players.views.PlayerActivity import com.woka.userPreference.UserType import com.woka.userdata.userDataModels.UserDataResponse import com.woka.utils.hide @@ -124,6 +127,29 @@ class Home2Fragment : Fragment() { startActivity(Intent(it, KaraokeActivity::class.java)) } } + + playTrailer.setOnClickListener { + activity?.let { + it.startActivity(Intent(it, PlayerActivity::class.java).apply { + putExtra( + PlayerActivity.EXTRA_PLAY_LIST, + VideoPlayList( + ArrayList().apply { + add( + PlaylistItem.Builder() + .file("https://cdn.jwplayer.com/manifests/Iygt11AD.m3u8") + .image("https://cdn.jwplayer.com/manifests/Iygt11AD.m3u8") + .title("Masila") + .build() + ) + }, + null + ) + ) + putExtra(PlayerActivity.EXTRA_PLAY_INDEX, 0) + }) + } + } } } @@ -149,7 +175,7 @@ class Home2Fragment : Fragment() { exploreWokaTxt.text = getString(R.string.explore_woka) comingSoonTxt.text = getString(R.string.coming_soonn_on_woka) - playTrailer.text = getString(R.string.play_trailer) + playTrailerTxt.text = getString(R.string.play_trailer) masila.text = getString(R.string.masila) } diff --git a/app/src/main/java/com/woka/shop/ShopApiService.kt b/app/src/main/java/com/woka/shop/ShopApiService.kt index d432496..685fba3 100644 --- a/app/src/main/java/com/woka/shop/ShopApiService.kt +++ b/app/src/main/java/com/woka/shop/ShopApiService.kt @@ -1,6 +1,8 @@ package com.woka.shop import com.woka.networking.ApiResponse +import com.woka.shop.models.addresslisting.ParentAddress +import com.woka.shop.models.applycoupon.ApplyCouponResponse import com.woka.shop.models.cartlisting.CartResponse import com.woka.shop.models.categorylisting.CategoryResponse import com.woka.shop.models.couponlisting.CouponsResponse @@ -31,4 +33,10 @@ interface ShopApiService { @GET("coupon_listing") suspend fun couponsListing(): Response> + + @POST("applied_coupon_discount") + suspend fun applyCoupon(@Body formBody: FormBody): Response> + + @GET("parent_address_listing") + suspend fun parentAddressListing(): 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 52af212..4e82ec4 100644 --- a/app/src/main/java/com/woka/shop/ShopRepository.kt +++ b/app/src/main/java/com/woka/shop/ShopRepository.kt @@ -3,6 +3,8 @@ 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.addresslisting.ParentAddress +import com.woka.shop.models.applycoupon.ApplyCouponResponse import com.woka.shop.models.cartlisting.CartResponse import com.woka.shop.models.categorylisting.CategoryResponse import com.woka.shop.models.couponlisting.CouponsResponse @@ -106,4 +108,21 @@ object ShopRepository { apiService.couponsListing() } } + + suspend fun applyCoupon(couponData: String, amount: String): ApiResult { + return handleApiCall { + apiService.applyCoupon( + FormBody.Builder() + .add("coupon_code", couponData) + .add("total_amount", amount) + .build() + ) + } + } + + suspend fun parentAddressListing(): ApiResult> { + return handleApiCall { + apiService.parentAddressListing() + } + } } \ 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 index 3cb3c25..44c922c 100644 --- a/app/src/main/java/com/woka/shop/adapters/CouponAdapter.kt +++ b/app/src/main/java/com/woka/shop/adapters/CouponAdapter.kt @@ -6,11 +6,13 @@ import androidx.recyclerview.widget.AsyncDifferConfig import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView.ViewHolder +import com.woka.R import com.woka.databinding.CouponViewHolderrBinding import com.woka.shop.models.couponlisting.CouponData import java.util.concurrent.Executors -class CouponAdapter : ListAdapter(DIFF_CONFIG) { +class CouponAdapter(private var selectedCouponId: Int?) : + ListAdapter(DIFF_CONFIG) { companion object { private val DIFF_UTIL = object : DiffUtil.ItemCallback() { @@ -18,7 +20,7 @@ class CouponAdapter : ListAdapter(DI oldItem.id == newItem.id override fun areContentsTheSame(oldItem: CouponData, newItem: CouponData): Boolean = - oldItem == newItem + oldItem.id == newItem.id } private val DIFF_CONFIG = AsyncDifferConfig.Builder(DIFF_UTIL) @@ -28,6 +30,10 @@ class CouponAdapter : ListAdapter(DI inner class CouponViewHolder(val binding: CouponViewHolderrBinding) : ViewHolder(binding.root) + var onSelectionChanged: ((CouponData) -> Unit)? = null + + private var selectedCouponPos: Int? = null + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CouponViewHolder { return CouponViewHolder( CouponViewHolderrBinding.inflate( @@ -47,6 +53,28 @@ class CouponAdapter : ListAdapter(DI val finalTxt = "$off OFF with coupon code ${coupon.coupon_code}" textView.text = finalTxt + + textView.setBackgroundResource( + if (selectedCouponId == coupon.id) R.color.coupon_selection + else R.color.white + ) + + root.setOnClickListener { + if (selectedCouponId != coupon.id) { + selectedCouponId = coupon.id + onSelectionChanged?.invoke(coupon) + + selectedCouponPos?.let { + if (it >= 0 && it < currentList.size){ + notifyItemChanged(it) + } + } + + selectedCouponPos = holder.absoluteAdapterPosition + + textView.setBackgroundResource(R.color.coupon_selection) + } + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/models/addresslisting/ParentAddress.kt b/app/src/main/java/com/woka/shop/models/addresslisting/ParentAddress.kt new file mode 100644 index 0000000..af3c12a --- /dev/null +++ b/app/src/main/java/com/woka/shop/models/addresslisting/ParentAddress.kt @@ -0,0 +1,14 @@ +package com.woka.shop.models.addresslisting + +data class ParentAddress( + val address: String?, + val address_name: String?, + val address_type: String?, + val city: String?, + val country: String?, + val email: String?, + val id: Int?, + val phone_no: String?, + val pincode: String?, + val state: String? +) \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/models/applycoupon/ApplyCouponResponse.kt b/app/src/main/java/com/woka/shop/models/applycoupon/ApplyCouponResponse.kt new file mode 100644 index 0000000..ef200e1 --- /dev/null +++ b/app/src/main/java/com/woka/shop/models/applycoupon/ApplyCouponResponse.kt @@ -0,0 +1,7 @@ +package com.woka.shop.models.applycoupon + +data class ApplyCouponResponse( + val cart_discounted_amount: String?, + val cart_total_amount: String?, + val discount_value: String? +) \ 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 index 7379ddb..93d3dc0 100644 --- a/app/src/main/java/com/woka/shop/viewmodels/CartViewModel.kt +++ b/app/src/main/java/com/woka/shop/viewmodels/CartViewModel.kt @@ -6,6 +6,8 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.woka.networking.ApiResult import com.woka.shop.ShopRepository +import com.woka.shop.models.addresslisting.ParentAddress +import com.woka.shop.models.applycoupon.ApplyCouponResponse import com.woka.shop.models.cartlisting.CartResponse import com.woka.shop.models.couponlisting.CouponsResponse import kotlinx.coroutines.launch @@ -14,6 +16,9 @@ class CartViewModel: ViewModel() { // ui callbacks var onToolBarTitleChange: ((String) -> Unit)? = null + var appliedCoupon: String? = null + var selectedCouponId: Int? = null + var selectedCouponCode: String? = null // data callbacks private val repository = ShopRepository @@ -36,4 +41,27 @@ class CartViewModel: ViewModel() { suspend fun loadCoupons(): ApiResult{ return repository.couponsListing() } + + // applying coupon + private val _applyCouponLiveData = MutableLiveData?>() + val applyCouponLiveData: LiveData?> + get() = _applyCouponLiveData + + fun applyCoupon(couponData: String, amount: String){ + viewModelScope.launch { + _applyCouponLiveData.postValue(ApiResult.Loading()) + _applyCouponLiveData.postValue(repository.applyCoupon(couponData, amount)) + } + } + + fun clearAppliedCoupon(){ + _applyCouponLiveData.postValue(null) + appliedCoupon = null + selectedCouponCode = null + selectedCouponId = null + } + + suspend fun parentAddressListing(): ApiResult> { + return repository.parentAddressListing() + } } \ 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 index 6fc8a57..4ad3419 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/CartFragment.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/CartFragment.kt @@ -101,6 +101,7 @@ class CartFragment: Fragment() { } binding.checkout.setOnClickListener { + viewModel.clearAppliedCoupon() findNavController().navigate(R.id.action_cartFragment_to_orderSummaryFragment) } } 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 index 52a61c7..eca9ae8 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/OrderSummaryFragment.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/OrderSummaryFragment.kt @@ -8,14 +8,17 @@ import androidx.core.view.isVisible 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.FragmentOrderSummaryBinding import com.woka.networking.ApiResult import com.woka.shop.adapters.CouponAdapter import com.woka.shop.adapters.SummaryCartAdapter 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 OrderSummaryFragment : Fragment() { @@ -24,6 +27,9 @@ class OrderSummaryFragment : Fragment() { private lateinit var viewModel: CartViewModel private lateinit var adapter: SummaryCartAdapter private lateinit var couponAdapter: CouponAdapter + private lateinit var progressView: ProgressView + + private var cartTotalAmount: String? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -33,7 +39,8 @@ class OrderSummaryFragment : Fragment() { viewModel = ViewModelProvider(requireActivity())[CartViewModel::class.java] adapter = SummaryCartAdapter() - couponAdapter = CouponAdapter() + couponAdapter = CouponAdapter(viewModel.selectedCouponId) + progressView = ProgressView(requireContext()) return binding.root } @@ -50,62 +57,141 @@ class OrderSummaryFragment : Fragment() { loadCoupons() } - private fun initViews(){ + private fun initViews() { binding.apply { viewModel.onToolBarTitleChange?.invoke(getString(R.string.payment_options)) rvCart.adapter = adapter rvCoupons.adapter = couponAdapter + rvCoupons.itemAnimator = null + + couponCode.setText(viewModel.selectedCouponCode) } } - private fun clickEvents(){ + private fun clickEvents() { binding.apply { - showCoupons.setOnClickListener{ - if (rvCoupons.isVisible){ - rvCoupons.hide() + showCoupons.setOnClickListener { + if (couponsView.isVisible) { + couponsView.hide() showCouponIndicator.setImageResource(R.drawable.ic_half_arrow_right) - }else{ - rvCoupons.show() + } else { + couponsView.show() showCouponIndicator.setImageResource(R.drawable.ic_half_arrow_up) } } + + applyBtn.setOnClickListener { + if (couponCode.text.isEmpty()) { + toast(getString(R.string.enter_a_valid_coupon_code)) + return@setOnClickListener + } + + if (viewModel.appliedCoupon == couponCode.text.toString()) { + toast(getString(R.string.coupon_already_applied)) + return@setOnClickListener + } + + viewModel.applyCoupon(couponCode.text.toString(), "$cartTotalAmount") + } + + confirm.setOnClickListener { + findNavController().navigate(R.id.action_orderSummaryFragment_to_parentAddressFragment) + } } } - private fun loadCoupons(){ + private fun loadCoupons() { lifecycleScope.launch { - when (val response = viewModel.loadCoupons()){ + when (val response = viewModel.loadCoupons()) { is ApiResult.Error -> {} is ApiResult.Loading -> {} is ApiResult.Success -> { response.data?.result?.filterNotNull()?.let { - couponAdapter.submitList(it) + if (it.isNotEmpty()) { + couponAdapter.submitList(it) { + binding.rvCoupons.show() + binding.noCouponsView.hide() + } + + return@launch + } } + + binding.rvCoupons.hide() + binding.noCouponsView.show() } } } } private fun setObservers() { - viewModel.cartListLiveData.observe(viewLifecycleOwner){ + couponAdapter.onSelectionChanged = { + binding.couponCode.setText(it.coupon_code) + viewModel.selectedCouponCode = it.coupon_code + viewModel.selectedCouponId = it.id + } + + viewModel.applyCouponLiveData.observe(viewLifecycleOwner) { + when (it) { + is ApiResult.Error -> { + progressView.hide() + toast(it.errorMessage) + } + + is ApiResult.Loading -> { + progressView.show(getString(R.string.applying_coupon)) + } + + is ApiResult.Success -> { + progressView.hide() + it.data?.let { + binding.apply { + + viewModel.appliedCoupon = couponCode.text.toString() + + subTotalAmount.text = it.cart_total_amount + discountAmount.text = it.discount_value + totalAmount.text = it.cart_discounted_amount + + discountView.show() + + discountView.post { + root.smoothScrollTo(0, root.height + discountView.height) + } + } + } + } + + null -> {} + } + } + + viewModel.cartListLiveData.observe(viewLifecycleOwner) { binding.apply { - when (it){ + 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()){ + it.data?.let { cartData -> + cartData.result?.let { cartList -> + if (cartList.isNotEmpty()) { mainLayout.show() - adapter.submitList(cartList){ + adapter.submitList(cartList) { rvCart.show() + + val finalAmount = "₹ ${cartData.total_amount}" + totalAmount.text = finalAmount + + cartTotalAmount = "${cartData.total_amount?.toInt()}" } - }else{ + } else { // cart is empty rvCart.hide() } diff --git a/app/src/main/java/com/woka/shop/views/fragments/ParentAddressFragment.kt b/app/src/main/java/com/woka/shop/views/fragments/ParentAddressFragment.kt new file mode 100644 index 0000000..3d4176d --- /dev/null +++ b/app/src/main/java/com/woka/shop/views/fragments/ParentAddressFragment.kt @@ -0,0 +1,38 @@ +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 com.woka.R +import com.woka.databinding.FragmentParentAddressBinding +import com.woka.shop.viewmodels.CartViewModel + +class ParentAddressFragment : Fragment() { + + private lateinit var binding: FragmentParentAddressBinding + private lateinit var viewModel: CartViewModel + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentParentAddressBinding.inflate(inflater, container, false) + viewModel = ViewModelProvider(requireActivity())[CartViewModel::class.java] + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + initViews() + } + + private fun initViews(){ + binding.apply { + viewModel.onToolBarTitleChange?.invoke(getString(R.string.address_details)) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/round_stroke_25.xml b/app/src/main/res/drawable/round_stroke_25.xml new file mode 100644 index 0000000..9aaa6f1 --- /dev/null +++ b/app/src/main/res/drawable/round_stroke_25.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/cart_address_view_holder.xml b/app/src/main/res/layout/cart_address_view_holder.xml new file mode 100644 index 0000000..f9c6a25 --- /dev/null +++ b/app/src/main/res/layout/cart_address_view_holder.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home2.xml b/app/src/main/res/layout/fragment_home2.xml index 77eaa3e..53f1364 100644 --- a/app/src/main/res/layout/fragment_home2.xml +++ b/app/src/main/res/layout/fragment_home2.xml @@ -590,6 +590,7 @@ /> - - tools:itemCount="3" - tools:listitem="@layout/coupon_view_holderr" - app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" - /> + + + + +