TP-73090 TP-73092 | Nominee details page changes (#11770)
This commit is contained in:
committed by
GitHub
parent
5114dce317
commit
ef1b830fe1
@@ -12,6 +12,7 @@ import com.navi.naviwidgets.models.response.TextFieldData
|
||||
|
||||
data class MemberDetailInputWidgetModel(
|
||||
@SerializedName("dropDownDetails") val dropDownDetails: DropDownDetails? = null,
|
||||
@SerializedName("radioQuestionInfo") val radioQuestionInfo: RadioInput? = null,
|
||||
@SerializedName("pickerInfo") val pickerInfo: PickerTextInput? = null,
|
||||
@SerializedName("subWidgetData") val subWidgetData: SubWidgetData? = null,
|
||||
@SerializedName("textInputDetails") val textInputDetails: TextInputDetails? = null,
|
||||
@@ -54,3 +55,14 @@ data class TextInputDetails(
|
||||
@SerializedName("labelName") val labelName: TextFieldData? = null,
|
||||
@SerializedName("inputText") val inputText: TextFieldData? = null
|
||||
)
|
||||
|
||||
data class RadioInput(
|
||||
@SerializedName("labelName") val labelName: TextFieldData? = null,
|
||||
@SerializedName("radioOptionOne") val radioOptionYes: RadioOption? = null,
|
||||
@SerializedName("radioOptionTwo") val radioOptionNo: RadioOption? = null
|
||||
) {
|
||||
data class RadioOption(
|
||||
@SerializedName("labelName") val labelName: TextFieldData? = null,
|
||||
@SerializedName("id") val id: String? = null
|
||||
)
|
||||
}
|
||||
|
||||
@@ -63,7 +63,8 @@ data class OptionsData(
|
||||
@SerializedName("gender") val gender: String? = null,
|
||||
@SerializedName("isDefaultSelected", alternate = ["defaultSelected"])
|
||||
val isDefaultSelected: Boolean? = null,
|
||||
@SerializedName("imageUrl") val imageUrl: String? = null
|
||||
@SerializedName("imageUrl") val imageUrl: String? = null,
|
||||
@SerializedName("showDependentWidget") val showDependentWidget: Boolean? = null
|
||||
)
|
||||
|
||||
data class NumberPickerData(
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.navi.base.model.AnalyticsEvent
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.base.model.CtaType
|
||||
import com.navi.base.model.LineItem
|
||||
import com.navi.base.utils.isNotNull
|
||||
import com.navi.base.utils.isNull
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.common.ResponseState
|
||||
@@ -102,6 +103,7 @@ class PostPurchaseFormBasedFragment : GiBaseFragment(), ActionHandler.ActionOwne
|
||||
private var pageType: String? = null
|
||||
private var requestPageType: String? = null
|
||||
private var footerData: NaviWidgetData? = null
|
||||
private var footerLoaderEnabled: Boolean = false
|
||||
private var nextTransitionName: String? = null
|
||||
private var previousTransitionName: String? = null
|
||||
|
||||
@@ -237,19 +239,18 @@ class PostPurchaseFormBasedFragment : GiBaseFragment(), ActionHandler.ActionOwne
|
||||
(footerBinding?.root as? BaseNaviWidgetView)?.showErrorView(
|
||||
error = formNextPageState.errorData
|
||||
)
|
||||
binding.progressBar.isVisible = false
|
||||
hideLoader(footerLoaderEnabled)
|
||||
binding.formList.isVisible = true
|
||||
}
|
||||
is FormNextPageResponseState.Error -> {
|
||||
shouldHandleBackPress = false
|
||||
binding.progressBar.isVisible = false
|
||||
hideLoader(footerLoaderEnabled)
|
||||
}
|
||||
is FormNextPageResponseState.Loading -> {
|
||||
binding.progressBar.isVisible = true
|
||||
binding.formList.isVisible = false
|
||||
showLoader(footerLoaderEnabled)
|
||||
}
|
||||
is FormNextPageResponseState.Success -> {
|
||||
binding.progressBar.isVisible = false
|
||||
hideLoader(footerLoaderEnabled)
|
||||
viewModel.performActionFromCta(
|
||||
formNextPageState.data?.cta,
|
||||
activity as? PostPurchaseFormActivity
|
||||
@@ -272,18 +273,17 @@ class PostPurchaseFormBasedFragment : GiBaseFragment(), ActionHandler.ActionOwne
|
||||
when (formPreviousPageState) {
|
||||
is FormPreviousPageResponseState.Failure -> {
|
||||
shouldHandleBackPress = false
|
||||
binding.progressBar.isVisible = false
|
||||
hideLoader(footerLoaderEnabled)
|
||||
}
|
||||
is FormPreviousPageResponseState.Error -> {
|
||||
shouldHandleBackPress = false
|
||||
binding.progressBar.isVisible = false
|
||||
hideLoader(footerLoaderEnabled)
|
||||
}
|
||||
is FormPreviousPageResponseState.Loading -> {
|
||||
binding.progressBar.isVisible = true
|
||||
binding.formList.isVisible = false
|
||||
showLoader(footerLoaderEnabled)
|
||||
}
|
||||
is FormPreviousPageResponseState.Success -> {
|
||||
binding.progressBar.isVisible = false
|
||||
hideLoader(footerLoaderEnabled)
|
||||
viewModel.performActionFromCta(
|
||||
formPreviousPageState.data?.backCta,
|
||||
activity as? PostPurchaseFormActivity
|
||||
@@ -347,6 +347,11 @@ class PostPurchaseFormBasedFragment : GiBaseFragment(), ActionHandler.ActionOwne
|
||||
formPageViewState.data?.footer?.getOrNull(0)?.widgetData?.run {
|
||||
updateContainer(this, binding.footerContainer, true)
|
||||
footerData = this
|
||||
footerLoaderEnabled =
|
||||
(footerData as? FooterWithLeftRightButtonData)
|
||||
?.rightButton
|
||||
?.lottieLoaderUrl
|
||||
.isNotNull()
|
||||
}
|
||||
sendInitEvent(
|
||||
formPageViewState.data?.metaData?.analyticsInitEventName,
|
||||
@@ -384,6 +389,29 @@ class PostPurchaseFormBasedFragment : GiBaseFragment(), ActionHandler.ActionOwne
|
||||
}
|
||||
}
|
||||
|
||||
private fun showLoader(footerLoaderEnabled: Boolean) {
|
||||
if (footerLoaderEnabled) {
|
||||
toggleFooterLoader(true)
|
||||
} else {
|
||||
binding.progressBar.isVisible = true
|
||||
binding.formList.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideLoader(footerLoaderEnabled: Boolean) {
|
||||
if (footerLoaderEnabled) {
|
||||
toggleFooterLoader(false)
|
||||
} else {
|
||||
binding.progressBar.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleFooterLoader(isLoading: Boolean) {
|
||||
(binding.footerContainer.children.firstOrNull() as? FooterWithLeftRightButtonView)
|
||||
?.handleLoader(showRightButtonLoader = isLoading)
|
||||
binding.root.isClickable = !isLoading
|
||||
}
|
||||
|
||||
private val widgetCallback = { cta: CtaData ->
|
||||
cta.analyticsEventProperties?.run { analyticsHandler.sendEvent(this, screenName) }
|
||||
when (cta.type) {
|
||||
@@ -460,7 +488,7 @@ class PostPurchaseFormBasedFragment : GiBaseFragment(), ActionHandler.ActionOwne
|
||||
|
||||
private fun processNext(transitionKey: String? = null) {
|
||||
if (formAdapter?.isValidWidget() == true) {
|
||||
binding.progressBar.isVisible = true
|
||||
showLoader(footerLoaderEnabled)
|
||||
viewModel.processDataForNextPageApi(
|
||||
formAdapter?.getFormPageData(),
|
||||
referenceId,
|
||||
@@ -492,15 +520,21 @@ class PostPurchaseFormBasedFragment : GiBaseFragment(), ActionHandler.ActionOwne
|
||||
|
||||
// The below method will trigger for UI validations if required
|
||||
// Used for overriding default footer behaviours as well
|
||||
validateWidgetErrors(it)
|
||||
|
||||
// We don't need to validate when back button is clicked
|
||||
if (
|
||||
(it.type != CtaType.TRANSITION_API.value ||
|
||||
getTransitionName(it) != TRANSITION_BACK) &&
|
||||
it.type != CtaType.PREVIOUS_PAGE_API.value
|
||||
) {
|
||||
validateWidgetErrors(it)
|
||||
}
|
||||
when (it.type) {
|
||||
CtaType.VALIDATE_FORM_PAGE.value -> {
|
||||
toggleFooterState()
|
||||
}
|
||||
CtaType.TRANSITION_API.value -> {
|
||||
val transitionName = getTransitionName(it)
|
||||
if (transitionName == "BACK") {
|
||||
if (transitionName == TRANSITION_BACK) {
|
||||
previousTransitionName = transitionName
|
||||
processPrevious(transitionKey = transitionName)
|
||||
} else {
|
||||
@@ -655,6 +689,7 @@ class PostPurchaseFormBasedFragment : GiBaseFragment(), ActionHandler.ActionOwne
|
||||
const val TAG = "PostPurchaseFormBasedFragment"
|
||||
const val PAGE_TYPE = "pageType"
|
||||
const val POSITION = "position"
|
||||
const val TRANSITION_BACK = "BACK"
|
||||
}
|
||||
|
||||
override val screenName: String
|
||||
|
||||
@@ -18,6 +18,7 @@ import android.view.ViewParent
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.AdapterView
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.ScrollView
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
@@ -25,6 +26,7 @@ import androidx.databinding.ViewDataBinding
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.common.R as CommonR
|
||||
import com.navi.design.utils.hideCutCopyMenuPopUp
|
||||
import com.navi.insurance.R
|
||||
@@ -35,8 +37,11 @@ import com.navi.insurance.common.fragment.NaviInsuranceDatePickerHelper
|
||||
import com.navi.insurance.common.listener.EmptyTextWatcher
|
||||
import com.navi.insurance.common.models.DropDownData
|
||||
import com.navi.insurance.common.models.MemberDetailInputWidgetModel
|
||||
import com.navi.insurance.common.models.MemberDetailInputWidgetModel.SubWidgetData.AdditionalInputDetail
|
||||
import com.navi.insurance.common.models.NaviWidgetData
|
||||
import com.navi.insurance.common.models.OptionsData
|
||||
import com.navi.insurance.common.models.PickerTextInput
|
||||
import com.navi.insurance.common.models.RadioInput
|
||||
import com.navi.insurance.common.widgets.FormBaseWidgetView
|
||||
import com.navi.insurance.databinding.WidgetMemberDetailInputBinding
|
||||
import com.navi.insurance.health.fragment.CompleteMemberDetailFormFragment
|
||||
@@ -69,6 +74,8 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
private val analyticsEventTracker = NaviInsuranceAnalytics.instance.CompleteMemberDetailForm()
|
||||
private val screenName = InsuranceAnalyticsConstants.POLICY_CREATION_FORM_SCREEN
|
||||
private var applicationType = EMPTY
|
||||
// To check if the age radio type question has been answered
|
||||
private var isRadioOptionSelected = false
|
||||
|
||||
override fun updateLayout(
|
||||
binding: ViewDataBinding?,
|
||||
@@ -101,25 +108,45 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
policyDetailsNomineeLabelRelationship.setTextFieldData(
|
||||
it.dropDownDetails?.labelName
|
||||
)
|
||||
// To set relationship data in the spinner
|
||||
setRelationshipData(
|
||||
policyDetailsNomineeRelationship,
|
||||
relationshipSelectErrorTv,
|
||||
(it.dropDownDetails?.dropDownInfo?.data as? DropDownData)?.options
|
||||
)
|
||||
policyDetailsNomineeLabelDob.setTextFieldData(it.pickerInfo?.labelName)
|
||||
policyDetailsNomineeInputDob.hideCutCopyMenuPopUp()
|
||||
policyDetailsNomineeInputDob.setTextFieldHintData(it.pickerInfo?.hint)
|
||||
policyDetailsNomineeInputDob.setText(
|
||||
formatDate(it.pickerInfo?.inputText?.text, YYYY_MM_DD, DD_MM_YYYY)
|
||||
)
|
||||
stringToDate(it.pickerInfo?.inputText?.text, YYYY_MM_DD)?.let { date ->
|
||||
toggleAppointeeView(date)
|
||||
) { selectedOption ->
|
||||
// To show/hide age radio widget based on the selected relationship
|
||||
toggleAgeRadioWidgetView(selectedOption?.showDependentWidget.orFalse())
|
||||
}
|
||||
setDatePickerFor(
|
||||
policyDetailsNomineeInputDob,
|
||||
policyDetailsNomineeLabelDobVerify
|
||||
) { date ->
|
||||
toggleAppointeeView(date)
|
||||
// To show/hide DOB question based on pickInfo present in the response
|
||||
updateDobView(it.pickerInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateDobView(pickerInfo: PickerTextInput?) {
|
||||
val isVisible = pickerInfo != null
|
||||
binding.run {
|
||||
policyDetailsNomineeLabelDob.visibility = if (isVisible) VISIBLE else GONE
|
||||
policyDetailsNomineeInputDob.visibility = if (isVisible) VISIBLE else GONE
|
||||
policyDetailsNomineeLabelDobVerify.visibility = if (isVisible) VISIBLE else GONE
|
||||
|
||||
if (isVisible) {
|
||||
pickerInfo?.let {
|
||||
policyDetailsNomineeLabelDob.setTextFieldData(it.labelName)
|
||||
policyDetailsNomineeInputDob.hideCutCopyMenuPopUp()
|
||||
policyDetailsNomineeInputDob.setTextFieldHintData(it.hint)
|
||||
policyDetailsNomineeInputDob.setText(
|
||||
formatDate(it.inputText?.text, YYYY_MM_DD, DD_MM_YYYY)
|
||||
)
|
||||
stringToDate(it.inputText?.text, YYYY_MM_DD)?.let { date ->
|
||||
toggleAppointeeView(date)
|
||||
}
|
||||
setDatePickerFor(
|
||||
policyDetailsNomineeInputDob,
|
||||
policyDetailsNomineeLabelDobVerify
|
||||
) { date ->
|
||||
toggleAppointeeView(date)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,6 +164,51 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleAgeRadioWidgetView(isVisible: Boolean) {
|
||||
// Ensure the appointee view is initially toggled off
|
||||
toggleAppointeeView(false)
|
||||
|
||||
// Determine the visibility state
|
||||
val visibility = if (isVisible) VISIBLE else GONE
|
||||
|
||||
// Update the visibility of the age-related UI elements
|
||||
binding.policyDetailsNomineeLabelAge.visibility = visibility
|
||||
binding.policyDetailsNomineeAgeRadioYes.visibility = visibility
|
||||
binding.policyDetailsNomineeAgeRadioNo.visibility = visibility
|
||||
binding.ageErrorTv.visibility = GONE
|
||||
|
||||
if (isVisible) {
|
||||
memberDetailInputWidgetModel?.radioQuestionInfo?.let { radioQuestionInfo ->
|
||||
// Set the text for the age label
|
||||
binding.policyDetailsNomineeLabelAge.setTextFieldData(radioQuestionInfo.labelName)
|
||||
|
||||
// Set the radio options data and handle selection callback
|
||||
setRadioOptionsData(
|
||||
binding.policyDetailsNomineeAgeRadioYes,
|
||||
binding.policyDetailsNomineeAgeRadioNo,
|
||||
binding.ageErrorTv,
|
||||
radioQuestionInfo.radioOptionYes,
|
||||
radioQuestionInfo.radioOptionNo
|
||||
) { selectedRadioOption ->
|
||||
// Determine if the selected option indicates the nominee is above 18
|
||||
val isNomineeAgeAbove18 = selectedRadioOption.id == RADIO_OPTION_YES
|
||||
|
||||
// Toggle the appointee view based on the selected option
|
||||
toggleAppointeeView(!isNomineeAgeAbove18)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleAppointeeView(isVisible: Boolean) {
|
||||
if (isVisible && memberDetailInputWidgetModel?.widgetKey == TYPE_NOMINEE) { // 18 years
|
||||
binding.appointeeView.visibility = VISIBLE
|
||||
} else {
|
||||
formAppointeeRequestPayload.clear()
|
||||
binding.appointeeView.visibility = GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun setAppointeeUI() {
|
||||
binding.run {
|
||||
memberDetailInputWidgetModel?.subWidgetData?.let {
|
||||
@@ -163,12 +235,25 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
policyDetailsAppointeeInputDob.setText(
|
||||
formatDate(it.pickerTextInput?.inputText?.text, YYYY_MM_DD, DD_MM_YYYY)
|
||||
)
|
||||
policyDetailsAppointeeLabelPhone.setTextFieldData(
|
||||
it.additionalInputDetails?.labelName
|
||||
)
|
||||
policyDetailsAppointeePhone.hideCutCopyMenuPopUp()
|
||||
policyDetailsAppointeePhone.setTextFieldHintData(it.additionalInputDetails?.hint)
|
||||
policyDetailsAppointeePhone.setTextFieldData(it.additionalInputDetails?.inputText)
|
||||
if (it.additionalInputDetails == null) {
|
||||
policyDetailsAppointeeLabelPhone.visibility = GONE
|
||||
policyDetailsAppointeePhone.visibility = GONE
|
||||
} else {
|
||||
policyDetailsAppointeeLabelPhone.visibility = VISIBLE
|
||||
policyDetailsAppointeePhone.visibility = VISIBLE
|
||||
updateAppointeePhoneDetails(it.additionalInputDetails)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAppointeePhoneDetails(details: AdditionalInputDetail) {
|
||||
binding.run {
|
||||
policyDetailsAppointeeLabelPhone.setTextFieldData(details.labelName)
|
||||
policyDetailsAppointeePhone.apply {
|
||||
hideCutCopyMenuPopUp()
|
||||
setTextFieldHintData(details.hint)
|
||||
setTextFieldData(details.inputText)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,7 +269,8 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
private fun setRelationshipData(
|
||||
customSpinner: CustomSpinner,
|
||||
errorTextView: TextView,
|
||||
options: List<OptionsData?>?
|
||||
options: List<OptionsData?>?,
|
||||
onItemSelected: (OptionsData?) -> Unit = {}
|
||||
) {
|
||||
var selectedItemPosition = -1
|
||||
val dataList: Array<OptionsData> =
|
||||
@@ -205,7 +291,9 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
|
||||
customSpinner.onItemSelectedListener =
|
||||
object : AdapterView.OnItemSelectedListener {
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
onItemSelected(null)
|
||||
}
|
||||
|
||||
override fun onItemSelected(
|
||||
parent: AdapterView<*>?,
|
||||
@@ -223,6 +311,9 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
)
|
||||
if (position < dataList.size) {
|
||||
customSpinner.tag = dataList[position].id
|
||||
onItemSelected(dataList[position])
|
||||
} else {
|
||||
onItemSelected(null)
|
||||
}
|
||||
errorTextView.visibility =
|
||||
if (
|
||||
@@ -236,6 +327,73 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun setRadioOptionsData(
|
||||
optionOne: View,
|
||||
optionTwo: View,
|
||||
errorTextView: TextView,
|
||||
radioOptionOne: RadioInput.RadioOption?,
|
||||
radioOptionTwo: RadioInput.RadioOption?,
|
||||
callback: (selectedOption: RadioInput.RadioOption) -> Unit = {}
|
||||
) {
|
||||
// Reset the radio button selection state
|
||||
isRadioOptionSelected = false
|
||||
setRadioButtonState(
|
||||
binding.policyDetailsNomineeAgeRadioBtnYes,
|
||||
binding.policyDetailsNomineeAgeRadioBtnNo,
|
||||
isSelected = false
|
||||
)
|
||||
|
||||
// Set the text for radio options
|
||||
binding.policyDetailsNomineeAgeRadioBtnTxtYes.setTextFieldData(radioOptionOne?.labelName)
|
||||
binding.policyDetailsNomineeAgeRadioBtnTxtNo.setTextFieldData(radioOptionTwo?.labelName)
|
||||
|
||||
// Configure click listeners for radio options
|
||||
optionOne.setOnClickListener {
|
||||
handleRadioOptionClick(
|
||||
selectedOptionView = binding.policyDetailsNomineeAgeRadioBtnYes,
|
||||
otherOptionView = binding.policyDetailsNomineeAgeRadioBtnNo,
|
||||
errorTextView = errorTextView,
|
||||
callback = callback,
|
||||
selectedOption = radioOptionOne
|
||||
)
|
||||
}
|
||||
optionTwo.setOnClickListener {
|
||||
handleRadioOptionClick(
|
||||
selectedOptionView = binding.policyDetailsNomineeAgeRadioBtnNo,
|
||||
otherOptionView = binding.policyDetailsNomineeAgeRadioBtnYes,
|
||||
errorTextView = errorTextView,
|
||||
callback = callback,
|
||||
selectedOption = radioOptionTwo
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setRadioButtonState(
|
||||
selectedView: ImageView,
|
||||
unselectedView: ImageView,
|
||||
isSelected: Boolean
|
||||
) {
|
||||
selectedView.setImageResource(
|
||||
if (isSelected) com.navi.naviwidgets.R.drawable.radio_button_checked_blue
|
||||
else com.navi.naviwidgets.R.drawable.radio_button_unchecked_grey
|
||||
)
|
||||
unselectedView.setImageResource(com.navi.naviwidgets.R.drawable.radio_button_unchecked_grey)
|
||||
}
|
||||
|
||||
private fun handleRadioOptionClick(
|
||||
selectedOptionView: ImageView,
|
||||
otherOptionView: ImageView,
|
||||
errorTextView: TextView,
|
||||
callback: (selectedOption: RadioInput.RadioOption) -> Unit,
|
||||
selectedOption: RadioInput.RadioOption?
|
||||
) {
|
||||
if (selectedOption == null) return
|
||||
errorTextView.visibility = GONE
|
||||
isRadioOptionSelected = true
|
||||
setRadioButtonState(selectedOptionView, otherOptionView, isSelected = true)
|
||||
callback(selectedOption)
|
||||
}
|
||||
|
||||
private fun addNomineeDetailsTextWatcher() {
|
||||
binding.policyDetailsNomineeInputFullName.addTextChangedListener(
|
||||
EmptyTextWatcher(binding.nameErrorTv)
|
||||
@@ -391,7 +549,8 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
hideKeyboard()
|
||||
validateNomineeName(name)
|
||||
validateNomineeRelation(relation)
|
||||
validateNomineeDob(dob)
|
||||
memberDetailInputWidgetModel?.radioQuestionInfo?.let { validateNomineeAgeSelection() }
|
||||
memberDetailInputWidgetModel?.pickerInfo?.let { validateNomineeDob(dob) }
|
||||
validateAppointeeView()
|
||||
if (isValid) {
|
||||
onValid()
|
||||
@@ -414,14 +573,16 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
formNomineeRequestPayload =
|
||||
mutableMapOf<String, String>().apply {
|
||||
put(KEY_NAME, binding.policyDetailsNomineeInputFullName.text.toString().trim())
|
||||
put(
|
||||
KEY_DOB,
|
||||
sdf.format(
|
||||
displayDateFormat.parse(
|
||||
binding.policyDetailsNomineeInputDob.text.toString()
|
||||
memberDetailInputWidgetModel?.pickerInfo?.let {
|
||||
put(
|
||||
KEY_DOB,
|
||||
sdf.format(
|
||||
displayDateFormat.parse(
|
||||
binding.policyDetailsNomineeInputDob.text.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
(binding.policyDetailsNomineeRelationship.tag as? String)?.let {
|
||||
when (memberDetailInputWidgetModel?.widgetKey) {
|
||||
TYPE_NOMINEE -> put(KEY_RELATION, it)
|
||||
@@ -450,7 +611,9 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
(binding.policyDetailsAppointeeRelationship.tag as? String)?.let {
|
||||
put(KEY_RELATION, it)
|
||||
}
|
||||
put(KEY_PHONE, binding.policyDetailsAppointeePhone.text.toString().trim())
|
||||
memberDetailInputWidgetModel?.subWidgetData?.additionalInputDetails?.let {
|
||||
put(KEY_PHONE, binding.policyDetailsAppointeePhone.text.toString().trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,7 +628,9 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
validateAppointeeName(name)
|
||||
validateAppointeeRelation(relation)
|
||||
validateAppointeeDob(dob)
|
||||
validateAppointeePhone(phone)
|
||||
memberDetailInputWidgetModel?.subWidgetData?.additionalInputDetails?.let {
|
||||
validateAppointeePhone(phone)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,6 +812,17 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateNomineeAgeSelection() {
|
||||
val isAgeVisible = binding.policyDetailsNomineeLabelAge.isVisible
|
||||
val isValidSelection = !isAgeVisible || isRadioOptionSelected
|
||||
|
||||
isValid = isValid && isValidSelection
|
||||
|
||||
if (!isValidSelection) {
|
||||
showAgeError()
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateNomineeRelation(relation: String) {
|
||||
isValid =
|
||||
isValid &&
|
||||
@@ -709,6 +885,17 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun showAgeError() {
|
||||
binding.ageErrorTv.apply {
|
||||
visibility = VISIBLE
|
||||
text = context.getString(R.string.error_select_age_option)
|
||||
}
|
||||
bringAttentionOnErrorView(
|
||||
binding.policyDetailsNomineeAgeRadioGrp,
|
||||
binding.layoutPolicyNomineeView
|
||||
)
|
||||
}
|
||||
|
||||
private fun stringToDate(date: String?, format: String): Date? {
|
||||
return try {
|
||||
val simpleDateFormat = SimpleDateFormat(format)
|
||||
@@ -785,5 +972,7 @@ class MemberDetailInputWidget(context: Context, attrs: AttributeSet? = null) :
|
||||
|
||||
const val TYPE_SELF = "owner_details"
|
||||
const val TYPE_NOMINEE = "nominee_detail"
|
||||
|
||||
const val RADIO_OPTION_YES = "YES"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/dp_8"
|
||||
android:translationY="@dimen/dp_1"
|
||||
android:visibility="visible"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@id/error_view"
|
||||
app:layout_constraintBottom_toTopOf="@id/progressBar"
|
||||
tools:visibility="visible">
|
||||
|
||||
@@ -15,15 +15,7 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_policy_nominee"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center_horizontal|top"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_policy_nominee"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
@@ -36,12 +28,6 @@
|
||||
android:paddingRight="20dp"
|
||||
android:paddingBottom="20dp">
|
||||
|
||||
<View
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:background="#dfdfdf" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
|
||||
android:id="@+id/policy_details_nominee_name"
|
||||
@@ -82,7 +68,7 @@
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="textPersonName|textCapWords|textFilter|textVisiblePassword"
|
||||
android:maxLines="1"
|
||||
android:minWidth="140dp"
|
||||
android:minWidth="280dp"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
@@ -133,6 +119,99 @@
|
||||
tools:text="Please enter gender"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
|
||||
android:id="@+id/policy_details_nominee_label_age"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:layout_marginTop="40dp"
|
||||
android:clipToPadding="false"
|
||||
android:fontFamily="@font/tt_regular"
|
||||
android:gravity="start"
|
||||
tools:text="Is nominee’s age more than 18?"
|
||||
android:textColor="#4D4D4D"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/policy_details_nominee_age_radio_grp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_6">
|
||||
|
||||
<!-- Yes option -->
|
||||
<LinearLayout
|
||||
android:id="@+id/policy_details_nominee_age_radio_yes"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/policy_details_nominee_age_radio_btn_yes"
|
||||
android:layout_width="@dimen/layout_dp_14"
|
||||
android:layout_height="@dimen/layout_dp_14"
|
||||
android:src="@drawable/radio_button_unchecked_grey" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/policy_details_nominee_age_radio_btn_txt_yes"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/tt_medium"
|
||||
android:layout_marginStart="@dimen/dp_8"
|
||||
android:textColor="#191919"
|
||||
android:textSize="14sp"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="Yes" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- No option -->
|
||||
<LinearLayout
|
||||
android:id="@+id/policy_details_nominee_age_radio_no"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_24"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/policy_details_nominee_age_radio_yes">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/policy_details_nominee_age_radio_btn_no"
|
||||
android:layout_width="@dimen/layout_dp_14"
|
||||
android:layout_height="@dimen/layout_dp_14"
|
||||
android:src="@drawable/radio_button_unchecked_grey" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
android:id="@+id/policy_details_nominee_age_radio_btn_txt_no"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/tt_medium"
|
||||
android:layout_marginStart="@dimen/dp_8"
|
||||
android:textColor="#191919"
|
||||
android:textSize="14sp"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="No" />
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
|
||||
android:id="@+id/age_error_tv"
|
||||
style="@style/ErrorTextFontStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:clipToPadding="false"
|
||||
tools:text="Please select nominee's age"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
|
||||
android:id="@+id/policy_details_nominee_label_dob"
|
||||
@@ -147,6 +226,7 @@
|
||||
android:textColor="#4D4D4D"
|
||||
android:textSize="14sp" />
|
||||
|
||||
|
||||
<EditText
|
||||
android:id="@+id/policy_details_nominee_input_dob"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -163,7 +243,6 @@
|
||||
android:maxLines="1"
|
||||
android:minWidth="140dp"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
|
||||
android:id="@+id/dob_error_tv"
|
||||
@@ -255,7 +334,7 @@
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="textPersonName|textCapWords|textFilter|textVisiblePassword"
|
||||
android:maxLines="1"
|
||||
android:minWidth="140dp"
|
||||
android:minWidth="280dp"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<com.navi.design.textview.NaviTextView
|
||||
@@ -407,7 +486,6 @@
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
@@ -481,6 +481,7 @@ I highly recommend Navi Health policy because of its comprehensive benefits with
|
||||
<string name="error_enter_appointee_full_name">Please enter appointee\'s full name</string>
|
||||
<string name="error_please_enter_nominee_relationship">Please enter nominee\'s relationship with you</string>
|
||||
<string name="error_enter_nominee_dob">Please enter nominee\'s date of birth</string>
|
||||
<string name="error_select_age_option">Please select an option</string>
|
||||
<string name="error_enter_relationship_with_nominee">Please enter appointee\'s relationship with nominee</string>
|
||||
<string name="error_enter_appointee_dob">Please enter appointee\'s date of birth</string>
|
||||
<string name="error_appointee_min_age">Appointee should be at-least 18 years old</string>
|
||||
|
||||
@@ -453,7 +453,7 @@ fun TextView.setTextFieldData(
|
||||
data.cta?.let {
|
||||
if (ctaCallback != null) {
|
||||
addOnMultipleClicksHandler { ctaCallback?.invoke(data.cta) }
|
||||
}
|
||||
} else setOnClickListener(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user