TP-83691 | Benefit Screen Final (#12582)
Co-authored-by: Kshitij Pramod Ghongadi <kshitij.pramod@navi.com>
This commit is contained in:
@@ -55,7 +55,7 @@ const DropDownComponent = ({
|
||||
}).start();
|
||||
};
|
||||
|
||||
const getBulletPoint = (item: DropdownContent) => {
|
||||
const BulletPoint = ({ item }: { item: DropdownContent }) => {
|
||||
return (
|
||||
<View>
|
||||
{item?.icon?.url ? (
|
||||
@@ -70,7 +70,7 @@ const DropDownComponent = ({
|
||||
const DropdownItemComponent = ({ item }: { item: DropdownContent }) => {
|
||||
return (
|
||||
<View style={styles.rowContainer}>
|
||||
{getBulletPoint(item)}
|
||||
<BulletPoint item={item} />
|
||||
{item?.content?.text && <StyledText textFieldData={item.content} />}
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
FlatList,
|
||||
LayoutAnimation,
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from "react-native";
|
||||
import Animated, {
|
||||
useAnimatedStyle,
|
||||
useDerivedValue,
|
||||
useSharedValue,
|
||||
} from "react-native-reanimated";
|
||||
import { commonStyles } from "../../../App/Container/Navi-Insurance/Styles";
|
||||
import { INITIAL_Y_VALUE } from "../../../App/common/constants";
|
||||
import { sendAsAnalyticsEvent } from "../../../App/common/hooks/useAnalyticsEvent";
|
||||
import { NaviLinearGradient } from "../../../App/common/hooks/useGradient";
|
||||
import {
|
||||
DropdownContent,
|
||||
DropdownData,
|
||||
TitleSubtitleWithDropdownBottomSheetProps,
|
||||
} from "../../../App/common/interface/widgets/modalData";
|
||||
import { TextFieldData } from "../../../App/common/interface/widgets/widgetData";
|
||||
import { StyledImage } from "../../StyledImage";
|
||||
import { StyledText } from "../../widgets/styled-text/StyledText";
|
||||
import styles from "./TopSectionExpandableBottomSheetStyle";
|
||||
|
||||
const TopSectionExpandableBottomSheet = ({
|
||||
bottomSheetData,
|
||||
handleModalClick,
|
||||
handleActions,
|
||||
}: TitleSubtitleWithDropdownBottomSheetProps) => {
|
||||
const y = useSharedValue(INITIAL_Y_VALUE);
|
||||
const onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||
y.value = event.nativeEvent.contentOffset.y;
|
||||
};
|
||||
const derivedY = useDerivedValue(() => {
|
||||
return y.value;
|
||||
});
|
||||
|
||||
const handleRightTitleClick = () => {
|
||||
handleModalClick && handleModalClick(bottomSheetData?.rightTitle?.cta!!);
|
||||
};
|
||||
|
||||
const headerIconClick = () => {
|
||||
handleModalClick &&
|
||||
bottomSheetData?.headerDescriptionText?.cta &&
|
||||
handleModalClick(bottomSheetData?.headerDescriptionText?.cta);
|
||||
};
|
||||
|
||||
const headerStyle = useAnimatedStyle(() => {
|
||||
return {
|
||||
shadowColor: derivedY.value > 0 ? "black" : "transparent",
|
||||
shadowOpacity: derivedY.value > 0 ? 1 : 0,
|
||||
shadowRadius: derivedY.value > 0 ? 8 : 0,
|
||||
elevation: derivedY.value > 0 ? 32 : 0,
|
||||
};
|
||||
});
|
||||
|
||||
const Header = () => {
|
||||
return (
|
||||
<Animated.View style={[styles.title, headerStyle]}>
|
||||
{bottomSheetData?.title?.text && (
|
||||
<StyledText textFieldData={bottomSheetData.title} />
|
||||
)}
|
||||
{bottomSheetData?.rightTitle && (
|
||||
<TouchableOpacity activeOpacity={1} onPress={handleRightTitleClick}>
|
||||
<StyledText textFieldData={bottomSheetData.rightTitle} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<View style={bottomSheetData?.viewStyle}>
|
||||
<ScrollView
|
||||
nestedScrollEnabled={true}
|
||||
showsVerticalScrollIndicator={false}
|
||||
bounces={false}
|
||||
scrollEnabled={true}
|
||||
overScrollMode={"never"}
|
||||
stickyHeaderIndices={[0]}
|
||||
onScroll={onScroll}
|
||||
>
|
||||
<Header />
|
||||
<TouchableOpacity activeOpacity={1}>
|
||||
<NaviLinearGradient
|
||||
gradientColors={bottomSheetData?.backgroundGradient}
|
||||
orientation={bottomSheetData?.gradientOrientation}
|
||||
>
|
||||
{bottomSheetData?.subtitle?.text && (
|
||||
<StyledText textFieldData={bottomSheetData.subtitle} />
|
||||
)}
|
||||
<View style={styles.videoContainer}>
|
||||
<TouchableOpacity activeOpacity={1} onPress={headerIconClick}>
|
||||
{bottomSheetData?.headerDescriptionText && (
|
||||
<StyledText
|
||||
textFieldData={bottomSheetData.headerDescriptionText}
|
||||
/>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
{bottomSheetData?.headerDescriptionIcon && (
|
||||
<StyledImage
|
||||
imageFieldData={bottomSheetData.headerDescriptionIcon}
|
||||
handleClick={handleModalClick}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</NaviLinearGradient>
|
||||
{bottomSheetData?.dropdownData?.title?.text && (
|
||||
<DropDownComponent dropdownData={bottomSheetData?.dropdownData} />
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const DropDownComponent = ({
|
||||
dropdownData,
|
||||
}: {
|
||||
dropdownData: DropdownData;
|
||||
}) => {
|
||||
const [isExpanded, setIsExpanded] = useState<boolean>(false);
|
||||
const toggleOpen = () => {
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
setIsExpanded(value => !value);
|
||||
dropdownData?.toggleEvent &&
|
||||
sendAsAnalyticsEvent(dropdownData?.toggleEvent);
|
||||
};
|
||||
|
||||
const BulletPoint = ({ item }: { item: DropdownContent }) => {
|
||||
return (
|
||||
<View>
|
||||
{item?.icon?.url ? (
|
||||
<StyledImage imageFieldData={item.icon} />
|
||||
) : (
|
||||
<View style={styles.bulletIcon}></View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const DropdownItemComponent = ({ item }: { item: DropdownContent }) => {
|
||||
return (
|
||||
<View style={styles.rowContainer}>
|
||||
<BulletPoint item={item} />
|
||||
{item?.content?.text && <StyledText textFieldData={item.content} />}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const CollapsableText = (collapsableText?: TextFieldData) => {
|
||||
return (
|
||||
<View>
|
||||
{collapsableText?.text && (
|
||||
<TouchableOpacity onPress={toggleOpen} activeOpacity={1}>
|
||||
<StyledText textFieldData={collapsableText} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={[styles.contentSection, dropdownData?.style]}>
|
||||
<TouchableOpacity
|
||||
disabled={isExpanded}
|
||||
onPress={!isExpanded ? toggleOpen : undefined}
|
||||
activeOpacity={1}
|
||||
style={commonStyles.flexStart}
|
||||
>
|
||||
{dropdownData?.title?.text && (
|
||||
<StyledText textFieldData={dropdownData.title} />
|
||||
)}
|
||||
{dropdownData?.contentList?.[0] && (
|
||||
<DropdownItemComponent
|
||||
item={{
|
||||
...dropdownData.contentList[0],
|
||||
content: {
|
||||
...(dropdownData.contentList[0]?.content as TextFieldData),
|
||||
numberOfLines: isExpanded ? 10 : 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
{isExpanded && dropdownData?.contentList && (
|
||||
<FlatList
|
||||
data={dropdownData?.contentList?.slice(1)}
|
||||
renderItem={({ item }) => <DropdownItemComponent item={item} />}
|
||||
/>
|
||||
)}
|
||||
<View style={styles.expandText}>
|
||||
{isExpanded
|
||||
? CollapsableText(dropdownData?.collapseText)
|
||||
: CollapsableText(dropdownData?.expandText)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopSectionExpandableBottomSheet;
|
||||
@@ -0,0 +1,43 @@
|
||||
import { StyleSheet } from "react-native";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
title: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
paddingHorizontal: 16,
|
||||
backgroundColor: "#FFFFFF",
|
||||
paddingBottom: 16,
|
||||
},
|
||||
videoContainer: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
},
|
||||
contentSection: {
|
||||
flexDirection: "column",
|
||||
alignItems: "flex-start",
|
||||
paddingHorizontal: 16,
|
||||
paddingTop: 16,
|
||||
},
|
||||
bulletIcon: {
|
||||
width: 4,
|
||||
height: 4,
|
||||
borderRadius: 4,
|
||||
backgroundColor: "#444444",
|
||||
marginTop: 8,
|
||||
},
|
||||
rowContainer: {
|
||||
flexDirection: "row",
|
||||
alignItems: "flex-start",
|
||||
marginVertical: 8,
|
||||
},
|
||||
expandText: {
|
||||
backgroundColor: "white",
|
||||
width: "100%",
|
||||
alignItems: "flex-start",
|
||||
paddingTop: 8,
|
||||
},
|
||||
});
|
||||
|
||||
export default styles;
|
||||
@@ -64,11 +64,21 @@ const FooterWithCardWidget = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handleSecondaryFooterClick = () => {
|
||||
if (handleClick && widgetData?.secondaryFooterButton?.cta) {
|
||||
handleClick(widgetData.secondaryFooterButton.cta);
|
||||
} else {
|
||||
handleActions(null, widgetData?.secondaryButtonAction);
|
||||
}
|
||||
};
|
||||
|
||||
const getViewStyle = (): ViewStyle => {
|
||||
return widgetData.cardInfo?.title?.text ||
|
||||
widgetData.cardInfo?.centerTitle?.text
|
||||
? styles.rowContainer
|
||||
: styles.roundedRowContainer;
|
||||
: widgetData.bottomTitle?.text
|
||||
? styles.roundedRowContainerWithBottomTitle
|
||||
: styles.roundedRowContainer;
|
||||
};
|
||||
|
||||
const throttledHandleActions = useCallback(
|
||||
@@ -114,7 +124,14 @@ const FooterWithCardWidget = ({
|
||||
: ButtonState.ENABLED;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View
|
||||
style={[
|
||||
styles.container,
|
||||
widgetData?.borderRadius != undefined
|
||||
? { borderRadius: widgetData?.borderRadius }
|
||||
: {},
|
||||
]}
|
||||
>
|
||||
{widgetData?.cardInfo?.title?.text &&
|
||||
widgetData?.cardInfo?.rightTitle?.text && (
|
||||
<TouchableOpacity onPress={cardAction} activeOpacity={1}>
|
||||
@@ -156,15 +173,32 @@ const FooterWithCardWidget = ({
|
||||
</View>
|
||||
)}
|
||||
<View style={commonStyles.flex_1}>
|
||||
<CtaButton
|
||||
state={buttonState}
|
||||
onPress={handleFooterClick}
|
||||
style={commonStyles.height54}
|
||||
>
|
||||
{widgetData?.footerButton?.title && (
|
||||
{widgetData?.footerButton?.title?.text && (
|
||||
<CtaButton
|
||||
state={buttonState}
|
||||
onPress={handleFooterClick}
|
||||
style={commonStyles.height54}
|
||||
>
|
||||
<StyledText textFieldData={widgetData?.footerButton?.title} />
|
||||
)}
|
||||
</CtaButton>
|
||||
</CtaButton>
|
||||
)}
|
||||
{widgetData?.secondaryFooterButton?.title?.text && (
|
||||
<CtaButton
|
||||
state={buttonState}
|
||||
onPress={handleSecondaryFooterClick}
|
||||
style={styles.secondaryFooterButton}
|
||||
>
|
||||
<StyledText
|
||||
textFieldData={widgetData?.secondaryFooterButton?.title}
|
||||
/>
|
||||
</CtaButton>
|
||||
)}
|
||||
{widgetData?.bottomTitle?.text && (
|
||||
<TitleWidget
|
||||
widgetData={{ title: widgetData?.bottomTitle }}
|
||||
handleClick={handleClick}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -36,6 +36,16 @@ const styles = StyleSheet.create({
|
||||
paddingTop: 16,
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
|
||||
roundedRowContainerWithBottomTitle: {
|
||||
backgroundColor: "white",
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
paddingBottom: 24,
|
||||
paddingTop: 16,
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
|
||||
centerTitleContainer: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
@@ -62,6 +72,13 @@ const styles = StyleSheet.create({
|
||||
paddingTop: 5,
|
||||
paddingBottom: 2,
|
||||
},
|
||||
secondaryFooterButton: {
|
||||
height: 54,
|
||||
backgroundColor: "#F5F5F5",
|
||||
borderRadius: 4,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
},
|
||||
});
|
||||
|
||||
export default styles;
|
||||
|
||||
@@ -20,3 +20,4 @@ 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";
|
||||
export { default as ListItemWidget } from "./list-item-with-icon-widget/ListItemWidget";
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { useCallback } from "react";
|
||||
import { FlatList, TouchableOpacity, View } from "react-native";
|
||||
import {
|
||||
ListItemWidgetProps,
|
||||
TitleWithAssetsWidgetData,
|
||||
} from "../../../App/common/interface/widgets/widgetData";
|
||||
import { createThrottledHandler } from "../../../App/common/utilities/ThrottleUtil";
|
||||
import { StyledImage } from "../../StyledImage";
|
||||
import { StyledLottie } from "../styled-lottie/StyledLottie";
|
||||
import { StyledText } from "../styled-text/StyledText";
|
||||
import styles from "./ListItemWidgetStyles";
|
||||
|
||||
const ListItemWidget = ({
|
||||
widgetData,
|
||||
widgetStyle,
|
||||
handleActions,
|
||||
widgetIndex,
|
||||
handleClick,
|
||||
}: ListItemWidgetProps) => {
|
||||
const throttledHandleActions = useCallback(
|
||||
createThrottledHandler(action => handleActions(null, action), 700),
|
||||
[widgetData],
|
||||
);
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
data={widgetData.listItems}
|
||||
renderItem={({ item }: { item: TitleWithAssetsWidgetData }) => (
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
const { cta, actions } = item || {};
|
||||
if (actions) {
|
||||
throttledHandleActions(actions);
|
||||
} else if (cta && handleClick) {
|
||||
handleClick(cta);
|
||||
}
|
||||
}}
|
||||
activeOpacity={1}
|
||||
>
|
||||
<View style={styles.container}>
|
||||
<View style={styles.rowContainer}>
|
||||
{item?.leftIcon && (
|
||||
<StyledImage imageFieldData={item?.leftIcon} />
|
||||
)}
|
||||
{item?.leftLottie && (
|
||||
<StyledLottie lottieFieldData={item?.leftLottie} />
|
||||
)}
|
||||
<View style={styles.titleContainer}>
|
||||
{item?.title && <StyledText textFieldData={item?.title} />}
|
||||
{item?.subtitle && (
|
||||
<StyledText textFieldData={item?.subtitle} />
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
{item?.rightIcon && (
|
||||
<StyledImage imageFieldData={item?.rightIcon} />
|
||||
)}
|
||||
{item?.rightLottie && (
|
||||
<StyledLottie lottieFieldData={item?.rightLottie} />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
keyExtractor={(item, index) => item?.id || index.toString()}
|
||||
ItemSeparatorComponent={() => <View style={styles.separator} />}
|
||||
contentContainerStyle={widgetData?.listStyle}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ListItemWidget;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { StyleSheet } from "react-native";
|
||||
import Colors from "../../../assets/colors/colors";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
paddingTop: 16,
|
||||
paddingBottom: 20,
|
||||
},
|
||||
rowContainer: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "flex-start",
|
||||
alignItems: "center",
|
||||
gap: 12,
|
||||
width: "80%",
|
||||
},
|
||||
titleContainer: {
|
||||
flexDirection: "column",
|
||||
alignItems: "flex-start",
|
||||
},
|
||||
separator: {
|
||||
height: 1,
|
||||
width: "100%",
|
||||
backgroundColor: Colors.lightGray,
|
||||
},
|
||||
});
|
||||
|
||||
export default styles;
|
||||
@@ -49,7 +49,11 @@ const TitleWidget = ({
|
||||
return (
|
||||
<View style={widgetStyle}>
|
||||
{widgetData.title && (
|
||||
<TouchableOpacity onPress={handleTitleClick} activeOpacity={1}>
|
||||
<TouchableOpacity
|
||||
onPress={handleTitleClick}
|
||||
activeOpacity={1}
|
||||
disabled={!(widgetData?.title?.cta || widgetData?.title?.actions)}
|
||||
>
|
||||
<StyledText textFieldData={widgetData.title} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
@@ -57,7 +61,13 @@ const TitleWidget = ({
|
||||
<StyledText textFieldData={widgetData.subtitle} />
|
||||
)}
|
||||
{widgetData.rightTitle && (
|
||||
<TouchableOpacity onPress={handleRightTitleClick} activeOpacity={1}>
|
||||
<TouchableOpacity
|
||||
onPress={handleRightTitleClick}
|
||||
activeOpacity={1}
|
||||
disabled={
|
||||
!(widgetData?.rightTitle?.cta || widgetData?.rightTitle?.actions)
|
||||
}
|
||||
>
|
||||
<StyledText textFieldData={widgetData.rightTitle} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { View, ViewStyle } from "react-native";
|
||||
import { commonStyles } from "../../../App/Container/Navi-Insurance/Styles";
|
||||
import { GenericActionPayload } from "../../../App/common/actions/GenericAction";
|
||||
import { CtaData } from "../../../App/common/interface";
|
||||
import { TitleWithColumnWidgetData } from "../../../App/common/interface/widgets/widgetData/TitleWithColumnWidgetData";
|
||||
import { StyledText } from "../styled-text/StyledText";
|
||||
import {
|
||||
ImageFieldData,
|
||||
TextFieldData,
|
||||
} from "../../../App/common/interface/widgets/widgetData/TitleWidgetData";
|
||||
import { TitleWithColumnWidgetData } from "../../../App/common/interface/widgets/widgetData/TitleWithColumnWidgetData";
|
||||
import { StyledImage } from "../../StyledImage";
|
||||
import { commonStyles } from "../../../App/Container/Navi-Insurance/Styles";
|
||||
import { StyledText } from "../styled-text/StyledText";
|
||||
import { styles } from "./TitleWithColumnWidgetStyle";
|
||||
|
||||
const TitleWithColumnWidget = ({
|
||||
|
||||
@@ -32,7 +32,11 @@ const ListItemComponent = ({
|
||||
item.onViewEvent && sendAsAnalyticsEvent(item.onViewEvent);
|
||||
});
|
||||
return (
|
||||
<TouchableOpacity onPress={() => handleWidgetClick(item)} activeOpacity={1}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleWidgetClick(item)}
|
||||
activeOpacity={1}
|
||||
disabled={!(item?.cta || item?.actions)}
|
||||
>
|
||||
<TitleWidget
|
||||
widgetData={item}
|
||||
widgetStyle={styles.itemRowContainer}
|
||||
|
||||
Reference in New Issue
Block a user