From 78c309e0463e3b5c374ab1f124089f49bf88b168 Mon Sep 17 00:00:00 2001 From: AdityaGaikwad Date: Fri, 26 Jul 2024 21:22:40 +0530 Subject: [PATCH] Address view created. Address selection in adapter. EDD api integration and caching. order creation api integration. PaymentActivity created to load payment url. AddressActivity creation and api integration for edd on pincode check screen --- app/src/main/AndroidManifest.xml | 11 +- .../main/java/com/woka/shop/ShopApiService.kt | 23 ++- .../main/java/com/woka/shop/ShopRepository.kt | 39 +++- .../com/woka/shop/adapters/CouponAdapter.kt | 5 +- .../shop/adapters/ParentAddressAdapter.kt | 123 ++++++++++++ .../addaddress/AddAddressRequestData.kt | 10 + .../addaddress/AddAddressResponseData.kt | 16 ++ ...{ParentAddress.kt => ParentAddressData.kt} | 2 +- .../createorder/CreateOrderRequestData.kt | 14 ++ .../models/createorder/CreateOrderResponse.kt | 5 + .../com/woka/shop/models/edd/EDDResponse.kt | 5 + .../java/com/woka/shop/models/edd/Result.kt | 9 + .../woka/shop/viewmodels/AddressViewModel.kt | 22 +++ .../com/woka/shop/viewmodels/CartViewModel.kt | 70 ++++++- .../com/woka/shop/views/AddressActivity.kt | 33 ++++ .../com/woka/shop/views/PaymentActivity.kt | 74 +++++++ .../java/com/woka/shop/views/ShopActivity.kt | 2 +- .../views/fragments/ParentAddressFragment.kt | 38 ---- .../fragments/address/PinCodeFragment.kt | 99 ++++++++++ .../fragments/{ => cart}/CartFragment.kt | 2 +- .../{ => cart}/OrderSummaryFragment.kt | 5 +- .../fragments/cart/ParentAddressFragment.kt | 182 ++++++++++++++++++ .../fragments/{ => shop}/ShopFragment1.kt | 2 +- .../fragments/{ => shop}/ShopFragment2.kt | 2 +- .../fragments/{ => shop}/ShopFragment3.kt | 2 +- app/src/main/res/layout/activity_address.xml | 23 +++ app/src/main/res/layout/activity_payment.xml | 16 ++ .../res/layout/cart_address_view_holder.xml | 27 +-- app/src/main/res/layout/fragment_cart.xml | 2 +- .../res/layout/fragment_order_summary.xml | 2 +- .../res/layout/fragment_parent_address.xml | 18 +- app/src/main/res/layout/fragment_pin_code.xml | 89 +++++++++ app/src/main/res/layout/fragment_shop1.xml | 2 +- app/src/main/res/layout/fragment_shop2.xml | 2 +- app/src/main/res/layout/fragment_shop3.xml | 2 +- .../res/navigation/nav_graph_shop_cart.xml | 6 +- app/src/main/res/values/strings.xml | 9 + 37 files changed, 904 insertions(+), 89 deletions(-) create mode 100644 app/src/main/java/com/woka/shop/adapters/ParentAddressAdapter.kt create mode 100644 app/src/main/java/com/woka/shop/models/addaddress/AddAddressRequestData.kt create mode 100644 app/src/main/java/com/woka/shop/models/addaddress/AddAddressResponseData.kt rename app/src/main/java/com/woka/shop/models/addresslisting/{ParentAddress.kt => ParentAddressData.kt} (90%) create mode 100644 app/src/main/java/com/woka/shop/models/createorder/CreateOrderRequestData.kt create mode 100644 app/src/main/java/com/woka/shop/models/createorder/CreateOrderResponse.kt create mode 100644 app/src/main/java/com/woka/shop/models/edd/EDDResponse.kt create mode 100644 app/src/main/java/com/woka/shop/models/edd/Result.kt create mode 100644 app/src/main/java/com/woka/shop/viewmodels/AddressViewModel.kt create mode 100644 app/src/main/java/com/woka/shop/views/AddressActivity.kt create mode 100644 app/src/main/java/com/woka/shop/views/PaymentActivity.kt delete mode 100644 app/src/main/java/com/woka/shop/views/fragments/ParentAddressFragment.kt create mode 100644 app/src/main/java/com/woka/shop/views/fragments/address/PinCodeFragment.kt rename app/src/main/java/com/woka/shop/views/fragments/{ => cart}/CartFragment.kt (99%) rename app/src/main/java/com/woka/shop/views/fragments/{ => cart}/OrderSummaryFragment.kt (97%) create mode 100644 app/src/main/java/com/woka/shop/views/fragments/cart/ParentAddressFragment.kt rename app/src/main/java/com/woka/shop/views/fragments/{ => shop}/ShopFragment1.kt (98%) rename app/src/main/java/com/woka/shop/views/fragments/{ => shop}/ShopFragment2.kt (98%) rename app/src/main/java/com/woka/shop/views/fragments/{ => shop}/ShopFragment3.kt (98%) create mode 100644 app/src/main/res/layout/activity_address.xml create mode 100644 app/src/main/res/layout/activity_payment.xml create mode 100644 app/src/main/res/layout/fragment_pin_code.xml 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 @@ + + + + + + + + + +