From 356b4edeaaa8332af8b43010f1ba5d2208595850 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Tue, 2 Jun 2026 09:34:54 +0530 Subject: [PATCH 1/3] fix: close HR OAuth WebView modal on connection complete Signed-off-by: krishna2323 --- src/components/ConnectToHRFlow/index.native.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/ConnectToHRFlow/index.native.tsx b/src/components/ConnectToHRFlow/index.native.tsx index bb5e859d952d..db54e473fa04 100644 --- a/src/components/ConnectToHRFlow/index.native.tsx +++ b/src/components/ConnectToHRFlow/index.native.tsx @@ -1,5 +1,6 @@ import React, {useRef, useState} from 'react'; import {StyleSheet, View} from 'react-native'; +import type {WebViewNavigation} from 'react-native-webview'; import {WebView} from 'react-native-webview'; import ActivityIndicator from '@components/ActivityIndicator'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; @@ -10,6 +11,7 @@ import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type ConnectToHRFlowProps from './types'; function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) { @@ -28,6 +30,13 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) { ); + const handleNavigationStateChange = (navState: WebViewNavigation) => { + if (!navState.url.includes(ROUTES.CONNECTION_COMPLETE)) { + return; + } + setIsWebViewOpen(false); + }; + const authToken = session?.authToken ?? null; return ( From fd34214657401a68e714e05d1613be368557080c Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Tue, 2 Jun 2026 10:07:24 +0530 Subject: [PATCH 2/3] fix: defer HR sync spinner until API call succeeds (offline pattern B) Signed-off-by: krishna2323 --- src/libs/actions/connections/Gusto.ts | 12 ++++++------ src/libs/actions/connections/Zenefits.ts | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libs/actions/connections/Gusto.ts b/src/libs/actions/connections/Gusto.ts index 6af636c97b9b..4b4c16813c33 100644 --- a/src/libs/actions/connections/Gusto.ts +++ b/src/libs/actions/connections/Gusto.ts @@ -53,7 +53,7 @@ function updateGustoApprovalMode( } const previousApprovalMode = currentApprovalMode ?? null; - const optimisticData: Array> = [ + const optimisticData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -69,9 +69,8 @@ function updateGustoApprovalMode( }, }, }, - getGustoSyncProgressOptimisticData(policyID), ]; - const successData: Array> = [ + const successData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -86,6 +85,7 @@ function updateGustoApprovalMode( }, }, }, + getGustoSyncProgressOptimisticData(policyID), ]; const failureData: Array> = [ { @@ -120,7 +120,7 @@ function updateGustoFinalApprover( } const previousFinalApprover = currentFinalApprover ?? null; - const optimisticData: Array> = [ + const optimisticData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -136,9 +136,8 @@ function updateGustoFinalApprover( }, }, }, - getGustoSyncProgressOptimisticData(policyID), ]; - const successData: Array> = [ + const successData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -153,6 +152,7 @@ function updateGustoFinalApprover( }, }, }, + getGustoSyncProgressOptimisticData(policyID), ]; const failureData: Array> = [ { diff --git a/src/libs/actions/connections/Zenefits.ts b/src/libs/actions/connections/Zenefits.ts index 409353741346..781593b5c148 100644 --- a/src/libs/actions/connections/Zenefits.ts +++ b/src/libs/actions/connections/Zenefits.ts @@ -53,7 +53,7 @@ function updateZenefitsApprovalMode( } const previousApprovalMode = currentApprovalMode ?? null; - const optimisticData: Array> = [ + const optimisticData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -69,9 +69,8 @@ function updateZenefitsApprovalMode( }, }, }, - getZenefitsSyncProgressOptimisticData(policyID), ]; - const successData: Array> = [ + const successData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -86,6 +85,7 @@ function updateZenefitsApprovalMode( }, }, }, + getZenefitsSyncProgressOptimisticData(policyID), ]; const failureData: Array> = [ { @@ -120,7 +120,7 @@ function updateZenefitsFinalApprover( } const previousFinalApprover = currentFinalApprover ?? null; - const optimisticData: Array> = [ + const optimisticData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -136,9 +136,8 @@ function updateZenefitsFinalApprover( }, }, }, - getZenefitsSyncProgressOptimisticData(policyID), ]; - const successData: Array> = [ + const successData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -153,6 +152,7 @@ function updateZenefitsFinalApprover( }, }, }, + getZenefitsSyncProgressOptimisticData(policyID), ]; const failureData: Array> = [ { From 5ee232220c1064ea51d2895a1c92ce3a5e4c7718 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Tue, 2 Jun 2026 10:21:57 +0530 Subject: [PATCH 3/3] fix: remove fake sync progress from HR approval mode/approver actions Signed-off-by: krishna2323 --- src/libs/actions/connections/Gusto.ts | 46 +++---------------- src/libs/actions/connections/Zenefits.ts | 46 +++---------------- .../hr/gusto/GustoApprovalModePage.tsx | 2 +- .../hr/gusto/GustoFinalApproverPage.tsx | 2 +- .../hr/zenefits/ZenefitsApprovalModePage.tsx | 3 +- .../hr/zenefits/ZenefitsFinalApproverPage.tsx | 2 +- 6 files changed, 16 insertions(+), 85 deletions(-) diff --git a/src/libs/actions/connections/Gusto.ts b/src/libs/actions/connections/Gusto.ts index 4b4c16813c33..0315b43d1f5b 100644 --- a/src/libs/actions/connections/Gusto.ts +++ b/src/libs/actions/connections/Gusto.ts @@ -1,4 +1,4 @@ -import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; +import type {OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import {write} from '@libs/API'; @@ -8,7 +8,6 @@ import {getCommandURL} from '@libs/ApiUtils'; import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {PolicyConnectionSyncProgress} from '@src/types/onyx/Policy'; function getGustoSetupLink(policyID: string) { const params: ConnectPolicyToGustoParams = {policyID}; @@ -19,34 +18,10 @@ function getGustoSetupLink(policyID: string) { return commandURL + new URLSearchParams(params).toString(); } -function getGustoSyncProgressOptimisticData(policyID: string): OnyxUpdate { - return { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policyID}`, - value: { - stageInProgress: CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.GUSTO_SYNC_TITLE, - connectionName: CONST.POLICY.CONNECTIONS.NAME.GUSTO, - timestamp: new Date().toISOString(), - }, - }; -} - -function getGustoSyncProgressFailureData( - policyID: string, - currentConnectionSyncProgress: OnyxEntry, -): OnyxUpdate { - return { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policyID}`, - value: currentConnectionSyncProgress ?? null, - }; -} - function updateGustoApprovalMode( policyID: string | undefined, approvalMode: ValueOf, currentApprovalMode?: ValueOf | null, - currentConnectionSyncProgress?: OnyxEntry, ) { if (!policyID) { return; @@ -70,7 +45,7 @@ function updateGustoApprovalMode( }, }, ]; - const successData: Array> = [ + const successData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -85,9 +60,8 @@ function updateGustoApprovalMode( }, }, }, - getGustoSyncProgressOptimisticData(policyID), ]; - const failureData: Array> = [ + const failureData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -103,18 +77,12 @@ function updateGustoApprovalMode( }, }, }, - getGustoSyncProgressFailureData(policyID, currentConnectionSyncProgress), ]; write(WRITE_COMMANDS.UPDATE_GUSTO_APPROVAL_MODE, {policyID, approvalMode}, {optimisticData, successData, failureData}); } -function updateGustoFinalApprover( - policyID: string | undefined, - finalApprover: string | null, - currentFinalApprover?: string | null, - currentConnectionSyncProgress?: OnyxEntry, -) { +function updateGustoFinalApprover(policyID: string | undefined, finalApprover: string | null, currentFinalApprover?: string | null) { if (!policyID) { return; } @@ -137,7 +105,7 @@ function updateGustoFinalApprover( }, }, ]; - const successData: Array> = [ + const successData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -152,9 +120,8 @@ function updateGustoFinalApprover( }, }, }, - getGustoSyncProgressOptimisticData(policyID), ]; - const failureData: Array> = [ + const failureData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -170,7 +137,6 @@ function updateGustoFinalApprover( }, }, }, - getGustoSyncProgressFailureData(policyID, currentConnectionSyncProgress), ]; write(WRITE_COMMANDS.UPDATE_GUSTO_FINAL_APPROVER, {policyID, finalApprover}, {optimisticData, successData, failureData}); diff --git a/src/libs/actions/connections/Zenefits.ts b/src/libs/actions/connections/Zenefits.ts index 781593b5c148..d027e4eb30aa 100644 --- a/src/libs/actions/connections/Zenefits.ts +++ b/src/libs/actions/connections/Zenefits.ts @@ -1,4 +1,4 @@ -import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; +import type {OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import {write} from '@libs/API'; @@ -8,7 +8,6 @@ import {getCommandURL} from '@libs/ApiUtils'; import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {PolicyConnectionSyncProgress} from '@src/types/onyx/Policy'; function getZenefitsSetupLink(policyID: string) { const params: ConnectPolicyToZenefitsParams = {policyID}; @@ -19,34 +18,10 @@ function getZenefitsSetupLink(policyID: string) { return commandURL + new URLSearchParams(params).toString(); } -function getZenefitsSyncProgressOptimisticData(policyID: string): OnyxUpdate { - return { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policyID}`, - value: { - stageInProgress: CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.ZENEFITS_SYNC_TITLE, - connectionName: CONST.POLICY.CONNECTIONS.NAME.ZENEFITS, - timestamp: new Date().toISOString(), - }, - }; -} - -function getZenefitsSyncProgressFailureData( - policyID: string, - currentConnectionSyncProgress: OnyxEntry, -): OnyxUpdate { - return { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policyID}`, - value: currentConnectionSyncProgress ?? null, - }; -} - function updateZenefitsApprovalMode( policyID: string | undefined, approvalMode: ValueOf, currentApprovalMode?: ValueOf | null, - currentConnectionSyncProgress?: OnyxEntry, ) { if (!policyID) { return; @@ -70,7 +45,7 @@ function updateZenefitsApprovalMode( }, }, ]; - const successData: Array> = [ + const successData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -85,9 +60,8 @@ function updateZenefitsApprovalMode( }, }, }, - getZenefitsSyncProgressOptimisticData(policyID), ]; - const failureData: Array> = [ + const failureData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -103,18 +77,12 @@ function updateZenefitsApprovalMode( }, }, }, - getZenefitsSyncProgressFailureData(policyID, currentConnectionSyncProgress), ]; write(WRITE_COMMANDS.UPDATE_ZENEFITS_APPROVAL_MODE, {policyID, approvalMode}, {optimisticData, successData, failureData}); } -function updateZenefitsFinalApprover( - policyID: string | undefined, - finalApprover: string | null, - currentFinalApprover?: string | null, - currentConnectionSyncProgress?: OnyxEntry, -) { +function updateZenefitsFinalApprover(policyID: string | undefined, finalApprover: string | null, currentFinalApprover?: string | null) { if (!policyID) { return; } @@ -137,7 +105,7 @@ function updateZenefitsFinalApprover( }, }, ]; - const successData: Array> = [ + const successData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -152,9 +120,8 @@ function updateZenefitsFinalApprover( }, }, }, - getZenefitsSyncProgressOptimisticData(policyID), ]; - const failureData: Array> = [ + const failureData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, @@ -170,7 +137,6 @@ function updateZenefitsFinalApprover( }, }, }, - getZenefitsSyncProgressFailureData(policyID, currentConnectionSyncProgress), ]; write(WRITE_COMMANDS.UPDATE_ZENEFITS_FINAL_APPROVER, {policyID, finalApprover}, {optimisticData, successData, failureData}); diff --git a/src/pages/workspace/hr/gusto/GustoApprovalModePage.tsx b/src/pages/workspace/hr/gusto/GustoApprovalModePage.tsx index 6f46f3ebbd91..de80395dd1b6 100644 --- a/src/pages/workspace/hr/gusto/GustoApprovalModePage.tsx +++ b/src/pages/workspace/hr/gusto/GustoApprovalModePage.tsx @@ -26,7 +26,7 @@ function GustoApprovalModePage({ getCurrentApprovalMode: (policy) => policy?.connections?.gusto?.config?.approvalMode ?? null, getProviderName: () => translate('workspace.hr.gusto.title'), getHeaderTitle: () => translate('workspace.hr.approvalMode'), - handleSave: ({draftApprovalMode, currentApprovalMode, connectionSyncProgress}) => updateGustoApprovalMode(policyID, draftApprovalMode, currentApprovalMode, connectionSyncProgress), + handleSave: ({draftApprovalMode, currentApprovalMode}) => updateGustoApprovalMode(policyID, draftApprovalMode, currentApprovalMode), }; return ( diff --git a/src/pages/workspace/hr/gusto/GustoFinalApproverPage.tsx b/src/pages/workspace/hr/gusto/GustoFinalApproverPage.tsx index 1a2aa8a2d4d4..0a762fad1c47 100644 --- a/src/pages/workspace/hr/gusto/GustoFinalApproverPage.tsx +++ b/src/pages/workspace/hr/gusto/GustoFinalApproverPage.tsx @@ -23,7 +23,7 @@ function GustoFinalApproverPage({ getCurrentFinalApprover: (policy) => policy?.connections?.gusto?.config?.finalApprover ?? null, getProviderName: () => translate('workspace.hr.gusto.title'), getHeaderTitle: () => translate('workspace.hr.finalApprover'), - handleSave: ({policyID: id, email, currentFinalApprover, connectionSyncProgress}) => updateGustoFinalApprover(id, email, currentFinalApprover, connectionSyncProgress), + handleSave: ({policyID: id, email, currentFinalApprover}) => updateGustoFinalApprover(id, email, currentFinalApprover), }; return ( diff --git a/src/pages/workspace/hr/zenefits/ZenefitsApprovalModePage.tsx b/src/pages/workspace/hr/zenefits/ZenefitsApprovalModePage.tsx index f91a213c3bcd..52711a9055cc 100644 --- a/src/pages/workspace/hr/zenefits/ZenefitsApprovalModePage.tsx +++ b/src/pages/workspace/hr/zenefits/ZenefitsApprovalModePage.tsx @@ -27,8 +27,7 @@ function ZenefitsApprovalModePage({ getCurrentApprovalMode: (policy) => policy?.connections?.zenefits?.config?.approvalMode ?? null, getProviderName: () => translate('workspace.hr.zenefits.title'), getHeaderTitle: () => translate('workspace.hr.approvalMode'), - handleSave: ({draftApprovalMode, currentApprovalMode, connectionSyncProgress}) => - updateZenefitsApprovalMode(policyID, draftApprovalMode, currentApprovalMode, connectionSyncProgress), + handleSave: ({draftApprovalMode, currentApprovalMode}) => updateZenefitsApprovalMode(policyID, draftApprovalMode, currentApprovalMode), }; return ( diff --git a/src/pages/workspace/hr/zenefits/ZenefitsFinalApproverPage.tsx b/src/pages/workspace/hr/zenefits/ZenefitsFinalApproverPage.tsx index b4b846d18e8b..0d90ddada070 100644 --- a/src/pages/workspace/hr/zenefits/ZenefitsFinalApproverPage.tsx +++ b/src/pages/workspace/hr/zenefits/ZenefitsFinalApproverPage.tsx @@ -25,7 +25,7 @@ function ZenefitsFinalApproverPage({ getCurrentFinalApprover: (policy) => policy?.connections?.zenefits?.config?.finalApprover ?? null, getProviderName: () => translate('workspace.hr.zenefits.title'), getHeaderTitle: () => translate('workspace.hr.finalApprover'), - handleSave: ({policyID: id, email, currentFinalApprover, connectionSyncProgress}) => updateZenefitsFinalApprover(id, email, currentFinalApprover, connectionSyncProgress), + handleSave: ({policyID: id, email, currentFinalApprover}) => updateZenefitsFinalApprover(id, email, currentFinalApprover), }; return (