NTP-2474 | Turbo checkout integration with SIP details page (#12461)

Co-authored-by: shrihari-raju_navi <shrihari.raju@navi.com>
Co-authored-by: Raaj Gopal <raaj.gopal@navi.com>
Co-authored-by: Aman S <aman.s@navi.com>
This commit is contained in:
Varun Jain
2024-09-10 23:27:26 +05:30
committed by GitHub
parent 485a2b4059
commit 3bd1d2724f
12 changed files with 240 additions and 28 deletions

View File

@@ -45,6 +45,7 @@ import com.navi.amc.utils.Constant.DISMISS
import com.navi.amc.utils.Constant.FUND_ID
import com.navi.amc.utils.Constant.HELP_BOTTOMSHEET
import com.navi.amc.utils.Constant.INIT_REFUND
import com.navi.amc.utils.Constant.ORDER_HEADER_SUBTITLE
import com.navi.amc.utils.Constant.ORDER_HEADER_TITLE
import com.navi.amc.utils.Constant.ORDER_ID
import com.navi.amc.utils.Constant.PAYMENT_ORDER_STATUS_POLLING
@@ -185,6 +186,7 @@ class OrderStatusFragment :
viewModel.sourceScreen = buyFlowVM.provideLatestGreenScreen()
if (viewModel.isOrderStatusPolling.orFalse()) {
val fundName = arguments?.getString(ORDER_HEADER_TITLE).orEmpty()
val paymentType = arguments?.getString(ORDER_HEADER_SUBTITLE).orEmpty()
val fundId = arguments?.getString(FUND_ID).orEmpty()
val orderAmount = arguments?.getString(AMOUNT).orEmpty()
val paymentTimeStamp = arguments?.getString(PAYMENT_TIMESTAMP).orEmpty()
@@ -192,7 +194,8 @@ class OrderStatusFragment :
fundName,
fundId,
orderAmount,
paymentTimeStamp
paymentTimeStamp,
paymentType
)
// start api polling for status
val requestId = arguments?.getString(Constant.TRANSACTION_ID)

View File

@@ -25,10 +25,12 @@ import com.navi.design.utils.parseColorSafe
import com.navi.design.utils.setSpannableString
import com.navi.naviwidgets.R as WidgetsR
import com.navi.naviwidgets.extensions.showWhenDataIsAvailable
import com.navi.naviwidgets.utils.setButtonLoaderState
class FooterView(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) {
private var binding: FooterLayoutBinding
private var footerInteractionListener: FooterInteractionListener? = null
private var nextCtaText: String? = null
init {
val inflater = LayoutInflater.from(context)
@@ -49,7 +51,10 @@ class FooterView(context: Context, attrs: AttributeSet?) : ConstraintLayout(cont
footerInteractionListener?.onFooterBackPress(footer.backCta)
}
}
footer?.nextCta?.title?.let { binding.nextCta.text = it }
footer?.nextCta?.title?.let {
nextCtaText = it
binding.nextCta.text = it
}
footer?.nextCta?.titleColor?.let { binding.nextCta.setTextColor(it.parseColorSafe()) }
footer?.backCta?.title?.let { binding.backCta.text = it }
footer?.backCta?.titleColor?.let { binding.backCta.setTextColor(it.parseColorSafe()) }
@@ -155,6 +160,10 @@ class FooterView(context: Context, attrs: AttributeSet?) : ConstraintLayout(cont
return binding.nextCta.text.toString()
}
fun updateButtonLoaderState(state: Boolean) {
nextCtaText?.let { setButtonLoaderState(binding.nextCta, binding.buttonLoader, state, it) }
}
enum class NextButtonTag {
ENABLED,
DISABLED

View File

@@ -29,6 +29,7 @@ import com.navi.amc.utils.updateCheckerResponse
import com.navi.base.model.ActionData
import com.navi.base.model.LineItem
import com.navi.base.utils.isNotNull
import com.navi.base.utils.isNotNullAndNotEmpty
import com.navi.base.utils.orFalse
import com.navi.common.firebasedb.FirebaseStatusType
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
@@ -91,6 +92,7 @@ constructor(
private var orderAmount: String? = null
private var fundId: String? = null
private var fundName: String? = null
private var paymentType: String? = null
var isScratchCardApiCalled = false
private var rewardLottieVisibility = false
private var rewardTextVisibility = false
@@ -100,17 +102,24 @@ constructor(
fundName: String,
fundId: String,
orderAmount: String,
paymentTimeStamp: String
paymentTimeStamp: String,
paymentType: String
) {
setFundData(fundName, fundId, orderAmount)
setFundData(fundName, fundId, orderAmount, paymentType)
_orderStatusScreenData.value =
getPollingScreenData(fundName, fundId, orderAmount, paymentTimeStamp)
getPollingScreenData(fundName, fundId, orderAmount, paymentTimeStamp, paymentType)
}
private fun setFundData(fundName: String, fundId: String, orderAmount: String) {
private fun setFundData(
fundName: String,
fundId: String,
orderAmount: String,
paymentType: String
) {
this.fundName = fundName
this.fundId = fundId
this.orderAmount = orderAmount
this.paymentType = paymentType
}
fun fetchPaymentOrderPollingScreenTimeOutData() {
@@ -153,8 +162,10 @@ constructor(
val response = repository.fetchAsyncRequestDataPayment(requestId)
_asyncResponse.value = response.data
if (response.data?.status == FirebaseStatusType.SUCCESS) {
val prefetchTaskList = AmcTaskManager.KYC_PREFETCH_TASK
val prefetchTaskList = AmcTaskManager.PAYMENT_SUCCESS_PREFETCH_TASK
triggerPreloadIfRequired(prefetchTaskList)
} else if (response.error != null || response.errors.isNullOrEmpty().not()) {
setErrorData(response.errors, response.error)
}
}
else -> {
@@ -268,6 +279,9 @@ constructor(
screenData?.let {
val fundHeaderTitle =
it.content?.amcHeaderData?.title?.copy(text = "${RUPEE_SYMBOL}$orderAmount")
val orderStatusTitle =
if (paymentType.isNotNullAndNotEmpty()) paymentType
else it.content?.orderStatusTitle?.text
val orderAmountData =
it.content
?.orderDetails
@@ -292,17 +306,19 @@ constructor(
)
)
),
orderStatusTitle =
it.content.orderStatusTitle?.copy(text = orderStatusTitle),
orderInformation =
it.content.orderInformation?.copy(
title = orderInfoTitle,
),
orderDetails =
it.content.orderDetails?.copy(
orderAmount =
it.content.orderDetails.orderAmount?.copy(
subtitle = orderAmountData
)
),
orderInformation =
it.content.orderInformation?.copy(
title = orderInfoTitle,
),
)
)
)
}
@@ -313,7 +329,8 @@ constructor(
fundName: String,
fundId: String,
orderAmount: String,
paymentTimeStamp: String
paymentTimeStamp: String,
paymentType: String
): OrderStatusScreenData? {
val jsonString: String =
FirebaseRemoteConfigHelper.getString(
@@ -328,6 +345,9 @@ constructor(
screenData?.let {
val fundHeaderTitle =
it.content?.amcHeaderData?.title?.copy(text = "${RUPEE_SYMBOL}$orderAmount")
val orderStatusTitle =
if (paymentType.isNotNullAndNotEmpty()) paymentType
else it.content?.orderStatusTitle?.text
val orderAmountData =
it.content
?.orderDetails
@@ -352,13 +372,8 @@ constructor(
)
)
),
orderDetails =
it.content.orderDetails?.copy(
orderAmount =
it.content.orderDetails.orderAmount?.copy(
subtitle = orderAmountData
)
),
orderStatusTitle =
it.content.orderStatusTitle?.copy(text = orderStatusTitle),
orderInformation =
it.content.orderInformation?.copy(
title = orderInfoTitle,

View File

@@ -36,6 +36,7 @@ import com.navi.amc.utils.Constant.AUTO_PAY_CALLBACK_ERROR
import com.navi.amc.utils.Constant.AUTO_PAY_CALLBACK_RESULT_CODE
import com.navi.amc.utils.Constant.BACK_PRESS
import com.navi.amc.utils.Constant.FLOW_TYPE_LUMPSUM_PURCHASE
import com.navi.amc.utils.Constant.FLOW_TYPE_SIP_PURCHASE
import com.navi.amc.utils.Constant.FUND_ID
import com.navi.amc.utils.Constant.INVALID_STATE
import com.navi.amc.utils.Constant.ORDER_HEADER_TITLE
@@ -138,19 +139,19 @@ class FundBuyActivity :
val url =
if (
sharedVM.paymentFlowType in
listOf(OTP_FLOW_TYPE_LUMPSUM_PURCHASE, FLOW_TYPE_LUMPSUM_PURCHASE)
listOf(
OTP_FLOW_TYPE_LUMPSUM_PURCHASE,
FLOW_TYPE_LUMPSUM_PURCHASE,
FLOW_TYPE_SIP_PURCHASE
)
) {
ORDER_STATUS // for lump sum payment
ORDER_STATUS
} else {
// for sip payment
getPaymentSyncFlowStatusCta(CheckerActivity.PAYMENT_CALLBACK_SYNC)
}
val bundle = sharedVM.paymentArgsDataMap?.toBundle() ?: Bundle()
bundle.apply {
putBoolean(
PAYMENT_ORDER_STATUS_POLLING,
true
) // needed only in case of lumpsum payment
putBoolean(PAYMENT_ORDER_STATUS_POLLING, true)
putString(ORDER_HEADER_TITLE, viewModel.fundName.orEmpty())
putString(PAYMENT_TIMESTAMP, formattedPaymentTimeStamp)
putString(FUND_ID, viewModel.fundId.orEmpty())
@@ -197,6 +198,7 @@ class FundBuyActivity :
composePaymentsResultLauncher,
this@FundBuyActivity
)
viewModel.setStartPaymentFlow(true)
}
}
}
@@ -353,6 +355,7 @@ class FundBuyActivity :
}
override fun onBackPressed() {
if (isBlockInteractability()) return
val header =
(supportFragmentManager.findFragmentById(R.id.container) as? AmcBaseFragment)
?.getHeaderData()

View File

@@ -18,6 +18,7 @@ data class SipDetailsData(
@SerializedName("autoPayChecked") val autoPayChecked: Boolean? = null,
@SerializedName("paymentMode") val paymentMode: String? = null,
@SerializedName("orderId") val orderId: String? = null,
@SerializedName("sipReferenceId") val sipReferenceId: String? = null
)
data class SipDetailsResponse(

View File

@@ -22,6 +22,7 @@ import com.navi.base.model.ActionData
import com.navi.base.model.LineItem
import com.navi.base.utils.isNull
import com.navi.common.utils.Constants.TRUE
import com.navi.common.utils.SingleLiveEvent
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@@ -33,6 +34,14 @@ class FundBuyFlowViewModel @Inject constructor() : BaseAmcVM() {
var fundName: String? = null
var fundId: String? = null
private val _startPaymentFlow = SingleLiveEvent<Boolean?>()
val startPaymentFlow: SingleLiveEvent<Boolean?>
get() = _startPaymentFlow
fun setStartPaymentFlow(state: Boolean) {
_startPaymentFlow.value = state
}
fun navigateToScreenOnBack(action: (Int) -> Unit) {
if (fragmentStack.isEmpty()) return
val screen = fragmentStack.last()

View File

@@ -14,6 +14,7 @@ import android.view.ViewStub
import android.widget.LinearLayout.LayoutParams
import androidx.core.view.updateLayoutParams
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import com.google.gson.reflect.TypeToken
import com.navi.amc.R
@@ -22,7 +23,9 @@ import com.navi.amc.common.listener.FooterInteractionListener
import com.navi.amc.common.model.InformationCardData
import com.navi.amc.common.taskProcessor.AmcTaskManager
import com.navi.amc.common.view.InformationView
import com.navi.amc.common.viewmodel.PaymentSharedVM
import com.navi.amc.databinding.FragmentSipModificationBinding
import com.navi.amc.fundbuy.models.SipDetailsData
import com.navi.amc.portfolio.models.AutoPayCardData
import com.navi.amc.portfolio.models.SingleProductData
import com.navi.amc.portfolio.models.SipModificationResponse
@@ -30,23 +33,36 @@ import com.navi.amc.portfolio.viewmodels.SipModificationVM
import com.navi.amc.portfolio.views.AutoPayCardView
import com.navi.amc.portfolio.views.ProductDetailInformationLayout
import com.navi.amc.utils.AmcAnalytics
import com.navi.amc.utils.AmcAnalytics.ISIN
import com.navi.amc.utils.Constant
import com.navi.amc.utils.Constant.ACTION_PERFORMED
import com.navi.amc.utils.Constant.AMOUNT
import com.navi.amc.utils.Constant.BYPASS_OTP
import com.navi.amc.utils.Constant.DELETED
import com.navi.amc.utils.Constant.DELETE_SIP_WITH_REASON
import com.navi.amc.utils.Constant.FLOW_TYPE_SIP_PURCHASE
import com.navi.amc.utils.Constant.FORMATTED_AMOUNT
import com.navi.amc.utils.Constant.MANDATE_OPTED_IN
import com.navi.amc.utils.Constant.MANDATE_OPTED_OUT
import com.navi.amc.utils.Constant.MODIFY_BOTTOM_SHEET
import com.navi.amc.utils.Constant.ORDER_HEADER_SUBTITLE
import com.navi.amc.utils.Constant.ORDER_ID
import com.navi.amc.utils.Constant.PAUSED
import com.navi.amc.utils.Constant.PAYMENT
import com.navi.amc.utils.Constant.REQUEST_CONFIG
import com.navi.amc.utils.Constant.RESUMED
import com.navi.amc.utils.Constant.RESUMED_INSTALLMENT
import com.navi.amc.utils.Constant.SIP_REFERENCE_ID
import com.navi.amc.utils.Constant.SKIPPED
import com.navi.amc.utils.Constant.SOURCE_TYPE
import com.navi.amc.utils.Constant.TRANSACTION_ID
import com.navi.amc.utils.SubPageStatusType
import com.navi.amc.utils.bundleToMap
import com.navi.amc.utils.getJsonObject
import com.navi.amc.utils.showToastMessage
import com.navi.base.model.ActionData
import com.navi.base.model.CtaData
import com.navi.base.utils.isNotNullAndNotEmpty
import com.navi.base.utils.orFalse
import com.navi.common.csat.CsatBottomSheet
import com.navi.common.csat.models.NetPromoterScoreRequest
@@ -54,6 +70,7 @@ import com.navi.common.listeners.FragmentInterchangeListener
import com.navi.common.listeners.HeaderInteractionListener
import com.navi.common.model.ModuleNameV2
import com.navi.common.network.models.GenericErrorResponse
import com.navi.common.ui.activity.BaseActivity
import com.navi.common.ui.fragment.HorizontalActionErrorFragment
import com.navi.common.ui.fragment.SingleSelectionBottomSheet
import com.navi.common.utils.observeNonNull
@@ -67,6 +84,11 @@ import com.navi.naviwidgets.utils.getDividerView
import com.navi.naviwidgets.utils.setMarginToChild
import com.navi.naviwidgets.views.DataSafeWidgetLayout
import com.navi.naviwidgets.views.NoteViewWidgetLayout
import com.navi.payment.model.common.PaymentSdkInitParams
import com.navi.payment.model.initiatesdk.PaymentPrefetchMethodRequest
import com.navi.payment.nativepayment.sharedviewmodel.NaviCheckoutViewModel
import com.navi.payment.utils.PaymentAnalytics
import com.navi.payment.utils.PaymentSource
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -74,6 +96,8 @@ class SipModifyFragment : AmcBaseFragment(), FooterInteractionListener {
private lateinit var binding: FragmentSipModificationBinding
private val viewModel by viewModels<SipModificationVM>()
private var bottomSheetData: GenericErrorResponse? = null
private val paymentSharedVM: PaymentSharedVM by activityViewModels()
private val naviCheckoutViewModel by activityViewModels<NaviCheckoutViewModel>()
override val screenName: String
get() = SubPageStatusType.SIP_MODIFICATION
@@ -194,6 +218,67 @@ class SipModifyFragment : AmcBaseFragment(), FooterInteractionListener {
}
}
}
buyFlowVM.startPaymentFlow.observeNonNull(viewLifecycleOwner) {
if (it == true) {
buyFlowVM.setStartPaymentFlow(false)
updateLoadingState(false)
}
}
viewModel.paymentInitiateData.observe(viewLifecycleOwner) {
sendEvent(
AmcAnalytics.AMC_PAYMENT_TOKEN_RECEIVED,
hashMapOf(
PaymentAnalytics.SYNC to it?.syncFlow?.orFalse().toString(),
PaymentAnalytics.IS_TOKEN_VALID to
it?.tokenDetails?.naviSdkToken.isNotNullAndNotEmpty().toString()
)
)
if (it?.isTurboCheckoutFlow.orFalse()) {
it?.tokenDetails
?.naviSdkToken
?.takeIf { token -> token.isNotNullAndNotEmpty() }
?.let { token ->
val paymentSdkInitParams =
PaymentSdkInitParams(
token = token,
requestId = it.tokenDetails?.transactionId.orEmpty(),
mintToken = false,
paymentPreFetchMethodRequest =
PaymentPrefetchMethodRequest(
callSdkExitOnBack = false,
previousScreenName = PaymentSource.AMC.name
),
paymentSource = PaymentSource.AMC.name
)
paymentSharedVM.paymentFlowType = FLOW_TYPE_SIP_PURCHASE
val bundle =
Bundle().apply {
putAll(arguments)
putString(SOURCE_TYPE, PAYMENT)
putString(
TRANSACTION_ID,
viewModel.paymentInitiateData.value?.tokenDetails?.transactionId
)
putParcelable(
REQUEST_CONFIG,
viewModel.paymentInitiateData.value?.requestConfig
)
putString(
ORDER_ID,
viewModel.paymentInitiateData.value?.tokenDetails?.naviOrderId
)
}
paymentSharedVM.paymentArgsDataMap = bundleToMap(bundle)
naviCheckoutViewModel.initiatePayment(paymentSdkInitParams)
}
}
}
viewModel.errorResponse.observe(viewLifecycleOwner) { updateLoadingState(false) }
}
private val primaryClickListener: View.OnClickListener =
@@ -237,11 +322,49 @@ class SipModifyFragment : AmcBaseFragment(), FooterInteractionListener {
actionData?.url.orEmpty(),
viewModel.getNetPromoterScoreRequest()
)
} else if (actionData?.url == BYPASS_OTP) {
buyFlowVM.apply {
fundName = viewModel.sipDetailsData.value?.content?.subHeader?.title?.text.orEmpty()
fundId = getParameterValue(ISIN)
}
val sipDetailsData =
SipDetailsData(
sipReferenceId = getParameterValue(SIP_REFERENCE_ID),
amount = getParameterValue(AMOUNT),
scheme = getParameterValue(ISIN)
)
arguments?.apply {
putString(AMOUNT, getParameterValue(FORMATTED_AMOUNT))
putString(ORDER_HEADER_SUBTITLE, getParameterValue(ORDER_HEADER_SUBTITLE))
}
updateLoadingState(true)
viewModel.initiateSipPayment(sipDetailsData)
} else if (actionData?.url.isNullOrEmpty().not()) {
fragmentInterchangeListener?.navigateToNextScreen(actionData, arguments ?: Bundle())
}
}
private fun getParameterValue(key: String): String {
return viewModel.sipDetailsData.value
?.footer
?.nextCta
?.parameters
?.firstOrNull { it.key.equals(key, ignoreCase = true) }
?.value
.orEmpty()
}
private fun updateLoadingState(isLoading: Boolean) {
binding.footerView.updateButtonLoaderState(isLoading)
if (isLoading) {
(activity as? BaseActivity)?.blockInteractability()
} else {
(activity as? BaseActivity)?.unblockInteractability()
}
}
private fun openCsatBottomSheet(data: CsatWidgetData?) {
data?.selected = DELETE_SIP_WITH_REASON
data?.bottomSheetData?.get(DELETE_SIP_WITH_REASON)?.reasons?.forEach {

View File

@@ -7,6 +7,7 @@
package com.navi.amc.portfolio.repositories
import com.navi.amc.fundbuy.models.SipDetailsData
import com.navi.amc.network.retrofit.RetrofitService
import com.navi.common.csat.models.NetPromoterScoreRequest
import com.navi.common.network.retrofit.ResponseCallback
@@ -26,4 +27,7 @@ class SipModificationRepository @Inject constructor(private val retrofitService:
apiResponseCallback(
retrofitService.updateSip(sipReferenceId, action, netPromoterScoreRequest)
)
suspend fun initiateSipPayment(sipDetails: SipDetailsData) =
apiResponseCallback(retrofitService.initiateSipPayment(sipDetails))
}

View File

@@ -10,10 +10,15 @@ package com.navi.amc.portfolio.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.navi.amc.common.model.AdditionalDataAsyncResponse
import com.navi.amc.common.model.NextCtaResponse
import com.navi.amc.fundbuy.models.SipDetailsData
import com.navi.amc.portfolio.models.SipModificationResponse
import com.navi.amc.portfolio.models.SipUpdateResponse
import com.navi.amc.portfolio.repositories.SipModificationRepository
import com.navi.amc.utils.updateCheckerResponse
import com.navi.common.csat.models.NetPromoterScoreRequest
import com.navi.common.network.models.RepoResult
import com.navi.common.utils.SingleLiveEvent
import com.navi.common.viewmodel.BaseVM
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -31,6 +36,11 @@ class SipModificationVM @Inject constructor(private val repository: SipModificat
val sipUpdateData: LiveData<SipUpdateResponse?>
get() = _sipUpdateData
private val _paymentInitiateData =
SingleLiveEvent<AdditionalDataAsyncResponse<NextCtaResponse>?>()
val paymentInitiateData: LiveData<AdditionalDataAsyncResponse<NextCtaResponse>?>
get() = _paymentInitiateData
private var netPromoterScoreRequest: NetPromoterScoreRequest = NetPromoterScoreRequest()
fun fetchSipModificationDetails(sipReferenceId: String, source: String) {
@@ -59,6 +69,23 @@ class SipModificationVM @Inject constructor(private val repository: SipModificat
}
}
fun initiateSipPayment(sipDetailsData: SipDetailsData) {
viewModelScope.launch {
val response = repository.initiateSipPayment(sipDetailsData)
consumePaymentInitiateResponse(response)
}
}
private fun consumePaymentInitiateResponse(
response: RepoResult<AdditionalDataAsyncResponse<NextCtaResponse>>
) {
if (response.error == null && response.errors.isNullOrEmpty()) {
_paymentInitiateData.value = updateCheckerResponse(response.data)
} else {
setErrorData(response.errors, response.error)
}
}
fun getNetPromoterScoreRequest(): NetPromoterScoreRequest {
return netPromoterScoreRequest
}

View File

@@ -57,6 +57,7 @@ object Constant {
const val DATA_SOURCE = "dataSource"
const val PURCHASE_ORDER = "PURCHASE_ORDER"
const val AMOUNT = "amount"
const val FORMATTED_AMOUNT = "formattedAmount"
const val AMOUNT_AND_UNITS = "AMOUNT_AND_UNITS"
const val FREQUENCY = "frequency"
const val AUTOPAY_CHECKED = "autopayChecked"
@@ -70,6 +71,7 @@ object Constant {
const val FUND_HEADER = "fundHeader"
const val TYPE = "type"
const val MODIFY_BOTTOM_SHEET = "MODIFY_BOTTOM_SHEET"
const val BYPASS_OTP = "BYPASS_OTP"
const val SKIPPED = "SKIPPED"
const val PAUSED = "PAUSED"
const val RESUMED = "RESUMED"
@@ -143,6 +145,7 @@ object Constant {
const val OTP_FLOW_TYPE_SIP_AUTOPAY = "SIP_AUTOPAY"
const val OTP_FLOW_TYPE_SIP_MANUAL = "SIP_MANUAL"
const val FLOW_TYPE_LUMPSUM_PURCHASE = "FLOW_TYPE_LUMPSUM_PURCHASE"
const val FLOW_TYPE_SIP_PURCHASE = "FLOW_TYPE_SIP_PURCHASE"
const val CUSTOMER_PRIOR_INVESTMENT_QUESTIONNAIRE_REQUIRED =
"customerPriorInvestmentQuestionnaireRequired"
@@ -187,6 +190,7 @@ object Constant {
const val ORDER_STATUS_TIMESTAMP_FORMAT = "dd MMM YYYY, hh:mm a"
const val PAYMENT_ORDER_STATUS_POLLING = "paymentOrderStatusPolling"
const val ORDER_HEADER_TITLE = "orderHeaderTitle"
const val ORDER_HEADER_SUBTITLE = "orderHeaderSubtitle"
const val PAYMENT_TIMESTAMP = "paymentTimeStamp"
const val FUND_ID = "fundId"
const val RUPEE_SYMBOL = ""

View File

@@ -110,6 +110,20 @@
app:layout_goneMarginStart="@dimen/dp_16"
tools:text="HELP" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/button_loader"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_48"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/next_cta"
app:layout_constraintEnd_toEndOf="@id/next_cta"
app:layout_constraintStart_toStartOf="@id/next_cta"
app:layout_constraintTop_toTopOf="@id/next_cta"
app:lottie_autoPlay="false"
app:lottie_loop="true"
app:lottie_rawRes="@raw/cta_loader"
app:lottie_speed="1.0" />
<com.navi.naviwidgets.views.DataSafeWidgetLayout
android:id="@+id/footer_note"
android:layout_width="wrap_content"

View File

@@ -47,7 +47,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/footer_tv"
android:orientation="vertical" />
<com.navi.design.textview.NaviTextView
android:id="@+id/footer_tv"
android:layout_width="match_parent"