diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/analytics/NaviPayAnalytics.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/analytics/NaviPayAnalytics.kt index 9a4b8a76b4..f14a3c90e4 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/analytics/NaviPayAnalytics.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/analytics/NaviPayAnalytics.kt @@ -5609,6 +5609,32 @@ class NaviPayAnalytics private constructor() { eventValues = mapOf("orderId" to orderId, "productType" to productType) ) } + + fun onNotifyClicked(productType: String) { + NaviTrackEvent.trackEventOnClickStream( + "NaviTStore_OrderDetails_Notify_Clicked", + eventValues = mapOf("productType" to productType) + ) + } + + fun onNotifyPermissionGranted(productType: String) { + NaviTrackEvent.trackEventOnClickStream( + "NaviTStore_OrderDetails_NotifyPermissionGranted", + eventValues = mapOf("productType" to productType) + ) + } + + fun onNotifyPermissionDenied(showRationale: Boolean, productType: String) { + NaviTrackEvent.trackEventOnClickStream( + "NaviTStore_OrderDetails_NotifyPermissionDenied", + eventValues = + mapOf("productType" to productType, "showRationale" to showRationale.toString()) + ) + } + + fun onAppSettingsLaunched() { + NaviTrackEvent.trackEventOnClickStream("NaviTStore_OrderDetails_AppSettingsLaunched") + } } inner class NaviPayLinkUpiNumber { diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/config/NaviPayDefaultConfig.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/config/NaviPayDefaultConfig.kt index ed350db91b..a998927e6b 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/config/NaviPayDefaultConfig.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/config/NaviPayDefaultConfig.kt @@ -23,6 +23,8 @@ data class DefaultConfigContent( @SerializedName("upiIdMaxLength") val upiIdMaxLength: Int = 50, @SerializedName("contactSearchQueryMaxLength") val contactSearchQueryMaxLength: Int = 50, @SerializedName("configMessage") val configMessage: ConfigMessage = ConfigMessage(), + @SerializedName("notifyWidgetTextMessage") + val notifyWidgetTextMessage: NotifyWidgetTextMessage = NotifyWidgetTextMessage(), @SerializedName("amountLimits") val amountLimits: AmountLimits = AmountLimits(), @SerializedName("linkUpiNumberBannerData") val linkUpiNumberBannerData: EngagementWidgetBannerData = @@ -173,3 +175,11 @@ data class EngagementWidgetBannerData( @SerializedName("ctaText") val ctaText: String = "", @SerializedName("ctaUrl") val ctaUrl: String = "" ) + +data class NotifyWidgetTextMessage( + @SerializedName("mainText") val mainText: String = "Turn on notifications to get updates", + @SerializedName("subText") val subText: String = "We are processing your payment", + @SerializedName("successMainText") + val successMainText: String = "You will get updates on payment status", + @SerializedName("successSubText") val successSubText: String = "We are actively working on it", +) diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/model/view/OrderDetailsScreenBottomSheetStateHolder.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/model/view/OrderDetailsScreenBottomSheetStateHolder.kt new file mode 100644 index 0000000000..76473c0ff3 --- /dev/null +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/model/view/OrderDetailsScreenBottomSheetStateHolder.kt @@ -0,0 +1,15 @@ +/* + * + * * Copyright © 2024 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.pay.tstore.details.model.view + +import com.navi.pay.tstore.details.viewmodel.OrderDetailsScreenBottomSheetUIState + +data class OrderDetailsScreenBottomSheetStateHolder( + val bottomSheetStateChange: Boolean, + val bottomSheetUIState: OrderDetailsScreenBottomSheetUIState +) diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/repository/OrderDetailsRepository.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/repository/OrderDetailsRepository.kt index 6f89bb6991..3259888b41 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/repository/OrderDetailsRepository.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/repository/OrderDetailsRepository.kt @@ -8,8 +8,11 @@ package com.navi.pay.tstore.details.repository import com.navi.common.checkmate.model.MetricInfo +import com.navi.common.model.NotificationSettings +import com.navi.common.model.NotificationSettingsRequest import com.navi.common.network.models.RepoResult import com.navi.common.network.retrofit.ResponseCallback +import com.navi.common.network.retrofit.RetrofitService as CommonRetrofitService import com.navi.pay.network.retrofit.NaviPayRetrofitService import com.navi.pay.tstore.details.model.network.OrderStatusResponse import com.navi.pay.tstore.list.db.dao.OrderDao @@ -20,7 +23,8 @@ class OrderDetailsRepository @Inject constructor( private val naviPayRetrofitService: NaviPayRetrofitService, - private val orderDao: OrderDao + private val orderDao: OrderDao, + private val commonRetrofitService: CommonRetrofitService, ) : ResponseCallback() { suspend fun fetchOrderStatus( orderId: String, @@ -39,4 +43,16 @@ constructor( suspend fun getOrderEntity(orderId: String): OrderEntity? { return orderDao.getOrderEntity(orderId) } + + suspend fun updateNotificationsPermission( + notificationSettings: List + ): RepoResult { + return apiResponseCallback( + response = + commonRetrofitService.updateNotificationsPermission( + notificationSettings = + NotificationSettingsRequest(global = notificationSettings) + ) + ) + } } diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsScreen.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsScreen.kt index 56205de0ff..c5da6e7a25 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsScreen.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsScreen.kt @@ -10,40 +10,55 @@ package com.navi.pay.tstore.details.ui.common import android.content.ClipboardManager import android.content.Context import androidx.activity.compose.BackHandler +import androidx.compose.material.ModalBottomSheetValue +import androidx.compose.material.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.core.content.ContextCompat import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.navi.base.utils.orFalse import com.navi.common.utils.copyToClipboard import com.navi.common.utils.navigateUp import com.navi.naviwidgets.utils.EMPTY +import com.navi.naviwidgets.views.composables.NotifyPermissionBottomSheet import com.navi.pay.R import com.navi.pay.analytics.NaviPayAnalytics +import com.navi.pay.common.model.view.NaviPermissionResult +import com.navi.pay.common.model.view.rememberMultiplePermissions import com.navi.pay.common.setup.NaviPayRouter import com.navi.pay.common.ui.LoadingScreen +import com.navi.pay.common.ui.NaviPayModalBottomSheetLayout +import com.navi.pay.common.utils.NaviPayCommonUtils.launchPermissionSettingsScreen import com.navi.pay.common.utils.launchOnboardingSDK import com.navi.pay.destinations.OrderHistoryScreenDestination import com.navi.pay.destinations.UPILiteScreenDestination import com.navi.pay.entry.NaviPayActivity import com.navi.pay.management.common.sendmoney.model.view.PayeeTransactionHistoryEntity import com.navi.pay.onboarding.common.NaviPayOnboardingActionsType +import com.navi.pay.permission.utils.PermissionKeys +import com.navi.pay.permission.utils.PermissionUtils import com.navi.pay.tstore.details.model.view.SharableReceipt import com.navi.pay.tstore.details.ui.bbps.BbpsShareImageUtils +import com.navi.pay.tstore.details.viewmodel.OrderDetailsScreenBottomSheetUIState import com.navi.pay.tstore.details.viewmodel.OrderDetailsScreenUIState import com.navi.pay.tstore.details.viewmodel.OrderDetailsViewModel import com.navi.pay.utils.SAVINGS_ONLY_ENABLED_ACCOUNTS import com.navi.pay.utils.clearBackStackUpToAndNavigate import com.navi.pay.utils.shareReceipt +import com.navi.rr.R.string as RewardsR import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.navigation.DestinationsNavigator import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch +@OptIn(ExperimentalPermissionsApi::class) @Destination @Composable fun OrderDetailsScreen( @@ -120,7 +135,7 @@ fun OrderDetailsScreen( naviPayActivity.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager } val context = LocalContext.current - + val scope = rememberCoroutineScope() val orderHistoryDetailItemProperty by orderDetailsViewModel.orderHistoryDetailItemProperty.collectAsStateWithLifecycle() val naviPayOrderHistoryDetailItemProperty by @@ -151,6 +166,12 @@ fun OrderDetailsScreen( val vpaTpapMapping by orderDetailsViewModel.vpaTpapMapping.collectAsStateWithLifecycle() val selectedCtaToShowLoader by orderDetailsViewModel.selectedCtaToShowLoader.collectAsStateWithLifecycle() + val bottomSheetStateHolder by + orderDetailsViewModel.bottomSheetStateHolder.collectAsStateWithLifecycle() + val isNotifyButtonClicked by + orderDetailsViewModel.isNotifyButtonClicked.collectAsStateWithLifecycle() + val notifyWidgetTextMessage by + orderDetailsViewModel.notifyWidgetTextMessage.collectAsStateWithLifecycle() val onCheckBalanceCtaClicked = { naviPayAnalytics.onCheckBalanceCtaClicked(orderId = orderEntity?.orderReferenceId.orEmpty()) @@ -240,57 +261,167 @@ fun OrderDetailsScreen( ) } + val bottomSheetState = + rememberModalBottomSheetState( + initialValue = ModalBottomSheetValue.Hidden, + confirmValueChange = { bottomSheetStateHolder.bottomSheetStateChange }, + skipHalfExpanded = true + ) + + val openSheet = { scope.launch { bottomSheetState.show() } } + + val closeSheet = { + scope.launch { bottomSheetState.hide() } + Unit + } + + val openNotifyPermissionBottomSheet = { + orderDetailsViewModel.updateBottomSheetUIState( + bottomSheetUIState = + OrderDetailsScreenBottomSheetUIState.NotificationPermissionsBottomSheet + ) + openSheet() + Unit + } + + val notificationPermissionState = + rememberMultiplePermissions( + permissions = + PermissionUtils.getPermissionListFromPermissionKey( + permissionKey = PermissionKeys.NOTIFICATION_PERMISSION_KEY + ) + ) { + when (it) { + NaviPermissionResult.ShowRationale -> { + naviPayAnalytics.onNotifyPermissionDenied( + showRationale = true, + productType = orderEntity?.productType.orEmpty() + ) + } + NaviPermissionResult.HardDenied -> { + openNotifyPermissionBottomSheet() + naviPayAnalytics.onNotifyPermissionDenied( + showRationale = false, + productType = orderEntity?.productType.orEmpty() + ) + } + else -> {} + } + } + + LaunchedEffect(notificationPermissionState.allPermissionsGranted) { + if (notificationPermissionState.allPermissionsGranted && isNotifyButtonClicked) { + orderDetailsViewModel.updateNotificationPermission() + naviPayAnalytics.onNotifyPermissionGranted( + productType = orderEntity?.productType.orEmpty() + ) + } + } + + val onNotifyButtonClicked = { + orderDetailsViewModel.onNotifyButtonClicked() + notificationPermissionState.launchMultiplePermissionRequest() + } + when (uiState) { OrderDetailsScreenUIState.Loading -> LoadingScreen() OrderDetailsScreenUIState.Loaded -> { - OrderDetailsScreenContent( - naviPayActivity = naviPayActivity, - onBackClick = onBackClick, - helpCtaText = orderDetailsViewModel.helpCta.title.orEmpty(), - onHelpCtaClicked = { - naviPayAnalytics.onHelpCtaClicked( - orderId = orderEntity?.orderReferenceId.orEmpty() - ) - orderDetailsViewModel.onHelpClicked() - }, - orderHistoryDetailItemProperty = orderHistoryDetailItemProperty, - naviPayOrderHistoryDetailItemProperty = naviPayOrderHistoryDetailItemProperty, - orderEntity = orderEntity, - orderDetailsMetadataProvider = orderDetailsMetadataProvider, - transactionBankInfo = transactionBankInfo, - onCopyIconClicked = { - copyToClipboard( - text = it, - clipboardManager = clipboardManager, - context = context, - toastText = context.getString(R.string.copied_to_clipboard) + + NaviPayModalBottomSheetLayout( + sheetContent = { + RenderOrderDetailsScreenBottomSheet( + bottomSheetUIState = bottomSheetStateHolder.bottomSheetUIState, + closeSheet = closeSheet, + naviPayActivity = naviPayActivity, + naviPayAnalytics = naviPayAnalytics ) }, - onMandateNumberCopyClicked = onMandateNumberCopyClicked, - onUpiRequestIdCopyClicked = onUpiRequestIdCopyClicked, - onNaviPayTransactionIdCopyClicked = onNaviPayTransactionIdCopyClicked, - onShareReceiptCtaClicked = orderDetailsViewModel::onShareReceiptCtaClicked, - isTransactionDetailsVisible = isTransactionDetailsVisible, - isRepeatTransactionEnabled = isRepeatTransactionEnabled, - onTransactionDetailsVisibilityChanged = - orderDetailsViewModel::updateTransactionDetailsVisibility, - naviPayAnalytics = naviPayAnalytics, - refundStatusWidgetProperties = refundStatusWidgetProperties, - paymentStatusWidgetProperties = paymentStatusWidgetProperties, - onCheckBalanceClicked = onCheckBalanceCtaClicked, - onRepeatTransactionCtaClicked = - orderDetailsViewModel::handleRepeatTransactionForTransactionHistoryDetailCase, - isCheckBalanceButtonVisible = isCheckBalanceButtonVisible, - isCreditCardTransaction = isCreditCardTransaction, - onPayeeLevelTransactionHistoryCtaClicked = onPayeeLevelTransactionHistoryCtaClicked, - onOrderDescriptionClicked = onOrderDescriptionClicked, - showLoader = showLoader, - upiAppLogoBaseUrl = upiAppLogoBaseUrl, - upiAppsIconList = upiAppsIconList, - coinsSavedMessage = coinsSavedMessage, - vpaTpapMapping = vpaTpapMapping, - onAutopayDetailsCtaClicked = orderDetailsViewModel::onAutopayDetailsCtaClicked, - selectedCtaToShowLoader = selectedCtaToShowLoader + sheetState = bottomSheetState + ) { + OrderDetailsScreenContent( + naviPayActivity = naviPayActivity, + onBackClick = onBackClick, + helpCtaText = orderDetailsViewModel.helpCta.title.orEmpty(), + onHelpCtaClicked = { + naviPayAnalytics.onHelpCtaClicked( + orderId = orderEntity?.orderReferenceId.orEmpty() + ) + orderDetailsViewModel.onHelpClicked() + }, + orderHistoryDetailItemProperty = orderHistoryDetailItemProperty, + naviPayOrderHistoryDetailItemProperty = naviPayOrderHistoryDetailItemProperty, + orderEntity = orderEntity, + orderDetailsMetadataProvider = orderDetailsMetadataProvider, + transactionBankInfo = transactionBankInfo, + onCopyIconClicked = { + copyToClipboard( + text = it, + clipboardManager = clipboardManager, + context = context, + toastText = context.getString(R.string.copied_to_clipboard) + ) + }, + onMandateNumberCopyClicked = onMandateNumberCopyClicked, + onUpiRequestIdCopyClicked = onUpiRequestIdCopyClicked, + onNaviPayTransactionIdCopyClicked = onNaviPayTransactionIdCopyClicked, + onShareReceiptCtaClicked = orderDetailsViewModel::onShareReceiptCtaClicked, + isTransactionDetailsVisible = isTransactionDetailsVisible, + isRepeatTransactionEnabled = isRepeatTransactionEnabled, + onTransactionDetailsVisibilityChanged = + orderDetailsViewModel::updateTransactionDetailsVisibility, + naviPayAnalytics = naviPayAnalytics, + refundStatusWidgetProperties = refundStatusWidgetProperties, + paymentStatusWidgetProperties = paymentStatusWidgetProperties, + onCheckBalanceClicked = onCheckBalanceCtaClicked, + onRepeatTransactionCtaClicked = + orderDetailsViewModel:: + handleRepeatTransactionForTransactionHistoryDetailCase, + isCheckBalanceButtonVisible = isCheckBalanceButtonVisible, + isCreditCardTransaction = isCreditCardTransaction, + onPayeeLevelTransactionHistoryCtaClicked = + onPayeeLevelTransactionHistoryCtaClicked, + onOrderDescriptionClicked = onOrderDescriptionClicked, + showLoader = showLoader, + upiAppLogoBaseUrl = upiAppLogoBaseUrl, + upiAppsIconList = upiAppsIconList, + coinsSavedMessage = coinsSavedMessage, + vpaTpapMapping = vpaTpapMapping, + onAutopayDetailsCtaClicked = orderDetailsViewModel::onAutopayDetailsCtaClicked, + selectedCtaToShowLoader = selectedCtaToShowLoader, + onNotifyButtonClicked = onNotifyButtonClicked, + notificationPermissionState = notificationPermissionState, + notifyWidgetTextMessage = notifyWidgetTextMessage + ) + } + } + } +} + +@Composable +fun RenderOrderDetailsScreenBottomSheet( + bottomSheetUIState: OrderDetailsScreenBottomSheetUIState, + naviPayActivity: NaviPayActivity, + naviPayAnalytics: NaviPayAnalytics.OrderDetails, + closeSheet: () -> Unit +) { + + when (bottomSheetUIState) { + OrderDetailsScreenBottomSheetUIState.NotificationPermissionsBottomSheet -> { + NotifyPermissionBottomSheet( + titleText = stringResource(RewardsR.allow_notifications), + bodyTitleText = stringResource(RewardsR.app_notifications), + bodySubText = stringResource(RewardsR.to_enable), + bodySubSubText = stringResource(RewardsR.phone_settings), + buttonText = stringResource(RewardsR.go_to_settings), + onClick = { + launchPermissionSettingsScreen( + naviPayActivity = naviPayActivity, + naviPayAnalytics = NaviPayAnalytics.INSTANCE.NaviPayPermission() + ) + naviPayAnalytics.onAppSettingsLaunched() + closeSheet() + }, + onDismiss = {} ) } } diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsScreenContent.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsScreenContent.kt index a4407e0c61..8fe8148253 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsScreenContent.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsScreenContent.kt @@ -25,8 +25,11 @@ import androidx.core.content.ContextCompat import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.compose.LocalLifecycleOwner +import com.google.accompanist.permissions.ExperimentalPermissionsApi +import com.google.accompanist.permissions.MultiplePermissionsState import com.navi.base.utils.EMPTY import com.navi.pay.analytics.NaviPayAnalytics +import com.navi.pay.common.model.config.NotifyWidgetTextMessage import com.navi.pay.common.theme.color.NaviPayColor import com.navi.pay.common.ui.NaviPayHeader import com.navi.pay.entry.NaviPayActivity @@ -41,7 +44,7 @@ import com.navi.pay.tstore.list.model.view.OrderEntity import kotlinx.coroutines.delay import kotlinx.coroutines.launch -@OptIn(ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3Api::class, ExperimentalPermissionsApi::class) @Composable fun OrderDetailsScreenContent( naviPayActivity: NaviPayActivity, @@ -76,7 +79,10 @@ fun OrderDetailsScreenContent( coinsSavedMessage: String, vpaTpapMapping: Map, onAutopayDetailsCtaClicked: () -> Unit, - selectedCtaToShowLoader: OrderDetailsLoadingStateCtaType? = null + selectedCtaToShowLoader: OrderDetailsLoadingStateCtaType? = null, + onNotifyButtonClicked: () -> Unit, + notificationPermissionState: MultiplePermissionsState, + notifyWidgetTextMessage: NotifyWidgetTextMessage ) { val lifecycleOwner = LocalLifecycleOwner.current @@ -136,6 +142,7 @@ fun OrderDetailsScreenContent( orderHistoryDetailItemProperty = orderHistoryDetailItemProperty, coinsSavedMessage = coinsSavedMessage ) + OrderDetailsSummarySection( orderEntity = orderEntity, orderDetailsMetadataProvider = orderDetailsMetadataProvider, @@ -166,7 +173,10 @@ fun OrderDetailsScreenContent( vpaTpapMapping = vpaTpapMapping, scrollState = scrollState, onAutopayDetailsCtaClicked = onAutopayDetailsCtaClicked, - selectedCtaToShowLoader = selectedCtaToShowLoader + selectedCtaToShowLoader = selectedCtaToShowLoader, + onNotifyButtonClicked = onNotifyButtonClicked, + notificationPermissionState = notificationPermissionState, + notifyWidgetTextMessage = notifyWidgetTextMessage ) } }, diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsSummarySection.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsSummarySection.kt index 59cd8f2fd0..15dca87d6c 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsSummarySection.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/ui/common/OrderDetailsSummarySection.kt @@ -26,14 +26,22 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.google.accompanist.permissions.ExperimentalPermissionsApi +import com.google.accompanist.permissions.MultiplePermissionsState import com.navi.base.utils.isNotNullAndNotEmpty +import com.navi.base.utils.orFalse import com.navi.design.font.FontWeightEnum import com.navi.design.font.getFontWeight import com.navi.design.font.naviFontFamily +import com.navi.elex.molecules.ElexNotifyWidget import com.navi.naviwidgets.extensions.NaviText +import com.navi.naviwidgets.utils.NOTIFICATION_SUCCESS +import com.navi.pay.R import com.navi.pay.analytics.NaviPayAnalytics +import com.navi.pay.common.model.config.NotifyWidgetTextMessage import com.navi.pay.common.theme.color.NaviPayColor import com.navi.pay.common.ui.NaviPayCard import com.navi.pay.common.ui.NaviPayCreditCardSponsorView @@ -57,6 +65,7 @@ import com.navi.pay.tstore.list.model.view.OrderEntity * responsible for displaying the summary of the order i.e. order id etc. This section is displayed * at the center of the screen. */ +@OptIn(ExperimentalPermissionsApi::class) @Composable internal fun OrderDetailsSummarySection( orderEntity: OrderEntity?, @@ -87,7 +96,10 @@ internal fun OrderDetailsSummarySection( vpaTpapMapping: Map, scrollState: ScrollState, onAutopayDetailsCtaClicked: () -> Unit, - selectedCtaToShowLoader: OrderDetailsLoadingStateCtaType? = null + selectedCtaToShowLoader: OrderDetailsLoadingStateCtaType? = null, + onNotifyButtonClicked: () -> Unit, + notificationPermissionState: MultiplePermissionsState, + notifyWidgetTextMessage: NotifyWidgetTextMessage ) { paymentStatusWidgetProperties?.let { @@ -103,13 +115,31 @@ internal fun OrderDetailsSummarySection( } Column( - modifier = Modifier.fillMaxSize().verticalScroll(state = scrollState), + modifier = + Modifier.fillMaxSize().padding(horizontal = 16.dp).verticalScroll(state = scrollState), horizontalAlignment = Alignment.CenterHorizontally ) { Spacer(modifier = Modifier.height(24.dp)) + if (orderEntity?.orderStatusOfView?.isPending().orFalse()) { + + ElexNotifyWidget( + isSuccessState = notificationPermissionState.allPermissionsGranted, + mainText = notifyWidgetTextMessage.mainText, + subText = notifyWidgetTextMessage.subText, + successMainText = notifyWidgetTextMessage.successMainText, + successSubText = notifyWidgetTextMessage.successSubText, + isCrossbuttonVisible = false, + onClick = onNotifyButtonClicked, + ctaButtonText = stringResource(id = R.string.np_notify_me), + crossIconUrl = "", + notificationSuccessIconUrl = NOTIFICATION_SUCCESS + ) + Spacer(modifier = Modifier.height(24.dp)) + } + NaviPayCard( - modifier = Modifier.padding(horizontal = 16.dp).fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), borderStroke = BorderStroke(width = 1.dp, color = NaviPayColor.borderDefault) ) { Column(modifier = Modifier.fillMaxWidth()) { diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/viewmodel/OrderDetailsViewModel.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/viewmodel/OrderDetailsViewModel.kt index 11bd0d7996..6db4764e30 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/viewmodel/OrderDetailsViewModel.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/tstore/details/viewmodel/OrderDetailsViewModel.kt @@ -21,6 +21,8 @@ import com.navi.base.utils.orFalse import com.navi.common.R as CommonR import com.navi.common.di.CoroutineDispatcherProvider import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper +import com.navi.common.model.NotificationSettings +import com.navi.common.model.SettingsMedium import com.navi.common.network.models.RepoResult import com.navi.common.network.models.isSuccessWithData import com.navi.common.utils.NaviApiPoller @@ -29,6 +31,7 @@ import com.navi.pay.analytics.NaviPayAnalytics import com.navi.pay.analytics.NaviPayAnalytics.Companion.NAVI_PAY_T_STORE_ORDER_DETAILS import com.navi.pay.common.connectivity.NaviPayNetworkConnectivity import com.navi.pay.common.model.config.NaviPayDefaultConfig +import com.navi.pay.common.model.config.NotifyWidgetTextMessage import com.navi.pay.common.model.view.NaviPayButtonAction import com.navi.pay.common.model.view.NaviPayButtonTheme import com.navi.pay.common.model.view.NaviPayErrorButtonConfig @@ -71,6 +74,7 @@ import com.navi.pay.onboarding.account.common.repository.AccountsRepository import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity import com.navi.pay.onboarding.account.linked.model.view.LinkedAccountsScreenSource import com.navi.pay.tstore.details.model.network.OrderStatusResponse +import com.navi.pay.tstore.details.model.view.OrderDetailsScreenBottomSheetStateHolder import com.navi.pay.tstore.details.model.view.OrderHistoryDetailItemProperty import com.navi.pay.tstore.details.model.view.OrderPaymentStatus import com.navi.pay.tstore.details.model.view.OrderProductType @@ -266,8 +270,25 @@ constructor( MutableStateFlow(OrderDetailsLoadingStateCtaType.AutopayDetails) val selectedCtaToShowLoader = _selectedCtaToShowLoader.asStateFlow() + private val _notifyWidgetTextMessage = + MutableStateFlow(naviPayDefaultConfig.config.notifyWidgetTextMessage) + val notifyWidgetTextMessage = _notifyWidgetTextMessage.asStateFlow() + private val selectedBankAccount = MutableStateFlow(null) + private val _bottomSheetStateHolder = + MutableStateFlow( + OrderDetailsScreenBottomSheetStateHolder( + bottomSheetStateChange = true, + bottomSheetUIState = + OrderDetailsScreenBottomSheetUIState.NotificationPermissionsBottomSheet + ) + ) + val bottomSheetStateHolder = _bottomSheetStateHolder.asStateFlow() + + private val _isNotifyButtonClicked = MutableStateFlow(false) + val isNotifyButtonClicked = _isNotifyButtonClicked.asStateFlow() + init { viewModelScope.launch(dispatcherProvider.io) { val isError = getOrderDetails() @@ -431,6 +452,13 @@ constructor( updateUpiAppLogoBaseUrl(url = naviPayDefaultConfig.config.upiAppLogoS3BaseUrl) updateUpiAppsIconList(list = naviPayDefaultConfig.config.upiAppsIconList) updateVpaTpapMapping(vpaTpapMapping = naviPayDefaultConfig.config.vpaTpapMapping) + updateNotifyWidgetTextMessage( + notifyWidgetTextMessage = naviPayDefaultConfig.config.notifyWidgetTextMessage + ) + } + + private fun updateNotifyWidgetTextMessage(notifyWidgetTextMessage: NotifyWidgetTextMessage) { + _notifyWidgetTextMessage.update { notifyWidgetTextMessage } } private fun updateUpiMandateInfo(mandateInfo: MandateEntity?) { @@ -491,6 +519,33 @@ constructor( } } + fun updateBottomSheetUIState( + bottomSheetStateChange: Boolean? = null, + bottomSheetUIState: OrderDetailsScreenBottomSheetUIState? = null + ) { + _bottomSheetStateHolder.update { + it.copy( + bottomSheetStateChange = bottomSheetStateChange ?: it.bottomSheetStateChange, + bottomSheetUIState = bottomSheetUIState ?: it.bottomSheetUIState + ) + } + } + + fun updateNotificationPermission() { + val notificationSettings = + listOf(NotificationSettings(medium = SettingsMedium.PUSH_NOTIFICATION, enabled = true)) + viewModelScope.launch(Dispatchers.IO) { + orderDetailsRepository.updateNotificationsPermission( + notificationSettings = notificationSettings + ) + } + } + + fun onNotifyButtonClicked() { + _isNotifyButtonClicked.update { true } + naviPayAnalytics.onNotifyClicked(productType = orderEntity.value?.productType.orEmpty()) + } + private suspend fun getPayerDetails( naviPayTransactionDetailsMetadata: NaviPayTransactionDetailsMetadata? ): UserTxnInfo? = @@ -1169,3 +1224,8 @@ enum class OrderDetailsLoadingStateCtaType { CheckBalance, AutopayDetails } + +sealed class OrderDetailsScreenBottomSheetUIState { + + data object NotificationPermissionsBottomSheet : OrderDetailsScreenBottomSheetUIState() +} diff --git a/android/navi-pay/src/main/res/values/strings.xml b/android/navi-pay/src/main/res/values/strings.xml index df3ffdd4c8..a283ee905a 100644 --- a/android/navi-pay/src/main/res/values/strings.xml +++ b/android/navi-pay/src/main/res/values/strings.xml @@ -611,6 +611,11 @@ Payment failed We will update the payment status soon. Your recharge may reflect within 48 hours + "Turn on notifications to get updates" + "We are processing your payment" + "You will get updates on payment status" + "We are actively working on it" + Notify Redirecting you to make payment Declining the payment request Debit card cannot be used to set PIN for this credit line. Set PIN with Aadhaar card.