From ae6e2313938ff382376c3f2578b1c194f91e2846 Mon Sep 17 00:00:00 2001 From: A Shrihari Raju Date: Tue, 22 Oct 2024 23:29:36 +0530 Subject: [PATCH] NTP-7460 || Shrihari | Projected Returns for Funds v1 (#13225) --- .../fundbuy/fragments/FundBuyingFragmentV2.kt | 147 ++++++++++++++++-- .../fundbuy/fragments/FundDetailsFragment.kt | 12 +- .../amc/fundbuy/models/FundBuyScreenData.kt | 6 +- .../amc/fundbuy/models/FundGraphDetails.kt | 14 +- .../fundbuy/viewmodel/FundBuyV2ViewModel.kt | 34 +++- .../fundbuy/viewmodel/FundDetailViewModel.kt | 1 + .../navi/amc/fundbuy/views/FundGraphView.kt | 122 ++++++++++++--- .../java/com/navi/amc/utils/ColorUtils.kt | 2 + .../java/com/navi/amc/utils/CommonUtils.kt | 3 + .../drawable/amc_radio_button_selector.xml | 14 ++ .../res/drawable/ic_radio_button_default.xml | 23 +++ .../res/drawable/ic_radio_button_selected.xml | 24 +++ .../res/layout/fragment_fund_buying_v2.xml | 18 ++- .../src/main/res/layout/fund_graph_layout.xml | 4 +- .../res/layout/generic_tooltip_layout.xml | 56 ++++++- .../src/main/res/values/dimens.xml | 1 + .../horizontal_straight_line_ebebeb.xml | 9 ++ 17 files changed, 440 insertions(+), 50 deletions(-) create mode 100644 android/navi-amc/src/main/res/drawable/amc_radio_button_selector.xml create mode 100644 android/navi-amc/src/main/res/drawable/ic_radio_button_default.xml create mode 100644 android/navi-amc/src/main/res/drawable/ic_radio_button_selected.xml create mode 100644 android/navi-widgets/src/main/res/drawable/horizontal_straight_line_ebebeb.xml diff --git a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/fragments/FundBuyingFragmentV2.kt b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/fragments/FundBuyingFragmentV2.kt index b080ad860f..0021746d14 100644 --- a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/fragments/FundBuyingFragmentV2.kt +++ b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/fragments/FundBuyingFragmentV2.kt @@ -30,6 +30,7 @@ import com.navi.amc.common.viewmodel.AmcCommonBottomSheetVM import com.navi.amc.common.viewmodel.PaymentSharedVM import com.navi.amc.databinding.FragmentFundBuyingV2Binding import com.navi.amc.fundbuy.models.AmountPageFooter +import com.navi.amc.fundbuy.models.AmountSimulationData import com.navi.amc.fundbuy.models.FundBuyData import com.navi.amc.fundbuy.models.GenericFooter import com.navi.amc.fundbuy.models.PaymentPostData @@ -126,6 +127,7 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { private val naviCheckoutViewModel by activityViewModels() private var confinedInvestmentType: String = AmcAnalytics.SIP_AND_LUMPSUM private var isin: String? = null + private var sipSimulationFragmentData: AmountSimulationData? = null private lateinit var rewardCalloutWidgetBinding: RewardCalloutWidgetLayoutBinding private lateinit var timerWithImageWidgetLayoutBinding: TimerWithImageWidgetLayoutBinding private val genericTimer by lazy { GenericTimer() } @@ -231,6 +233,16 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { binding.lumpsumPaymentCard.isVisible = false binding.cutoffBanner.isVisible = false binding.lumpsumProjection.container.visibility = View.GONE + viewModel.isSipSelected = true + if ( + viewModel.isSipFundReturnNegative || + viewModel.isSipErrorState || + viewModel.sipType.isNullOrEmpty() + ) { + binding.sipProjection.container.visibility = View.GONE + } else { + binding.sipProjection.container.visibility = View.VISIBLE + } setFooter() } @@ -256,11 +268,13 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { } ?: run { binding.lumpsumPaymentCard.isVisible = false } binding.cutoffBanner.isVisible = true + viewModel.isSipSelected = false if (viewModel.isFundReturnNegative || viewModel.isAmountErrorState) { binding.lumpsumProjection.container.visibility = View.GONE } else { binding.lumpsumProjection.container.visibility = View.VISIBLE } + binding.sipProjection.container.visibility = View.GONE setFooter() } @@ -308,6 +322,11 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { binding.lumpsumAmount.toggleSuccessStateVisibility(false) } + content.fundInvestmentType?.sipSimulationData?.let { + binding.sipAmount.enableSuccessText = false + binding.sipAmount.toggleSuccessStateVisibility(false) + } + viewModel.sipData = content.fundInvestmentType?.sipData viewModel.lumpsumData = content.fundInvestmentType?.lumpsumData @@ -375,16 +394,18 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { if (errorState != null && userInput.isNotNullAndNotEmpty()) { viewModel.isAmountErrorState = false if (viewModel.isSipSelected == false) { - viewModel.projectedReturn(userInput).apply { - viewModel.projectedText?.let { projectedText -> - projectedText.text = this - binding.lumpsumProjection.projectionTitle - .setSpannableString(projectedText) - slideInFromTop( - binding.lumpsumProjection.container - ) {} + viewModel + .projectedReturn(userInput, viewModel.isSipSelected) + .apply { + viewModel.projectedText?.let { projectedText -> + projectedText.text = this + binding.lumpsumProjection.projectionTitle + .setSpannableString(projectedText) + slideInFromTop( + binding.lumpsumProjection.container + ) {} + } } - } } } else { binding.lumpsumProjection.container.visibility = View.GONE @@ -411,7 +432,8 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { simulationData.simulationText ) if (viewModel.lumpsumAmount.isNotNullAndNotEmpty()) { - val defaultAmount = viewModel.projectedReturn(viewModel.lumpsumAmount) + val defaultAmount = + viewModel.projectedReturn(viewModel.lumpsumAmount, false) defaultAmount?.let { amount -> viewModel.projectedText = simulationData.projectedReturnsText viewModel.projectedText?.text = amount @@ -514,12 +536,42 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { viewModel.lastSipInteraction = AmcAnalytics.TYPE - binding.sipAmount.getUserInput()?.let { it -> - binding.sipRecommended.setSelectedAmount(it) + binding.sipAmount.getUserInput()?.let { sipUserInput -> + binding.sipRecommended.setSelectedAmount(sipUserInput) + val errorState = binding.sipAmount.getUserInputPostValidation() + if (errorState != null && sipUserInput.isNotNullAndNotEmpty()) { + viewModel.isSipErrorState = false + if ( + viewModel.isSipSelected == true && + viewModel.sipType.isNotNullAndNotEmpty() + ) { + viewModel + .projectedReturn( + sipUserInput, + viewModel.isSipSelected, + viewModel.sipType + ) + .apply { + viewModel.projectedText?.let { projectedText -> + projectedText.text = this + binding.sipProjection.projectionTitle + .setSpannableString(projectedText) + slideInFromTop( + binding.sipProjection.container + ) {} + } + } + } + } else { + binding.sipProjection.container.visibility = View.GONE + snapOut(binding.sipProjection.container) {} + viewModel.isSipErrorState = true + } (content.fundInvestmentType?.sipData?.getOrNull(1) as? LabeledTextInputFixedHintWidgetModel) ?.let { sip -> - sip.widgetData?.inputTextFixedHintItemData?.savedText = it + sip.widgetData?.inputTextFixedHintItemData?.savedText = + sipUserInput } } } @@ -527,6 +579,44 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { override fun afterTextChanged(p0: Editable?) {} } ) + content.fundInvestmentType?.sipSimulationData?.let { sipSimulationData -> + viewModel.dailySipReturnRate = sipSimulationData.dailySipReturnRate + viewModel.weeklySipReturnRate = sipSimulationData.weeklySipReturnRate + viewModel.monthlySipReturnRate = sipSimulationData.monthlySipReturnRate + viewModel.isSipFundReturnNegative = + when (viewModel.sipType) { + Constant.DAILY -> viewModel.dailySipReturnRate == null + Constant.WEEKLY -> viewModel.weeklySipReturnRate == null + Constant.MONTHLY -> viewModel.monthlySipReturnRate == null + else -> false + } + sipSimulationFragmentData = sipSimulationData + binding.sipProjection.image.showWhenDataIsAvailable(sipSimulationData.iconCode) + binding.sipProjection.title.setSpannableString(sipSimulationData.simulationText) + sipSimulationFragmentData?.let { simulationData -> + if (viewModel.sipAmount.isNotNullAndNotEmpty()) { + viewModel.isSipErrorState = false + val defaultAmount = + viewModel.projectedReturn( + viewModel.sipAmount, + viewModel.isSipSelected, + viewModel.sipType + ) + defaultAmount?.let { amount -> + viewModel.projectedText = simulationData.projectedReturnsText + viewModel.projectedText?.text = amount + binding.sipProjection.projectionTitle.setSpannableString( + viewModel.projectedText + ) + } + } + } + } + ?: run { + viewModel.isSipFundReturnNegative = true + binding.sipAmount.enableSuccessText = true + binding.sipAmount.toggleSuccessStateVisibility(false) + } content.fundInvestmentType?.sipRecommendedAmount?.let { chipData -> binding.sipRecommended.setProperties(chipData) { sipRecommended, action -> val updatedAmount = @@ -688,6 +778,35 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { ) } + viewModel.selectedSipType.observe(viewLifecycleOwner) { + it.let { + sipSimulationFragmentData?.let { simulationData -> + if (viewModel.sipAmount.isNotNullAndNotEmpty()) { + viewModel.isSipErrorState = false + val defaultAmount = + viewModel.projectedReturn( + viewModel.sipAmount, + viewModel.isSipSelected, + viewModel.sipType + ) + defaultAmount?.let { amount -> + viewModel.projectedText = simulationData.projectedReturnsText + viewModel.projectedText?.text = amount + binding.sipProjection.projectionTitle.setSpannableString( + viewModel.projectedText + ) + if ( + viewModel.isSipSelected == true && + viewModel.sipType.isNotNullAndNotEmpty() + ) { + binding.sipProjection.container.isVisible = true + } + } + } + } + } + } + viewModel.sipDetailsResponse.observe(viewLifecycleOwner) { hideLoader() it?.let { @@ -1046,6 +1165,7 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { bottomSheet.selectedItem.observeNonNull(this) { item -> binding.sipAmount.visibility = View.VISIBLE viewModel.sipType = item.id + viewModel.setSelectedSipType(viewModel.sipType) binding.sipRecommended.isVisible = viewModel.toShowSipRecommended if (item.id == Constant.MONTHLY) { viewModel.toHideDate = false @@ -1527,6 +1647,7 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback { sipFrequency?.let { frequency -> viewModel.sipType = frequency + viewModel.setSelectedSipType(viewModel.sipType) binding.sipAmount.visibility = View.VISIBLE binding.sipRecommended.isVisible = viewModel.toShowSipRecommended val bottomSheetData = diff --git a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/fragments/FundDetailsFragment.kt b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/fragments/FundDetailsFragment.kt index 519a34dac9..b78db27e09 100644 --- a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/fragments/FundDetailsFragment.kt +++ b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/fragments/FundDetailsFragment.kt @@ -275,7 +275,9 @@ class FundDetailsFragment : AmcBaseFragment(), FooterInteractionListener { action = ::setFundReturns, navigateAction = ::navigate, apiClickAction = ::pillClickAction, - vmSelectedKey = viewModel.selectedChipId + vmSelectedKey = viewModel.selectedChipId, + setRadioAction = ::setSelectedRadio, + vmSelectedRadio = viewModel.selectedRadio ) view.tag = "graph" addView(view) @@ -430,7 +432,9 @@ class FundDetailsFragment : AmcBaseFragment(), FooterInteractionListener { action = ::setFundReturns, navigateAction = ::navigate, apiClickAction = ::pillClickAction, - vmSelectedKey = viewModel.selectedChipId + vmSelectedKey = viewModel.selectedChipId, + setRadioAction = ::setSelectedRadio, + vmSelectedRadio = viewModel.selectedRadio ) } @@ -619,6 +623,10 @@ class FundDetailsFragment : AmcBaseFragment(), FooterInteractionListener { binding.footer.footerTopNote3.isVisible = true } + private fun setSelectedRadio(key: String) { + viewModel.selectedRadio = key + } + private fun onTimerRefresh() { fetchData(genericTimer.isInitialised()) } diff --git a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/models/FundBuyScreenData.kt b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/models/FundBuyScreenData.kt index db3a745378..ee1ba851a5 100644 --- a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/models/FundBuyScreenData.kt +++ b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/models/FundBuyScreenData.kt @@ -95,12 +95,16 @@ data class FundInvestmentType( @SerializedName("informationNote") val informationNote: InformationNoteData? = null, @SerializedName("sipStartDateOffset") val sipStartDateOffset: SipStartDateOffset? = null, @SerializedName("noteBanner") val noteBanner: NoteBannerData? = null, - @SerializedName("simulationData") val simulationData: AmountSimulationData? = null + @SerializedName("simulationData") val simulationData: AmountSimulationData? = null, + @SerializedName("sipSimulationData") val sipSimulationData: AmountSimulationData? = null ) data class AmountSimulationData( @SerializedName("iconCode") val iconCode: String? = null, @SerializedName("lumpsumReturnRate") val lumpsumReturnRate: Double? = null, + @SerializedName("dailySipReturnRate") val dailySipReturnRate: Double? = null, + @SerializedName("weeklySipReturnRate") val weeklySipReturnRate: Double? = null, + @SerializedName("monthlySipReturnRate") val monthlySipReturnRate: Double? = null, @SerializedName("backgroundColor") val backgroundColor: String? = null, @SerializedName("simulationText") val simulationText: TextWithStyle? = null, @SerializedName("projectedReturnsText") val projectedReturnsText: TextWithStyle? = null diff --git a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/models/FundGraphDetails.kt b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/models/FundGraphDetails.kt index 8a51c73f24..797d2bdfc4 100644 --- a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/models/FundGraphDetails.kt +++ b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/models/FundGraphDetails.kt @@ -61,8 +61,18 @@ data class FundDuration( ) data class ReturnsTooltipData( - @SerializedName("imageUrl") val imageUrl: String? = null, - @SerializedName("title") val title: TextWithStyle? = null + @SerializedName("oneTimeReturns") val oneTimeReturns: ReturnsData? = null, + @SerializedName("sipReturns") val sipReturns: ReturnsData? = null, + @SerializedName("selectedTextColor") val selectedColor: String? = null, + @SerializedName("unselectedTextColor") val unselectedTextColor: String? = null +) + +data class ReturnsData( + @SerializedName("key") val key: String? = null, + @SerializedName("title") val title: TextWithStyleVariation? = null, + @SerializedName("imageUrl", alternate = ["iconCode"]) val imageUrl: String? = null, + @SerializedName("returnsInformation") val returnsInformation: TextWithStyle? = null, + @SerializedName("isSelected") val isSelected: Boolean? = null ) data class XAxisLabelData( diff --git a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/viewmodel/FundBuyV2ViewModel.kt b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/viewmodel/FundBuyV2ViewModel.kt index 6e016497aa..400dad1775 100644 --- a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/viewmodel/FundBuyV2ViewModel.kt +++ b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/viewmodel/FundBuyV2ViewModel.kt @@ -32,6 +32,7 @@ import com.navi.amc.utils.Constant.WEEKLY import com.navi.amc.utils.roundOffAmount import com.navi.amc.utils.updateCheckerResponse import com.navi.base.model.ActionData +import com.navi.base.utils.orZero import com.navi.common.utils.EMPTY import com.navi.common.utils.formatDateIntoPrefixMonthNamesWithYear import com.navi.common.viewmodel.BaseVM @@ -75,15 +76,28 @@ class FundBuyV2ViewModel @Inject constructor(private val repository: FundBuyRepo var sipData: List? = null var lumpsumData: List? = null var lumpSumReturnRate: Double? = null + var dailySipReturnRate: Double? = null + var weeklySipReturnRate: Double? = null + var monthlySipReturnRate: Double? = null var projectedText: TextWithStyle? = null var isFundReturnNegative: Boolean = false var isAmountErrorState: Boolean = false + var isSipFundReturnNegative: Boolean = false + var isSipErrorState: Boolean = false private val _paymentInitiateData = MutableLiveData?>() val paymentInitiateData: LiveData?> get() = _paymentInitiateData + private val _selectedSipType = MutableLiveData() + val selectedSipType: LiveData + get() = _selectedSipType + + fun setSelectedSipType(sipType: String?) { + _selectedSipType.value = sipType + } + private val gson by lazy { Gson() } fun getFundBuyScreenData( @@ -361,10 +375,24 @@ class FundBuyV2ViewModel @Inject constructor(private val repository: FundBuyRepo return _fundBuyScreenData.value?.content?.isManualVsAutopay.orFalse() } - fun projectedReturn(userInput: String?): String? { - val returnRate = lumpSumReturnRate + fun projectedReturn( + userInput: String?, + isSipSelected: Boolean? = false, + sipType: String? = null + ): String? { + val returnRate = + if (isSipSelected.orFalse()) { + when (sipType) { + WEEKLY -> weeklySipReturnRate + MONTHLY -> monthlySipReturnRate + DAILY -> dailySipReturnRate + else -> null + } + } else { + lumpSumReturnRate + } if (returnRate != null && userInput != null) { - return roundOffAmount(userInput.toDouble() * returnRate) + return roundOffAmount(userInput.toDouble().orZero() * returnRate) } return null } diff --git a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/viewmodel/FundDetailViewModel.kt b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/viewmodel/FundDetailViewModel.kt index 547af82a36..de5ddef59f 100644 --- a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/viewmodel/FundDetailViewModel.kt +++ b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/viewmodel/FundDetailViewModel.kt @@ -48,6 +48,7 @@ class FundDetailViewModel @Inject constructor(private val repository: FundDetail val chipIdToGraphDataMap = mutableMapOf() var selectedChipId: String? = null var fundName: String? = null + var selectedRadio: String? = null fun getFundScreenData(isin: String) { viewModelScope.launch { diff --git a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/views/FundGraphView.kt b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/views/FundGraphView.kt index f1418f65c3..fb3416b77a 100644 --- a/android/navi-amc/src/main/java/com/navi/amc/fundbuy/views/FundGraphView.kt +++ b/android/navi-amc/src/main/java/com/navi/amc/fundbuy/views/FundGraphView.kt @@ -44,14 +44,17 @@ import com.navi.amc.fundbuy.models.FundDuration import com.navi.amc.fundbuy.models.FundGraphData import com.navi.amc.fundbuy.models.FundGraphDetails import com.navi.amc.fundbuy.models.FundReturn +import com.navi.amc.fundbuy.models.ReturnsData import com.navi.amc.utils.ColorUtils import com.navi.amc.utils.ColorUtils.FUND_GRAPH_BG_END_GRADIENT_COLOR import com.navi.amc.utils.ColorUtils.FUND_GRAPH_BG_START_GRADIENT_COLOR import com.navi.amc.utils.ColorUtils.FUND_GRAPH_CHIP_SELECTED_COLOR +import com.navi.amc.utils.Constant import com.navi.base.model.ActionData import com.navi.base.utils.orFalse import com.navi.base.utils.orZero import com.navi.common.animation.fadeIn +import com.navi.design.textview.model.TextWithStyle import com.navi.design.utils.CornerRadius import com.navi.design.utils.dpToPxInInt import com.navi.design.utils.getNaviDrawable @@ -72,11 +75,27 @@ class FundGraphView(context: Context, attributeSet: AttributeSet? = null) : private var isInvestmentDetailsUpdated: Boolean = false private var isGraphPillUpdated: Boolean = false private var selectedKey: String? = null + private var selectedRadio: String? = null + private var setRadioAction: ((String) -> Unit)? = null + private var fundDurationData: FundDuration? = null + private var selectedId: Int = 0 init { val inflater = LayoutInflater.from(context) binding = DataBindingUtil.inflate(inflater, R.layout.fund_graph_layout, this, true) layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT) + + binding.chipTooltipContent.radioGroup.setOnCheckedChangeListener { group, checkedId -> + when (checkedId) { + R.id.radio_option_one_time -> { + selectedRadio = Constant.ONE_TIME + } + R.id.radio_option_sip -> { + selectedRadio = Constant.SIP + } + } + updateSelectedTooltip(fundDurationData, selectedId) + } } fun setProperties( @@ -86,9 +105,13 @@ class FundGraphView(context: Context, attributeSet: AttributeSet? = null) : action: ((FundReturn) -> Unit)? = null, navigateAction: ((ActionData) -> Unit)? = null, apiClickAction: ((String?, Boolean?) -> Unit)? = null, - vmSelectedKey: String? = null + vmSelectedKey: String? = null, + setRadioAction: ((String) -> Unit)? = null, + vmSelectedRadio: String? = null ) { this.apiClickAction = apiClickAction + this.setRadioAction = setRadioAction + selectedRadio = vmSelectedRadio if (isGraphPillUpdated.not()) { setFundGraphPillsData(data, vmSelectedKey) } @@ -456,31 +479,92 @@ class FundGraphView(context: Context, attributeSet: AttributeSet? = null) : } private fun updateSelectedTooltip(childData: FundDuration?, childId: Int) { - childData?.returnsTooltip?.let { tooltipData -> - val triangle = binding.triangles.findViewById(childId) - binding.triangles.visibility = View.VISIBLE - triangle.visibility = View.VISIBLE - fadeIn(binding.chipTooltipContent.root) {} - binding.chipTooltipContent.tooltipImage.showWhenDataIsAvailable(tooltipData.imageUrl) - binding.chipTooltipContent.title.setSpannableString(tooltipData.title) - } - ?: run { - val triangle = binding.triangles.findViewById(childId) - TransitionManager.beginDelayedTransition( - binding.root as ViewGroup, - Fade().apply { duration = FADE_OUT_DURATION } - ) - triangle.visibility = View.GONE - binding.triangles.visibility = View.GONE - binding.chipTooltipContent.root.visibility = View.GONE + binding.chipTooltipContent.radioOptionOneTime.setSpannableString( + childData?.returnsTooltip?.oneTimeReturns?.title + ) + binding.chipTooltipContent.radioOptionSip.setSpannableString( + childData?.returnsTooltip?.sipReturns?.title + ) + binding.chipTooltipContent.divider.visibility = View.VISIBLE + + fundDurationData = childData + selectedId = childId + setRadioAction?.invoke(selectedRadio.orEmpty()) + + when (selectedRadio) { + Constant.ONE_TIME -> { + childData?.returnsTooltip?.oneTimeReturns?.let { tooltipData -> + binding.chipTooltipContent.radioOptionSip.setSpannableString( + childData.returnsTooltip.sipReturns?.title + ) + binding.chipTooltipContent.radioOptionOneTime.setSpannableString( + textData = + TextWithStyle( + text = childData.returnsTooltip.oneTimeReturns.title?.text, + style = + childData.returnsTooltip.oneTimeReturns.title + ?.styleVariations + ?.get("selected") + ) + ) + binding.chipTooltipContent.radioOptionOneTime.isChecked = true + setTooltipData(tooltipData, childId) + } ?: run { fadeOutTooltip(childId) } } + Constant.SIP -> { + childData?.returnsTooltip?.sipReturns?.let { tooltipData -> + binding.chipTooltipContent.radioOptionOneTime.setSpannableString( + childData.returnsTooltip.oneTimeReturns?.title + ) + binding.chipTooltipContent.radioOptionSip.setSpannableString( + textData = + TextWithStyle( + text = childData.returnsTooltip.sipReturns.title?.text, + style = + childData.returnsTooltip.sipReturns.title + ?.styleVariations + ?.get("selected") + ) + ) + binding.chipTooltipContent.radioOptionSip.isChecked = true + setTooltipData(tooltipData, childId) + } ?: run { fadeOutTooltip(childId) } + } + else -> { + selectedRadio = + childData?.returnsTooltip?.oneTimeReturns?.isSelected?.let { + if (it) Constant.ONE_TIME else Constant.SIP + } ?: Constant.SIP + updateSelectedTooltip(childData, childId) + } + } + } + + private fun setTooltipData(toolTipData: ReturnsData, childId: Int) { + val triangle = binding.triangles.findViewById(childId) + binding.triangles.visibility = View.VISIBLE + triangle.visibility = View.VISIBLE + fadeIn(binding.chipTooltipContent.root) {} + binding.chipTooltipContent.tooltipImage.showWhenDataIsAvailable(toolTipData.imageUrl) + binding.chipTooltipContent.title.setSpannableString(toolTipData.returnsInformation) + } + + private fun fadeOutTooltip(childId: Int) { + val triangle = binding.triangles.findViewById(childId) + TransitionManager.beginDelayedTransition( + binding.root as ViewGroup, + Fade().apply { duration = FADE_OUT_DURATION } + ) + triangle.visibility = View.GONE + binding.triangles.visibility = View.GONE + binding.chipTooltipContent.root.visibility = View.GONE } companion object { const val TAG = "FundGraphView" const val TRIANGLE_WIDTH = 20 - const val TRIANGLE_HEIGHT = 12 + const val TRIANGLE_HEIGHT = 10 const val TRIANGLE_MARGIN_START = 16 const val TRIANGLE_MARGIN_TOP = 8 const val TRIANGLE_MARGIN_END = 16 diff --git a/android/navi-amc/src/main/java/com/navi/amc/utils/ColorUtils.kt b/android/navi-amc/src/main/java/com/navi/amc/utils/ColorUtils.kt index 5dea094f83..9e66f2dbd1 100644 --- a/android/navi-amc/src/main/java/com/navi/amc/utils/ColorUtils.kt +++ b/android/navi-amc/src/main/java/com/navi/amc/utils/ColorUtils.kt @@ -27,6 +27,8 @@ object ColorUtils { const val FUND_GRAPH_BG_START_GRADIENT_COLOR = "#64FFFCEC" const val FUND_GRAPH_BG_END_GRADIENT_COLOR = "#FFFFFF" const val FUND_GRAPH_CHIP_SELECTED_COLOR = "#1F002A" + const val RADIO_SELECTED_COLOR = "#191919" + const val RADIO_UNSELECTED_COLOR = "#6B6B6B" fun getPurpleRoundedDrawable(context: Context) = getNaviDrawable( diff --git a/android/navi-amc/src/main/java/com/navi/amc/utils/CommonUtils.kt b/android/navi-amc/src/main/java/com/navi/amc/utils/CommonUtils.kt index 307125b82f..50a5d785f4 100644 --- a/android/navi-amc/src/main/java/com/navi/amc/utils/CommonUtils.kt +++ b/android/navi-amc/src/main/java/com/navi/amc/utils/CommonUtils.kt @@ -42,6 +42,7 @@ import com.navi.naviwidgets.widgets.NaviWidgetJsonDeserializer import java.lang.reflect.Type import java.net.URI import java.text.DecimalFormat +import java.text.NumberFormat import java.text.SimpleDateFormat import java.util.TimeZone import kotlin.math.floor @@ -207,11 +208,13 @@ fun getFundGraphItemCacheKey(key: String, fundName: String): String { fun roundOffAmount(value: Double): String { // function to return amount in K, L, Cr if greater than 10K and rounded up to 2 decimal places val df = DecimalFormat("#.##") + val nf = NumberFormat.getInstance().apply { maximumFractionDigits = 0 } return RUPEE_SYMBOL + when { value >= 1_00_00_000 -> df.format(floor(value / 1_00_00_000 * 100) / 100) + " Cr" value >= 1_00_000 -> df.format(floor(value / 1_00_000 * 100) / 100) + " L" value >= 10_000 -> df.format(floor(value / 1_000 * 100) / 100) + " K" + value >= 1_000 -> nf.format(value) else -> df.format(floor(value * 100) / 100.0f) } } diff --git a/android/navi-amc/src/main/res/drawable/amc_radio_button_selector.xml b/android/navi-amc/src/main/res/drawable/amc_radio_button_selector.xml new file mode 100644 index 0000000000..c820b586de --- /dev/null +++ b/android/navi-amc/src/main/res/drawable/amc_radio_button_selector.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/android/navi-amc/src/main/res/drawable/ic_radio_button_default.xml b/android/navi-amc/src/main/res/drawable/ic_radio_button_default.xml new file mode 100644 index 0000000000..8a32833496 --- /dev/null +++ b/android/navi-amc/src/main/res/drawable/ic_radio_button_default.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/android/navi-amc/src/main/res/drawable/ic_radio_button_selected.xml b/android/navi-amc/src/main/res/drawable/ic_radio_button_selected.xml new file mode 100644 index 0000000000..3920f82d41 --- /dev/null +++ b/android/navi-amc/src/main/res/drawable/ic_radio_button_selected.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/android/navi-amc/src/main/res/layout/fragment_fund_buying_v2.xml b/android/navi-amc/src/main/res/layout/fragment_fund_buying_v2.xml index bb21f6dc42..dad93caeb2 100644 --- a/android/navi-amc/src/main/res/layout/fragment_fund_buying_v2.xml +++ b/android/navi-amc/src/main/res/layout/fragment_fund_buying_v2.xml @@ -126,12 +126,12 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="@dimen/dp_16" - android:layout_marginTop="@dimen/dp_24" + android:layout_marginTop="@dimen/dp_130" android:layout_marginEnd="@dimen/dp_16" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/sip_amount" /> + app:layout_constraintTop_toTopOf="@id/sip_amount" /> + + + app:layout_constraintTop_toTopOf="@id/chip_group" /> + + + + + + + + + @@ -31,10 +76,9 @@ android:layout_width="@dimen/_0dp" android:layout_height="wrap_content" android:lineSpacingExtra="@dimen/_3dp" - android:layout_marginStart="@dimen/_12dp" - app:layout_constraintStart_toEndOf="@id/tooltip_image" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@id/tooltip_image" + app:layout_constraintTop_toBottomOf="@id/divider" app:layout_constraintBottom_toBottomOf="parent" tools:text="About SIPS" /> diff --git a/android/navi-design/src/main/res/values/dimens.xml b/android/navi-design/src/main/res/values/dimens.xml index 067993d016..b41699afa7 100644 --- a/android/navi-design/src/main/res/values/dimens.xml +++ b/android/navi-design/src/main/res/values/dimens.xml @@ -67,6 +67,7 @@ 52dp 54dp 56dp + 57dp 58dp 60dp 62dp diff --git a/android/navi-widgets/src/main/res/drawable/horizontal_straight_line_ebebeb.xml b/android/navi-widgets/src/main/res/drawable/horizontal_straight_line_ebebeb.xml new file mode 100644 index 0000000000..20ae411ee3 --- /dev/null +++ b/android/navi-widgets/src/main/res/drawable/horizontal_straight_line_ebebeb.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file