diff --git a/RN-UI-LIB b/RN-UI-LIB
index efa590cd..ede6bd38 160000
--- a/RN-UI-LIB
+++ b/RN-UI-LIB
@@ -1 +1 @@
-Subproject commit efa590cd27c169a2f479b1caf7aad0c35a81aabb
+Subproject commit ede6bd382eb6e02aee1edb7b86f41be9d3763c80
diff --git a/src/assets/icons/AnomalyIcon.tsx b/src/assets/icons/AnomalyIcon.tsx
index 20a47ec0..7d598ef5 100644
--- a/src/assets/icons/AnomalyIcon.tsx
+++ b/src/assets/icons/AnomalyIcon.tsx
@@ -1,33 +1,38 @@
+import { COLORS } from '@rn-ui-lib/colors';
+import { IconProps } from '@rn-ui-lib/icons/types';
import * as React from 'react';
-import Svg, { Path, Rect } from 'react-native-svg';
+import Svg, { Path } from 'react-native-svg';
-const AnomalyTrackerIcon = () => (
-
-);
+const AnomalyTrackerIcon: React.FC = (props) => {
+ const { fillColor = COLORS.TEXT.YELLOW_LIGHT, width = 32, height = 36 } = props;
+ return (
+
+ );
+};
export default AnomalyTrackerIcon;
diff --git a/src/assets/icons/EscalatedAnomalyIcon.tsx b/src/assets/icons/EscalatedAnomalyIcon.tsx
new file mode 100644
index 00000000..82cdabb6
--- /dev/null
+++ b/src/assets/icons/EscalatedAnomalyIcon.tsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import Svg, { ClipPath, Defs, G, Path, Rect } from 'react-native-svg';
+
+const EscalatedAnomalyIcon = () => {
+ return (
+
+ );
+};
+
+export default EscalatedAnomalyIcon;
diff --git a/src/common/FormInput.tsx b/src/common/FormInput.tsx
new file mode 100644
index 00000000..cd2045ed
--- /dev/null
+++ b/src/common/FormInput.tsx
@@ -0,0 +1,158 @@
+import { GenericStyles } from '@rn-ui-lib/styles';
+import React from 'react';
+import { Control, Controller, ControllerRenderProps } from 'react-hook-form';
+import { View, StyleSheet } from 'react-native';
+import Text from '@rn-ui-lib/components/Text';
+import {
+ BUSINESS_DATE_FORMAT,
+ CUSTOM_ISO_DATE_FORMAT,
+ dateFormat,
+ ISO_DATE_FORMAT,
+} from '@rn-ui-lib/utils/dates';
+import dayjs from 'dayjs';
+import WebBasedDatePicker from '@rn-ui-lib/components/WebBasedDatePicker';
+import ErrorMessage from '@components/form/components/ErrorMessage';
+import { AnswerType } from '@components/form/interface';
+import RadioGroup from '@rn-ui-lib/components/radio_button/RadioGroup';
+import { IOption, IEtaFormData, IRcaFormData } from '@screens/Dashboard/AnomalyTracker/interfaces';
+import TextInput from '@rn-ui-lib/components/TextInput';
+import { COLORS } from '@rn-ui-lib/colors';
+import RNRadioButton from '@rn-ui-lib/components/radio_button/RadioButton';
+
+interface IFormInputProps {
+ control: Control;
+ question: {
+ text: string;
+ type: AnswerType;
+ };
+ maxDate?: string;
+ name: 'at' | 'comment' | 'reason';
+ isQuestionMandatory?: boolean;
+ placeholder?: string;
+ keyboardType?: 'default' | 'number-pad' | 'email-address' | 'phone-pad';
+ answerOptions?: IOption[];
+ rules?: {};
+ maxLength?: number;
+}
+
+const FormInput = (props: IFormInputProps) => {
+ const {
+ control,
+ maxDate,
+ question,
+ name,
+ isQuestionMandatory = false,
+ placeholder,
+ keyboardType = 'default',
+ answerOptions,
+ rules,
+ maxLength = 300,
+ } = props;
+
+ const todaysDate = dateFormat(new Date(), ISO_DATE_FORMAT);
+
+ const renderInput = (
+ field: ControllerRenderProps,
+ hasError: boolean
+ ) => {
+ const { onChange, value, onBlur } = field;
+ switch (question.type) {
+ case AnswerType.date:
+ let dateString = value;
+ if (dateString) {
+ const parsedDate = dayjs(dateString, CUSTOM_ISO_DATE_FORMAT, true);
+ dateString = parsedDate.format(ISO_DATE_FORMAT);
+ }
+ return (
+
+ );
+ case AnswerType.option:
+ return (
+
+ {answerOptions?.map((option: IOption) => {
+ return (
+
+ );
+ })}
+
+ );
+
+ case AnswerType.text:
+ return (
+
+ );
+
+ default:
+ return (
+
+ );
+ }
+ };
+
+ return (
+
+
+ {question?.text}
+ {isQuestionMandatory && *}
+
+ (
+ <>
+ {renderInput(field, !!fieldState?.error)}
+ {fieldState?.error?.message ? (
+
+ ) : null}
+ >
+ )}
+ />
+
+ );
+};
+
+const styles = StyleSheet.create({
+ inputContainerStyle: {
+ backgroundColor: COLORS.BACKGROUND.PRIMARY,
+ borderRadius: 8,
+ borderWidth: 1,
+ padding: 0,
+ borderColor: COLORS.BORDER.PRIMARY,
+ color: COLORS.TEXT.BLACK,
+ },
+});
+
+export default FormInput;
diff --git a/src/components/utlis/apiHelper.ts b/src/components/utlis/apiHelper.ts
index 8874192c..7edc961c 100644
--- a/src/components/utlis/apiHelper.ts
+++ b/src/components/utlis/apiHelper.ts
@@ -126,6 +126,8 @@ export enum ApiKeys {
FEEDBACK_ORIGINAL_IMAGE_ACK = 'FEEDBACK_ORIGINAL_IMAGE_ACK',
GET_ANOMALY_DETAILS = 'GET_ANOMALY_DETAILS',
GET_ANOMALY_ACTIVITY_LOG = 'GET_ANOMALY_ACTIVITY_LOG',
+ GET_ANOMALY_RCA_QUESTION = 'GET_ANOMALY_RCA_QUESTION',
+ UPDATE_ANOMALY_ACTION = 'UPDATE_ANOMALY_ACTION',
}
export const API_URLS: Record = {} as Record;
@@ -241,6 +243,9 @@ API_URLS[ApiKeys.GET_PRE_SIGNED_URL_FOR_FEEDBACK_IMAGE] = '/file-upload/presigne
API_URLS[ApiKeys.FEEDBACK_ORIGINAL_IMAGE_ACK] = '/file-upload/acknowledge';
API_URLS[ApiKeys.GET_ANOMALY_DETAILS] = '/anomaly-tracker';
API_URLS[ApiKeys.GET_ANOMALY_ACTIVITY_LOG] = '/anomaly-tracker/activity-logs/{anomalyReferenceId}';
+API_URLS[ApiKeys.UPDATE_ANOMALY_ACTION] = '/anomaly-tracker/action/{anomalyReferenceId}';
+API_URLS[ApiKeys.GET_ANOMALY_RCA_QUESTION] =
+ '/anomaly-tracker/question-tree/rca/{anomalyReferenceId}';
export const API_STATUS_CODE = {
OK: 200,
diff --git a/src/reducer/anomalyTrackerSlice.ts b/src/reducer/anomalyTrackerSlice.ts
index 85830429..db95cb75 100644
--- a/src/reducer/anomalyTrackerSlice.ts
+++ b/src/reducer/anomalyTrackerSlice.ts
@@ -1,8 +1,44 @@
import { createSlice } from '@reduxjs/toolkit';
+import { ActivityLog, AnomalyItem, AnomalyResponse, IOption } from '@screens/Dashboard/AnomalyTracker/interfaces';
-const initialState = {
- openAnomaliesList: {},
- closedAnomaliesList: {},
+interface AnomalyTrackerState {
+ openAnomaliesList: AnomalyResponse;
+ closedAnomaliesList: AnomalyResponse;
+ anomalyDetailsLoading: boolean;
+ anomalyDetails: {
+ data: AnomalyItem;
+ loading: boolean;
+ };
+ actionLoading: boolean;
+ acitvityLogs: {
+ data: ActivityLog[];
+ loading: boolean;
+ };
+ rcaReasons: Array<{
+ options: IOption[] | undefined; label: string; value: string
+}>;
+ updatingForm: boolean;
+}
+
+const initialState: AnomalyTrackerState = {
+ openAnomaliesList: {
+ data: [],
+ pages: {
+ pageNo: 0,
+ totalPages: 0,
+ pageSize: 0,
+ totalElements: 0
+ }
+ },
+ closedAnomaliesList: {
+ data: [],
+ pages: {
+ pageNo: 0,
+ totalPages: 0,
+ pageSize: 0,
+ totalElements: 0
+ }
+ },
anomalyDetailsLoading: false,
anomalyDetails: {
data: {},
@@ -13,6 +49,8 @@ const initialState = {
data: [],
loading: false,
},
+ rcaReasons: [],
+ updatingForm: false,
};
const anomalyTrackerSlice = createSlice({
@@ -34,6 +72,12 @@ const anomalyTrackerSlice = createSlice({
setActivityLogsLoading: (state, action) => {
state.acitvityLogs.loading = action.payload;
},
+ setRcaReasons: (state, action) => {
+ state.rcaReasons = action.payload;
+ },
+ setUpdatingForm: (state, action) => {
+ state.updatingForm = action.payload;
+ },
},
});
@@ -44,6 +88,7 @@ export const {
setRcaReasons,
setActivityLogs,
setActivityLogsLoading,
+ setUpdatingForm,
} = anomalyTrackerSlice.actions;
export default anomalyTrackerSlice.reducer;
diff --git a/src/reducer/userSlice.ts b/src/reducer/userSlice.ts
index 050a69ac..c0f68d32 100644
--- a/src/reducer/userSlice.ts
+++ b/src/reducer/userSlice.ts
@@ -76,6 +76,7 @@ export interface IUserSlice extends IUser {
fieldAgentPerformanceDashboardEnabled: boolean;
isCallRecordingCosmosExotelEnabled: boolean;
isCosmosDiallerEnabled: boolean;
+ enableFieldAppAnomalyTracker: boolean;
};
employeeId: string;
is1To30FieldAgent: boolean;
@@ -111,6 +112,7 @@ const initialState: IUserSlice = {
fieldAgentPerformanceDashboardEnabled: false,
isCallRecordingCosmosExotelEnabled: false,
isCosmosDiallerEnabled: false,
+ enableFieldAppAnomalyTracker: false,
},
employeeId: '',
is1To30FieldAgent: false,
diff --git a/src/screens/Dashboard/AnomalyTracker/AnomaliesDetailsList.tsx b/src/screens/Dashboard/AnomalyTracker/AnomaliesDetailsList.tsx
index b4acd477..6474aa73 100644
--- a/src/screens/Dashboard/AnomalyTracker/AnomaliesDetailsList.tsx
+++ b/src/screens/Dashboard/AnomalyTracker/AnomaliesDetailsList.tsx
@@ -35,7 +35,7 @@ const AnomaliesDetailsList = ({ anomalyType }: IAnomaliesDetailsListProps) => {
{openAnomaliesData?.length > 0 ? (
item?.anomalyId}
+ keyExtractor={(item) => item?.anomalyId as string}
renderItem={({ item }) => }
contentContainerStyle={[GenericStyles.pb16]}
/>
@@ -65,7 +65,7 @@ const AnomaliesDetailsList = ({ anomalyType }: IAnomaliesDetailsListProps) => {
{closedAnomaliesData?.length > 0 ? (
item?.anomalyId}
+ keyExtractor={(item) => item?.anomalyId as string}
renderItem={({ item }) => }
contentContainerStyle={[GenericStyles.pb16]}
/>
diff --git a/src/screens/Dashboard/AnomalyTracker/AnomalyOverviewCard.tsx b/src/screens/Dashboard/AnomalyTracker/AnomalyOverviewCard.tsx
index 080dad06..d58eaefd 100644
--- a/src/screens/Dashboard/AnomalyTracker/AnomalyOverviewCard.tsx
+++ b/src/screens/Dashboard/AnomalyTracker/AnomalyOverviewCard.tsx
@@ -5,34 +5,47 @@ import AnomalyIcon from '@assets/icons/AnomalyIcon';
import { navigateToScreen } from '@components/utlis/navigationUtlis';
import { PageRouteEnum } from '@screens/auth/ProtectedRouter';
import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack';
-import { GenericStyles, getShadowStyle } from '@rn-ui-lib/styles';
+import { getShadowStyle } from '@rn-ui-lib/styles';
import { COLORS } from '@rn-ui-lib/colors';
import Chevron from '@rn-ui-lib/icons/Chevron';
import { useAppSelector } from '@hooks';
const AnomalyOverviewCard = () => {
- const totalOpenAnomalies =
- useAppSelector((state) => state?.anomalyTracker?.openAnomaliesList?.pages?.totalElements);
+ const totalOpenAnomalies = useAppSelector(
+ (state) => state?.anomalyTracker?.openAnomaliesList?.pages?.totalElements
+ );
const onClick = () => {
navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
screen: CaseDetailStackEnum.ANOMALY_TRACKER,
});
};
+ const areAllIssuesResolved = totalOpenAnomalies === 0;
return (
-
+
-
- {totalOpenAnomalies} Open issues
+
+
+ {areAllIssuesResolved ? 'All issues are closed' : `${totalOpenAnomalies} Open issues`}
+
-
+
+
View
-
-
+
+
);
};
@@ -40,12 +53,10 @@ const styles = StyleSheet.create({
container: {
display: 'flex',
flexDirection: 'row',
- borderRadius: 4,
+ borderRadius: 6,
marginHorizontal: 16,
...getShadowStyle(2),
- backgroundColor: COLORS.BACKGROUND.ORANGE,
borderWidth: 1,
- borderColor: COLORS.BORDER.ORANGE,
marginBottom: 16,
padding: 12,
justifyContent: 'space-between',
@@ -56,6 +67,14 @@ const styles = StyleSheet.create({
alignItems: 'center',
gap: 6,
},
+ openAnomalyState: {
+ backgroundColor: COLORS.BACKGROUND.ORANGE,
+ borderColor: COLORS.BORDER.ORANGE,
+ },
+ closedAnomalyState: {
+ backgroundColor: COLORS.BACKGROUND.GREEN,
+ borderColor: COLORS.BORDER.GREEN,
+ },
rightIcon: {
marginTop: 3,
},
diff --git a/src/screens/Dashboard/AnomalyTracker/AnomalyTrackerActions.ts b/src/screens/Dashboard/AnomalyTracker/AnomalyTrackerActions.ts
new file mode 100644
index 00000000..15a604c1
--- /dev/null
+++ b/src/screens/Dashboard/AnomalyTracker/AnomalyTrackerActions.ts
@@ -0,0 +1,103 @@
+import axiosInstance, { API_STATUS_CODE, ApiKeys, getApiUrl } from '@components/utlis/apiHelper';
+import { AnomalyType } from './constants';
+import { logError } from '@components/utlis/errorUtils';
+
+import { AppDispatch } from '@store';
+import {
+ setActivityLogs,
+ setActivityLogsLoading,
+ setAnomalyDetailsLoading,
+ setClosedAnomalyList,
+ setOpenAnomalyList,
+ setRcaReasons,
+ setUpdatingForm,
+} from '@reducers/anomalyTrackerSlice';
+import { IEtaFormPayload, IRcaFormPayload } from './interfaces';
+import { toast } from '@rn-ui-lib/components/toast';
+import { ToastMessages } from '@screens/allCases/constants';
+
+export const getAnomalyDetails =
+ (anomalyType: string, isLoading: boolean) => (dispatch: AppDispatch) => {
+ const url = getApiUrl(ApiKeys.GET_ANOMALY_DETAILS);
+ if (isLoading) dispatch(setAnomalyDetailsLoading(true));
+ axiosInstance
+ .get(url, {
+ params: { status: anomalyType },
+ })
+ .then((res) => {
+ if (res?.status === API_STATUS_CODE.OK) {
+ if (anomalyType === AnomalyType.OPEN) {
+ dispatch(setOpenAnomalyList(res?.data));
+ return;
+ }
+ dispatch(setClosedAnomalyList(res?.data));
+ }
+ })
+ .catch((err) => {
+ logError(err);
+ })
+ .finally(() => {
+ dispatch(setAnomalyDetailsLoading(false));
+ });
+ };
+
+export const getActivityLogs = (anomalyReferenceId: string) => (dispatch: AppDispatch) => {
+ const url = getApiUrl(ApiKeys.GET_ANOMALY_ACTIVITY_LOG, { anomalyReferenceId });
+ dispatch(setActivityLogsLoading(true));
+ axiosInstance
+ .get(url)
+ .then((response) => {
+ if (response?.status === API_STATUS_CODE.OK) {
+ dispatch(setActivityLogs(response?.data));
+ }
+ })
+ .catch((err) => {
+ toast({
+ text1: ToastMessages.GENERIC_ERROR_TOAST,
+ type: 'error',
+ });
+ })
+ .finally(() => dispatch(setActivityLogsLoading(false)));
+};
+
+export const getRcaReasons =
+ (
+ anomalyReferenceId: string,
+ setIsRcaReasonsLoading: React.Dispatch>
+ ) =>
+ (dispatch: AppDispatch) => {
+ const url = getApiUrl(ApiKeys.GET_ANOMALY_RCA_QUESTION, { anomalyReferenceId });
+ axiosInstance
+ .get(url)
+ .then((response) => {
+ if (response?.status === API_STATUS_CODE.OK) {
+ dispatch(setRcaReasons(response?.data));
+ }
+ })
+ .catch((err) => {
+ logError(err);
+ })
+ .finally(() => setIsRcaReasonsLoading(false));
+ };
+
+export const updateAnomaly =
+ (
+ anomalyReferenceId: string,
+ payload: IEtaFormPayload | IRcaFormPayload,
+ callbackFn: () => void
+ ) =>
+ (dispatch: AppDispatch) => {
+ const url = getApiUrl(ApiKeys.UPDATE_ANOMALY_ACTION, { anomalyReferenceId });
+ dispatch(setUpdatingForm(true));
+ axiosInstance
+ .put(url, payload)
+ .then((response) => {
+ if (response.status === API_STATUS_CODE.OK) {
+ callbackFn?.();
+ }
+ })
+ .catch((err) => {
+ logError(err);
+ })
+ .finally(() => dispatch(setUpdatingForm(false)));
+ };
diff --git a/src/screens/Dashboard/AnomalyTracker/AnomlayTracker.tsx b/src/screens/Dashboard/AnomalyTracker/AnomlayTracker.tsx
index 8340986f..91968232 100644
--- a/src/screens/Dashboard/AnomalyTracker/AnomlayTracker.tsx
+++ b/src/screens/Dashboard/AnomalyTracker/AnomlayTracker.tsx
@@ -6,24 +6,22 @@ import CustomTabs from '@rn-ui-lib/components/customTabs/CustomTabs';
import { goBack } from '@components/utlis/navigationUtlis';
import AnomaliesDetailsList from './AnomaliesDetailsList';
import { useAppDispatch } from '@hooks';
-import { getAnomalyDetails } from './utils';
+import { getAnomalyDetails } from './AnomalyTrackerActions';
-interface IAnomalyTracker {}
-
-const AnomalyTracker: React.FC = (props: IAnomalyTracker) => {
+const AnomalyTracker = () => {
const [currentTab, setCurrentTab] = useState(AnomalyType.OPEN);
const dispatch = useAppDispatch();
useEffect(() => {
- dispatch(getAnomalyDetails(AnomalyType.OPEN, {}, true));
+ dispatch(getAnomalyDetails(AnomalyType.OPEN, true));
}, []);
const handleTabChange = (tab: string) => {
if (tab === currentTab) return;
if (tab === AnomalyType.OPEN) {
- dispatch(getAnomalyDetails(AnomalyType.OPEN, {}, true));
+ dispatch(getAnomalyDetails(AnomalyType.OPEN, true));
} else {
- dispatch(getAnomalyDetails(AnomalyType.RESOLVED, {}, true));
+ dispatch(getAnomalyDetails(AnomalyType.RESOLVED, true));
}
setCurrentTab(tab);
};
@@ -36,6 +34,7 @@ const AnomalyTracker: React.FC = (props: IAnomalyTracker) => {
currentTab={currentTab}
onTabChange={handleTabChange}
containerStyle={[getShadowStyle(2), GenericStyles.pt12]}
+ tabContainerStyle={GenericStyles.ml16}
/>
>
diff --git a/src/screens/Dashboard/AnomalyTracker/BottomsheetHeader.tsx b/src/screens/Dashboard/AnomalyTracker/BottomsheetHeader.tsx
index 969a5756..58a665f9 100644
--- a/src/screens/Dashboard/AnomalyTracker/BottomsheetHeader.tsx
+++ b/src/screens/Dashboard/AnomalyTracker/BottomsheetHeader.tsx
@@ -9,9 +9,11 @@ import UpdateIcon from '@assets/icons/UpdateIcon';
interface IBottomsheetHeaderProps {
title: string;
handleClose: () => void;
+ showUpdateButton?: boolean;
+ handleUpdateButtonClick: () => void;
}
const BottomsheetHeader = (props: IBottomsheetHeaderProps) => {
- const { title, handleClose } = props;
+ const { title, handleClose, showUpdateButton = false, handleUpdateButtonClick } = props;
return (
{
View {title}
- {}} //TODO - Redirect toRCA ETA form
- style={[styles.title, styles.gap4]}
- >
-
-
- Update
-
-
+ {showUpdateButton ? (
+
+
+
+ Update
+
+
+ ) : null}
diff --git a/src/screens/Dashboard/AnomalyTracker/DaysTillEscalationComponent.tsx b/src/screens/Dashboard/AnomalyTracker/DaysTillEscalationComponent.tsx
index d063d3af..555e161f 100644
--- a/src/screens/Dashboard/AnomalyTracker/DaysTillEscalationComponent.tsx
+++ b/src/screens/Dashboard/AnomalyTracker/DaysTillEscalationComponent.tsx
@@ -3,6 +3,7 @@ import { View, StyleSheet } from 'react-native';
import Text from '@rn-ui-lib/components/Text';
import { COLORS } from '@rn-ui-lib/colors';
import AnimatedCircularLoaderIcon from '@assets/icons/AnimatedCircularLoaderIcon';
+import EscalatedAnomalyIcon from '@assets/icons/EscalatedAnomalyIcon';
const DaysTillEscalationComponent = (props: {
dayTillEscalation: number;
@@ -19,16 +20,13 @@ const DaysTillEscalationComponent = (props: {
circumference={circumference}
progressPercent={dayTillEscalation > 0 ? progressPercent : 0}
/>
-
+
{dayTillEscalation > 0 ? (
{dayTillEscalation}
) : (
- 0
+
+
+
)}
>
@@ -36,5 +34,12 @@ const DaysTillEscalationComponent = (props: {
};
const styles = StyleSheet.create({
textContainer: { fontSize: 14, color: COLORS.TEXT.YELLOW, fontWeight: '700' },
+ escalationTextContainer: {
+ position: 'absolute',
+ transform: [{ translateX: 82 }],
+ },
+ iconContainer: {
+ transform: [{ translateY: 6 }, { translateX: 4 }],
+ },
});
export default DaysTillEscalationComponent;
diff --git a/src/screens/Dashboard/AnomalyTracker/Forms.tsx/EtaForm.tsx b/src/screens/Dashboard/AnomalyTracker/Forms.tsx/EtaForm.tsx
new file mode 100644
index 00000000..c12d33e2
--- /dev/null
+++ b/src/screens/Dashboard/AnomalyTracker/Forms.tsx/EtaForm.tsx
@@ -0,0 +1,151 @@
+import React from 'react';
+import { View, StyleSheet, SafeAreaView, ScrollView, ActivityIndicator } from 'react-native';
+import NavigationHeader, { Icon } from '@rn-ui-lib/components/NavigationHeader';
+import { GenericStyles } from '@rn-ui-lib/styles';
+import { goBack, navigateToScreen } from '@components/utlis/navigationUtlis';
+import Button from '@rn-ui-lib/components/Button';
+import { useForm } from 'react-hook-form';
+import FormInput from '@common/FormInput';
+import { AnswerType } from '@components/form/interface';
+import { useAppDispatch, useAppSelector } from '@hooks';
+import { getAnomalyDetails, updateAnomaly } from '../AnomalyTrackerActions';
+import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack';
+import { PageRouteEnum } from '@screens/auth/ProtectedRouter';
+import { toast } from '@rn-ui-lib/components/toast';
+import { dateFormat, ISO_DATE_FORMAT } from '@rn-ui-lib/utils/dates';
+import { COLORS } from '@rn-ui-lib/colors';
+import { AnomalyType, VALIDATION_ERROR_MESSAGES } from '../constants';
+import { IEtaFormData } from '../interfaces';
+import { getLastDateOfNextMonth } from './utils';
+
+interface IEtaForm {
+ route: {
+ params: {
+ selectedAnomalyId: string;
+ };
+ };
+}
+const EtaForm = (props: IEtaForm) => {
+ const { selectedAnomalyId } = props.route.params || {};
+ const showLoader = useAppSelector((state) => state?.anomalyTracker?.updatingForm);
+ const dispatch = useAppDispatch();
+ const {
+ control,
+ reset,
+ formState: { isValid },
+ handleSubmit,
+ } = useForm({
+ defaultValues: {
+ at: '',
+ reason: '',
+ },
+ mode: 'onBlur',
+ });
+ const successCallback = () => {
+ reset();
+ toast({
+ text1: 'ETA submitted successfully',
+ type: 'success',
+ });
+ dispatch(getAnomalyDetails(AnomalyType.OPEN, true));
+ navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
+ screen: CaseDetailStackEnum.ANOMALY_TRACKER,
+ });
+ };
+ const submitETA = (data: IEtaFormData) => {
+ dispatch(updateAnomaly(selectedAnomalyId, { eta: data }, successCallback));
+ };
+
+ const maxDate = dateFormat(getLastDateOfNextMonth(), ISO_DATE_FORMAT);
+
+ return (
+
+
+ {showLoader ? (
+
+
+
+ ) : (
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ );
+};
+export const styles = StyleSheet.create({
+ container: {
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'flex-end',
+ borderTopColor: COLORS.BORDER.PRIMARY,
+ borderBottomColor: COLORS.BORDER.PRIMARY,
+ },
+ header: { fontSize: 16, fontWeight: '600' },
+});
+export default EtaForm;
diff --git a/src/screens/Dashboard/AnomalyTracker/Forms.tsx/RcaForm.tsx b/src/screens/Dashboard/AnomalyTracker/Forms.tsx/RcaForm.tsx
new file mode 100644
index 00000000..20e4f41c
--- /dev/null
+++ b/src/screens/Dashboard/AnomalyTracker/Forms.tsx/RcaForm.tsx
@@ -0,0 +1,156 @@
+import React, { useEffect, useState } from 'react';
+import { View, StyleSheet, SafeAreaView, ScrollView, ActivityIndicator } from 'react-native';
+import NavigationHeader, { Icon } from '@rn-ui-lib/components/NavigationHeader';
+import { GenericStyles } from '@rn-ui-lib/styles';
+import { goBack, navigateToScreen } from '@components/utlis/navigationUtlis';
+import Button from '@rn-ui-lib/components/Button';
+import { useForm } from 'react-hook-form';
+import FormInput from '@common/FormInput';
+import { AnswerType } from '@components/form/interface';
+import { useAppDispatch, useAppSelector } from '@hooks';
+import { getAnomalyDetails, getRcaReasons, updateAnomaly } from '../AnomalyTrackerActions';
+import { toast } from '@rn-ui-lib/components/toast';
+import { PageRouteEnum } from '@screens/auth/ProtectedRouter';
+import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack';
+import { COLORS } from '@rn-ui-lib/colors';
+import { AnomalyType, VALIDATION_ERROR_MESSAGES } from '../constants';
+import { IRcaFormData } from '../interfaces';
+
+interface IRcaForm {
+ route: {
+ params: {
+ selectedAnomalyId: string;
+ };
+ };
+}
+
+const RcaForm = (props: IRcaForm) => {
+ const { selectedAnomalyId } = props.route.params || {};
+ const dispatch = useAppDispatch();
+
+ const {
+ control,
+ reset,
+ formState: { isValid },
+ handleSubmit,
+ } = useForm({
+ defaultValues: {
+ comment: '',
+ reason: '',
+ },
+ mode: 'onBlur',
+ });
+ const [rcaReasonsLoading, setIsRcaReasonsLoading] = useState(true);
+ const rcaReasons = useAppSelector((state) => state?.anomalyTracker?.rcaReasons);
+ const showLoader = useAppSelector((state) => state?.anomalyTracker?.updatingForm);
+
+ useEffect(() => {
+ if (selectedAnomalyId) {
+ dispatch(getRcaReasons(selectedAnomalyId, setIsRcaReasonsLoading));
+ }
+ }, [selectedAnomalyId]);
+
+ const successCallback = () => {
+ reset();
+ toast({
+ text1: 'RCA submitted successfully',
+ type: 'success',
+ });
+ dispatch(getAnomalyDetails(AnomalyType.OPEN, true));
+ navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
+ screen: CaseDetailStackEnum.ANOMALY_TRACKER,
+ });
+ };
+ const submitRCA = (data: IRcaFormData) => {
+ dispatch(updateAnomaly(selectedAnomalyId, { rca: data }, successCallback));
+ };
+
+ return (
+
+
+ {showLoader || rcaReasonsLoading ? (
+
+
+
+ ) : (
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ );
+};
+export const styles = StyleSheet.create({
+ container: {
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'flex-end',
+ borderTopColor: COLORS.BORDER.PRIMARY,
+ borderBottomColor: COLORS.BORDER.PRIMARY,
+ },
+ header: { fontSize: 16, fontWeight: '600' },
+});
+export default RcaForm;
diff --git a/src/screens/Dashboard/AnomalyTracker/Forms.tsx/utils.ts b/src/screens/Dashboard/AnomalyTracker/Forms.tsx/utils.ts
new file mode 100644
index 00000000..62b4c69e
--- /dev/null
+++ b/src/screens/Dashboard/AnomalyTracker/Forms.tsx/utils.ts
@@ -0,0 +1,6 @@
+export const getLastDateOfNextMonth = () => {
+ const todaysDate = new Date();
+ const nextMonth = new Date(todaysDate.getFullYear(), todaysDate.getMonth() + 1, 1);
+ const lastDateOfNextMonth = new Date(nextMonth.getFullYear(), nextMonth.getMonth() + 1, 0);
+ return lastDateOfNextMonth;
+};
diff --git a/src/screens/Dashboard/AnomalyTracker/RcaEtaContainer.tsx b/src/screens/Dashboard/AnomalyTracker/RcaEtaContainer.tsx
index 55c556a9..7f787de2 100644
--- a/src/screens/Dashboard/AnomalyTracker/RcaEtaContainer.tsx
+++ b/src/screens/Dashboard/AnomalyTracker/RcaEtaContainer.tsx
@@ -1,82 +1,103 @@
import { COLORS } from '@rn-ui-lib/colors';
-import React, { useEffect, useState } from 'react';
-import { View, StyleSheet } from 'react-native';
+import React, { useState } from 'react';
+import { View, StyleSheet, ScrollView, Pressable } from 'react-native';
import BottomSheetWrapper from '@common/BottomSheetWrapper';
import { AnomalyType } from './constants';
-import { useAppDispatch } from '@hooks';
-import { getActivityLogs } from './utils';
import dayjs from 'dayjs';
import { BUSINESS_DATE_FORMAT } from '@rn-ui-lib/utils/dates';
import RcaEtaActionRow from './RcaEtaActionRow';
import BottomsheetHeader from './BottomsheetHeader';
import ViewRcaEtaDetails from './ViewRcaEtaDetails';
-import { AnomalyItem } from './interfaces';
-
-interface IRcaEtaContainerProps {
- item: AnomalyItem;
- anomalyType: string;
-}
+import { ANOMALY_ACTIONS, IRcaEtaContainerProps } from './interfaces';
+import { navigateToScreen } from '@components/utlis/navigationUtlis';
+import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack';
+import { GenericStyles } from '@rn-ui-lib/styles';
const RcaEtaContainer = (props: IRcaEtaContainerProps) => {
const { item, anomalyType } = props;
const [showETABottomSheet, setShowETABottomSheet] = useState(false);
const [showRCABottomSheet, setShowRCABottomSheet] = useState(false);
- const [selectedAnomalyId, setSelectedAnomalyId] = useState('');
- const dispatch = useAppDispatch();
+ const selectedAnomalyId = item?.anomalyReferenceId as string;
+
+ const isEtaFilled = item?.estimatedTime || anomalyType === AnomalyType.RESOLVED;
+ const isRcaFilled = item?.rca || anomalyType === AnomalyType.RESOLVED;
const onETAClick = () => {
- if (!(item?.estimatedTime || anomalyType === AnomalyType.RESOLVED)) return; //TODO - Redirect to fill ETA form
- setSelectedAnomalyId(item?.anomalyReferenceId as string);
+ if (!isEtaFilled) {
+ navigateToScreen(CaseDetailStackEnum.ETA_FORM, { selectedAnomalyId });
+ return;
+ }
setShowETABottomSheet(true);
};
+
const onRCAClick = () => {
- if (!(item?.rca || anomalyType === AnomalyType.RESOLVED)) return; //TODO - Redirect to fill ETA form
- setSelectedAnomalyId(item?.anomalyReferenceId as string);
+ if (!isRcaFilled) {
+ navigateToScreen(CaseDetailStackEnum.RCA_FORM, { selectedAnomalyId });
+ return;
+ }
setShowRCABottomSheet(true);
};
+
const etaStatus = item?.estimatedTime
? dayjs(item?.estimatedTime?.at)?.format(BUSINESS_DATE_FORMAT)
: 'Unfilled';
const handleClose = () => {
- setShowRCABottomSheet(false);
+ if (showRCABottomSheet) {
+ setShowRCABottomSheet(false);
+ return;
+ }
setShowETABottomSheet(false);
- setSelectedAnomalyId('');
};
- useEffect(() => {
- if (selectedAnomalyId) dispatch(getActivityLogs(selectedAnomalyId));
- }, [selectedAnomalyId]);
+ const handleUpdateButtonClick = () => {
+ if (showRCABottomSheet) {
+ navigateToScreen(CaseDetailStackEnum.RCA_FORM, { selectedAnomalyId });
+ } else {
+ navigateToScreen(CaseDetailStackEnum.ETA_FORM, { selectedAnomalyId });
+ }
+ };
return (
(
-
+
+
+
)}
allowBackdropClose={true}
setVisible={handleClose}
- heightPercentage={showETABottomSheet ? 26 : 30}
+ heightPercentage={showETABottomSheet ? 28 : 32}
>
-
+
+
+
+
+
);
diff --git a/src/screens/Dashboard/AnomalyTracker/SingleAnomalyDetails.tsx b/src/screens/Dashboard/AnomalyTracker/SingleAnomalyDetails.tsx
index 09e18aa8..4e073025 100644
--- a/src/screens/Dashboard/AnomalyTracker/SingleAnomalyDetails.tsx
+++ b/src/screens/Dashboard/AnomalyTracker/SingleAnomalyDetails.tsx
@@ -23,12 +23,18 @@ const SingleAnomalyDetails = (props: ISingleAnomalyDetailsProps) => {
Created on
- {sanitizeString(dateFormat(new Date(item?.createdAt as string), BUSINESS_DATE_FORMAT))}
+ {sanitizeString(
+ item?.createdAt
+ ? dateFormat(new Date(item?.createdAt as string), BUSINESS_DATE_FORMAT)
+ : ''
+ )}
{anomalyType === AnomalyType.OPEN ? (
- Days till Escalation
+
+ Days till Escalation
+
{
Resolved on
- {sanitizeString(dateFormat(new Date(item?.resolution?.at), BUSINESS_DATE_FORMAT))}
+ {sanitizeString(
+ item?.resolution?.at
+ ? dateFormat(new Date(item?.resolution?.at), BUSINESS_DATE_FORMAT)
+ : ''
+ )}
)}
diff --git a/src/screens/Dashboard/AnomalyTracker/ViewRcaEtaDetails.tsx b/src/screens/Dashboard/AnomalyTracker/ViewRcaEtaDetails.tsx
index 22dc3135..b936d49f 100644
--- a/src/screens/Dashboard/AnomalyTracker/ViewRcaEtaDetails.tsx
+++ b/src/screens/Dashboard/AnomalyTracker/ViewRcaEtaDetails.tsx
@@ -1,57 +1,87 @@
-import React from 'react';
-import { View, StyleSheet } from 'react-native';
+import React, { useEffect } from 'react';
+import { View, StyleSheet, ActivityIndicator } from 'react-native';
import RcaEtaQuestionRenderer from './RcaEtaQuestionRenderer';
import dayjs from 'dayjs';
import { BUSINESS_DATE_FORMAT } from '@rn-ui-lib/utils/dates';
-import { useAppSelector } from '@hooks';
+import { useAppDispatch, useAppSelector } from '@hooks';
import { GenericStyles } from '@rn-ui-lib/styles';
import { DATE_TIME_FORMAT, RCA_ETA_FORM_QUESTIONS } from './constants';
+import { ActivityLog, ANOMALY_ACTIONS, EtaActivityLog, RcaActivityLog } from './interfaces';
+import { COLORS } from '@rn-ui-lib/colors';
+import { getActivityLogs } from './AnomalyTrackerActions';
-const ViewRcaEtaDetails = (props: { showETABottomSheet: boolean }) => {
- const { showETABottomSheet } = props;
- const anomalyDetails = useAppSelector((state) => state?.anomalyTracker?.anomalyDetails?.data);
- const { estimatedTime } = anomalyDetails || {};
- const rcaDetails = useAppSelector((state) => state?.anomalyTracker?.acitvityLogs?.data); //To do same for eta after backend changes
- const { details, type } = rcaDetails?.[0] || {};
+const ViewRcaEtaDetails = (props: { showETABottomSheet: boolean; selectedAnomalyId: string }) => {
+ const { showETABottomSheet, selectedAnomalyId } = props;
+ const dispatch = useAppDispatch();
+ const activityLogs: ActivityLog[] | undefined = useAppSelector(
+ (state) => state?.anomalyTracker?.acitvityLogs?.data
+ );
+ const activityLogsLoading = useAppSelector(
+ (state) => state?.anomalyTracker?.acitvityLogs?.loading
+ );
- if (showETABottomSheet)
+ useEffect(() => {
+ dispatch(getActivityLogs(selectedAnomalyId));
+ }, []);
+
+ if (activityLogsLoading)
return (
-
-
-
-
+
+
);
+ if (showETABottomSheet) {
+ const etaData = activityLogs?.find(
+ (item) => item.type === ANOMALY_ACTIONS.ETA
+ ) as EtaActivityLog;
+ const { details: etaDetails } = etaData || {};
+
+ return (
+
+
+
+
+
+ );
+ }
+
+ const rcaData = activityLogs?.find((item) => item.type === ANOMALY_ACTIONS.RCA) as RcaActivityLog;
+ const { details: rcaDetails } = rcaData || {};
+
return (
-
+
);
};
const styles = StyleSheet.create({
- mv24: { paddingVertical: 24 },
+ mv8: { marginVertical: 8 },
+ position: { flex: 1, marginTop: 62 },
});
export default ViewRcaEtaDetails;
diff --git a/src/screens/Dashboard/AnomalyTracker/constants.ts b/src/screens/Dashboard/AnomalyTracker/constants.ts
index 494be756..eb40d546 100644
--- a/src/screens/Dashboard/AnomalyTracker/constants.ts
+++ b/src/screens/Dashboard/AnomalyTracker/constants.ts
@@ -40,3 +40,15 @@ export const RCA_ETA_FORM_QUESTIONS = {
DATE: 'Date',
REASON: 'Reason',
};
+
+export const VALIDATION_ERROR_MESSAGES = {
+ REQUIRED: 'This field is required',
+ MIN_LENGTH: 'Enter at least 20 characters',
+ REASON_REQUIRED: 'Please select a reason',
+ DATE: 'Please select a date',
+};
+
+export const FORM_STATUS = {
+ FILLED: 'Filled',
+ UNFILLED: 'Unfilled',
+};
diff --git a/src/screens/Dashboard/AnomalyTracker/interfaces.ts b/src/screens/Dashboard/AnomalyTracker/interfaces.ts
index 0a8916d6..875f81a2 100644
--- a/src/screens/Dashboard/AnomalyTracker/interfaces.ts
+++ b/src/screens/Dashboard/AnomalyTracker/interfaces.ts
@@ -7,15 +7,108 @@ export interface AnomalyItem {
subtype?: string;
priority?: string;
anomalyDetectedOn?: string;
- raisedFor?: {};
+ raisedFor?: {
+ name: string;
+ id: string;
+ allocations: number;
+ agencyCode: string;
+ agencyName: string;
+ phoneNumber: string;
+ };
anomalyReferenceId?: string;
- resolution?: {};
- estimatedTime?: {};
- rca?: {};
+ resolution?: {
+ at: string;
+ type: string;
+ name: string;
+ };
+ estimatedTime?: IEstimatedTime;
+ rca?: IRca;
resolutionTime?: string;
resolutionType?: string;
}
+export interface PagesData {
+ pageNo: number;
+ totalPages: number;
+ pageSize: number;
+ totalElements: number;
+}
+
+export interface AnomalyResponse {
+ data: AnomalyItem[];
+ pages: PagesData;
+}
+
export interface AnomalyCardHeaderProps {
item: AnomalyItem;
}
+
+export interface IEstimatedTime {
+ at: string;
+ by: string;
+ reason: string;
+ status: string;
+}
+
+export interface IRca {
+ at: string;
+ by: string;
+}
+
+export interface ActivityDetails {
+ name: string;
+ at: string;
+ by: string;
+ reason: string;
+ comment?: string;
+}
+
+export interface RcaActivityLog {
+ type: ANOMALY_ACTIONS.RCA;
+ details: ActivityDetails;
+}
+
+export interface EtaActivityLog {
+ type: ANOMALY_ACTIONS.ETA;
+ details: ActivityDetails;
+}
+
+export type ActivityLog = RcaActivityLog | EtaActivityLog;
+
+export interface IRcaEtaContainerProps {
+ item: AnomalyItem;
+ anomalyType: string;
+}
+
+export interface IEtaFormPayload {
+ eta: {
+ at: string;
+ reason: string;
+ };
+}
+export interface IRcaFormPayload {
+ rca: {
+ comment: string;
+ reason: string;
+ };
+}
+
+export interface IOption {
+ label: string;
+ value: string;
+}
+
+export enum ANOMALY_ACTIONS {
+ RCA = 'RCA',
+ ETA = 'ETA',
+}
+
+export interface IEtaFormData {
+ at: string;
+ reason: string;
+}
+
+export interface IRcaFormData {
+ comment: string;
+ reason: string;
+}
diff --git a/src/screens/Dashboard/AnomalyTracker/utils.ts b/src/screens/Dashboard/AnomalyTracker/utils.ts
deleted file mode 100644
index 0fcca877..00000000
--- a/src/screens/Dashboard/AnomalyTracker/utils.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import axiosInstance, { API_STATUS_CODE, ApiKeys, getApiUrl } from '@components/utlis/apiHelper';
-import { AnomalyType } from './constants';
-import { logError } from '@components/utlis/errorUtils';
-
-import { AppDispatch } from '@store';
-import {
- setActivityLogs,
- setActivityLogsLoading,
- setAnomalyDetailsLoading,
- setClosedAnomalyList,
- setOpenAnomalyList,
-} from '@reducers/anomalyTrackerSlice';
-
-export const getAnomalyDetails =
- (anomalyType: string, payload: {}, isLoading: boolean) => (dispatch: AppDispatch) => {
- const url = getApiUrl(ApiKeys.GET_ANOMALY_DETAILS);
- if (isLoading) dispatch(setAnomalyDetailsLoading(true));
- axiosInstance
- .get(url, {
- params: { status: anomalyType },
- })
- .then((res) => {
- if (res?.status === API_STATUS_CODE.OK) {
- if (anomalyType === AnomalyType.OPEN) {
- dispatch(setOpenAnomalyList(res?.data));
- return;
- }
- dispatch(setClosedAnomalyList(res?.data));
- }
- })
- .catch((err) => {
- logError(err);
- })
- .finally(() => {
- dispatch(setAnomalyDetailsLoading(false));
- });
- };
-
-export const getActivityLogs = (anomalyReferenceId: string) => (dispatch: AppDispatch) => {
- const url = getApiUrl(ApiKeys.GET_ANOMALY_ACTIVITY_LOG, { anomalyReferenceId });
- dispatch(setActivityLogsLoading(true));
- axiosInstance
- .get(url)
- .then((response) => {
- if (response.status === API_STATUS_CODE.OK) {
- dispatch(setActivityLogs(response?.data));
- }
- })
- .catch((err) => {
- logError(err);
- })
- .finally(() => dispatch(setActivityLogsLoading(false)));
-};
diff --git a/src/screens/Dashboard/InternalAgentDashboard.tsx b/src/screens/Dashboard/InternalAgentDashboard.tsx
index 7d9bb24d..abfc32da 100644
--- a/src/screens/Dashboard/InternalAgentDashboard.tsx
+++ b/src/screens/Dashboard/InternalAgentDashboard.tsx
@@ -20,11 +20,16 @@ const InternalAgentDashboard = () => {
const totalClosedAnomalies =
useAppSelector((state) => state?.anomalyTracker?.closedAnomaliesList?.pages?.totalElements) ||
0;
+ const enableFieldAppAnomalyTracker = useAppSelector(
+ (state) => state?.user?.featureFlags?.enableFieldAppAnomalyTracker
+ );
const isOpenOrClosedAnomaliesPresent = totalOpenAnomalies + totalClosedAnomalies > 0;
return (
<>
- {isOpenOrClosedAnomaliesPresent ? : null}
+ {enableFieldAppAnomalyTracker && isOpenOrClosedAnomaliesPresent ? (
+
+ ) : null}
diff --git a/src/screens/Dashboard/index.tsx b/src/screens/Dashboard/index.tsx
index 10c32576..8d6cbb91 100644
--- a/src/screens/Dashboard/index.tsx
+++ b/src/screens/Dashboard/index.tsx
@@ -16,7 +16,7 @@ import { addClickstreamEvent } from '../../services/clickstreamEventService';
import DashboardHeader from './DashboardHeader';
import ExternalAgentDashboard from './ExternalAgentDashboard';
import InternalAgentDashboard from './InternalAgentDashboard';
-import { getAnomalyDetails } from './AnomalyTracker/utils';
+import { getAnomalyDetails } from './AnomalyTracker/AnomalyTrackerActions';
import { AnomalyType } from './AnomalyTracker/constants';
const Dashboard = () => {
@@ -32,15 +32,14 @@ const Dashboard = () => {
dispatch(
getPerformanceMetrics(Object.keys(caseDetailsIds ?? {}), isExternalAgent, setIsLoading)
);
- // TODO: Uncomment when api is added by backend
- // if (!isExternalAgent) {
- // dispatch(getAnomalyDetails(AnomalyType.OPEN, {}, false));
- // dispatch(getAnomalyDetails(AnomalyType.RESOLVED, {}, false));
- // }
};
useEffect(() => {
fetchAgentPerformanceMetrics();
+ if (!isExternalAgent) {
+ dispatch(getAnomalyDetails(AnomalyType.OPEN, false));
+ dispatch(getAnomalyDetails(AnomalyType.RESOLVED, false));
+ }
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_PERFORMANCE_DASHBOARD_PAGE_LOAD, {});
}, []);
diff --git a/src/screens/caseDetails/CaseDetailStack.tsx b/src/screens/caseDetails/CaseDetailStack.tsx
index 6c22f3d6..ff91bc50 100644
--- a/src/screens/caseDetails/CaseDetailStack.tsx
+++ b/src/screens/caseDetails/CaseDetailStack.tsx
@@ -33,6 +33,8 @@ import OtherAddresses from '@screens/addresses/otherAddresses/OtherAddresses';
import Escalations from '@screens/escalations/Escalations';
import TopAddressMapView from '@screens/MapView/TopAddress';
import AnomalyTracker from '@screens/Dashboard/AnomalyTracker/AnomlayTracker';
+import RcaForm from '@screens/Dashboard/AnomalyTracker/Forms.tsx/RcaForm';
+import EtaForm from '@screens/Dashboard/AnomalyTracker/Forms.tsx/EtaForm';
const Stack = createNativeStackNavigator();
@@ -62,7 +64,9 @@ export enum CaseDetailStackEnum {
MAP_VIEW_TOP_ADDRESS = 'mapViewTopAddress',
OTHER_ADDRESSES = 'OtherAddresses',
ESCALATIONS = 'Escalations',
- ANOMALY_TRACKER = 'ANOMALY_TRACKER',
+ ANOMALY_TRACKER = "anomalyTracker",
+ RCA_FORM = 'rcaForm',
+ ETA_FORM = 'etaForm',
}
const CaseDetailStack = () => {
@@ -130,6 +134,8 @@ const CaseDetailStack = () => {
+
+
);
};
diff --git a/src/screens/notifications/NotificationItem.tsx b/src/screens/notifications/NotificationItem.tsx
index 40264fd2..f4055efb 100644
--- a/src/screens/notifications/NotificationItem.tsx
+++ b/src/screens/notifications/NotificationItem.tsx
@@ -127,6 +127,9 @@ const getRevivalNotificationHeading = {
const NotificationItem: React.FC = ({ data }) => {
const { id, clickable, template, scheduledAt, collectionCaseId, params, headerLabel } = data;
+ const enableFieldAppAnomalyTracker = useAppSelector(
+ (state) => state?.user?.featureFlags?.enableFieldAppAnomalyTracker
+ );
if (headerLabel) {
return (
@@ -200,6 +203,15 @@ const NotificationItem: React.FC = ({ data }) => {
return;
}
+ if (templateName === NotificationTypes.ANOMALY_TRACKER_DETECTION) {
+ if (enableFieldAppAnomalyTracker) {
+ navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
+ screen: CaseDetailStackEnum.ANOMALY_TRACKER,
+ });
+ }
+ return;
+ }
+
const agentRevivalNotificationAction = AgentRevivalNotificationTemplateActionMap[templateName];
if (agentRevivalNotificationAction) {
handleRevivalNotificationNavigation(agentRevivalNotificationAction as string, id);