Files
super-app/components/widgets/sum-insured-carousel-widget/SumInsuredWidget.tsx
2024-04-07 16:44:41 +00:00

196 lines
6.1 KiB
TypeScript

import _ from "lodash";
import { useCallback, useEffect, useRef } from "react";
import { View, ViewStyle, useWindowDimensions } from "react-native";
import Animated, {
useAnimatedScrollHandler,
useSharedValue,
} from "react-native-reanimated";
import { AnimatedScrollView } from "react-native-reanimated/lib/typescript/reanimated2/component/ScrollView";
import { GenericActionPayload } from "../../../App/common/actions/GenericAction";
import {
AnalyticsEventNameConstants,
AnalyticsEventPropertyConstants,
} from "../../../App/common/constants/AnalyticsEventsConstant";
import { sendAsAnalyticsEvent } from "../../../App/common/hooks/useAnalyticsEvent";
import { logToSentry } from "../../../App/common/hooks/useSentryLogging";
import { AnalyticsEvent } from "../../../App/common/interface";
import { SumInsuredWidgetData } from "../../../App/common/interface/widgets/widgetData/SumInsuredWidgetData";
import { getIndexFromOffset } from "../../../App/common/utilities/SizeUtils";
import CarouselItem from "./component/CarouselItem";
const SumInsuredWidget = ({
widgetData,
handleActions,
widgetIndex,
widgetStyle,
}: {
widgetData: SumInsuredWidgetData;
handleActions: (
value: any | undefined | null,
actionPayloadList: GenericActionPayload | undefined
) => void;
widgetIndex: number;
widgetStyle?: ViewStyle;
}) => {
const { width } = useWindowDimensions();
const SIZE = width * 0.4;
const SPACER_SIZE = (width - SIZE) / 2;
const x = useSharedValue(0);
const isMiddleCard = useSharedValue(false);
const scrollViewRef = useRef<AnimatedScrollView>(null);
const scrollToPosition = (index: number) => {
if (index <= 0) {
return;
}
if (scrollViewRef.current) {
scrollViewRef.current.scrollTo({
x: (index - 1) * SIZE,
animated: true,
});
if (widgetData?.carouselListData) {
handleActions(
widgetData?.carouselListData[index - 1]?.dependentWidgets,
widgetData?.widgetMetaData?.onValueChangeAction
);
}
const clickEvent: AnalyticsEvent = {
name: AnalyticsEventNameConstants.HI_SI_PILLS_CLICK,
properties: new Map([
[
AnalyticsEventPropertyConstants.SUM_INSURED,
widgetData?.carouselListData
?.at(index - 1)
?.sumInsured?.toString() ?? "",
],
[
AnalyticsEventPropertyConstants.TAG,
widgetData?.widgetMetaData?.recommendItemIndex === index - 1
? AnalyticsEventPropertyConstants.RECOMMENDED
: AnalyticsEventPropertyConstants.NOT_RECOMMENDED,
],
]),
};
sendAsAnalyticsEvent(clickEvent);
}
};
useEffect(() => {
if (widgetData?.widgetMetaData?.selectedItemIndex === undefined) return;
if (scrollViewRef.current) {
scrollViewRef.current.scrollTo({
x: SIZE * widgetData?.widgetMetaData?.selectedItemIndex,
animated: false,
});
}
}, []);
const onScroll = useAnimatedScrollHandler({
onScroll: (event) => {
x.value = event.contentOffset.x;
},
});
// Makes a patch call to update the sumInsured in the backend
const handleActionApiCall = (index: number) => {
const actionPayloadList =
widgetData?.widgetMetaData?.onCarouselReleaseActionSequence;
if (!actionPayloadList) {
logToSentry(
`Payload not present: ${actionPayloadList} | MethodName: handleActionApiCall`
);
return;
}
// Makes a patch call to update the sumInsured in the backend
const updatedActionPayload: GenericActionPayload = {
...actionPayloadList,
metaData: actionPayloadList.metaData?.map((actionPayload) => {
return {
...actionPayload,
data: {
sumInsured: widgetData?.carouselListData?.[index]?.sumInsured,
},
};
}),
};
handleActions(null, updatedActionPayload);
};
// We can use this debounced function to make api calls on scroll
const debouncedHandleActions = useCallback(
_.debounce((index: number) => handleActionApiCall(index), 1000),
[handleActions, handleActionApiCall]
);
const onMomentumScrollEnd = (event: any) => {
const index = getIndexFromOffset(event.nativeEvent.contentOffset.x, SIZE);
if (widgetData?.carouselListData) {
handleActions(
widgetData?.carouselListData[index]?.dependentWidgets,
widgetData?.widgetMetaData?.onValueChangeAction
);
}
const clickEvent: AnalyticsEvent = {
name: AnalyticsEventNameConstants.HI_SI_PILLS_CLICK,
properties: new Map([
[
AnalyticsEventPropertyConstants.SUM_INSURED,
widgetData?.carouselListData?.at(index)?.sumInsured?.toString() ?? "",
],
[
AnalyticsEventPropertyConstants.TAG,
widgetData?.widgetMetaData?.recommendItemIndex === index
? AnalyticsEventPropertyConstants.RECOMMENDED
: AnalyticsEventPropertyConstants.NOT_RECOMMENDED,
],
]),
};
sendAsAnalyticsEvent(clickEvent);
};
const data = widgetData.carouselListData && [
{ isFirst: true },
...widgetData?.carouselListData,
{ isLast: true },
];
return (
<Animated.ScrollView
ref={scrollViewRef}
horizontal
showsHorizontalScrollIndicator={false}
bounces={false}
scrollEventThrottle={16}
snapToInterval={SIZE}
decelerationRate="fast"
onScroll={onScroll}
onMomentumScrollEnd={onMomentumScrollEnd}
>
{data?.map((item, index) => {
if (item?.isFirst || item?.isLast) {
return <View style={{ width: SPACER_SIZE }} key={index} />;
}
return (
<View style={{ width: SIZE }} key={item?.itemId + "_" + index}>
<CarouselItem
item={item}
index={index}
isMiddleCard={isMiddleCard}
widgetData={widgetData}
x={x}
SIZE={SIZE}
scrollToPosition={scrollToPosition}
/>
</View>
);
})}
</Animated.ScrollView>
);
};
export default SumInsuredWidget;