From 6ae72f04f413210f4728de591ad6602d8735df18 Mon Sep 17 00:00:00 2001 From: Prajjaval Verma Date: Thu, 25 Apr 2024 22:19:53 +0530 Subject: [PATCH] TP-63571 | Relationship Manager Widget (#10578) --- App/common/constants/WidgetNameConstants.ts | 4 +- .../widgetData/CardWithIconWidgetData.ts | 12 + .../widgets/widgetData/SpacerWidgetData.ts | 5 + App/common/widgets/widgetResolver.tsx | 62 ++-- .../analytics/InsuranceAnalyticsConstants.kt | 3 + .../HeaderWithIconContentFooterBottomSheet.kt | 267 ++++++++++++++++++ .../common/bottom_sheet/UITronBottomSheet.kt | 149 ++++++++++ .../common/models/GiErrorMetaData.kt | 1 + .../HeaderItemsFooterBottomSheetData.kt | 1 + .../common/models/UITronBottomSheetData.kt | 12 + .../insurance/common/util/DeserializerUtil.kt | 18 ++ .../common/util/NavigationHandler.kt | 2 + .../common/viewmodel/UITronBottomSheetVM.kt | 51 ++++ .../NaviInsuranceDeeplinkNavigator.kt | 14 + .../CardWithIconWidget.tsx | 61 ++++ .../CardWithIconWidgetStyle.ts | 22 ++ .../widgets/spacer-widget/SpacerWidget.tsx | 24 ++ 17 files changed, 686 insertions(+), 22 deletions(-) create mode 100644 App/common/interface/widgets/widgetData/CardWithIconWidgetData.ts create mode 100644 App/common/interface/widgets/widgetData/SpacerWidgetData.ts create mode 100644 android/navi-insurance/src/main/java/com/navi/insurance/common/bottom_sheet/HeaderWithIconContentFooterBottomSheet.kt create mode 100644 android/navi-insurance/src/main/java/com/navi/insurance/common/bottom_sheet/UITronBottomSheet.kt create mode 100644 android/navi-insurance/src/main/java/com/navi/insurance/common/models/UITronBottomSheetData.kt create mode 100644 android/navi-insurance/src/main/java/com/navi/insurance/common/util/DeserializerUtil.kt create mode 100644 android/navi-insurance/src/main/java/com/navi/insurance/common/viewmodel/UITronBottomSheetVM.kt create mode 100644 components/widgets/card-with-icon-widget/CardWithIconWidget.tsx create mode 100644 components/widgets/card-with-icon-widget/CardWithIconWidgetStyle.ts create mode 100644 components/widgets/spacer-widget/SpacerWidget.tsx diff --git a/App/common/constants/WidgetNameConstants.ts b/App/common/constants/WidgetNameConstants.ts index 2f63d07111..655a2c57a3 100644 --- a/App/common/constants/WidgetNameConstants.ts +++ b/App/common/constants/WidgetNameConstants.ts @@ -14,4 +14,6 @@ export const SUM_INSURED_WIDGET = "SUM_INSURED_WIDGET"; export const TITLE_SUBTITLE_WITH_ASSET_WIDGET = "TITLE_SUBTITLE_WITH_ASSET_WIDGET"; export const FAB_REQUEST_TO_CALLBACK = "FAB_REQUEST_TO_CALLBACK"; export const TITLE_WITH_COLUMN_WIDGET = "TITLE_WITH_COLUMN_WIDGET"; -export const TITLE_WITH_ASSET_BACKGROUND_WIDGET = "TITLE_WITH_ASSET_BACKGROUND_WIDGET"; \ No newline at end of file +export const TITLE_WITH_ASSET_BACKGROUND_WIDGET = "TITLE_WITH_ASSET_BACKGROUND_WIDGET"; +export const CARD_WITH_ICON_WIDGET = "CARD_WITH_ICON_WIDGET"; +export const SPACER_WIDGET = "SPACER_WIDGET"; diff --git a/App/common/interface/widgets/widgetData/CardWithIconWidgetData.ts b/App/common/interface/widgets/widgetData/CardWithIconWidgetData.ts new file mode 100644 index 0000000000..6eab0971fd --- /dev/null +++ b/App/common/interface/widgets/widgetData/CardWithIconWidgetData.ts @@ -0,0 +1,12 @@ +import { CtaData } from "../.."; +import { GenericWidgetData } from "../Widget"; +import { ButtonData } from "./FooterWithCardWidgetData"; +import { ImageFieldData, TextFieldData, TitleWidgetData } from "./TitleWidgetData"; + +export interface CardWithIconWidgetData extends GenericWidgetData { + title?: TextFieldData; + subtitle?: TextFieldData; + button?: ButtonData + rightIcon?: ImageFieldData; + cta?: CtaData +} diff --git a/App/common/interface/widgets/widgetData/SpacerWidgetData.ts b/App/common/interface/widgets/widgetData/SpacerWidgetData.ts new file mode 100644 index 0000000000..9d7470597c --- /dev/null +++ b/App/common/interface/widgets/widgetData/SpacerWidgetData.ts @@ -0,0 +1,5 @@ +import { GenericWidgetData } from "../Widget"; + +export interface SpacerWidgetData extends GenericWidgetData { + verticalSeparation?: number; +} \ No newline at end of file diff --git a/App/common/widgets/widgetResolver.tsx b/App/common/widgets/widgetResolver.tsx index f515aab0ac..ed42788e08 100644 --- a/App/common/widgets/widgetResolver.tsx +++ b/App/common/widgets/widgetResolver.tsx @@ -11,8 +11,10 @@ import SumInsuredWidget from "../../../components/widgets/sum-insured-carousel-w import TitleSubtitleWithAssetWidget from "../../../components/widgets/title-subtitle-with-asset-widget/TitleSubtitleWithAssetWidget"; import TitleWidget from "../../../components/widgets/title-widget/TitleWidget"; import TitleWithListWidget from "../../../components/widgets/title-with-list-widget/TitleWithListWidget"; +import SpacerWidget from "../../../components/widgets/spacer-widget/SpacerWidget"; import { GenericActionPayload } from "../actions/GenericAction"; import { + CARD_WITH_ICON_WIDGET, COMPARISON_WIDGET, FAB_REQUEST_TO_CALLBACK, FOOTER_WITH_CARD_WIDGET, @@ -20,6 +22,7 @@ import { HEADER_LOTTIE_ANIMATION_WIDGET, HEADER_WITH_ASSETS_WIDGET, SLIDER_WIDGET, + SPACER_WIDGET, SUM_INSURED_WIDGET, TITLE_SUBTITLE_WITH_ASSET_WIDGET, TITLE_WIDGET, @@ -34,6 +37,7 @@ import { SumInsuredWidgetData } from "../interface/widgets/widgetData/SumInsured import { ScreenState } from "../screen/BaseScreen"; import { TitleWithColumnWidget } from "../../../components/widgets/title-with-column-widget/TitleWithColumnWidget"; import { TitleWithAssetBackgroundWidget } from "../../../components/widgets/title-with-asset-background/TitleWithAssetBackground"; +import CardWithIconWidget from "../../../components/widgets/card-with-icon-widget/CardWithIconWidget"; export const GetWidgetView = { getWidget: ( @@ -202,27 +206,43 @@ function resolveWidgetView( handleClick={handleClick} /> ); - case TITLE_WITH_COLUMN_WIDGET: - return ( - - ) - case TITLE_WITH_ASSET_BACKGROUND_WIDGET: - return ( - - ); + case TITLE_WITH_COLUMN_WIDGET: + return ( + + ); + case TITLE_WITH_ASSET_BACKGROUND_WIDGET: + return ( + + ); + case CARD_WITH_ICON_WIDGET: + return ( + + ); + case SPACER_WIDGET: + return ( + + ); default: return ; } diff --git a/android/navi-insurance/src/main/java/com/navi/insurance/analytics/InsuranceAnalyticsConstants.kt b/android/navi-insurance/src/main/java/com/navi/insurance/analytics/InsuranceAnalyticsConstants.kt index 40ca4ce334..25a51904cb 100644 --- a/android/navi-insurance/src/main/java/com/navi/insurance/analytics/InsuranceAnalyticsConstants.kt +++ b/android/navi-insurance/src/main/java/com/navi/insurance/analytics/InsuranceAnalyticsConstants.kt @@ -576,7 +576,10 @@ object InsuranceAnalyticsConstants { const val TITLE_WITH_FOOTER_CARD_BOTTOMSHEET = "TITLE_WITH_FOOTER_CARD_BOTTOMSHEET" const val LOTTIE_WITH_TITLE_BOTTOMSHEET = "LOTTIE_WITH_TITLE_BOTTOMSHEET" const val HEADER_WITH_LIST_ITEMS_AND_FOOTER = "HEADER_WITH_LIST_ITEMS_AND_FOOTER" + const val HEADER_WITH_ICON_CONTENT_FOOTER = "HEADER_WITH_ICON_CONTENT_FOOTER" const val CHECKBOX_WITH_DROPDOWN_BOTTOMSHEET = "CHECKBOX_WITH_DROPDOWN_BOTTOMSHEET" + const val UITRON_BOTTOM_SHEET = "UITRON_BOTTOM_SHEET" + // Endorsement const val ENDORSEMENT_ACTIVITY = "endorsement_activity" diff --git a/android/navi-insurance/src/main/java/com/navi/insurance/common/bottom_sheet/HeaderWithIconContentFooterBottomSheet.kt b/android/navi-insurance/src/main/java/com/navi/insurance/common/bottom_sheet/HeaderWithIconContentFooterBottomSheet.kt new file mode 100644 index 0000000000..bc2e404873 --- /dev/null +++ b/android/navi-insurance/src/main/java/com/navi/insurance/common/bottom_sheet/HeaderWithIconContentFooterBottomSheet.kt @@ -0,0 +1,267 @@ +package com.navi.insurance.common.bottom_sheet + +import android.os.Bundle +import android.view.ViewStub +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Divider +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.databinding.DataBindingUtil +import com.google.gson.reflect.TypeToken +import com.navi.analytics.utils.NaviTrackEvent +import com.navi.base.model.CtaData +import com.navi.base.model.CtaType +import com.navi.base.model.NaviClickAction +import com.navi.base.utils.orFalse +import com.navi.common.constants.VENDOR_NAVI_API +import com.navi.common.model.ModuleName +import com.navi.common.utils.CommonNaviAnalytics +import com.navi.common.utils.getNetworkType +import com.navi.insurance.R +import com.navi.insurance.analytics.InsuranceAnalyticsConstants +import com.navi.insurance.analytics.InsuranceAnalyticsHandler +import com.navi.insurance.common.fragment.BaseBottomSheet +import com.navi.insurance.common.models.BottomSheetHeaderData +import com.navi.insurance.common.models.BottomSheetItemData +import com.navi.insurance.common.models.GiErrorMetaData +import com.navi.insurance.common.models.HeaderItemsFooterBottomSheetData +import com.navi.insurance.databinding.LayoutClaimsStepsBottomSheetBinding +import com.navi.insurance.navigator.NaviInsuranceDeeplinkNavigator +import com.navi.insurance.pre.purchase.journey.FooterButtonState +import com.navi.insurance.pre.purchase.journey.colorCTASecondary +import com.navi.insurance.pre.purchase.journey.composables.reusable.FooterButtonComposable +import com.navi.insurance.util.CONTENT_DATA_JSON_STRING +import com.navi.insurance.util.Constants +import com.navi.naviwidgets.callbacks.WidgetCallback +import com.navi.naviwidgets.extensions.NaviImage +import com.navi.naviwidgets.extensions.NaviTextWidgetized +import com.navi.naviwidgets.extensions.getJsonObject +import com.navi.naviwidgets.extensions.hexToColor +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.MutableStateFlow +import javax.inject.Inject + +@AndroidEntryPoint +class HeaderWithIconContentFooterBottomSheet : BaseBottomSheet(), WidgetCallback { + @Inject + lateinit var analyticsHandler: InsuranceAnalyticsHandler + private lateinit var binding: LayoutClaimsStepsBottomSheetBinding + private val errorTracker = CommonNaviAnalytics.naviAnalytics.GiError() + + override fun setContainerView(viewStub: ViewStub) { + viewStub.layoutResource = R.layout.layout_claims_steps_bottom_sheet + binding = DataBindingUtil.getBinding(viewStub.inflate())!! + initUI() + } + + private fun initUI() { + val dataType = object : TypeToken() {}.type + val bottomSheetData = getJsonObject(dataType, + (arguments?.getString(CONTENT_DATA_JSON_STRING)), + onErrorOccured = { exception -> + trackError(exception) + } + ) + bottomSheetData?.let { data -> + NaviTrackEvent.sendEvent( + data.metaData?.analyticsEventProperties, + screenName + ) + binding.root.setContent { + setPadding(0, 0, 0, 0) + HeaderWithIconContentFooterComposable(data = data, widgetCallback = this) + } + } + } + + override fun onClick(naviClickAction: NaviClickAction, widgetId: String?) { + if (naviClickAction is CtaData) { + naviClickAction.analyticsEventProperties?.let { analyticsEvent -> + analyticsHandler.sendEvent(analyticsEvent, screenName) + } + val bundle = Bundle() + bundle.putParcelable(Constants.PARAMS_EXTRA, naviClickAction) + when (naviClickAction.type) { + + CtaType.DISMISS_BOTTOM_SHEET.name -> { + safelyDismissDialog() + } + + else -> { + NaviInsuranceDeeplinkNavigator.navigate( + activity = activity, + ctaData = naviClickAction, + bundle = bundle, + finish = naviClickAction.finish.orFalse(), + clearTask = naviClickAction.clearTask.orFalse(), + callbackHandler = requestToCallbackHAndler + ) + safelyDismissDialog() + } + } + } + } + + @Composable + fun HeaderWithIconContentFooterComposable( + modifier: Modifier = Modifier, + data: HeaderItemsFooterBottomSheetData? = null, + widgetCallback: WidgetCallback? = null + ) { + Column { + BottomSheetHeaderComposable(modifier = modifier, data?.header) + data?.contentTitle?.let { + NaviTextWidgetized( + textFieldData = it, + modifier = Modifier.padding(top = 24.dp, bottom = 10.dp, start= 16.dp, end = 16.dp) + ) + } + BottomSheetListItemsComposable(data?.items, widgetCallback) + FooterButtonComposable( + data = data?.footerButton, + state = FooterButtonState.ENABLED.name, + widgetCallback = widgetCallback + ) + } + } + + @Composable + fun BottomSheetHeaderComposable( + modifier: Modifier = Modifier, + headerData: BottomSheetHeaderData?, + widgetCallback: WidgetCallback? = null + ) { + Row( + modifier = modifier + .fillMaxWidth() + .wrapContentHeight() + .background( + hexToColor(headerData?.background?.backgroundColor), + RoundedCornerShape(topStart = 4.dp, topEnd = 4.dp) + ) + .padding(start = 20.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column(modifier = Modifier.wrapContentSize()) { + NaviTextWidgetized( + textFieldData = headerData?.title, + modifier = Modifier, + widgetCallback = widgetCallback + ) + NaviTextWidgetized( + textFieldData = headerData?.subTitle, + modifier = Modifier, + widgetCallback = widgetCallback + ) + } + NaviImage( + imageFieldData = headerData?.rightIcon, + modifier = Modifier.height(95.dp), + widgetCallback = widgetCallback + ) + } + } + + @Composable + fun BottomSheetListItemsComposable( + data: List?, + widgetCallback: WidgetCallback? = null + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp) + ) { + data?.forEachIndexed { index, itemData -> + BottomSheetItemComposable(itemData, widgetCallback) + if (index != data.lastIndex) { + Divider( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + .height(1.dp), + color = colorCTASecondary + ) + } + } + } + } + + @Composable + fun BottomSheetItemComposable(itemData: BottomSheetItemData?, widgetCallback: WidgetCallback?) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = { + itemData?.cta?.let { cta -> + widgetCallback?.onClick(cta) + } + }, indication = null, interactionSource = remember { MutableInteractionSource() }) + .padding(vertical = 16.dp, horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + NaviImage( + imageFieldData = itemData?.leftIcon, + modifier = Modifier.size(24.dp) + ) + Column( + modifier = Modifier + .weight(1f) + .padding(horizontal = 20.dp), + horizontalAlignment = Alignment.Start + ) { + NaviTextWidgetized( + textFieldData = itemData?.title, + modifier = Modifier + ) + NaviTextWidgetized( + textFieldData = itemData?.subTitle, + modifier = Modifier.padding(top = 4.dp) + ) + } + NaviImage( + imageFieldData = itemData?.rightIcon, + modifier = Modifier.size(24.dp) + ) + } + } + + + private fun trackError(error: Exception) { + errorTracker.onGlobalError( + error.stackTrace.getOrNull(0).toString(), + screenName, + ModuleName.GI.name, + CommonNaviAnalytics.GLOBAL_GENERIC_ERRORS, + null, + context?.let { getNetworkType(it) }, + GiErrorMetaData.FLOW_PRE_PURCHASE, + GiErrorMetaData.GET_JSON_OBJECT, + VENDOR_NAVI_API + ) + } + + override val screenName = InsuranceAnalyticsConstants.HEADER_WITH_ICON_CONTENT_FOOTER + + companion object { + const val TAG = InsuranceAnalyticsConstants.HEADER_WITH_ICON_CONTENT_FOOTER + } + + +} \ No newline at end of file diff --git a/android/navi-insurance/src/main/java/com/navi/insurance/common/bottom_sheet/UITronBottomSheet.kt b/android/navi-insurance/src/main/java/com/navi/insurance/common/bottom_sheet/UITronBottomSheet.kt new file mode 100644 index 0000000000..428cb86f2c --- /dev/null +++ b/android/navi-insurance/src/main/java/com/navi/insurance/common/bottom_sheet/UITronBottomSheet.kt @@ -0,0 +1,149 @@ +package com.navi.insurance.common.bottom_sheet + +import android.view.ViewStub +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.databinding.DataBindingUtil +import androidx.fragment.app.viewModels +import com.google.gson.reflect.TypeToken +import com.navi.analytics.utils.NaviTrackEvent +import com.navi.base.model.CtaType +import com.navi.base.utils.orFalse +import com.navi.base.utils.orZero +import com.navi.common.constants.VENDOR_NAVI_API +import com.navi.common.model.ModuleName +import com.navi.common.utils.CommonNaviAnalytics +import com.navi.common.utils.getNetworkType +import com.navi.insurance.R +import com.navi.insurance.analytics.InsuranceAnalyticsConstants +import com.navi.insurance.analytics.InsuranceAnalyticsHandler +import com.navi.insurance.common.fragment.BaseBottomSheet +import com.navi.insurance.common.models.GiErrorMetaData +import com.navi.insurance.common.models.UITronBottomSheetData +import com.navi.insurance.common.util.getJsonObject +import com.navi.insurance.common.viewmodel.UITronBottomSheetVM +import com.navi.insurance.databinding.LayoutClaimsStepsBottomSheetBinding +import com.navi.insurance.navigator.NaviInsuranceDeeplinkNavigator +import com.navi.insurance.util.CONTENT_DATA_JSON_STRING +import com.navi.naviwidgets.callbacks.WidgetCallback +import com.navi.uitron.render.UiTronRenderer +import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject + +@AndroidEntryPoint +class UITronBottomSheet : BaseBottomSheet(), WidgetCallback { + @Inject + lateinit var analyticsHandler: InsuranceAnalyticsHandler + private val viewModel by viewModels() + private lateinit var binding: LayoutClaimsStepsBottomSheetBinding + private val errorTracker = CommonNaviAnalytics.naviAnalytics.GiError() + + override fun setContainerView(viewStub: ViewStub) { + viewStub.layoutResource = R.layout.layout_claims_steps_bottom_sheet + binding = DataBindingUtil.getBinding(viewStub.inflate())!! + initUI() + observeCtaData() + } + + private fun initUI() { + val dataType = object : TypeToken() {}.type + val bottomSheetData = getJsonObject(dataType, + (arguments?.getString(CONTENT_DATA_JSON_STRING)), + onErrorOccured = { exception -> + trackError(exception) + }) + bottomSheetData?.let { data -> + NaviTrackEvent.sendEvent( + data.metaData?.analyticsEventProperties, screenName + ) + binding.root.setContent { + setPadding(0, 0, 0, 0) + BottomSheetComposable(data = data) + } + } + } + + private fun observeCtaData() { + viewModel.redirectionCta.observe(viewLifecycleOwner) { ctaData -> + if (ctaData != null) { + NaviTrackEvent.sendEvent(ctaData, screenName) + } + ctaData.let { + when (ctaData?.type) { + CtaType.DISMISS_BOTTOM_SHEET.name -> { + safelyDismissDialog() + } + + else -> { + if (it != null) { + NaviInsuranceDeeplinkNavigator.navigate( + requireActivity(), + it, + finish = it.finish.orFalse(), + clearTask = it.clearTask.orFalse() + ) + } + safelyDismissDialog() + } + } + } + + } + } + + @Composable + fun BottomSheetComposable( + data: UITronBottomSheetData? = null + ) { + val listState = rememberLazyListState() + Column( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + ) { + UiTronRenderer( + data?.header?.data, viewModel + ).Render(composeViews = data?.header?.parentComposeView.orEmpty()) + LazyColumn( + state = listState, modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + ) { + items(data?.content?.size.orZero()) { index -> + val uiTronResponse = data?.content?.getOrNull(index) + UiTronRenderer( + uiTronResponse?.data, viewModel + ).Render(composeViews = uiTronResponse?.parentComposeView.orEmpty()) + } + } + UiTronRenderer( + data?.footer?.data, viewModel + ).Render(composeViews = data?.footer?.parentComposeView.orEmpty()) + } + } + + private fun trackError(error: Exception) { + errorTracker.onGlobalError( + error.stackTrace[0].toString(), + screenName, + ModuleName.GI.name, + CommonNaviAnalytics.GLOBAL_GENERIC_ERRORS, + null, + context?.let { getNetworkType(it) }, + GiErrorMetaData.FLOW_UITRON_BOTTOM_SHEET, + GiErrorMetaData.GET_JSON_OBJECT, + VENDOR_NAVI_API + ) + } + + override val screenName = InsuranceAnalyticsConstants.UITRON_BOTTOM_SHEET + + companion object { + const val TAG = InsuranceAnalyticsConstants.UITRON_BOTTOM_SHEET + } +} diff --git a/android/navi-insurance/src/main/java/com/navi/insurance/common/models/GiErrorMetaData.kt b/android/navi-insurance/src/main/java/com/navi/insurance/common/models/GiErrorMetaData.kt index fad846bfba..971166d323 100644 --- a/android/navi-insurance/src/main/java/com/navi/insurance/common/models/GiErrorMetaData.kt +++ b/android/navi-insurance/src/main/java/com/navi/insurance/common/models/GiErrorMetaData.kt @@ -69,5 +69,6 @@ data class GiErrorMetaData( const val INSURANCE_TAB_FLOW = "insurance_tab" const val TRIAL_INSURANCE_FLOW = "trial_insurance" const val FLOW_STATIC_DIGITAL_CLAIM = "static_digital_claim" + const val FLOW_UITRON_BOTTOM_SHEET = "uitron_bottom_sheet" } } diff --git a/android/navi-insurance/src/main/java/com/navi/insurance/common/models/HeaderItemsFooterBottomSheetData.kt b/android/navi-insurance/src/main/java/com/navi/insurance/common/models/HeaderItemsFooterBottomSheetData.kt index d40697fe42..94e9664f78 100644 --- a/android/navi-insurance/src/main/java/com/navi/insurance/common/models/HeaderItemsFooterBottomSheetData.kt +++ b/android/navi-insurance/src/main/java/com/navi/insurance/common/models/HeaderItemsFooterBottomSheetData.kt @@ -10,6 +10,7 @@ import com.navi.naviwidgets.models.response.TextFieldData data class HeaderItemsFooterBottomSheetData( @SerializedName("header") val header: BottomSheetHeaderData? = null, + @SerializedName("contentTitle") val contentTitle: TextFieldData? = null, @SerializedName("items") val items: List? = null, @SerializedName("footerButton") val footerButton: FooterButtonData? = null, @SerializedName("metaData") val metaData: PageMetaData? = null, diff --git a/android/navi-insurance/src/main/java/com/navi/insurance/common/models/UITronBottomSheetData.kt b/android/navi-insurance/src/main/java/com/navi/insurance/common/models/UITronBottomSheetData.kt new file mode 100644 index 0000000000..55540925f6 --- /dev/null +++ b/android/navi-insurance/src/main/java/com/navi/insurance/common/models/UITronBottomSheetData.kt @@ -0,0 +1,12 @@ +package com.navi.insurance.common.models + +import com.google.gson.annotations.SerializedName +import com.navi.naviwidgets.models.response.PageMetaData +import com.navi.uitron.model.UiTronResponse + +data class UITronBottomSheetData( + @SerializedName("header") val header: UiTronResponse? = null, + @SerializedName("footer") val footer: UiTronResponse? = null, + @SerializedName("content") val content: List? = null, + @SerializedName("metaData") val metaData: PageMetaData? = null, +) \ No newline at end of file diff --git a/android/navi-insurance/src/main/java/com/navi/insurance/common/util/DeserializerUtil.kt b/android/navi-insurance/src/main/java/com/navi/insurance/common/util/DeserializerUtil.kt new file mode 100644 index 0000000000..8a47e2c02f --- /dev/null +++ b/android/navi-insurance/src/main/java/com/navi/insurance/common/util/DeserializerUtil.kt @@ -0,0 +1,18 @@ +package com.navi.insurance.common.util + +import com.google.gson.GsonBuilder +import com.navi.common.utils.registerUiTronDeSerializers +import java.lang.reflect.Type + +fun getJsonObject( + type: Type, jsonString: String?, onErrorOccured: (exception: Exception) -> Unit = {} +): T? { + val gson = GsonBuilder().registerUiTronDeSerializers().create() + var jsonObject: T? = null + try { + jsonObject = gson.fromJson(jsonString, type) + } catch (e: Exception) { + onErrorOccured.invoke(e) + } + return jsonObject +} diff --git a/android/navi-insurance/src/main/java/com/navi/insurance/common/util/NavigationHandler.kt b/android/navi-insurance/src/main/java/com/navi/insurance/common/util/NavigationHandler.kt index a9a2289fc8..b0dca04f45 100644 --- a/android/navi-insurance/src/main/java/com/navi/insurance/common/util/NavigationHandler.kt +++ b/android/navi-insurance/src/main/java/com/navi/insurance/common/util/NavigationHandler.kt @@ -389,8 +389,10 @@ class NavigationHandler @Inject constructor(private val uiControllerUtil: UiCont const val TITLE_WITH_FOOTER_CARD_BOTTOM_SHEET = "title_with_footer_card_bottomsheet" const val LOTTIE_WITH_TITLE_BOTTOM_SHEET = "lottie_with_title_bottomsheet" const val HEADER_WITH_ITEMS_AND_FOOTER_BOTTOM_SHEET = "header_with_items_and_footer_bottomsheet" + const val HEADER_WITH_ICON_CONTENT_FOOTER_BOTTOM_SHEET = "header_with_icon_content_footer_bottomsheet" const val CHECKBOX_WITH_DROPDOWN_BOTTOMSHEET = "checkbox_with_dropdown_bottomsheet" const val TRIAL_INFO_BOTTOM_SHEET = "trial_info_bottom_sheet" const val URL_PAYMENT_STATUS_SCREEN = "payment_status_screen" + const val UITRON_BOTTOM_SHEET = "uitron_bottom_sheet" } } diff --git a/android/navi-insurance/src/main/java/com/navi/insurance/common/viewmodel/UITronBottomSheetVM.kt b/android/navi-insurance/src/main/java/com/navi/insurance/common/viewmodel/UITronBottomSheetVM.kt new file mode 100644 index 0000000000..3f1897d1ef --- /dev/null +++ b/android/navi-insurance/src/main/java/com/navi/insurance/common/viewmodel/UITronBottomSheetVM.kt @@ -0,0 +1,51 @@ +package com.navi.insurance.common.viewmodel + +import androidx.lifecycle.viewModelScope +import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.navi.analytics.utils.NaviTrackEvent +import com.navi.base.model.CtaData +import com.navi.common.uitron.model.action.CtaAction +import com.navi.common.utils.SingleLiveEvent +import com.navi.common.viewmodel.BaseVM +import com.navi.uitron.model.action.AnalyticsAction +import com.navi.uitron.model.data.UiTronAction +import kotlinx.coroutines.launch +import timber.log.Timber + +class UITronBottomSheetVM : BaseVM() { + + init { + viewModelScope.launch { + getActionCallback().collect { + onActionTriggered(it) + } + } + } + + val redirectionCta = SingleLiveEvent() + + private fun onActionTriggered(uiTronAction: UiTronAction?) { + when (uiTronAction) { + is CtaAction -> { + handleCtaAction(ctaAction = uiTronAction) + } + + is AnalyticsAction -> { + NaviTrackEvent.trackEvent( + uiTronAction.eventName ?: "", uiTronAction.eventProperties, uiTronAction.isNeededForAppsflyer, uiTronAction.isNeededForFirebase + ) + } + + else -> { + FirebaseCrashlytics.getInstance() + .log("${uiTronAction?.type} Action not handled now") + } + } + } + + private fun handleCtaAction(ctaAction: CtaAction) { + ctaAction.ctaData?.let { ctaData -> + redirectionCta.postValue(ctaAction.ctaData) + } + } +} \ No newline at end of file diff --git a/android/navi-insurance/src/main/java/com/navi/insurance/navigator/NaviInsuranceDeeplinkNavigator.kt b/android/navi-insurance/src/main/java/com/navi/insurance/navigator/NaviInsuranceDeeplinkNavigator.kt index efe9fb7321..ab867813f2 100644 --- a/android/navi-insurance/src/main/java/com/navi/insurance/navigator/NaviInsuranceDeeplinkNavigator.kt +++ b/android/navi-insurance/src/main/java/com/navi/insurance/navigator/NaviInsuranceDeeplinkNavigator.kt @@ -46,6 +46,7 @@ import com.navi.insurance.common.activity.PopUpActivity import com.navi.insurance.common.bottom_sheet.CheckboxWithDropdownBottomsheet import com.navi.insurance.common.bottom_sheet.ClaimsStepsBottomSheet import com.navi.insurance.common.bottom_sheet.HeaderItemFooterBottomSheet +import com.navi.insurance.common.bottom_sheet.HeaderWithIconContentFooterBottomSheet import com.navi.insurance.common.bottom_sheet.LottieWithTitleBottomSheet import com.navi.insurance.common.bottom_sheet.TIExplainerBottomSheet import com.navi.insurance.common.bottom_sheet.TabularContentBottomSheet @@ -62,6 +63,7 @@ import com.navi.insurance.common.fragment.SelectPolicyItemBottomSheet import com.navi.insurance.common.fragment.TitleIconDescBottomSheet import com.navi.insurance.common.bottom_sheet.TitleWithGridBottomSheet import com.navi.insurance.common.bottom_sheet.TrialInfoBottomSheet +import com.navi.insurance.common.bottom_sheet.UITronBottomSheet import com.navi.insurance.common.helper.ShareUtils import com.navi.insurance.common.models.RedirectToPhoneActionData import com.navi.insurance.common.util.ActionHandler @@ -76,6 +78,7 @@ import com.navi.insurance.common.util.NavigationHandler.Companion.GENERIC_INFO_B import com.navi.insurance.common.util.NavigationHandler.Companion.GI_CLAIMS_BOTTOM_SHEET import com.navi.insurance.common.util.NavigationHandler.Companion.GI_SURVEY_BOTTOMSHEET import com.navi.insurance.common.util.NavigationHandler.Companion.HEADER_LINE_ITEM_BOTTOMSHEET +import com.navi.insurance.common.util.NavigationHandler.Companion.HEADER_WITH_ICON_CONTENT_FOOTER_BOTTOM_SHEET import com.navi.insurance.common.util.NavigationHandler.Companion.HEADER_WITH_ITEMS_AND_FOOTER_BOTTOM_SHEET import com.navi.insurance.common.util.NavigationHandler.Companion.LANDING_PAGE_VERSION import com.navi.insurance.common.util.NavigationHandler.Companion.LOTTIE_WITH_TITLE_BOTTOM_SHEET @@ -88,6 +91,7 @@ import com.navi.insurance.common.util.NavigationHandler.Companion.TITLE_WITH_FOO import com.navi.insurance.common.util.NavigationHandler.Companion.TITLE_WITH_GRID_BOTTOM_SHEET import com.navi.insurance.common.util.NavigationHandler.Companion.TI_EXPLAINER_BOTTOM_SHEET import com.navi.insurance.common.util.NavigationHandler.Companion.TRIAL_INFO_BOTTOM_SHEET +import com.navi.insurance.common.util.NavigationHandler.Companion.UITRON_BOTTOM_SHEET import com.navi.insurance.common.util.NavigationHandler.Companion.URL_EMI_BOTTOMSHEET import com.navi.insurance.common.util.NavigationHandler.Companion.URL_FULL_PAYMENT_BOTTOMSHEET import com.navi.insurance.common.util.NavigationHandler.Companion.URL_OFFER_PREMIUM_BOTTOMSHEET @@ -737,10 +741,20 @@ object NaviInsuranceDeeplinkNavigator { HeaderItemFooterBottomSheet() ) + HEADER_WITH_ICON_CONTENT_FOOTER_BOTTOM_SHEET -> Pair( + HeaderWithIconContentFooterBottomSheet.TAG, + HeaderWithIconContentFooterBottomSheet() + ) + TRIAL_INFO_BOTTOM_SHEET -> Pair( TrialInfoBottomSheet.TAG, TrialInfoBottomSheet() ) + + UITRON_BOTTOM_SHEET -> Pair( + UITronBottomSheet.TAG, + UITronBottomSheet() + ) else -> null } } diff --git a/components/widgets/card-with-icon-widget/CardWithIconWidget.tsx b/components/widgets/card-with-icon-widget/CardWithIconWidget.tsx new file mode 100644 index 0000000000..76c19ae0c4 --- /dev/null +++ b/components/widgets/card-with-icon-widget/CardWithIconWidget.tsx @@ -0,0 +1,61 @@ +import { View, ViewStyle } from "react-native"; +import { CardWithIconWidgetData } from "../../../App/common/interface/widgets/widgetData/CardWithIconWidgetData"; +import { GenericActionPayload } from "../../../App/common/actions/GenericAction"; +import { CtaData } from "../../../App/common/interface"; +import { styles } from "./CardWithIconWidgetStyle"; +import { StyledText } from "../styled-text/StyledText"; +import CtaButton from "../../reusable/cta-button/CtaButton"; +import { StyledImage } from "../../StyledImage"; +import { commonStyles } from "../../../App/Container/Navi-Insurance/Styles"; +import { TouchableOpacity } from "react-native-gesture-handler"; + +const CardWithIconWidget = ({ + widgetData, + handleActions, + handleClick, +}: { + widgetData: CardWithIconWidgetData; + handleActions: ( + value?: any | undefined | null, + screenActionPayload?: GenericActionPayload + ) => void; + handleClick?: (cta: CtaData) => void; +}) => { + const cardClick = () => { + handleClick && widgetData.cta && handleClick(widgetData.cta); + }; + return ( + + + {widgetData.title?.text && } + {widgetData.title?.text && widgetData.subtitle && ( + + )} + {widgetData.subtitle?.text && ( + + )} + {widgetData.button && widgetData.subtitle && ( + + )} + {widgetData.button && ( + + {widgetData.button.title && ( + + )} + + )} + + + {widgetData.rightIcon && ( + + )} + + + ); +}; + +export default CardWithIconWidget; diff --git a/components/widgets/card-with-icon-widget/CardWithIconWidgetStyle.ts b/components/widgets/card-with-icon-widget/CardWithIconWidgetStyle.ts new file mode 100644 index 0000000000..7fa6c1b03b --- /dev/null +++ b/components/widgets/card-with-icon-widget/CardWithIconWidgetStyle.ts @@ -0,0 +1,22 @@ +import { StyleSheet } from "react-native"; + +export const styles = StyleSheet.create({ + background: { + flex: 1, + flexDirection: "row", + justifyContent: "space-between", + alignItems: "flex-end", + backgroundColor: "#F0F6FF", + borderWidth: 1, + borderColor: "#BED7FF80", + borderRadius: 4, + }, + columnContainer: { + flex: 1, + flexDirection: "column", + justifyContent: "center", + alignItems: "flex-start", + paddingVertical: 16, + paddingStart: 16, + }, +}); diff --git a/components/widgets/spacer-widget/SpacerWidget.tsx b/components/widgets/spacer-widget/SpacerWidget.tsx new file mode 100644 index 0000000000..ccc0f7c854 --- /dev/null +++ b/components/widgets/spacer-widget/SpacerWidget.tsx @@ -0,0 +1,24 @@ +import { View } from "react-native"; +import { SpacerWidgetData } from "../../../App/common/interface/widgets/widgetData/SpacerWidgetData"; +import { GenericActionPayload } from "../../../App/common/actions/GenericAction"; +import { CtaData } from "../../../App/common/interface"; +import { ScreenState } from "../../../App/common/screen/BaseScreen"; + +const SpacerWidget = ({ + widgetData, + handleActions, + handleClick, + screenState, +}: { + widgetData: SpacerWidgetData; + handleActions: ( + value?: any | undefined | null, + screenActionPayload?: GenericActionPayload + ) => void; + handleClick?: (ctaData: CtaData) => void; + screenState?: ScreenState | null; +}) => { + return ; +}; + +export default SpacerWidget;