NTP-4550 | Filter addition in fund list (#12929)
Co-authored-by: saksham <saksham>
This commit is contained in:
@@ -27,7 +27,7 @@ class EmptyFilterView(context: Context, attributeSet: AttributeSet? = null) :
|
||||
private var binding: EmptyFilterItemLayoutBinding =
|
||||
DataBindingUtil.inflate(inflater, R.layout.empty_filter_item_layout, this, true)
|
||||
|
||||
fun setProperties(data: EmptyProductContent?, action: (ActionData) -> Unit) {
|
||||
fun setProperties(data: EmptyProductContent?, action: (ActionData) -> Unit = {}) {
|
||||
binding.apply {
|
||||
isVisible = true
|
||||
ivContentIcon.showWhenDataIsAvailable(data?.iconUrl)
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
package com.navi.amc.fundbuy.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewStub
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.isVisible
|
||||
@@ -30,7 +33,12 @@ import com.navi.amc.common.taskProcessor.FundLandingPrefetchTask
|
||||
import com.navi.amc.common.taskProcessor.FundListingPrefetchTask
|
||||
import com.navi.amc.common.viewmodel.PaymentSharedVM
|
||||
import com.navi.amc.databinding.FundListFragmentV2LayoutBinding
|
||||
import com.navi.amc.fundbuy.models.ChipData
|
||||
import com.navi.amc.fundbuy.models.FilterItems
|
||||
import com.navi.amc.fundbuy.models.FundExtraData
|
||||
import com.navi.amc.fundbuy.models.FundListResponseV3
|
||||
import com.navi.amc.fundbuy.models.Identifier
|
||||
import com.navi.amc.fundbuy.models.SelectOptionsBottomSheetData
|
||||
import com.navi.amc.fundbuy.viewmodel.FundListViewModel
|
||||
import com.navi.amc.navigator.NaviAmcDeeplinkNavigator
|
||||
import com.navi.amc.utils.AmcAnalytics
|
||||
@@ -38,7 +46,9 @@ import com.navi.amc.utils.AmcAnalytics.LEGACY
|
||||
import com.navi.amc.utils.AmcAnalytics.PAGE_TYPE
|
||||
import com.navi.amc.utils.AmcAnalytics.TRUE
|
||||
import com.navi.amc.utils.Constant
|
||||
import com.navi.amc.utils.Constant.DARK_YELLOW_COLOR
|
||||
import com.navi.amc.utils.Constant.FUND_CATEGORY
|
||||
import com.navi.amc.utils.Constant.PURPLE
|
||||
import com.navi.amc.utils.Constant.WHITE
|
||||
import com.navi.amc.utils.SubPageStatusType
|
||||
import com.navi.amc.utils.TempStorageHelper
|
||||
@@ -53,6 +63,7 @@ import com.navi.base.model.NaviClickAction
|
||||
import com.navi.base.model.NaviWidgetClickWithActionData
|
||||
import com.navi.base.utils.EMPTY
|
||||
import com.navi.base.utils.LOAD_TIME
|
||||
import com.navi.base.utils.isNotNull
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.base.utils.orElse
|
||||
import com.navi.base.utils.orFalse
|
||||
@@ -64,16 +75,22 @@ import com.navi.common.utils.CommonUtils.toMap
|
||||
import com.navi.common.utils.Constants
|
||||
import com.navi.common.utils.Constants.FALSE
|
||||
import com.navi.common.utils.toActionData
|
||||
import com.navi.design.font.FontWeightEnum
|
||||
import com.navi.design.textview.model.NaviSpan
|
||||
import com.navi.design.textview.model.TextWithStyle
|
||||
import com.navi.design.utils.dpToPx
|
||||
import com.navi.design.utils.dpToPxInInt
|
||||
import com.navi.design.utils.getNaviDrawable
|
||||
import com.navi.design.utils.parseColorSafe
|
||||
import com.navi.design.utils.setSpannableString
|
||||
import com.navi.naviwidgets.R as WidgetsR
|
||||
import com.navi.naviwidgets.actions.NaviWidgetClick
|
||||
import com.navi.naviwidgets.adapters.NaviAdapter
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.databinding.LayoutListOverlappingHeaderBinding
|
||||
import com.navi.naviwidgets.itemAnimator.SlideOutItemAnimator
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import com.navi.naviwidgets.models.response.amc.ListOverlappingHeaderWidget
|
||||
import com.navi.naviwidgets.models.response.amc.PaymentCardData
|
||||
import com.navi.naviwidgets.models.response.amc.PaymentCardData.Companion.PAYMENT_CARD_ID
|
||||
import com.navi.naviwidgets.models.response.amc.UpcomingPaymentsWidget
|
||||
@@ -82,12 +99,14 @@ import com.navi.naviwidgets.utils.LottieEnums
|
||||
import com.navi.naviwidgets.utils.setBackgroundTintList
|
||||
import com.navi.naviwidgets.viewholder.ViewHolderFactoryImpl
|
||||
import com.navi.naviwidgets.widgets.HomeProductWidgetLayout
|
||||
import com.navi.naviwidgets.widgets.amc.ListOverlappingHeaderLayout
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class FundListingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
|
||||
private lateinit var binding: FundListFragmentV2LayoutBinding
|
||||
private lateinit var headerWidgetBinding: LayoutListOverlappingHeaderBinding
|
||||
private val viewModel by lazy { ViewModelProvider(this).get(FundListViewModel::class.java) }
|
||||
private val paymentSharedVM: PaymentSharedVM by activityViewModels()
|
||||
private var naviAdapter: NaviAdapter<NaviWidget> =
|
||||
@@ -130,8 +149,17 @@ class FundListingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
updateHeaderTextAndColor()
|
||||
val fundCategory = fundData?.fundCategory.orEmpty()
|
||||
when (fundCategory) {
|
||||
SubPageStatusType.FUND_LANDING -> updateHeaderTextAndColor()
|
||||
else -> {
|
||||
updateHeaderTextAndColor(
|
||||
needToUpdateHeaderBgForcefully = true,
|
||||
headerColorForcefully = DARK_YELLOW_COLOR,
|
||||
headerVisibility = true
|
||||
)
|
||||
}
|
||||
}
|
||||
val taskName =
|
||||
if (fundCategory == SubPageStatusType.FUND_LANDING) {
|
||||
if (fundData?.v2 == TRUE) FundLandingPrefetchTask.FUND_LANDING_PREFETCH else EMPTY
|
||||
@@ -275,6 +303,175 @@ class FundListingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
updateHeaderTextAndColor()
|
||||
}
|
||||
viewModel.fetchingFromRemote.observe(viewLifecycleOwner) { if (it) showLoader() }
|
||||
viewModel.fundListDataV3.observe(viewLifecycleOwner) { response ->
|
||||
hideLoader()
|
||||
setFundListWithFilterUI(response)
|
||||
}
|
||||
|
||||
viewModel.selectedFilterItems.observe(viewLifecycleOwner) { selectedItems ->
|
||||
val filteredList = viewModel.getListBasedOnFilterApplied(selectedItems)
|
||||
setHeaderWidgetData(
|
||||
viewModel.getHeaderWidget(selectedItems, filteredList.isNullOrEmpty().orFalse())
|
||||
)
|
||||
selectedItems?.let { addFilterDataChips(it) }
|
||||
filteredList?.let { list ->
|
||||
binding.rvProducts.apply {
|
||||
if (adapter != null) {
|
||||
naviAdapter.setData(list)
|
||||
} else {
|
||||
layoutManager =
|
||||
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
||||
naviAdapter.list = list
|
||||
adapter = naviAdapter
|
||||
}
|
||||
}
|
||||
binding.rvProducts.visibility = View.VISIBLE
|
||||
} ?: run { binding.rvProducts.visibility = View.GONE }
|
||||
|
||||
if (filteredList.isNullOrEmpty()) {
|
||||
binding.filter.emptyFilter.setProperties(
|
||||
viewModel.fundListDataV3.value?.extraData?.emptyFilterState
|
||||
)
|
||||
} else {
|
||||
binding.filter.emptyFilter.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setFundListWithFilterUI(response: FundListResponseV3?) {
|
||||
response?.header?.let { header -> setHeaderProperties(header) }
|
||||
hideDivider()
|
||||
response?.extraData?.fundCategoryHeaderWidgetMap?.let { viewModel.headerWidgetMap = it }
|
||||
?: run { headerWidgetBinding.root.isVisible = false }
|
||||
viewModel.setListItems(response?.content)
|
||||
response?.extraData?.filterItems?.let { filterItems ->
|
||||
binding.filter.root.isVisible = true
|
||||
setFilterItems(filterItems)
|
||||
} ?: run { binding.filter.root.isVisible = false }
|
||||
viewModel.setSelectedFilterItems(
|
||||
viewModel.selectedFilterItems.value ?: response?.extraData?.filterItems?.selectedFilter
|
||||
)
|
||||
}
|
||||
|
||||
private fun addFilterDataChips(list: List<Identifier>) {
|
||||
viewModel.bottomSheetData?.data?.forEach { data ->
|
||||
data.options?.forEach { item ->
|
||||
item.isChecked =
|
||||
list.any {
|
||||
it.key == item.identifier?.key && it.value == item.identifier?.value
|
||||
}
|
||||
}
|
||||
}
|
||||
val chipUiData =
|
||||
list.map {
|
||||
ChipData(
|
||||
borderColor = PURPLE,
|
||||
title =
|
||||
TextWithStyle(
|
||||
text = it.value,
|
||||
style =
|
||||
listOf(
|
||||
NaviSpan(
|
||||
fontSize = 14.0,
|
||||
fontName = FontWeightEnum.NAVI_BOLD.name,
|
||||
spanColor = PURPLE
|
||||
)
|
||||
)
|
||||
),
|
||||
key = it.value
|
||||
)
|
||||
}
|
||||
binding.filter.chips.apply {
|
||||
visibility = View.VISIBLE
|
||||
setProperties(chipUiData, ::removeFilterDataKey)
|
||||
}
|
||||
list.let {}
|
||||
|
||||
binding.filter.indicator.isVisible = list.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun removeFilterDataKey(key: String) {
|
||||
viewModel.removeFilterKey(key)
|
||||
}
|
||||
|
||||
private fun setHeaderWidgetData(headerWidget: NaviWidget? = null) {
|
||||
activity?.window?.statusBarColor = DARK_YELLOW_COLOR.parseColorSafe()
|
||||
headerWidget?.let {
|
||||
binding.headerWidget.removeAllViews()
|
||||
binding.headerWidget.isVisible = true
|
||||
headerWidgetBinding = LayoutListOverlappingHeaderBinding.inflate(layoutInflater)
|
||||
binding.headerWidget.isVisible = true
|
||||
(headerWidgetBinding.root as ListOverlappingHeaderLayout).update(
|
||||
(it as ListOverlappingHeaderWidget),
|
||||
headerWidgetBinding,
|
||||
this,
|
||||
0
|
||||
)
|
||||
|
||||
val layoutParams =
|
||||
ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
|
||||
headerWidgetBinding.root.setPadding(0, 0, 0, dpToPxInInt(24))
|
||||
headerWidgetBinding.root.layoutParams = layoutParams
|
||||
binding.headerWidget.addView(headerWidgetBinding.root)
|
||||
} ?: run { binding.headerWidget.isVisible = false }
|
||||
}
|
||||
|
||||
private fun setFilterItems(filterItems: FilterItems) {
|
||||
binding.filter.apply {
|
||||
title.setSpannableString(filterItems.title)
|
||||
filterTitle.setSpannableString(filterItems.filterData?.title)
|
||||
filterIcon.isVisible = filterItems.filterData?.iconCode.isNotNull()
|
||||
touch.apply {
|
||||
setOnClickListener { view ->
|
||||
openBottomSheet(filterItems?.filterData?.selectOptionsBottomSheetData)
|
||||
}
|
||||
}
|
||||
touch.setBackgroundResource(R.drawable.bg_light_grey_rounded_4_amc)
|
||||
val backgroundDrawableShape =
|
||||
getNaviDrawable(
|
||||
radii =
|
||||
com.navi.design.utils.CornerRadius(
|
||||
dpToPxInInt(8).toFloat(),
|
||||
dpToPxInInt(8).toFloat(),
|
||||
0f,
|
||||
0f
|
||||
),
|
||||
backgroundColor = Color.WHITE
|
||||
)
|
||||
|
||||
val backgroundDrawableColor =
|
||||
getNaviDrawable(
|
||||
radii = com.navi.design.utils.CornerRadius(0f, 0f, 0f, 0f),
|
||||
backgroundColor = DARK_YELLOW_COLOR.parseColorSafe()
|
||||
)
|
||||
val layers = arrayOf(backgroundDrawableColor, backgroundDrawableShape)
|
||||
val layerDrawable = LayerDrawable(layers)
|
||||
root.background = layerDrawable
|
||||
}
|
||||
}
|
||||
|
||||
private fun openBottomSheet(data: SelectOptionsBottomSheetData?) {
|
||||
val bottomSheetData =
|
||||
viewModel.bottomSheetData?.let { it }
|
||||
?: run {
|
||||
viewModel.bottomSheetData = data
|
||||
data
|
||||
}
|
||||
val bundle =
|
||||
Bundle().apply { putParcelable(SelectOptionBottomSheet.information, bottomSheetData) }
|
||||
safelyShowBottomSheet(
|
||||
SelectOptionBottomSheet.getInstance(bundle).apply { setAction(::setFilterItemList) },
|
||||
SelectOptionBottomSheet.TAG,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
private fun setFilterItemList(list: List<Identifier>) {
|
||||
viewModel.setSelectedFilterItems(list)
|
||||
}
|
||||
|
||||
private fun fetchData(
|
||||
@@ -291,7 +488,10 @@ class FundListingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
extraParams,
|
||||
previousScreenName
|
||||
)
|
||||
else -> viewModel.fetchFundsDataV2(fundData?.fundCategory)
|
||||
else -> {
|
||||
showLoader()
|
||||
viewModel.fetchFundsDataV3(fundData?.fundCategory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,7 +655,11 @@ class FundListingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateHeaderTextAndColor() {
|
||||
private fun updateHeaderTextAndColor(
|
||||
needToUpdateHeaderBgForcefully: Boolean = false,
|
||||
headerColorForcefully: String? = null,
|
||||
headerVisibility: Boolean = false
|
||||
) {
|
||||
val firstVisibleItemPosition =
|
||||
(binding.rvProducts.layoutManager as? LinearLayoutManager)
|
||||
?.findFirstVisibleItemPosition()
|
||||
@@ -469,11 +673,14 @@ class FundListingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
viewModel.isHomeProductWidget(firstVisibleItemPosition)
|
||||
val needToUpdateHeader = viewModel.isImageHeaderWidget(firstVisibleItemPosition)
|
||||
var color = WHITE
|
||||
if (needToUpdateHeaderBg) {
|
||||
color = viewModel.getHeaderColor(firstVisibleItemPosition)
|
||||
if (
|
||||
(needToUpdateHeaderBg || needToUpdateHeaderBgForcefully) &&
|
||||
firstVisibleItemPosition.isNotNull()
|
||||
) {
|
||||
color = headerColorForcefully ?: viewModel.getHeaderColor(firstVisibleItemPosition)
|
||||
}
|
||||
activity?.window?.statusBarColor = color.parseColorSafe()
|
||||
updateHeaderTitleVisibility(!needToUpdateHeader)
|
||||
updateHeaderTitleVisibility(!needToUpdateHeader || headerVisibility)
|
||||
setHeaderColor(color)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.amc.fundbuy.models
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.amc.common.model.EmptyProductContent
|
||||
import com.navi.common.model.Header
|
||||
import com.navi.design.textview.model.TextWithStyle
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import java.io.Serializable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class FundListResponseV3(
|
||||
@SerializedName("header") val header: Header? = null,
|
||||
@SerializedName("content") val content: List<NaviWidget>? = null,
|
||||
@SerializedName("extraData") val extraData: FundListExtraData? = null
|
||||
) : Serializable, Parcelable
|
||||
|
||||
data class FundListExtraData(
|
||||
@SerializedName("filterItems") val filterItems: FilterItems? = null,
|
||||
@SerializedName("fundCategoryHeaderWidgetMap")
|
||||
val fundCategoryHeaderWidgetMap: Map<String, NaviWidget>? = null,
|
||||
@SerializedName("emptyFilterState") val emptyFilterState: EmptyProductContent? = null,
|
||||
) : Serializable
|
||||
|
||||
@Parcelize
|
||||
data class FilterItems(
|
||||
@SerializedName("filterData") val filterData: IconData? = null,
|
||||
@SerializedName("selectedFilter") val selectedFilter: List<Identifier>? = null,
|
||||
@SerializedName("title") val title: TextWithStyle? = null
|
||||
) : Serializable, Parcelable
|
||||
@@ -20,6 +20,9 @@ class FundListRepository @Inject constructor(private val retrofitService: Retrof
|
||||
suspend fun fetchFundsDataV2(fundCategory: String?) =
|
||||
apiResponseCallback(retrofitService.fetchFundListDataV2(fundCategory))
|
||||
|
||||
suspend fun fetchFundsDataV3(fundCategory: String?) =
|
||||
apiResponseCallback(retrofitService.fetchFundListDataV3(fundCategory))
|
||||
|
||||
suspend fun fetchFundLandingData(
|
||||
v2: String,
|
||||
isInvestmentOnBottomNav: String,
|
||||
|
||||
@@ -17,12 +17,17 @@ import com.navi.amc.common.taskProcessor.FundLandingPrefetchTask
|
||||
import com.navi.amc.common.taskProcessor.FundListingPrefetchTask
|
||||
import com.navi.amc.common.viewmodel.BaseAmcVM
|
||||
import com.navi.amc.fundbuy.models.FundListResponse
|
||||
import com.navi.amc.fundbuy.models.FundListResponseV3
|
||||
import com.navi.amc.fundbuy.models.FundListScreen
|
||||
import com.navi.amc.fundbuy.models.Identifier
|
||||
import com.navi.amc.fundbuy.models.SelectOptionsBottomSheetData
|
||||
import com.navi.amc.fundbuy.repository.FundListRepository
|
||||
import com.navi.amc.utils.AmcAnalytics
|
||||
import com.navi.amc.utils.Constant
|
||||
import com.navi.amc.utils.Constant.ALL
|
||||
import com.navi.amc.utils.Constant.WHITE
|
||||
import com.navi.amc.utils.SubPageStatusType
|
||||
import com.navi.base.utils.isNotNull
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.base.utils.orZero
|
||||
@@ -36,6 +41,7 @@ import com.navi.naviwidgets.models.response.HomeProductWidget
|
||||
import com.navi.naviwidgets.models.response.NaviSeparatorWidget
|
||||
import com.navi.naviwidgets.models.response.TopProductWidget
|
||||
import com.navi.naviwidgets.models.response.amc.AmcPortfolioInformationWidget
|
||||
import com.navi.naviwidgets.models.response.amc.FundCardWidget
|
||||
import com.navi.naviwidgets.models.response.amc.ListOverlappingHeaderWidget
|
||||
import com.navi.naviwidgets.models.response.amc.UpcomingPaymentsWidget
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
@@ -55,6 +61,18 @@ class FundListViewModel @Inject constructor(private val repository: FundListRepo
|
||||
val fundListDataV2: LiveData<FundListResponse?>
|
||||
get() = _fundListDataV2
|
||||
|
||||
private val _fundListDataV3 = MutableLiveData<FundListResponseV3?>()
|
||||
val fundListDataV3: LiveData<FundListResponseV3?>
|
||||
get() = _fundListDataV3
|
||||
|
||||
private val _selectedFilterItems = MutableLiveData<List<Identifier>?>()
|
||||
val selectedFilterItems: LiveData<List<Identifier>?>
|
||||
get() = _selectedFilterItems
|
||||
|
||||
private var listItems: List<NaviWidget>? = null
|
||||
var bottomSheetData: SelectOptionsBottomSheetData? = null
|
||||
var headerWidgetMap: Map<String, NaviWidget>? = null
|
||||
|
||||
fun fetchFundsData(fundCategory: String?) {
|
||||
viewModelScope.launch {
|
||||
val response = repository.fetchFundsData(fundCategory)
|
||||
@@ -66,40 +84,6 @@ class FundListViewModel @Inject constructor(private val repository: FundListRepo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We are making same api call on homeVM too, If you want to modify this api please do same on
|
||||
* homeVM too
|
||||
*/
|
||||
fun fetchFundsDataV2(fundCategory: String?) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val taskName =
|
||||
if (fundCategory.isNullOrEmpty()) FundListingPrefetchTask.FUND_LISTING_PREFETCH
|
||||
else FundCategoryListingPrefetchingTask.FUND_CATEGORY_LISTING_PREFETCH
|
||||
if (getFundListDataFromCache(fundCategory, taskName).not()) {
|
||||
if (AmcTaskManager.isTaskActive(taskName)) {
|
||||
setFetchingFromRemote(true)
|
||||
AmcTaskManager.addListener(
|
||||
taskName,
|
||||
object : AmcTaskListener {
|
||||
override fun onTaskStarted(task: String) {}
|
||||
|
||||
override fun onTaskCompletion(task: String, status: String) {
|
||||
if (getFundListDataFromCache(fundCategory, taskName).not()) {
|
||||
fetchFundListDataRemote(fundCategory, taskName)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
if (AmcTaskManager.isTaskInQueue(taskName)) {
|
||||
AmcTaskManager.removeTask(taskName)
|
||||
}
|
||||
fetchFundListDataRemote(fundCategory, taskName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We are making same api call on homeVM too, If you want to modify this api please do same on
|
||||
* homeVM too
|
||||
@@ -209,28 +193,6 @@ class FundListViewModel @Inject constructor(private val repository: FundListRepo
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchFundListDataRemote(fundCategory: String?, taskName: String) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
setFetchingFromRemote(true)
|
||||
val response = repository.fetchFundsDataV2(fundCategory)
|
||||
setFetchingFromRemote(false)
|
||||
if (response.isValidResponse()) {
|
||||
_fundListDataV2.postValue(restoreScrollState(response.data))
|
||||
AmcTaskManager.SOFT_REF_CACHE.add(
|
||||
key = taskName,
|
||||
value = response.data as Any,
|
||||
maxTtl = response.data?.cacheConfig?.ttl ?: AmcTaskManager.DEFAULT_TTL,
|
||||
maxConsumptions =
|
||||
response.data?.cacheConfig?.maxConsumptions
|
||||
?: AmcTaskManager.DEFAULT_MAX_CONSUMPTIONS,
|
||||
params = mapOf(Constant.FUND_CATEGORY to fundCategory.orEmpty())
|
||||
)
|
||||
} else {
|
||||
setErrorData(response.errors, response.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFundLandingDataFromCache(): Boolean {
|
||||
AmcTaskManager.SOFT_REF_CACHE.get(FundLandingPrefetchTask.FUND_LANDING_PREFETCH)
|
||||
?.let { it as? FundListResponse }
|
||||
@@ -365,6 +327,9 @@ class FundListViewModel @Inject constructor(private val repository: FundListRepo
|
||||
fun clearData() {
|
||||
errorResponse.value = null
|
||||
_fundListData.value = null
|
||||
bottomSheetData?.data?.forEach { data ->
|
||||
data.options?.forEach { item -> item.isChecked = false }
|
||||
}
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
@@ -435,4 +400,65 @@ class FundListViewModel @Inject constructor(private val repository: FundListRepo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun fetchFundsDataV3(fundCategory: String?) {
|
||||
viewModelScope.safeLaunch {
|
||||
val response = repository.fetchFundsDataV3(fundCategory)
|
||||
if (
|
||||
response.error == null &&
|
||||
response.errors.isNullOrEmpty() &&
|
||||
response.data.isNotNull()
|
||||
) {
|
||||
_fundListDataV3.value = response.data
|
||||
} else {
|
||||
setErrorData(response.errors, response.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setListItems(listItems: List<NaviWidget>?) {
|
||||
this.listItems = listItems
|
||||
}
|
||||
|
||||
fun getListBasedOnFilterApplied(selectedFilterItems: List<Identifier>?): List<NaviWidget>? {
|
||||
return if (selectedFilterItems.isNullOrEmpty()) {
|
||||
listItems
|
||||
} else {
|
||||
val filteredSet = mutableSetOf<NaviWidget>()
|
||||
listItems?.forEach { widget ->
|
||||
if (widget is FundCardWidget) {
|
||||
selectedFilterItems.forEach {
|
||||
widget.widgetData?.fundCategory?.forEach { fundCategory ->
|
||||
if (it.value == fundCategory) {
|
||||
filteredSet.add(widget)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
filteredSet.toList()
|
||||
}
|
||||
}
|
||||
|
||||
fun setSelectedFilterItems(selectedFilterItems: List<Identifier>?) {
|
||||
_selectedFilterItems.value = selectedFilterItems
|
||||
}
|
||||
|
||||
fun removeFilterKey(key: String) {
|
||||
_selectedFilterItems.value =
|
||||
_selectedFilterItems.value?.filterNot { it.value == key }?.toMutableList()
|
||||
}
|
||||
|
||||
fun getHeaderWidget(
|
||||
selectedFilterItems: List<Identifier>?,
|
||||
getDefaultWidget: Boolean = false
|
||||
): NaviWidget? {
|
||||
return if (
|
||||
selectedFilterItems.isNullOrEmpty() || selectedFilterItems.size > 1 || getDefaultWidget
|
||||
) {
|
||||
headerWidgetMap?.get(ALL)
|
||||
} else {
|
||||
headerWidgetMap?.get(selectedFilterItems.firstOrNull()?.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.navi.amc.redemption.model.FundSellScreenResponse
|
||||
import com.navi.amc.redemption.model.RedemptionOrderDetails
|
||||
import com.navi.amc.utils.Constant.FUND_LANDING_DATA_V2
|
||||
import com.navi.amc.utils.Constant.FUND_LIST_DATA_V2
|
||||
import com.navi.amc.utils.Constant.FUND_LIST_DATA_V3
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.common.csat.models.NetPromoterScoreRequest
|
||||
import com.navi.common.model.UploadDataAsyncResponse
|
||||
@@ -303,6 +304,11 @@ interface RetrofitService {
|
||||
@Query("fundCategory") fundCategory: String?
|
||||
): Response<GenericResponse<FundListResponse>>
|
||||
|
||||
@GET(FUND_LIST_DATA_V3)
|
||||
suspend fun fetchFundListDataV3(
|
||||
@Query("fundCategory") fundCategory: String?
|
||||
): Response<GenericResponse<FundListResponseV3>>
|
||||
|
||||
@GET(FUND_LANDING_DATA_V2)
|
||||
suspend fun fetchFundLandingData(
|
||||
@Query("v2") v2: String,
|
||||
|
||||
@@ -135,6 +135,7 @@ object Constant {
|
||||
const val OKYC = "OKYC"
|
||||
|
||||
const val FUND_LIST_DATA_V2 = "/fund/fund-list/v2"
|
||||
const val FUND_LIST_DATA_V3 = "/fund/fund-list/v3"
|
||||
const val FUND_LANDING_DATA_V2 = "/fund/fund-landing"
|
||||
|
||||
const val FLOW_TYPE = "flow_type"
|
||||
@@ -201,4 +202,6 @@ object Constant {
|
||||
const val INVESTMENT_SIGNATURE_PAD_ENABLED = "INVESTMENT_SIGNATURE_PAD_ENABLED"
|
||||
const val AMC_FIRST_NAVI_UPI_TXN = "AMC_FIRST_NAVI_UPI_TXN"
|
||||
const val NAVI_UPI_TXN = "NAVI_UPI_TXN"
|
||||
const val ALL = "ALL"
|
||||
const val DARK_YELLOW_COLOR = "#FFE6A0"
|
||||
}
|
||||
|
||||
90
android/navi-amc/src/main/res/layout/amc_filter.xml
Normal file
90
android/navi-amc/src/main/res/layout/amc_filter.xml
Normal file
@@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/dp_16">
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/touch"
|
||||
app:layout_constraintBottom_toBottomOf="@id/touch"
|
||||
tools:text="My Orders" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/filter_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/dp_16"
|
||||
android:layout_marginEnd="@dimen/dp_12"
|
||||
android:src="@drawable/inactive_filter"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="@id/touch"
|
||||
app:layout_constraintBottom_toBottomOf="@id/touch"
|
||||
app:layout_constraintEnd_toEndOf="@id/touch" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/indicator"
|
||||
android:layout_width="@dimen/dp_8"
|
||||
android:layout_height="@dimen/dp_8"
|
||||
android:src="@drawable/filter_indicator"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@id/touch"
|
||||
app:layout_constraintTop_toTopOf="@id/touch"
|
||||
app:layout_constraintStart_toEndOf="@+id/touch"
|
||||
app:layout_constraintEnd_toEndOf="@+id/touch" />
|
||||
|
||||
<View
|
||||
android:id="@+id/touch"
|
||||
android:layout_width="@dimen/dp_80"
|
||||
android:layout_height="@dimen/dp_32"
|
||||
android:elevation="-2dp"
|
||||
android:layout_marginTop="@dimen/dp_16"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
app:layout_goneMarginTop="@dimen/dp_24"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/filter_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/dp_4"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="@id/filter_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/filter_icon"
|
||||
app:layout_constraintEnd_toStartOf="@id/filter_icon"
|
||||
tools:text="Filter" />
|
||||
|
||||
<com.navi.amc.fundbuy.views.HorizontalChipGroupView
|
||||
android:id="@+id/chips"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginTop="@dimen/dp_16"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
android:scrollbars="none"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/touch" />
|
||||
|
||||
<com.navi.amc.common.view.EmptyFilterView
|
||||
android:id="@+id/empty_filter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginTop="@dimen/dp_72"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/chips" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
@@ -13,6 +13,25 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white">
|
||||
|
||||
<com.navi.naviwidgets.widgets.amc.ListOverlappingHeaderLayout
|
||||
android:id="@+id/header_widget"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<include
|
||||
android:id="@+id/filter"
|
||||
layout="@layout/amc_filter"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background = "@drawable/rounded_top_corner_image_red"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/header_widget" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvProducts"
|
||||
android:layout_width="match_parent"
|
||||
@@ -20,7 +39,7 @@
|
||||
app:layout_constraintBottom_toTopOf="@id/footer"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toBottomOf="@id/filter" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/flError"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2023 by Navi Technologies Limited
|
||||
* * Copyright © 2023-2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
@@ -31,7 +31,8 @@ data class FundCardWidget(
|
||||
data class FundCardWidgetData(
|
||||
@SerializedName("header") val header: FundCardWidgetHeader? = null,
|
||||
@SerializedName("items") val items: List<FundCardData>? = null,
|
||||
@SerializedName("gradient") val gradient: Gradient? = null
|
||||
@SerializedName("gradient") val gradient: Gradient? = null,
|
||||
@SerializedName("fundCategory") val fundCategory: List<String>? = null
|
||||
)
|
||||
|
||||
data class FundCardData(
|
||||
|
||||
Reference in New Issue
Block a user