NTP-3997, NTP-4001 || Projected Returns for Funds (#12630)
This commit is contained in:
@@ -68,6 +68,8 @@ import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.base.utils.isNull
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.base.utils.orZero
|
||||
import com.navi.common.animation.slideInFromTop
|
||||
import com.navi.common.animation.snapOut
|
||||
import com.navi.common.listeners.FragmentInterchangeListener
|
||||
import com.navi.common.listeners.HeaderInteractionListener
|
||||
import com.navi.common.pushnotification.NotificationConstants
|
||||
@@ -223,6 +225,7 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
binding.lumpsumTutorial.root.visibility = View.GONE
|
||||
binding.lumpsumPaymentCard.isVisible = false
|
||||
binding.cutoffBanner.isVisible = false
|
||||
binding.lumpsumProjection.container.isVisible = false
|
||||
setFooter()
|
||||
}
|
||||
|
||||
@@ -248,6 +251,11 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
} ?: run { binding.lumpsumPaymentCard.isVisible = false }
|
||||
|
||||
binding.cutoffBanner.isVisible = true
|
||||
if (viewModel.isFundReturnNegative || viewModel.isAmountErrorState) {
|
||||
binding.lumpsumProjection.container.visibility = View.GONE
|
||||
} else {
|
||||
binding.lumpsumProjection.container.visibility = View.VISIBLE
|
||||
}
|
||||
setFooter()
|
||||
}
|
||||
|
||||
@@ -290,6 +298,11 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
content.fundInvestmentType?.lumpsumData = viewModel.lumpsumData
|
||||
}
|
||||
|
||||
content.fundInvestmentType?.simulationData?.let {
|
||||
binding.lumpsumAmount.enableSuccessText = false
|
||||
binding.lumpsumAmount.toggleSuccessStateVisibility(false)
|
||||
}
|
||||
|
||||
viewModel.sipData = content.fundInvestmentType?.sipData
|
||||
viewModel.lumpsumData = content.fundInvestmentType?.lumpsumData
|
||||
|
||||
@@ -338,23 +351,40 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
|
||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
|
||||
viewModel.lastLumpsumInteraction = AmcAnalytics.TYPE
|
||||
binding.lumpsumAmount.getUserInput()?.let { it ->
|
||||
binding.lumpsumRecommended.setSelectedAmount(it)
|
||||
binding.lumpsumAmount.getUserInput()?.let { userInput ->
|
||||
binding.lumpsumRecommended.setSelectedAmount(userInput)
|
||||
val errorState = binding.lumpsumAmount.getUserInputPostValidation()
|
||||
if (binding.paymentFooter.root.visibility == View.VISIBLE) {
|
||||
val errorState =
|
||||
binding.lumpsumAmount.getUserInputPostValidation()
|
||||
binding.paymentFooter.amount.text =
|
||||
CurrencyUtils.getNormalizedAmount(
|
||||
if (errorState != null && it.isNotNullAndNotEmpty())
|
||||
it.toBigDecimal()
|
||||
if (
|
||||
errorState != null &&
|
||||
userInput.isNotNullAndNotEmpty()
|
||||
)
|
||||
userInput.toBigDecimal()
|
||||
else BigDecimal(0)
|
||||
)
|
||||
}
|
||||
if (errorState != null && userInput.isNotNullAndNotEmpty()) {
|
||||
viewModel.isAmountErrorState = false
|
||||
viewModel.projectedReturn(userInput).apply {
|
||||
viewModel.projectedText?.let { projectedText ->
|
||||
projectedText.text = this
|
||||
binding.lumpsumProjection.projectionTitle
|
||||
.setSpannableString(projectedText)
|
||||
slideInFromTop(binding.lumpsumProjection.container) {}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.lumpsumProjection.container.visibility = View.GONE
|
||||
snapOut(binding.lumpsumProjection.container) {}
|
||||
viewModel.isAmountErrorState = true
|
||||
}
|
||||
(content.fundInvestmentType?.lumpsumData?.getOrNull(0)
|
||||
as? LabeledTextInputFixedHintWidgetModel)
|
||||
?.let { lumpSum ->
|
||||
lumpSum.widgetData?.inputTextFixedHintItemData?.savedText =
|
||||
it
|
||||
userInput
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -362,6 +392,28 @@ class FundBuyingFragmentV2 : AmcBaseFragment(), WidgetCallback {
|
||||
override fun afterTextChanged(p0: Editable?) {}
|
||||
}
|
||||
)
|
||||
content.fundInvestmentType?.simulationData?.let { simulationData ->
|
||||
viewModel.lumpSumReturnRate = simulationData.lumpsumReturnRate
|
||||
viewModel.isFundReturnNegative = simulationData.lumpsumReturnRate == null
|
||||
binding.lumpsumProjection.image.showWhenDataIsAvailable(simulationData.iconCode)
|
||||
binding.lumpsumProjection.title.setSpannableString(
|
||||
simulationData.simulationText
|
||||
)
|
||||
val defaultAmount = viewModel.projectedReturn(viewModel.lumpsumAmount)
|
||||
defaultAmount?.let { amount ->
|
||||
viewModel.projectedText = simulationData.projectedReturnsText
|
||||
viewModel.projectedText?.text = amount
|
||||
binding.lumpsumProjection.projectionTitle.setSpannableString(
|
||||
viewModel.projectedText
|
||||
)
|
||||
binding.lumpsumProjection.container.isVisible = true
|
||||
}
|
||||
}
|
||||
?: run {
|
||||
viewModel.isFundReturnNegative = true
|
||||
binding.lumpsumAmount.enableSuccessText = true
|
||||
binding.lumpsumAmount.toggleSuccessStateVisibility(false)
|
||||
}
|
||||
content.fundInvestmentType?.lumpsumRecommendedAmount?.let { chipData ->
|
||||
binding.lumpsumRecommended.setProperties(chipData) { lsRecommended, action ->
|
||||
val updatedAmount =
|
||||
|
||||
@@ -94,7 +94,16 @@ data class FundInvestmentType(
|
||||
@SerializedName("lumpsumPaymentMode") val lumpsumPaymentMode: PaymentMode? = null,
|
||||
@SerializedName("informationNote") val informationNote: InformationNoteData? = null,
|
||||
@SerializedName("sipStartDateOffset") val sipStartDateOffset: SipStartDateOffset? = null,
|
||||
@SerializedName("noteBanner") val noteBanner: NoteBannerData? = null
|
||||
@SerializedName("noteBanner") val noteBanner: NoteBannerData? = null,
|
||||
@SerializedName("simulationData") val simulationData: AmountSimulationData? = null
|
||||
)
|
||||
|
||||
data class AmountSimulationData(
|
||||
@SerializedName("iconCode") val iconCode: String? = null,
|
||||
@SerializedName("lumpsumReturnRate") val lumpsumReturnRate: Double? = null,
|
||||
@SerializedName("backgroundColor") val backgroundColor: String? = null,
|
||||
@SerializedName("simulationText") val simulationText: TextWithStyle? = null,
|
||||
@SerializedName("projectedReturnsText") val projectedReturnsText: TextWithStyle? = null
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
|
||||
@@ -56,7 +56,13 @@ data class FundDuration(
|
||||
@SerializedName("key") val key: String? = null,
|
||||
@SerializedName("durationInMonths") val durationInMonths: Int? = null,
|
||||
@SerializedName("selected") var selected: Boolean? = null,
|
||||
@SerializedName("bgColorVariations") val bgColorVariations: Map<String, String>? = null
|
||||
@SerializedName("bgColorVariations") val bgColorVariations: Map<String, String>? = null,
|
||||
@SerializedName("returnsTooltip") val returnsTooltip: ReturnsTooltipData? = null
|
||||
)
|
||||
|
||||
data class ReturnsTooltipData(
|
||||
@SerializedName("imageUrl") val imageUrl: String? = null,
|
||||
@SerializedName("title") val title: TextWithStyle? = null
|
||||
)
|
||||
|
||||
data class XAxisLabelData(
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.navi.amc.utils.Constant.DAILY
|
||||
import com.navi.amc.utils.Constant.FORTNIGHTLY
|
||||
import com.navi.amc.utils.Constant.MONTHLY
|
||||
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.common.utils.EMPTY
|
||||
@@ -73,6 +74,10 @@ class FundBuyV2ViewModel @Inject constructor(private val repository: FundBuyRepo
|
||||
var sipAmount: String? = null
|
||||
var sipData: List<NaviWidget>? = null
|
||||
var lumpsumData: List<NaviWidget>? = null
|
||||
var lumpSumReturnRate: Double? = null
|
||||
var projectedText: TextWithStyle? = null
|
||||
var isFundReturnNegative: Boolean = false
|
||||
var isAmountErrorState: Boolean = false
|
||||
|
||||
private val _paymentInitiateData =
|
||||
MutableLiveData<AdditionalDataAsyncResponse<NextCtaResponse>?>()
|
||||
@@ -312,6 +317,10 @@ class FundBuyV2ViewModel @Inject constructor(private val repository: FundBuyRepo
|
||||
isAutoPaySelected = null
|
||||
sipData = null
|
||||
lumpsumData = null
|
||||
lumpSumReturnRate = null
|
||||
projectedText = null
|
||||
isFundReturnNegative = false
|
||||
isAmountErrorState = false
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
@@ -345,6 +354,14 @@ class FundBuyV2ViewModel @Inject constructor(private val repository: FundBuyRepo
|
||||
return _fundBuyScreenData.value?.content?.isManualVsAutopay.orFalse()
|
||||
}
|
||||
|
||||
fun projectedReturn(userInput: String?): String? {
|
||||
val returnRate = lumpSumReturnRate
|
||||
if (returnRate != null && userInput != null) {
|
||||
return roundOffAmount(userInput.toDouble() * returnRate)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val DAY_IN_MILLIS = 24 * 60 * 60 * 1000L
|
||||
}
|
||||
|
||||
@@ -14,14 +14,20 @@ import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import android.view.ViewTreeObserver
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.forEach
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.transition.Fade
|
||||
import androidx.transition.TransitionManager
|
||||
import com.github.mikephil.charting.data.Entry
|
||||
import com.github.mikephil.charting.data.LineData
|
||||
import com.github.mikephil.charting.data.LineDataSet
|
||||
@@ -45,11 +51,14 @@ import com.navi.amc.utils.ColorUtils.FUND_GRAPH_CHIP_SELECTED_COLOR
|
||||
import com.navi.base.model.ActionData
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.base.utils.orZero
|
||||
import com.navi.common.animation.fadeOut
|
||||
import com.navi.common.animation.slideInFromTop
|
||||
import com.navi.design.utils.CornerRadius
|
||||
import com.navi.design.utils.dpToPxInInt
|
||||
import com.navi.design.utils.getNaviDrawable
|
||||
import com.navi.design.utils.parseColorSafe
|
||||
import com.navi.design.utils.setSpannableString
|
||||
import com.navi.naviwidgets.extensions.showWhenDataIsAvailable
|
||||
import com.navi.naviwidgets.widgets.InfoWithTimerWidgetLayout.Companion.COLOR_WHITE
|
||||
|
||||
class FundGraphView(context: Context, attributeSet: AttributeSet? = null) :
|
||||
@@ -159,9 +168,26 @@ class FundGraphView(context: Context, attributeSet: AttributeSet? = null) :
|
||||
object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
binding.options.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
val chipSpacing = dpToPxInInt(8)
|
||||
val chipSpacing = dpToPxInInt(CHIP_SPACING_DENSE)
|
||||
binding.options.chipSpacingHorizontal = chipSpacing
|
||||
binding.triangles.forEach { triangle ->
|
||||
triangle.apply {
|
||||
layoutParams =
|
||||
LinearLayout.LayoutParams(dpToPxInInt(20), dpToPxInInt(12))
|
||||
.apply {
|
||||
setMargins(
|
||||
dpToPxInInt(TRIANGLE_MARGIN_START),
|
||||
0,
|
||||
dpToPxInInt(
|
||||
TRIANGLE_MARGIN_END + CHIP_SPACING_DENSE
|
||||
),
|
||||
0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.options.requestLayout()
|
||||
binding.triangles.requestLayout()
|
||||
}
|
||||
}
|
||||
binding.options.viewTreeObserver.addOnGlobalLayoutListener(globalLayoutListener)
|
||||
@@ -326,6 +352,7 @@ class FundGraphView(context: Context, attributeSet: AttributeSet? = null) :
|
||||
|
||||
private fun addChipView(data: FundDuration) {
|
||||
|
||||
val itemId = ViewCompat.generateViewId()
|
||||
val chipBinding =
|
||||
DataBindingUtil.inflate<ChipBinding>(
|
||||
LayoutInflater.from(context),
|
||||
@@ -333,14 +360,32 @@ class FundGraphView(context: Context, attributeSet: AttributeSet? = null) :
|
||||
binding.options,
|
||||
false
|
||||
)
|
||||
|
||||
chipBinding.chip.id = ViewCompat.generateViewId()
|
||||
chipBinding.chip.id = itemId
|
||||
chipIdToDataMap[chipBinding.chip.id] = data
|
||||
|
||||
chipBinding.chip.chipBackgroundColor = createChipBg(data)
|
||||
|
||||
chipBinding.chip.setSpannableString(data.title)
|
||||
binding.options.addView(chipBinding.root)
|
||||
|
||||
val triangle =
|
||||
ImageView(context).apply {
|
||||
id = itemId
|
||||
setImageResource(R.drawable.triangle)
|
||||
visibility = View.GONE
|
||||
layoutParams =
|
||||
LinearLayout.LayoutParams(
|
||||
dpToPxInInt(TRIANGLE_WIDTH),
|
||||
dpToPxInInt(TRIANGLE_HEIGHT)
|
||||
)
|
||||
.apply {
|
||||
setMargins(
|
||||
dpToPxInInt(TRIANGLE_MARGIN_START),
|
||||
0,
|
||||
dpToPxInInt(TRIANGLE_MARGIN_END + CHIP_SPACING_NORMAL),
|
||||
0
|
||||
)
|
||||
}
|
||||
}
|
||||
binding.triangles.addView(triangle)
|
||||
}
|
||||
|
||||
private fun updateSelectedChips(group: ChipGroup, checkedIds: List<Int>) {
|
||||
@@ -359,10 +404,13 @@ class FundGraphView(context: Context, attributeSet: AttributeSet? = null) :
|
||||
if (checkedIds.contains(childId)) {
|
||||
fundDurationSelectedListener?.invoke(childData, isChipCheckedByUser)
|
||||
childView.setSpannableString(childData.title, ColorUtils.KEY_COLOR_SELECTED)
|
||||
updateSelectedTooltip(childData, childId)
|
||||
childData.key?.let { key -> updateGraph(key) }
|
||||
childData.selected = true
|
||||
} else {
|
||||
childView.setSpannableString(childData.title)
|
||||
val triangle = binding.triangles.findViewById<ImageView>(childId)
|
||||
triangle.visibility = View.INVISIBLE
|
||||
childData.selected = false
|
||||
}
|
||||
}
|
||||
@@ -397,4 +445,40 @@ class FundGraphView(context: Context, attributeSet: AttributeSet? = null) :
|
||||
intArrayOf(defaultColor.parseColorSafe(), selectedColor.parseColorSafe())
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
binding.chipTooltipContent.root.visibility = View.VISIBLE
|
||||
slideInFromTop(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 }
|
||||
)
|
||||
fadeOut(binding.chipTooltipContent.root) {
|
||||
triangle.visibility = View.GONE
|
||||
binding.triangles.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "FundGraphView"
|
||||
const val TRIANGLE_WIDTH = 20
|
||||
const val TRIANGLE_HEIGHT = 12
|
||||
const val TRIANGLE_MARGIN_START = 16
|
||||
const val TRIANGLE_MARGIN_TOP = 8
|
||||
const val TRIANGLE_MARGIN_END = 16
|
||||
const val CHIP_SPACING_NORMAL = 16
|
||||
const val CHIP_SPACING_DENSE = 8
|
||||
const val FADE_OUT_DURATION = 1000L
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.navi.amc.common.model.NextCtaResponse
|
||||
import com.navi.amc.fundbuy.models.FundDuration
|
||||
import com.navi.amc.fundbuy.models.NavInfo
|
||||
import com.navi.amc.network.deserializer.FundListDeserializer
|
||||
import com.navi.amc.utils.Constant.RUPEE_SYMBOL
|
||||
import com.navi.amc.utils.Constant.UPI_APP_INTENT_URL
|
||||
import com.navi.base.AppServiceManager
|
||||
import com.navi.base.model.ActionData
|
||||
@@ -40,8 +41,10 @@ import com.navi.naviwidgets.validations.ValidationJsonDeserializer
|
||||
import com.navi.naviwidgets.widgets.NaviWidgetJsonDeserializer
|
||||
import java.lang.reflect.Type
|
||||
import java.net.URI
|
||||
import java.text.DecimalFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.TimeZone
|
||||
import kotlin.math.floor
|
||||
import kotlin.math.max
|
||||
|
||||
fun calculateInvestmentReturnsAmount(
|
||||
@@ -200,3 +203,15 @@ fun getFundGraphItemCacheKey(key: String, fundName: String): String {
|
||||
.plus(UNDERSCORE)
|
||||
.plus("CACHE_KEY")
|
||||
}
|
||||
|
||||
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("#.##")
|
||||
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"
|
||||
else -> df.format(floor(value * 100) / 100.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="328dp"
|
||||
android:height="76dp"
|
||||
android:viewportWidth="328"
|
||||
android:viewportHeight="76"
|
||||
>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M4 0H324C326.209 0 328 1.79086 328 4V72C328 74.2091 326.209 76 324 76H4C1.79086 76 0 74.2091 0 72V4C0 1.79086 1.79086 0 4 0Z"
|
||||
/>
|
||||
<path
|
||||
android:pathData="M0 0V76H328V0"
|
||||
android:fillColor="#FFFFFF"
|
||||
/>
|
||||
<path
|
||||
android:pathData="M4 0H324C326.209 0 328 1.79086 328 4V72C328 74.2091 326.209 76 324 76H4C1.79086 76 0 74.2091 0 72V4C0 1.79086 1.79086 0 4 0Z"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="#EBEBEB"
|
||||
/>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="328dp"
|
||||
android:height="40dp"
|
||||
android:viewportWidth="328"
|
||||
android:viewportHeight="40">
|
||||
<path
|
||||
android:pathData="M0,0V36C0,38.21 1.79,40 4,40H324C326.21,40 328,38.21 328,36V0C328,2.21 326.21,4 324,4H4C1.79,4 0,2.21 0,0Z"
|
||||
android:fillColor="#F5F5F5"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
14
android/navi-amc/src/main/res/drawable/triangle.xml
Normal file
14
android/navi-amc/src/main/res/drawable/triangle.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="12dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="12">
|
||||
<path
|
||||
android:pathData="M9.268,1L1,11.627L17.801,11.458L9.268,1Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M19.355,10.68H17.909C16.955,10.68 16.058,10.227 15.493,9.458L9.268,1L3.396,9.402C2.834,10.205 1.916,10.684 0.937,10.684H0"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#EBEBEB"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingHorizontal="@dimen/_8dp"
|
||||
android:paddingTop="@dimen/_10dp"
|
||||
android:background="@drawable/projection_background"
|
||||
android:paddingBottom="@dimen/_8dp"
|
||||
android:translationZ="-2dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/image"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_width="@dimen/_22dp"
|
||||
android:layout_height="@dimen/_22dp"/>
|
||||
|
||||
<LinearLayout
|
||||
app:layout_constraintStart_toEndOf="@id/image"
|
||||
android:layout_marginStart="@dimen/_4dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="@dimen/_3dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:lineSpacingExtra="@dimen/_3dp"
|
||||
android:maxLines="@integer/integer_1"
|
||||
app:layout_constraintEnd_toStartOf="@id/title2"
|
||||
tools:text="About SIPS" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/projection_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:lineSpacingExtra="@dimen/_3dp"
|
||||
android:maxLines="@integer/integer_1"
|
||||
app:layout_constraintStart_toEndOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:text="About SIPS" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_8"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
android:layout_marginBottom="@dimen/dp_16"
|
||||
android:lineSpacingExtra="@dimen/dp_4"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
tools:text="SIP allows you to invest a fixed amount of money at pre-defined intervals." />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/cross"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
android:layout_marginTop="@dimen/dp_16"
|
||||
android:src="@drawable/small_cross"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
@@ -5,7 +5,7 @@
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/chip"
|
||||
style="@style/ChipStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="@dimen/dp_51"
|
||||
android:layout_height="wrap_content"
|
||||
android:checkable="true"
|
||||
android:clickable="true"
|
||||
|
||||
@@ -95,17 +95,31 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/social_validation" />
|
||||
|
||||
<include
|
||||
android:id="@+id/lumpsum_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/lumpsum_amount" />
|
||||
|
||||
<com.navi.amc.fundbuy.views.AmountChipGroupView
|
||||
android:id="@+id/lumpsum_recommended"
|
||||
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/lumpsum_amount" />
|
||||
app:layout_constraintTop_toTopOf="@id/lumpsum_amount" />
|
||||
|
||||
<com.navi.amc.fundbuy.views.AmountChipGroupView
|
||||
android:id="@+id/sip_recommended"
|
||||
@@ -318,7 +332,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="sip_frequency,sip_amount,date,lumpsum_amount" />
|
||||
app:constraint_referenced_ids="sip_frequency,sip_amount,date,lumpsum_projection" />
|
||||
|
||||
<com.navi.naviwidgets.widgets.TimerWithImageWidgetLayout
|
||||
android:id="@+id/cutoff_banner"
|
||||
|
||||
@@ -166,26 +166,60 @@
|
||||
android:id = "@+id/chip_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:translationZ="@dimen/dp_8"
|
||||
android:gravity="center_horizontal"
|
||||
android:paddingTop="@dimen/dp_8"
|
||||
android:layout_marginTop="317dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/chart_label_barrier">
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/options"
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:paddingTop="@dimen/dp_8"
|
||||
android:layout_marginHorizontal="@dimen/dp_8"
|
||||
app:chipSpacingHorizontal="@dimen/dp_16"
|
||||
app:selectionRequired="true"
|
||||
app:singleLine="true"
|
||||
app:singleSelection="true" />
|
||||
android:orientation="vertical"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/options"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:paddingTop="@dimen/dp_8"
|
||||
android:layout_marginHorizontal="@dimen/dp_8"
|
||||
app:chipSpacingHorizontal="@dimen/dp_16"
|
||||
app:selectionRequired="true"
|
||||
app:singleLine="true"
|
||||
app:singleSelection="true" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/triangles"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:showDividers="middle"
|
||||
android:layout_marginTop="@dimen/_8dp"
|
||||
android:elevation="@dimen/_8dp"
|
||||
android:translationZ="@dimen/dp_8"
|
||||
android:layout_marginHorizontal="@dimen/dp_8"
|
||||
android:divider="@color/transparent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/chip_tooltip_content"
|
||||
layout="@layout/generic_tooltip_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="-1dp"
|
||||
android:translationZ="-8dp"
|
||||
android:visibility="gone"
|
||||
android:layout_marginTop="-2dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/chip_group" />
|
||||
|
||||
|
||||
<com.navi.amc.common.view.FundInvestmentDetailsView
|
||||
android:id="@+id/fund_investment_details"
|
||||
@@ -195,6 +229,6 @@
|
||||
android:layout_marginTop="@dimen/dp_30"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/chip_group" />
|
||||
app:layout_constraintTop_toBottomOf="@id/chip_tooltip_content" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:padding="@dimen/_16dp"
|
||||
android:background="@drawable/box_shadow_bottom_4"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/tooltip_image"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_width="@dimen/_44dp"
|
||||
android:layout_height="@dimen/_44dp"/>
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/title"
|
||||
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_constraintBottom_toBottomOf="parent"
|
||||
tools:text="About SIPS" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="@dimen/dp_0"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_8"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
android:layout_marginBottom="@dimen/dp_16"
|
||||
android:lineSpacingExtra="@dimen/dp_4"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
tools:text="SIP allows you to invest a fixed amount of money at pre-defined intervals." />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/cross"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
android:layout_marginTop="@dimen/dp_16"
|
||||
android:src="@drawable/small_cross"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
@@ -112,4 +112,5 @@
|
||||
<dimen name="_dp55">55dp</dimen>
|
||||
<dimen name="_dp33">33dp</dimen>
|
||||
<dimen name="_dp125">125dp</dimen>
|
||||
<dimen name="dp_51">51dp</dimen>
|
||||
</resources>
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2022-2023 by Navi Technologies Limited
|
||||
* * Copyright © 2022-2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
@@ -47,6 +47,14 @@ fun slideOutBottom(view: View?, callback: () -> Unit = {}) {
|
||||
outAnimation(R.anim.slide_out_bottom, view, callback)?.let { view?.startAnimation(it) }
|
||||
}
|
||||
|
||||
fun snapOut(view: View?, callback: () -> Unit = {}) {
|
||||
outAnimation(R.anim.snap_out, view, callback)?.let { view?.startAnimation(it) }
|
||||
}
|
||||
|
||||
fun slideInFromTop(view: View?, callback: () -> Unit = {}) {
|
||||
inAnimation(R.anim.snap_slide_in_top, view, callback)?.let { view?.startAnimation(it) }
|
||||
}
|
||||
|
||||
fun shakeAnimation(view: View?) {
|
||||
if (view == null || view.visibility == View.GONE || view.visibility == View.INVISIBLE) {
|
||||
return
|
||||
|
||||
11
android/navi-common/src/main/res/anim/snap_out.xml
Normal file
11
android/navi-common/src/main/res/anim/snap_out.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="250"
|
||||
android:fromYDelta="1%"
|
||||
android:toYDelta="-100%" />
|
||||
<alpha
|
||||
android:duration="250"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0" />
|
||||
</set>
|
||||
11
android/navi-common/src/main/res/anim/snap_slide_in_top.xml
Normal file
11
android/navi-common/src/main/res/anim/snap_slide_in_top.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromYDelta="-100%"
|
||||
android:toYDelta="1%" />
|
||||
<alpha
|
||||
android:duration="300"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0" />
|
||||
</set>
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2023 by Navi Technologies Limited
|
||||
* * Copyright © 2023-2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
@@ -49,6 +49,7 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
var showInfoIcon: Boolean = false
|
||||
var baseBorderDrawable: Int? = null
|
||||
var isErrorTextNull = true
|
||||
var isSuccessStateVisible = true
|
||||
|
||||
fun generateQueryParam(
|
||||
widgetModel: InputWidgetModel,
|
||||
@@ -249,7 +250,9 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
}
|
||||
return if (isInputValid) {
|
||||
setError(null)
|
||||
setMoneySuccessText(tempInput)
|
||||
if (isSuccessStateVisible) {
|
||||
setMoneySuccessText(tempInput)
|
||||
}
|
||||
tempInput
|
||||
} else {
|
||||
null
|
||||
@@ -521,5 +524,9 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
binding.info.isVisible = show && showInfoIcon
|
||||
}
|
||||
|
||||
fun toggleSuccessStateVisibility(show: Boolean) {
|
||||
isSuccessStateVisible = show
|
||||
}
|
||||
|
||||
class EndTextClickAction(val baseInputWidget: BaseInputWidget) : NaviClickAction()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user