NTP-12975 | multi plan v2 changes (#14236)

This commit is contained in:
Somarapu Vamshi
2024-12-18 18:35:28 +05:30
committed by GitHub
parent 5909c06089
commit a5db8f7944
19 changed files with 559 additions and 60 deletions

View File

@@ -0,0 +1,51 @@
import { View, ViewStyle } from "react-native";
import { NaviLinearGradient } from "../../../App/common/hooks/useGradient";
import { GradientBorderData } from "../../../App/common/interface/components/GradientBorderData";
import { commonStyles } from "../../../App/Container/Navi-Insurance/Styles";
const GradientBorder = ({
gradientBorderData,
children,
style,
}: {
gradientBorderData?: GradientBorderData;
children?: React.ReactNode;
style?: ViewStyle;
}) => {
let data = gradientBorderData;
let gradientColors = data?.gradientColors;
let orientation = gradientBorderData?.orientation;
let borderWidth = gradientBorderData?.borderWidth;
let outerRadius = gradientBorderData?.borderRadius || 0;
let innerRadius = Math.max(outerRadius - (borderWidth || 0), 0);
return (
<NaviLinearGradient
gradientColors={gradientColors}
orientation={orientation}
style={
[
style,
commonStyles.overflowHidden,
{
padding: borderWidth,
borderRadius: outerRadius,
},
] as ViewStyle
}
>
<View
style={[
commonStyles.overflowHidden,
{
borderRadius: innerRadius,
},
]}
>
{children}
</View>
</NaviLinearGradient>
);
};
export default GradientBorder;

View File

@@ -23,13 +23,18 @@ import Animated, {
useSharedValue,
} from "react-native-reanimated";
import { GenericActionPayload } from "../../../App/common/actions/GenericAction";
import {
FAB_WIDTH_LARGE,
FAB_WIDTH_SMALL,
FabIconSize,
OsTypeConstants,
} from "../../../App/common/constants";
import { NativeEventNameConstants } from "../../../App/common/constants/EventNameConstants";
import { CtaData } from "../../../App/common/interface";
import { FabWidgetData } from "../../../App/common/interface/widgets/widgetData/FabWidgetData";
import { getTextWithHtmlSpace } from "../../../App/common/utilities/MiscUtils";
import { StyledImage } from "../../StyledImage";
import { FAB_HEIGHT, styles } from "./FABStyle";
import { OsTypeConstants } from "../../../App/common/constants";
import { createStyles } from "./FABStyle";
const FAB = ({
widgetData,
@@ -69,6 +74,11 @@ const FAB = ({
}, [widgetData]);
const FAB_STARTING_POSITION = widgetData?.properties?.startingPosition ?? 145;
const getFabWidth = (fabIconSize?: string) =>
fabIconSize === FabIconSize.SMALL ? FAB_WIDTH_SMALL : FAB_WIDTH_LARGE;
const FAB_WIDTH = getFabWidth(widgetData?.properties?.fabIconSize);
const styles = createStyles(FAB_WIDTH);
const FAB_HEIGHT = FAB_WIDTH;
const fabPositionY = useSharedValue(-FAB_STARTING_POSITION);

View File

@@ -1,46 +1,79 @@
import { StyleSheet } from "react-native";
import { StyleSheet, ViewStyle } from "react-native";
import { FAB_WIDTH_SMALL } from "../../../App/common/constants/FabIconConstants";
export const FAB_WIDTH = 48;
export const FAB_HEIGHT = FAB_WIDTH;
export const FAB_BORDER_RADIUS = FAB_WIDTH / 2;
const BASE_ROOT_STYLES: ViewStyle = {
position: "absolute",
bottom: 0,
right: 20,
};
export const FAB_MARGIN_BOTTOM = 0;
const SMALL_FAB_ICON_ROOT_STYLES: ViewStyle = {
...BASE_ROOT_STYLES,
paddingBottom: 1,
paddingRight: 1,
backgroundColor: "#BED7FF",
};
export const styles = StyleSheet.create({
rootStyles: {
borderRadius: FAB_BORDER_RADIUS,
position: "absolute",
bottom: FAB_MARGIN_BOTTOM,
right: 20,
},
fabButtonStyles: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#0047D6",
height: FAB_HEIGHT,
borderRadius: FAB_BORDER_RADIUS,
},
lottie: {
height: FAB_HEIGHT,
width: FAB_WIDTH,
},
topLottie: {
position: "absolute",
top: 0,
left: 0,
height: 16,
width: 16,
},
image: {
height: FAB_HEIGHT,
width: FAB_WIDTH,
justifyContent: "center",
alignItems: "center",
},
buttonTitle: {
height: 22,
paddingRight: 16,
width: "auto",
}
});
const BASE_FAB_BUTTON_STYLES: ViewStyle = {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
};
const SMALL_FAB_BUTTON_STYLES: ViewStyle = {
...BASE_FAB_BUTTON_STYLES,
backgroundColor: "#EAF2FF",
borderColor: "#BED7FF",
borderWidth: 1,
shadowOffset: { width: 1, height: 5 },
shadowOpacity: 0,
shadowRadius: 0,
shadowColor: "#BED7FF",
elevation: 3,
};
const LARGE_FAB_BUTTON_STYLES: ViewStyle = {
...BASE_FAB_BUTTON_STYLES,
backgroundColor: "#0047D6",
};
export const createStyles = (fabWidth: number) => {
const fabHeight = fabWidth;
const fabBorderRadius = fabWidth / 2;
const isSmall = fabWidth === FAB_WIDTH_SMALL;
const buttonTitleHeight = isSmall ? 19 : 22;
return StyleSheet.create({
rootStyles: {
...(isSmall ? SMALL_FAB_ICON_ROOT_STYLES : BASE_ROOT_STYLES),
borderRadius: fabBorderRadius,
},
fabButtonStyles: {
...(isSmall ? SMALL_FAB_BUTTON_STYLES : LARGE_FAB_BUTTON_STYLES),
height: fabHeight,
borderRadius: fabBorderRadius,
},
lottie: {
height: fabHeight,
width: fabWidth,
},
topLottie: {
position: "absolute",
top: 0,
left: 0,
height: 16,
width: 16,
},
image: {
height: fabHeight,
width: fabWidth,
justifyContent: "center",
alignItems: "center",
},
buttonTitle: {
height: buttonTitleHeight,
paddingRight: 16,
width: "auto",
},
});
};

View File

@@ -23,3 +23,4 @@ export { default as TitleWithListWidget } from "./title-with-list-widget/TitleWi
export { default as ListItemWidget } from "./list-item-with-icon-widget/ListItemWidget";
export { default as CardWithListItemsWidget } from "./card-with-list-items-widget/CardWithListItemsWidget";
export { default as TitleWithHorizontalCarouselListWidget } from "./title-with-horizontal-carousel-list-widget/TitleWithHorizontalCarouselListWidget";
export { default as SelectCardWithTagListItems } from "./select-card-with-tag-list-items/SelectCardWithTagListItems";

View File

@@ -0,0 +1,129 @@
import { useEffect } from "react";
import { FlatList, TouchableOpacity, View } from "react-native";
import { StyledImage, StyledText } from "..";
import { SelectButtonType } from "../../../App/common/constants";
import { sendAsAnalyticsEvent } from "../../../App/common/hooks/useAnalyticsEvent";
import { NaviLinearGradient } from "../../../App/common/hooks/useGradient";
import {
ButtonData,
CardFooterCtaButtonProps,
ItemCardProps,
} from "../../../App/common/interface/widgets/widgetData";
import { SelectButton } from "../../reusable";
import CtaButton from "../../reusable/cta-button/CtaButton";
import GradientBorder from "../../reusable/gradient-border/GradientBorder";
import { styles } from "./SelectCardWithTagListItemsStyles";
const CardFooterCtaButton = ({
buttonState,
buttonData,
handleFooterButtonClick,
}: CardFooterCtaButtonProps) => {
return (
<CtaButton
state={buttonState}
onPress={() => handleFooterButtonClick?.(buttonData)}
style={buttonData?.buttonStyle}
>
{buttonData?.title && <StyledText textFieldData={buttonData.title} />}
</CtaButton>
);
};
export const ItemCardWithTag = ({
handleClick,
item,
selected,
onSelect,
showContainerTag,
containerTag,
handleActions,
}: ItemCardProps) => {
useEffect(() => {
item?.analyticEvents?.onViewEvent &&
sendAsAnalyticsEvent(item?.analyticEvents?.onViewEvent);
}, []);
const handleFooterButtonClick = (buttonData?: ButtonData) => {
if (!buttonData) return;
const { actions, cta } = buttonData;
if (actions && handleActions) {
handleActions(actions);
} else if (cta && handleClick) {
handleClick(cta);
}
};
return (
<TouchableOpacity
style={[styles.card, selected && styles.selectedCard]}
onPress={onSelect}
activeOpacity={1}
>
<View style={styles.headerContainer}>
<View style={styles.alignStart}>
{item?.cardImage && (
<StyledImage
imageFieldData={item.cardImage}
handleActions={handleActions}
handleClick={handleClick}
/>
)}
<View style={styles.textContainer}>
{item?.title?.text && <StyledText textFieldData={item?.title} />}
{item?.subtitle?.text && (
<StyledText textFieldData={item?.subtitle} />
)}
</View>
</View>
<SelectButton selected={selected} type={SelectButtonType.RADIO} />
</View>
{item?.tag &&
item?.tag?.map((tagItem, index) => (
<GradientBorder
key={index}
gradientBorderData={tagItem?.gradientBorderData}
style={tagItem?.tagContainer}
>
<NaviLinearGradient
gradientColors={tagItem?.gradientData?.gradientColors}
orientation={tagItem?.gradientData?.orientation}
style={tagItem?.gradientData?.style}
>
{tagItem?.title && <StyledText textFieldData={tagItem?.title} />}
</NaviLinearGradient>
</GradientBorder>
))}
{item?.listData && (
<FlatList
contentContainerStyle={item?.listData?.listStyle}
data={item?.listData?.items}
renderItem={({ item }) => (
<StyledText
textFieldData={item}
handleClick={handleClick}
handleActions={handleActions}
/>
)}
keyExtractor={(item, index) =>
item?.id || item?.text || index.toString()
}
nestedScrollEnabled={true}
/>
)}
{item?.leftFooter && (
<View style={styles.footerContainer}>
<CardFooterCtaButton
buttonData={item?.leftFooter}
handleFooterButtonClick={handleFooterButtonClick}
/>
</View>
)}
</TouchableOpacity>
);
};

View File

@@ -0,0 +1,76 @@
import { useEffect, useState } from "react";
import { TitleWidget } from "..";
import { sendAsAnalyticsEvent } from "../../../App/common/hooks/useAnalyticsEvent";
import {
Item,
SelectCardWithDetailListProps,
} from "../../../App/common/interface/widgets/widgetData";
import { ItemCardWithTag } from "./ItemCardWithTag";
import { styles } from "./SelectCardWithTagListItemsStyles";
const SelectCardWithTagListItems = ({
widgetData,
widgetStyle,
handleActions,
handleClick,
widgetIndex,
}: SelectCardWithDetailListProps) => {
const [selectedItem, setSelectedItem] = useState<string | undefined>(
widgetData?.widgetMetaData?.selectedItem,
);
const handleSelect = (itemType?: string) => {
setSelectedItem(itemType);
const item = widgetData?.items?.find(item => item?.itemType === itemType);
item?.analyticEvents?.onSelectedEvent &&
sendAsAnalyticsEvent(item?.analyticEvents?.onSelectedEvent);
if (item?.dependentWidgets) {
handleActions(
item?.dependentWidgets,
widgetData?.widgetMetaData?.onValueChangeAction,
);
}
};
useEffect(() => {
const item = widgetData?.items?.find(
item => item?.itemType === selectedItem,
);
if (item?.dependentWidgets) {
handleActions(
item.dependentWidgets,
widgetData?.widgetMetaData?.onValueChangeAction,
);
}
}, [
widgetData?.items
?.map(item => JSON.stringify(item?.dependentWidgets))
.join(","),
]);
return (
<>
<TitleWidget
widgetData={widgetData}
widgetStyle={styles.detailLeftText}
handleActions={handleActions}
handleClick={handleClick}
widgetIndex={widgetIndex}
/>
{widgetData?.items?.map((item: Item) => {
return (
<ItemCardWithTag
handleClick={handleClick}
containerTag={widgetData?.containerTag}
showContainerTag={widgetData?.widgetMetaData?.showContainerTag}
item={item}
selected={selectedItem === item?.itemType}
onSelect={() => handleSelect(item?.itemType)}
/>
);
})}
</>
);
};
export default SelectCardWithTagListItems;

View File

@@ -0,0 +1,90 @@
import { StyleSheet } from "react-native";
export const styles = StyleSheet.create({
card: {
backgroundColor: "#ffffff",
borderRadius: 8,
paddingTop: 20,
paddingHorizontal: 16,
paddingBottom: 20,
marginTop: 15,
marginBottom: 5,
width: "100%",
borderColor: "#EBEBEB",
borderWidth: 1,
position: "relative",
elevation: 5,
shadowColor: "#D1D9E6",
shadowOffset: { width: 3, height: 3 },
shadowOpacity: 0.3,
shadowRadius: 33,
},
selectedCard: {
borderColor: "#1F002A",
backgroundColor: "#FFFFFF",
shadowColor: "#000000",
shadowOffset: { width: 3, height: 3 },
shadowOpacity: 0.3,
shadowRadius: 16,
elevation: 5,
},
detailCardContainer: {
borderRadius: 4,
overflow: "hidden",
},
detailCard: {
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
backgroundColor: "#F5F5F5",
paddingHorizontal: 12,
paddingVertical: 8,
},
detailLeftText: {
flexDirection: "row",
justifyContent: "flex-start",
},
alignStart: {
flexDirection: "row",
alignItems: "flex-start",
},
borderBottom: {
borderBottomWidth: 1,
borderBottomColor: "#E3E5E5",
},
selectedDetailCard: {
backgroundColor: "#FFFFFF",
},
headerContainer: {
flexDirection: "row",
justifyContent: "space-between",
marginBottom: 16,
},
tag: {
justifyContent: "flex-start",
alignItems: "flex-end",
top: 14,
right: -3,
position: "absolute",
},
tagContainer: {
backgroundColor: "#3C7DFF",
paddingHorizontal: 8,
paddingVertical: 4,
borderTopStartRadius: 2,
borderTopEndRadius: 2,
borderBottomStartRadius: 2,
},
rightTextStyle: { paddingVertical: 8, paddingLeft: 8 },
textContainer: {
alignItems: "flex-start",
},
tagTextContainer: {
alignItems: "flex-start",
},
footerContainer: {
flexDirection: "row",
alignItems: "center",
},
});

View File

@@ -6,8 +6,10 @@ import { sendAsAnalyticsEvent } from "../../../App/common/hooks/useAnalyticsEven
import { AnalyticsEvent } from "../../../App/common/interface";
import {
CarouselListData,
ListItem,
TitleWithHorizontalCarouselListWidgetProps,
} from "../../../App/common/interface/widgets/widgetData";
import { ItemSeparator } from "../../reusable";
import styles from "./TitleWithHorizontalCarouselListWidgetStyle";
const TitleWithHorizontalCarouselListWidget = ({
@@ -42,25 +44,50 @@ const TitleWithHorizontalCarouselListWidget = ({
}
};
const renderListItem = ({ item }: { item: ListItem }) => (
<View style={styles.listItem}>
{item?.title && <StyledText textFieldData={item?.title} />}
{item?.rightTitle && <StyledText textFieldData={item?.rightTitle} />}
</View>
);
const CarouselItem = ({ item }: { item: CarouselListData }) => {
const isSelected = selectedItem === item?.id;
const containerStyles = [
widgetData?.defaultItemContainerStyles,
isSelected && widgetData?.selectedItemContainerStyles,
];
const listData = isSelected
? item?.selectedState?.listData
: item?.unSelectedState?.listData;
return (
<TouchableOpacity
style={containerStyles}
onPress={() => handleSelectItem(item)}
activeOpacity={1}
>
<StyledText
textFieldData={
isSelected
? item?.selectedState?.title
: item?.unSelectedState?.title
}
/>
<View
style={[
widgetData?.titleContainerStyles,
isSelected && widgetData?.selectedTitleContainerStyles,
]}
>
<StyledText
textFieldData={
isSelected
? item?.selectedState?.title
: item?.unSelectedState?.title
}
/>
</View>
{!isSelected && widgetData?.separatorData && (
<ItemSeparator separatorData={widgetData?.separatorData} />
)}
{listData && (
<View style={styles.listContainer}>
{listData?.map(listItem => renderListItem({ item: listItem }))}
</View>
)}
</TouchableOpacity>
);
};
@@ -97,7 +124,10 @@ const TitleWithHorizontalCarouselListWidget = ({
renderItem={({ item }) => <CarouselItem item={item} />}
keyExtractor={item => item?.id.toString()}
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.flatListContainer}
contentContainerStyle={[
styles.flatListContainer,
widgetData?.flatListContainerStyles,
]}
overScrollMode={"never"}
/>
</View>

View File

@@ -6,6 +6,15 @@ const styles = StyleSheet.create({
paddingRight: 8,
paddingVertical: 14,
},
listItem: {
flexDirection: "row",
justifyContent: "space-between",
backgroundColor: "#FFF",
},
listContainer: {
paddingHorizontal: 12,
paddingTop: 12,
},
});
export default styles;