NTP-7916 | coach mark cosmetic fixes
This commit is contained in:
@@ -2,7 +2,9 @@ import firestore from '@react-native-firebase/firestore';
|
||||
import dayjs from 'dayjs';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
import timezone from 'dayjs/plugin/timezone';
|
||||
import { TIMESTAMP_IST } from '@rn-ui-lib/utils/dates';
|
||||
import { TIMESTAMP_IST, TIMEZONE_ASIA } from '@rn-ui-lib/utils/dates';
|
||||
import { addClickstreamEvent } from '@services/clickstreamEventService';
|
||||
import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants';
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
@@ -15,7 +17,7 @@ export const showCoachMark = async (
|
||||
const coachMarkDoc = firestore().collection('coachMarks').doc(agentId);
|
||||
const userSnapshot = await coachMarkDoc.get();
|
||||
let coachMarkData = userSnapshot.data()?.coachMarkData;
|
||||
const dayJsTime = dayjs().tz('Asia/Kolkata').format(TIMESTAMP_IST);
|
||||
const dayJsTime = dayjs().tz(TIMEZONE_ASIA).format(TIMESTAMP_IST);
|
||||
const timestamp = serverTimestamp || dayJsTime;
|
||||
|
||||
if (!coachMarkData) {
|
||||
@@ -26,10 +28,11 @@ export const showCoachMark = async (
|
||||
};
|
||||
callback().then(
|
||||
async () => {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_FILTER_COACHMARKS_LOADED);
|
||||
await coachMarkDoc.set({ coachMarkData }, { merge: true });
|
||||
},
|
||||
(error) => {
|
||||
console.log('error', error);
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_FILTER_COACHMARKS_FAILED);
|
||||
}
|
||||
);
|
||||
return;
|
||||
@@ -46,10 +49,11 @@ export const showCoachMark = async (
|
||||
coachMarkData.lastSeenDate = timestamp;
|
||||
callback().then(
|
||||
async () => {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_FILTER_COACHMARKS_LOADED);
|
||||
await coachMarkDoc.set({ coachMarkData }, { merge: true });
|
||||
},
|
||||
(error) => {
|
||||
console.log('error', error);
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_FILTER_COACHMARKS_FAILED);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1385,6 +1385,16 @@ export const CLICKSTREAM_EVENT_NAMES = {
|
||||
name: 'FA_PERSIST_ORIGINAL_IMAGE_FAILURE',
|
||||
description: 'Failed to persist original image'
|
||||
},
|
||||
|
||||
// Filter coachmarks
|
||||
FA_FILTER_COACHMARKS_LOADED: {
|
||||
name: 'FA_FILTER_COACHMARKS_LOADED',
|
||||
description: 'Filter coachmarks loaded'
|
||||
},
|
||||
FA_FILTER_COACHMARKS_FAILED: {
|
||||
name: 'FA_FILTER_COACHMARKS_FAILED',
|
||||
description: 'Filter coachmarks failed'
|
||||
}
|
||||
} as const;
|
||||
|
||||
export enum MimeType {
|
||||
|
||||
@@ -60,6 +60,7 @@ export const CopilotModal = forwardRef<CopilotModalHandle, CopilotOptions>(funct
|
||||
setStylesForNoHighlightArea(rect);
|
||||
return;
|
||||
}
|
||||
// center of the coachmark element
|
||||
const center = {
|
||||
x: rect.x + rect.width / 2,
|
||||
y: rect.y + rect.height / 2,
|
||||
@@ -70,24 +71,31 @@ export const CopilotModal = forwardRef<CopilotModalHandle, CopilotOptions>(funct
|
||||
const relativeToBottom = Math.abs(center.y - SCREEN_HEIGHT);
|
||||
const relativeToRight = Math.abs(center.x - SCREEN_WIDTH);
|
||||
|
||||
// position of tooltip
|
||||
const verticalPosition = relativeToBottom > relativeToTop ? 'bottom' : 'top';
|
||||
const horizontalPosition = relativeToLeft > relativeToRight ? 'left' : 'right';
|
||||
|
||||
const tooltip: ViewStyle = {};
|
||||
|
||||
if (verticalPosition === 'bottom') {
|
||||
// if the tooltip is at the bottom, we need to add some margin to the bottom
|
||||
tooltip.top = rect.y + rect.height + margin;
|
||||
} else {
|
||||
// if the tooltip is at the top, we need to add some margin to the top
|
||||
tooltip.bottom = noHighlightArea ? 40 : SCREEN_HEIGHT - rect.y + margin + margin;
|
||||
}
|
||||
|
||||
if (horizontalPosition === 'left') {
|
||||
// if the tooltip is at the left, we need to add some margin to the left
|
||||
tooltip.right = Math.min(SCREEN_WIDTH - (rect.x + rect.width), 24);
|
||||
} else {
|
||||
// if the tooltip is at the right, we need to add some margin to the right
|
||||
tooltip.left = noHighlightArea ? 50 : Math.min(rect.x, 24);
|
||||
}
|
||||
|
||||
setTooltipStyles(tooltip);
|
||||
|
||||
// highlight area dimensions and position
|
||||
setMaskRect({
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
@@ -144,14 +152,14 @@ export const CopilotModal = forwardRef<CopilotModalHandle, CopilotOptions>(funct
|
||||
transparent
|
||||
style={{ backgroundColor: 'transparent' }}
|
||||
>
|
||||
<View style={styles.container}>
|
||||
{showMask ? <AnimatedRenderMask maskRect={maskRect} /> : null}
|
||||
{showMask ? (
|
||||
{showMask ? (
|
||||
<View style={styles.container}>
|
||||
<AnimatedRenderMask maskRect={maskRect} />
|
||||
<View style={[styles.tooltip, tooltipStyles, tooltipStyle]}>
|
||||
<TooltipComponent labels={labels} maskRect={maskRect} />
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
</ModalWrapperForAlfredV2>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useMemo, useRef } from 'react';
|
||||
import { View, type NativeMethods } from 'react-native';
|
||||
import { StyleSheet, View, type NativeMethods } from 'react-native';
|
||||
import { useCopilot } from '../contexts/CopilotProvider';
|
||||
import { GenericStyles, SCREEN_HEIGHT, SCREEN_WIDTH } from '@rn-ui-lib/styles';
|
||||
import { CopilotStepProps } from '../types';
|
||||
@@ -97,22 +97,17 @@ export const CopilotStep = ({
|
||||
if (!isNoHighlightAreaStepActive) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
GenericStyles.centerAlignedRow,
|
||||
{
|
||||
width: SCREEN_WIDTH,
|
||||
height: SCREEN_HEIGHT,
|
||||
position: 'absolute',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
return <View style={[GenericStyles.centerAlignedRow, styles.wrapper]}>{children}</View>;
|
||||
}
|
||||
|
||||
return React.cloneElement(children, { ...copilotProps, ref: wrapperRef });
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
wrapper: {
|
||||
width: SCREEN_WIDTH,
|
||||
height: SCREEN_HEIGHT,
|
||||
position: 'absolute',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ export const Tooltip: React.FC<ITooltip> = ({ labels }) => {
|
||||
useEffect(() => {
|
||||
if (currentStepNumber) {
|
||||
tooltipOpacity.value = 0;
|
||||
tooltipOpacity.value = withTiming(1, { duration: 1000 });
|
||||
tooltipOpacity.value = withTiming(1, { duration: 700 });
|
||||
}
|
||||
}, [currentStepNumber]);
|
||||
|
||||
@@ -50,7 +50,7 @@ export const Tooltip: React.FC<ITooltip> = ({ labels }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Animated.View style={[animatedStyle]}>
|
||||
<Animated.View style={[animatedStyle, GenericStyles.ph16]}>
|
||||
<Text testID="stepDescription" style={styles.tooltipText}>
|
||||
{currentStep?.text}
|
||||
</Text>
|
||||
@@ -59,7 +59,7 @@ export const Tooltip: React.FC<ITooltip> = ({ labels }) => {
|
||||
GenericStyles.row,
|
||||
GenericStyles.alignCenter,
|
||||
GenericStyles.mt16,
|
||||
{ alignSelf: 'flex-end' },
|
||||
GenericStyles.spaceBetween,
|
||||
]}
|
||||
>
|
||||
{totalStepsNumber > 1 ? (
|
||||
@@ -67,14 +67,7 @@ export const Tooltip: React.FC<ITooltip> = ({ labels }) => {
|
||||
{currentStepNumber}/{totalStepsNumber}
|
||||
</Text>
|
||||
) : null}
|
||||
<View style={[GenericStyles.row, GenericStyles.mh12]}>
|
||||
<Button
|
||||
onPress={handleStop}
|
||||
title={isLastStep ? labels?.finish : labels?.skip}
|
||||
style={GenericStyles.mr10}
|
||||
buttonStyle={styles.nextBtn}
|
||||
pressableWidthChange={false}
|
||||
/>
|
||||
<View style={[GenericStyles.row]}>
|
||||
{!isFirstStep ? (
|
||||
<Button
|
||||
variant="primaryText"
|
||||
@@ -87,6 +80,15 @@ export const Tooltip: React.FC<ITooltip> = ({ labels }) => {
|
||||
underlayColor="transparent"
|
||||
/>
|
||||
) : null}
|
||||
{isLastStep ? (
|
||||
<Button
|
||||
onPress={handleStop}
|
||||
title={labels?.finish}
|
||||
style={GenericStyles.mr10}
|
||||
buttonStyle={styles.nextBtn}
|
||||
pressableWidthChange={false}
|
||||
/>
|
||||
) : null}
|
||||
{!isLastStep ? (
|
||||
<Button
|
||||
onPress={handleNext}
|
||||
|
||||
@@ -27,7 +27,6 @@ export const styles = StyleSheet.create({
|
||||
color: COLORS.TEXT.WHITE,
|
||||
fontSize: 16,
|
||||
fontWeight: '700',
|
||||
marginHorizontal: 20,
|
||||
},
|
||||
nextBtn: {
|
||||
paddingHorizontal: 21,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { ScrollView, TouchableOpacity, View } from 'react-native';
|
||||
import { GenericStyles } from '../../../../../RN-UI-LIB/src/styles';
|
||||
import Heading from '../../../../../RN-UI-LIB/src/components/Heading';
|
||||
@@ -36,6 +36,7 @@ const FiltersContainer: React.FC<FilterContainerProps> = (props) => {
|
||||
const selectedFilters = useAppSelector((state: RootState) =>
|
||||
getSelectedFilters(state, isAgentDashboard, isVisitPlan)
|
||||
);
|
||||
const onLayoutHandled = useRef(false);
|
||||
const [selectedFiltersMap, setSelectedFiltersMap] =
|
||||
React.useState<Record<string, any>>(selectedFilters);
|
||||
const filterGroupKeys = Object.keys(filters);
|
||||
@@ -108,7 +109,9 @@ const FiltersContainer: React.FC<FilterContainerProps> = (props) => {
|
||||
};
|
||||
|
||||
const startCoachMark = async () => {
|
||||
if(onLayoutHandled.current) return;
|
||||
if (userId) {
|
||||
onLayoutHandled.current = true;
|
||||
showCoachMark(userId, serverTimestamp, copilot.start);
|
||||
}
|
||||
};
|
||||
@@ -132,7 +135,7 @@ const FiltersContainer: React.FC<FilterContainerProps> = (props) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={[GenericStyles.fill, { flex: 1 }]} onLayout={startCoachMark}>
|
||||
<View style={GenericStyles.fill} onLayout={startCoachMark}>
|
||||
<View
|
||||
style={[
|
||||
GenericStyles.row,
|
||||
@@ -204,7 +207,7 @@ const FiltersContainer: React.FC<FilterContainerProps> = (props) => {
|
||||
text={ENABLE_COACHMARK[filterKey]?.description}
|
||||
>
|
||||
<Text
|
||||
style={[filterKey === selectedFilterKey.filterKey && styles.blueText]}
|
||||
style={[filterKey === selectedFilterKey.filterKey && styles.blueText, GenericStyles.flex80]}
|
||||
dark
|
||||
>
|
||||
{filters[filterGroupKey].filters[filterKey].displayText}
|
||||
@@ -212,7 +215,7 @@ const FiltersContainer: React.FC<FilterContainerProps> = (props) => {
|
||||
</CopilotStep>
|
||||
) : (
|
||||
<Text
|
||||
style={[filterKey === selectedFilterKey.filterKey && styles.blueText]}
|
||||
style={[filterKey === selectedFilterKey.filterKey && styles.blueText, GenericStyles.flex80]}
|
||||
dark
|
||||
>
|
||||
{filters[filterGroupKey].filters[filterKey].displayText}
|
||||
|
||||
@@ -4,11 +4,11 @@ export const ENABLE_COACHMARK: Record<string, ICoachMark> = {
|
||||
CURRENT_MONTH_INTERACTION_STATUS: {
|
||||
key: 'CURRENT_MONTH_INTERACTION_STATUS',
|
||||
order: 1,
|
||||
description: '👆 You can find latest feedbacks in current month status',
|
||||
description: '👆 You can find the priority feedback of current month in Current Month Status',
|
||||
},
|
||||
LAST_MONTH_INTERACTION_STATUS: {
|
||||
key: 'LAST_MONTH_INTERACTION_STATUS',
|
||||
order: 2,
|
||||
description: "👆 You can find last month's feedbacks here",
|
||||
description: "👆 You can find the priority feedback of last month in Last Month Status",
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user