TP-84151 | Waiting Period Screen + Atomic Components Action Handling cleanup (#12576)

Co-authored-by: Somarapu Vamshi <somarapu.vamshi@navi.com>
This commit is contained in:
Kshitij Pramod Ghongadi
2024-09-24 23:09:17 +05:30
committed by GitHub
parent 6d8f1b2933
commit ab74346b98
36 changed files with 797 additions and 143 deletions

View File

@@ -2,5 +2,6 @@ export { default as QuoteOfferScreen } from "./screen/quote-offer-screen/QuoteOf
export { default as QuoteApologyScreen } from "./screen/quote-apology-screen/QuoteApologyScreen";
export { default as ComparePlanScreen } from "./screen/compare-plan-screen/ComparePlanScreen";
export { default as MarketBenefitCompareScreen } from "./screen/market-benefit-compare-screen/MarketBenefitCompareScreen";
export { default as WaitingPeriodScreen } from "./screen/waiting-period-screen/WaitingPeriodScreen";
export { default as GenericShimmerScreen } from "./screen/generic-shimmer-screen/GenericShimmerScreen";
export { default as GenericErrorScreen } from "./screen/generic-error-screen/GenericErrorScreen";

View File

@@ -0,0 +1,39 @@
import { Dispatch, SetStateAction } from "react";
import { getXTargetHeaderInfo } from "../../../../network/ApiClient";
import { get } from "../../../../network/NetworkService";
import { ActionMetaData } from "../../../common/actions/GenericAction";
import {
AnalyticsFlowNameConstant,
AnalyticsMethodNameConstant,
GI,
} from "../../../common/constants";
import { CtaData } from "../../../common/interface";
import { ScreenData } from "../../../common/interface/widgets/screenData/ScreenData";
import {
handleErrorData,
handleResponseData,
} from "../../../common/screen/ScreenActionHandler";
import { ScreenActionTypes } from "../../../common/screen/ScreenActionTypes";
export const getWaitingPeriodScreenData = async (
screenMetaData: ActionMetaData,
setScreenData: Dispatch<SetStateAction<ScreenData | null>>,
) => {
const url = "waiting-period";
return get<ApiResponse<CtaData>>(
url,
getXTargetHeaderInfo(GI.toLocaleUpperCase()),
)
.then(response => {
handleResponseData(setScreenData, response);
})
.catch(error => {
handleErrorData(
error,
setScreenData,
screenMetaData,
AnalyticsFlowNameConstant.GI_WAITING_PERIOD,
AnalyticsMethodNameConstant.WAITING_PERIOD_SCREEN,
ScreenActionTypes.FETCH_WAITING_PERIOD_SCREEN,
);
});
};

View File

@@ -1,2 +1,3 @@
export * from "./MarketBenefitComparePageApi";
export * from "./WaitingPeriodApi";
export * from "./QuotePageApi";
export * from "./MarketBenefitComparePageApi";

View File

@@ -1,25 +1,25 @@
import { useNavigation } from "@react-navigation/native";
import React, { useEffect } from "react";
import { ScrollView, Text, View } from "react-native";
import { CtaData, CtaType } from "../../../../common/interface";
import { ScreenData } from "../../../../common/interface/widgets/screenData/ScreenData";
import { BackHandler, ScrollView, View } from "react-native";
import BaseWidget from "../../../../../components/widgets/BaseWidget";
import {
BaseActionTypes,
GenericActionPayload,
} from "../../../../common/actions/GenericAction";
import { ScreenActionTypes } from "../../../../common/screen/ScreenActionTypes";
import { Widget } from "../../../../common/interface/widgets/Widget";
import { ScreenState } from "../../../../common/screen/BaseScreen";
import BaseWidget from "../../../../../components/widgets/BaseWidget";
import { COMPARE_PLAN_SCREEN, ConstantCta } from "../../../../common/constants";
import { logToSentry } from "../../../../common/hooks/useSentryLogging";
import { CtaData, CtaType } from "../../../../common/interface";
import { Widget } from "../../../../common/interface/widgets/Widget";
import { ScreenData } from "../../../../common/interface/widgets/screenData/ScreenData";
import { NativeDeeplinkNavigatorModule } from "../../../../common/native-module/NativeModules";
import { useNavigation } from "@react-navigation/native";
import ComparePlanShimmerScreen from "./shimmer-screen/ComparePlanShimmerScreen";
import {
CtaNavigator,
extractCtaParameters,
} from "../../../../common/navigator/NavigationRouter";
import { ScreenState } from "../../../../common/screen/BaseScreen";
import { ScreenActionTypes } from "../../../../common/screen/ScreenActionTypes";
import QuoteOfferErrorScreen from "../quote-offer-screen/error-screen/QuoteOfferErrorScreen";
import { COMPARE_PLAN_SCREEN, ConstantCta } from "../../../../common/constants";
import ComparePlanShimmerScreen from "./shimmer-screen/ComparePlanShimmerScreen";
const ComparePlanScreen = ({
ctaData,
@@ -52,6 +52,13 @@ const ComparePlanScreen = ({
case CtaType.RN_NAVIGATOR:
CtaNavigator.performNavigation(navigation, navigatorType, cta);
break;
case CtaType.GO_BACK:
if (navigation.canGoBack()) {
navigation.goBack();
} else {
BackHandler.exitApp();
}
break;
default:
NativeDeeplinkNavigatorModule.navigateToNaviDeeplinkNavigator(
JSON.stringify(cta),

View File

@@ -3,46 +3,20 @@ import SkeletonPlaceholder from "react-native-skeleton-placeholder";
import Colors from "../../../../../assets/colors/colors";
import { StaticHeader } from "../../../../../components/reusable/static-header/StaticHeader";
import { ConstantCta } from "../../../../common/constants/CtaConstants";
import { logToSentry } from "../../../../common/hooks/useSentryLogging";
import { CtaData, CtaType } from "../../../../common/interface";
import { NativeDeeplinkNavigatorModule } from "../../../../common/native-module/NativeModules";
import { CtaData } from "../../../../common/interface";
import styles from "./GenericShimmerScreenStyle";
const GenericShimmerScreen = () => {
const handleClick = (cta?: CtaData) => {
if (!cta) {
logToSentry(
`Navigation cta is missing or invalid: ${cta} | MethodName: handleClick}`,
);
return;
}
try {
switch (cta.type) {
case CtaType.DEEP_LINK:
case CtaType.USE_ROOT_DEEPLINK_NAVIGATOR:
NativeDeeplinkNavigatorModule.navigateToNaviInsuranceDeeplinkNavigator(
JSON.stringify(cta),
);
break;
default:
NativeDeeplinkNavigatorModule.navigateToNaviDeeplinkNavigator(
JSON.stringify(cta),
);
break;
}
} catch (error) {
logToSentry(
`Error while navigating to deep link with CTA: ${cta} | MethodName: handleClick}`,
);
}
};
const GenericShimmerScreen = ({
handleClick,
}: {
handleClick: (cta: CtaData) => void;
}) => {
return (
<View style={styles.container}>
<View style={styles.header}>
<StaticHeader
handleClick={handleClick}
leftIconCta={ConstantCta.STATIC_HEADER_LEFT_ICON_CTA}
leftIconCta={ConstantCta.GO_BACK_CTA}
/>
</View>
<ContentShimmer />

View File

@@ -167,7 +167,7 @@ const MarketBenefitCompareScreen = ({
}, [screenData?.screenState]);
if (screenData?.screenState === ScreenState.LOADING) {
return <GenericShimmerScreen />;
return <GenericShimmerScreen handleClick={handleClick} />;
}
if (screenData?.screenState === ScreenState.ERROR) {

View File

@@ -0,0 +1,240 @@
import { useNavigation } from "@react-navigation/native";
import React, { useEffect } from "react";
import {
BackHandler,
NativeScrollEvent,
NativeSyntheticEvent,
View,
} from "react-native";
import Animated, {
useAnimatedStyle,
useSharedValue,
} from "react-native-reanimated";
import BaseWidget from "../../../../../components/widgets/BaseWidget";
import {
BaseActionTypes,
GenericActionPayload,
} from "../../../../common/actions/GenericAction";
import {
AnalyticsEventNameConstants,
AnalyticsMethodNameConstant,
ConstantCta,
INITIAL_Y_VALUE,
NAVIGATION_ERROR,
WAITING_PERIOD_SCREEN,
} from "../../../../common/constants";
import { sendAsAnalyticsEvent } from "../../../../common/hooks/useAnalyticsEvent";
import { AnalyticsEvent, CtaData, CtaType } from "../../../../common/interface";
import { Widget } from "../../../../common/interface/widgets/Widget";
import { ScreenData } from "../../../../common/interface/widgets/screenData/ScreenData";
import { NativeDeeplinkNavigatorModule } from "../../../../common/native-module/NativeModules";
import {
CtaNavigator,
extractCtaParameters,
} from "../../../../common/navigator/NavigationRouter";
import { ScreenState } from "../../../../common/screen/BaseScreen";
import { ScreenActionTypes } from "../../../../common/screen/ScreenActionTypes";
import GenericShimmerScreen from "../generic-shimmer-screen/GenericShimmerScreen";
import QuoteOfferErrorScreen from "../quote-offer-screen/error-screen/QuoteOfferErrorScreen";
import styles from "./WaitingPeriodScreenStyles";
const WaitingPeriodScreen = ({
ctaData,
screenData,
handleActions,
}: {
ctaData: CtaData;
screenData: ScreenData | null;
handleActions: (screenPayload?: GenericActionPayload) => void;
}) => {
const navigation = useNavigation();
const y = useSharedValue(INITIAL_Y_VALUE);
const onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
y.value = event.nativeEvent.contentOffset.y;
};
const handleClick = (cta?: CtaData) => {
if (!cta) {
const errorEvent: AnalyticsEvent = {
name: AnalyticsEventNameConstants.HI_INVALID_SCREEN_CTA,
properties: {
screenName: WAITING_PERIOD_SCREEN,
methodName: AnalyticsMethodNameConstant.HANDLE_CTA_CLICK,
},
};
sendAsAnalyticsEvent(errorEvent);
return;
}
const { navigatorType } = extractCtaParameters(cta);
try {
switch (cta.type) {
case CtaType.DEEP_LINK:
case CtaType.USE_ROOT_DEEPLINK_NAVIGATOR:
NativeDeeplinkNavigatorModule.navigateToNaviInsuranceDeeplinkNavigator(
JSON.stringify(cta),
);
break;
case CtaType.RN_NAVIGATOR:
CtaNavigator.performNavigation(navigation, navigatorType, cta);
break;
case CtaType.GO_BACK:
if (navigation.canGoBack()) {
navigation.goBack();
} else {
BackHandler.exitApp();
}
break;
default:
NativeDeeplinkNavigatorModule.navigateToNaviDeeplinkNavigator(
JSON.stringify(cta),
);
break;
}
} catch (error) {
const errorEvent: AnalyticsEvent = {
name: AnalyticsEventNameConstants.HI_INVALID_SCREEN_CTA,
properties: {
screenName: WAITING_PERIOD_SCREEN,
methodName: AnalyticsMethodNameConstant.HANDLE_CTA_CLICK,
reason: NAVIGATION_ERROR,
},
};
sendAsAnalyticsEvent(errorEvent);
}
};
useEffect(() => {
handleActions({
baseActionType: BaseActionTypes.SCREEN_ACTION,
metaData: [
{
actionType: ScreenActionTypes.FETCH_WAITING_PERIOD_SCREEN,
data: ctaData?.data,
screenName: WAITING_PERIOD_SCREEN,
},
],
});
}, [ctaData]);
const headerStyle = useAnimatedStyle(() => {
return {
shadowColor: y.value > 1 ? "black" : "transparent",
shadowOpacity: y.value > 1 ? 1 : 0,
shadowRadius: y.value > 1 ? 8 : 0,
elevation: y.value > 1 ? 32 : 0,
};
});
const Header = () => {
return (
<Animated.View style={[styles.header, headerStyle]}>
{getWidgetViews(
screenData?.screenWidgets?.headerWidgets,
handleActions,
screenData?.screenState,
handleClick,
)}
</Animated.View>
);
};
const ContentWidgets = () => {
return getWidgetViews(
screenData?.screenWidgets?.contentWidgets,
handleActions,
screenData?.screenState,
handleClick,
);
};
const Footer = () => {
return (
<View style={styles.footer}>
{getWidgetViews(
screenData?.screenWidgets?.footerWidgets,
handleActions,
screenData?.screenState,
handleClick,
)}
</View>
);
};
useEffect(() => {
switch (screenData?.screenState) {
case ScreenState.LOADED:
const initEvent: AnalyticsEvent = {
name: AnalyticsEventNameConstants.HI_RN_WAITING_PERIOD_PAGE_INIT,
};
sendAsAnalyticsEvent(initEvent);
break;
case ScreenState.ERROR:
const errorEvent: AnalyticsEvent = {
name: AnalyticsEventNameConstants.HI_RN_WAITING_PERIOD_PAGE_ERROR_VIEW,
};
sendAsAnalyticsEvent(errorEvent);
break;
default:
break;
}
}, [screenData?.screenState]);
if (screenData?.screenState === ScreenState.LOADING) {
return <GenericShimmerScreen handleClick={handleClick} />;
}
if (screenData?.screenState === ScreenState.ERROR) {
return (
<QuoteOfferErrorScreen
errorMetaData={screenData.errorMetaData}
handleActions={handleActions}
handleClick={handleClick}
headerProperties={{
leftIconCta: ConstantCta.GO_BACK_CTA,
rightIconCta: ConstantCta.STATIC_HEADER_RIGHT_ICON_CTA,
}}
/>
);
}
return (
<View style={[styles.container, screenData?.screenStyle]}>
<Header />
<Animated.ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.content}
nestedScrollEnabled={true}
onScroll={onScroll}
>
<ContentWidgets />
</Animated.ScrollView>
<Footer />
</View>
);
};
function getWidgetViews(
widgetList: Widget[] | undefined,
handleActions: (screenActionPayload?: GenericActionPayload) => void,
screenState?: ScreenState | null,
handleClick?: (ctaData: CtaData) => void,
): React.JSX.Element {
return (
<View>
{widgetList?.map((widget, index) => {
return (
<BaseWidget
widget={widget}
handleScreenActions={handleActions}
screenState={screenState}
widgetIndex={index}
key={index}
handleClick={handleClick}
/>
);
})}
</View>
);
}
export default WaitingPeriodScreen;

View File

@@ -0,0 +1,22 @@
import { StyleSheet } from "react-native";
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
},
header: {
width: "100%",
alignItems: "stretch",
backgroundColor: "#FFFFFF",
zIndex: 1,
},
content: {
flexGrow: 1,
},
footer: {
alignItems: "stretch",
},
});
export default styles;

View File

@@ -5,7 +5,10 @@ export const AnalyticsEventNameConstants = {
HI_RN_BENEFIT_COMPARE_PAGE_INIT: "hi_rn_benefit_compare_page_init",
HI_RN_BENEFIT_COMPARE_PAGE_ERROR_VIEW:
"hi_rn_benefit_compare_page_error_view",
HI_RN_WAITING_PERIOD_PAGE_INIT: "hi_rn_waiting_period_page_init",
HI_RN_WAITING_PERIOD_PAGE_ERROR_VIEW: "hi_rn_waiting_period_page_error_view",
PATCH_QUOTE_V2: "patch_quote_v2",
HI_INVALID_SCREEN_CTA: "hi_invalid_screen_cta",
};
export const AnalyticsEventPropertyConstants = {
@@ -19,6 +22,7 @@ export const AnalyticsEventPropertyConstants = {
export const AnalyticsFlowNameConstant = {
GI_RN_QUOTE: "GiRnQuote",
GI_RN_BENEFIT_COMPARE: "GiRnBenefitCompare",
GI_WAITING_PERIOD: "GiWaitingPeriod",
REACT_NATIVE: "ReactNative",
};
@@ -33,6 +37,8 @@ export const AnalyticsMethodNameConstant = {
FINAL_PATCH_CALL: "finalPatchCall",
COMPARE_PLAN_LIST: "comparePlanList",
MARKET_BENEFIT_COMPARE_LIST: "gi_market_benefit_compare_list_error",
WAITING_PERIOD_SCREEN: "gi_waiting_period_screen_error",
HANDLE_CTA_CLICK: "handleCtaClick",
};
export const AnalyticsGlobalErrorTypeConstant = {

View File

@@ -4,13 +4,7 @@ export const ConstantCta = {
},
GO_BACK_CTA: {
url: "",
type: "RN_NAVIGATOR",
parameters: [
{
key: "RnNavigatorType",
value: "goBack",
},
],
type: "GO_BACK",
},
STATIC_HEADER_RIGHT_ICON_CTA: {
url: "PRODUCT_HELP_PAGE",

View File

@@ -1,3 +1,4 @@
export const HEADER_LOTTIE_WIDGET_HEIGHT = 180;
export const HEADER_LOTTIE_TITLE_HEIGHT = 84;
export const BOTTOMSHEET_ANIMATION_DURATION = 200;
export const BOTTOMSHEET_ANIMATION_DURATION = 200;
export const INITIAL_Y_VALUE = 0;

View File

@@ -9,3 +9,4 @@ export const BUY_INSURANCE_SCREEN = "buyinsurance";
export const QUOTE_APOLOGY_SCREEN = "fresh_policy_form";
export const MARKET_BENEFITS_COMPARE_SCREEN = "market_benefits_compare";
export const COMPARE_PLAN_SCREEN = "compare_plans";
export const WAITING_PERIOD_SCREEN = "waiting_period";

View File

@@ -46,6 +46,7 @@ export const APPLICATION_ID = "applicationId";
export const BUILD_CONFIG_DETAILS = "BUILD_CONFIG_DETAILS";
export const SPACE_UNICODE = "\u00A0";
export const REACT_NATIVE = "rn";
export const NAVIGATION_ERROR = "Navigation Error";
export enum SeparatorType {
DASHED = "dashed",

View File

@@ -11,12 +11,17 @@ export const TITLE_WITH_ASSETS_WIDGET = "TITLE_WITH_ASSETS_WIDGET";
export const HEADER_WITH_ASSETS_WIDGET = "HEADER_WITH_ASSETS_WIDGET";
export const HEADER_LOTTIE_ANIMATION_WIDGET = "HEADER_LOTTIE_ANIMATION_WIDGET";
export const SUM_INSURED_WIDGET = "SUM_INSURED_WIDGET";
export const TITLE_SUBTITLE_WITH_ASSET_WIDGET = "TITLE_SUBTITLE_WITH_ASSET_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";
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";
export const TABLE_WIDGET = "TABLE_WIDGET";
export const HERO_SECTION_WIDGET = "HERO_SECTION_WIDGET";
export const SELECT_CARD_WITH_DETAIL_LIST_WIDGET = "SELECT_CARD_WITH_DETAIL_LIST_WIDGET";
export const SELECT_CARD_WITH_DETAIL_LIST_WIDGET =
"SELECT_CARD_WITH_DETAIL_LIST_WIDGET";
export const TITLE_RIGHT_TITLE_WITH_CONTENT_LIST_WIDGET =
"TITLE_RIGHT_TITLE_WITH_CONTENT_LIST_WIDGET";

View File

@@ -6,6 +6,7 @@ import { ImageFieldData, TextFieldData } from "./TitleWidgetData";
export interface HeroSectionWidgetData extends GenericWidgetData {
title?: TextFieldData;
subtitle?: TextFieldData;
image?: ImageFieldData;
backgroundGradient?: string[];
gradientOrientation?: string;

View File

@@ -0,0 +1,41 @@
import { ViewStyle } from "react-native";
import { CtaData } from "../..";
import { GenericActionPayload } from "../../../actions/GenericAction";
import { GenericWidgetData } from "../Widget";
import { TextFieldData } from "./TitleWidgetData";
import { ItemSeparatorData } from "../../components/ItemSeparatorData";
export interface TitleRightTitleWithContentListWidgetData
extends GenericWidgetData {
listData?: TitleRightTitleWithContentListWidgetDataItem[];
separatorData?: ItemSeparatorData;
}
export interface TitleRightTitleWithContentListWidgetProps {
widgetData: TitleRightTitleWithContentListWidgetData;
widgetStyle?: ViewStyle;
handleActions: (
value: any | undefined | null,
actionPayloadList: GenericActionPayload | undefined,
) => void;
handleClick?: (cta: CtaData) => void;
widgetIndex?: number;
}
export interface TitleRightTitleWithContentListWidgetDataItem {
id?: string;
title?: TextFieldData;
rightTitle?: TextFieldData;
subtitle?: TextFieldData;
content?: TextFieldData;
action?: GenericActionPayload;
}
export interface TitleRightTitleWithContentListWidgetDataItemProps {
item: TitleRightTitleWithContentListWidgetDataItem;
handleActions: (
value: any | undefined | null,
actionPayloadList: GenericActionPayload | undefined,
) => void;
handleClick?: (cta: CtaData) => void;
}

View File

@@ -43,6 +43,7 @@ export interface ImageFieldData {
url: string;
imageStyle?: ImageStyle;
cta?: CtaData;
actions?: GenericActionPayload;
}
export interface LottieFieldData {
@@ -52,4 +53,5 @@ export interface LottieFieldData {
lottieStyle?: ImageStyle;
cta?: CtaData;
delayAnimationBy?: number;
actions?: GenericActionPayload;
}

View File

@@ -19,6 +19,11 @@ export type {
CellProps,
} from "./TableWidgetData";
export type { HeroSectionWidgetData } from "./HeroSectionWidgetData";
export type {
HeroSectionWidgetData
} from "./HeroSectionWidgetData"
TitleRightTitleWithContentListWidgetData,
TitleRightTitleWithContentListWidgetProps,
TitleRightTitleWithContentListWidgetDataItem,
TitleRightTitleWithContentListWidgetDataItemProps,
} from "./TitleRightTitleWithContentListWidgetData";

View File

@@ -4,18 +4,16 @@ import {
fetchComparisonPlanList,
getMarketBenefitComparePageData,
getQuotePageData,
getWaitingPeriodScreenData,
} from "../../Container/Navi-Insurance/network";
import { ActionMetaData, BaseActionTypes } from "../actions/GenericAction";
import { ScreenData } from "../interface/widgets/screenData/ScreenData";
import { ScreenState } from "./BaseScreen";
import { ScreenActionTypes } from "./ScreenActionTypes";
import {
AnalyticsModuleNameConstant,
AnalyticsFlowNameConstant,
} from "../constants";
import { AnalyticsModuleNameConstant } from "../constants";
import { sendAsGlobalErrorEvent } from "../hooks/useAnalyticsEvent";
import { logToSentry } from "../hooks/useSentryLogging";
import { ScreenData } from "../interface/widgets/screenData/ScreenData";
import { getErrorTypeFromStatusCode } from "../utilities/ErrorUtils";
import { ScreenState } from "./BaseScreen";
import { ScreenActionTypes } from "./ScreenActionTypes";
export const ScreenActionHandler = {
handleScreenAction: (
@@ -42,6 +40,9 @@ export const ScreenActionHandler = {
case ScreenActionTypes.FETCH_BENEFIT_COMPARE_LIST: {
return getMarketBenefitComparePageData(screenMetaData, setScreenData);
}
case ScreenActionTypes.FETCH_WAITING_PERIOD_SCREEN: {
return getWaitingPeriodScreenData(screenMetaData, setScreenData);
}
case ScreenActionTypes.SHOW_LOADER: {
const updatedScreenData: ScreenData = {
...screenData,

View File

@@ -6,4 +6,5 @@ export const ScreenActionTypes = {
SHOW_LOADER: "SHOW_LOADER",
FETCH_BENEFIT_COMPARE_LIST: "FETCH_BENEFIT_COMPARE_LIST",
FETCH_COMPARE_PLAN_LIST: "FETCH_COMPARE_PLAN_LIST",
FETCH_WAITING_PERIOD_SCREEN: "FETCH_WAITING_PERIOD_SCREEN",
};

View File

@@ -4,6 +4,7 @@ import {
MarketBenefitCompareScreen,
QuoteApologyScreen,
QuoteOfferScreen,
WaitingPeriodScreen,
} from "../../../Container/Navi-Insurance";
import { GenericActionPayload } from "../../actions/GenericAction";
import {
@@ -12,6 +13,7 @@ import {
MARKET_BENEFITS_COMPARE_SCREEN,
QUOTE_APOLOGY_SCREEN,
QUOTE_OFFER_SCREEN,
WAITING_PERIOD_SCREEN,
} from "../../constants";
import { logToSentry } from "../../hooks/useSentryLogging";
import { CtaData } from "../../interface";
@@ -60,6 +62,14 @@ export const GIScreenMapper = {
handleActions={handleActions}
/>
);
case WAITING_PERIOD_SCREEN:
return (
<WaitingPeriodScreen
ctaData={ctaData}
screenData={screenData}
handleActions={handleActions}
/>
);
default: {
return <View />;
}

View File

@@ -0,0 +1,14 @@
import throttle from "lodash/throttle";
import { GenericActionPayload } from "../actions/GenericAction";
export const createThrottledHandler = (
handleActions: (action?: GenericActionPayload) => void,
delay: number,
options = { leading: true, trailing: false },
) => {
return throttle(
(action?: GenericActionPayload) => handleActions(action),
delay,
options,
);
};

View File

@@ -1,25 +1,26 @@
import { View, ViewStyle } from "react-native";
import {
CardWithIconWidget,
ComparisonWidget,
FAB,
FooterWithCardWidget,
GridWithCardWidget,
HeaderLottieAnimationWidget,
HeaderWithAssetsWidget,
HeroSectionWidget,
SelectCardWithDetailListWidget,
SliderWidget,
SpacerWidget,
SumInsuredWidget,
TableWidget,
TitleRightTitleWithContentListWidget,
TitleSubtitleWithAssetWidget,
TitleWidget,
TitleWithAssetBackgroundWidget,
HeroSectionWidget
TitleWithAssetsWidget,
TitleWithColumnWidget,
TitleWithListWidget,
} from "../../../components/widgets";
import ComparisonWidget from "../../../components/widgets/ComparisonWidget";
import HeaderLottieAnimationWidget from "../../../components/widgets/HeaderLottieAnimationWidget";
import HeaderWithAssetsWidget from "../../../components/widgets/HeaderWithAssetsWidget";
import SliderWidget from "../../../components/widgets/SliderWidget";
import TitleWithAssetsWidget from "../../../components/widgets/TitleWithAssetsWidget";
import CardWithIconWidget from "../../../components/widgets/card-with-icon-widget/CardWithIconWidget";
import FAB from "../../../components/widgets/fab/FAB";
import FooterWithCardWidget from "../../../components/widgets/footer-with-card-widget/FooterWithCardWidget";
import GridWithCardWidget from "../../../components/widgets/grid-with-card-widget/GridWithCardWidget";
import SpacerWidget from "../../../components/widgets/spacer-widget/SpacerWidget";
import SumInsuredWidget from "../../../components/widgets/sum-insured-carousel-widget/SumInsuredWidget";
import TitleSubtitleWithAssetWidget from "../../../components/widgets/title-subtitle-with-asset-widget/TitleSubtitleWithAssetWidget";
import TitleWidget from "../../../components/widgets/title-widget/TitleWidget";
import { TitleWithColumnWidget } from "../../../components/widgets/title-with-column-widget/TitleWithColumnWidget";
import TitleWithListWidget from "../../../components/widgets/title-with-list-widget/TitleWithListWidget";
import { GenericActionPayload } from "../actions/GenericAction";
import {
CARD_WITH_ICON_WIDGET,
@@ -35,6 +36,7 @@ import {
SPACER_WIDGET,
SUM_INSURED_WIDGET,
TABLE_WIDGET,
TITLE_RIGHT_TITLE_WITH_CONTENT_LIST_WIDGET,
TITLE_SUBTITLE_WITH_ASSET_WIDGET,
TITLE_WIDGET,
TITLE_WITH_ASSETS_WIDGET,
@@ -284,6 +286,17 @@ function resolveWidgetView(
handleClick={handleClick}
/>
);
case TITLE_RIGHT_TITLE_WITH_CONTENT_LIST_WIDGET:
return (
<TitleRightTitleWithContentListWidget
widgetData={widgetData}
widgetStyle={widgetStyle}
handleActions={handleActions}
widgetIndex={widgetIndex}
key={widgetIndex}
handleClick={handleClick}
/>
);
default:
return <View />;
}

Binary file not shown.

View File

@@ -1,6 +1,10 @@
{
"migIndex": 1,
"data": [
{
"path": "assets/fonts/tt_bold.otf",
"sha1": "ca3a9a379963ee468eb61022cd5d7ddc41286657"
},
{
"path": "assets/fonts/tt_medium.ttf",
"sha1": "97ae9273c19e455a0d807e38113277ee75ad11c7"

BIN
assets/fonts/tt_bold.otf Normal file

Binary file not shown.

View File

@@ -3,29 +3,42 @@ import { ImageFieldData } from "../App/common/interface/widgets/widgetData/Title
import { Image } from "react-native";
import { TouchableOpacity } from "react-native-gesture-handler";
import { CtaData } from "../App/common/interface";
import { GenericActionPayload } from "../App/common/actions/GenericAction";
export const StyledImage = ({
imageFieldData,
handleClick,
handleActions,
}: {
imageFieldData: ImageFieldData;
handleClick?: (ctaData: CtaData) => void;
handleActions?: (
value: any | undefined | null,
actionPayloadList: GenericActionPayload | undefined,
) => void;
}) => {
if (!imageFieldData?.url) return <></>;
return imageFieldData?.cta ? (
const { cta, actions } = imageFieldData;
const handleImageClick = () => {
if (actions && handleActions) {
handleActions(null, actions);
} else if (cta && handleClick) {
handleClick(cta);
}
};
return (
<TouchableOpacity
onPress={() => handleClick && handleClick(imageFieldData?.cta!!)}
disabled={!(cta || actions)}
activeOpacity={1}
onPress={handleImageClick}
>
<Image
source={{ uri: imageFieldData?.url }}
style={imageFieldData?.imageStyle}
/>
</TouchableOpacity>
) : (
<Image
source={{ uri: imageFieldData?.url }}
style={imageFieldData?.imageStyle}
/>
);
};

View File

@@ -19,9 +19,14 @@ const HeroSectionWidget = ({
>
<View style={styles.container}>
<View style={styles.rowContainer}>
{widgetData?.title?.text && (
<StyledText textFieldData={widgetData?.title} />
)}
<View style={styles.columnContainer}>
{widgetData?.title?.text && (
<StyledText textFieldData={widgetData?.title} />
)}
{widgetData?.subtitle?.text && (
<StyledText textFieldData={widgetData?.subtitle} />
)}
</View>
{widgetData?.image?.url && (
<StyledImage imageFieldData={widgetData?.image} />
)}

View File

@@ -9,7 +9,13 @@ const styles = StyleSheet.create({
},
rowContainer: {
flexDirection: "row",
justifyContent: "space-between"
justifyContent: "space-between",
},
columnContainer: {
flexDirection: "column",
alignItems: "flex-start",
flexGrow: 1,
flexBasis: 0,
},
calloutContainer: {
flexShrink: 1,

View File

@@ -1,8 +1,22 @@
export { StyledText } from "./styled-text/StyledText";
export { StyledImage } from "../StyledImage";
export { default as TitleWidget } from "./title-widget/TitleWidget";
export { default as ComparisonWidget } from "./ComparisonWidget";
export { default as HeaderLottieAnimationWidget } from "./HeaderLottieAnimationWidget";
export { default as HeaderWithAssetsWidget } from "./HeaderWithAssetsWidget";
export { default as SliderWidget } from "./SliderWidget";
export { default as TitleWithAssetsWidget } from "./TitleWithAssetsWidget";
export { default as CardWithIconWidget } from "./card-with-icon-widget/CardWithIconWidget";
export { default as FAB } from "./fab/FAB";
export { default as FooterWithCardWidget } from "./footer-with-card-widget/FooterWithCardWidget";
export { default as TitleWithAssetBackgroundWidget } from "./title-with-asset-background/TitleWithAssetBackground";
export { default as SelectCardWithDetailListWidget } from "./select-card-with-detail-list/SelectCardWithDetailList";
export { default as TableWidget } from "./table-widget/Table";
export { default as GridWithCardWidget } from "./grid-with-card-widget/GridWithCardWidget";
export { default as HeroSectionWidget } from "./hero-section-widget/HeroSectionWidget";
export { default as SelectCardWithDetailListWidget } from "./select-card-with-detail-list/SelectCardWithDetailList";
export { default as SpacerWidget } from "./spacer-widget/SpacerWidget";
export { StyledText } from "./styled-text/StyledText";
export { default as SumInsuredWidget } from "./sum-insured-carousel-widget/SumInsuredWidget";
export { default as TableWidget } from "./table-widget/Table";
export { default as TitleRightTitleWithContentListWidget } from "./title-right-title-with-content-list-widget/TitleRightTitleWithContentListWidget";
export { default as TitleSubtitleWithAssetWidget } from "./title-subtitle-with-asset-widget/TitleSubtitleWithAssetWidget";
export { default as TitleWidget } from "./title-widget/TitleWidget";
export { default as TitleWithAssetBackgroundWidget } from "./title-with-asset-background/TitleWithAssetBackground";
export { default as TitleWithColumnWidget } from "./title-with-column-widget/TitleWithColumnWidget";
export { default as TitleWithListWidget } from "./title-with-list-widget/TitleWithListWidget";

View File

@@ -1,6 +1,7 @@
import LottieView from "lottie-react-native";
import React, { useEffect, useRef } from "react";
import { TouchableOpacity } from "react-native";
import { GenericActionPayload } from "../../../App/common/actions/GenericAction";
import { CtaData } from "../../../App/common/interface";
import { LottieFieldData } from "../../../App/common/interface/widgets/widgetData/TitleWidgetData";
import styles from "./StyledLottieComponentStyle";
@@ -8,12 +9,26 @@ import styles from "./StyledLottieComponentStyle";
export const StyledLottie = ({
lottieFieldData,
handleClick,
handleActions,
}: {
lottieFieldData: LottieFieldData;
handleClick?: (ctaData: CtaData) => void;
handleActions?: (
value: any | undefined | null,
actionPayloadList: GenericActionPayload | undefined,
) => void;
}) => {
const animationRef = useRef<LottieView | null>(null);
const handleLottieClick = () => {
const { cta, actions } = lottieFieldData;
if (actions && handleActions) {
handleActions(null, actions);
} else if (cta && handleClick) {
handleClick(cta);
}
};
useEffect(() => {
const timeoutId = setTimeout(() => {
animationRef.current?.play();
@@ -25,9 +40,8 @@ export const StyledLottie = ({
if (!lottieFieldData?.url) return <></>;
return (
<TouchableOpacity
onPress={() => {
lottieFieldData.cta && handleClick && handleClick(lottieFieldData.cta);
}}
disabled={!(lottieFieldData.cta || lottieFieldData.actions)}
onPress={handleLottieClick}
style={styles.touchableOpacity}
activeOpacity={1}
>

View File

@@ -1,6 +1,8 @@
import React from "react";
import { View } from "react-native";
import { TouchableOpacity, View } from "react-native";
import Animated from "react-native-reanimated";
import { GenericActionPayload } from "../../../App/common/actions/GenericAction";
import { CtaData } from "../../../App/common/interface";
import {
ImageFieldData,
LottieFieldData,
@@ -13,13 +15,17 @@ import styles from "./StyledTextComponentStyle";
export const StyledText = ({
textFieldData,
handleClick,
handleActions,
}: {
textFieldData: TextFieldData;
handleClick?: (ctaData: CtaData) => void;
handleActions?: (
value: any | undefined | null,
actionPayloadList: GenericActionPayload | undefined,
) => void;
}) => {
let renderedText: string[] = [textFieldData.text];
let substringStyleMap: SubstringStyle[] = [];
let textFieldString: string = textFieldData.text || "";
let text: string = textFieldData.text;
let topImage: ImageFieldData | undefined =
textFieldData?.textDrawableData?.top;
let bottomImage: ImageFieldData | undefined =
@@ -38,6 +44,112 @@ export const StyledText = ({
let rightLottie: LottieFieldData | undefined =
textFieldData?.textDrawableData?.rightLottie;
return (
<View style={[styles.columnContainer, textFieldData.viewStyle]}>
{topImage && (
<StyledImage
imageFieldData={topImage}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
{topLottie && (
<StyledLottie
lottieFieldData={topLottie}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
<View style={styles.rowContainer}>
{leftImage && (
<StyledImage
imageFieldData={leftImage}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
{leftLottie && (
<StyledLottie
lottieFieldData={leftLottie}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
{text && (
<StyledTextComponent
textFieldData={textFieldData}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
{rightImage && (
<StyledImage
imageFieldData={rightImage}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
{rightLottie && (
<StyledLottie
lottieFieldData={rightLottie}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
</View>
{bottomImage && (
<StyledImage
imageFieldData={bottomImage}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
{bottomLottie && (
<StyledLottie
lottieFieldData={bottomLottie}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
</View>
);
};
const StyledTextComponent = ({
textFieldData,
handleClick,
handleActions,
}: {
textFieldData: TextFieldData;
handleClick?: (ctaData: CtaData) => void;
handleActions?: (
value: any | undefined | null,
actionPayloadList: GenericActionPayload | undefined,
) => void;
}) => {
const handleTextClick = () => {
const { cta, actions } = textFieldData;
if (actions && handleActions) {
handleActions(null, actions);
} else if (cta && handleClick) {
handleClick(cta);
}
};
return (
<TouchableOpacity
disabled={!(textFieldData.cta || textFieldData.actions)}
onPress={handleTextClick}
activeOpacity={1}
>
<TextComponent textFieldData={textFieldData} />
</TouchableOpacity>
);
};
const TextComponent = ({ textFieldData }: { textFieldData: TextFieldData }) => {
let substringStyleMap: SubstringStyle[] = [];
let textFieldString: string = textFieldData.text || "";
textFieldData.substringStyles?.forEach(({ substring, textStyle }, index) => {
textFieldString = substringStyleMap?.pop()?.substring || textFieldData.text;
const splitArray = textFieldString.split(substring);
@@ -53,36 +165,25 @@ export const StyledText = ({
};
substringStyleMap = [...substringStyleMap, part1, part2, part3];
});
return (
<View style={[styles.columnContainer, textFieldData.viewStyle]}>
{topImage && <StyledImage imageFieldData={topImage} />}
{topLottie && <StyledLottie lottieFieldData={topLottie} />}
<View style={styles.rowContainer}>
{leftImage && <StyledImage imageFieldData={leftImage} />}
{leftLottie && <StyledLottie lottieFieldData={leftLottie} />}
<Animated.Text
ellipsizeMode={textFieldData.ellipsizeMode}
numberOfLines={textFieldData.numberOfLines}
style={textFieldData.textStyle || undefined}
>
{substringStyleMap.length !== 0
? substringStyleMap.map((substringStyle, index) => {
return (
<Animated.Text
style={substringStyle.textStyle || undefined}
key={index}
>
{substringStyle.substring}
</Animated.Text>
);
})
: textFieldData.text}
</Animated.Text>
{rightImage && <StyledImage imageFieldData={rightImage} />}
{rightLottie && <StyledLottie lottieFieldData={rightLottie} />}
</View>
{bottomImage && <StyledImage imageFieldData={bottomImage} />}
{bottomLottie && <StyledLottie lottieFieldData={bottomLottie} />}
</View>
<Animated.Text
ellipsizeMode={textFieldData.ellipsizeMode}
numberOfLines={textFieldData.numberOfLines}
style={textFieldData.textStyle || undefined}
>
{substringStyleMap.length !== 0
? substringStyleMap.map((substringStyle, index) => {
return (
<Animated.Text
style={substringStyle.textStyle || undefined}
key={index}
>
{substringStyle.substring}
</Animated.Text>
);
})
: textFieldData.text}
</Animated.Text>
);
};

View File

@@ -0,0 +1,89 @@
import { useCallback } from "react";
import { FlatList, View } from "react-native";
import {
TitleRightTitleWithContentListWidgetDataItem,
TitleRightTitleWithContentListWidgetDataItemProps,
TitleRightTitleWithContentListWidgetProps,
} from "../../../App/common/interface/widgets/widgetData";
import { createThrottledHandler } from "../../../App/common/utilities/ThrottleUtil";
import { ItemSeparator } from "../../reusable";
import { StyledText } from "../styled-text/StyledText";
import styles from "./TitleRightTitleWithContentListWidgetStyles";
const TitleRightTitleWithContentListWidget = ({
widgetData,
widgetStyle,
handleActions,
handleClick,
widgetIndex,
}: TitleRightTitleWithContentListWidgetProps) => {
const throttledHandleActions = useCallback(
createThrottledHandler(action => handleActions(null, action), 700),
[widgetData],
);
return (
<FlatList
data={widgetData.listData}
renderItem={({
item,
}: {
item: TitleRightTitleWithContentListWidgetDataItem;
}) => (
<ListItemComponent
item={item}
handleActions={throttledHandleActions}
handleClick={handleClick}
/>
)}
ItemSeparatorComponent={() => (
<ItemSeparator separatorData={widgetData.separatorData!!} />
)}
keyExtractor={(item, index) => item.id || index.toString()}
/>
);
};
const ListItemComponent = ({
item,
handleActions,
handleClick,
}: TitleRightTitleWithContentListWidgetDataItemProps) => {
return (
<View style={styles.columnContainer}>
<View style={styles.rowContainer}>
{item.title && (
<StyledText
textFieldData={item.title}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
{item.rightTitle && (
<StyledText
textFieldData={item.rightTitle}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
</View>
<View style={styles.contentContainer}>
{item.subtitle && (
<StyledText
textFieldData={item.subtitle}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
{item.content && (
<StyledText
textFieldData={item.content}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
</View>
</View>
);
};
export default TitleRightTitleWithContentListWidget;

View File

@@ -0,0 +1,18 @@
import { StyleSheet } from "react-native";
const styles = StyleSheet.create({
rowContainer: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "flex-end",
},
columnContainer: {
flexDirection: "column",
},
contentContainer: {
flexDirection: "column",
alignItems: "flex-start",
},
});
export default styles;

View File

@@ -11,7 +11,7 @@ import { StyledImage } from "../../StyledImage";
import { commonStyles } from "../../../App/Container/Navi-Insurance/Styles";
import { styles } from "./TitleWithColumnWidgetStyle";
export const TitleWithColumnWidget = ({
const TitleWithColumnWidget = ({
widgetData,
widgetStyle,
handleActions,
@@ -22,7 +22,7 @@ export const TitleWithColumnWidget = ({
widgetStyle: ViewStyle;
handleActions: (
value?: any | undefined | null,
screenActionPayload?: GenericActionPayload
screenActionPayload?: GenericActionPayload,
) => void;
handleClick?: (cta: CtaData) => void;
widgetIndex: number;
@@ -39,9 +39,13 @@ export const TitleWithColumnWidget = ({
return (
<View style={styles.columnItem}>
{imageData?.url && <StyledImage imageFieldData={imageData} />}
{imageData?.url && title?.text && <View style={commonStyles.verticalSpacer16} />}
{imageData?.url && title?.text && (
<View style={commonStyles.verticalSpacer16} />
)}
{title?.text && <StyledText textFieldData={title} />}
{title?.text && subtitle?.text && <View style={commonStyles.verticalSpacer4} />}
{title?.text && subtitle?.text && (
<View style={commonStyles.verticalSpacer4} />
)}
{subtitle?.text && <StyledText textFieldData={subtitle} />}
</View>
);
@@ -50,8 +54,12 @@ export const TitleWithColumnWidget = ({
return (
<View style={styles.container}>
<View style={styles.columnContainer}>
{widgetData.title?.text && <StyledText textFieldData={widgetData.title} />}
{widgetData.title?.text && <View style={commonStyles.verticalSpacer24} />}
{widgetData.title?.text && (
<StyledText textFieldData={widgetData.title} />
)}
{widgetData.title?.text && (
<View style={commonStyles.verticalSpacer24} />
)}
<View style={styles.rowContainer}>
<ColumnItem
imageData={widgetData.leftIcon}
@@ -67,4 +75,6 @@ export const TitleWithColumnWidget = ({
</View>
</View>
);
};
};
export default TitleWithColumnWidget;

View File

@@ -1,5 +1,5 @@
import throttle from "lodash/throttle";
import React, { useCallback, useEffect } from "react";
import { useCallback, useEffect } from "react";
import { FlatList, TouchableOpacity, View, ViewStyle } from "react-native";
import { GenericActionPayload } from "../../../App/common/actions/GenericAction";
import { sendAsAnalyticsEvent } from "../../../App/common/hooks/useAnalyticsEvent";