NTP-7460 || Shrihari | Projected Returns for Funds v1 (#13225)
This commit is contained in:
@@ -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<NaviCheckoutViewModel>()
|
||||
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 =
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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<NaviWidget>? = null
|
||||
var lumpsumData: List<NaviWidget>? = 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<AdditionalDataAsyncResponse<NextCtaResponse>?>()
|
||||
val paymentInitiateData: LiveData<AdditionalDataAsyncResponse<NextCtaResponse>?>
|
||||
get() = _paymentInitiateData
|
||||
|
||||
private val _selectedSipType = MutableLiveData<String?>()
|
||||
val selectedSipType: LiveData<String?>
|
||||
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
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ class FundDetailViewModel @Inject constructor(private val repository: FundDetail
|
||||
val chipIdToGraphDataMap = mutableMapOf<String, FundGraphData>()
|
||||
var selectedChipId: String? = null
|
||||
var fundName: String? = null
|
||||
var selectedRadio: String? = null
|
||||
|
||||
fun getFundScreenData(isin: String) {
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -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<ImageView>(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<ImageView>(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<ImageView>(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<ImageView>(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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
~
|
||||
~ * Copyright © 2022-2023 by Navi Technologies Limited
|
||||
~ * All rights reserved. Strictly confidential
|
||||
~
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_radio_button_default" android:state_checked="false" />
|
||||
<item android:drawable="@drawable/ic_radio_button_selected" android:state_checked="true" />
|
||||
<item android:drawable="@drawable/ic_radio_button_default" />
|
||||
</selector>
|
||||
@@ -0,0 +1,23 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16"
|
||||
>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M8 0C12.4183 0 16 3.58172 16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0Z"
|
||||
/>
|
||||
<path
|
||||
android:pathData="M0 0V16H16V0"
|
||||
android:fillColor="#FFFFFF"
|
||||
/>
|
||||
<path
|
||||
android:pathData="M8 0C12.4183 0 16 3.58172 16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0Z"
|
||||
android:strokeWidth="1.34"
|
||||
android:strokeColor="#EBEBEB"
|
||||
/>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -0,0 +1,24 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16"
|
||||
>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M8 0C12.4183 0 16 3.58172 16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0Z"
|
||||
/>
|
||||
<path
|
||||
android:pathData="M8 0C12.4183 0 16 3.58172 16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0Z"
|
||||
android:strokeWidth="2.69"
|
||||
android:strokeColor="#1F002A"
|
||||
/>
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M11.5,8C11.5,9.933 9.933,11.5 8,11.5C6.067,11.5 4.5,9.933 4.5,8C4.5,6.067 6.067,4.5 8,4.5C9.933,4.5 11.5,6.067 11.5,8Z"
|
||||
android:fillColor="#1F002A"
|
||||
android:strokeColor="#1F002A"/>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -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" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/lumpsum_payment_card"
|
||||
@@ -286,6 +286,20 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/sip_frequency" />
|
||||
|
||||
<include
|
||||
android:id="@+id/sip_projection"
|
||||
layout="@layout/amc_amount_projection_fundbuy_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:paddingTop="@dimen/_4dp"
|
||||
android:layout_marginTop="-4dp"
|
||||
android:elevation="-2dp"
|
||||
android:layout_marginHorizontal="@dimen/_16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/sip_amount" />
|
||||
|
||||
<com.navi.naviwidgets.widgets.labeledinputsearch.ui.LabeledTextSearchInputWidget
|
||||
android:id="@+id/date"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -214,10 +214,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:translationZ="8dp"
|
||||
android:visibility="gone"
|
||||
android:layout_marginTop="-8dp"
|
||||
android:layout_marginTop="@dimen/dp_57"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/chip_group" />
|
||||
app:layout_constraintTop_toTopOf="@id/chip_group" />
|
||||
|
||||
|
||||
<com.navi.amc.common.view.FundInvestmentDetailsView
|
||||
|
||||
@@ -18,11 +18,56 @@
|
||||
android:background="@drawable/box_shadow_bottom_4"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/radio_group"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_width="match_parent"
|
||||
android:weightSum="@integer/integer_1"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radio_option_one_time"
|
||||
tools:text="One-time"
|
||||
android:button="@null"
|
||||
android:drawableStart="@drawable/amc_radio_button_selector"
|
||||
android:drawablePadding="@dimen/_8dp"
|
||||
android:background="@null"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<RadioButton
|
||||
android:layout_marginStart="@dimen/dp_31"
|
||||
android:id="@+id/radio_option_sip"
|
||||
tools:text="Monthly SIP"
|
||||
android:button="@null"
|
||||
android:drawableStart="@drawable/amc_radio_button_selector"
|
||||
android:drawablePadding="@dimen/_8dp"
|
||||
android:background="@null"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</RadioGroup>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="@dimen/_20dp"
|
||||
android:background="@drawable/horizontal_straight_line_ebebeb"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/radio_group"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/tooltip_image"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginStart="@dimen/_16dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/divider"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/title"
|
||||
android:layout_width="@dimen/_44dp"
|
||||
android:layout_height="@dimen/_44dp"/>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
<dimen name="dp_52">52dp</dimen>
|
||||
<dimen name="dp_54">54dp</dimen>
|
||||
<dimen name="dp_56">56dp</dimen>
|
||||
<dimen name="dp_57">57dp</dimen>
|
||||
<dimen name="dp_58">58dp</dimen>
|
||||
<dimen name="dp_60">60dp</dimen>
|
||||
<dimen name="dp_62">62dp</dimen>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="line">
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#EBEBEB"/>
|
||||
</shape>
|
||||
Reference in New Issue
Block a user