NTP-57102 | Goal Based Investing (#16105)
Co-authored-by: shrihari-raju_navi <shrihari.raju@navi.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.navi.amc.common.viewmodel.CheckerVM
|
||||
import com.navi.amc.compose.feature.goalBasedSip.viewmodel.GoalBasedSipSetupVM
|
||||
import com.navi.amc.fundbuy.models.AutoPaySetupRequestData
|
||||
import com.navi.amc.fundbuy.viewmodel.FundBuyFlowViewModel
|
||||
import com.navi.amc.fundbuy.viewmodel.FundListViewModel
|
||||
@@ -30,12 +31,17 @@ import com.navi.amc.utils.AmcAnalytics.ORDER_TYPE
|
||||
import com.navi.amc.utils.Constant.ACTION_PERFORMED
|
||||
import com.navi.amc.utils.Constant.AMOUNT
|
||||
import com.navi.amc.utils.Constant.BANK_DETAILS_REF_ID
|
||||
import com.navi.amc.utils.Constant.GOAL_NAME
|
||||
import com.navi.amc.utils.Constant.GOAL_REFERENCE_ID
|
||||
import com.navi.amc.utils.Constant.MANDATE_OPTED_IN
|
||||
import com.navi.amc.utils.Constant.PAYMENT_MODE
|
||||
import com.navi.amc.utils.Constant.SETUP_AUTOPAY_EXISTING_SIP
|
||||
import com.navi.amc.utils.Constant.SIP_REFERENCE_ID
|
||||
import com.navi.analytics.utils.NaviTrackEvent
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.common.utils.Constants.AMC_GOAL_BASED_SIP_AMOUNT_SCREEN
|
||||
import com.navi.common.utils.Constants.AMC_GOAL_BASED_SIP_SUMMARY_SCREEN
|
||||
import com.navi.common.utils.Constants.AMC_GOAL_BASED_SIP_TARGET_SETUP_SCREEN
|
||||
import com.navi.common.utils.Constants.CTAData
|
||||
import com.navi.common.utils.Constants.HOPPER_API_RESPONSE_NOT_RECEIVED
|
||||
import com.navi.common.utils.Constants.HOPPER_API_TIMEOUT
|
||||
@@ -52,6 +58,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -180,6 +187,62 @@ class HopperHelper {
|
||||
)
|
||||
}
|
||||
}
|
||||
is GoalBasedSipSetupVM -> {
|
||||
when (ctaData.url) {
|
||||
AMC_GOAL_BASED_SIP_TARGET_SETUP_SCREEN -> {
|
||||
viewModel.fetchTargetSetupScreenDataFromRemote(
|
||||
goalName =
|
||||
ctaData.parameters
|
||||
?.firstOrNull { it.key == GOAL_NAME }
|
||||
?.value
|
||||
.orEmpty(),
|
||||
goalReferenceId =
|
||||
ctaData.parameters
|
||||
?.firstOrNull { it.key == GOAL_REFERENCE_ID }
|
||||
?.value
|
||||
.orEmpty(),
|
||||
)
|
||||
observeAndHandleResponse(
|
||||
activity,
|
||||
ctaData,
|
||||
onResult = onResult,
|
||||
stateFlow = viewModel.goalBasedSipScreenState,
|
||||
)
|
||||
}
|
||||
AMC_GOAL_BASED_SIP_AMOUNT_SCREEN -> {
|
||||
viewModel.fetchSipAmountScreenDataFromRemote(
|
||||
screenName = AMC_GOAL_BASED_SIP_AMOUNT_SCREEN,
|
||||
goalReferenceId =
|
||||
ctaData.parameters
|
||||
?.firstOrNull { it.key == GOAL_REFERENCE_ID }
|
||||
?.value
|
||||
.orEmpty(),
|
||||
)
|
||||
observeAndHandleResponse(
|
||||
activity,
|
||||
ctaData,
|
||||
viewModel.sipAmountScreenData,
|
||||
onResult,
|
||||
)
|
||||
}
|
||||
AMC_GOAL_BASED_SIP_SUMMARY_SCREEN -> {
|
||||
viewModel.fetchGoalSummaryScreenDataFromRemote(
|
||||
screenName = AMC_GOAL_BASED_SIP_SUMMARY_SCREEN,
|
||||
goalReferenceId =
|
||||
ctaData.parameters
|
||||
?.firstOrNull { it.key == GOAL_REFERENCE_ID }
|
||||
?.value
|
||||
.orEmpty(),
|
||||
)
|
||||
observeAndHandleResponse(
|
||||
activity,
|
||||
ctaData,
|
||||
viewModel.goalSummaryScreenData,
|
||||
onResult,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
onResult(false)
|
||||
}
|
||||
@@ -191,7 +254,10 @@ class HopperHelper {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
when (viewModel) {
|
||||
is InvestmentsVm -> {
|
||||
viewModel.getDynamicCTA(ctaData.action ?: KYC_JOURNEY)
|
||||
viewModel.getDynamicCTA(
|
||||
ctaData.action ?: KYC_JOURNEY,
|
||||
ctaData.parameters ?: emptyList(),
|
||||
)
|
||||
observeAndHandleDynamicCtaResponse(viewModel.dynamicCta, onResult)
|
||||
}
|
||||
}
|
||||
@@ -213,9 +279,10 @@ class HopperHelper {
|
||||
private fun observeAndHandleResponse(
|
||||
activity: ComponentActivity,
|
||||
ctaData: CtaData,
|
||||
liveData: LiveData<*>,
|
||||
liveData: LiveData<*>? = null,
|
||||
onResult: (Boolean) -> Unit,
|
||||
timeoutMillis: Long = HOPPER_API_TIMEOUT,
|
||||
stateFlow: StateFlow<*>? = null,
|
||||
) {
|
||||
var responseReceived = false
|
||||
val job =
|
||||
@@ -225,8 +292,13 @@ class HopperHelper {
|
||||
NaviTrackEvent.trackEvent(eventName = HOPPER_API_RESPONSE_NOT_RECEIVED)
|
||||
onResult(false)
|
||||
}
|
||||
stateFlow?.collectLatest { response ->
|
||||
responseReceived = true
|
||||
cancel()
|
||||
handleResponse(ctaData, response, onResult)
|
||||
}
|
||||
}
|
||||
liveData.observeNullable(activity) { response ->
|
||||
liveData?.observeNullable(activity) { response ->
|
||||
responseReceived = true
|
||||
liveData.removeObservers(activity)
|
||||
job.cancel()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * Copyright © 2024-2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
@@ -12,6 +12,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.navi.amc.common.viewmodel.CheckerVM
|
||||
import com.navi.amc.common.viewmodel.OTPVM
|
||||
import com.navi.amc.compose.feature.goalBasedSip.viewmodel.GoalBasedSipSetupVM
|
||||
import com.navi.amc.fundbuy.viewmodel.FundBuyFlowViewModel
|
||||
import com.navi.amc.fundbuy.viewmodel.FundListViewModel
|
||||
import com.navi.amc.kyc.viewmodel.BankDetailsVM
|
||||
@@ -29,6 +30,9 @@ import com.navi.amc.portfolio.viewmodels.SipModificationVM
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.common.utils.Constants.AMC_FUND_AUTOPAY_SETUP_V3
|
||||
import com.navi.common.utils.Constants.AMC_FUND_OTP
|
||||
import com.navi.common.utils.Constants.AMC_GOAL_BASED_SIP_AMOUNT_SCREEN
|
||||
import com.navi.common.utils.Constants.AMC_GOAL_BASED_SIP_SUMMARY_SCREEN
|
||||
import com.navi.common.utils.Constants.AMC_GOAL_BASED_SIP_TARGET_SETUP_SCREEN
|
||||
import com.navi.common.utils.Constants.AMC_HPC_NAME_REDIRECT_PAGE_URL
|
||||
import com.navi.common.utils.Constants.AMC_HPC_PAN_REDIRECT_PAGE_URL
|
||||
import com.navi.common.utils.Constants.AMC_KYC_BANK_DETAILS_URL
|
||||
@@ -72,6 +76,10 @@ class ViewModelMapper {
|
||||
AMC_FUND_OTP -> ViewModelProvider(activity)[OTPVM::class.java]
|
||||
AMC_FUND_AUTOPAY_SETUP_V3 ->
|
||||
ViewModelProvider(activity)[FundBuyFlowViewModel::class.java]
|
||||
AMC_GOAL_BASED_SIP_TARGET_SETUP_SCREEN,
|
||||
AMC_GOAL_BASED_SIP_AMOUNT_SCREEN,
|
||||
AMC_GOAL_BASED_SIP_SUMMARY_SCREEN ->
|
||||
ViewModelProvider(activity)[GoalBasedSipSetupVM::class.java]
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.naviapp.home.dashboard.models.investmentTabWidgetData
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.amc.common.model.GenericComposableWidget
|
||||
import com.navi.amc.fundbuy.models.widgets.FundCardData
|
||||
import com.navi.amc.fundbuy.models.widgets.SetupMonthlyTargetCard
|
||||
import com.navi.base.model.GenericAnalytics
|
||||
import com.navi.common.model.InvestmentBaseProperty
|
||||
import com.navi.naviwidgets.models.response.Footer
|
||||
@@ -35,7 +36,8 @@ data class TopInvestingFundsExtraData(
|
||||
)
|
||||
|
||||
data class TopInvestingFundsContentData(
|
||||
@SerializedName("fundCards") val fundCards: List<FundCardData>? = null
|
||||
@SerializedName("goalCards") val goalCards: List<SetupMonthlyTargetCard>? = null,
|
||||
@SerializedName("fundCards") val fundCards: List<FundCardData>? = null,
|
||||
)
|
||||
|
||||
data class HeaderData(
|
||||
|
||||
@@ -9,6 +9,7 @@ package com.naviapp.home.dashboard.repo
|
||||
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.base.model.JourneyType
|
||||
import com.navi.base.model.LineItem
|
||||
import com.navi.common.checkmate.model.MetricInfo
|
||||
import com.navi.common.model.ModuleNameV2
|
||||
import com.navi.common.network.models.RepoResult
|
||||
@@ -42,12 +43,13 @@ constructor(@SuperAppRetroFit private val superAppRetrofitService: RetrofitServi
|
||||
|
||||
suspend fun getDynamicCTA(
|
||||
context: String?,
|
||||
parameters: List<LineItem>? = null,
|
||||
metricInfo: MetricInfo<RepoResult<ActionData>>,
|
||||
): RepoResult<ActionData> {
|
||||
return apiResponseCallback(
|
||||
superAppRetrofitService.getDynamicCta(
|
||||
target = ModuleNameV2.AMC.name,
|
||||
journeyType = JourneyType(context = context),
|
||||
journeyType = JourneyType(context = context, parameters = parameters),
|
||||
),
|
||||
metricInfo = metricInfo,
|
||||
)
|
||||
|
||||
@@ -91,6 +91,7 @@ fun InvestmentGenericComposableWidgetFactory(
|
||||
onClick = onClick,
|
||||
investmentsTabVm = investmentsTabVm,
|
||||
onVisible = onVisible,
|
||||
onHopperStart = onHopperStart,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,13 @@ package com.naviapp.home.dashboard.ui.compose.investmentTab
|
||||
import UpcomingSipPaymentWidget
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import com.navi.amc.fundbuy.models.cards.InvestmentGoalCardData
|
||||
import com.navi.amc.fundbuy.models.cards.PaymentCard
|
||||
import com.navi.amc.fundbuy.models.widgets.FtueWithTrackerWidget
|
||||
import com.navi.amc.fundbuy.models.widgets.FundCardData
|
||||
import com.navi.amc.fundbuy.models.widgets.RepeatOrderWidget
|
||||
import com.navi.amc.fundbuy.models.widgets.RiskFreeFundWidget
|
||||
import com.navi.amc.fundbuy.models.widgets.SetupMonthlyTargetCard
|
||||
import com.navi.amc.fundbuy.models.widgets.SetupMonthlyTargetWidget
|
||||
import com.navi.base.model.GenericAnalytics
|
||||
import com.naviapp.home.dashboard.models.investmentTabWidgetData.ActionCardWidget
|
||||
@@ -73,6 +75,8 @@ fun <T> extractMetaData(widgetData: T): GenericAnalytics? {
|
||||
is CutOffTimerWidget -> widgetData.widgetData?.extraData?.metaData
|
||||
is BuyTheDipWidget -> widgetData.widgetData?.extraData?.metaData
|
||||
is FtueWithTrackerWidget -> widgetData.widgetData?.extraData?.metaData
|
||||
is SetupMonthlyTargetCard -> widgetData.actionData?.metaData
|
||||
is InvestmentGoalCardData -> widgetData.actionData?.metaData
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,12 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.navi.amc.fundbuy.composables.cards.MonthlyInvestmentGoalCardComposable
|
||||
import com.navi.amc.fundbuy.composables.cards.SetupMonthlyTargetCardComposable
|
||||
import com.navi.amc.fundbuy.models.cards.InvestmentGoalCardData
|
||||
import com.navi.amc.fundbuy.models.cards.PaymentCard
|
||||
import com.navi.amc.fundbuy.models.widgets.FundCardData
|
||||
import com.navi.amc.fundbuy.models.widgets.SetupMonthlyTargetCard
|
||||
import com.navi.amc.utils.Constant.GOAL_BASED_SIP_SETUP_CARD
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.base.model.GenericAnalytics
|
||||
@@ -47,6 +50,7 @@ import com.naviapp.utils.Constants.ORDER_IN_PROGRESS_CARD
|
||||
import com.naviapp.utils.Constants.PAGER_SCROLL
|
||||
import com.naviapp.utils.Constants.RANK_OF_CARD
|
||||
import com.naviapp.utils.Constants.REPEAT_ORDER
|
||||
import com.naviapp.utils.Constants.SETUP_MONTHLY_INVESTMENT_GOAL_CARD
|
||||
import com.naviapp.utils.Constants.SIP_AUTOPAY_NUDGE_CARD
|
||||
import com.naviapp.utils.Constants.SIP_AUTOPAY_NUDGE_CARD_V2
|
||||
import com.naviapp.utils.Constants.UPCOMING_SIP_PAYMENT_CARD
|
||||
@@ -254,5 +258,26 @@ fun RenderCardBasedOnType(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SETUP_MONTHLY_INVESTMENT_GOAL_CARD -> {
|
||||
VisibilityTracker(widgetData = data, onVisible = onVisible) {
|
||||
SetupMonthlyTargetCardComposable(
|
||||
cardData = data as SetupMonthlyTargetCard,
|
||||
onClick = onClick,
|
||||
cardWidth = cardWidth,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
GOAL_BASED_SIP_SETUP_CARD -> {
|
||||
VisibilityTracker(widgetData = data, onVisible = onVisible) {
|
||||
GoalBasedSipSetupCardComposable(
|
||||
cardData = data as SetupMonthlyTargetCard,
|
||||
onClick = onClick,
|
||||
cardWidth = cardWidth,
|
||||
onHopperStart = onHopperStart,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.naviapp.home.dashboard.ui.compose.investmentTab.genericComposables
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.navi.amc.fundbuy.models.widgets.SetupMonthlyTargetCard
|
||||
import com.navi.amc.utils.Constant.DEFAULT_COLUMN_WEIGHT
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.common.utils.Constants.HOPPER
|
||||
import com.navi.common.utils.toCtaData
|
||||
import com.navi.design.utils.clickableWithNoGesture
|
||||
import com.navi.naviwidgets.composewidget.reusable.ButtonComposable
|
||||
import com.navi.naviwidgets.extensions.NaviImage
|
||||
import com.navi.naviwidgets.extensions.NaviTextWidgetized
|
||||
import com.navi.naviwidgets.extensions.hexToColor
|
||||
import com.navi.naviwidgets.models.FooterButtonData
|
||||
import com.navi.naviwidgets.models.FooterButtonState
|
||||
import com.navi.uitron.utils.ShapeUtil
|
||||
import com.navi.uitron.utils.getBorderStrokeBrushData
|
||||
import com.navi.uitron.utils.hexToComposeColor
|
||||
import com.navi.uitron.utils.setPadding
|
||||
import com.naviapp.R
|
||||
import com.naviapp.home.dashboard.ui.compose.investmentTab.InvestmentsScreenHelper
|
||||
|
||||
@Composable
|
||||
fun GoalBasedSipSetupCardComposable(
|
||||
cardData: SetupMonthlyTargetCard? = null,
|
||||
onClick: (actionData: ActionData?) -> Unit = {},
|
||||
cardWidth: Dp,
|
||||
onHopperStart: (ctaData: CtaData, buttonState: MutableState<FooterButtonState>) -> Unit =
|
||||
{ _, _ ->
|
||||
},
|
||||
) {
|
||||
val buttonState = remember { mutableStateOf(FooterButtonState.ENABLED) }
|
||||
|
||||
cardData?.let { it ->
|
||||
Card(
|
||||
shape = ShapeUtil.run { getShape(shape = it.properties?.cardProperty?.shape) },
|
||||
elevation = it.properties?.cardProperty?.elevation?.dp ?: 0.dp,
|
||||
backgroundColor =
|
||||
it.properties?.cardProperty?.backgroundColor?.hexToComposeColor ?: Color.White,
|
||||
border =
|
||||
BorderStroke(
|
||||
width = ((it.properties?.cardProperty?.borderStrokeData?.width) ?: 0.0f).dp,
|
||||
brush = getBorderStrokeBrushData(it.properties?.cardProperty?.borderStrokeData),
|
||||
),
|
||||
modifier =
|
||||
Modifier.width(cardWidth)
|
||||
.shadow(
|
||||
elevation = (it.properties?.cardProperty?.elevation ?: 0).dp,
|
||||
ambientColor = hexToColor(it.properties?.cardProperty?.ambientColor),
|
||||
spotColor = hexToColor(it.properties?.cardProperty?.spotColor),
|
||||
shape = ShapeUtil.getShape(shape = it.properties?.cardProperty?.shape),
|
||||
)
|
||||
.clickableWithNoGesture {
|
||||
it.actionData?.let { actionData ->
|
||||
if (actionData.url == HOPPER) {
|
||||
InvestmentsScreenHelper()
|
||||
.setActionStatus(
|
||||
actionData = actionData,
|
||||
buttonState = buttonState,
|
||||
onClick = onClick,
|
||||
onHopperStart = onHopperStart,
|
||||
)
|
||||
} else {
|
||||
onClick(actionData)
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.padding(end = it.properties?.cardProperty?.padding?.end?.dp ?: 0.dp),
|
||||
contentAlignment = Alignment.TopEnd,
|
||||
) {
|
||||
NaviTextWidgetized(
|
||||
textFieldData = it.tagData,
|
||||
modifier =
|
||||
Modifier.background(
|
||||
color =
|
||||
it.properties?.tagProperty?.backgroundColor?.hexToComposeColor
|
||||
?: Color.Transparent,
|
||||
shape = ShapeUtil.getShape(it.properties?.tagProperty?.shape),
|
||||
)
|
||||
.border(
|
||||
BorderStroke(
|
||||
width =
|
||||
it.properties?.tagProperty?.borderStrokeData?.width?.dp
|
||||
?: 0.dp,
|
||||
brush =
|
||||
getBorderStrokeBrushData(
|
||||
it.properties?.tagProperty?.borderStrokeData
|
||||
),
|
||||
),
|
||||
shape = ShapeUtil.getShape(it.properties?.tagProperty?.shape),
|
||||
)
|
||||
.setPadding(it.properties?.tagProperty?.padding),
|
||||
)
|
||||
}
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
Column(Modifier.fillMaxWidth().setPadding(it.properties?.cardProperty?.padding)) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Column(
|
||||
modifier =
|
||||
Modifier.weight(
|
||||
it.properties?.cardProperty?.columnWeight
|
||||
?: DEFAULT_COLUMN_WEIGHT
|
||||
)
|
||||
) {
|
||||
NaviTextWidgetized(
|
||||
textFieldData = it.title,
|
||||
modifier =
|
||||
Modifier.setPadding(it.properties?.titleProperty?.padding),
|
||||
)
|
||||
NaviTextWidgetized(
|
||||
textFieldData = it.subtitle,
|
||||
modifier =
|
||||
Modifier.setPadding(it.properties?.subtitleProperty?.padding),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
ButtonComposable(
|
||||
data =
|
||||
FooterButtonData(
|
||||
title = it.buttonText,
|
||||
backgroundColor =
|
||||
if (
|
||||
buttonState.value.name ==
|
||||
FooterButtonState.LOADING.name
|
||||
)
|
||||
"#8F8095"
|
||||
else "#1F002A",
|
||||
cta = it.actionData?.toCtaData(),
|
||||
),
|
||||
modifier = Modifier.wrapContentWidth().wrapContentHeight(),
|
||||
textModifier = Modifier.wrapContentWidth().wrapContentHeight(),
|
||||
contentPadding =
|
||||
if (buttonState.value.name == FooterButtonState.LOADING.name) {
|
||||
PaddingValues(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
top = 12.dp,
|
||||
bottom = 12.dp,
|
||||
)
|
||||
} else {
|
||||
PaddingValues(
|
||||
start =
|
||||
((it.properties?.buttonProperty?.padding?.start)
|
||||
?: R.integer.value_16)
|
||||
.dp,
|
||||
end =
|
||||
((it.properties?.buttonProperty?.padding?.end)
|
||||
?: R.integer.value_16)
|
||||
.dp,
|
||||
top =
|
||||
((it.properties?.buttonProperty?.padding?.top)
|
||||
?: R.integer.value_12)
|
||||
.dp,
|
||||
bottom =
|
||||
((it.properties?.buttonProperty?.padding?.bottom)
|
||||
?: R.integer.value_12)
|
||||
.dp,
|
||||
)
|
||||
},
|
||||
state = buttonState.value.name,
|
||||
onClick = { ctaData ->
|
||||
it.actionData?.let {
|
||||
InvestmentsScreenHelper()
|
||||
.setActionStatus(
|
||||
actionData = it,
|
||||
buttonState = buttonState,
|
||||
onClick = onClick,
|
||||
onHopperStart = onHopperStart,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier =
|
||||
Modifier.weight(
|
||||
1 -
|
||||
(it.properties?.cardProperty?.columnWeight
|
||||
?: DEFAULT_COLUMN_WEIGHT)
|
||||
)
|
||||
.align(Alignment.Bottom),
|
||||
horizontalAlignment = Alignment.End,
|
||||
) {
|
||||
NaviImage(
|
||||
imageFieldData = it.icon,
|
||||
modifier =
|
||||
Modifier.setPadding(it.properties?.cardIconProperty?.padding),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,17 +15,21 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.navi.amc.utils.Constant.GOAL_BASED_SIP_SETUP_CARD
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.base.model.GenericAnalytics
|
||||
import com.navi.design.theme.FFF6D5
|
||||
import com.navi.design.theme.FFF9E0
|
||||
import com.navi.naviwidgets.extensions.NaviImage
|
||||
import com.navi.naviwidgets.extensions.NaviTextWidgetized
|
||||
import com.navi.naviwidgets.models.FooterButtonState
|
||||
import com.navi.rr.utils.composeutils.brushType
|
||||
import com.navi.uitron.utils.setPadding
|
||||
import com.naviapp.R
|
||||
@@ -43,6 +47,9 @@ fun TopInvestingFundsWidgetComposable(
|
||||
investmentsTabVm: InvestmentsVm,
|
||||
onClick: (actionData: ActionData?) -> Unit,
|
||||
onVisible: (genericAnalytics: GenericAnalytics?) -> Unit,
|
||||
onHopperStart: (ctaData: CtaData, buttonState: MutableState<FooterButtonState>) -> Unit =
|
||||
{ _, _ ->
|
||||
},
|
||||
) {
|
||||
widget?.widgetData?.let { widgetData ->
|
||||
Column(
|
||||
@@ -64,7 +71,7 @@ fun TopInvestingFundsWidgetComposable(
|
||||
widgetData.header.let { headerData ->
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().setPadding(headerData?.property?.padding),
|
||||
verticalAlignment = Alignment.Top,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(
|
||||
modifier =
|
||||
@@ -118,8 +125,7 @@ fun TopInvestingFundsWidgetComposable(
|
||||
Spacer(
|
||||
modifier =
|
||||
Modifier.height(
|
||||
widgetData.topInvestingFundsContent.fundCards
|
||||
.get(0)
|
||||
widgetData.topInvestingFundsContent.fundCards[0]
|
||||
.property
|
||||
?.margin
|
||||
?.top
|
||||
@@ -142,6 +148,34 @@ fun TopInvestingFundsWidgetComposable(
|
||||
investmentsTabVm = investmentsTabVm,
|
||||
)
|
||||
}
|
||||
|
||||
if (widgetData.topInvestingFundsContent?.goalCards?.isNotEmpty() == true) {
|
||||
Spacer(
|
||||
modifier =
|
||||
Modifier.height(
|
||||
widgetData.topInvestingFundsContent.goalCards[0]
|
||||
.properties
|
||||
?.cardProperty
|
||||
?.margin
|
||||
?.top
|
||||
?.dp ?: R.integer.value_24.dp
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
widgetData.topInvestingFundsContent?.goalCards?.let { list ->
|
||||
CardListComposable(
|
||||
cardType = GOAL_BASED_SIP_SETUP_CARD,
|
||||
cardWidthFactor =
|
||||
(widgetData.extraData?.extraProperties?.cardWidthFactor
|
||||
?: DEFAULT_CARD_WIDTH_FACTOR),
|
||||
cardList = list,
|
||||
onClick = onClick,
|
||||
onVisible = onVisible,
|
||||
investmentsTabVm = investmentsTabVm,
|
||||
onHopperStart = onHopperStart,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.navi.base.cache.repository.NaviCacheRepositoryImpl
|
||||
import com.navi.base.cache.util.NaviSharedDbKeys
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.base.model.LineItem
|
||||
import com.navi.base.sharedpref.PreferenceManager
|
||||
import com.navi.base.utils.isNotNull
|
||||
import com.navi.base.utils.orFalse
|
||||
@@ -390,14 +391,15 @@ constructor(
|
||||
return bottomSheetDataFromType[bottomSheetType]
|
||||
}
|
||||
|
||||
fun getDynamicCTA(context: String?) {
|
||||
fun getDynamicCTA(context: String?, parameters: List<LineItem>) {
|
||||
viewModelScope.safeLaunch(Dispatchers.IO) {
|
||||
val metricInfo =
|
||||
MetricInfo.AMCMetric<ActionData>(
|
||||
screen = INVESTMENT_TAB_SCREEN_V3,
|
||||
isNae = { !(it.errors.isNullOrEmpty() && it.error == null) },
|
||||
)
|
||||
val response = investmentsTabRepository.getDynamicCTA(context, metricInfo = metricInfo)
|
||||
val response =
|
||||
investmentsTabRepository.getDynamicCTA(context, parameters, metricInfo = metricInfo)
|
||||
if (response.error == null && response.errors.isNullOrEmpty()) {
|
||||
response.data?.let { _dynamicCta.emit(it.toCtaData()) }
|
||||
} else {
|
||||
|
||||
@@ -196,6 +196,7 @@ object Constants {
|
||||
const val SIP_AUTOPAY_NUDGE_CARD = "sipAutopayNudgeCard"
|
||||
const val SIP_AUTOPAY_NUDGE_CARD_V2 = "sipAutopayNudgeCardV2"
|
||||
const val MONTHLY_INVESTMENT_GOAL_CARD = "monthlyInvestmentGoalCard"
|
||||
const val SETUP_MONTHLY_INVESTMENT_GOAL_CARD = "setupMonthlyInvestmentGoalCard"
|
||||
const val DEFAULT_CARD_WIDTH_FACTOR = 0.92f
|
||||
const val FUND_CARD = "fundCard"
|
||||
const val FUND_BOX_CARD = "fundBoxCard"
|
||||
|
||||
Reference in New Issue
Block a user