Merge pull request #2294 from medici/feature/configure_chat_touchpoints
Configure chat touchpoints
This commit is contained in:
@@ -2,17 +2,18 @@ package com.naviapp.common.customview
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.navi.common.extensions.setVisibilityState
|
||||
import com.navi.naviwidgets.extensions.showWhenDataIsAvailable
|
||||
import com.naviapp.R
|
||||
import com.naviapp.databinding.IconButtonViewBinding
|
||||
import com.naviapp.models.response.ImageDetail
|
||||
import com.naviapp.utils.*
|
||||
|
||||
class IconTextCustomView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {
|
||||
@@ -91,4 +92,15 @@ class IconTextCustomView(context: Context, attrs: AttributeSet?) : LinearLayout(
|
||||
binding.iconIv.setImageResource(icon)
|
||||
binding.titleTv.spannableString(text, spanLength, color)
|
||||
}
|
||||
|
||||
fun setProperties(title: String?, subtitle: String?, imageDetail: ImageDetail?) {
|
||||
imageDetail?.let {
|
||||
binding.iconIv.setVisibilityState(VISIBLE)
|
||||
IconUtils.updateIcon(it, binding.iconIv)
|
||||
} ?: binding.iconIv.setVisibilityState(GONE)
|
||||
|
||||
binding.titleTv.showWhenDataIsAvailable(title)
|
||||
|
||||
binding.tvSubTitle.showWhenDataIsAvailable(subtitle)
|
||||
}
|
||||
}
|
||||
@@ -31,4 +31,11 @@ class DashboardRepository : ResponseCallback() {
|
||||
|
||||
suspend fun submitLatePaymentReason(latePaymentReason: LatePaymentReasonData) =
|
||||
apiResponseCallback(retrofitService().submitLatePaymentReason(latePaymentReason))
|
||||
|
||||
suspend fun fetchCustomerSupportOptions(screenName: String) =
|
||||
apiResponseCallback(
|
||||
retrofitService().fetchCustomerSupportOptions(
|
||||
screenName = screenName
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import com.naviapp.models.GiPaymentError
|
||||
import com.naviapp.models.PgRepaymentData
|
||||
import com.naviapp.models.UserProfile
|
||||
import com.naviapp.models.request.LatePaymentReasonData
|
||||
import com.naviapp.models.response.CustomerSupportOptionsResponse
|
||||
import com.naviapp.models.response.GroupFaq
|
||||
import com.naviapp.models.response.SuccessResponse
|
||||
import com.naviapp.models.response.WidgetGenericResponse
|
||||
@@ -79,6 +80,10 @@ class DashboardSharedVM(private val repository: DashboardRepository = DashboardR
|
||||
val latePaymentReasonSubmitResponse: LiveData<SuccessResponse>
|
||||
get() = _latePaymentReasonSubmitResponse
|
||||
|
||||
private val _customerSupportOptionsResponse = MutableLiveData<CustomerSupportOptionsResponse>()
|
||||
val customerSupportOptionsResponse: LiveData<CustomerSupportOptionsResponse>
|
||||
get() = _customerSupportOptionsResponse
|
||||
|
||||
fun fetchFaqs() {
|
||||
coroutineScope.launch {
|
||||
val response = repository.fetchFaqs()
|
||||
@@ -152,4 +157,15 @@ class DashboardSharedVM(private val repository: DashboardRepository = DashboardR
|
||||
_latePaymentReasonSubmitResponse.value = response.data
|
||||
}
|
||||
}
|
||||
|
||||
fun fetchCustomerSupportOptions(screenName: String) {
|
||||
coroutineScope.launch {
|
||||
val response = repository.fetchCustomerSupportOptions(screenName)
|
||||
if (response.error == null && response.errors.isNullOrEmpty()) {
|
||||
_customerSupportOptionsResponse.value = response.data
|
||||
} else {
|
||||
setErrorData(response.errors, response.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,12 +29,10 @@ import com.naviapp.models.RedirectPageStatus
|
||||
import com.naviapp.models.response.RejectionDetailsResponse
|
||||
import com.naviapp.network.models.GenericErrorResponse
|
||||
import com.naviapp.personalloan.getloan.activities.GetLoanActivity.Companion.IS_FOR_SECOND_LOAN_JOURNEY
|
||||
import com.naviapp.personalloan.getloan.activities.GetLoanActivity.Companion.LOAN_OFFER_TYPE
|
||||
import com.naviapp.utils.*
|
||||
import com.naviapp.utils.Constants.E_ELIGIBILITY_SOFT_REJECTION_001
|
||||
import com.naviapp.utils.Constants.E_OFFER_SOFT_REJECTION_001
|
||||
import com.naviapp.utils.Constants.REJECTED
|
||||
import com.naviapp.utils.IntentConstants.OFFER_TYPE_ON_DEMAND
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
@@ -127,10 +125,14 @@ class ErrorActivity : BaseActivity(), View.OnClickListener {
|
||||
val bundle = fragment.arguments ?: Bundle()
|
||||
fragment.arguments =
|
||||
bundle.apply {
|
||||
if (isHomeLoan) putBoolean(IS_SOFT_REJECT, true)
|
||||
else putBoolean(IS_SOFT_REJECT, isSoftReject)
|
||||
if (isHomeLoan) {
|
||||
putBoolean(IS_SOFT_REJECT, true)
|
||||
} else {
|
||||
putBoolean(IS_SOFT_REJECT, isSoftReject)
|
||||
}
|
||||
putParcelable(SECOND_LOAN_ERROR_DATA, data?.humanReadableContent)
|
||||
putParcelable(CREDIT_ANALYSIS_DATA, data?.creditScoreData)
|
||||
putParcelable(CHAT_NUDGE_DATA, data?.chatNudge)
|
||||
}
|
||||
supportFragmentManager.beginTransaction().run {
|
||||
replace(R.id.error_container_fl, fragment, tag)
|
||||
@@ -292,6 +294,7 @@ class ErrorActivity : BaseActivity(), View.OnClickListener {
|
||||
const val LOAN_OFFER_EXPIRED = "LOAN_OFFER_EXPIRED"
|
||||
const val SECOND_LOAN_ERROR_DATA = "SECOND_LOAN_ERROR_DATA"
|
||||
const val CREDIT_ANALYSIS_DATA = "CREDIT_ANALYSIS_DATA"
|
||||
const val CHAT_NUDGE_DATA = "CHAT_NUDGE_DATA"
|
||||
const val REJECTION_DATA = "REJECTION_DATA"
|
||||
const val IS_SOFT_REJECT = "softReject"
|
||||
const val SYSTEM_UNDER_MAINTENANCE = "SYSTEM_UNDER_MAINTENANCE"
|
||||
|
||||
@@ -4,7 +4,9 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.navi.common.model.CtaData
|
||||
import com.naviapp.R
|
||||
import com.naviapp.chat.NaviChatUtil
|
||||
import com.naviapp.common.fragment.BaseFragment
|
||||
import com.naviapp.common.navigator.NaviDeepLinkNavigator
|
||||
import com.naviapp.dashboard.listeners.FragmentListener
|
||||
@@ -16,8 +18,7 @@ import com.naviapp.errors.fragments.ActionErrorFragment.Companion.DOCUMENT_ERROR
|
||||
import com.naviapp.errors.fragments.ActionErrorFragment.Companion.PROFILE_ERROR_ICON
|
||||
import com.naviapp.errors.fragments.ActionErrorFragment.Companion.USER_ERROR_ICON
|
||||
import com.naviapp.errors.utils.getRejectionScreenData
|
||||
import com.navi.common.model.CtaData
|
||||
import com.naviapp.chat.NaviChatUtil
|
||||
import com.naviapp.models.response.ChatNudge
|
||||
import com.naviapp.models.response.CreditAnalysisData
|
||||
import com.naviapp.models.response.ErrorContent
|
||||
import com.naviapp.network.models.GenericErrorResponse
|
||||
@@ -64,9 +65,10 @@ class OfferRejectedFragment : BaseFragment(), FragmentListener {
|
||||
it, this, R.color.white
|
||||
)
|
||||
}
|
||||
if (NaviChatUtil.shouldShowFreshChat()) {
|
||||
val chatNudge = arguments?.getParcelable<ChatNudge>(ErrorActivity.CHAT_NUDGE_DATA)
|
||||
chatNudge?.let {
|
||||
binding.chatView.setProperties(
|
||||
resources.getString(R.string.chat_help),
|
||||
it.text ?: resources.getString(R.string.chat_help),
|
||||
iconResId = R.drawable.ic_chat_dots,
|
||||
styleResId = R.style.InstructionsFontStyle
|
||||
)
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.naviapp.common.fragment.BaseFragment
|
||||
import com.naviapp.common.navigator.NaviDeepLinkNavigator
|
||||
import com.naviapp.dashboard.listeners.FragmentListener
|
||||
import com.naviapp.databinding.ProfileRejectedFragmentBinding
|
||||
import com.naviapp.errors.activities.ErrorActivity.Companion.CHAT_NUDGE_DATA
|
||||
import com.naviapp.errors.activities.ErrorActivity.Companion.CREDIT_ANALYSIS_DATA
|
||||
import com.naviapp.errors.activities.ErrorActivity.Companion.ERROR_DATA
|
||||
import com.naviapp.errors.activities.ErrorActivity.Companion.IS_SOFT_REJECT
|
||||
@@ -20,6 +21,7 @@ import com.naviapp.errors.fragments.ActionErrorFragment.Companion.DOCUMENT_ERROR
|
||||
import com.naviapp.errors.fragments.ActionErrorFragment.Companion.PROFILE_ERROR_ICON
|
||||
import com.naviapp.errors.fragments.ActionErrorFragment.Companion.USER_ERROR_ICON
|
||||
import com.naviapp.errors.utils.getProfileRejectionScreenData
|
||||
import com.naviapp.models.response.ChatNudge
|
||||
import com.naviapp.models.response.CreditAnalysisData
|
||||
import com.naviapp.models.response.ErrorContent
|
||||
import com.naviapp.network.models.GenericErrorResponse
|
||||
@@ -66,9 +68,10 @@ class ProfileRejectedFragment : BaseFragment(), FragmentListener {
|
||||
it, this, R.color.white
|
||||
)
|
||||
}
|
||||
if (NaviChatUtil.shouldShowFreshChat()) {
|
||||
val chatNudge = arguments?.getParcelable<ChatNudge>(CHAT_NUDGE_DATA)
|
||||
chatNudge?.let {
|
||||
binding.chatView.setProperties(
|
||||
resources.getString(R.string.chat_help),
|
||||
it.text ?: resources.getString(R.string.chat_help),
|
||||
iconResId = R.drawable.ic_chat_dots,
|
||||
styleResId = R.style.InstructionsFontStyle
|
||||
)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.naviapp.models
|
||||
|
||||
enum class CustomerSupportOptionEnum {
|
||||
FAQ,
|
||||
EMAIL,
|
||||
CALL,
|
||||
CHAT
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.naviapp.models.response
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.common.model.CtaData
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class CustomerSupportOptionsResponse(
|
||||
@SerializedName("title")
|
||||
val title: String? = null,
|
||||
@SerializedName("items")
|
||||
val listOfOptions: List<CustomerSupportOption>? = null
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class CustomerSupportOption(
|
||||
@SerializedName("type")
|
||||
val type: String? = null,
|
||||
@SerializedName("title")
|
||||
val title: String? = null,
|
||||
@SerializedName("subTitle")
|
||||
val subTitle: String? = null,
|
||||
@SerializedName("imageDetail")
|
||||
val imageDetail: ImageDetail? = null,
|
||||
@SerializedName("cta")
|
||||
val cta: CtaData? = null
|
||||
) : Parcelable
|
||||
@@ -11,8 +11,8 @@ data class RejectionDetailsResponse(
|
||||
@SerializedName("rejectionCode") val rejectionCode: String?,
|
||||
@SerializedName("humanReadableContent") val humanReadableContent: ErrorContent? = null,
|
||||
@SerializedName("creditScoreData") val creditScoreData: CreditAnalysisData? = null,
|
||||
@SerializedName("ratingEnabled") val ratingEnabled: Boolean? = null
|
||||
|
||||
@SerializedName("ratingEnabled") val ratingEnabled: Boolean? = null,
|
||||
@SerializedName("chatNudge") val chatNudge: ChatNudge? = null
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
@@ -26,4 +26,9 @@ data class ErrorContent(
|
||||
@SerializedName("iconCode") val iconCode: String?,
|
||||
@SerializedName("optionIconCode") val optionIconCode: String?,
|
||||
@SerializedName("numberOfDays") val numberOfDays: String?
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class ChatNudge(
|
||||
@SerializedName("text") val text: String? = null
|
||||
) : Parcelable
|
||||
@@ -758,4 +758,9 @@ interface RetrofitService {
|
||||
@Query("page") page: String
|
||||
): Response<GenericResponse<UxCamMetaConfig>>
|
||||
|
||||
@GET("/fetch-customer-support-options")
|
||||
suspend fun fetchCustomerSupportOptions(
|
||||
@Header("screenName") screenName: String
|
||||
): Response<GenericResponse<CustomerSupportOptionsResponse>>
|
||||
|
||||
}
|
||||
|
||||
@@ -2,20 +2,24 @@ package com.naviapp.personalloan.getloan.common.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewStub
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.navi.common.utils.CommonUtils
|
||||
import com.naviapp.R
|
||||
import com.naviapp.analytics.utils.NaviAnalytics
|
||||
import com.naviapp.chat.NaviChatUtil
|
||||
import com.naviapp.common.customview.BaseBottomSheet
|
||||
import com.naviapp.common.navigator.ScreenNavigator
|
||||
import com.naviapp.common.navigator.ScreenNavigator.Companion.FAQS_SCREEN
|
||||
import com.naviapp.dashboard.viewmodels.DashboardSharedVM
|
||||
import com.naviapp.databinding.CustomerSupportFragmentBinding
|
||||
import com.naviapp.models.CustomerSupportOptionEnum
|
||||
import com.naviapp.personalloan.getloan.activities.FaqsActivity.Companion.FAQS_DATA
|
||||
import com.naviapp.personalloan.getloan.utils.*
|
||||
import com.naviapp.utils.observeNonNull
|
||||
import com.naviapp.utils.setVisibilityState
|
||||
|
||||
class CustomerSupportFragment : BaseBottomSheet(), View.OnClickListener {
|
||||
private lateinit var binding: CustomerSupportFragmentBinding
|
||||
@@ -25,13 +29,19 @@ class CustomerSupportFragment : BaseBottomSheet(), View.OnClickListener {
|
||||
override fun setContainerView(viewStub: ViewStub) {
|
||||
viewStub.layoutResource = R.layout.customer_support_fragment
|
||||
binding = DataBindingUtil.getBinding(viewStub.inflate())!!
|
||||
initUI()
|
||||
val screenName = arguments?.getString(CUST_SCREEN_NAME)
|
||||
if (shouldFetchCustomerSupportOptions(screenName)) {
|
||||
screenName?.let { fetchCustomerSupportOptions(it) }
|
||||
} else {
|
||||
initUI()
|
||||
}
|
||||
initListeners()
|
||||
}
|
||||
|
||||
private fun initListeners() {
|
||||
binding.sendEmailIbv.setOnClickListener(this)
|
||||
binding.faqsIbv.setOnClickListener(this)
|
||||
binding.itcvChat.setOnClickListener(this)
|
||||
viewModel.userProfile.observeNonNull(this) {
|
||||
hideLoader()
|
||||
ScreenNavigator.instance.startActivity(
|
||||
@@ -40,13 +50,50 @@ class CustomerSupportFragment : BaseBottomSheet(), View.OnClickListener {
|
||||
isRootActivity = false
|
||||
)
|
||||
}
|
||||
viewModel.customerSupportOptionsResponse.observeNonNull(this) { customerSupportOptionResponse ->
|
||||
hideLoader()
|
||||
customerSupportOptionResponse.listOfOptions?.let { listOfOptions ->
|
||||
for (customerSupportOption in listOfOptions) {
|
||||
when (customerSupportOption.type) {
|
||||
CustomerSupportOptionEnum.FAQ.toString() -> {
|
||||
binding.faqsIbv.setVisibilityState(VISIBLE)
|
||||
binding.faqsIbv.setProperties(
|
||||
title = customerSupportOption.title,
|
||||
subtitle = customerSupportOption.subTitle,
|
||||
imageDetail = customerSupportOption.imageDetail
|
||||
)
|
||||
}
|
||||
|
||||
CustomerSupportOptionEnum.CHAT.toString() -> {
|
||||
binding.itcvChat.setVisibilityState(VISIBLE)
|
||||
binding.itcvChat.setProperties(
|
||||
title = customerSupportOption.title,
|
||||
subtitle = customerSupportOption.subTitle,
|
||||
imageDetail = customerSupportOption.imageDetail
|
||||
)
|
||||
}
|
||||
|
||||
CustomerSupportOptionEnum.EMAIL.toString() -> {
|
||||
binding.sendEmailIbv.setVisibilityState(VISIBLE)
|
||||
binding.sendEmailIbv.setProperties(
|
||||
title = customerSupportOption.title,
|
||||
subtitle = customerSupportOption.subTitle,
|
||||
imageDetail = customerSupportOption.imageDetail
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initUI() {
|
||||
binding.faqsIbv.setVisibilityState(VISIBLE)
|
||||
binding.faqsIbv.setProperties(
|
||||
R.drawable.ic_help_svg,
|
||||
getString(R.string.faqs_text)
|
||||
)
|
||||
binding.sendEmailIbv.setVisibilityState(VISIBLE)
|
||||
binding.sendEmailIbv.setProperties(
|
||||
R.drawable.ic_send_email_icon_svg,
|
||||
getString(R.string.send_email)
|
||||
@@ -63,6 +110,9 @@ class CustomerSupportFragment : BaseBottomSheet(), View.OnClickListener {
|
||||
R.id.faqs_ibv -> {
|
||||
navigateToFaqs()
|
||||
}
|
||||
R.id.itcvChat -> {
|
||||
NaviChatUtil.showConversations()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +138,11 @@ class CustomerSupportFragment : BaseBottomSheet(), View.OnClickListener {
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchCustomerSupportOptions(screenName: String) {
|
||||
showLoader()
|
||||
viewModel.fetchCustomerSupportOptions(screenName)
|
||||
}
|
||||
|
||||
override val screenName: String
|
||||
get() = "help_${arguments?.getString(CUST_SCREEN_NAME).orEmpty()}_screen"
|
||||
|
||||
@@ -104,4 +159,15 @@ class CustomerSupportFragment : BaseBottomSheet(), View.OnClickListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldFetchCustomerSupportOptions(screenName: String?): Boolean {
|
||||
return when (screenName) {
|
||||
NaviAnalytics.LOAN_DETAILS,
|
||||
NaviAnalytics.KYC,
|
||||
NaviAnalytics.BANK_DETAILS,
|
||||
NaviAnalytics.BANK_DETAIL_AUTO_DEBIT,
|
||||
NaviAnalytics.LOAN_AGREEMENT -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,14 +22,24 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/layout_dp_16"
|
||||
android:layout_marginBottom="@dimen/layout_dp_16" />
|
||||
android:layout_marginBottom="@dimen/layout_dp_16"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.naviapp.common.customview.IconTextCustomView
|
||||
android:id="@+id/itcvChat"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/layout_dp_16"
|
||||
android:layout_marginBottom="@dimen/layout_dp_16"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.naviapp.common.customview.IconTextCustomView
|
||||
android:id="@+id/send_email_ibv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/layout_dp_16"
|
||||
android:layout_marginBottom="@dimen/layout_dp_16" />
|
||||
android:layout_marginBottom="@dimen/layout_dp_16"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
@@ -21,7 +21,18 @@
|
||||
style="@style/AgreementTwoFontStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/_4dp"
|
||||
android:layout_toEndOf="@id/icon_iv"
|
||||
tools:text="@string/send_email" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/tvSubTitle"
|
||||
android:layout_marginTop="@dimen/_1dp"
|
||||
style="@style/TextDescExtraSmallRegularStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/title_tv"
|
||||
android:visibility="gone"
|
||||
tools:text="(Mon-Fri)" />
|
||||
</RelativeLayout>
|
||||
</layout>
|
||||
Reference in New Issue
Block a user