From 77cca0abb9f360e1599ca6175bcf5002dd4d5b62 Mon Sep 17 00:00:00 2001 From: yashmantri Date: Thu, 3 Oct 2024 23:57:02 +0530 Subject: [PATCH 01/56] TP-87084 | Exponential delay for retry API calls --- src/components/utlis/apiHelper.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/utlis/apiHelper.ts b/src/components/utlis/apiHelper.ts index a8f1d522..6e211041 100644 --- a/src/components/utlis/apiHelper.ts +++ b/src/components/utlis/apiHelper.ts @@ -246,15 +246,15 @@ const errorsToRetry = [500, 503]; const axiosInstance = axios.create({ timeout: API_TIMEOUT_INTERVAL }); axiosInstance.interceptors.request.use((request) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - request.retry = request?.retry < 4 ? request.retry : 3; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore request.headers['X-Auth-Source'] = 'mjolnir'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore request.retry = request?.retry < 4 ? request.retry : 3; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + request.delay = request?.delay > 1000 ? request.delay : 1000; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore request.headers['request-start-time'] = Date.now(); @@ -353,8 +353,9 @@ axiosInstance.interceptors.response.use( const delayRetryRequest = new Promise((resolve) => { setTimeout(() => { resolve(); - }, 500); + }, config.delay); }); + config.delay *= 2; return delayRetryRequest.then(() => axiosInstance(config)); } ); From 40a4c63dd7e1dfc4ed20b117e3a85aef313d0917 Mon Sep 17 00:00:00 2001 From: yashmantri Date: Wed, 9 Oct 2024 12:54:18 +0530 Subject: [PATCH 02/56] NTP-7181 | SWW logging added --- App.tsx | 4 ++++ src/common/Constants.ts | 9 +++++++++ src/components/utlis/apiHelper.ts | 12 ++++++++++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/App.tsx b/App.tsx index 40db284c..5f1ec834 100644 --- a/App.tsx +++ b/App.tsx @@ -124,6 +124,10 @@ function App() { case codePush.SyncStatus.UP_TO_DATE: modalRef.current?.hide(); break; + case codePush.SyncStatus.UNKNOWN_ERROR: + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_CODEPUSH_UNKNOWN_ERROR, {}); + modalRef.current?.hide(); + break; default: addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_CODEPUSH_DEFAULT_STATUS, {}); modalRef.current?.hide(); diff --git a/src/common/Constants.ts b/src/common/Constants.ts index 7df85363..33a28f7e 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -1301,6 +1301,10 @@ export const CLICKSTREAM_EVENT_NAMES = { name : 'FA_CODEPUSH_DEFAULT_STATUS', description: 'Codepush default fallback case' }, + FA_CODEPUSH_UNKNOWN_ERROR: { + name : 'FA_CODEPUSH_UNKNOWN_ERROR', + description: 'Codepush unknown error' + }, FA_FEEDBACK_IMAGE_NOT_FOUND: { name: 'FA_FEEDBACK_IMAGE_NOT_FOUND', description: 'Feedback image not found' @@ -1309,6 +1313,11 @@ export const CLICKSTREAM_EVENT_NAMES = { name: 'FA_UNSYNC_FEEDBACK_CAPTURED', description: 'Unsync feedback captured' }, + + FA_API_FAILED: { + name: 'FA_API_FAILED', + description: 'API failed' + }, } as const; export enum MimeType { diff --git a/src/components/utlis/apiHelper.ts b/src/components/utlis/apiHelper.ts index b2d3d5ad..728770f5 100644 --- a/src/components/utlis/apiHelper.ts +++ b/src/components/utlis/apiHelper.ts @@ -6,10 +6,14 @@ import { GLOBAL } from '../../constants/Global'; import { _map, compareUrl } from '../../../RN-UI-LIB/src/utlis/common'; import { BASE_AV_APP_URL } from '../../constants/config'; import { logError } from './errorUtils'; -import { sendApiToClickstreamEvent } from '../../services/clickstreamEventService'; +import { + addClickstreamEvent, + sendApiToClickstreamEvent, +} from '../../services/clickstreamEventService'; import { handleLogout } from '../../action/authActions'; import { API_ERROR_MESSAGE, + CLICKSTREAM_EVENT_NAMES, REQUEST_TO_UNBLOCK_FOR_IMPERSONATION, REQUEST_TYPE_TO_BLOCK_FOR_IMPERSONATION, } from '../../common/Constants'; @@ -97,7 +101,7 @@ export enum ApiKeys { GENERATE_DYNAMIC_DOCUMENT = 'GENERATE_DYNAMIC_DOCUMENT', DOWNLOAD_LATEST_APP = 'DOWNLOAD_LATEST_APP', GET_SIGNED_URL_V2 = 'GET_SIGNED_URL_V2', - GET_SIGNED_URL_FOR_REPORTEE_V2 = 'GET_SIGNED_URL_FOR_REPORTEE_V2' + GET_SIGNED_URL_FOR_REPORTEE_V2 = 'GET_SIGNED_URL_FOR_REPORTEE_V2', } export const API_URLS: Record = {} as Record; @@ -317,6 +321,10 @@ axiosInstance.interceptors.response.use( const end = Date.now(); const milliseconds = end - Number(start); sendApiToClickstreamEvent(response, milliseconds, false); + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_API_FAILED, { + statusCode: response?.status, + url: response?.config?.url, + }); const donotHandleErrorOnStatusCode = (config.headers.donotHandleErrorOnStatusCode || []).map( Number ); From f5e9eda047db61eba8f80fb32c56e830717c56a9 Mon Sep 17 00:00:00 2001 From: yashmantri Date: Wed, 9 Oct 2024 13:08:30 +0530 Subject: [PATCH 03/56] TP-87084 | Exponential delay for retry API calls --- src/components/utlis/apiHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/utlis/apiHelper.ts b/src/components/utlis/apiHelper.ts index 6e211041..20ec031f 100644 --- a/src/components/utlis/apiHelper.ts +++ b/src/components/utlis/apiHelper.ts @@ -254,7 +254,7 @@ axiosInstance.interceptors.request.use((request) => { request.retry = request?.retry < 4 ? request.retry : 3; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - request.delay = request?.delay > 1000 ? request.delay : 1000; + request.delay = request?.delay > 2000 ? request.delay : 2000; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore request.headers['request-start-time'] = Date.now(); From 9864d018cebbfe66e37f82977ebad3a819857fb6 Mon Sep 17 00:00:00 2001 From: security user Date: Wed, 9 Oct 2024 14:01:44 +0530 Subject: [PATCH 04/56] SP-1022 | Update Semgrep configuration --- .github/workflows/semgrep.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 2d4c12f5..6f4676ed 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -15,13 +15,13 @@ on: jobs: central-semgrep: name: Static code Analysis - uses: navi-infosec/central-semgrep-action/.github/workflows/central-semgrep.yml@master + uses: navi-infosec/central-semgrep-action/.github/workflows/central-semgrep.yml@using-token with: github-event-number: ${{github.event.number}} github-event-name: ${{github.event_name}} github-repository: ${{github.repository}} secrets: - READ_SEMGREP_RULES: ${{secrets.READ_SEMGREP_RULES}} + READ_SEMGREP_RULES_TOKEN: ${{secrets.READ_SEMGREP_RULES_TOKEN}} run-if-failed: runs-on: [ self-hosted ] From c129e447657114338f73e0f7c16362f4d3089007 Mon Sep 17 00:00:00 2001 From: yashmantri Date: Wed, 9 Oct 2024 17:49:50 +0530 Subject: [PATCH 05/56] TP-87084 | Feedback interaction delete for image when clicked on delete button --- .../components/imageUpload/ImageUploadV2.tsx | 67 ++++++++++--------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/components/form/components/imageUpload/ImageUploadV2.tsx b/src/components/form/components/imageUpload/ImageUploadV2.tsx index c5b8dfff..d3b21066 100644 --- a/src/components/form/components/imageUpload/ImageUploadV2.tsx +++ b/src/components/form/components/imageUpload/ImageUploadV2.tsx @@ -88,8 +88,9 @@ const ImageUploadV2: React.FC = (props) => { dispatch(addIntermediateDocument({ caseId, fileUri, questionKey, imageWidth, imageHeight })); }; - const handleImageDelete = () => { + const handleImageDelete = (onChange: (...event: any[]) => void) => { setImageId(''); + onChange(undefined) dispatch(deleteIntermediateDocument({ caseId, questionKey: questionId })); }; @@ -317,11 +318,11 @@ const ImageUploadV2: React.FC = (props) => { {question.text}{' '} {isQuestionMandatory(question) && *} - {showClickPictureCTA ? ( - validateInput(data, question.metadata.validators) }} - render={({ field: { onChange } }) => ( + validateInput(data, question.metadata.validators) }} + render={({ field: { onChange } }) => + showClickPictureCTA ? ( <> = (props) => { ) : null} - )} - name={`widgetContext.${widgetId}.sectionContext.${props.sectionId}.questionContext.${questionId}`} - /> - ) : ( - - handleError('Error in image rendering')} - > - {!imageLoading && !imageError ? ( - - - - ) : null} - - - - )} + ) : ( + + handleError('Error in image rendering')} + > + {!imageLoading && !imageError ? ( + handleImageDelete(onChange)} style={styles.deleteButton}> + + + ) : null} + + + + ) + } + name={`widgetContext.${widgetId}.sectionContext.${props.sectionId}.questionContext.${questionId}`} + /> Date: Wed, 9 Oct 2024 17:52:35 +0530 Subject: [PATCH 06/56] TP-87084 | Feedback interaction delete for image when clicked on delete button --- src/components/form/components/imageUpload/ImageUploadV2.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/form/components/imageUpload/ImageUploadV2.tsx b/src/components/form/components/imageUpload/ImageUploadV2.tsx index d3b21066..f3ca2e29 100644 --- a/src/components/form/components/imageUpload/ImageUploadV2.tsx +++ b/src/components/form/components/imageUpload/ImageUploadV2.tsx @@ -90,8 +90,8 @@ const ImageUploadV2: React.FC = (props) => { const handleImageDelete = (onChange: (...event: any[]) => void) => { setImageId(''); - onChange(undefined) dispatch(deleteIntermediateDocument({ caseId, questionKey: questionId })); + onChange(undefined); }; const handleError = (error: string) => { From 6765363fcbeb5c0f9d965b55101b8e407a688a0b Mon Sep 17 00:00:00 2001 From: yashmantri Date: Wed, 9 Oct 2024 18:17:44 +0530 Subject: [PATCH 07/56] TP-87084 | Version Bump --- android/app/build.gradle | 4 ++-- package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 00e467f1..275a8ca6 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -134,8 +134,8 @@ def reactNativeArchitectures() { return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } -def VERSION_CODE = 200 -def VERSION_NAME = "2.14.0" +def VERSION_CODE = 201 +def VERSION_NAME = "2.14.1" android { ndkVersion rootProject.ext.ndkVersion diff --git a/package.json b/package.json index d71d1f44..abaeedfb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "AV_APP", - "version": "2.14.0", - "buildNumber": "200", + "version": "2.14.1", + "buildNumber": "201", "private": true, "scripts": { "android:dev": "yarn move:dev && react-native run-android", From 15d218ced2397f0457119c23f707902c15fa937d Mon Sep 17 00:00:00 2001 From: Aman Chaturvedi Date: Wed, 9 Oct 2024 18:47:49 +0530 Subject: [PATCH 08/56] NTP-6184 | Clickstream events added for app update --- src/action/appDownloadAction.ts | 33 +++++++++++++-- src/common/BlockerScreen.tsx | 75 +++++++++++++++++++++++++-------- src/common/Constants.ts | 38 +++++++++++++++++ src/reducer/appUpdateSlice.ts | 29 +++++++++++++ src/store/store.ts | 5 ++- 5 files changed, 157 insertions(+), 23 deletions(-) create mode 100644 src/reducer/appUpdateSlice.ts diff --git a/src/action/appDownloadAction.ts b/src/action/appDownloadAction.ts index 5203abbe..b81e8c94 100644 --- a/src/action/appDownloadAction.ts +++ b/src/action/appDownloadAction.ts @@ -1,6 +1,8 @@ -import { BuildFlavours } from '@common/Constants'; +import { BuildFlavours, CLICKSTREAM_EVENT_NAMES } from '@common/Constants'; import { ApiKeys, getApiUrl } from '@components/utlis/apiHelper'; +import { getBuildVersion } from '@components/utlis/commonFunctions'; import { logError } from '@components/utlis/errorUtils'; +import { addClickstreamEvent } from '@services/clickstreamEventService'; import axios from 'axios'; import { Linking, NativeModules } from 'react-native'; import RNFetchBlob from 'react-native-blob-util'; @@ -24,17 +26,33 @@ export const deleteCachedApkFiles = async () => { } }; -export const downloadApkFromS3 = async (s3Url: string, fileName: string) => { +export const downloadApkFromS3 = async (s3Url: string, fileName: string, newAppVersion: number) => { deleteCachedApkFiles(); const dirs = RNFetchBlob.fs.dirs; const pathToSaveAPK = `${dirs.CacheDir}/latest-app/${fileName}.apk`; + const oldAppVersion = getBuildVersion(); try { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_APK_UPDATE_DOWNLOAD_STARTED, { + downloadPath: pathToSaveAPK, + oldAppVersion, + newAppVersion, + }); const res = await RNFetchBlob.config({ path: pathToSaveAPK, fileCache: true, }).fetch('GET', s3Url, {}); + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_APK_UPDATE_DOWNLOAD_SUCCESS, { + downloadPath: res.path(), + oldAppVersion, + newAppVersion, + }); return res.path(); } catch (err) { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_APK_UPDATE_DOWNLOAD_FAILED, { + errorMessage: (err as Error)?.message, + oldAppVersion, + newAppVersion, + }); logError(err as Error, 'Error while downloading the latest app'); } }; @@ -56,18 +74,25 @@ const openApkDownloadLink = (url: string) => { export const openFallbackLonghornLink = (fallbackUrl?: string) => { if (fallbackUrl) { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_APK_UPDATE_FALLBACK_TRIGGERED, { + fallbackUrl, + }); openApkDownloadLink(fallbackUrl); } }; -export const downloadLatestApkAndGetFilePath = async (buildFlavour: BuildFlavours) => { +export const downloadLatestApkAndGetFilePath = async ( + buildFlavour: BuildFlavours, + appVersion: number +) => { const appUrl = await downloadLatestAppS3Url(buildFlavour); if (!appUrl) { return ''; } const appFileUrl = await downloadApkFromS3( appUrl, - `Cosmos_${BuildFlavours.FIELD_AGENTS}_${Date.now()}` + `Cosmos_${BuildFlavours.FIELD_AGENTS}_${Date.now()}`, + appVersion ); if (!appFileUrl) { return ''; diff --git a/src/common/BlockerScreen.tsx b/src/common/BlockerScreen.tsx index 853e880e..5ee5b237 100644 --- a/src/common/BlockerScreen.tsx +++ b/src/common/BlockerScreen.tsx @@ -26,6 +26,8 @@ import { openFallbackLonghornLink, } from '@actions/appDownloadAction'; import AppUpdate from './AppUpdate'; +import ReactNativeBlobUtil from 'react-native-blob-util'; +import { setShouldUpdate } from '@reducers/appUpdateSlice'; interface IBlockerScreen { children?: ReactNode; @@ -42,15 +44,11 @@ const BlockerScreen = (props: IBlockerScreen) => { const approvalStatus = useAppSelector((state) => state.profile?.approvalStatus); const isLoading = useAppSelector((state) => state.profile?.isLoading); const roles = useAppSelector((state) => state.user?.agentRoles); + const shouldUpdate = useAppSelector((state) => state.appUpdate.shouldUpdate) || {}; const isFieldAgent = (roles?.length === 1 && roles.includes(IUserRole.ROLE_FIELD_AGENT)) || roles.includes(IUserRole.ROLE_OMA); - const [shouldUpdate, setShouldUpdate] = useState({ - newApkCachedUrl: '', - switchToFallback: false, - }); - const [showActionBtnLoader, setShowActionBtnLoader] = useState(false); const dispatch = useAppDispatch(); @@ -61,34 +59,71 @@ const BlockerScreen = (props: IBlockerScreen) => { let apkFileUrl; if (GLOBAL.BUILD_FLAVOUR.includes(BuildFlavours.FIELD_AGENTS)) { // Download app for Field agent - apkFileUrl = await downloadLatestApkAndGetFilePath(BuildFlavours.FIELD_AGENTS); + apkFileUrl = await downloadLatestApkAndGetFilePath( + BuildFlavours.FIELD_AGENTS, + appState?.fieldAgents?.version + ); } else { // Download app for Calling agent - apkFileUrl = await downloadLatestApkAndGetFilePath(BuildFlavours.CALLING_AGENTS); + apkFileUrl = await downloadLatestApkAndGetFilePath( + BuildFlavours.CALLING_AGENTS, + appState?.telecallingAgents?.version + ); } if (apkFileUrl) { - setShouldUpdate({ newApkCachedUrl: apkFileUrl, switchToFallback: false }); + dispatch(setShouldUpdate({ newApkCachedUrl: apkFileUrl, switchToFallback: false })); } else { - setShouldUpdate({ newApkCachedUrl: '', switchToFallback: true }); + dispatch(setShouldUpdate({ newApkCachedUrl: '', switchToFallback: true })); } }; const handleAppUpdate = () => { let fallbackLonghornUrl; + let oldAppVersion = getBuildVersion(); + let newAppVersion = appState?.fieldAgents?.version; if (GLOBAL.BUILD_FLAVOUR.includes('fieldAgents')) { fallbackLonghornUrl = appState?.fieldAgents?.currentProdAPK; } else { + newAppVersion = appState?.telecallingAgents?.version; fallbackLonghornUrl = appState?.telecallingAgents?.currentProdAPK; } + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_APK_UPDATE_BUTTON_CLICKED, { + apkPath: shouldUpdate.newApkCachedUrl, + oldAppVersion, + newAppVersion, + }); if (!shouldUpdate.newApkCachedUrl) { openFallbackLonghornLink(fallbackLonghornUrl); return; } - installApk(shouldUpdate.newApkCachedUrl, (error) => { - if (!error) { - return; + ReactNativeBlobUtil.fs.stat(shouldUpdate.newApkCachedUrl).then((res) => { + if (res.size < 10e6) { + // Temporary check: if size less than 10MB, then file is corrupted. Go to fallback link + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_APK_UPDATE_CORRUPTED_FILE_DOWNLOADED, { + apkPath: shouldUpdate.newApkCachedUrl, + oldAppVersion, + newAppVersion, + }); + openFallbackLonghornLink(fallbackLonghornUrl); + } else { + installApk(shouldUpdate.newApkCachedUrl, (error) => { + if (!error) { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_APK_UPDATE_INSTALL_STARTED, { + apkPath: shouldUpdate.newApkCachedUrl, + oldAppVersion, + newAppVersion, + }); + return; + } + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_APK_UPDATE_INSTALL_FAILED, { + apkPath: shouldUpdate.newApkCachedUrl, + errorMessage: error, + oldAppVersion, + newAppVersion, + }); + openFallbackLonghornLink(fallbackLonghornUrl); + }); } - openFallbackLonghornLink(fallbackLonghornUrl); }); }; @@ -105,18 +140,22 @@ const BlockerScreen = (props: IBlockerScreen) => { if (!flavorToUpdate) return; const currentBuildNumber = getBuildVersion(); - if ( currentBuildNumber && !isNaN(currentBuildNumber) && currentBuildNumber < flavorToUpdate.version ) { downloadLatestApp(); - } else { - setShouldUpdate({ - newApkCachedUrl: '', - switchToFallback: false, + } else if (shouldUpdate.newApkCachedUrl) { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_APK_UPDATE_INSTALL_SUCCESS, { + appVersion: currentBuildNumber, }); + dispatch( + setShouldUpdate({ + newApkCachedUrl: '', + switchToFallback: false, + }) + ); deleteCachedApkFiles(); } }, [appState]); diff --git a/src/common/Constants.ts b/src/common/Constants.ts index 7df85363..d48340be 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -1309,6 +1309,44 @@ export const CLICKSTREAM_EVENT_NAMES = { name: 'FA_UNSYNC_FEEDBACK_CAPTURED', description: 'Unsync feedback captured' }, + + // Apk Update + FA_APK_UPDATE_DOWNLOAD_STARTED: { + name: 'FA_APK_UPDATE_DOWNLOAD_STARTED', + description: 'APK update download started' + }, + FA_APK_UPDATE_DOWNLOAD_SUCCESS: { + name: 'FA_APK_UPDATE_DOWNLOAD_SUCCESS', + description: 'APK update download completed' + }, + FA_APK_UPDATE_DOWNLOAD_FAILED: { + name: 'FA_APK_UPDATE_DOWNLOAD_FAILED', + description: 'APK update download failed' + }, + FA_APK_UPDATE_BUTTON_CLICKED: { + name: 'FA_APK_UPDATE_BUTTON_CLICKED', + description: 'APK update button clicked' + }, + FA_APK_UPDATE_INSTALL_STARTED: { + name: 'FA_APK_UPDATE_INSTALL_STARTED', + description: 'APK update installation started' + }, + FA_APK_UPDATE_INSTALL_FAILED: { + name: 'FA_APK_UPDATE_INSTALL_FAILED', + description: 'APK update installation failed' + }, + FA_APK_UPDATE_FALLBACK_TRIGGERED: { + name: 'FA_APK_UPDATE_FALLBACK_TRIGGERED', + description: 'APK update fallback triggered' + }, + FA_APK_UPDATE_CORRUPTED_FILE_DOWNLOADED: { + name: 'FA_APK_UPDATE_CORRUPTED_FILE_DOWNLOADED', + description: 'APK update corrupted file downloaded' + }, + FA_APK_UPDATE_INSTALL_SUCCESS: { + name: 'FA_APK_UPDATE_INSTALL_SUCCESS', + description: 'APK update installation success' + }, } as const; export enum MimeType { diff --git a/src/reducer/appUpdateSlice.ts b/src/reducer/appUpdateSlice.ts new file mode 100644 index 00000000..c4d9cde6 --- /dev/null +++ b/src/reducer/appUpdateSlice.ts @@ -0,0 +1,29 @@ +import { createSlice } from '@reduxjs/toolkit'; + +interface IAppUpdateSlice { + shouldUpdate: { + newApkCachedUrl: string; + switchToFallback: boolean; + }; +} + +const initialState: IAppUpdateSlice = { + shouldUpdate: { + newApkCachedUrl: '', + switchToFallback: false, + }, +}; + +const AppUpdateSlice = createSlice({ + name: 'appUpdate', + initialState, + reducers: { + setShouldUpdate: (state, action) => { + state.shouldUpdate = action.payload; + }, + }, +}); + +export const { setShouldUpdate } = AppUpdateSlice.actions; + +export default AppUpdateSlice.reducer; diff --git a/src/store/store.ts b/src/store/store.ts index 2ecd7293..0c728e9a 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -16,6 +16,7 @@ import repaymentsSlice from '../reducer/repaymentsSlice'; import feedbackHistorySlice from '../reducer/feedbackHistorySlice'; import notificationsSlice from '../reducer/notificationsSlice'; import MetadataSlice from '../reducer/metadataSlice'; +import AppUpdateSlice from '../reducer/appUpdateSlice'; import foregroundServiceSlice from '../reducer/foregroundServiceSlice'; import feedbackImagesSlice from '../reducer/feedbackImagesSlice'; import configSlice from '../reducer/configSlice'; @@ -47,6 +48,7 @@ const rootReducer = combineReducers({ address: addressSlice, notifications: notificationsSlice, metadata: MetadataSlice, + appUpdate: AppUpdateSlice, foregroundService: foregroundServiceSlice, feedbackImages: feedbackImagesSlice, config: configSlice, @@ -86,7 +88,8 @@ const persistConfig = { 'foregroundService', 'feedbackFilters', 'litmusExperiment', - 'activeCall' + 'activeCall', + 'appUpdate' ], blackList: [ 'case', From 073c715e3dea7140030989fc728739b42e68adae Mon Sep 17 00:00:00 2001 From: Shri Prakash Bajpai Date: Mon, 14 Oct 2024 18:06:14 +0530 Subject: [PATCH 09/56] NTP-7706 Sentry changes (#975) --- App.tsx | 7 +------ android/app/build.gradle | 4 ++-- package.json | 4 ++-- src/components/utlis/errorUtils.ts | 20 ++++++++++---------- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/App.tsx b/App.tsx index 5f1ec834..93efc6e8 100644 --- a/App.tsx +++ b/App.tsx @@ -1,6 +1,5 @@ import AsyncStorage from '@react-native-async-storage/async-storage'; import { NavigationContainer } from '@react-navigation/native'; -import * as Sentry from '@sentry/react-native'; import React, { useEffect } from 'react'; import { AppState, @@ -38,7 +37,6 @@ import { CLICKSTREAM_EVENT_NAMES, LocalStorageKeys } from './src/common/Constant import ErrorBoundary from './src/common/ErrorBoundary'; import { getPermissionsToRequest } from './src/components/utlis/PermissionUtils'; import ScreenshotBlocker from './src/components/utlis/ScreenshotBlocker'; -import { initSentry } from './src/components/utlis/sentry'; import { setItem } from './src/components/utlis/storageHelper'; import { ENV } from './src/constants/config'; import usePolling from './src/hooks/usePolling'; @@ -51,7 +49,6 @@ import fetchUpdatedRemoteConfig from './src/services/firebaseFetchAndUpdate.serv import { StorageKeys } from './src/types/storageKeys'; import CodePushLoadingModal, { CodePushLoadingModalRef } from './CodePushModal'; -initSentry(); if (ENV !== 'prod') { // mockApiServer(); @@ -218,6 +215,4 @@ function App() { ); } -const AppWithSentry = Sentry.wrap(App); - -export default AppWithSentry; +export default App; diff --git a/android/app/build.gradle b/android/app/build.gradle index 275a8ca6..44a33a3f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -134,8 +134,8 @@ def reactNativeArchitectures() { return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } -def VERSION_CODE = 201 -def VERSION_NAME = "2.14.1" +def VERSION_CODE = 202 +def VERSION_NAME = "2.14.2" android { ndkVersion rootProject.ext.ndkVersion diff --git a/package.json b/package.json index abaeedfb..2c669b83 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "AV_APP", - "version": "2.14.1", - "buildNumber": "201", + "version": "2.14.2", + "buildNumber": "202", "private": true, "scripts": { "android:dev": "yarn move:dev && react-native run-android", diff --git a/src/components/utlis/errorUtils.ts b/src/components/utlis/errorUtils.ts index 2a0d30e2..f64f42b2 100644 --- a/src/components/utlis/errorUtils.ts +++ b/src/components/utlis/errorUtils.ts @@ -6,17 +6,17 @@ export const logError = (error: Error, extraInfo = '') => { // Disable sentry in development mode return; } - Sentry.setTag('agentId', GLOBAL.AGENT_ID || 'not-logged-in'); - Sentry.captureException(error, (scope) => { - scope.setExtra('ExtraInfo', extraInfo); - return scope; - }); + // Sentry.setTag('agentId', GLOBAL.AGENT_ID || 'not-logged-in'); + // Sentry.captureException(error, (scope) => { + // scope.setExtra('ExtraInfo', extraInfo); + // return scope; + // }); }; export const sentryCaptureMessage = (errorStr: string, extraInfo = '') => { - Sentry.setTag('agentId', GLOBAL.AGENT_ID || 'not-logged-in'); - Sentry.captureMessage(errorStr, (scope) => { - scope.setExtra('ExtraInfo', extraInfo); - return scope; - }); + // Sentry.setTag('agentId', GLOBAL.AGENT_ID || 'not-logged-in'); + // Sentry.captureMessage(errorStr, (scope) => { + // scope.setExtra('ExtraInfo', extraInfo); + // return scope; + // }); }; From 4f711899d318df0696e818536dfff4e8eae3810c Mon Sep 17 00:00:00 2001 From: "aishwarya.srivastava" Date: Tue, 15 Oct 2024 16:03:44 +0530 Subject: [PATCH 10/56] NTP-6457| DPD cycle for 16 to 30 field --- src/reducer/userSlice.ts | 13 +++++++++++-- src/screens/allCases/ListItem.tsx | 17 +++++++++++++---- src/screens/caseDetails/CollectionCaseData.tsx | 16 ++++++++++++---- src/screens/caseDetails/interface.ts | 1 + 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/reducer/userSlice.ts b/src/reducer/userSlice.ts index b4d0bffb..5bfbde58 100644 --- a/src/reducer/userSlice.ts +++ b/src/reducer/userSlice.ts @@ -77,6 +77,7 @@ export interface IUserSlice extends IUser { isCallRecordingCosmosExotelEnabled: boolean; }; employeeId: string; + is16To30FieldAgent: boolean; } const initialState: IUserSlice = { @@ -105,6 +106,7 @@ const initialState: IUserSlice = { isCallRecordingCosmosExotelEnabled: false, }, employeeId: '', + is16To30FieldAgent: false, }; export const userSlice = createSlice({ @@ -142,8 +144,14 @@ export const userSlice = createSlice({ state.agentAttendance = action.payload; }, setUserAccessData: (state, action) => { - const { roles, isExternalAgent, isFieldTeamLeadOrAgencyManager, featureFlags, employeeId } = - action.payload || {}; + const { + roles, + isExternalAgent, + is16To30FieldAgent, + isFieldTeamLeadOrAgencyManager, + featureFlags, + employeeId, + } = action.payload || {}; if (roles?.length) { state.isTeamLead = isFieldTeamLeadOrAgencyManager; } else { @@ -153,6 +161,7 @@ export const userSlice = createSlice({ state.agentRoles = roles; state.featureFlags = featureFlags; state.employeeId = employeeId; + state.is16To30FieldAgent = is16To30FieldAgent; }, }, }); diff --git a/src/screens/allCases/ListItem.tsx b/src/screens/allCases/ListItem.tsx index 7fe62155..f2c9c3fa 100644 --- a/src/screens/allCases/ListItem.tsx +++ b/src/screens/allCases/ListItem.tsx @@ -77,6 +77,7 @@ const ListItem: React.FC = (props) => { collectionTag, paymentStatus, dpdBucket, + dpdCycle, pinRank, isSynced, isNewlyAdded, @@ -191,6 +192,7 @@ const ListItem: React.FC = (props) => { !isTeamLead && !nearbyCaseView; + const is16to30FieldAgent = useAppSelector((state) => state.user?.is16To30FieldAgent); const distanceMapOfNearbyCases = useAppSelector((state) => state.nearbyCasesSlice.caseReferenceIdToDistanceMap) || {}; const selectedTab = useAppSelector((state) => state?.nearbyCasesSlice?.sortTabSelected); @@ -291,10 +293,17 @@ const ListItem: React.FC = (props) => { )} - - Total due {formatAmount(totalOverdueAmount, false)} - {' '}DPD bucket {dpdBucket} - + {is16to30FieldAgent ? ( + + Total due {formatAmount(totalOverdueAmount, false)} + {' '}DPD Cycle {dpdCycle} + + ) : ( + + Total due {formatAmount(totalOverdueAmount, false)} + {' '}DPD bucket {dpdBucket} + + )} {caseInteractionStatus ? ( {caseInteractionStatus} diff --git a/src/screens/caseDetails/CollectionCaseData.tsx b/src/screens/caseDetails/CollectionCaseData.tsx index dd9354c4..8e2546c8 100644 --- a/src/screens/caseDetails/CollectionCaseData.tsx +++ b/src/screens/caseDetails/CollectionCaseData.tsx @@ -11,6 +11,7 @@ import { addClickstreamEvent } from '../../services/clickstreamEventService'; import { CLICKSTREAM_EVENT_NAMES } from '../../common/Constants'; import { ToastMessages } from '../allCases/constants'; import { toTileCase } from '../../components/utlis/commonFunctions'; +import { useAppSelector } from '@hooks'; interface ICollectionCaseData { caseData: CaseDetail; @@ -22,12 +23,13 @@ const CollectionCaseData: React.FC = ({ caseData }) => { currentDpd, loanAccountNumber, dpdBucket, + dpdCycle, pos, collectionTag, employmentDetail, unpaidDays } = caseData; - + const is16to30FieldAgent = useAppSelector((state) => state.user.is16To30FieldAgent ); return ( {fatherName && ( @@ -67,9 +69,15 @@ const CollectionCaseData: React.FC = ({ caseData }) => { GenericStyles.flexWrap, ]} > - - DPD bucket {dpdBucket} - + {is16to30FieldAgent ? ( + + DPD Cycle {dpdCycle} + + ) : ( + + DPD bucket {dpdBucket} + + )} POS {formatAmount(pos)} diff --git a/src/screens/caseDetails/interface.ts b/src/screens/caseDetails/interface.ts index eaafec3a..a6031e07 100644 --- a/src/screens/caseDetails/interface.ts +++ b/src/screens/caseDetails/interface.ts @@ -284,6 +284,7 @@ export interface CaseDetail { customerName: string; pos: number; dpdBucket: string; + dpdCycle: string; addresses?: Address[]; currentAllocationReferenceId: string; customerReferenceId: string; From e42b1441a4311d5859ed6a4788b0e4a266eb474a Mon Sep 17 00:00:00 2001 From: "aishwarya.srivastava" Date: Tue, 15 Oct 2024 17:24:14 +0530 Subject: [PATCH 11/56] NTP-6457| added optional chaining --- src/screens/caseDetails/CollectionCaseData.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/caseDetails/CollectionCaseData.tsx b/src/screens/caseDetails/CollectionCaseData.tsx index 8e2546c8..5d219d25 100644 --- a/src/screens/caseDetails/CollectionCaseData.tsx +++ b/src/screens/caseDetails/CollectionCaseData.tsx @@ -29,7 +29,7 @@ const CollectionCaseData: React.FC = ({ caseData }) => { employmentDetail, unpaidDays } = caseData; - const is16to30FieldAgent = useAppSelector((state) => state.user.is16To30FieldAgent ); + const is16to30FieldAgent = useAppSelector((state) => state.user?.is16To30FieldAgent ); return ( {fatherName && ( From b82afb5223504e5cce62fc4e2615457d42a5e89e Mon Sep 17 00:00:00 2001 From: "aishwarya.srivastava" Date: Tue, 15 Oct 2024 17:44:08 +0530 Subject: [PATCH 12/56] NTP-6457| Version bump(due cycle for 16 to 30 field) --- android/app/build.gradle | 4 ++-- package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 44a33a3f..9effb6ca 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -134,8 +134,8 @@ def reactNativeArchitectures() { return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } -def VERSION_CODE = 202 -def VERSION_NAME = "2.14.2" +def VERSION_CODE = 203 +def VERSION_NAME = "2.14.3" android { ndkVersion rootProject.ext.ndkVersion diff --git a/package.json b/package.json index 2c669b83..5ad95340 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "AV_APP", - "version": "2.14.2", - "buildNumber": "202", + "version": "2.14.3", + "buildNumber": "203", "private": true, "scripts": { "android:dev": "yarn move:dev && react-native run-android", From 4cd7d90bcdf5b9b0316b0e08ba14b1e3ceab9ca9 Mon Sep 17 00:00:00 2001 From: Aman Chaturvedi Date: Tue, 15 Oct 2024 17:46:18 +0530 Subject: [PATCH 13/56] NTP-5975 | Pin case V2 --- android/app/build.gradle | 4 ++-- package.json | 4 ++-- src/action/dataActions.ts | 39 ++++++++++++++++++++++--------- src/common/Constants.ts | 2 ++ src/components/utlis/apiHelper.ts | 2 ++ 5 files changed, 36 insertions(+), 15 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 44a33a3f..9effb6ca 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -134,8 +134,8 @@ def reactNativeArchitectures() { return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } -def VERSION_CODE = 202 -def VERSION_NAME = "2.14.2" +def VERSION_CODE = 203 +def VERSION_NAME = "2.14.3" android { ndkVersion rootProject.ext.ndkVersion diff --git a/package.json b/package.json index 2c669b83..5ad95340 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "AV_APP", - "version": "2.14.2", - "buildNumber": "202", + "version": "2.14.3", + "buildNumber": "203", "private": true, "scripts": { "android:dev": "yarn move:dev && react-native run-android", diff --git a/src/action/dataActions.ts b/src/action/dataActions.ts index 962b737e..55bbca61 100644 --- a/src/action/dataActions.ts +++ b/src/action/dataActions.ts @@ -34,7 +34,7 @@ const SUBMIT_FEEDBACK_API_VERSION = 5; export const postPinnedList = (pinnedCases: IPinnedCasesPayload[], updatedCaseList: ICaseItem[], type: string) => - (dispatch: AppDispatch) => { + async (dispatch: AppDispatch) => { dispatch(setVisitPlansUpdating(true)); let pinRankCount = 1; const payload: IPinnedCasesPayload[] = pinnedCases.reduce((acc, pinnedCase) => { @@ -44,7 +44,12 @@ export const postPinnedList = }); return acc; }, [] as IPinnedCasesPayload[]); - const url = getApiUrl(ApiKeys.PINNED_CASES); + const enableCaseCollectionManager = + (await getAsyncStorageItem(LocalStorageKeys.COSMOS_CASE_COLLECTION_MANAGER_ENABLE, true)) ?? + false; + const url = getApiUrl( + enableCaseCollectionManager ? ApiKeys.PINNED_CASES_V2 : ApiKeys.PINNED_CASES + ); axiosInstance .post(url, payload) .then((response) => { @@ -148,22 +153,34 @@ export type ISignedRequest = ISignedRequestItem[]; export const getSignedApi = async ( signedRequestPayload: ISignedRequest, shouldBatch = false, - skipFirebaseUpdate = false, + skipFirebaseUpdate = false ): Promise<{ imageUrl: string }> => { return new Promise((res) => { if (shouldBatch) { - batchSignedApiRequest(signedRequestPayload, (results: any) => { + batchSignedApiRequest( + signedRequestPayload, + (results: any) => { res({ imageUrl: results?.[signedRequestPayload[0].documentReferenceId] || '' }); - }, skipFirebaseUpdate); + }, + skipFirebaseUpdate + ); } else { - makeBulkSignedApiRequest(signedRequestPayload, (results: any) => { + makeBulkSignedApiRequest( + signedRequestPayload, + (results: any) => { res({ imageUrl: results?.[signedRequestPayload[0].documentReferenceId] || '' }); - }, skipFirebaseUpdate); + }, + skipFirebaseUpdate + ); } }); }; -async function batchSignedApiRequest(payload: ISignedRequestItem[], callback: GenericFunctionArgs, skipFirebaseUpdate = false) { +async function batchSignedApiRequest( + payload: ISignedRequestItem[], + callback: GenericFunctionArgs, + skipFirebaseUpdate = false +) { payload.forEach((item) => { _signedApiCallBucket.push({ req: item, added_At: Date.now(), callback }); }); @@ -171,7 +188,7 @@ async function batchSignedApiRequest(payload: ISignedRequestItem[], callback: Ge await makeBulkSignedApiRequest( _signedApiCallBucket.map((a) => a.req), _signedApiCallBucket.map((a) => a.callback), - skipFirebaseUpdate, + skipFirebaseUpdate ); return; } else if (!_signedApiCallBucketTimer) { @@ -179,7 +196,7 @@ async function batchSignedApiRequest(payload: ISignedRequestItem[], callback: Ge await makeBulkSignedApiRequest( _signedApiCallBucket.map((a) => a.req), _signedApiCallBucket.map((a) => a.callback), - skipFirebaseUpdate, + skipFirebaseUpdate ); }, SIGNED_API_BUCKET_TIMEOUT); } @@ -188,7 +205,7 @@ async function batchSignedApiRequest(payload: ISignedRequestItem[], callback: Ge async function makeBulkSignedApiRequest( payload: ISignedRequestItem[], callback: GenericFunctionArgs | GenericFunctionArgs[], - skipFirebaseUpdate = false, + skipFirebaseUpdate = false ) { const enableCaseCollectionManager = (await getAsyncStorageItem(LocalStorageKeys.COSMOS_CASE_COLLECTION_MANAGER_ENABLE, true)) ?? diff --git a/src/common/Constants.ts b/src/common/Constants.ts index 759a84da..f78b2ac7 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -1476,8 +1476,10 @@ export const BUTTON_PRESS_COUNT_FOR_IMPERSONATION = 5; export const REQUEST_TYPE_TO_BLOCK_FOR_IMPERSONATION = ['post', 'put', 'patch', 'delete']; export const REQUEST_TO_UNBLOCK_FOR_IMPERSONATION = [ + getApiUrl(ApiKeys.GET_SIGNED_URL_V2), getApiUrl(ApiKeys.GET_SIGNED_URL), getApiUrl(ApiKeys.GET_SIGNED_URL_FOR_REPORTEE), + getApiUrl(ApiKeys.GET_SIGNED_URL_FOR_REPORTEE_V2), getApiUrl(ApiKeys.LOGOUT), getApiUrl(ApiKeys.PAST_FEEDBACK), getApiUrl(ApiKeys.GET_CSA_TICKETS), diff --git a/src/components/utlis/apiHelper.ts b/src/components/utlis/apiHelper.ts index bb1ea85f..042a5eee 100644 --- a/src/components/utlis/apiHelper.ts +++ b/src/components/utlis/apiHelper.ts @@ -26,6 +26,7 @@ export enum ApiKeys { ALL_CASES = 'ALL_CASES', CASE_DETAIL = 'CASE_DETAIL', PINNED_CASES = 'PINNED_CASES', + PINNED_CASES_V2 = 'PINNED_CASES_V2', LOGOUT = 'LOGOUT', FEEDBACK = 'FEEDBACK', FILTERS = 'FILTERS', @@ -110,6 +111,7 @@ API_URLS[ApiKeys.VERIFY_OTP] = '/auth/otp/verify'; API_URLS[ApiKeys.ALL_CASES] = '/cases/all-cases'; API_URLS[ApiKeys.CASE_DETAIL] = '/cases/get-cases'; API_URLS[ApiKeys.PINNED_CASES] = '/cases/pin'; +API_URLS[ApiKeys.PINNED_CASES_V2] = '/cases/v2/pin'; API_URLS[ApiKeys.LOGOUT] = '/auth/logout'; API_URLS[ApiKeys.FEEDBACK] = '/cases/feedback'; API_URLS[ApiKeys.FILTERS] = '/cases/filters'; From 8f7e46c30bc3158b096ceba94a1c62379780f737 Mon Sep 17 00:00:00 2001 From: "aishwarya.srivastava" Date: Wed, 16 Oct 2024 15:22:03 +0530 Subject: [PATCH 14/56] NTP-6457| rename flag to 1to30FieldAgent --- src/reducer/userSlice.ts | 8 ++++---- src/screens/allCases/ListItem.tsx | 4 ++-- src/screens/caseDetails/CollectionCaseData.tsx | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/reducer/userSlice.ts b/src/reducer/userSlice.ts index 5bfbde58..571defed 100644 --- a/src/reducer/userSlice.ts +++ b/src/reducer/userSlice.ts @@ -77,7 +77,7 @@ export interface IUserSlice extends IUser { isCallRecordingCosmosExotelEnabled: boolean; }; employeeId: string; - is16To30FieldAgent: boolean; + is1To30FieldAgent: boolean; } const initialState: IUserSlice = { @@ -106,7 +106,7 @@ const initialState: IUserSlice = { isCallRecordingCosmosExotelEnabled: false, }, employeeId: '', - is16To30FieldAgent: false, + is1To30FieldAgent: false, }; export const userSlice = createSlice({ @@ -147,7 +147,7 @@ export const userSlice = createSlice({ const { roles, isExternalAgent, - is16To30FieldAgent, + is1To30FieldAgent, isFieldTeamLeadOrAgencyManager, featureFlags, employeeId, @@ -161,7 +161,7 @@ export const userSlice = createSlice({ state.agentRoles = roles; state.featureFlags = featureFlags; state.employeeId = employeeId; - state.is16To30FieldAgent = is16To30FieldAgent; + state.is1To30FieldAgent = is1To30FieldAgent; }, }, }); diff --git a/src/screens/allCases/ListItem.tsx b/src/screens/allCases/ListItem.tsx index f2c9c3fa..6abc086c 100644 --- a/src/screens/allCases/ListItem.tsx +++ b/src/screens/allCases/ListItem.tsx @@ -192,7 +192,7 @@ const ListItem: React.FC = (props) => { !isTeamLead && !nearbyCaseView; - const is16to30FieldAgent = useAppSelector((state) => state.user?.is16To30FieldAgent); + const is1To30FieldAgent = useAppSelector((state) => state.user?.is1To30FieldAgent); const distanceMapOfNearbyCases = useAppSelector((state) => state.nearbyCasesSlice.caseReferenceIdToDistanceMap) || {}; const selectedTab = useAppSelector((state) => state?.nearbyCasesSlice?.sortTabSelected); @@ -293,7 +293,7 @@ const ListItem: React.FC = (props) => { )} - {is16to30FieldAgent ? ( + {is1To30FieldAgent ? ( Total due {formatAmount(totalOverdueAmount, false)} {' '}DPD Cycle {dpdCycle} diff --git a/src/screens/caseDetails/CollectionCaseData.tsx b/src/screens/caseDetails/CollectionCaseData.tsx index 5d219d25..893f6f00 100644 --- a/src/screens/caseDetails/CollectionCaseData.tsx +++ b/src/screens/caseDetails/CollectionCaseData.tsx @@ -29,7 +29,7 @@ const CollectionCaseData: React.FC = ({ caseData }) => { employmentDetail, unpaidDays } = caseData; - const is16to30FieldAgent = useAppSelector((state) => state.user?.is16To30FieldAgent ); + const is1To30FieldAgent = useAppSelector((state) => state.user?.is1To30FieldAgent ); return ( {fatherName && ( @@ -69,7 +69,7 @@ const CollectionCaseData: React.FC = ({ caseData }) => { GenericStyles.flexWrap, ]} > - {is16to30FieldAgent ? ( + {is1To30FieldAgent ? ( DPD Cycle {dpdCycle} From 0d175c04fcdf83f0b0dd393d2d57072c8fbd4f4a Mon Sep 17 00:00:00 2001 From: yashmantri Date: Wed, 16 Oct 2024 17:18:16 +0530 Subject: [PATCH 15/56] TP-85529 | Location Reference Id fix --- .../form/components/AddressSelection.tsx | 87 +++++++++---------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/src/components/form/components/AddressSelection.tsx b/src/components/form/components/AddressSelection.tsx index 4111a736..ac6f300d 100644 --- a/src/components/form/components/AddressSelection.tsx +++ b/src/components/form/components/AddressSelection.tsx @@ -109,20 +109,6 @@ const AddressSelection: React.FC = (props) => { }; if (isGeolocation) { - if (isLoading) { - return ( - - {[...Array(7).keys()].map((_, index) => ( - - ))} - - ); - } if (!addresses?.length) { return ( @@ -137,41 +123,54 @@ const AddressSelection: React.FC = (props) => { key={controllerName} control={control} rules={{ validate: (data) => validateInput(data, question.metadata.validators) }} - render={({ field: { onChange, value } }) => ( - + render={({ field: { onChange, value } }) => + isLoading ? ( + + {[...Array(7).keys()].map((_, index) => ( + + ))} + + ) : ( - - - No nearby geolocations found - + + + + No nearby geolocations found + + + + + + + Retry + - - - - - Retry - - - )} + ) + } name={controllerName} /> From 6d410b64ffb5e4a63dc958cc89d9f26891ced0c4 Mon Sep 17 00:00:00 2001 From: yashmantri Date: Fri, 18 Oct 2024 01:28:04 +0530 Subject: [PATCH 16/56] NTP-8286 | Block Cosmos Post Operative Hours --- src/assets/icons/AppRestrictionIcon.tsx | 22 +++++ src/common/AppRestriction.tsx | 114 ++++++++++++++++++++++++ src/common/BlockerScreen.tsx | 6 ++ src/reducer/userSlice.ts | 4 + 4 files changed, 146 insertions(+) create mode 100644 src/assets/icons/AppRestrictionIcon.tsx create mode 100644 src/common/AppRestriction.tsx diff --git a/src/assets/icons/AppRestrictionIcon.tsx b/src/assets/icons/AppRestrictionIcon.tsx new file mode 100644 index 00000000..e48d5ab7 --- /dev/null +++ b/src/assets/icons/AppRestrictionIcon.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { Circle, G, Mask, Path, Rect, Svg } from 'react-native-svg'; + +const AppRestrictionIcon = () => { + return ( + + + + + + + + + + + ); +}; + +export default AppRestrictionIcon; diff --git a/src/common/AppRestriction.tsx b/src/common/AppRestriction.tsx new file mode 100644 index 00000000..f98c1e07 --- /dev/null +++ b/src/common/AppRestriction.tsx @@ -0,0 +1,114 @@ +import { getAgentDetail, logout } from '@actions/authActions'; +import AppRestrictionIcon from '@assets/icons/AppRestrictionIcon'; +import { useAppDispatch } from '@hooks'; +import { AppStates } from '@interfaces/appStates'; +import { COLORS } from '@rn-ui-lib/colors'; +import Button from '@rn-ui-lib/components/Button'; +import Text from '@rn-ui-lib/components/Text'; +import LogoutIcon from '@rn-ui-lib/icons/LogoutIcon'; +import { GenericStyles } from '@rn-ui-lib/styles'; +import React, { useEffect } from 'react'; +import { AppState, AppStateStatus, StyleSheet } from 'react-native'; +import { View } from 'react-native'; + +const AppRestriction = () => { + const dispatch = useAppDispatch(); + + useEffect(() => { + dispatch(getAgentDetail()); + }, []); + + const handleAppStateChange = (nextAppState: AppStateStatus) => { + if (nextAppState === AppStates.ACTIVE) { + dispatch(getAgentDetail()); + } + }; + + useEffect(() => { + const appStateListener = AppState.addEventListener('change', handleAppStateChange); + return () => { + appStateListener.remove(); + }; + }, []); + + return ( + + + + + + You have logged in post operative hours! + + Please{' '} + + login tomorrow at 8 AM + + {'\n'} + to access COSMOS + + +