NTP-4550 | Filter addition in fund list (#12929)

Co-authored-by: saksham <saksham>
This commit is contained in:
Saksham Mahajan
2024-10-09 12:29:37 +05:30
committed by GitHub
parent ee21188f04
commit 7b43818c65
10 changed files with 459 additions and 66 deletions

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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,

View File

@@ -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)
}
}
}

View File

@@ -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,

View File

@@ -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"
}

View 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>

View File

@@ -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"

View File

@@ -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(