diff --git a/src/assets/icons/FlagIcon.tsx b/src/assets/icons/FlagIcon.tsx new file mode 100644 index 00000000..86a7db79 --- /dev/null +++ b/src/assets/icons/FlagIcon.tsx @@ -0,0 +1,31 @@ +import { IconProps } from "@rn-ui-lib/icons/types" +import * as React from "react" +import Svg, { Path, Mask, G } from "react-native-svg" + +const FlagIcon : React.FC = ({ fillColor = 'E92C2C' }) => ( + + + + + + + + +); + +export default FlagIcon diff --git a/src/common/Constants.ts b/src/common/Constants.ts index 5e3be6b2..bb434ce5 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -456,7 +456,10 @@ export const CLICKSTREAM_EVENT_NAMES = { name: 'FA_VIEW_PAST_FEEDBACK_PREV_PAGE_FAILED', description: 'FA_VIEW_PAST_FEEDBACK_PREV_PAGE_FAILED', }, - FA_VIEW_PHOTO_CLICKED: { name: 'FA_VIEW_PHOTO_CLICKED', description: 'FA_VIEW_PHOTO_CLICKED' }, + FA_VIEW_PHOTO_CLICKED: { + name: 'FA_VIEW_PHOTO_CLICKED', + description: 'FA_VIEW_PHOTO_CLICKED' + }, FA_CUSTOMER_DOCUMENT_CLICKED: { name: 'FA_CUSTOMER_DOCUMENT_CLICKED', description: 'FA_CUSTOMER_DOCUMENT_CLICKED', @@ -494,6 +497,15 @@ export const CLICKSTREAM_EVENT_NAMES = { name: 'FA_PERFORMANCE_DASHBOARD_PERFORMANCE_GRAPH_CLICKED', description: 'When the user clicks on expand/collapse of the performance graph', }, + FA_VIEW_ALL_ESCALATIONS_SCREEN_CLICKED: { + name: 'FA_VIEW_ALL_ESCALATIONS_SCREEN_CLICKED', + description: 'FA_VIEW_ALL_ESCALATIONS_SCREEN_CLICKED', + }, + FA_VIEW_ALL_ESCALATIONS_SCREEN_LANDED: { + name: 'FA_VIEW_ALL_ESCALATIONS_SCREEN_LANDED', + description: 'FA_VIEW_ALL_ESCALATIONS_SCREEN_LANDED', + }, + // Notifications FA_NOTIFICATION_ICON_CLICK: { diff --git a/src/components/utlis/apiHelper.ts b/src/components/utlis/apiHelper.ts index 89aeac03..465e462f 100644 --- a/src/components/utlis/apiHelper.ts +++ b/src/components/utlis/apiHelper.ts @@ -357,7 +357,7 @@ axiosInstance.interceptors.response.use( if ([API_STATUS_CODE.UNAUTHORIZED, API_STATUS_CODE.FORBIDDEN].includes(response.status)) { // Reset user info - dispatch(handleLogout()); + // dispatch(handleLogout()); } // Blocking cosmos after operative hours diff --git a/src/constants/config.js b/src/constants/config.js index df82b252..1e348c9a 100644 --- a/src/constants/config.js +++ b/src/constants/config.js @@ -1,6 +1,6 @@ import { MILLISECONDS_IN_A_MINUTE, MINUTES_IN_AN_HOUR } from '../../RN-UI-LIB/src/utlis/common'; -export const BASE_AV_APP_URL = 'https://qa-longhorn-portal.np.navi-tech.in/field-app'; +export const BASE_AV_APP_URL = 'https://qa-longhorn-server.np.navi-ppl.in/field-app'; export const SENTRY_DSN = 'https://acef93c884c1424cacc4ec899562e203@qa-longhorn-portal.np.navi-tech.in/glitchtip-events/173'; export const JANUS_SERVICE_URL = 'https://qa-longhorn-portal.np.navi-tech.in/api/events/json'; diff --git a/src/screens/allCases/ListItem.tsx b/src/screens/allCases/ListItem.tsx index 6abc086c..db0b4c94 100644 --- a/src/screens/allCases/ListItem.tsx +++ b/src/screens/allCases/ListItem.tsx @@ -13,7 +13,6 @@ import { import CaseItemAvatar from './CaseItemAvatar'; import { CaseStatuses, - displayStatuses, InteractionStatuses, TaskTitleUIMapping, ICaseItemAvatarCaseDetailObj, @@ -34,6 +33,7 @@ import relativeDistanceFormatter from '@screens/addressGeolocation/utils/relativ import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack'; import { PageRouteEnum } from '@screens/auth/ProtectedRouter'; import LocationDistanceIcon from '@assets/icons/LocationDistanceIcon'; +import FlagIcon from '@assets/icons/FlagIcon'; interface IListItem { caseListItemDetailObj: ICaseItemCaseDetailObj; @@ -82,7 +82,6 @@ const ListItem: React.FC = (props) => { isSynced, isNewlyAdded, interactionStatus, - caseVerdict, totalOverdueAmount, distanceInKm, } = caseListItemDetailObj; @@ -192,7 +191,7 @@ const ListItem: React.FC = (props) => { !isTeamLead && !nearbyCaseView; - const is1To30FieldAgent = useAppSelector((state) => state.user?.is1To30FieldAgent); + const is1To30FieldAgent = useAppSelector((state) => state.user?.is1To30FieldAgent); const distanceMapOfNearbyCases = useAppSelector((state) => state.nearbyCasesSlice.caseReferenceIdToDistanceMap) || {}; const selectedTab = useAppSelector((state) => state?.nearbyCasesSlice?.sortTabSelected); @@ -203,11 +202,21 @@ const ListItem: React.FC = (props) => { width: showInVisitPlanTag ? TAG_CONTAINER_WIDTH.VISIT_PLAN_TAG : showVisitPlanBtn - ? TAG_CONTAINER_WIDTH.VISIT_PLAN_BUTTON - : TAG_CONTAINER_WIDTH.DEFAULT, + ? TAG_CONTAINER_WIDTH.VISIT_PLAN_BUTTON + : TAG_CONTAINER_WIDTH.DEFAULT, }; + + const isEscalationCase = true; + const isActiveEscalationCase = true; + const isPastEscalationCase = false; + const escalationCount = 4; + const activeEscalationCaseCount = 2; + const pastEscalationCaseCount = 3; + const totalEscalationCaseCount = activeEscalationCaseCount + pastEscalationCaseCount; + return ( + = (props) => { backgroundColor: isNewlyAdded ? COLORS.BACKGROUND.ORANGE : isCaseSelected - ? COLORS.BACKGROUND.SILVER - : COLORS.BACKGROUND.PRIMARY, + ? COLORS.BACKGROUND.SILVER + : COLORS.BACKGROUND.PRIMARY, }, ]} > + {isEscalationCase ? ( + + + + {`${totalEscalationCaseCount} `}{isActiveEscalationCase ? 'Active Escalations' : 'Past Escalations'} + + + ) : null} + + { @@ -101,6 +103,7 @@ const CaseDetailStack = () => { component={FeedbackDetailContainer} /> + diff --git a/src/screens/caseDetails/CollectionCaseDetail.tsx b/src/screens/caseDetails/CollectionCaseDetail.tsx index a2131655..b9fddf67 100644 --- a/src/screens/caseDetails/CollectionCaseDetail.tsx +++ b/src/screens/caseDetails/CollectionCaseDetail.tsx @@ -6,7 +6,7 @@ import CaseDetailsHeader from './CaseDetailHeader'; import UserDetailsSection from './UserDetailsSection'; import Layout from '../layout/Layout'; import { _map } from '../../../RN-UI-LIB/src/utlis/common'; -import { AppDispatch, RootState } from '../../store/store'; +import { RootState } from '../../store/store'; import { getCaseUnifiedData, UnifiedCaseDetailsTypes } from '../../action/caseApiActions'; import useIsOnline from '../../hooks/useIsOnline'; import { CLICKSTREAM_EVENT_NAMES } from '../../common/Constants'; @@ -21,10 +21,8 @@ import CollectionCaseDetailFooter from './CollectionCaseDetailFooter'; import FeedbackDetailsSection from './FeedbackDetailsSection'; import { COLORS } from '@rn-ui-lib/colors'; import { syncActiveCallDetails } from '@actions/callRecordingActions'; -import { getCustomerDocuments } from '@screens/allCases/utils'; -import { logError } from '@components/utlis/errorUtils'; -import { GenericObject, GenericType } from '@common/GenericTypes'; import { getUngroupedAddress } from '@actions/addressGeolocationAction'; +import EscalationsSection from '@screens/escalations/EscalationsSection'; interface ICaseDetails { route: { @@ -129,6 +127,7 @@ const CollectionCaseDetails: React.FC = (props) => { > + diff --git a/src/screens/escalations/Escalations.tsx b/src/screens/escalations/Escalations.tsx new file mode 100644 index 00000000..0a2d5932 --- /dev/null +++ b/src/screens/escalations/Escalations.tsx @@ -0,0 +1,345 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { ScrollView, StyleSheet, View } from 'react-native'; +import { CLICKSTREAM_EVENT_NAMES } from '../../common/Constants'; +import { ToastMessages } from '../allCases/constants'; +import useIsOnline from '../../hooks/useIsOnline'; +import { addClickstreamEvent } from '../../services/clickstreamEventService'; +import { goBack } from '../../components/utlis/navigationUtlis'; +import { toast } from '../../../RN-UI-LIB/src/components/toast'; +import { GenericStyles, SCREEN_HEIGHT, getShadowStyle } from '../../../RN-UI-LIB/src/styles'; +import NavigationHeader from '../../../RN-UI-LIB/src/components/NavigationHeader'; +import SuspenseLoader from '../../../RN-UI-LIB/src/components/suspense_loader/SuspenseLoader'; +import LineLoader from '../../../RN-UI-LIB/src/components/suspense_loader/LineLoader'; +import Text from '../../../RN-UI-LIB/src/components/Text'; +import { COLORS } from '../../../RN-UI-LIB/src/styles/colors'; +import Pagination from '../../../RN-UI-LIB/src/components/pagination/Pagination'; +import { GenericObject } from '@common/GenericTypes'; +import FlagIcon from '@assets/icons/FlagIcon'; +import Tag, { TagVariant } from '@rn-ui-lib/components/Tag'; + +const Escalations = () => { + + const [escalationsList, setEscalationsList] = useState([]); + const [totalPage, setTotalPage] = useState(0); + const [loading, setLoading] = useState(false); + const [currentPage, setCurrentPage] = useState(1); + + const isOnline = useIsOnline(); + + const getAllEscalations = useCallback(() => { + setTotalPage(escalationsList.length) + }, [currentPage]); + + useEffect(() => { + setLoading(true); + setEscalationsList([{ + id: 1, + title: 'Physical assault/threatening to physically assault', + raisedOn: '9 May, 2024', + time: '2:29 PM', + status: 'Closed', + description: 'Extension of time for paying dues.', + isActiveEscalation: false, // Closed = not active + }, + { + id: 2, + title: 'Miscommunication about loan terms', + raisedOn: '15 April, 2024', + time: '10:15 AM', + status: 'In Progress', + description: 'Clarification required regarding interest rates.', + isActiveEscalation: true, // In Progress = active + }, + { + id: 3, + title: 'Unauthorized access to account', + raisedOn: '28 March, 2024', + time: '4:45 PM', + status: 'Open', + description: 'Suspicious activity detected in the bank account.', + isActiveEscalation: true, // Open = active + }, + { + id: 4, + title: 'Delayed processing of payment', + raisedOn: '5 March, 2024', + time: '1:00 PM', + status: 'Closed', + description: 'Payment was not processed on time.', + isActiveEscalation: false, // Closed = not active + }, + { + id: 5, + title: 'Incorrect charges applied', + raisedOn: '20 February, 2024', + time: '9:30 AM', + status: 'Resolved', + description: 'Extra charges applied without notice.', + isActiveEscalation: false, // Resolved = not active + }, + { + id: 3, + title: 'Unauthorized access to account', + raisedOn: '28 March, 2024', + time: '4:45 PM', + status: 'Open', + description: 'Suspicious activity detected in the bank account.', + isActiveEscalation: true, // Open = active + }, + { + id: 4, + title: 'Delayed processing of payment', + raisedOn: '5 March, 2024', + time: '1:00 PM', + status: 'Closed', + description: 'Payment was not processed on time.', + isActiveEscalation: false, // Closed = not active + }, + { + id: 5, + title: 'Incorrect charges applied', + raisedOn: '20 February, 2024', + time: '9:30 AM', + status: 'Resolved', + description: 'Extra charges applied without notice.', + isActiveEscalation: false, // Resolved = not active + }, + { + id: 3, + title: 'Unauthorized access to account', + raisedOn: '28 March, 2024', + time: '4:45 PM', + status: 'Open', + description: 'Suspicious activity detected in the bank account.', + isActiveEscalation: true, // Open = active + }, + { + id: 4, + title: 'Delayed processing of payment', + raisedOn: '5 March, 2024', + time: '1:00 PM', + status: 'Closed', + description: 'Payment was not processed on time.', + isActiveEscalation: false, // Closed = not active + }, + { + id: 5, + title: 'Incorrect charges applied', + raisedOn: '20 February, 2024', + time: '9:30 AM', + status: 'Resolved', + description: 'Extra charges applied without notice.', + isActiveEscalation: false, // Resolved = not active + }, { + id: 3, + title: 'Unauthorized access to account', + raisedOn: '28 March, 2024', + time: '4:45 PM', + status: 'Open', + description: 'Suspicious activity detected in the bank account.', + isActiveEscalation: true, // Open = active + }, + { + id: 4, + title: 'Delayed processing of payment', + raisedOn: '5 March, 2024', + time: '1:00 PM', + status: 'Closed', + description: 'Payment was not processed on time.', + isActiveEscalation: false, // Closed = not active + }, + { + id: 5, + title: 'Incorrect charges applied', + raisedOn: '20 February, 2024', + time: '9:30 AM', + status: 'Resolved', + description: 'Extra charges applied without notice.', + isActiveEscalation: false, // Resolved = not active + }, + { + id: 3, + title: 'Unauthorized access to account', + raisedOn: '28 March, 2024', + time: '4:45 PM', + status: 'Open', + description: 'Suspicious activity detected in the bank account.', + isActiveEscalation: true, // Open = active + }, + { + id: 4, + title: 'Delayed processing of payment', + raisedOn: '5 March, 2024', + time: '1:00 PM', + status: 'Closed', + description: 'Payment was not processed on time.', + isActiveEscalation: false, // Closed = not active + }, + { + id: 5, + title: 'Incorrect charges applied', + raisedOn: '20 February, 2024', + time: '9:30 AM', + status: 'Resolved', + description: 'Extra charges applied without notice.', + isActiveEscalation: false, // Resolved = not active + } + ]); + getAllEscalations(); + }, [currentPage]); + + useEffect(() => { + if (!isOnline) { + setCurrentPage(1); + } + }, [isOnline]); + + useEffect(() => { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_VIEW_ALL_ESCALATIONS_SCREEN_LANDED); + }, []); + + const handlePageChange = (page: number) => { + if (!isOnline) { + toast({ type: 'info', text1: ToastMessages.OFFLINE_MESSAGE }); + return; + } + setCurrentPage(page); + }; + + const isActiveEscalationCase = true; + + + + return ( + + + + + {[...Array(8).keys()].map(() => ( + + ))} + + } + > + + {escalationsList?.length ? ( + <> + {escalationsList.map((escalation) => ( + + + + + + + + + + + + {escalation.title} + + + + + + {escalation.raisedOn} + + + {'|'} + + + {escalation.time} + + + + {escalation.isActiveEscalation ? ( + + ) : ( + + )} + + + + + + + Description + {escalation.description} + + + + ))} + + ) : ( + + <> + + )} + + + + {escalationsList?.length && totalPage > 1 ? ( + + ) : null} + + ); +}; + +const styles = StyleSheet.create({ + br16: { + borderRadius: 16, + }, + horizontalLine: { + backgroundColor: COLORS.BACKGROUND.BLACK, + width: '100%', + height: 1, + marginTop: 16, + }, + textColorGrayscale: { + color: COLORS.TEXT.DARK, + }, + textColorGrayscale2: { + color: COLORS.TEXT.BLACK, + }, + textColorGrayscale3: { + color: COLORS.TEXT.LIGHT, + }, + + + upperContainer: { + width: 248, + }, + flagContainer: { + height: 40, + width: 40, + borderRadius: 20, + }, +}); + +export default Escalations; diff --git a/src/screens/escalations/EscalationsSection.tsx b/src/screens/escalations/EscalationsSection.tsx new file mode 100644 index 00000000..840b5057 --- /dev/null +++ b/src/screens/escalations/EscalationsSection.tsx @@ -0,0 +1,131 @@ +import React from 'react'; +import { StyleSheet, TouchableOpacity, View } from 'react-native'; +import { COLORS } from '@rn-ui-lib/colors'; +import { GenericStyles, getShadowStyle } from '@rn-ui-lib/styles'; +import Text from '@rn-ui-lib/components/Text'; +import Chevron from '@rn-ui-lib/icons/Chevron'; +import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants'; +import { navigateToScreen } from '@components/utlis/navigationUtlis'; +import { RootState } from '@store'; +import { useAppSelector } from '@hooks'; +import { addClickstreamEvent } from '@services/clickstreamEventService'; +import { CaseDetailStackEnum } from '../caseDetails/CaseDetailStack'; +import FlagIcon from '@assets/icons/FlagIcon'; + +interface IEscalationsSection { + caseId: string; +} + +const EscalationsSection = ({ caseId }: IEscalationsSection) => { + + const caseDetail = useAppSelector((state: RootState) => state.allCases?.caseDetails?.[caseId]) || {}; + const { loanAccountNumber } = caseDetail; + + + const handleOnPressClick = () => { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_VIEW_ALL_ESCALATIONS_SCREEN_CLICKED, { + lan: loanAccountNumber, + }); + navigateToScreen(CaseDetailStackEnum.ESCALATIONS); + }; + + + + + const activeEscalationsCount = 2; + const pastEscalationsCount = 3; + const totalEscalationsCount = activeEscalationsCount + pastEscalationsCount; // might break for 2-3 digit number + const isActiveEscalationCase = true; + + return ( + + + + + + + + + {`${totalEscalationsCount} `}{isActiveEscalationCase ? 'Active Escalations' : 'Past Escalations'} + + + + + + + {'Fake/False commitments/information'} + + + + + {'Raised on:'} + + + {'9 May, 2024'} + + + {'|'} + + + {'2:29 PM'} + + + + + + + View all {`(${totalEscalationsCount})`} + + + + + + + + + ); +}; +export const styles = StyleSheet.create({ + escalationContainer: { + height: 26, + marginBottom: 16, + paddingLeft: 8, + paddingRight: 8, + borderBottomRightRadius: 6, + borderTopLeftRadius: 16, + width : 148, + + }, + activeEscalationText: { + color: COLORS.TEXT.RED, + marginLeft: 4, + }, + pastEscalationText: { + color: COLORS.TEXT.YELLOW, + marginLeft: 4, + }, + viewAllButton: { + color: COLORS.TEXT.BLUE, + fontSize: 12, + lineHeight: 15, + marginRight: 10, + }, + br16: { + borderRadius: 16, + }, +}); + +export default EscalationsSection;