From 0b6e8a84dd98325b768e770e987d68c09508f3ea Mon Sep 17 00:00:00 2001
From: Huu Le <20178761+huult@users.noreply.github.com>
Date: Thu, 16 Jan 2025 10:24:51 +0700
Subject: [PATCH 1/9] handle offline mode for bank connection
---
.../addNew/BankConnection/index.tsx | 29 +++++++++++--------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx b/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx
index e7e71d1c3785..da41d2cbe789 100644
--- a/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx
+++ b/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx
@@ -2,12 +2,14 @@ import React, {useCallback, useEffect, useMemo} from 'react';
import {useOnyx} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import BlockingView from '@components/BlockingViews/BlockingView';
+import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Illustrations from '@components/Icon/Illustrations';
import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
+import useNetwork from '@hooks/useNetwork';
import usePrevious from '@hooks/usePrevious';
import useThemeStyles from '@hooks/useThemeStyles';
import * as CardUtils from '@libs/CardUtils';
@@ -36,6 +38,7 @@ function BankConnection({policyID}: BankConnectionStepProps) {
const [cardFeeds] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`);
const prevFeedsData = usePrevious(cardFeeds?.settings?.oAuthAccountDetails);
const {isNewFeedConnected, newFeed} = useMemo(() => CardUtils.checkIfNewFeedConnected(prevFeedsData ?? {}, cardFeeds?.settings?.oAuthAccountDetails ?? {}), [cardFeeds, prevFeedsData]);
+ const {isOffline} = useNetwork();
const url = getCompanyCardBankConnection(policyID, bankName);
@@ -67,7 +70,7 @@ function BankConnection({policyID}: BankConnectionStepProps) {
);
useEffect(() => {
- if (!url) {
+ if (!url || isOffline) {
return;
}
if (isNewFeedConnected) {
@@ -79,7 +82,7 @@ function BankConnection({policyID}: BankConnectionStepProps) {
return;
}
customWindow = openBankConnection(url);
- }, [isNewFeedConnected, newFeed, policyID, url]);
+ }, [isNewFeedConnected, isOffline, newFeed, policyID, url]);
return (
@@ -87,16 +90,18 @@ function BankConnection({policyID}: BankConnectionStepProps) {
title={translate('workspace.companyCards.addCards')}
onBackButtonPress={handleBackButtonPress}
/>
-
+
+
+
);
}
From 9cfd06bdca4c6a97d2bb84518cba667b43b3879d Mon Sep 17 00:00:00 2001
From: Huu Le <20178761+huult@users.noreply.github.com>
Date: Thu, 16 Jan 2025 10:54:03 +0700
Subject: [PATCH 2/9] fix eslint
---
.../addNew/BankConnection/index.tsx | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx b/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx
index da41d2cbe789..009533bc8e79 100644
--- a/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx
+++ b/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx
@@ -12,11 +12,11 @@ import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import usePrevious from '@hooks/usePrevious';
import useThemeStyles from '@hooks/useThemeStyles';
-import * as CardUtils from '@libs/CardUtils';
+import {checkIfNewFeedConnected} from '@libs/CardUtils';
import Navigation from '@libs/Navigation/Navigation';
-import * as PolicyUtils from '@libs/PolicyUtils';
-import * as Card from '@userActions/Card';
-import * as CompanyCards from '@userActions/CompanyCards';
+import {getWorkspaceAccountID} from '@libs/PolicyUtils';
+import {updateSelectedFeed} from '@userActions/Card';
+import {setAddNewCompanyCardStepAndData} from '@userActions/CompanyCards';
import getCompanyCardBankConnection from '@userActions/getCompanyCardBankConnection';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -34,10 +34,10 @@ function BankConnection({policyID}: BankConnectionStepProps) {
const {translate} = useLocalize();
const [addNewCard] = useOnyx(ONYXKEYS.ADD_NEW_COMPANY_CARD);
const bankName: ValueOf | undefined = addNewCard?.data?.selectedBank;
- const workspaceAccountID = PolicyUtils.getWorkspaceAccountID(policyID);
+ const workspaceAccountID = getWorkspaceAccountID(policyID);
const [cardFeeds] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`);
const prevFeedsData = usePrevious(cardFeeds?.settings?.oAuthAccountDetails);
- const {isNewFeedConnected, newFeed} = useMemo(() => CardUtils.checkIfNewFeedConnected(prevFeedsData ?? {}, cardFeeds?.settings?.oAuthAccountDetails ?? {}), [cardFeeds, prevFeedsData]);
+ const {isNewFeedConnected, newFeed} = useMemo(() => checkIfNewFeedConnected(prevFeedsData ?? {}, cardFeeds?.settings?.oAuthAccountDetails ?? {}), [cardFeeds, prevFeedsData]);
const {isOffline} = useNetwork();
const url = getCompanyCardBankConnection(policyID, bankName);
@@ -52,14 +52,14 @@ function BankConnection({policyID}: BankConnectionStepProps) {
const handleBackButtonPress = () => {
customWindow?.close();
if (bankName === CONST.COMPANY_CARDS.BANKS.BREX) {
- CompanyCards.setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.SELECT_BANK});
+ setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.SELECT_BANK});
return;
}
if (bankName === CONST.COMPANY_CARDS.BANKS.AMEX) {
- CompanyCards.setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.AMEX_CUSTOM_FEED});
+ setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.AMEX_CUSTOM_FEED});
return;
}
- CompanyCards.setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.SELECT_FEED_TYPE});
+ setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.SELECT_FEED_TYPE});
};
const CustomSubtitle = (
@@ -76,7 +76,7 @@ function BankConnection({policyID}: BankConnectionStepProps) {
if (isNewFeedConnected) {
customWindow?.close();
if (newFeed) {
- Card.updateSelectedFeed(newFeed, policyID);
+ updateSelectedFeed(newFeed, policyID);
}
Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(policyID));
return;
From 86490d86a1283e1a3475009337c34865ce839511 Mon Sep 17 00:00:00 2001
From: Huu Le <20178761+huult@users.noreply.github.com>
Date: Mon, 20 Jan 2025 22:46:16 +0700
Subject: [PATCH 3/9] Disable assign card button when offline
---
.../companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx
index 590aa2e78459..1cba02f22277 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx
@@ -4,6 +4,7 @@ import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import CardRowSkeleton from '@components/Skeletons/CardRowSkeleton';
import useLocalize from '@hooks/useLocalize';
+import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import colors from '@styles/theme/colors';
import CONST from '@src/CONST';
@@ -19,6 +20,7 @@ type WorkspaceCompanyCardsFeedAddedEmptyPageProps = {
function WorkspaceCompanyCardsFeedAddedEmptyPage({handleAssignCard, isDisabledAssignCardButton}: WorkspaceCompanyCardsFeedAddedEmptyPageProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
+ const {isOffline} = useNetwork();
return (
From f115b9b7dbe526158c7e8d50529cfed5a73202f5 Mon Sep 17 00:00:00 2001
From: Huu Le <20178761+huult@users.noreply.github.com>
Date: Mon, 20 Jan 2025 22:56:00 +0700
Subject: [PATCH 4/9] Update dependencies
---
.../workspace/companyCards/addNew/BankConnection/index.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx b/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx
index ee05a373fdcc..e59477a96bf8 100644
--- a/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx
+++ b/src/pages/workspace/companyCards/addNew/BankConnection/index.tsx
@@ -86,7 +86,7 @@ function BankConnection({policyID}: BankConnectionStepProps) {
if (!shouldBlockWindowOpen) {
customWindow = openBankConnection(url);
}
- }, [isNewFeedConnected, shouldBlockWindowOpen, newFeed, policyID, url]);
+ }, [isNewFeedConnected, shouldBlockWindowOpen, newFeed, policyID, url, isOffline]);
return (
From 7ce7b8398fb90823fbd93c7f40624685d4d2fc2a Mon Sep 17 00:00:00 2001
From: Huu Le <20178761+huult@users.noreply.github.com>
Date: Wed, 22 Jan 2025 13:37:18 +0700
Subject: [PATCH 5/9] Update condition to disable button
---
.../companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx
index 1cba02f22277..9fedc7905fe3 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx
@@ -38,7 +38,7 @@ function WorkspaceCompanyCardsFeedAddedEmptyPage({handleAssignCard, isDisabledAs
buttonAction: handleAssignCard,
icon: Expensicons.Plus,
success: true,
- isDisabled: isDisabledAssignCardButton ?? isOffline,
+ isDisabled: isOffline || isDisabledAssignCardButton,
},
]}
/>
From da198cc77298c1ef9ebe3749a24c3c63a8671eaa Mon Sep 17 00:00:00 2001
From: Huu Le <20178761+huult@users.noreply.github.com>
Date: Tue, 4 Feb 2025 00:11:02 +0700
Subject: [PATCH 6/9] add offline alert modal for direct feed
---
...orkspaceCompanyCardsFeedAddedEmptyPage.tsx | 4 +---
.../WorkspaceCompanyCardsPage.tsx | 23 ++++++++++++++++++-
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx
index 9fedc7905fe3..590aa2e78459 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx
@@ -4,7 +4,6 @@ import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import CardRowSkeleton from '@components/Skeletons/CardRowSkeleton';
import useLocalize from '@hooks/useLocalize';
-import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import colors from '@styles/theme/colors';
import CONST from '@src/CONST';
@@ -20,7 +19,6 @@ type WorkspaceCompanyCardsFeedAddedEmptyPageProps = {
function WorkspaceCompanyCardsFeedAddedEmptyPage({handleAssignCard, isDisabledAssignCardButton}: WorkspaceCompanyCardsFeedAddedEmptyPageProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
- const {isOffline} = useNetwork();
return (
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
index 5fef9d0dba38..372a6b4c64d8 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
@@ -2,13 +2,14 @@ import {useFocusEffect} from '@react-navigation/native';
import React, {useCallback, useEffect, useState} from 'react';
import {ActivityIndicator} from 'react-native';
import {useOnyx} from 'react-native-onyx';
+import ConfirmModal from '@components/ConfirmModal';
import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
import * as Illustrations from '@components/Icon/Illustrations';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
-import {checkIfFeedConnectionIsBroken, getCompanyFeeds, getFilteredCardList, getSelectedFeed, hasOnlyOneCardToAssign, isSelectedFeedExpired} from '@libs/CardUtils';
+import {checkIfFeedConnectionIsBroken, getCompanyFeeds, getFilteredCardList, getSelectedFeed, hasOnlyOneCardToAssign, isCustomFeed, isSelectedFeedExpired} from '@libs/CardUtils';
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import type {FullScreenNavigatorParamList} from '@libs/Navigation/types';
@@ -56,6 +57,7 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
const isFeedAdded = !isPending && !isNoFeed;
const isFeedExpired = isSelectedFeedExpired(selectedFeed ? cardFeeds?.settings?.oAuthAccountDetails?.[selectedFeed] : undefined);
const isFeedConnectionBroken = checkIfFeedConnectionIsBroken(cards);
+ const [shouldShowOfflineModal, setShouldShowOfflineModal] = useState(false);
const fetchCompanyCards = useCallback(() => {
openPolicyCompanyCardsPage(policyID, workspaceAccountID);
@@ -82,6 +84,16 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
if (!selectedFeed) {
return;
}
+
+ const isCommercialFeed = isCustomFeed(selectedFeed);
+
+ // If the feed is a direct feed (not a commercial feed) and the user is offline,
+ // show the offline alert modal to inform them of the connectivity issue.
+ if (!isCommercialFeed && isOffline) {
+ setShouldShowOfflineModal(true);
+ return;
+ }
+
const data: Partial = {
bankName: selectedFeed,
};
@@ -159,6 +171,15 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
onClose={() => setIsNoDelegateAccessMenuVisible(false)}
/>
+ setShouldShowOfflineModal(false)}
+ onCancel={() => setShouldShowOfflineModal(false)}
+ confirmText={translate('common.buttonConfirm')}
+ prompt={translate('common.offlinePrompt')}
+ shouldShowCancelButton={false}
+ />
);
}
From fb84a5054fa859d758bafcf9e84eacf6011bdc92 Mon Sep 17 00:00:00 2001
From: Huu Le <20178761+huult@users.noreply.github.com>
Date: Tue, 4 Feb 2025 11:16:30 +0700
Subject: [PATCH 7/9] Update download button and remove unused actions
---
src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
index 372a6b4c64d8..6e439027642f 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
@@ -175,10 +175,10 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
title={translate('common.youAppearToBeOffline')}
isVisible={shouldShowOfflineModal}
onConfirm={() => setShouldShowOfflineModal(false)}
- onCancel={() => setShouldShowOfflineModal(false)}
confirmText={translate('common.buttonConfirm')}
prompt={translate('common.offlinePrompt')}
shouldShowCancelButton={false}
+ success={false}
/>
);
From adf01fb8e2a23699cb773df95b31128d0785daaa Mon Sep 17 00:00:00 2001
From: Huu Le <20178761+huult@users.noreply.github.com>
Date: Tue, 4 Feb 2025 12:27:39 +0700
Subject: [PATCH 8/9] change to DecisionModal
---
.../companyCards/WorkspaceCompanyCardsPage.tsx | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
index 6e439027642f..fdba1ca5481b 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
@@ -2,11 +2,12 @@ import {useFocusEffect} from '@react-navigation/native';
import React, {useCallback, useEffect, useState} from 'react';
import {ActivityIndicator} from 'react-native';
import {useOnyx} from 'react-native-onyx';
-import ConfirmModal from '@components/ConfirmModal';
+import DecisionModal from '@components/DecisionModal';
import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
import * as Illustrations from '@components/Icon/Illustrations';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {checkIfFeedConnectionIsBroken, getCompanyFeeds, getFilteredCardList, getSelectedFeed, hasOnlyOneCardToAssign, isCustomFeed, isSelectedFeedExpired} from '@libs/CardUtils';
@@ -58,7 +59,7 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
const isFeedExpired = isSelectedFeedExpired(selectedFeed ? cardFeeds?.settings?.oAuthAccountDetails?.[selectedFeed] : undefined);
const isFeedConnectionBroken = checkIfFeedConnectionIsBroken(cards);
const [shouldShowOfflineModal, setShouldShowOfflineModal] = useState(false);
-
+ const {isSmallScreenWidth} = useResponsiveLayout();
const fetchCompanyCards = useCallback(() => {
openPolicyCompanyCardsPage(policyID, workspaceAccountID);
}, [policyID, workspaceAccountID]);
@@ -171,14 +172,15 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
onClose={() => setIsNoDelegateAccessMenuVisible(false)}
/>
- setShouldShowOfflineModal(false)}
- confirmText={translate('common.buttonConfirm')}
prompt={translate('common.offlinePrompt')}
- shouldShowCancelButton={false}
- success={false}
+ isSmallScreenWidth={isSmallScreenWidth}
+ onSecondOptionSubmit={() => setShouldShowOfflineModal(false)}
+ secondOptionText={translate('common.buttonConfirm')}
+ isVisible={shouldShowOfflineModal}
+ onClose={() => setShouldShowOfflineModal(false)}
/>
);
From 82aafc132074b515d89c7ac117f89bca9219e31e Mon Sep 17 00:00:00 2001
From: Huu Le <20178761+huult@users.noreply.github.com>
Date: Tue, 4 Feb 2025 12:31:03 +0700
Subject: [PATCH 9/9] fix lint
---
.../workspace/companyCards/WorkspaceCompanyCardsPage.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
index fdba1ca5481b..6450bd058565 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
@@ -59,7 +59,7 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
const isFeedExpired = isSelectedFeedExpired(selectedFeed ? cardFeeds?.settings?.oAuthAccountDetails?.[selectedFeed] : undefined);
const isFeedConnectionBroken = checkIfFeedConnectionIsBroken(cards);
const [shouldShowOfflineModal, setShouldShowOfflineModal] = useState(false);
- const {isSmallScreenWidth} = useResponsiveLayout();
+ const {shouldUseNarrowLayout} = useResponsiveLayout();
const fetchCompanyCards = useCallback(() => {
openPolicyCompanyCardsPage(policyID, workspaceAccountID);
}, [policyID, workspaceAccountID]);
@@ -176,7 +176,7 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
setShouldShowOfflineModal(false)}
secondOptionText={translate('common.buttonConfirm')}
isVisible={shouldShowOfflineModal}