TP-47206 | Repeat and Top Up Revamp on AP (#9732)
Co-authored-by: Hitesh Kumar <hitesh.kumar@navi.com>
This commit is contained in:
@@ -9,6 +9,7 @@ package com.navi.ap.common.deserializer
|
||||
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonElement
|
||||
import com.navi.ap.common.models.CalendarWidgetData
|
||||
import com.navi.ap.common.models.CardWithHeaderFooterAndLazyColumnWidgetData
|
||||
import com.navi.ap.common.models.CollapsableItemsWithTitleWidgetData
|
||||
import com.navi.ap.common.models.CustomWidgets
|
||||
@@ -31,14 +32,25 @@ class CustomUiTronDataDeserializer : UiTronDataDeserializer() {
|
||||
return when (jsonObject["viewType"].asString) {
|
||||
CustomWidgets.COLLAPSABLE_ITEMS_WITH_TITLE_WIDGET.name ->
|
||||
context?.deserialize(json, CollapsableItemsWithTitleWidgetData::class.java)
|
||||
|
||||
CustomWidgets.DYNAMIC_GRID_WIDGET.name ->
|
||||
context?.deserialize(json, DynamicGridWidgetData::class.java)
|
||||
|
||||
CustomWidgets.DYNAMIC_COLUMN_WIDGET.name ->
|
||||
context?.deserialize(json, DynamicColumnWidgetData::class.java)
|
||||
|
||||
CustomWidgets.DYNAMIC_ROW_WIDGET.name ->
|
||||
context?.deserialize(json, DynamicRowWidgetData::class.java)
|
||||
|
||||
CustomWidgets.CARD_WITH_HEADER_FOOTER_AND_LAZY_COLUMN_WIDGET.name ->
|
||||
context?.deserialize(json, CardWithHeaderFooterAndLazyColumnWidgetData::class.java)
|
||||
context?.deserialize(
|
||||
json,
|
||||
CardWithHeaderFooterAndLazyColumnWidgetData::class.java
|
||||
)
|
||||
|
||||
CustomWidgets.CALENDAR_WIDGET.name ->
|
||||
context?.deserialize(json, CalendarWidgetData::class.java)
|
||||
|
||||
else -> super.deserialize(json, typeOfT, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class LambdaFactory(
|
||||
bridge: LambdaBridge
|
||||
): Lambda {
|
||||
return when (applicationType) {
|
||||
ApplicationType.PL.name, ApplicationType.PL_REFILL.name -> PLLambdaHandler(bridge)
|
||||
ApplicationType.PL.name, ApplicationType.PL_REPEAT.name,ApplicationType.PL_TOP_UP.name , ApplicationType.PL_REFILL.name-> PLLambdaHandler(bridge)
|
||||
ApplicationType.COINS.name -> CoinsLambdaHandler(bridge)
|
||||
else -> DefaultLambdaHandler(bridge)
|
||||
}
|
||||
|
||||
@@ -136,6 +136,12 @@ internal class PLLambdaHandler(
|
||||
)
|
||||
}
|
||||
|
||||
LambdaType.FETCH_CALENDER_DETAILS.name -> {
|
||||
lambdaImpl.fetchCalendarDetails(
|
||||
lambadaData.resolvedValue.toMutableMap()
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
super.execute(lambdaApiAction, lambadaData)
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ internal class PLLambdaImpl(
|
||||
val amount = resolvedValues[SELECTED_LOAN_AMOUNT]?.toString()
|
||||
var tenure = resolvedValues[SELECTED_TENURE]?.toString()
|
||||
val emiPlanSelected = resolvedValues[SELECTED_TENURE_PILL_INDEX]?.toString()
|
||||
val offerType = resolvedValues[OFFER_TYPE]?.toString()
|
||||
|
||||
if (savedAmount == amount && savedTenure == tenure && savedAmount.isNotNull() && savedTenure.isNotNull()) return@launch
|
||||
|
||||
@@ -117,7 +118,7 @@ internal class PLLambdaImpl(
|
||||
}
|
||||
|
||||
val lambdaResponse = repository.fetchOfferDetails(
|
||||
amount = amount, tenureInMonths = tenure, emiPlansSelected = emiPlanSelected
|
||||
amount = amount, tenureInMonths = tenure, emiPlansSelected = emiPlanSelected, offerType = offerType
|
||||
)
|
||||
lambdaHandler.bridge.setLambdaState(
|
||||
when {
|
||||
@@ -844,7 +845,7 @@ internal class PLLambdaImpl(
|
||||
lambdaResponse.data.isNotNull() -> {
|
||||
val updatedLambdaApiAction =
|
||||
PathInjector<LambdaApiAction, Any?>().injectData(
|
||||
lambdaApiAction, lambdaResponse.data!!
|
||||
lambdaApiAction, lambdaResponse.data
|
||||
)
|
||||
lambdaHandler.bridge.executeActions(updatedLambdaApiAction.onSuccess)
|
||||
LambdaState.Success(LambdaResponseType())
|
||||
@@ -905,7 +906,7 @@ internal class PLLambdaImpl(
|
||||
)
|
||||
|
||||
val updatedLambdaApiAction = PathInjector<LambdaApiAction, Any?>().injectData(
|
||||
lambdaApiAction, lambdaResponse.data!!
|
||||
lambdaApiAction, lambdaResponse.data
|
||||
)
|
||||
updatedResponse?.let {
|
||||
lambdaHandler.bridge.setMetaData(updatedResponse.screenData?.metaData ?: mapOf())
|
||||
@@ -1058,6 +1059,64 @@ internal class PLLambdaImpl(
|
||||
}
|
||||
}
|
||||
|
||||
fun fetchCalendarDetails(
|
||||
resolvedValues: MutableMap<String, Any?>
|
||||
) {
|
||||
lambdaHandler.bridge.getViewModelScope().launch(Dispatchers.IO) {
|
||||
|
||||
if (lambdaHandler.getClonedScreenDefinitionState().isNull()) {
|
||||
lambdaHandler.setClonedScreenDefinitionState(lambdaHandler.bridge.getScreenStructurePreRenderState())
|
||||
}
|
||||
|
||||
lambdaHandler.bridge.setLambdaState(LambdaState.Loading)
|
||||
val lambdaResponse = repository.fetchOfferDetails(
|
||||
fetchEmiDates = resolvedValues[FETCH_EMI_DATES]?.toString()?.toBoolean()
|
||||
)
|
||||
|
||||
lambdaHandler.bridge.setLambdaState(
|
||||
when {
|
||||
lambdaResponse.data.isNotNull() && lambdaHandler.getClonedScreenDefinitionState().isNotNull() -> {
|
||||
|
||||
val updatedResponse =
|
||||
BasePathInjector<ApScreenDefinitionStructure, Any?>().injectData(
|
||||
lambdaHandler.getClonedScreenDefinitionState(),
|
||||
lambdaResponse.data
|
||||
)
|
||||
updatedResponse?.let {
|
||||
lambdaHandler.bridge.setScreenDefinitionState(
|
||||
ApScreenDefinitionState.Success(updatedResponse)
|
||||
)
|
||||
}
|
||||
LambdaState.Success(LambdaResponseType())
|
||||
}
|
||||
|
||||
lambdaResponse.errorBottomSheetStructure.isNotNull() -> {
|
||||
LambdaState.Error(
|
||||
lambdaResponse.statusCode,
|
||||
lambdaResponse.errorBottomSheetStructure,
|
||||
lambdaResponse.genericErrorBottomSheetFields
|
||||
)
|
||||
}
|
||||
|
||||
lambdaResponse.isNull() -> {
|
||||
val errorBottomSheetFields = BottomSheetHelper.getLambdaErrorBottomSheet(
|
||||
ApiType.LambdaApiAction.name
|
||||
)
|
||||
LambdaState.Error(
|
||||
lambdaResponse.statusCode,
|
||||
getBottomSheetStructure(errorBottomSheetFields),
|
||||
errorBottomSheetFields
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
LambdaState.Nothing
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun initiateAgreementAndSanctionLetterDownload(
|
||||
resolvedValues: MutableMap<String, Any?>,
|
||||
lambdaApiAction: LambdaApiAction,
|
||||
|
||||
@@ -59,12 +59,16 @@ class PLLambdaRepository @Inject constructor(private val retrofitService: APRetr
|
||||
amount: String? = null,
|
||||
tenureInMonths: String? = null,
|
||||
emiPlansSelected: String? = null,
|
||||
fetchEmiDates: Boolean? = false,
|
||||
offerType: String? = null
|
||||
): ApRepoResult<Any> {
|
||||
val response =
|
||||
retrofitService.getOfferDetails(
|
||||
amount = amount,
|
||||
tenureInMonths = tenureInMonths,
|
||||
emiPlansSelected = emiPlansSelected
|
||||
emiPlansSelected = emiPlansSelected,
|
||||
fetchEmiDates = fetchEmiDates,
|
||||
offerType = offerType
|
||||
)
|
||||
logApEvent(
|
||||
Pair(
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.navi.ap.common.models
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class CalendarData(
|
||||
@SerializedName("rawDate") val rawDate: Int,
|
||||
@SerializedName("formattedDate") val formattedDate: String,
|
||||
@SerializedName("isEnabled") val isEnabled: Boolean,
|
||||
@SerializedName("textInWords") val textInWords: String,
|
||||
@SerializedName("dateWithSuffix") val dateWithSuffix: String,
|
||||
) : Parcelable
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.navi.ap.common.models
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.navi.uitron.model.data.TextData
|
||||
import com.navi.uitron.model.data.UiTronData
|
||||
import com.navi.uitron.model.ui.ColumnProperty
|
||||
import com.navi.uitron.model.ui.ImageProperty
|
||||
import com.navi.uitron.model.ui.TextProperty
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlinx.parcelize.RawValue
|
||||
|
||||
|
||||
@Parcelize
|
||||
data class CalendarWidgetData(
|
||||
|
||||
@SerializedName("selectedDate") var selectedDate: String? = null,
|
||||
@SerializedName("layoutId") var layoutId: String? = null,
|
||||
@SerializedName("errorLayoutId") var errorLayoutId: String? = null,
|
||||
@SerializedName("emiDates") val emiDates: @RawValue Any? = null,
|
||||
@SerializedName("calendarProperties") var calendarProperties: ColumnProperty? = null,
|
||||
@SerializedName("calendarPadding") val calendarPadding: String? = null,
|
||||
@SerializedName("calendarRowGap") val calendarRowGap: String? = null,
|
||||
@SerializedName("dateBoxSize") val dateBoxSize: String? = null,
|
||||
@SerializedName("calendarColors") val calendarColors: CalendarColors? = null,
|
||||
@SerializedName("calendarTextProperty") val calendarTextProperty: TextProperty? = null,
|
||||
@SerializedName("errorTextProperty") val errorTextProperty: TextProperty? = null,
|
||||
@SerializedName("errorIconProperty") val errorIconProperty: ImageProperty? = null,
|
||||
@SerializedName("errorImageUrl") val errorImageUrl: String? = null,
|
||||
@SerializedName("errorMessage") val errorMessage: TextData? = null,
|
||||
|
||||
) : UiTronData(), Parcelable {
|
||||
|
||||
@IgnoredOnParcel
|
||||
val emiDate: List<CalendarData>? = null
|
||||
get() {
|
||||
if(field == null){
|
||||
return getCalendarData()
|
||||
}
|
||||
return field
|
||||
}
|
||||
|
||||
private fun getCalendarData(): List<CalendarData>? {
|
||||
val type = object : TypeToken<List<CalendarData>>() {}.type
|
||||
return Gson().fromJson(emiDates.toString(), type)
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class CalendarColors(
|
||||
@SerializedName("calendarBorderColor") val calendarBorderColor: String? = null,
|
||||
@SerializedName("calendarErrorBorderColor") val calendarErrorBorderColor: String? = null,
|
||||
@SerializedName("selectedDateColor") val selectedDateColor: String? = null,
|
||||
@SerializedName("selectedDateTextColor") val selectedDateTextColor: String? = null,
|
||||
@SerializedName("defaultDateTextColor") val defaultDateTextColor: String? = null,
|
||||
@SerializedName("disabledDateTextColor") val disabledDateTextColor: String? = null,
|
||||
) : Parcelable
|
||||
}
|
||||
|
||||
|
||||
@@ -44,5 +44,6 @@ enum class CustomWidgets {
|
||||
DYNAMIC_COLUMN_WIDGET,
|
||||
DYNAMIC_ROW_WIDGET,
|
||||
DYNAMIC_GRID_WIDGET,
|
||||
CARD_WITH_HEADER_FOOTER_AND_LAZY_COLUMN_WIDGET
|
||||
CARD_WITH_HEADER_FOOTER_AND_LAZY_COLUMN_WIDGET,
|
||||
CALENDAR_WIDGET,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.navi.ap.common.models.lambdamodels
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class LoanSummaryResponse(
|
||||
@SerializedName("dataList") val dataList: List<EmiResponse>? = null,
|
||||
@SerializedName("lastEmiData") val lastEmiData: EmiDetails? = null,
|
||||
@SerializedName("placeHolderKey") val placeHolderKey: String? = null
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class EmiResponse(
|
||||
@SerializedName("year") val year: String? = null,
|
||||
@SerializedName("emiDataList") val emiDataList: List<EmiData>? = null
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class EmiData(
|
||||
@SerializedName("emiDetails") val emiDetails: EmiDetails? = null,
|
||||
@SerializedName("emiChange") val emiChange: EmiChange? = null
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class EmiDetails(
|
||||
@SerializedName("month") val month: Int? = null,
|
||||
@SerializedName("date") val date: String? = null,
|
||||
@SerializedName("amount") val amount: String? = null,
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class EmiChange(
|
||||
@SerializedName("originalAmount") val originalAmount: String? = null,
|
||||
@SerializedName("changedAmount") val changedAmount: String? = null,
|
||||
) : Parcelable
|
||||
@@ -0,0 +1,313 @@
|
||||
package com.navi.ap.common.renderer
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.navi.ap.common.models.CalendarData
|
||||
import com.navi.ap.common.models.CalendarWidgetData
|
||||
import com.navi.ap.common.models.WidgetModelDefinition
|
||||
import com.navi.ap.utils.constants.SELECTED_DATE
|
||||
import com.navi.ap.utils.constants.SELECTED_DATE_WITH_SUFFIX
|
||||
import com.navi.ap.utils.constants.SELECTED_FORMATTED_DATE
|
||||
import com.navi.ap.utils.constants.SELECTED_RAW_DATE
|
||||
import com.navi.ap.utils.constants.SHOW
|
||||
import com.navi.ap.utils.constants.WIDGET_DATA
|
||||
import com.navi.ap.utils.injector.FieldInjector
|
||||
import com.navi.base.utils.EMPTY
|
||||
import com.navi.design.theme.getFontFamily
|
||||
import com.navi.design.theme.getFontWeight
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
import com.navi.uitron.model.data.ImageData
|
||||
import com.navi.uitron.model.data.UiTronActionData
|
||||
import com.navi.uitron.render.ImageRenderer
|
||||
import com.navi.uitron.render.TextRenderer
|
||||
import com.navi.uitron.utils.ShapeUtil
|
||||
import com.navi.uitron.viewmodel.UiTronViewModel
|
||||
import getInputId
|
||||
import getTextAlignment
|
||||
import hexToComposeColor
|
||||
|
||||
class CalendarWidget {
|
||||
|
||||
@Composable
|
||||
fun Render(viewModel: UiTronViewModel, widget: WidgetModelDefinition<UiTronResponse>) {
|
||||
val calendarWidgetData: CalendarWidgetData? =
|
||||
widget.widgetData?.data?.get("$WIDGET_DATA${widget.widgetId}") as? CalendarWidgetData
|
||||
val updatedSelectedDate = viewModel.handle.get<Int>(SELECTED_RAW_DATE)
|
||||
?: calendarWidgetData?.selectedDate?.toIntOrNull()
|
||||
CalendarView(
|
||||
selectedDateInitial = updatedSelectedDate,
|
||||
calendarWidgetData = calendarWidgetData ?: CalendarWidgetData(),
|
||||
viewModel = viewModel,
|
||||
onClickAction = calendarWidgetData?.onClick
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CalendarView(
|
||||
selectedDateInitial: Int? = null,
|
||||
calendarWidgetData: CalendarWidgetData,
|
||||
viewModel: UiTronViewModel,
|
||||
onClickAction: UiTronActionData?
|
||||
) {
|
||||
|
||||
val daysInMonth = calendarWidgetData.emiDate ?: emptyList()
|
||||
val disabledDates = daysInMonth.filter { !it.isEnabled }.map { it.rawDate }.toSet()
|
||||
var selectedDate by remember { mutableStateOf(selectedDateInitial) }
|
||||
LaunchedEffect(selectedDate) {
|
||||
if (selectedDate in disabledDates) {
|
||||
selectedDate = null
|
||||
}
|
||||
if (selectedDate == null) return@LaunchedEffect
|
||||
viewModel.handle[calendarWidgetData.layoutId.getInputId()] = selectedDate.toString()
|
||||
val textInWord =
|
||||
calendarWidgetData.emiDate?.firstOrNull { it.rawDate == selectedDate }?.textInWords
|
||||
val selectedDateWithSuffix =
|
||||
calendarWidgetData.emiDate?.firstOrNull { it.rawDate == selectedDate }?.dateWithSuffix
|
||||
viewModel.handle[SELECTED_RAW_DATE] = selectedDate
|
||||
viewModel.handle[SELECTED_FORMATTED_DATE] =
|
||||
calendarWidgetData.emiDate?.firstOrNull { it.rawDate == selectedDate }?.formattedDate
|
||||
val updatedAction = FieldInjector<UiTronActionData, Any>().injectData(
|
||||
onClickAction, mapOf(
|
||||
SELECTED_DATE to textInWord,
|
||||
SELECTED_DATE_WITH_SUFFIX to selectedDateWithSuffix,
|
||||
SELECTED_RAW_DATE to selectedDate.toString(),
|
||||
SELECTED_FORMATTED_DATE to calendarWidgetData.emiDate?.firstOrNull { it.rawDate == selectedDate }?.formattedDate
|
||||
)
|
||||
)
|
||||
viewModel.handleActions(updatedAction)
|
||||
}
|
||||
CalendarGrid(disabledDates = disabledDates,
|
||||
daysInMonth = daysInMonth,
|
||||
selectedDate = selectedDate,
|
||||
calendarWidgetData = calendarWidgetData,
|
||||
viewModel = viewModel,
|
||||
onDateSelected = {
|
||||
selectedDate = it
|
||||
})
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CalendarGrid(
|
||||
disabledDates: Set<Int>,
|
||||
daysInMonth: List<CalendarData>,
|
||||
selectedDate: Int? = null,
|
||||
calendarWidgetData: CalendarWidgetData,
|
||||
viewModel: UiTronViewModel,
|
||||
onDateSelected: (Int) -> Unit
|
||||
) {
|
||||
val columns = numberOfColumns
|
||||
val rows = (daysInMonth.size + 6) / columns
|
||||
|
||||
Grid(
|
||||
items = daysInMonth, rows = rows, columns = columns, calendarWidgetData, viewModel
|
||||
) { day ->
|
||||
val isDisabled = day.rawDate in disabledDates
|
||||
val isSelected = day.rawDate == selectedDate
|
||||
val onClickAction = { if (!isDisabled) onDateSelected(day.rawDate) }
|
||||
|
||||
DateColumn(
|
||||
day = day.rawDate,
|
||||
isSelected = isSelected,
|
||||
isDisabled = isDisabled,
|
||||
calendarWidgetData = calendarWidgetData,
|
||||
onClick = onClickAction
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DateColumn(
|
||||
day: Int,
|
||||
isSelected: Boolean,
|
||||
isDisabled: Boolean,
|
||||
calendarWidgetData: CalendarWidgetData,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val selectedColor =
|
||||
calendarWidgetData.calendarColors?.selectedDateColor?.hexToComposeColor ?: Color(
|
||||
SELECTED_COLOR
|
||||
)
|
||||
val backgroundColor = if (isSelected) selectedColor else Color.Transparent
|
||||
val textColor = when {
|
||||
isSelected -> calendarWidgetData.calendarColors?.selectedDateTextColor?.hexToComposeColor
|
||||
?: Color.White
|
||||
|
||||
isDisabled -> calendarWidgetData.calendarColors?.disabledDateTextColor?.hexToComposeColor
|
||||
?: Color(
|
||||
DISABLED_COLOR
|
||||
)
|
||||
|
||||
else -> calendarWidgetData.calendarColors?.defaultDateTextColor?.hexToComposeColor
|
||||
?: Color(DEFAULT_COLOR)
|
||||
}
|
||||
|
||||
val dateColumnModifier = Modifier
|
||||
.width(calendarWidgetData.dateBoxSize?.toInt()?.dp ?: 26.dp)
|
||||
.height(calendarWidgetData.dateBoxSize?.toInt()?.dp ?: 26.dp)
|
||||
.background(backgroundColor, CircleShape)
|
||||
.clickable(
|
||||
enabled = !isDisabled,
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
onClick = onClick
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = dateColumnModifier,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = day.toString(),
|
||||
fontFamily = getFontFamily(calendarWidgetData.calendarTextProperty?.fontFamily),
|
||||
fontWeight = getFontWeight(calendarWidgetData.calendarTextProperty?.fontWeight),
|
||||
fontSize = calendarWidgetData.calendarTextProperty?.fontSize?.sp ?: 14.sp,
|
||||
textAlign = getTextAlignment(calendarWidgetData.calendarTextProperty?.textAlign),
|
||||
color = textColor
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun <T> Grid(
|
||||
items: List<T>,
|
||||
rows: Int,
|
||||
columns: Int,
|
||||
calendarWidgetData: CalendarWidgetData,
|
||||
viewModel: UiTronViewModel,
|
||||
itemContent: @Composable BoxScope.(T) -> Unit
|
||||
) {
|
||||
|
||||
var showErrorState by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
viewModel.handle.getStateFlow<String?>(
|
||||
calendarWidgetData.errorLayoutId.toString(), null
|
||||
).collect {
|
||||
showErrorState = it == SHOW
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
calendarWidgetData.calendarProperties?.padding?.start?.dp ?: 16.dp,
|
||||
calendarWidgetData.calendarProperties?.padding?.top?.dp ?: 16.dp,
|
||||
calendarWidgetData.calendarProperties?.padding?.end?.dp ?: 16.dp,
|
||||
calendarWidgetData.calendarProperties?.padding?.bottom?.dp ?: 0.dp
|
||||
)
|
||||
.border(
|
||||
width = calendarWidgetData.calendarProperties?.borderStrokeData?.width?.dp
|
||||
?: 1.dp,
|
||||
color = when {
|
||||
showErrorState -> calendarWidgetData.calendarColors?.calendarErrorBorderColor?.hexToComposeColor
|
||||
?: Color(ERROR_STATE_COLOR)
|
||||
|
||||
else -> calendarWidgetData.calendarColors?.calendarBorderColor?.hexToComposeColor
|
||||
?: Color(BORDER_COLOR)
|
||||
},
|
||||
shape = ShapeUtil.getShape(shape = calendarWidgetData.calendarProperties?.borderStrokeData?.shape)
|
||||
)
|
||||
.background(
|
||||
color = calendarWidgetData.calendarProperties?.backgroundColor?.hexToComposeColor
|
||||
?: Color.White,
|
||||
)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(calendarWidgetData.calendarPadding?.toIntOrNull()?.dp ?: 16.dp),
|
||||
) {
|
||||
for (i in 0 until rows) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
) {
|
||||
for (j in 0 until columns) {
|
||||
val index = i * columns + j
|
||||
Box(
|
||||
modifier = Modifier.weight(1f, true),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (index < items.size) {
|
||||
itemContent(items[index])
|
||||
} else {
|
||||
Text(text = EMPTY)
|
||||
}
|
||||
}
|
||||
if (j != columns - 1) Spacer(modifier = Modifier.weight(0.6f))
|
||||
}
|
||||
}
|
||||
if (i != rows - 1) {
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(calendarWidgetData.calendarRowGap?.toInt()?.dp ?: 10.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (showErrorState) {
|
||||
Row(modifier = Modifier.padding(start = 16.dp, end = 16.dp)) {
|
||||
calendarWidgetData.errorIconProperty?.let {
|
||||
ImageRenderer().Render(
|
||||
property = it,
|
||||
uiTronData = ImageData(
|
||||
iconUrl = calendarWidgetData.errorImageUrl,
|
||||
),
|
||||
uiTronViewModel = viewModel,
|
||||
modifier = null
|
||||
)
|
||||
}
|
||||
calendarWidgetData.errorTextProperty?.let {
|
||||
TextRenderer().Render(
|
||||
property = it,
|
||||
uiTronData = calendarWidgetData.errorMessage,
|
||||
uiTronViewModel = viewModel,
|
||||
modifier = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ERROR_STATE_COLOR = 0xFFEF0000
|
||||
const val BORDER_COLOR = 0xFFEBEBEB
|
||||
const val SELECTED_COLOR = 0xFF1F002A
|
||||
const val DISABLED_COLOR = 0xFFA8A8A8
|
||||
const val DEFAULT_COLOR = 0xFF444444
|
||||
private const val numberOfColumns = 7
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import coil.size.Size
|
||||
import com.navi.ap.common.models.CollapsableItemsWithTitleWidgetData
|
||||
import com.navi.ap.common.models.WidgetModelDefinition
|
||||
import com.navi.ap.common.viewmodel.ApplicationPlatformVM
|
||||
import com.navi.ap.utils.constants.WIDGET_DATA
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
import com.navi.uitron.model.data.TextData
|
||||
import com.navi.uitron.model.ui.TextProperty
|
||||
@@ -41,7 +42,7 @@ class CollapsableItemsWithTitleWidget {
|
||||
@Composable
|
||||
fun Render(viewModel: ApplicationPlatformVM, widget: WidgetModelDefinition<UiTronResponse>) {
|
||||
val titleDescriptionListWidgetData =
|
||||
widget.widgetData?.data?.get("widget_data_${widget.widgetId}")
|
||||
widget.widgetData?.data?.get("${WIDGET_DATA}${widget.widgetId}")
|
||||
as? CollapsableItemsWithTitleWidgetData
|
||||
Column(
|
||||
modifier =
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.navi.uitron.serializer.UiTronDataSerializer
|
||||
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.navi.ap.common.models.CalendarWidgetData
|
||||
import com.navi.ap.common.models.CardWithHeaderFooterAndLazyColumnWidgetData
|
||||
import com.navi.ap.common.models.CollapsableItemsWithTitleWidgetData
|
||||
import com.navi.ap.common.models.CustomWidgets
|
||||
@@ -50,6 +51,12 @@ class CustomUiTronDataSerializer : UiTronDataSerializer() {
|
||||
)
|
||||
}
|
||||
|
||||
CustomWidgets.CALENDAR_WIDGET.name -> {
|
||||
context?.serialize(
|
||||
src as CalendarWidgetData, CalendarWidgetData::class.java
|
||||
)
|
||||
}
|
||||
|
||||
else -> super.serialize(src, typeOfSrc, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.navi.ap.common.widgetfactory
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.navi.ap.common.models.CustomWidgets
|
||||
import com.navi.ap.common.models.WidgetModelDefinition
|
||||
import com.navi.ap.common.renderer.CalendarWidget
|
||||
import com.navi.ap.common.renderer.CardWithHeaderFooterAndLazyColumnWidget
|
||||
import com.navi.ap.common.renderer.CollapsableItemsWithTitleWidget
|
||||
import com.navi.ap.common.renderer.DynamicColumnWidget
|
||||
@@ -21,18 +22,30 @@ fun CustomWidgetRenderer(
|
||||
CustomWidgets.COLLAPSABLE_ITEMS_WITH_TITLE_WIDGET.name -> {
|
||||
CollapsableItemsWithTitleWidget().Render(viewModel = viewModel, widget = widget)
|
||||
}
|
||||
|
||||
CustomWidgets.DYNAMIC_COLUMN_WIDGET.name -> {
|
||||
DynamicColumnWidget().Render(viewModel = viewModel, widget = widget)
|
||||
}
|
||||
|
||||
CustomWidgets.DYNAMIC_ROW_WIDGET.name -> {
|
||||
DynamicRowWidget().Render(viewModel = viewModel, widget = widget)
|
||||
}
|
||||
|
||||
CustomWidgets.DYNAMIC_GRID_WIDGET.name -> {
|
||||
DynamicGridWidget().Render(viewModel = viewModel, widget = widget)
|
||||
}
|
||||
|
||||
CustomWidgets.CARD_WITH_HEADER_FOOTER_AND_LAZY_COLUMN_WIDGET.name -> {
|
||||
CardWithHeaderFooterAndLazyColumnWidget().Render(applicationPlatformVM = viewModel,widget = widget)
|
||||
CardWithHeaderFooterAndLazyColumnWidget().Render(
|
||||
applicationPlatformVM = viewModel,
|
||||
widget = widget
|
||||
)
|
||||
}
|
||||
|
||||
CustomWidgets.CALENDAR_WIDGET.name -> {
|
||||
CalendarWidget().Render(viewModel = viewModel, widget = widget)
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,9 +40,11 @@ interface PlLambdaService {
|
||||
|
||||
@GET("/customer/offer-details")
|
||||
suspend fun getOfferDetails(
|
||||
@Query("offerType") offerType: String? = null,
|
||||
@Query("amount") amount: String? = null,
|
||||
@Query("tenureInMonths") tenureInMonths: String? = null,
|
||||
@Query("emiPlansSelected") emiPlansSelected: String? = null,
|
||||
@Query("fetchEmiDates") fetchEmiDates: Boolean? = null,
|
||||
@Header("X-Target") target: String = ModuleName.LE.name,
|
||||
): Response<GenericResponse<Any>>
|
||||
|
||||
@@ -53,6 +55,7 @@ interface PlLambdaService {
|
||||
@Query("emiPlansSelected") emiPlansSelected: String? = null,
|
||||
@Header("X-Target") target: String = ModuleName.LE.name,
|
||||
): Response<GenericResponse<Any>>
|
||||
|
||||
@POST("/offer/{offerReferenceId}/apply")
|
||||
suspend fun applyLoan(
|
||||
@Header("X-Target") target: String = ModuleName.LE.name,
|
||||
|
||||
@@ -76,4 +76,9 @@ val noLoaderScreenTypes: MutableSet<String> = mutableSetOf(
|
||||
const val SUCCESS_CODE = 200
|
||||
const val FAILURE = "failure"
|
||||
const val HIDE_LOADER_STATE_ID = "hide_loader_state_id"
|
||||
const val CUSTOMER_CAPITAL = "CUSTOMER"
|
||||
const val SELECTED_RAW_DATE = "selectedRawDate"
|
||||
const val CUSTOMER_CAPITAL = "CUSTOMER"
|
||||
const val SELECTED_DATE = "selectedDate"
|
||||
const val SELECTED_DATE_WITH_SUFFIX = "selectedDateWithSuffix"
|
||||
const val SELECTED_FORMATTED_DATE = "selectedFormattedDate"
|
||||
const val SHOW = "show"
|
||||
@@ -68,12 +68,14 @@ enum class LambdaType {
|
||||
POST_PAYMENT_METHOD_STATUS,
|
||||
VALIDATE_COINS_UPI_ID,
|
||||
FETCH_EMI_CALENDER_DETAILS,
|
||||
DOWNLOAD_LOAN_AGREEMENT_AND_SANCTION_LETTER
|
||||
|
||||
DOWNLOAD_LOAN_AGREEMENT_AND_SANCTION_LETTER,
|
||||
FETCH_CALENDER_DETAILS,
|
||||
}
|
||||
|
||||
enum class ApplicationType{
|
||||
PL,
|
||||
PL_REFILL,
|
||||
COINS
|
||||
COINS,
|
||||
PL_REPEAT,
|
||||
PL_TOP_UP,
|
||||
PL_REFILL
|
||||
}
|
||||
@@ -47,4 +47,7 @@ const val DEFAULT_BANKS_SEARCH_QUERY = ""
|
||||
const val TRIGGER_LOADING_STATE = "trigger_loading_state"
|
||||
const val SUCCESS_CAP = "SUCCESS"
|
||||
const val FAILURE_CAP = "FAILURE"
|
||||
const val DOCUMENT_TYPE = "documentType"
|
||||
const val DOCUMENT_TYPE = "documentType"
|
||||
const val LOAN_APPLICATION_REFERENCE_ID = "loan_application_id"
|
||||
const val OFFER_TYPE = "offerType"
|
||||
const val FETCH_EMI_DATES = "fetchEmiDates"
|
||||
@@ -6,7 +6,7 @@ import java.util.Stack
|
||||
|
||||
|
||||
/**
|
||||
* Use this to inject values with place holder pattern "key" : "${place_holder}"
|
||||
* Use this to inject values with place holder pattern "key" : "@{place_holder}"
|
||||
* place_holder will get replaced with corresponding values in FieldObjectType.
|
||||
**/
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.util.Stack
|
||||
class FieldInjector<U, V>() : Injector<U, V>() {
|
||||
|
||||
override val placeHolderPattern: String
|
||||
get() = "\${place_holder_name}"
|
||||
get() = "@\${place_holder_name}"
|
||||
|
||||
override fun replacePlaceHolders(configObj: JSONObject, dataObject : JSONObject) {
|
||||
val dataMap = jsonNodeToMappedValues(dataObject)
|
||||
@@ -55,7 +55,7 @@ class FieldInjector<U, V>() : Injector<U, V>() {
|
||||
dataMap: Map<String, Any?>
|
||||
) {
|
||||
val value = currentObject.get(key)
|
||||
if (value is String && value.startsWith('$') && value.length > 3) {
|
||||
if (value is String && value.startsWith('@') && value.length > 3) {
|
||||
val trimmedValue = value.trim()
|
||||
val placeHolderKey = trimmedValue.substring(2, trimmedValue.length - 1)
|
||||
currentObject.putOpt(key, dataMap[placeHolderKey])
|
||||
|
||||
Reference in New Issue
Block a user