diff --git a/navi-hl/build.gradle b/navi-hl/build.gradle index 3000463816..1741cc6c82 100644 --- a/navi-hl/build.gradle +++ b/navi-hl/build.gradle @@ -27,9 +27,13 @@ android { } } buildFeatures { + compose true dataBinding true viewBinding true } + composeOptions { + kotlinCompilerExtensionVersion compose_version + } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 diff --git a/navi-hl/src/main/java/com/navi/hl/landingpage/bottomsheet/TitleWithStartAndEndIconBottomSheet.kt b/navi-hl/src/main/java/com/navi/hl/landingpage/bottomsheet/TitleWithStartAndEndIconBottomSheet.kt new file mode 100644 index 0000000000..aff03ddb35 --- /dev/null +++ b/navi-hl/src/main/java/com/navi/hl/landingpage/bottomsheet/TitleWithStartAndEndIconBottomSheet.kt @@ -0,0 +1,161 @@ +/* + * + * * Copyright © 2023 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.hl.landingpage.bottomsheet + +import android.os.Bundle +import android.view.ViewStub +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Divider +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.databinding.DataBindingUtil +import coil.compose.AsyncImage +import com.navi.base.model.CtaData +import com.navi.base.utils.EMPTY +import com.navi.common.ui.fragment.BaseBottomSheet +import com.navi.design.font.FontWeightEnum +import com.navi.design.theme.getFontWeight +import com.navi.design.theme.ttComposeFontFamily +import com.navi.hl.R +import com.navi.hl.common.listeners.HLCommonBottomSheetListener +import com.navi.hl.databinding.BottomSheetHlTitleWithStartAndEndIconBinding +import com.navi.hl.landingpage.model.BottomSheetContent +import com.navi.hl.utils.NaviHLAnalytics +import com.navi.naviwidgets.extensions.NaviText +import com.navi.naviwidgets.models.response.TitleWithStartAndEndIconBottomSheetData + +class TitleWithStartAndEndIconBottomSheet : BaseBottomSheet() { + + private lateinit var binding: BottomSheetHlTitleWithStartAndEndIconBinding + private var listItems: List = emptyList() + private var listener: HLCommonBottomSheetListener? = null + + override fun setContainerView(viewStub: ViewStub) { + viewStub.layoutResource = R.layout.bottom_sheet_hl_title_with_start_and_end_icon + binding = DataBindingUtil.getBinding(viewStub.inflate())!! + initUI() + } + + private fun initUI() { + arguments?.getParcelable(BOTTOM_SHEET_DATA)?.let { bottomSheetContent -> + bottomSheetContent.content?.let { + listItems = it + } + } + binding.bottomSheetComposeView.setContent { + BottomSheetContent() + } + } + + @Composable + fun BottomSheetContent() { + LazyColumn( + modifier = Modifier + .wrapContentHeight() + .padding(16.dp, 0.dp, 16.dp, 8.dp) + ) { + items(listItems) { item -> + if (item.showDivider == true) + HorizontalDividerView() + else + TitleWithStartAndEndIconView(item, ::onItemClick) + } + } + } + + @Composable + fun TitleWithStartAndEndIconView( + data: TitleWithStartAndEndIconBottomSheetData, + onItemClick: (CtaData) -> Unit + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(0.dp, 16.dp, 0.dp, 24.dp) + .clickable { onItemClick(data.cta ?: CtaData()) }, + verticalAlignment = Alignment.CenterVertically + ) { + AsyncImage( + model = data.startIcon?.url, + contentDescription = EMPTY, + modifier = Modifier + .size( + width = (data.startIcon?.iconWidth ?: 24).dp, + height = (data.startIcon?.iconHeight ?: 24).dp + ), + fallback = painterResource(id = R.drawable.ic_outlined_home_icon), + placeholder = painterResource(id = R.drawable.ic_outlined_home_icon), + error = painterResource(id = R.drawable.ic_outlined_home_icon), + ) + NaviText(textFieldData = data.title, Modifier.padding(start = 12.dp)) + Spacer(modifier = Modifier.weight(1f)) + AsyncImage( + model = data.endIcon?.url, + contentDescription = EMPTY, + modifier = Modifier + .size( + width = (data.endIcon?.iconWidth ?: 24).dp, + height = (data.endIcon?.iconHeight ?: 24).dp + ), + fallback = painterResource(id = R.drawable.ic_outlined_home_icon), + placeholder = painterResource(id = R.drawable.ic_outlined_home_icon), + error = painterResource(id = R.drawable.ic_outlined_home_icon), + ) + } + } + + @Composable + private fun HorizontalDividerView() { + Divider( + color = Color(0xFFE3E5E5), + thickness = 1.dp, + modifier = Modifier + .fillMaxWidth() + .padding(0.dp, 0.dp, 0.dp, 8.dp) + ) + } + + private fun onItemClick(ctaData: CtaData) { + listener?.onBsCtaClick(ctaData, TAG) + } + + fun setBottomSheetListener(listener: HLCommonBottomSheetListener) { + this.listener = listener + } + + override val screenName: String + get() = NaviHLAnalytics.HL_TITLE_WITH_START_AND_END_ICON_BOTTOM_SHEET + + companion object { + private const val BOTTOM_SHEET_DATA = "BOTTOM_SHEET_DATA" + const val TAG = "HL_TITLE_WITH_START_AND_END_ICON_BOTTOM_SHEET" + + fun getInstance(bottomSheetData: BottomSheetContent) = + TitleWithStartAndEndIconBottomSheet().apply { + val bundle = Bundle().apply { + putParcelable(BOTTOM_SHEET_DATA, bottomSheetData) + } + arguments = bundle + } + } +} diff --git a/navi-hl/src/main/java/com/navi/hl/landingpage/fragment/HomeLoanLandingPageFragment.kt b/navi-hl/src/main/java/com/navi/hl/landingpage/fragment/HomeLoanLandingPageFragment.kt index ad2241adbc..2dd039b12e 100644 --- a/navi-hl/src/main/java/com/navi/hl/landingpage/fragment/HomeLoanLandingPageFragment.kt +++ b/navi-hl/src/main/java/com/navi/hl/landingpage/fragment/HomeLoanLandingPageFragment.kt @@ -24,6 +24,7 @@ import com.navi.base.utils.BaseUtils import com.navi.common.utils.observeNullable import com.navi.hl.common.customview.HLTopNavigationHeaderInterface import com.navi.hl.common.listeners.BackListener +import com.navi.hl.common.listeners.HLCommonBottomSheetListener import com.navi.hl.common.listeners.HLFooterListener import com.navi.hl.common.ui.activity.Navigator import com.navi.hl.common.ui.fragment.HomeLoanBaseFragment @@ -33,13 +34,15 @@ import com.navi.hl.utils.NaviHLAnalytics import com.navi.hl.utils.slideViewFromBottom import com.navi.naviwidgets.adapters.NaviAdapter import com.navi.hl.landingpage.bottomsheet.IconTitleDescriptionInfoCtaBottomSheet +import com.navi.hl.landingpage.bottomsheet.TitleWithStartAndEndIconBottomSheet import com.navi.naviwidgets.callbacks.WidgetCallback import com.navi.naviwidgets.models.NaviWidget import com.navi.naviwidgets.viewholder.ViewHolderFactoryImpl import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint -class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFooterListener, WidgetCallback { +class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFooterListener, + WidgetCallback, HLCommonBottomSheetListener { private lateinit var binding: FragmentHlLandingPageBinding private val hlLandingPageEventTracker = @@ -147,8 +150,9 @@ class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFoot override fun onClick(naviClickAction: NaviClickAction, widgetId: String?) { when (naviClickAction) { is CtaData -> { - navigateTo(naviClickAction, false) + openBottomSheet(naviClickAction) } + is NaviBenefitsItemClick -> { hlLandingPageEventTracker.onBenefitsCardClicked(naviClickAction.ctaData) naviClickAction.ctaData?.url?.let { @@ -168,6 +172,7 @@ class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFoot } } } + is NaviWidgetClickWithCtaData -> { hlLandingPageEventTracker.onVideoCardClicked(naviClickAction.ctaData) navigateTo(naviClickAction.ctaData, false) @@ -175,6 +180,18 @@ class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFoot } } + private fun openBottomSheet(ctaData: CtaData?) { + viewModel.landingPageResponse.value?.content?.bottomSheetData?.let { + val bottomSheet = TitleWithStartAndEndIconBottomSheet.getInstance(it) + bottomSheet.setBottomSheetListener(this) + if (!isBottomSheetVisible(TitleWithStartAndEndIconBottomSheet.TAG)) { + safelyShowBottomSheet(bottomSheet, TitleWithStartAndEndIconBottomSheet.TAG) + } + } ?: run { + navigateTo(ctaData, false) + } + } + private fun navigateTo(cta: CtaData?, finish: Boolean = true) { val navigator = activity if (navigator is Navigator) { @@ -183,7 +200,11 @@ class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFoot } override fun onFooterCtaClick(ctaData: CtaData?) { - navigateTo(ctaData, finish = false) + openBottomSheet(ctaData) + } + + override fun onBsCtaClick(ctaData: CtaData?, bottomSheetType: String) { + navigateTo(ctaData, false) } override val screenName: String diff --git a/navi-hl/src/main/java/com/navi/hl/landingpage/model/HomeLoanLandingPageResponse.kt b/navi-hl/src/main/java/com/navi/hl/landingpage/model/HomeLoanLandingPageResponse.kt index b2bad27a25..55a2ca3148 100644 --- a/navi-hl/src/main/java/com/navi/hl/landingpage/model/HomeLoanLandingPageResponse.kt +++ b/navi-hl/src/main/java/com/navi/hl/landingpage/model/HomeLoanLandingPageResponse.kt @@ -7,11 +7,14 @@ package com.navi.hl.landingpage.model +import android.os.Parcelable import com.google.gson.annotations.SerializedName import com.navi.hl.common.models.HLFooter import com.navi.hl.common.models.HLHeader import com.navi.naviwidgets.models.NaviWidget import com.navi.naviwidgets.models.response.TextFieldData +import com.navi.naviwidgets.models.response.TitleWithStartAndEndIconBottomSheetData +import kotlinx.parcelize.Parcelize data class HLLandingPageResponse( @SerializedName("header") var header: HLHeader? = null, @@ -21,5 +24,11 @@ data class HLLandingPageResponse( data class HLLandingPageContent( @SerializedName("widgets") val widgets: List? = null, - @SerializedName("infoProviderText") val infoProviderText: TextFieldData? = null + @SerializedName("infoProviderText") val infoProviderText: TextFieldData? = null, + @SerializedName("bottomSheetData") val bottomSheetData: BottomSheetContent? = null ) + +@Parcelize +data class BottomSheetContent( + @SerializedName("content") val content: List? = null +) : Parcelable diff --git a/navi-hl/src/main/java/com/navi/hl/landingpage/repository/HomeLoanLandingPageRepository.kt b/navi-hl/src/main/java/com/navi/hl/landingpage/repository/HomeLoanLandingPageRepository.kt index 9f87699ae2..4cf40327c8 100644 --- a/navi-hl/src/main/java/com/navi/hl/landingpage/repository/HomeLoanLandingPageRepository.kt +++ b/navi-hl/src/main/java/com/navi/hl/landingpage/repository/HomeLoanLandingPageRepository.kt @@ -18,6 +18,7 @@ class HomeLoanLandingPageRepository constructor(private val retrofitService: RetrofitService) : ResponseCallback() { suspend fun fetchLandingPageResponse(): RepoResult { - return apiResponseCallback(retrofitService.fetchHomeLoanLandingPageResponse()) + return apiResponseCallback(retrofitService.fetchHomeLoanLandingPageResponse()) } + } diff --git a/navi-hl/src/main/java/com/navi/hl/utils/NaviHLAnalytics.kt b/navi-hl/src/main/java/com/navi/hl/utils/NaviHLAnalytics.kt index ea7740aa54..e0c1e39fc6 100644 --- a/navi-hl/src/main/java/com/navi/hl/utils/NaviHLAnalytics.kt +++ b/navi-hl/src/main/java/com/navi/hl/utils/NaviHLAnalytics.kt @@ -434,11 +434,14 @@ class NaviHLAnalytics private constructor() { const val HL_LANDING_PAGE = "HL_Landing_Page" const val HL_HELP_BOTTOM_SHEET = "New_HL_Help_Bottom_Sheet" const val HL_LOAN_DETAILS_BOTTOM_SHEET = "New_HL_Loan_Details_Bottom_Sheet" - const val HL_REVIEW_PROPERTY_DETAILS_BOTTOM_SHEET = "New_HL_Review_Property_Details_Bottom_Sheet" + const val HL_REVIEW_PROPERTY_DETAILS_BOTTOM_SHEET = + "New_HL_Review_Property_Details_Bottom_Sheet" const val HL_ACC_AGGREGATOR_BOTTOM_SHEET = "New_HL_Account_Aggregator_Bottom_Sheet" const val HL_EMI_PLAN_TAB_SCREEN = "New_HL_Emi_Plan_Tab_Screen" const val HL_EMI_MONTH_SLIDER_BOTTOM_SHEET = "New_HL_Emi_Month_Slider_Bottom_Sheet" const val HL_DOWPAYMENT_RANGE_BOTTOM_SHEET = "New_HL_Downpayment_Range_Bottom_Sheet" + const val HL_TITLE_WITH_START_AND_END_ICON_BOTTOM_SHEET = + "New_HL_Title_With_Start_And_End_Icon_Bottom_Sheet" const val POST_FIX_LANDED = "_Landed" const val POST_FIX_CLICKED = "_Clicked" diff --git a/navi-hl/src/main/res/layout/bottom_sheet_hl_title_with_start_and_end_icon.xml b/navi-hl/src/main/res/layout/bottom_sheet_hl_title_with_start_and_end_icon.xml new file mode 100644 index 0000000000..f63c629cf9 --- /dev/null +++ b/navi-hl/src/main/res/layout/bottom_sheet_hl_title_with_start_and_end_icon.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/navi-widgets/src/main/java/com/navi/naviwidgets/models/response/GenericBottomSheetData.kt b/navi-widgets/src/main/java/com/navi/naviwidgets/models/response/GenericBottomSheetData.kt index 80fa2f255b..3a5c512d37 100644 --- a/navi-widgets/src/main/java/com/navi/naviwidgets/models/response/GenericBottomSheetData.kt +++ b/navi-widgets/src/main/java/com/navi/naviwidgets/models/response/GenericBottomSheetData.kt @@ -71,3 +71,12 @@ data class GenericWidgetTimerConfig( @SerializedName("insertAt") val insertAt: Int? = null, @SerializedName("baseString") val baseString: String? = null ): Parcelable + +@Parcelize +data class TitleWithStartAndEndIconBottomSheetData( + @SerializedName("startIcon") val startIcon: ImageFieldData? = null, + @SerializedName("title") val title: TextFieldData? = null, + @SerializedName("endIcon") val endIcon: ImageFieldData? = null, + @SerializedName("showDivider") val showDivider: Boolean? = null, + @SerializedName("cta") val cta: CtaData? = null +) : Parcelable diff --git a/navi-widgets/src/main/java/com/navi/naviwidgets/widgets/ProductIntroWithButtonWidgetLayout.kt b/navi-widgets/src/main/java/com/navi/naviwidgets/widgets/ProductIntroWithButtonWidgetLayout.kt index 0bd86a721e..2feb3f898f 100644 --- a/navi-widgets/src/main/java/com/navi/naviwidgets/widgets/ProductIntroWithButtonWidgetLayout.kt +++ b/navi-widgets/src/main/java/com/navi/naviwidgets/widgets/ProductIntroWithButtonWidgetLayout.kt @@ -1,6 +1,6 @@ /* * - * * Copyright © 2022 by Navi Technologies Limited + * * Copyright © 2022-2023 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ @@ -54,9 +54,9 @@ class ProductIntroWithButtonWidgetLayout @JvmOverloads constructor( widgetData.productIntroWithButtonWidgetData?.let { productWidgetData -> binding.tvAction.apply { setOnClickListener { - widgetCallback.onClick(NaviWidgetClickWithCtaData( - ctaData = productWidgetData.cta - )) + productWidgetData.cta?.let { + widgetCallback.onClick(it) + } } } } @@ -99,4 +99,4 @@ class ProductIntroWithButtonWidgetLayout @JvmOverloads constructor( private const val DEFAULT_SLIDE_PERIOD_TIME = 2000L } -} \ No newline at end of file +}