Merge branch 'master' of github.cmd.navi-tech.in:medici/Address-Verification-App into feat/tp-29659
This commit is contained in:
16
App.tsx
16
App.tsx
@@ -19,7 +19,13 @@ import FullScreenLoader from './RN-UI-LIB/src/components/FullScreenLoader';
|
||||
import { toastConfigs, ToastContainer } from './RN-UI-LIB/src/components/toast';
|
||||
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import { APM_APP_NAME, APM_BASE_URL, ENV, SENTRY_DSN } from './src/constants/config';
|
||||
import {
|
||||
APM_APP_NAME,
|
||||
APM_BASE_URL,
|
||||
ENV,
|
||||
MS_CLARITY_PROJECT_ID,
|
||||
SENTRY_DSN,
|
||||
} from './src/constants/config';
|
||||
import { COLORS } from './RN-UI-LIB/src/styles/colors';
|
||||
import codePush from 'react-native-code-push';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
@@ -31,12 +37,16 @@ import ErrorBoundary from './src/common/ErrorBoundary';
|
||||
import CodePush from 'react-native-code-push';
|
||||
import { TDocumentObj } from './src/screens/caseDetails/interface';
|
||||
import AuthRouter from './src/screens/auth/AuthRouter';
|
||||
import { initialize } from 'react-native-clarity';
|
||||
|
||||
Sentry.init({ dsn: SENTRY_DSN });
|
||||
|
||||
if (ENV !== 'prod') {
|
||||
// mockApiServer();
|
||||
if (ENV === 'prod') {
|
||||
if (MS_CLARITY_PROJECT_ID) {
|
||||
initialize(MS_CLARITY_PROJECT_ID);
|
||||
}
|
||||
}
|
||||
|
||||
setJsErrorHandler();
|
||||
LogBox.ignoreAllLogs();
|
||||
|
||||
|
||||
@@ -8,3 +8,4 @@ export const APM_APP_NAME = 'cosmos-app';
|
||||
export const APM_BASE_URL = 'https://dev-longhorn-portal.np.navi-tech.in/apm-events';
|
||||
export const GOOGLE_SSO_CLIENT_ID =
|
||||
'60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com';
|
||||
export const MS_CLARITY_PROJECT_ID = '';
|
||||
|
||||
@@ -12,3 +12,4 @@ export const IS_DATA_SYNC_REQUIRED = true;
|
||||
export const DATA_SYNC_TIME_INTERVAL = 2 * MINUTES_IN_AN_HOUR * MILLISECONDS_IN_A_MINUTE; // 2hr
|
||||
export const GOOGLE_SSO_CLIENT_ID =
|
||||
'136591056725-ev8db4hrlud2m23n0o03or3cmmp3a3cq.apps.googleusercontent.com';
|
||||
export const MS_CLARITY_PROJECT_ID = 'gobifvjiac';
|
||||
|
||||
@@ -12,3 +12,4 @@ export const IS_DATA_SYNC_REQUIRED = true;
|
||||
export const DATA_SYNC_TIME_INTERVAL = 2 * MINUTES_IN_AN_HOUR * MILLISECONDS_IN_A_MINUTE; // 2hr
|
||||
export const GOOGLE_SSO_CLIENT_ID =
|
||||
'60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com';
|
||||
export const MS_CLARITY_PROJECT_ID = '';
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"react-hook-form": "7.40.0",
|
||||
"react-native": "0.70.6",
|
||||
"react-native-call-log": "2.1.2",
|
||||
"react-native-clarity": "0.0.3",
|
||||
"react-native-code-push": "7.1.0",
|
||||
"react-native-contacts": "7.0.5",
|
||||
"react-native-date-picker": "4.2.10",
|
||||
|
||||
63
src/action/firebaseFallbackActions.ts
Normal file
63
src/action/firebaseFallbackActions.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import axiosInstance, { ApiKeys, getApiUrl } from '../components/utlis/apiHelper';
|
||||
import { logError } from '../components/utlis/errorUtils';
|
||||
import { FilterResponse } from '../screens/allCases/interface';
|
||||
import { CaseDetail } from '../screens/caseDetails/interface';
|
||||
|
||||
export enum SyncStatus {
|
||||
SEND_CASES = 'SEND_CASES',
|
||||
FETCH_CASES = 'FETCH_CASES',
|
||||
SKIP = 'SKIP',
|
||||
}
|
||||
|
||||
interface IFilterSync {
|
||||
filterComponentList: FilterResponse[];
|
||||
}
|
||||
|
||||
export interface ISyncedCases {
|
||||
cases: CaseDetail[];
|
||||
filters: IFilterSync;
|
||||
deletedCaseIds: string[];
|
||||
payloadCreatedAt: number;
|
||||
}
|
||||
|
||||
interface ICases {
|
||||
caseId: string;
|
||||
caseViewCreatedAt?: number;
|
||||
}
|
||||
|
||||
export interface ISyncCaseIdPayload {
|
||||
agentId: string;
|
||||
cases: ICases[];
|
||||
}
|
||||
|
||||
export const getCasesSyncStatus = async (userReferenceId: string) => {
|
||||
try {
|
||||
const url = getApiUrl(ApiKeys.CASES_SYNC_STATUS, {}, { userReferenceId });
|
||||
const response = await axiosInstance.get(url, { headers: { donotHandleError: true } });
|
||||
return response?.data?.syncStatus;
|
||||
} catch (err) {
|
||||
logError(err as Error, 'Error getting sync status');
|
||||
}
|
||||
};
|
||||
|
||||
export const sendSyncCaseIds = async (payload: ISyncCaseIdPayload) => {
|
||||
try {
|
||||
const url = getApiUrl(ApiKeys.CASES_SEND_ID);
|
||||
const response = await axiosInstance.post(url, payload, {
|
||||
headers: { donotHandleError: true },
|
||||
});
|
||||
return response?.data;
|
||||
} catch (err) {
|
||||
logError(err as Error, 'Error sending case ids sync');
|
||||
}
|
||||
};
|
||||
|
||||
export const fetchCasesToSync = async (agentReferenceId: string) => {
|
||||
try {
|
||||
const url = getApiUrl(ApiKeys.FETCH_CASES, { agentReferenceId });
|
||||
const response = await axiosInstance.get(url, { headers: { donotHandleError: true } });
|
||||
return response?.data;
|
||||
} catch (err) {
|
||||
logError(err as Error, 'Error fetching cases to be synced');
|
||||
}
|
||||
};
|
||||
@@ -23,6 +23,8 @@ const BlockerScreen = (props: IBlockerScreen) => {
|
||||
const { isTimeSynced, isDeviceLocationEnabled } = useAppSelector(
|
||||
(state) => state.foregroundService
|
||||
);
|
||||
const { isWifiOrCellularOn } = useAppSelector((state) => state.metadata);
|
||||
|
||||
const [showActionBtnLoader, setShowActionBtnLoader] = useState(false);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
@@ -110,6 +112,20 @@ const BlockerScreen = (props: IBlockerScreen) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (!isWifiOrCellularOn) {
|
||||
const { heading, instructions } = BLOCKER_SCREEN_DATA.DEVICE_WIFI_OR_CELLULAR_OFF;
|
||||
return (
|
||||
<BlockerInstructions
|
||||
heading={heading}
|
||||
instructions={instructions}
|
||||
actionBtn={{
|
||||
title: 'Go to settings',
|
||||
action: handleOpenSettings,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <>{props.children}</>;
|
||||
};
|
||||
|
||||
|
||||
@@ -562,6 +562,13 @@ export const BLOCKER_SCREEN_DATA = {
|
||||
`Please retry connecting using the button below, if it doesn't automatically detect.`,
|
||||
],
|
||||
},
|
||||
DEVICE_WIFI_OR_CELLULAR_OFF: {
|
||||
heading: `Please turn on your internet`,
|
||||
instructions: [
|
||||
'Open the Settings app on your Android device.',
|
||||
'Check you wifi/cellular settings',
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const SCREEN_ANIMATION_DURATION = 300;
|
||||
|
||||
@@ -13,11 +13,23 @@ import { useAppDispatch, useAppSelector } from '../hooks';
|
||||
import { dataSyncService } from '../services/dataSync.service';
|
||||
import { DATA_SYNC_TIME_INTERVAL, IS_DATA_SYNC_REQUIRED } from '../constants/config';
|
||||
import useIsLocationEnabled from '../hooks/useIsLocationEnabled';
|
||||
import {
|
||||
ISyncCaseIdPayload,
|
||||
ISyncedCases,
|
||||
SyncStatus,
|
||||
fetchCasesToSync,
|
||||
getCasesSyncStatus,
|
||||
sendSyncCaseIds,
|
||||
} from '../action/firebaseFallbackActions';
|
||||
import { getSyncCaseIds } from '../components/utlis/firebaseFallbackUtils';
|
||||
import { syncCasesByFallback } from '../reducer/allCasesSlice';
|
||||
import { MILLISECONDS_IN_A_MINUTE } from '../../RN-UI-LIB/src/utlis/common';
|
||||
|
||||
export enum FOREGROUND_TASKS {
|
||||
GEOLOCATION = 'GEOLOCATION',
|
||||
TIME_SYNC = 'TIME_SYNC',
|
||||
DATA_SYNC = 'DATA_SYNC',
|
||||
FIRESTORE_FALLBACK = 'FIRESTORE_FALLBACK',
|
||||
}
|
||||
|
||||
interface ITrackingComponent {
|
||||
@@ -33,6 +45,16 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
|
||||
const bgTrackingTimeoutId = useRef<number>();
|
||||
const user = useAppSelector((state) => state.user);
|
||||
|
||||
const {
|
||||
referenceId,
|
||||
pendingList = [],
|
||||
pinnedList = [],
|
||||
} = useAppSelector((state) => ({
|
||||
referenceId: state.user.user?.referenceId!!,
|
||||
pendingList: state.allCases.pendingList,
|
||||
pinnedList: state.allCases.pinnedList,
|
||||
}));
|
||||
|
||||
const handleTimeSync = async () => {
|
||||
try {
|
||||
const timestamp = await getSyncTime();
|
||||
@@ -56,17 +78,44 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleGetCaseSyncStatus = async () => {
|
||||
try {
|
||||
const syncStatus = await getCasesSyncStatus(referenceId);
|
||||
if (syncStatus === SyncStatus.SEND_CASES) {
|
||||
const cases = getSyncCaseIds([...pendingList, ...pinnedList]);
|
||||
const payload: ISyncCaseIdPayload = {
|
||||
agentId: referenceId,
|
||||
cases,
|
||||
};
|
||||
sendSyncCaseIds(payload);
|
||||
} else if (syncStatus === SyncStatus.FETCH_CASES) {
|
||||
const updatedDetails: ISyncedCases = await fetchCasesToSync(referenceId);
|
||||
if (updatedDetails?.cases?.length) {
|
||||
dispatch(syncCasesByFallback(updatedDetails));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
logError(e as Error, 'Error during fetching case sync status');
|
||||
}
|
||||
};
|
||||
|
||||
const tasks: IForegroundTask[] = [
|
||||
{
|
||||
taskId: FOREGROUND_TASKS.TIME_SYNC,
|
||||
task: handleTimeSync,
|
||||
delay: 1000 * 60 * 5, // 5 minutes,
|
||||
delay: 5 * MILLISECONDS_IN_A_MINUTE, // 5 minutes,
|
||||
onLoop: true,
|
||||
},
|
||||
{
|
||||
taskId: FOREGROUND_TASKS.GEOLOCATION,
|
||||
task: handleSendGeolocation,
|
||||
delay: 1000 * 60 * 3, // 3 minutes
|
||||
delay: 3 * MILLISECONDS_IN_A_MINUTE, // 3 minutes
|
||||
onLoop: true,
|
||||
},
|
||||
{
|
||||
taskId: FOREGROUND_TASKS.FIRESTORE_FALLBACK,
|
||||
task: handleGetCaseSyncStatus,
|
||||
delay: 30 * MILLISECONDS_IN_A_MINUTE, // 30 minutes
|
||||
onLoop: true,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -43,6 +43,9 @@ export enum ApiKeys {
|
||||
DATA_SYNC_UPLOAD_COMPLETED = 'DATA_SYNC_UPLOAD_COMPLETED',
|
||||
IMPERSONATION = 'IMPERSONATION',
|
||||
TELEPHONES = 'TELEPHONES',
|
||||
CASES_SYNC_STATUS = 'CASES_SYNC_STATUS',
|
||||
CASES_SEND_ID = 'CASES_SEND_ID',
|
||||
FETCH_CASES = 'FETCH_CASES',
|
||||
}
|
||||
|
||||
export const API_URLS: Record<ApiKeys, string> = {} as Record<ApiKeys, string>;
|
||||
@@ -72,6 +75,9 @@ API_URLS[ApiKeys.GET_PRE_SIGNED_URL_DATA_SYNC] = '/sync-data/get-pre-signed-url'
|
||||
API_URLS[ApiKeys.DATA_SYNC_UPLOAD_COMPLETED] = '/sync-data/upload-completed';
|
||||
API_URLS[ApiKeys.IMPERSONATION] = '/auth/impersonation';
|
||||
API_URLS[ApiKeys.TELEPHONES] = '/telephones';
|
||||
API_URLS[ApiKeys.CASES_SYNC_STATUS] = '/cases/agents/sync-status';
|
||||
API_URLS[ApiKeys.CASES_SEND_ID] = '/cases/sync';
|
||||
API_URLS[ApiKeys.FETCH_CASES] = '/cases/agents/{agentReferenceId}';
|
||||
|
||||
export const API_STATUS_CODE = {
|
||||
OK: 200,
|
||||
|
||||
@@ -319,3 +319,13 @@ export const getMaxByPropFromList = (arr: GenericType, prop: string) => {
|
||||
const max = Math.max(...mappedArray);
|
||||
return arr.find((x: GenericType) => x[prop] == max);
|
||||
};
|
||||
|
||||
|
||||
export const getGoogleMapUrl = (latitude: string | number, longitude: string | number) => {
|
||||
if (!latitude || !longitude) return;
|
||||
return `https://www.google.com/maps/search/${latitude},+${longitude}`;
|
||||
}
|
||||
|
||||
export const isValidAmountEntered = (value: number) => {
|
||||
return typeof value === 'number' && !isNaN(value);
|
||||
};
|
||||
|
||||
8
src/components/utlis/firebaseFallbackUtils.ts
Normal file
8
src/components/utlis/firebaseFallbackUtils.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { ICaseItem } from '../../screens/allCases/interface';
|
||||
|
||||
export const getSyncCaseIds = (casesList: ICaseItem[] = []) => {
|
||||
return casesList.map((caseItem) => ({
|
||||
caseId: caseItem.caseReferenceId,
|
||||
caseViewCreatedAt: caseItem.caseViewCreatedAt,
|
||||
}));
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
import { setCustomUserId } from 'react-native-clarity';
|
||||
import { isNullOrUndefined } from '../components/utlis/commonFunctions';
|
||||
|
||||
export enum DEVICE_TYPE_ENUM {
|
||||
@@ -21,6 +22,10 @@ interface IGlobalUserData {
|
||||
isImpersonated?: boolean;
|
||||
}
|
||||
|
||||
interface IClarityConfiguration {
|
||||
customUserId?: string;
|
||||
}
|
||||
|
||||
export const setGlobalUserData = (userData: IGlobalUserData) => {
|
||||
const { token, deviceId, agentId, deviceType, isImpersonated } = userData;
|
||||
if (!isNullOrUndefined(token)) GLOBAL.SESSION_TOKEN = `${token}`;
|
||||
@@ -29,3 +34,9 @@ export const setGlobalUserData = (userData: IGlobalUserData) => {
|
||||
if (!isNullOrUndefined(deviceType)) GLOBAL.DEVICE_TYPE = deviceType as DEVICE_TYPE_ENUM;
|
||||
if (!isNullOrUndefined(isImpersonated)) GLOBAL.IS_IMPERSONATED = isImpersonated ?? false;
|
||||
};
|
||||
|
||||
export const setMsClarityConfig = (clarityConfig: IClarityConfiguration) => {
|
||||
if (clarityConfig?.customUserId) {
|
||||
setCustomUserId(clarityConfig.customUserId);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -12,3 +12,4 @@ export const IS_DATA_SYNC_REQUIRED = true;
|
||||
export const DATA_SYNC_TIME_INTERVAL = 2 * MINUTES_IN_AN_HOUR * MILLISECONDS_IN_A_MINUTE; // 2hr
|
||||
export const GOOGLE_SSO_CLIENT_ID =
|
||||
'60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com';
|
||||
export const MS_CLARITY_PROJECT_ID = '';
|
||||
|
||||
@@ -167,14 +167,6 @@ const useFirestoreUpdates = () => {
|
||||
.catch((error) => {
|
||||
dispatch(setLoading(false));
|
||||
logError(error as Error, 'Error in signInUserToFirebase');
|
||||
setGlobalUserData({ token: '', agentId: '', deviceId: '' });
|
||||
dispatch(
|
||||
setAuthData({
|
||||
sessionDetails: null,
|
||||
user: null,
|
||||
isLoggedIn: false,
|
||||
})
|
||||
);
|
||||
toast({
|
||||
type: 'error',
|
||||
text1: ToastMessages.FIRESTORE_SIGNIN_FAILED,
|
||||
|
||||
@@ -199,6 +199,18 @@ export const getUpdatedAVCaseDetail = ({
|
||||
return updatedValue;
|
||||
};
|
||||
|
||||
const getCaseListItem = (
|
||||
caseReferenceId: string,
|
||||
pinRank?: number | null,
|
||||
caseViewCreatedAt?: number
|
||||
) => {
|
||||
return {
|
||||
caseReferenceId,
|
||||
pinRank: pinRank || null,
|
||||
caseViewCreatedAt,
|
||||
};
|
||||
};
|
||||
|
||||
const allCasesSlice = createSlice({
|
||||
name: 'cases',
|
||||
initialState,
|
||||
@@ -219,7 +231,7 @@ const allCasesSlice = createSlice({
|
||||
let newVisitCollectionCases: string[] = [];
|
||||
let removedVisitedCasesLoanIds: string[] = [];
|
||||
caseUpdates.forEach(({ updateType, updatedCaseDetail }) => {
|
||||
const { caseType, caseReferenceId, id, pinRank } = updatedCaseDetail;
|
||||
const { caseType, caseReferenceId, id, pinRank, caseViewCreatedAt } = updatedCaseDetail;
|
||||
|
||||
const caseId = caseReferenceId || id;
|
||||
switch (updateType) {
|
||||
@@ -272,10 +284,7 @@ const allCasesSlice = createSlice({
|
||||
if (pinRank && caseType === CaseAllocationType.COLLECTION_CASE) {
|
||||
newVisitCollectionCases.push(caseId);
|
||||
}
|
||||
const caseListItem = {
|
||||
caseReferenceId: caseId,
|
||||
pinRank: pinRank || null,
|
||||
};
|
||||
const caseListItem = getCaseListItem(caseId, pinRank, caseViewCreatedAt);
|
||||
state.casesList.unshift(caseListItem);
|
||||
let currentTask = null;
|
||||
if (caseType !== CaseAllocationType.COLLECTION_CASE) {
|
||||
@@ -494,6 +503,33 @@ const allCasesSlice = createSlice({
|
||||
resetNewVisitedCases: (state) => {
|
||||
state.newVisitedCases = [];
|
||||
},
|
||||
syncCasesByFallback: (state, action) => {
|
||||
const { cases = [], deletedCaseIds = [], payloadCreatedAt } = action.payload;
|
||||
cases.forEach((caseItem: CaseDetail) => {
|
||||
const { caseViewCreatedAt, caseReferenceId, isSynced, pinRank } = caseItem;
|
||||
if (
|
||||
!state.caseDetails[caseReferenceId] ||
|
||||
(isSynced && caseViewCreatedAt && caseViewCreatedAt < payloadCreatedAt)
|
||||
) {
|
||||
const caseListItem = getCaseListItem(caseReferenceId, pinRank, caseViewCreatedAt);
|
||||
state.casesList.unshift(caseListItem);
|
||||
state.caseDetails[caseReferenceId] = { ...caseItem, isSynced: true };
|
||||
const { pendingList, completedList, pinnedList } = getCaseListComponents(
|
||||
state.casesList,
|
||||
state.caseDetails
|
||||
);
|
||||
state.pendingList = pendingList;
|
||||
state.completedList = completedList;
|
||||
state.pinnedList = pinnedList;
|
||||
}
|
||||
});
|
||||
deletedCaseIds.forEach((caseItem: CaseDetail) => {
|
||||
const { caseViewCreatedAt, caseReferenceId } = caseItem;
|
||||
if (caseViewCreatedAt && caseViewCreatedAt < payloadCreatedAt) {
|
||||
delete state.caseDetails[caseReferenceId];
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -513,6 +549,7 @@ export const {
|
||||
updateCaseDetailBeforeApiCall,
|
||||
setVisitPlansUpdating,
|
||||
resetNewVisitedCases,
|
||||
syncCasesByFallback,
|
||||
} = allCasesSlice.actions;
|
||||
|
||||
export default allCasesSlice.reducer;
|
||||
|
||||
@@ -7,11 +7,13 @@ export interface UninstallInformation {
|
||||
interface IMetadata {
|
||||
isOnline: boolean;
|
||||
forceUninstall: Record<string, UninstallInformation>;
|
||||
isWifiOrCellularOn: boolean;
|
||||
}
|
||||
|
||||
const initialState = {
|
||||
isOnline: true,
|
||||
forceUninstall: {},
|
||||
isWifiOrCellularOn: true,
|
||||
} as IMetadata;
|
||||
|
||||
const MetadataSlice = createSlice({
|
||||
@@ -24,9 +26,12 @@ const MetadataSlice = createSlice({
|
||||
setForceUninstallData: (state, action) => {
|
||||
state.forceUninstall = action.payload;
|
||||
},
|
||||
setIsWifiOrCellularOn: (state, action) => {
|
||||
state.isWifiOrCellularOn = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setIsOnline, setForceUninstallData } = MetadataSlice.actions;
|
||||
export const { setIsOnline, setForceUninstallData, setIsWifiOrCellularOn } = MetadataSlice.actions;
|
||||
|
||||
export default MetadataSlice.reducer;
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
BUSINESS_TIME_FORMAT,
|
||||
dateFormat,
|
||||
} from '../../../RN-UI-LIB/src/utlis/dates';
|
||||
import { sanitizeString } from '../../components/utlis/commonFunctions';
|
||||
import { getGoogleMapUrl, sanitizeString } from '../../components/utlis/commonFunctions';
|
||||
import { IGeoLocation } from '../../types/addressGeolocation.types';
|
||||
import { addClickstreamEvent } from '../../services/clickstreamEventService';
|
||||
import { CLICKSTREAM_EVENT_NAMES } from '../../common/Constants';
|
||||
@@ -30,7 +30,7 @@ const GeolocationItem = ({ geolocationItem, showSeparator = true }: IGeolocation
|
||||
latitude: geolocationItem.latitude,
|
||||
longitude: geolocationItem.longitude,
|
||||
});
|
||||
const geolocationUrl = `http://maps.google.com/?q=${geolocationItem?.latitude},${geolocationItem?.longitude}`;
|
||||
const geolocationUrl = getGoogleMapUrl(geolocationItem?.latitude, geolocationItem?.longitude);
|
||||
if (!geolocationUrl) return;
|
||||
|
||||
return Linking.openURL(geolocationUrl);
|
||||
|
||||
@@ -45,7 +45,14 @@ const Filters: React.FC<IFilters> = ({
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View style={[GenericStyles.ph16, GenericStyles.pb16, GenericStyles.centerAlignedRow]}>
|
||||
<View
|
||||
style={[
|
||||
GenericStyles.mh20,
|
||||
GenericStyles.ph16,
|
||||
GenericStyles.pb16,
|
||||
GenericStyles.centerAlignedRow,
|
||||
]}
|
||||
>
|
||||
<TextInput
|
||||
style={styles.textInput}
|
||||
LeftComponent={<SearchIcon />}
|
||||
|
||||
@@ -112,6 +112,7 @@ export const caseVerdictAndColor = {
|
||||
export interface ICaseItem {
|
||||
type?: CaseTypes; // this is for maintaining frontend
|
||||
pinRank: number | null;
|
||||
caseViewCreatedAt?: number;
|
||||
updatedAt?: any;
|
||||
allocatedAt?: any;
|
||||
caseReferenceId: string;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useSelector } from 'react-redux';
|
||||
import { RootState } from '../../store/store';
|
||||
import { getUniqueId, isTablet } from 'react-native-device-info';
|
||||
import { setDeviceId } from '../../reducer/userSlice';
|
||||
import { DEVICE_TYPE_ENUM, setGlobalUserData } from '../../constants/Global';
|
||||
import { DEVICE_TYPE_ENUM, setGlobalUserData, setMsClarityConfig } from '../../constants/Global';
|
||||
import { registerNavigateAndDispatch } from '../../components/utlis/apiHelper';
|
||||
import ProtectedRouter from './ProtectedRouter';
|
||||
import useNativeButtons from '../../hooks/useNativeButton';
|
||||
@@ -38,6 +38,8 @@ const AuthRouter = () => {
|
||||
isImpersonated: user?.isImpersonated ?? false,
|
||||
});
|
||||
|
||||
setMsClarityConfig({ customUserId: user?.user?.phoneNumber || user?.user?.emailId });
|
||||
|
||||
// Sets the dispatch for apiHelper
|
||||
registerNavigateAndDispatch(dispatch);
|
||||
|
||||
|
||||
@@ -47,7 +47,12 @@ const FeedbackDetailImageItem: React.FC<IFeedbackDetailImageItem> = ({ image })
|
||||
onPress={handleExpandImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<Modal visible={isImageExpanded} transparent animationType="fade">
|
||||
<Modal
|
||||
visible={isImageExpanded}
|
||||
transparent
|
||||
onRequestClose={handleExpandedImageClose}
|
||||
animationType="fade"
|
||||
>
|
||||
<ExpandableImage
|
||||
imageSrc={image.inputText}
|
||||
title={questionText}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
BUSINESS_TIME_FORMAT,
|
||||
dateFormat,
|
||||
} from '../../../../RN-UI-LIB/src/utlis/dates';
|
||||
import { sanitizeString } from '../../../components/utlis/commonFunctions';
|
||||
import { getGoogleMapUrl, sanitizeString } from '../../../components/utlis/commonFunctions';
|
||||
import { FIELD_FEEDBACKS, ICallingFeedback, IFeedback } from '../../../types/feedback.types';
|
||||
import { Address as IAddress } from '../interface';
|
||||
import MapIcon from '../../../../RN-UI-LIB/src/Icons/MapIcon';
|
||||
@@ -42,9 +42,8 @@ const openGeolocation = (latitude: string, longitude: string) => {
|
||||
latitude: latitude,
|
||||
longitude: longitude,
|
||||
});
|
||||
|
||||
if (!latitude || !longitude) return;
|
||||
const geolocationUrl = `http://maps.google.com/?q=${latitude},${longitude}`;
|
||||
const geolocationUrl = getGoogleMapUrl(latitude, longitude);
|
||||
if (!geolocationUrl) return;
|
||||
return Linking.openURL(geolocationUrl);
|
||||
};
|
||||
|
||||
|
||||
@@ -181,6 +181,7 @@ export interface CaseDetail {
|
||||
addresses?: Address[];
|
||||
currentAllocationReferenceId: string;
|
||||
customerReferenceId: string;
|
||||
caseViewCreatedAt?: number;
|
||||
// collection case
|
||||
addressString?: string;
|
||||
currentOutstandingEmi?: number;
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
copyToClipboard,
|
||||
getDynamicBottomSheetHeightPercentageFn,
|
||||
getPhoneNumberString,
|
||||
isValidAmountEntered,
|
||||
} from '../../components/utlis/commonFunctions';
|
||||
import useIsOnline from '../../hooks/useIsOnline';
|
||||
import { RootState } from '../../store/store';
|
||||
@@ -29,6 +30,7 @@ import { CLICKSTREAM_EVENT_NAMES } from '../../common/Constants';
|
||||
import QrCodeModal from './QrCodeModal';
|
||||
import ModalWrapper from '../../../RN-UI-LIB/src/components/modalWrapper/ModalWrapper';
|
||||
import OfflineScreen from '../../common/OfflineScreen';
|
||||
import { formatAmount } from '../../../RN-UI-LIB/src/utlis/amount';
|
||||
|
||||
interface IRegisterForm {
|
||||
selectedPhoneNumber: string;
|
||||
@@ -116,10 +118,10 @@ const RegisterPayments: React.FC<IRegisterPayments> = ({ route }) => {
|
||||
errorMessage = 'This is a required field';
|
||||
break;
|
||||
case 'min':
|
||||
errorMessage = 'Amount should be greater than min amount';
|
||||
break;
|
||||
case 'max':
|
||||
errorMessage = 'Amount should be less than max amount';
|
||||
errorMessage = `The entered amount should be between ${formatAmount(1)} and ${formatAmount(
|
||||
maxAmount
|
||||
)}`;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -217,7 +219,12 @@ const RegisterPayments: React.FC<IRegisterPayments> = ({ route }) => {
|
||||
/>
|
||||
)}
|
||||
name="amount"
|
||||
rules={{ required: true, min: 1, max: maxAmount }}
|
||||
rules={{
|
||||
required: true,
|
||||
min: 1,
|
||||
max: maxAmount,
|
||||
validate: (value) => isValidAmountEntered(Number(value)),
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<Button
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import NetInfo from '@react-native-community/netinfo';
|
||||
import NetInfo, { NetInfoStateType } from '@react-native-community/netinfo';
|
||||
import { setNetworkStatus } from './clickstreamEventService';
|
||||
import { setIsOnline } from '../reducer/metadataSlice';
|
||||
import { setIsOnline, setIsWifiOrCellularOn } from '../reducer/metadataSlice';
|
||||
|
||||
export class NetworkStatusService {
|
||||
private static isOnline = false;
|
||||
private static isAlreadyListening = false;
|
||||
private static isWifiOrCellularOn = false;
|
||||
// private static listeners: any[] = [];
|
||||
private constructor() {
|
||||
// singleton
|
||||
@@ -29,6 +30,14 @@ export class NetworkStatusService {
|
||||
// listen for changes.
|
||||
NetInfo.addEventListener((state) => {
|
||||
setNetworkStatus(state);
|
||||
const { type } = state;
|
||||
if (type === NetInfoStateType.none && NetworkStatusService.isWifiOrCellularOn) {
|
||||
NetworkStatusService.isWifiOrCellularOn = false;
|
||||
dispatch(setIsWifiOrCellularOn(false));
|
||||
} else if (type !== NetInfoStateType.none && !NetworkStatusService.isWifiOrCellularOn) {
|
||||
NetworkStatusService.isWifiOrCellularOn = true;
|
||||
dispatch(setIsWifiOrCellularOn(true));
|
||||
}
|
||||
if (NetworkStatusService.isOnline !== state.isConnected) {
|
||||
NetworkStatusService.isOnline = !!state.isConnected && !!state.isInternetReachable;
|
||||
dispatch(setIsOnline(NetworkStatusService.isOnline));
|
||||
|
||||
@@ -7566,6 +7566,11 @@ react-native-call-log@2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/react-native-call-log/-/react-native-call-log-2.1.2.tgz#f80d2fcb45f72118eb8048d5bfdef191fd4a3df3"
|
||||
integrity sha512-nWHmb+QMN/AbbZFEuUGiQePssPgjQr5dibNAURDlqO4S5wuLk1XzxxsLUAVHZnB0FdJoMlajD7tUAXtaoxYwUQ==
|
||||
|
||||
react-native-clarity@^0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-clarity/-/react-native-clarity-0.0.3.tgz#e9c83dd097c0cdaf0751c7f6683fc3b038134637"
|
||||
integrity sha512-uXccmC9iKwxBpsy7jOLaEo87RBQax/WNCI5EDa/hldn1+8eNCwwhkUdJZeNgi1pZ/dyBmHZj0Be0jgWy4K4gkA==
|
||||
|
||||
react-native-code-push@7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-code-push/-/react-native-code-push-7.1.0.tgz#9767518d684017993ff32875bfd349ce01298d35"
|
||||
|
||||
Reference in New Issue
Block a user