diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 65fef7f..c20acc2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,11 +17,20 @@ android:supportsRtl="true" android:theme="@style/Theme.Woka" tools:targetApi="31"> + + + android:windowSoftInputMode="adjustPan" /> > @@ -25,6 +31,7 @@ interface ShopApiService { @POST("sub_category_listing") suspend fun subcategoryListing(@Body formBody: FormBody): Response> + // cart @GET("cart_listing") suspend fun cartListing(): Response> @@ -38,5 +45,17 @@ interface ShopApiService { suspend fun applyCoupon(@Body formBody: FormBody): Response> @GET("parent_address_listing") - suspend fun parentAddressListing(): Response>> + suspend fun parentAddressListing(): Response>> + + @POST("add_parent_address") + suspend fun addAddress(@Body addAddressRequestData: AddAddressRequestData): Response> + + @POST("pincode_serviceability_check_edd") + suspend fun getEDD(@Body formBody: FormBody): Response> + + @POST("create_new_order") + suspend fun createOrder(@Body withCoupon: CreateOrderRequestData.WithCoupon): Response> + + @POST("create_new_order") + suspend fun createOrder(@Body withCoupon: CreateOrderRequestData.WithoutCoupon): 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 4e82ec4..9e6358d 100644 --- a/app/src/main/java/com/woka/shop/ShopRepository.kt +++ b/app/src/main/java/com/woka/shop/ShopRepository.kt @@ -3,11 +3,16 @@ 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.addaddress.AddAddressRequestData +import com.woka.shop.models.addaddress.AddAddressResponseData +import com.woka.shop.models.addresslisting.ParentAddressData 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 +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.subcategorylisting.SubCategoryResponse import com.woka.shop.models.superlisting.SuperCategoryResponse import okhttp3.FormBody @@ -120,9 +125,39 @@ object ShopRepository { } } - suspend fun parentAddressListing(): ApiResult> { + // address + suspend fun parentAddressListing(): ApiResult> { return handleApiCall { apiService.parentAddressListing() } } + + suspend fun addAddress(addAddressRequestData: AddAddressRequestData): ApiResult { + return handleApiCall { + apiService.addAddress(addAddressRequestData) + } + } + + suspend fun getEDD(pinCode: String): ApiResult { + return handleApiCall { + apiService.getEDD( + FormBody.Builder() + .add("pincode", pinCode) + .build() + ) + } + } + + // create order + suspend fun createOrder(withCoupon: CreateOrderRequestData.WithCoupon): ApiResult { + return handleApiCall { + apiService.createOrder(withCoupon) + } + } + + suspend fun createOrder(withoutCoupon: CreateOrderRequestData.WithoutCoupon): ApiResult { + return handleApiCall { + apiService.createOrder(withoutCoupon) + } + } } \ 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 44c922c..02beb15 100644 --- a/app/src/main/java/com/woka/shop/adapters/CouponAdapter.kt +++ b/app/src/main/java/com/woka/shop/adapters/CouponAdapter.kt @@ -55,7 +55,10 @@ class CouponAdapter(private var selectedCouponId: Int?) : textView.text = finalTxt textView.setBackgroundResource( - if (selectedCouponId == coupon.id) R.color.coupon_selection + if (selectedCouponId == coupon.id){ + selectedCouponPos = holder.absoluteAdapterPosition + R.color.coupon_selection + } else R.color.white ) diff --git a/app/src/main/java/com/woka/shop/adapters/ParentAddressAdapter.kt b/app/src/main/java/com/woka/shop/adapters/ParentAddressAdapter.kt new file mode 100644 index 0000000..e616d1a --- /dev/null +++ b/app/src/main/java/com/woka/shop/adapters/ParentAddressAdapter.kt @@ -0,0 +1,123 @@ +package com.woka.shop.adapters + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.lifecycle.viewModelScope +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.CartAddressViewHolderBinding +import com.woka.shop.models.addresslisting.ParentAddressData +import com.woka.shop.viewmodels.CartViewModel +import com.woka.utils.hide +import com.woka.utils.show +import kotlinx.coroutines.launch +import java.util.concurrent.Executors + +class ParentAddressAdapter (private val viewModel: CartViewModel) : + ListAdapter(ASYNC_DIFF_UTIL) { + + companion object { + private val DIFF_UTIL = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame( + oldItem: ParentAddressData, newItem: ParentAddressData + ): Boolean = oldItem.id == newItem.id + + override fun areContentsTheSame( + oldItem: ParentAddressData, newItem: ParentAddressData + ): Boolean = oldItem == newItem + } + + private val ASYNC_DIFF_UTIL = AsyncDifferConfig.Builder(DIFF_UTIL) + .setBackgroundThreadExecutor(Executors.newSingleThreadExecutor()).build() + } + + inner class AddressViewHolder(val binding: CartAddressViewHolderBinding) : + ViewHolder(binding.root) + + var addressSelectListener: ((Int?) -> Unit)? = null + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddressViewHolder { + return AddressViewHolder( + CartAddressViewHolderBinding.inflate( + LayoutInflater.from(parent.context), parent, false + ) + ) + } + + override fun onBindViewHolder(holder: AddressViewHolder, position: Int) { + val address = getItem(holder.absoluteAdapterPosition) + + with(holder.binding) { + name.text = "${address.address_name}" + val fullAddress = StringBuilder("${address.address}") + + address.city?.let { + fullAddress.append(", ").append(it) + } + + address.state?.let { + fullAddress.append(", ").append(it) + } + + address.country?.let { + fullAddress.append(", ").append(it) + } + + address.pincode?.let { + fullAddress.append("\nPinCode: ").append(it) + } + + address.phone_no?.let { + fullAddress.append("\nPhone no: ").append(it) + } + + addressTxt.text = fullAddress + + selectBtn.isChecked = viewModel.selectedAddressPos == holder.absoluteAdapterPosition + if (selectBtn.isChecked){ + expectedDelivery.show() + expectedDelivery.text = viewModel.eddMap.getOrDefault(address.id, null) + }else{ + expectedDelivery.hide() + } + + root.setOnClickListener { + selectBtn.performClick() + } + + selectBtn.setOnClickListener { + if (viewModel.selectedAddressPos != holder.absoluteAdapterPosition) { + val lastSelectedPos = viewModel.selectedAddressPos + viewModel.selectedAddressPos = holder.absoluteAdapterPosition + + if (lastSelectedPos >= 0 && lastSelectedPos < currentList.size) { + notifyItemChanged(lastSelectedPos) + } + + selectBtn.isChecked = true + addressSelectListener?.invoke(address.id) + + viewModel.viewModelScope.launch { + address.id?.let {id -> + if (viewModel.eddMap.containsKey(id)){ + expectedDelivery.show() + expectedDelivery.text = viewModel.eddMap[id] + }else{ + address.pincode?.let {pin -> + viewModel.getEDD(pin)?.let {edd -> + viewModel.eddMap[id] = "${root.context.getString(R.string.expected_delivery_by)}$edd" + expectedDelivery.show() + expectedDelivery.text = viewModel.eddMap[id] + } + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/models/addaddress/AddAddressRequestData.kt b/app/src/main/java/com/woka/shop/models/addaddress/AddAddressRequestData.kt new file mode 100644 index 0000000..e2fb966 --- /dev/null +++ b/app/src/main/java/com/woka/shop/models/addaddress/AddAddressRequestData.kt @@ -0,0 +1,10 @@ +package com.woka.shop.models.addaddress + +data class AddAddressRequestData( + val address_name: String, + val address: String, + val city: String, + val state: String, + val pincode: String, + val mobile_number: String +) diff --git a/app/src/main/java/com/woka/shop/models/addaddress/AddAddressResponseData.kt b/app/src/main/java/com/woka/shop/models/addaddress/AddAddressResponseData.kt new file mode 100644 index 0000000..b0d04f3 --- /dev/null +++ b/app/src/main/java/com/woka/shop/models/addaddress/AddAddressResponseData.kt @@ -0,0 +1,16 @@ +package com.woka.shop.models.addaddress + +data class AddAddressResponseData( + val address: String?, + val address_name: String?, + val city: String?, + val country: String?, + val created_at: String?, + val email: String?, + val id: Int?, + val phone_no: String?, + val pincode: String?, + val state: String?, + val updated_at: String?, + val user_id: String? +) \ 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/ParentAddressData.kt similarity index 90% rename from app/src/main/java/com/woka/shop/models/addresslisting/ParentAddress.kt rename to app/src/main/java/com/woka/shop/models/addresslisting/ParentAddressData.kt index af3c12a..eed9f5f 100644 --- a/app/src/main/java/com/woka/shop/models/addresslisting/ParentAddress.kt +++ b/app/src/main/java/com/woka/shop/models/addresslisting/ParentAddressData.kt @@ -1,6 +1,6 @@ package com.woka.shop.models.addresslisting -data class ParentAddress( +data class ParentAddressData( val address: String?, val address_name: String?, val address_type: String?, diff --git a/app/src/main/java/com/woka/shop/models/createorder/CreateOrderRequestData.kt b/app/src/main/java/com/woka/shop/models/createorder/CreateOrderRequestData.kt new file mode 100644 index 0000000..1745969 --- /dev/null +++ b/app/src/main/java/com/woka/shop/models/createorder/CreateOrderRequestData.kt @@ -0,0 +1,14 @@ +package com.woka.shop.models.createorder + +class CreateOrderRequestData{ + data class WithCoupon( + val product_ids: ArrayList, + val coupon_code: String, + val address_id: String + ) + + data class WithoutCoupon( + val product_ids: ArrayList, + val address_id: String + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/models/createorder/CreateOrderResponse.kt b/app/src/main/java/com/woka/shop/models/createorder/CreateOrderResponse.kt new file mode 100644 index 0000000..e35e137 --- /dev/null +++ b/app/src/main/java/com/woka/shop/models/createorder/CreateOrderResponse.kt @@ -0,0 +1,5 @@ +package com.woka.shop.models.createorder + +data class CreateOrderResponse( + val url: String? +) \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/models/edd/EDDResponse.kt b/app/src/main/java/com/woka/shop/models/edd/EDDResponse.kt new file mode 100644 index 0000000..f3d007f --- /dev/null +++ b/app/src/main/java/com/woka/shop/models/edd/EDDResponse.kt @@ -0,0 +1,5 @@ +package com.woka.shop.models.edd + +data class EDDResponse( + val result: Result? +) \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/models/edd/Result.kt b/app/src/main/java/com/woka/shop/models/edd/Result.kt new file mode 100644 index 0000000..f41239e --- /dev/null +++ b/app/src/main/java/com/woka/shop/models/edd/Result.kt @@ -0,0 +1,9 @@ +package com.woka.shop.models.edd + +data class Result( + val EDD: String?, + val fm_message: String?, + val fm_pincode: String?, + val lm_message: String?, + val lm_pincode: String? +) \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/viewmodels/AddressViewModel.kt b/app/src/main/java/com/woka/shop/viewmodels/AddressViewModel.kt new file mode 100644 index 0000000..e2037ce --- /dev/null +++ b/app/src/main/java/com/woka/shop/viewmodels/AddressViewModel.kt @@ -0,0 +1,22 @@ +package com.woka.shop.viewmodels + +import androidx.lifecycle.ViewModel +import com.woka.networking.ApiResult +import com.woka.shop.ShopRepository +import com.woka.shop.models.addaddress.AddAddressRequestData +import com.woka.shop.models.addaddress.AddAddressResponseData +import com.woka.shop.models.edd.EDDResponse + +class AddressViewModel: ViewModel() { + + private val repository = ShopRepository + + suspend fun addAddress(addressRequestData: AddAddressRequestData): ApiResult { + return repository.addAddress(addressRequestData) + } + + suspend fun getEDD(pinCode: String): ApiResult { + return repository.getEDD(pinCode) + } + +} \ 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 93d3dc0..151e4ca 100644 --- a/app/src/main/java/com/woka/shop/viewmodels/CartViewModel.kt +++ b/app/src/main/java/com/woka/shop/viewmodels/CartViewModel.kt @@ -6,20 +6,31 @@ 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.addresslisting.ParentAddressData import com.woka.shop.models.applycoupon.ApplyCouponResponse import com.woka.shop.models.cartlisting.CartResponse import com.woka.shop.models.couponlisting.CouponsResponse +import com.woka.shop.models.createorder.CreateOrderRequestData +import com.woka.shop.models.createorder.CreateOrderResponse +import kotlinx.coroutines.async import kotlinx.coroutines.launch class CartViewModel: ViewModel() { // ui callbacks + + // coupons var onToolBarTitleChange: ((String) -> Unit)? = null var appliedCoupon: String? = null var selectedCouponId: Int? = null var selectedCouponCode: String? = null + // address + var selectedAddressPos: Int = -1 + var selectedAddressId: Int? = null + val eddMap = HashMap() + + // data callbacks private val repository = ShopRepository @@ -61,7 +72,60 @@ class CartViewModel: ViewModel() { selectedCouponId = null } - suspend fun parentAddressListing(): ApiResult> { - return repository.parentAddressListing() + // addresses + private val _addressesLiveData = MutableLiveData>>() + val addressesLiveData: LiveData>> + get() = _addressesLiveData + + fun loadParentAddresses(){ + if (_addressesLiveData.isInitialized && _addressesLiveData.value is ApiResult.Success){ + return + } + + viewModelScope.launch { + _addressesLiveData.postValue(ApiResult.Loading()) + _addressesLiveData.postValue(repository.parentAddressListing()) + } + } + + fun clearAddressSelection(){ + selectedAddressPos = -1 + selectedAddressId = null + eddMap.clear() + _createOrderLiveData.postValue(null) + } + + suspend fun getEDD(pinCode: String): String? { + return viewModelScope.async { + when (val response = repository.getEDD(pinCode)){ + is ApiResult.Error -> null + is ApiResult.Loading -> null + is ApiResult.Success -> response.data?.result?.EDD + } + }.await() + } + + // creating order + private val _createOrderLiveData = MutableLiveData?>() + val createOrderLiveData: LiveData?> + get() = _createOrderLiveData + + fun createOrder(productIds: ArrayList, couponCode: String?, addressId: String) { + viewModelScope.launch { + _createOrderLiveData.postValue(ApiResult.Loading()) + _createOrderLiveData.postValue( + if (couponCode == null){ + // no coupon code + repository.createOrder(CreateOrderRequestData.WithoutCoupon( + productIds, addressId + )) + }else{ + // coupon code applied + repository.createOrder(CreateOrderRequestData.WithCoupon( + productIds, couponCode, addressId + )) + } + ) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/views/AddressActivity.kt b/app/src/main/java/com/woka/shop/views/AddressActivity.kt new file mode 100644 index 0000000..511ceba --- /dev/null +++ b/app/src/main/java/com/woka/shop/views/AddressActivity.kt @@ -0,0 +1,33 @@ +package com.woka.shop.views + +import android.os.Bundle +import androidx.activity.enableEdgeToEdge +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import com.woka.R +import com.woka.databinding.ActivityAddressBinding +import com.woka.shop.views.fragments.address.PinCodeFragment +import com.woka.utils.WokaBaseActivity + +class AddressActivity : WokaBaseActivity() { + + private lateinit var binding: ActivityAddressBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + binding = ActivityAddressBinding.inflate(layoutInflater) + setContentView(binding.root) + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> + val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) + insets + } + + binding.toolbar.title.text = getString(R.string.address_details) + + supportFragmentManager.beginTransaction() + .add(R.id.fcv_address, PinCodeFragment.newInstance()) + .commit() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/views/PaymentActivity.kt b/app/src/main/java/com/woka/shop/views/PaymentActivity.kt new file mode 100644 index 0000000..1fea1b8 --- /dev/null +++ b/app/src/main/java/com/woka/shop/views/PaymentActivity.kt @@ -0,0 +1,74 @@ +package com.woka.shop.views + +import android.annotation.SuppressLint +import android.graphics.Color +import android.os.Build +import android.os.Bundle +import android.webkit.WebSettings +import android.webkit.WebViewClient +import androidx.activity.enableEdgeToEdge +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import com.woka.R +import com.woka.databinding.ActivityPaymentBinding +import com.woka.utils.WokaBaseActivity +import com.woka.utils.lightStatusBar +import com.woka.utils.toast + +class PaymentActivity : WokaBaseActivity() { + + companion object{ + const val EXTRA_PAYMENT_LINK = "payment_link" + } + + private lateinit var binding: ActivityPaymentBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + binding = ActivityPaymentBinding.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 + } + + intent.getStringExtra(EXTRA_PAYMENT_LINK)?.let { + + with(window){ + lightStatusBar() + statusBarColor = Color.BLACK + navigationBarColor = Color.BLACK + } + + initWebView(it) + + }?:{ + toast(getString(R.string.couldn_t_load_payment_page)) + finish() + } + } + + override fun onDestroy() { + super.onDestroy() + binding.webView.destroy() + } + + @SuppressLint("SetJavaScriptEnabled") + private fun initWebView(it: String){ + val webSettings: WebSettings = binding.webView.getSettings() + webSettings.javaScriptEnabled = true + + webSettings.allowFileAccess = false + webSettings.allowContentAccess = false + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + webSettings.safeBrowsingEnabled = true + } + + binding.webView.setWebViewClient(WebViewClient()) + + binding.webView.loadUrl(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 28dfb36..1da9970 100644 --- a/app/src/main/java/com/woka/shop/views/ShopActivity.kt +++ b/app/src/main/java/com/woka/shop/views/ShopActivity.kt @@ -7,7 +7,7 @@ import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import com.woka.R import com.woka.databinding.ActivityShopBinding -import com.woka.shop.views.fragments.ShopFragment1 +import com.woka.shop.views.fragments.shop.ShopFragment1 import com.woka.utils.WokaBaseActivity class ShopActivity : WokaBaseActivity() { 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 deleted file mode 100644 index 3d4176d..0000000 --- a/app/src/main/java/com/woka/shop/views/fragments/ParentAddressFragment.kt +++ /dev/null @@ -1,38 +0,0 @@ -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/java/com/woka/shop/views/fragments/address/PinCodeFragment.kt b/app/src/main/java/com/woka/shop/views/fragments/address/PinCodeFragment.kt new file mode 100644 index 0000000..0ea4db4 --- /dev/null +++ b/app/src/main/java/com/woka/shop/views/fragments/address/PinCodeFragment.kt @@ -0,0 +1,99 @@ +package com.woka.shop.views.fragments.address + +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.widget.addTextChangedListener +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope +import com.woka.R +import com.woka.databinding.FragmentPinCodeBinding +import com.woka.networking.ApiResult +import com.woka.shop.viewmodels.AddressViewModel +import com.woka.utils.ProgressView +import com.woka.utils.toast +import kotlinx.coroutines.launch + +class PinCodeFragment private constructor(): Fragment() { + + private lateinit var binding: FragmentPinCodeBinding + private lateinit var progressView: ProgressView + private lateinit var viewModel: AddressViewModel + + private var selectedPinCode: String = "" + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentPinCodeBinding.inflate(inflater, container, false) + progressView = ProgressView(requireContext(), getString(R.string.please_wait)) + viewModel = ViewModelProvider(requireActivity())[AddressViewModel::class.java] + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + clickEvents() + + setObservers() + + } + + private fun clickEvents() { + binding.apply { + btn.setOnClickListener { + if (selectedPinCode.length == 6){ + toast(selectedPinCode) + return@setOnClickListener + } + + if (pincode.text.length < 6){ + pincode.error = getString(R.string.enter_a_valid_pincode) + return@setOnClickListener + } + + lifecycleScope.launch { + binding.apply { + val pinCode = pincode.text.toString() + progressView.show() + when (val response = viewModel.getEDD(pinCode)){ + is ApiResult.Error -> { + progressView.hide() + textView.text = response.errorMessage + } + is ApiResult.Loading -> {} + is ApiResult.Success -> { + progressView.hide() + val finalText = "${response.message}\nExpected delivery by ${response.data?.result?.EDD}" + textView.text = finalText + + selectedPinCode = pinCode + btn.text = getString(R.string.proceed) + + } + } + } + } + } + } + } + + private fun setObservers(){ + binding.pincode.addTextChangedListener { + if (selectedPinCode.length == 6){ + selectedPinCode = "" + binding.btn.text = getString(R.string.check_now) + binding.textView.text = null + } + } + } + + companion object { + @JvmStatic + fun newInstance() = PinCodeFragment() + } +} \ 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/cart/CartFragment.kt similarity index 99% rename from app/src/main/java/com/woka/shop/views/fragments/CartFragment.kt rename to app/src/main/java/com/woka/shop/views/fragments/cart/CartFragment.kt index 4ad3419..a7ba799 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/CartFragment.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/cart/CartFragment.kt @@ -1,4 +1,4 @@ -package com.woka.shop.views.fragments +package com.woka.shop.views.fragments.cart import android.os.Bundle import android.view.LayoutInflater diff --git a/app/src/main/java/com/woka/shop/views/fragments/OrderSummaryFragment.kt b/app/src/main/java/com/woka/shop/views/fragments/cart/OrderSummaryFragment.kt similarity index 97% rename from app/src/main/java/com/woka/shop/views/fragments/OrderSummaryFragment.kt rename to app/src/main/java/com/woka/shop/views/fragments/cart/OrderSummaryFragment.kt index eca9ae8..3da70f8 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/OrderSummaryFragment.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/cart/OrderSummaryFragment.kt @@ -1,4 +1,4 @@ -package com.woka.shop.views.fragments +package com.woka.shop.views.fragments.cart import android.os.Bundle import android.view.LayoutInflater @@ -17,6 +17,7 @@ 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.setVisibility import com.woka.utils.show import com.woka.utils.toast import kotlinx.coroutines.launch @@ -66,6 +67,7 @@ class OrderSummaryFragment : Fragment() { rvCoupons.itemAnimator = null couponCode.setText(viewModel.selectedCouponCode) + discountView.setVisibility(viewModel.appliedCoupon != null) } } @@ -96,6 +98,7 @@ class OrderSummaryFragment : Fragment() { } confirm.setOnClickListener { + viewModel.clearAddressSelection() findNavController().navigate(R.id.action_orderSummaryFragment_to_parentAddressFragment) } } diff --git a/app/src/main/java/com/woka/shop/views/fragments/cart/ParentAddressFragment.kt b/app/src/main/java/com/woka/shop/views/fragments/cart/ParentAddressFragment.kt new file mode 100644 index 0000000..bef3278 --- /dev/null +++ b/app/src/main/java/com/woka/shop/views/fragments/cart/ParentAddressFragment.kt @@ -0,0 +1,182 @@ +package com.woka.shop.views.fragments.cart + +import android.content.Intent +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.networking.ApiResult +import com.woka.shop.adapters.ParentAddressAdapter +import com.woka.shop.models.cartlisting.CartResponse +import com.woka.shop.viewmodels.CartViewModel +import com.woka.shop.views.AddressActivity +import com.woka.shop.views.PaymentActivity +import com.woka.shop.views.PaymentActivity.Companion.EXTRA_PAYMENT_LINK +import com.woka.utils.ProgressView +import com.woka.utils.hide +import com.woka.utils.setVisibility +import com.woka.utils.show +import com.woka.utils.toast + +class ParentAddressFragment : Fragment() { + + private lateinit var binding: FragmentParentAddressBinding + private lateinit var viewModel: CartViewModel + private lateinit var adapter: ParentAddressAdapter + + private lateinit var progressView: ProgressView + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentParentAddressBinding.inflate(inflater, container, false) + viewModel = ViewModelProvider(requireActivity())[CartViewModel::class.java] + adapter = ParentAddressAdapter(viewModel) + + progressView = ProgressView(requireContext(), getString(R.string.please_wait)) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + initViews() + + clickEvents() + + setObservers() + + viewModel.loadParentAddresses() + } + + private fun initViews() { + binding.apply { + viewModel.onToolBarTitleChange?.invoke(getString(R.string.address_details)) + + rvAddresses.adapter = adapter + + selectAddress.setVisibility(viewModel.selectedAddressId != null) + } + } + + private fun clickEvents(){ + binding.apply { + selectAddress.setOnClickListener { + val productIds = ArrayList() + + if (viewModel.cartListLiveData.value is ApiResult.Success){ + (viewModel.cartListLiveData.value as ApiResult.Success).data?.result?.let { + for (cartItem in it){ + cartItem?.id?.let {id -> + productIds.add(id) + } + } + } + } + + if (productIds.isEmpty()){ + toast(getString(R.string.no_products_added_to_cart)) + return@setOnClickListener + } + + if (viewModel.selectedAddressId == null){ + toast(getString(R.string.no_address_selected)) + return@setOnClickListener + } + + viewModel.createOrder(productIds, viewModel.appliedCoupon, "${viewModel.selectedAddressId}") + } + + addNewAddress.setOnClickListener { + activity?.let { + it.startActivity(Intent(it, AddressActivity::class.java)) + } + } + } + } + + private fun setObservers() { + adapter.addressSelectListener = { addressId -> + binding.selectAddress.show() + viewModel.selectedAddressId = addressId + } + + viewModel.createOrderLiveData.observe(viewLifecycleOwner){ + when(it){ + is ApiResult.Error -> { + progressView.hide() + toast(it.errorMessage) + } + is ApiResult.Loading -> { + progressView.show() + } + is ApiResult.Success -> { + progressView.hide() + + it.data?.url?.let {paymentUrl -> + activity?.let {activity -> + activity.startActivity( + Intent(activity, PaymentActivity::class.java).apply { + putExtra(EXTRA_PAYMENT_LINK, paymentUrl) + } + ) + } + } + } + null -> {} + } + } + + viewModel.addressesLiveData.observe(viewLifecycleOwner){ + binding.apply { + when (it) { + is ApiResult.Error -> { + rvAddresses.hide() + noDataView.show() + + shimmer.hide() + + addNewAddress.show() + } + + is ApiResult.Loading -> { + // loading + rvAddresses.hide() + noDataView.hide() + shimmer.show() + + addNewAddress.hide() + } + is ApiResult.Success -> { + it.data?.let { + if (it.isNotEmpty()) { + adapter.submitList(it) { + rvAddresses.show() + + noDataView.hide() + shimmer.hide() + + addNewAddress.show() + } + + return@observe + } + } + + rvAddresses.hide() + noDataView.show() + + shimmer.hide() + + addNewAddress.show() + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/woka/shop/views/fragments/ShopFragment1.kt b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment1.kt similarity index 98% rename from app/src/main/java/com/woka/shop/views/fragments/ShopFragment1.kt rename to app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment1.kt index e298567..150f094 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/ShopFragment1.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment1.kt @@ -1,4 +1,4 @@ -package com.woka.shop.views.fragments +package com.woka.shop.views.fragments.shop import android.os.Bundle import android.view.LayoutInflater diff --git a/app/src/main/java/com/woka/shop/views/fragments/ShopFragment2.kt b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment2.kt similarity index 98% rename from app/src/main/java/com/woka/shop/views/fragments/ShopFragment2.kt rename to app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment2.kt index a140d85..812e515 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/ShopFragment2.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment2.kt @@ -1,4 +1,4 @@ -package com.woka.shop.views.fragments +package com.woka.shop.views.fragments.shop import android.os.Bundle import android.view.LayoutInflater diff --git a/app/src/main/java/com/woka/shop/views/fragments/ShopFragment3.kt b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment3.kt similarity index 98% rename from app/src/main/java/com/woka/shop/views/fragments/ShopFragment3.kt rename to app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment3.kt index b98d998..f74d520 100644 --- a/app/src/main/java/com/woka/shop/views/fragments/ShopFragment3.kt +++ b/app/src/main/java/com/woka/shop/views/fragments/shop/ShopFragment3.kt @@ -1,4 +1,4 @@ -package com.woka.shop.views.fragments +package com.woka.shop.views.fragments.shop import android.os.Bundle import android.view.LayoutInflater diff --git a/app/src/main/res/layout/activity_address.xml b/app/src/main/res/layout/activity_address.xml new file mode 100644 index 0000000..087efba --- /dev/null +++ b/app/src/main/res/layout/activity_address.xml @@ -0,0 +1,23 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_payment.xml b/app/src/main/res/layout/activity_payment.xml new file mode 100644 index 0000000..fc25493 --- /dev/null +++ b/app/src/main/res/layout/activity_payment.xml @@ -0,0 +1,16 @@ + + + + + + \ 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 index f9c6a25..8427278 100644 --- a/app/src/main/res/layout/cart_address_view_holder.xml +++ b/app/src/main/res/layout/cart_address_view_holder.xml @@ -1,14 +1,14 @@ + android:layout_marginBottom="5dp"> - - + tools:context=".shop.views.fragments.cart.CartFragment"> + tools:context=".shop.views.fragments.cart.OrderSummaryFragment"> + tools:context=".shop.views.fragments.cart.ParentAddressFragment"> + app:layout_constraintBottom_toTopOf="@id/buttons"/> + app:layout_constraintBottom_toTopOf="@id/buttons"> diff --git a/app/src/main/res/layout/fragment_pin_code.xml b/app/src/main/res/layout/fragment_pin_code.xml new file mode 100644 index 0000000..fbe9f89 --- /dev/null +++ b/app/src/main/res/layout/fragment_pin_code.xml @@ -0,0 +1,89 @@ + + + + + + + + + +