Merge branch 'master' into TP-57833
This commit is contained in:
Submodule RN-UI-LIB updated: 9d5fa3961c...a33494e87f
@@ -134,8 +134,8 @@ def reactNativeArchitectures() {
|
||||
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
||||
}
|
||||
|
||||
def VERSION_CODE = 127
|
||||
def VERSION_NAME = "2.7.9"
|
||||
def VERSION_CODE = 128
|
||||
def VERSION_NAME = "2.7.10"
|
||||
|
||||
android {
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "AV_APP",
|
||||
"version": "2.7.9",
|
||||
"buildNumber": "127",
|
||||
"version": "2.7.10",
|
||||
"buildNumber": "128",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"android:dev": "yarn move:dev && react-native run-android",
|
||||
|
||||
@@ -11,6 +11,8 @@ import { getAddressString, getPhoneNumberString, memoize } from '../utlis/common
|
||||
import { getBase64ImageFromOfflineDb } from '../../services/casePayload.transformer';
|
||||
import { formatAmount } from '../../../RN-UI-LIB/src/utlis/amount';
|
||||
import GeolocationAddressAnswer from './components/GeolocationAddressAnswer';
|
||||
import dayjs from 'dayjs';
|
||||
import { BUSINESS_DATE_FORMAT, CUSTOM_ISO_DATE_FORMAT } from '@rn-ui-lib/utils/dates';
|
||||
|
||||
const RATING_COMPONENT = 'Rating';
|
||||
const MAX_RATING = 5;
|
||||
@@ -131,7 +133,9 @@ const AnswerRender: React.FC<IAnswerRender> = (props) => {
|
||||
case AnswerType.phoneNumber:
|
||||
return <DarkBoldText text={getPhoneNumberStringFromNumber(answer.answer)} />;
|
||||
case AnswerType.date:
|
||||
return <DarkBoldText text={answer.answer} />;
|
||||
return <DarkBoldText text={dayjs(answer?.answer, CUSTOM_ISO_DATE_FORMAT).format(BUSINESS_DATE_FORMAT)} />;
|
||||
case AnswerType.time:
|
||||
return <DarkBoldText text={dayjs(answer?.answer, 'HH:mm').format('hh:mm A')} />;
|
||||
default:
|
||||
return <DarkBoldText text={NA_TEXT} />;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { CLICKSTREAM_EVENT_NAMES } from '../../../common/Constants';
|
||||
import { AnswerType } from '../interface';
|
||||
import WebBasedDatePicker from '../../../../RN-UI-LIB/src/components/WebBasedDatePicker';
|
||||
import {
|
||||
BUSINESS_DATE_FORMAT,
|
||||
CUSTOM_ISO_DATE_FORMAT,
|
||||
DefaultPickerModeVisibleFormatMapping,
|
||||
IDateTimePickerMode,
|
||||
@@ -109,7 +110,7 @@ const DateInput: React.FC<IDateInput> = (props) => {
|
||||
}
|
||||
return (
|
||||
<WebBasedDatePicker
|
||||
displayFormat="DD-MM-YYYY"
|
||||
displayFormat={BUSINESS_DATE_FORMAT}
|
||||
value={
|
||||
question.metadata.defaultValue === DateValue.CURRENT
|
||||
? Date().toString()
|
||||
|
||||
@@ -62,6 +62,7 @@ const GeolocationAddress: React.FC<IGeolocationAddress> = ({
|
||||
: '';
|
||||
|
||||
const isFeedbackPresent = lastFeedbackForGeolocation?.feedbackPresent;
|
||||
const isDataSutramPrimarySource = primarySource === GeolocationSource.DATA_SUTRAM;
|
||||
|
||||
const { addressDate, addressTime } = useMemo(() => {
|
||||
const timestamp = new Date(Number(capturedTimestamp));
|
||||
@@ -98,14 +99,12 @@ const GeolocationAddress: React.FC<IGeolocationAddress> = ({
|
||||
})
|
||||
);
|
||||
if (visitedWidgets?.length) {
|
||||
_map(visitedWidgets, (visited) =>
|
||||
navigateToScreen(getTemplateRoute(visited, CaseAllocationType.COLLECTION_CASE), {
|
||||
caseId: caseId,
|
||||
journey: TaskTitleUIMapping.COLLECTION_FEEDBACK,
|
||||
handleCloseRouting,
|
||||
})
|
||||
);
|
||||
return;
|
||||
const lastVisitedWidget = visitedWidgets[visitedWidgets.length - 1];
|
||||
navigateToScreen(getTemplateRoute(lastVisitedWidget, CaseAllocationType.COLLECTION_CASE), {
|
||||
caseId: caseId,
|
||||
journey: TaskTitleUIMapping.COLLECTION_FEEDBACK,
|
||||
handleCloseRouting,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -145,7 +144,7 @@ const GeolocationAddress: React.FC<IGeolocationAddress> = ({
|
||||
<Text small>{addressTime}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{(primarySource && primarySource === GeolocationSource.DATA_SUTRAM) ? (
|
||||
{isDataSutramPrimarySource ? (
|
||||
<View style={[GenericStyles.row, GenericStyles.alignCenter]}>
|
||||
<View style={styles.circleSeparator} />
|
||||
<Text small>Skip Tracing</Text>
|
||||
|
||||
@@ -55,7 +55,7 @@ const TimeInput: React.FC<ITimeInput> = (props) => {
|
||||
const outputTime = convertTo24HourFormat(text);
|
||||
onChange({
|
||||
answer: outputTime,
|
||||
type: AnswerType.date,
|
||||
type: AnswerType.time,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import Geolocation from 'react-native-geolocation-service';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import Button from '../../../RN-UI-LIB/src/components/Button';
|
||||
import Heading from '../../../RN-UI-LIB/src/components/Heading';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
import ArrowSolidIcon from '../../../RN-UI-LIB/src/Icons/ArrowSolidIcon';
|
||||
import { GenericStyles } from '../../../RN-UI-LIB/src/styles';
|
||||
import { COLORS } from '../../../RN-UI-LIB/src/styles/colors';
|
||||
@@ -47,6 +46,7 @@ import NudgeSuspiciousFeedbackBottomSheet from './NudgeSuspiciousFeedbackBottomS
|
||||
import { API_STATUS_CODE } from '../utlis/apiHelper';
|
||||
import NavigationHeader, { Icon } from '../../../RN-UI-LIB/src/components/NavigationHeader';
|
||||
import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack';
|
||||
import { useNavigation, useRoute } from '@react-navigation/native';
|
||||
|
||||
interface IWidget {
|
||||
route: {
|
||||
@@ -59,6 +59,10 @@ interface IWidget {
|
||||
};
|
||||
}
|
||||
|
||||
enum NavigationActions {
|
||||
GO_BACK = 'GO_BACK',
|
||||
}
|
||||
|
||||
const Widget: React.FC<IWidget> = (props) => {
|
||||
const [isJourneyFirstScreen, setIsJourneyFirstScreen] = useState(true);
|
||||
const [showNudgeBottomSheet, setNudgeBottomSheet] = useState(false);
|
||||
@@ -67,30 +71,28 @@ const Widget: React.FC<IWidget> = (props) => {
|
||||
const { params } = props.route;
|
||||
const { caseId, journey, handleCloseRouting } = params;
|
||||
const caseKey = useRef<string>('');
|
||||
const {
|
||||
caseType,
|
||||
templateData,
|
||||
caseData,
|
||||
dataToBeValidated,
|
||||
docsToBeUploaded,
|
||||
intermediateDocsToBeUploaded,
|
||||
} = useAppSelector((state) => {
|
||||
const caseType =
|
||||
state.allCases.caseDetails[caseId]?.caseType || CaseAllocationType.ADDRESS_VERIFICATION_CASE;
|
||||
return {
|
||||
caseType,
|
||||
templateData: state.case.templateData[caseType],
|
||||
caseData: state.allCases.caseDetails[caseId],
|
||||
dataToBeValidated: state.case.caseForm?.[caseId]?.[journey],
|
||||
docsToBeUploaded: state.feedbackImages.docsToBeUploaded,
|
||||
intermediateDocsToBeUploaded: state.feedbackImages.intermediateDocsToBeUploaded,
|
||||
};
|
||||
});
|
||||
const disableFormInteractionUpdate = useRef(false);
|
||||
const { caseType, templateData, caseData, dataToBeValidated, intermediateDocsToBeUploaded } =
|
||||
useAppSelector((state) => {
|
||||
const caseType =
|
||||
state.allCases.caseDetails[caseId]?.caseType ||
|
||||
CaseAllocationType.ADDRESS_VERIFICATION_CASE;
|
||||
return {
|
||||
caseType,
|
||||
templateData: state.case.templateData[caseType],
|
||||
caseData: state.allCases.caseDetails[caseId],
|
||||
dataToBeValidated: state.case.caseForm?.[caseId]?.[journey],
|
||||
docsToBeUploaded: state.feedbackImages.docsToBeUploaded,
|
||||
intermediateDocsToBeUploaded: state.feedbackImages.intermediateDocsToBeUploaded,
|
||||
};
|
||||
});
|
||||
const name = getWidgetNameFromRoute(props.route.name, caseType);
|
||||
const { sections, conditionActions: widgetConditionActions, isLeaf } = templateData.widget[name];
|
||||
const sectionMap = templateData.sections;
|
||||
const [error, setError] = useState();
|
||||
const dispatch = useAppDispatch();
|
||||
const navigation = useNavigation();
|
||||
const route = useRoute();
|
||||
useEffect(() => {
|
||||
let isFirst = false;
|
||||
for (const journey of Object.values(templateData.journey)) {
|
||||
@@ -125,6 +127,49 @@ const Widget: React.FC<IWidget> = (props) => {
|
||||
return () => subscription.unsubscribe();
|
||||
}, [watch]);
|
||||
|
||||
useEffect(() => {
|
||||
const beforeRemoveListener = navigation.addListener('beforeRemove', (e) => {
|
||||
// If leaf widget, do nothing
|
||||
if (isLeaf && disableFormInteractionUpdate.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete interaction on going back the stack
|
||||
if (e.data.action.type === NavigationActions.GO_BACK) {
|
||||
dispatch(
|
||||
deleteInteraction({
|
||||
caseId,
|
||||
journeyId: journey,
|
||||
widgetId: name,
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const numberOfRoutes = navigation.getState().routes.length;
|
||||
const lastScreen = navigation.getState().routes[numberOfRoutes - 1];
|
||||
|
||||
const isLastScreen = lastScreen.name === route.name;
|
||||
|
||||
// Update form interaction when the last screen is about to be unmounted
|
||||
if (isLastScreen) {
|
||||
const submitHandler = handleSubmit((answer) => {
|
||||
dispatch(
|
||||
updateInteraction({
|
||||
caseId,
|
||||
journeyId: journey,
|
||||
widgetId: name,
|
||||
answer,
|
||||
})
|
||||
);
|
||||
});
|
||||
submitHandler();
|
||||
}
|
||||
});
|
||||
|
||||
return beforeRemoveListener;
|
||||
}, [navigation, route]);
|
||||
|
||||
const onSubmit = (data: any) => {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_FORM_NEXT_BUTTON_CLICKED, {
|
||||
caseId,
|
||||
@@ -221,6 +266,7 @@ const Widget: React.FC<IWidget> = (props) => {
|
||||
};
|
||||
|
||||
const handleSubmitJourney = async (data: any, coords: Geolocation.GeoCoordinates) => {
|
||||
disableFormInteractionUpdate.current = true;
|
||||
dispatch(
|
||||
updateInteraction({
|
||||
caseId,
|
||||
@@ -371,13 +417,6 @@ const Widget: React.FC<IWidget> = (props) => {
|
||||
journeyId: journey,
|
||||
widgetId: name,
|
||||
});
|
||||
dispatch(
|
||||
deleteInteraction({
|
||||
caseId,
|
||||
journeyId: journey,
|
||||
widgetId: name,
|
||||
})
|
||||
);
|
||||
goBack();
|
||||
};
|
||||
|
||||
@@ -398,9 +437,6 @@ const Widget: React.FC<IWidget> = (props) => {
|
||||
Add feedback for {caseData?.customerInfo?.customerName || caseData?.customerName}
|
||||
</Heading>
|
||||
}
|
||||
subTitle={
|
||||
isJourneyNameExists ? <Text light>{templateData?.journey?.[journey].name}</Text> : null
|
||||
}
|
||||
icon={Icon.close}
|
||||
onBack={handleCloseIconPress}
|
||||
/>
|
||||
@@ -444,17 +480,15 @@ const Widget: React.FC<IWidget> = (props) => {
|
||||
styles.borderTop,
|
||||
]}
|
||||
>
|
||||
{!isJourneyFirstScreen && (
|
||||
<Button
|
||||
variant={'secondary'}
|
||||
style={[styles.autoFlex, styles.mH16]}
|
||||
title={'Back'}
|
||||
testID={'test_back'}
|
||||
disabled={isLeaf && isSubmitting}
|
||||
onPress={handleBackButton}
|
||||
leftIcon={<ArrowSolidIcon size={10} />}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
variant={'secondary'}
|
||||
style={[styles.autoFlex, styles.mH16]}
|
||||
title={'Back'}
|
||||
testID={'test_back'}
|
||||
disabled={isLeaf && isSubmitting}
|
||||
onPress={handleBackButton}
|
||||
leftIcon={<ArrowSolidIcon size={10} />}
|
||||
/>
|
||||
<Button
|
||||
style={[styles.autoFlex, styles.mH16]}
|
||||
title={isLeaf ? 'Submit' : 'Next'}
|
||||
|
||||
@@ -7,6 +7,7 @@ export enum AnswerType {
|
||||
'address' = 'address',
|
||||
'phoneNumber' = 'phoneNumber',
|
||||
'date' = 'date',
|
||||
'time' = 'time',
|
||||
}
|
||||
|
||||
// @deprecated
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import { CaseAllocationType, ICaseItem } from '../screens/allCases/interface';
|
||||
import { FormTemplateV1, IVisitedWidgetContext } from '../types/template.types';
|
||||
import { mockTemplate } from '../template';
|
||||
|
||||
interface ICaseReducer {
|
||||
value: number;
|
||||
@@ -54,7 +53,7 @@ export const caseSlice = createSlice({
|
||||
state.caseForm = data;
|
||||
},
|
||||
updateInteraction: (state, action) => {
|
||||
const { caseId, journeyId, widgetId, answer } = action.payload;
|
||||
const { caseId, journeyId, widgetId, answer} = action.payload;
|
||||
const data = state.caseForm || {};
|
||||
if (!data[caseId]) {
|
||||
data[caseId] = {};
|
||||
@@ -74,20 +73,24 @@ export const caseSlice = createSlice({
|
||||
...answer.widgetContext,
|
||||
};
|
||||
data[caseId][journeyId].visitedWidgets = visited;
|
||||
// Update time of interaction
|
||||
data[caseId][journeyId].updatedAt = Date.now();
|
||||
state.caseForm = data;
|
||||
},
|
||||
deleteInteraction: (state, action) => {
|
||||
const { caseId, journeyId, widgetId } = action.payload;
|
||||
const data = state.caseForm;
|
||||
const data = state.caseForm || {};
|
||||
if (!data[caseId] || !data[caseId][journeyId]) return;
|
||||
const visited = data[caseId][journeyId]?.visitedWidgets;
|
||||
if (visited[visited.length - 1] === widgetId) {
|
||||
visited.pop();
|
||||
}
|
||||
data[caseId][journeyId].visitedWidgets = visited;
|
||||
data[caseId][journeyId].updatedAt = Date.now();
|
||||
state.caseForm = data;
|
||||
},
|
||||
deleteJourney: (state, action) => {
|
||||
const { caseId, journeyId, widgetId, answer } = action.payload;
|
||||
const { caseId, journeyId } = action.payload;
|
||||
const data = state.caseForm;
|
||||
delete data[caseId][journeyId];
|
||||
state.caseForm = data;
|
||||
@@ -106,12 +109,12 @@ export const caseSlice = createSlice({
|
||||
|
||||
export const {
|
||||
updateInteraction,
|
||||
deleteInteraction,
|
||||
updateAvTemplateData,
|
||||
updateCollectionTemplateData,
|
||||
deleteJourney,
|
||||
updateAlternateHeader,
|
||||
updatePreDefinedCaseFormJourney,
|
||||
deleteInteraction
|
||||
} = caseSlice.actions;
|
||||
|
||||
export default caseSlice.reducer;
|
||||
|
||||
@@ -100,12 +100,11 @@ function AddressItem({
|
||||
})
|
||||
);
|
||||
if (visitedWidgets?.length) {
|
||||
_map(visitedWidgets, (visited) => {
|
||||
navigateToScreen(getTemplateRoute(visited, CaseAllocationType.COLLECTION_CASE), {
|
||||
caseId,
|
||||
journey: TaskTitleUIMapping.COLLECTION_FEEDBACK,
|
||||
handleCloseRouting,
|
||||
});
|
||||
const lastVisitedWidget = visitedWidgets[visitedWidgets.length - 1];
|
||||
navigateToScreen(getTemplateRoute(lastVisitedWidget, CaseAllocationType.COLLECTION_CASE), {
|
||||
caseId,
|
||||
journey: TaskTitleUIMapping.COLLECTION_FEEDBACK,
|
||||
handleCloseRouting,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
IOutstandingEmiDetail,
|
||||
TaskTitleUIMapping,
|
||||
} from '../allCases/interface';
|
||||
import { _map } from '../../../RN-UI-LIB/src/utlis/common';
|
||||
import { MILLISECONDS_IN_A_MINUTE, _map } from '../../../RN-UI-LIB/src/utlis/common';
|
||||
import FeedbackListContainer from './feedback/FeedbackListContainer';
|
||||
import { RootState } from '../../store/store';
|
||||
import { IFeedback, IUnSyncedFeedbackItem } from '../../types/feedback.types';
|
||||
@@ -43,6 +43,7 @@ import ScreenshotBlocker from '../../components/utlis/ScreenshotBlocker';
|
||||
import { useIsFocused } from '@react-navigation/native';
|
||||
import { setSelectedCaseId } from '../../reducer/allCasesSlice';
|
||||
import { CaseDetailStackEnum } from './CaseDetailStack';
|
||||
import ArrowSolidIcon from '@rn-ui-lib/icons/ArrowSolidIcon';
|
||||
|
||||
interface ICaseDetails {
|
||||
route: {
|
||||
@@ -54,6 +55,8 @@ interface ICaseDetails {
|
||||
};
|
||||
}
|
||||
|
||||
const FEEDBACK_FORM_RESPONSE_EXPIRY_TIME = 60 * MILLISECONDS_IN_A_MINUTE;
|
||||
|
||||
const getOutstandingAmountBreakUp = (
|
||||
outstandingEmiDetails: IOutstandingEmiDetail[] = [],
|
||||
totalOverdueAmount: number = 0
|
||||
@@ -108,18 +111,11 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
|
||||
const isOnline = useIsOnline();
|
||||
|
||||
const caseDetail = useAppSelector((state) => state.allCases.caseDetails[caseId]!!);
|
||||
const data = useAppSelector(
|
||||
const preFilledFormData = useAppSelector(
|
||||
(state) => state.case.caseForm?.[caseId]?.[TaskTitleUIMapping.COLLECTION_FEEDBACK]
|
||||
);
|
||||
|
||||
const {
|
||||
addressString,
|
||||
phoneNumbers,
|
||||
currentOutstandingEmi,
|
||||
loanAccountNumber,
|
||||
totalOverdueAmount,
|
||||
pos,
|
||||
} = caseDetail;
|
||||
const { addressString, phoneNumbers, loanAccountNumber, totalOverdueAmount, pos } = caseDetail;
|
||||
|
||||
const feedbackList: IFeedback[] = useAppSelector(
|
||||
(state: RootState) => state.feedbackHistory?.[loanAccountNumber as string]?.data || []
|
||||
@@ -127,6 +123,14 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
|
||||
|
||||
const allCasesDetails = useAppSelector((state) => state.allCases.caseDetails);
|
||||
|
||||
useEffect(() => {
|
||||
if (caseId) dispatch(setSelectedCaseId(caseId));
|
||||
|
||||
return () => {
|
||||
dispatch(setSelectedCaseId(''));
|
||||
};
|
||||
}, [caseId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loanAccountNumber) {
|
||||
return;
|
||||
@@ -191,13 +195,26 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_CASE_DETAILS_ADD_FEEDBACK_CLICKED, {
|
||||
caseId: caseId,
|
||||
caseType: caseDetail?.caseType,
|
||||
journey: 'COLLECTION_FEEDBACK',
|
||||
journey: TaskTitleUIMapping.COLLECTION_FEEDBACK,
|
||||
});
|
||||
if (data?.visitedWidgets?.length) {
|
||||
_map(data.visitedWidgets, (visited) =>
|
||||
if (preFilledFormData?.visitedWidgets?.length) {
|
||||
const lastFormInteractionTs = preFilledFormData?.updatedAt || 0;
|
||||
// If Date.now() is greater than updatedAt by 60mins, then we will navigate to the first widget
|
||||
const isTimeExpired = Date.now() - lastFormInteractionTs > FEEDBACK_FORM_RESPONSE_EXPIRY_TIME;
|
||||
if (isTimeExpired) {
|
||||
navigateToScreen(
|
||||
getTemplateRoute(CollectionCaseWidgetId.START, CaseAllocationType.COLLECTION_CASE),
|
||||
{
|
||||
caseId: caseId,
|
||||
journey: TaskTitleUIMapping.COLLECTION_FEEDBACK,
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
_map(preFilledFormData.visitedWidgets, (visited) =>
|
||||
navigateToScreen(getTemplateRoute(visited, CaseAllocationType.COLLECTION_CASE), {
|
||||
caseId: caseId,
|
||||
journey: 'COLLECTION_FEEDBACK',
|
||||
journey: TaskTitleUIMapping.COLLECTION_FEEDBACK,
|
||||
})
|
||||
);
|
||||
return;
|
||||
@@ -206,7 +223,7 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
|
||||
getTemplateRoute(CollectionCaseWidgetId.START, CaseAllocationType.COLLECTION_CASE),
|
||||
{
|
||||
caseId: caseId,
|
||||
journey: 'COLLECTION_FEEDBACK',
|
||||
journey: TaskTitleUIMapping.COLLECTION_FEEDBACK,
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -513,7 +530,14 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
|
||||
/>
|
||||
<Button
|
||||
style={[styles.feedbackButton]}
|
||||
title="Add new feedback"
|
||||
title={preFilledFormData ? 'Continue feedback' : 'Add new feedback'}
|
||||
rightIcon={
|
||||
preFilledFormData ? (
|
||||
<View style={[GenericStyles.ml8]}>
|
||||
<ArrowSolidIcon rotateY={180} size={10} fillColor={COLORS.TEXT.WHITE} />
|
||||
</View>
|
||||
) : null
|
||||
}
|
||||
variant="primary"
|
||||
onPress={handleAddFeedback}
|
||||
testID={'test_add_feedback'}
|
||||
|
||||
@@ -58,7 +58,8 @@ export const extractQuestionContext = async (answer: Answer): Promise<IQuestionC
|
||||
if (
|
||||
answer.type === AnswerType.date ||
|
||||
answer.type === AnswerType.phoneNumber ||
|
||||
answer.type === AnswerType.address
|
||||
answer.type === AnswerType.address ||
|
||||
answer.type === AnswerType.time
|
||||
) {
|
||||
answer = { ...answer, type: AnswerType.text };
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ export interface IVisitedWidgetContext {
|
||||
};
|
||||
};
|
||||
};
|
||||
updatedAt?: number;
|
||||
}
|
||||
|
||||
export enum CommonCaseWidgetId {
|
||||
|
||||
Reference in New Issue
Block a user