From 6cb975cded21dc1a6b16f95e1e546652d6a52244 Mon Sep 17 00:00:00 2001 From: VH Date: Fri, 1 Nov 2024 18:14:53 +0700 Subject: [PATCH 1/6] Handle error gracefully when BE returns error --- .../qbd/QuickBooksDesktopSetupPage.tsx | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx b/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx index 559cdc0c7377..4bfaa6feb484 100644 --- a/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx +++ b/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx @@ -2,6 +2,7 @@ import type {StackScreenProps} from '@react-navigation/stack'; import React, {useCallback, useEffect, useState} from 'react'; import {View} from 'react-native'; import Computer from '@assets/images/laptop-with-second-screen-sync.svg'; +import BrokenMagnifyingGlass from '@assets/images/product-illustrations/broken-magnifying-glass.svg'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import Button from '@components/Button'; import CopyTextToClipboard from '@components/CopyTextToClipboard'; @@ -18,6 +19,7 @@ import * as QuickbooksDesktop from '@libs/actions/connections/QuickbooksDesktop' import Navigation from '@libs/Navigation/Navigation'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import * as PolicyAction from '@userActions/Policy/Policy'; +import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; @@ -28,15 +30,24 @@ function RequireQuickBooksDesktopModal({route}: RequireQuickBooksDesktopModalPro const styles = useThemeStyles(); const policyID: string = route.params.policyID; const [isLoading, setIsLoading] = useState(true); + const [hasError, setHasError] = useState(false); const [codatSetupLink, setCodatSetupLink] = useState(''); const ContentWrapper = codatSetupLink ? ({children}: React.PropsWithChildren) => children : FullPageOfflineBlockingView; const fetchSetupLink = useCallback(() => { setIsLoading(true); + setHasError(false); // eslint-disable-next-line rulesdir/no-thenable-actions-in-views QuickbooksDesktop.getQuickbooksDesktopCodatSetupLink(policyID).then((response) => { - setCodatSetupLink(String(response?.setupUrl ?? '')); + if (response?.jsonCode) { + if (response.jsonCode === CONST.JSON_CODE.SUCCESS) { + setCodatSetupLink(String(response?.setupUrl ?? '')); + } else { + setHasError(true); + } + } + setIsLoading(false); }); }, [policyID]); @@ -59,6 +70,9 @@ function RequireQuickBooksDesktopModal({route}: RequireQuickBooksDesktopModalPro }, }); + const shouldShowLoading = isLoading || !codatSetupLink; + const shouldShowError = shouldShowLoading && hasError; + return ( Navigation.dismissModal()} /> - {isLoading || !codatSetupLink ? ( - - ) : ( + {shouldShowLoading && } + {shouldShowError && ( + + + + + + )} + {!shouldShowLoading && !shouldShowError && ( From 224781c7187343c2591396ffa6e3be905925ac83 Mon Sep 17 00:00:00 2001 From: VH Date: Sun, 3 Nov 2024 16:58:29 +0700 Subject: [PATCH 2/6] Implement setup error page --- src/languages/en.ts | 4 +++ src/languages/es.ts | 4 +++ .../qbd/QuickBooksDesktopSetupPage.tsx | 31 ++++++++++++++----- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index ea3d970814aa..5795a463402e 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2477,6 +2477,10 @@ const translations = { setupPage: { title: 'Open this link to connect', body: 'To complete setup, open the following link on the computer where QuickBooks Desktop is running.', + setupErrorTitle: 'Something went wrong', + setupErrorBody1: "The QuickBooks Desktop connection isn't working at the moment. Please try again later or", + setupErrorBody2: 'if the problem persists.', + setupErrorBodyContactConcierge: 'reach out to Concierge', }, importDescription: 'Choose which coding configurations to import from QuickBooks Desktop to Expensify.', classes: 'Classes', diff --git a/src/languages/es.ts b/src/languages/es.ts index 5fb656902f92..90f242113258 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2502,6 +2502,10 @@ const translations = { setupPage: { title: 'Abre este enlace para conectar', body: 'Para completar la configuración, abre el siguiente enlace en la computadora donde se está ejecutando QuickBooks Desktop.', + setupErrorTitle: '¡Ups! Ha ocurrido un error', + setupErrorBody1: 'La conexión con QuickBooks Desktop no está funcionando en este momento. Por favor, inténtalo de nuevo más tarde o', + setupErrorBody2: 'si el problema persiste.', + setupErrorBodyContactConcierge: 'contacta a Concierge', }, importDescription: 'Elige que configuraciónes de codificación son importadas desde QuickBooks Desktop a Expensify.', classes: 'Clases', diff --git a/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx b/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx index 4bfaa6feb484..3b1a62d36445 100644 --- a/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx +++ b/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx @@ -2,16 +2,19 @@ import type {StackScreenProps} from '@react-navigation/stack'; import React, {useCallback, useEffect, useState} from 'react'; import {View} from 'react-native'; import Computer from '@assets/images/laptop-with-second-screen-sync.svg'; -import BrokenMagnifyingGlass from '@assets/images/product-illustrations/broken-magnifying-glass.svg'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import Button from '@components/Button'; import CopyTextToClipboard from '@components/CopyTextToClipboard'; import FixedFooter from '@components/FixedFooter'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import Icon from '@components/Icon'; +import * as Illustrations from '@components/Icon/Illustrations'; import ImageSVG from '@components/ImageSVG'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; +import TextLink from '@components/TextLink'; +import useEnvironment from '@hooks/useEnvironment'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -28,6 +31,7 @@ type RequireQuickBooksDesktopModalProps = StackScreenProps {shouldShowLoading && } {shouldShowError && ( - - - - + + + {translate('workspace.qbd.setupPage.setupErrorTitle')} + + {translate('workspace.qbd.setupPage.setupErrorBody1')}{' '} + + {translate('workspace.qbd.setupPage.setupErrorBodyContactConcierge')} + {' '} + {translate('workspace.qbd.setupPage.setupErrorBody2')} + )} {!shouldShowLoading && !shouldShowError && ( From 57f684886f215f285cde01918979c06b6a4ed891 Mon Sep 17 00:00:00 2001 From: VH Date: Sun, 3 Nov 2024 17:42:55 +0700 Subject: [PATCH 3/6] Optimistic set connection error --- src/languages/en.ts | 2 ++ src/languages/es.ts | 2 ++ src/libs/actions/connections/index.ts | 15 +++++++++++++++ .../accounting/qbd/QuickBooksDesktopSetupPage.tsx | 4 +++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 5795a463402e..cb22551f7b51 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3659,6 +3659,8 @@ const translations = { return "Can't connect to Xero."; case CONST.POLICY.CONNECTIONS.NAME.NETSUITE: return "Can't connect to NetSuite."; + case CONST.POLICY.CONNECTIONS.NAME.QBD: + return "Can't connect to QuickBooks Desktop."; default: { return "Can't connect to integration."; } diff --git a/src/languages/es.ts b/src/languages/es.ts index 90f242113258..7af4be422eb6 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -3664,6 +3664,8 @@ const translations = { return 'No se puede conectar a Xero.'; case CONST.POLICY.CONNECTIONS.NAME.NETSUITE: return 'No se puede conectar a NetSuite.'; + case CONST.POLICY.CONNECTIONS.NAME.QBD: + return 'No se puede conectar a QuickBooks Desktop.'; default: { return 'No se ha podido conectar a la integración.'; } diff --git a/src/libs/actions/connections/index.ts b/src/libs/actions/connections/index.ts index e4ef3e4ed047..d430b4e0279d 100644 --- a/src/libs/actions/connections/index.ts +++ b/src/libs/actions/connections/index.ts @@ -327,6 +327,20 @@ function isConnectionUnverified(policy: OnyxEntry, connectionName: Polic return !(policy?.connections?.[connectionName]?.lastSync?.isConnected ?? true); } +function setConnectionError(policyID: string, connectionName: PolicyConnectionName, errorMessage?: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { + connections: { + [connectionName]: { + lastSync: { + isSuccessful: false, + errorDate: new Date().toISOString(), + errorMessage, + }, + }, + }, + }); +} + function copyExistingPolicyConnection(connectedPolicyID: string, targetPolicyID: string, connectionName: ConnectionName) { let stageInProgress; switch (connectionName) { @@ -389,4 +403,5 @@ export { isConnectionUnverified, isConnectionInProgress, hasSynchronizationErrorMessage, + setConnectionError, }; diff --git a/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx b/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx index 3b1a62d36445..e67069f4dda2 100644 --- a/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx +++ b/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx @@ -18,6 +18,7 @@ import useEnvironment from '@hooks/useEnvironment'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; +import {setConnectionError} from '@libs/actions/connections'; import * as QuickbooksDesktop from '@libs/actions/connections/QuickbooksDesktop'; import Navigation from '@libs/Navigation/Navigation'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; @@ -48,13 +49,14 @@ function RequireQuickBooksDesktopModal({route}: RequireQuickBooksDesktopModalPro if (response.jsonCode === CONST.JSON_CODE.SUCCESS) { setCodatSetupLink(String(response?.setupUrl ?? '')); } else { + setConnectionError(policyID, CONST.POLICY.CONNECTIONS.NAME.QBD, translate('workspace.qbd.setupPage.setupErrorTitle')); setHasError(true); } } setIsLoading(false); }); - }, [policyID]); + }, [policyID, translate]); useEffect(() => { // Since QBD doesn't support Taxes, we should disable them from the LHN when connecting to QBD From f8ca901e7f379dc07b70297d6e260524d7d51f80 Mon Sep 17 00:00:00 2001 From: VH Date: Mon, 4 Nov 2024 17:14:24 +0700 Subject: [PATCH 4/6] Fix auto fetch setup link when go to online even it has error --- .../accounting/qbd/QuickBooksDesktopSetupPage.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx b/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx index e67069f4dda2..899629c4723f 100644 --- a/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx +++ b/src/pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage.tsx @@ -37,8 +37,9 @@ function RequireQuickBooksDesktopModal({route}: RequireQuickBooksDesktopModalPro const [isLoading, setIsLoading] = useState(true); const [hasError, setHasError] = useState(false); const [codatSetupLink, setCodatSetupLink] = useState(''); + const hasResultOfFetchingSetupLink = !!codatSetupLink || hasError; - const ContentWrapper = codatSetupLink ? ({children}: React.PropsWithChildren) => children : FullPageOfflineBlockingView; + const ContentWrapper = hasResultOfFetchingSetupLink ? ({children}: React.PropsWithChildren) => children : FullPageOfflineBlockingView; const fetchSetupLink = useCallback(() => { setIsLoading(true); @@ -69,15 +70,15 @@ function RequireQuickBooksDesktopModal({route}: RequireQuickBooksDesktopModalPro useNetwork({ onReconnect: () => { - if (codatSetupLink) { + if (hasResultOfFetchingSetupLink) { return; } fetchSetupLink(); }, }); - const shouldShowLoading = isLoading || (!codatSetupLink && !hasError); - const shouldShowError = hasError; + const shouldShowLoading = isLoading || !hasResultOfFetchingSetupLink; + const shouldShowError = !shouldShowLoading && hasError; return ( Date: Tue, 5 Nov 2024 17:38:55 +0700 Subject: [PATCH 5/6] Update Spanish for contact concierge --- src/languages/es.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/es.ts b/src/languages/es.ts index e4de785967e7..49fb7d9a1eba 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2505,7 +2505,7 @@ const translations = { setupErrorTitle: '¡Ups! Ha ocurrido un error', setupErrorBody1: 'La conexión con QuickBooks Desktop no está funcionando en este momento. Por favor, inténtalo de nuevo más tarde o', setupErrorBody2: 'si el problema persiste.', - setupErrorBodyContactConcierge: 'contacta a Concierge', + setupErrorBodyContactConcierge: 'contacta con Concierge', }, importDescription: 'Elige que configuraciónes de codificación son importadas desde QuickBooks Desktop a Expensify.', classes: 'Clases', From 1dc585e434b6cc0edfd6547e0c24713011f784de Mon Sep 17 00:00:00 2001 From: VH Date: Wed, 6 Nov 2024 15:53:02 +0700 Subject: [PATCH 6/6] Set isConnected = false when connection error --- src/libs/actions/connections/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/actions/connections/index.ts b/src/libs/actions/connections/index.ts index d430b4e0279d..b2cb6ffffe94 100644 --- a/src/libs/actions/connections/index.ts +++ b/src/libs/actions/connections/index.ts @@ -333,6 +333,7 @@ function setConnectionError(policyID: string, connectionName: PolicyConnectionNa [connectionName]: { lastSync: { isSuccessful: false, + isConnected: false, errorDate: new Date().toISOString(), errorMessage, },