diff --git a/src/CONST.ts b/src/CONST.ts index 9e3723e04c61..f085249a8254 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -5884,6 +5884,21 @@ const CONST = { // The timeout duration (1 minute) (in milliseconds) before the window reloads due to an error. ERROR_WINDOW_RELOAD_TIMEOUT: 60000, + INDICATOR_STATUS: { + HAS_USER_WALLET_ERRORS: 'hasUserWalletErrors', + HAS_PAYMENT_METHOD_ERROR: 'hasPaymentMethodError', + HAS_POLICY_ERRORS: 'hasPolicyError', + HAS_CUSTOM_UNITS_ERROR: 'hasCustomUnitsError', + HAS_EMPLOYEE_LIST_ERROR: 'hasEmployeeListError', + HAS_SYNC_ERRORS: 'hasSyncError', + HAS_SUBSCRIPTION_ERRORS: 'hasSubscriptionError', + HAS_REIMBURSEMENT_ACCOUNT_ERRORS: 'hasReimbursementAccountErrors', + HAS_LOGIN_LIST_ERROR: 'hasLoginListError', + HAS_WALLET_TERMS_ERRORS: 'hasWalletTermsErrors', + HAS_LOGIN_LIST_INFO: 'hasLoginListInfo', + HAS_SUBSCRIPTION_INFO: 'hasSubscriptionInfo', + }, + DEBUG: { DETAILS: 'details', JSON: 'json', diff --git a/src/components/Indicator.tsx b/src/components/Indicator.tsx index 4d352b6a6cde..105399936b43 100644 --- a/src/components/Indicator.tsx +++ b/src/components/Indicator.tsx @@ -1,109 +1,17 @@ import React from 'react'; import {StyleSheet, View} from 'react-native'; -import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; -import {useOnyx, withOnyx} from 'react-native-onyx'; -import useTheme from '@hooks/useTheme'; +import useIndicatorStatus from '@hooks/useIndicatorStatus'; import useThemeStyles from '@hooks/useThemeStyles'; -import {isConnectionInProgress} from '@libs/actions/connections'; -import * as PolicyUtils from '@libs/PolicyUtils'; -import * as SubscriptionUtils from '@libs/SubscriptionUtils'; -import * as UserUtils from '@libs/UserUtils'; -import * as PaymentMethods from '@userActions/PaymentMethods'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {BankAccountList, FundList, LoginList, Policy, ReimbursementAccount, UserWallet, WalletTerms} from '@src/types/onyx'; -type CheckingMethod = () => boolean; - -type IndicatorOnyxProps = { - /** All the user's policies (from Onyx via withFullPolicy) */ - policies: OnyxCollection; - - /** List of bank accounts */ - bankAccountList: OnyxEntry; - - /** List of user cards */ - fundList: OnyxEntry; - - /** The user's wallet (coming from Onyx) */ - userWallet: OnyxEntry; - - /** Bank account attached to free plan */ - reimbursementAccount: OnyxEntry; - - /** Information about the user accepting the terms for payments */ - walletTerms: OnyxEntry; - - /** Login list for the user that is signed in */ - loginList: OnyxEntry; -}; - -type IndicatorProps = IndicatorOnyxProps; - -function Indicator({reimbursementAccount, policies, bankAccountList, fundList, userWallet, walletTerms, loginList}: IndicatorOnyxProps) { - const theme = useTheme(); +function Indicator() { const styles = useThemeStyles(); - const [allConnectionSyncProgresses] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}`); - - // If a policy was just deleted from Onyx, then Onyx will pass a null value to the props, and - // those should be cleaned out before doing any error checking - const cleanPolicies = Object.fromEntries(Object.entries(policies ?? {}).filter(([, policy]) => policy?.id)); - - // All of the error & info-checking methods are put into an array. This is so that using _.some() will return - // early as soon as the first error / info condition is returned. This makes the checks very efficient since - // we only care if a single error / info condition exists anywhere. - const errorCheckingMethods: CheckingMethod[] = [ - () => Object.keys(userWallet?.errors ?? {}).length > 0, - () => PaymentMethods.hasPaymentMethodError(bankAccountList, fundList), - () => Object.values(cleanPolicies).some(PolicyUtils.hasPolicyError), - () => Object.values(cleanPolicies).some(PolicyUtils.hasCustomUnitsError), - () => Object.values(cleanPolicies).some(PolicyUtils.hasEmployeeListError), - () => - Object.values(cleanPolicies).some((cleanPolicy) => - PolicyUtils.hasSyncError( - cleanPolicy, - isConnectionInProgress(allConnectionSyncProgresses?.[`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${cleanPolicy?.id}`], cleanPolicy), - ), - ), - () => SubscriptionUtils.hasSubscriptionRedDotError(), - () => Object.keys(reimbursementAccount?.errors ?? {}).length > 0, - () => !!loginList && UserUtils.hasLoginListError(loginList), - - // Wallet term errors that are not caused by an IOU (we show the red brick indicator for those in the LHN instead) - () => Object.keys(walletTerms?.errors ?? {}).length > 0 && !walletTerms?.chatReportID, - ]; - const infoCheckingMethods: CheckingMethod[] = [() => !!loginList && UserUtils.hasLoginListInfo(loginList), () => SubscriptionUtils.hasSubscriptionGreenDotInfo()]; - const shouldShowErrorIndicator = errorCheckingMethods.some((errorCheckingMethod) => errorCheckingMethod()); - const shouldShowInfoIndicator = !shouldShowErrorIndicator && infoCheckingMethods.some((infoCheckingMethod) => infoCheckingMethod()); + const {indicatorColor, status} = useIndicatorStatus(); - const indicatorColor = shouldShowErrorIndicator ? theme.danger : theme.success; const indicatorStyles = [styles.alignItemsCenter, styles.justifyContentCenter, styles.statusIndicator(indicatorColor)]; - return (shouldShowErrorIndicator || shouldShowInfoIndicator) && ; + return !!status && ; } Indicator.displayName = 'Indicator'; -export default withOnyx({ - policies: { - key: ONYXKEYS.COLLECTION.POLICY, - }, - bankAccountList: { - key: ONYXKEYS.BANK_ACCOUNT_LIST, - }, - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, - fundList: { - key: ONYXKEYS.FUND_LIST, - }, - userWallet: { - key: ONYXKEYS.USER_WALLET, - }, - walletTerms: { - key: ONYXKEYS.WALLET_TERMS, - }, - loginList: { - key: ONYXKEYS.LOGIN_LIST, - }, -})(Indicator); +export default Indicator; diff --git a/src/hooks/useIndicatorStatus.ts b/src/hooks/useIndicatorStatus.ts new file mode 100644 index 000000000000..b026bc52fd7b --- /dev/null +++ b/src/hooks/useIndicatorStatus.ts @@ -0,0 +1,79 @@ +import {useMemo} from 'react'; +import {useOnyx} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; +import {isConnectionInProgress} from '@libs/actions/connections'; +import * as PolicyUtils from '@libs/PolicyUtils'; +import * as SubscriptionUtils from '@libs/SubscriptionUtils'; +import * as UserUtils from '@libs/UserUtils'; +import * as PaymentMethods from '@userActions/PaymentMethods'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import useTheme from './useTheme'; + +type IndicatorStatus = ValueOf; + +type IndicatorStatusResult = { + indicatorColor: string; + status: ValueOf | undefined; + policyIDWithErrors: string | undefined; +}; + +function useIndicatorStatus(): IndicatorStatusResult { + const theme = useTheme(); + const [allConnectionSyncProgresses] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS); + const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); + const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST); + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const [fundList] = useOnyx(ONYXKEYS.FUND_LIST); + const [userWallet] = useOnyx(ONYXKEYS.USER_WALLET); + const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS); + const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); + + // If a policy was just deleted from Onyx, then Onyx will pass a null value to the props, and + // those should be cleaned out before doing any error checking + const cleanPolicies = useMemo(() => Object.fromEntries(Object.entries(policies ?? {}).filter(([, policy]) => policy?.id)), [policies]); + + const policyErrors = { + [CONST.INDICATOR_STATUS.HAS_POLICY_ERRORS]: Object.values(cleanPolicies).find(PolicyUtils.hasPolicyError), + [CONST.INDICATOR_STATUS.HAS_CUSTOM_UNITS_ERROR]: Object.values(cleanPolicies).find(PolicyUtils.hasCustomUnitsError), + [CONST.INDICATOR_STATUS.HAS_EMPLOYEE_LIST_ERROR]: Object.values(cleanPolicies).find(PolicyUtils.hasEmployeeListError), + [CONST.INDICATOR_STATUS.HAS_SYNC_ERRORS]: Object.values(cleanPolicies).find((cleanPolicy) => + PolicyUtils.hasSyncError( + cleanPolicy, + isConnectionInProgress(allConnectionSyncProgresses?.[`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${cleanPolicy?.id}`], cleanPolicy), + ), + ), + }; + + // All of the error & info-checking methods are put into an array. This is so that using _.some() will return + // early as soon as the first error / info condition is returned. This makes the checks very efficient since + // we only care if a single error / info condition exists anywhere. + const errorChecking: Partial> = { + [CONST.INDICATOR_STATUS.HAS_USER_WALLET_ERRORS]: Object.keys(userWallet?.errors ?? {}).length > 0, + [CONST.INDICATOR_STATUS.HAS_PAYMENT_METHOD_ERROR]: PaymentMethods.hasPaymentMethodError(bankAccountList, fundList), + ...(Object.fromEntries(Object.entries(policyErrors).map(([error, policy]) => [error, !!policy])) as Record), + [CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_ERRORS]: SubscriptionUtils.hasSubscriptionRedDotError(), + [CONST.INDICATOR_STATUS.HAS_REIMBURSEMENT_ACCOUNT_ERRORS]: Object.keys(reimbursementAccount?.errors ?? {}).length > 0, + [CONST.INDICATOR_STATUS.HAS_LOGIN_LIST_ERROR]: !!loginList && UserUtils.hasLoginListError(loginList), + // Wallet term errors that are not caused by an IOU (we show the red brick indicator for those in the LHN instead) + [CONST.INDICATOR_STATUS.HAS_WALLET_TERMS_ERRORS]: Object.keys(walletTerms?.errors ?? {}).length > 0 && !walletTerms?.chatReportID, + }; + + const infoChecking: Partial> = { + [CONST.INDICATOR_STATUS.HAS_LOGIN_LIST_INFO]: !!loginList && UserUtils.hasLoginListInfo(loginList), + [CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_INFO]: SubscriptionUtils.hasSubscriptionGreenDotInfo(), + }; + + const [error] = Object.entries(errorChecking).find(([, value]) => value) ?? []; + const [info] = Object.entries(infoChecking).find(([, value]) => value) ?? []; + + const status = (error ?? info) as IndicatorStatus | undefined; + const policyIDWithErrors = Object.values(policyErrors).find(Boolean)?.id; + const indicatorColor = error ? theme.danger : theme.success; + + return {indicatorColor, status, policyIDWithErrors}; +} + +export default useIndicatorStatus; + +export type {IndicatorStatus}; diff --git a/src/languages/en.ts b/src/languages/en.ts index ff9daeb0d7ed..16d7a8c0b036 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -5102,6 +5102,22 @@ const translations = { hasChildReportAwaitingAction: 'Has child report awaiting action', hasMissingInvoiceBankAccount: 'Has missing invoice bank account', }, + indicatorStatus: { + theresAReportAwaitingAction: "There's a report awaiting action", + theresAReportWithErrors: "There's a report with errors", + theresAWorkspaceWithCustomUnitsErrors: "There's a workspace with custom units errors", + theresAProblemWithAWorkspaceMember: "There's a problem with a workspace member", + theresAProblemWithAContactMethod: "There's a problem with a contact method", + aContactMethodRequiresVerification: 'A contact method requires verification', + theresAProblemWithAPaymentMethod: "There's a problem with a payment method", + theresAProblemWithAWorkspace: "There's a problem with a workspace", + theresAProblemWithYourReimbursementAccount: "There's a problem with your reimbursement account", + theresABillingProblemWithYourSubscription: "There's a billing problem with your subscription", + yourSubscriptionHasBeenSuccessfullyRenewed: 'Your subscription has been successfully renewed', + theresWasAProblemDuringAWorkspaceConnectionSync: 'There was a problem during a workspace connection sync', + theresAProblemWithYourWallet: "There's a problem with your wallet", + theresAProblemWithYourWalletTerms: "There's a problem with your wallet terms", + }, }, emptySearchView: { takeATour: 'Take a tour', diff --git a/src/languages/es.ts b/src/languages/es.ts index a9d45c986238..3dd9dcf37c08 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1543,7 +1543,6 @@ const translations = { 'Has introducido incorrectamente los 4 últimos dígitos de tu tarjeta Expensify demasiadas veces. Si estás seguro de que los números son correctos, ponte en contacto con Conserjería para solucionarlo. De lo contrario, inténtalo de nuevo más tarde.', }, }, - // TODO: add translation getPhysicalCard: { header: 'Obtener tarjeta física', nameMessage: 'Introduce tu nombre y apellido como aparecerá en tu tarjeta.', @@ -5616,6 +5615,22 @@ const translations = { hasChildReportAwaitingAction: 'Informe secundario pendiente de acción', hasMissingInvoiceBankAccount: 'Falta la cuenta bancaria de la factura', }, + indicatorStatus: { + theresAReportAwaitingAction: 'Hay un informe pendiente de acción', + theresAReportWithErrors: 'Hay un informe con errores', + theresAWorkspaceWithCustomUnitsErrors: 'Hay un espacio de trabajo con errores en las unidades personalizadas', + theresAProblemWithAWorkspaceMember: 'Hay un problema con un miembro del espacio de trabajo', + theresAProblemWithAContactMethod: 'Hay un problema con un método de contacto', + aContactMethodRequiresVerification: 'Un método de contacto requiere verificación', + theresAProblemWithAPaymentMethod: 'Hay un problema con un método de pago', + theresAProblemWithAWorkspace: 'Hay un problema con un espacio de trabajo', + theresAProblemWithYourReimbursementAccount: 'Hay un problema con tu cuenta de reembolso', + theresABillingProblemWithYourSubscription: 'Hay un problema de facturación con tu suscripción', + yourSubscriptionHasBeenSuccessfullyRenewed: 'Tu suscripción se ha renovado con éxito', + theresWasAProblemDuringAWorkspaceConnectionSync: 'Hubo un problema durante la sincronización de la conexión del espacio de trabajo', + theresAProblemWithYourWallet: 'Hay un problema con tu billetera', + theresAProblemWithYourWalletTerms: 'Hay un problema con los términos de tu billetera', + }, }, emptySearchView: { takeATour: 'Haz un tour', diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx index da26d093f3ef..5a49d9cff993 100644 --- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx @@ -26,6 +26,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; +import DebugTabView from './DebugTabView'; type BottomTabBarProps = { selectedTab: string | undefined; @@ -64,12 +65,15 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const {activeWorkspaceID} = useActiveWorkspace(); - const transactionViolations = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS); + const [user] = useOnyx(ONYXKEYS.USER); + const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); + const [reportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS); + const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS); const [chatTabBrickRoad, setChatTabBrickRoad] = useState(getChatTabBrickRoad(activeWorkspaceID)); useEffect(() => { setChatTabBrickRoad(getChatTabBrickRoad(activeWorkspaceID)); - }, [activeWorkspaceID, transactionViolations]); + }, [activeWorkspaceID, transactionViolations, reports, reportActions]); const navigateToChats = useCallback(() => { if (selectedTab === SCREENS.HOME) { @@ -108,59 +112,72 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) { }, [activeWorkspaceID, selectedTab]); return ( - - - - - {chatTabBrickRoad && } - - - {translate('common.inbox')} - - - - - - - + {user?.isDebugModeEnabled && ( + + )} + + - {translate('common.search')} - - - - - + + + {chatTabBrickRoad && ( + + )} + + + {translate('common.inbox')} + + + + + + + + {translate('common.search')} + + + + + + - + ); } diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/DebugTabView.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/DebugTabView.tsx new file mode 100644 index 000000000000..3e5803b797dc --- /dev/null +++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/DebugTabView.tsx @@ -0,0 +1,172 @@ +import React, {useCallback, useMemo} from 'react'; +import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; +import Button from '@components/Button'; +import Icon from '@components/Icon'; +import * as Expensicons from '@components/Icon/Expensicons'; +import Text from '@components/Text'; +import type {IndicatorStatus} from '@hooks/useIndicatorStatus'; +import useIndicatorStatus from '@hooks/useIndicatorStatus'; +import useLocalize from '@hooks/useLocalize'; +import useStyleUtils from '@hooks/useStyleUtils'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@libs/Navigation/Navigation'; +import type {BrickRoad} from '@libs/WorkspacesSettingsUtils'; +import {getChatTabBrickRoadReport} from '@libs/WorkspacesSettingsUtils'; +import CONST from '@src/CONST'; +import type {TranslationPaths} from '@src/languages/types'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Route} from '@src/ROUTES'; +import ROUTES from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; +import type {ReimbursementAccount} from '@src/types/onyx'; + +type DebugTabViewProps = { + selectedTab?: string; + chatTabBrickRoad: BrickRoad; + activeWorkspaceID?: string; +}; + +function getSettingsMessage(status: IndicatorStatus | undefined): TranslationPaths | undefined { + switch (status) { + case CONST.INDICATOR_STATUS.HAS_CUSTOM_UNITS_ERROR: + return 'debug.indicatorStatus.theresAWorkspaceWithCustomUnitsErrors'; + case CONST.INDICATOR_STATUS.HAS_EMPLOYEE_LIST_ERROR: + return 'debug.indicatorStatus.theresAProblemWithAWorkspaceMember'; + case CONST.INDICATOR_STATUS.HAS_LOGIN_LIST_ERROR: + return 'debug.indicatorStatus.theresAProblemWithAContactMethod'; + case CONST.INDICATOR_STATUS.HAS_LOGIN_LIST_INFO: + return 'debug.indicatorStatus.aContactMethodRequiresVerification'; + case CONST.INDICATOR_STATUS.HAS_PAYMENT_METHOD_ERROR: + return 'debug.indicatorStatus.theresAProblemWithAPaymentMethod'; + case CONST.INDICATOR_STATUS.HAS_POLICY_ERRORS: + return 'debug.indicatorStatus.theresAProblemWithAWorkspace'; + case CONST.INDICATOR_STATUS.HAS_REIMBURSEMENT_ACCOUNT_ERRORS: + return 'debug.indicatorStatus.theresAProblemWithYourReimbursementAccount'; + case CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_ERRORS: + return 'debug.indicatorStatus.theresABillingProblemWithYourSubscription'; + case CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_INFO: + return 'debug.indicatorStatus.yourSubscriptionHasBeenSuccessfullyRenewed'; + case CONST.INDICATOR_STATUS.HAS_SYNC_ERRORS: + return 'debug.indicatorStatus.theresWasAProblemDuringAWorkspaceConnectionSync'; + case CONST.INDICATOR_STATUS.HAS_USER_WALLET_ERRORS: + return 'debug.indicatorStatus.theresAProblemWithYourWallet'; + case CONST.INDICATOR_STATUS.HAS_WALLET_TERMS_ERRORS: + return 'debug.indicatorStatus.theresAProblemWithYourWalletTerms'; + default: + return undefined; + } +} + +function getSettingsRoute(status: IndicatorStatus | undefined, reimbursementAccount: OnyxEntry, policyIDWithErrors = ''): Route | undefined { + switch (status) { + case CONST.INDICATOR_STATUS.HAS_CUSTOM_UNITS_ERROR: + return ROUTES.WORKSPACE_DISTANCE_RATES.getRoute(policyIDWithErrors); + case CONST.INDICATOR_STATUS.HAS_EMPLOYEE_LIST_ERROR: + return ROUTES.WORKSPACE_MEMBERS.getRoute(policyIDWithErrors); + case CONST.INDICATOR_STATUS.HAS_LOGIN_LIST_ERROR: + return ROUTES.SETTINGS_CONTACT_METHODS.route; + case CONST.INDICATOR_STATUS.HAS_LOGIN_LIST_INFO: + return ROUTES.SETTINGS_CONTACT_METHODS.route; + case CONST.INDICATOR_STATUS.HAS_PAYMENT_METHOD_ERROR: + return ROUTES.SETTINGS_WALLET; + case CONST.INDICATOR_STATUS.HAS_POLICY_ERRORS: + return ROUTES.WORKSPACE_INITIAL.getRoute(policyIDWithErrors); + case CONST.INDICATOR_STATUS.HAS_REIMBURSEMENT_ACCOUNT_ERRORS: + return ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute(reimbursementAccount?.achData?.currentStep, reimbursementAccount?.achData?.policyID); + case CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_ERRORS: + return ROUTES.SETTINGS_SUBSCRIPTION; + case CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_INFO: + return ROUTES.SETTINGS_SUBSCRIPTION; + case CONST.INDICATOR_STATUS.HAS_SYNC_ERRORS: + return ROUTES.WORKSPACE_ACCOUNTING.getRoute(policyIDWithErrors); + case CONST.INDICATOR_STATUS.HAS_USER_WALLET_ERRORS: + return ROUTES.SETTINGS_WALLET; + case CONST.INDICATOR_STATUS.HAS_WALLET_TERMS_ERRORS: + return ROUTES.SETTINGS_WALLET; + default: + return undefined; + } +} + +function DebugTabView({selectedTab = '', chatTabBrickRoad, activeWorkspaceID}: DebugTabViewProps) { + const StyleUtils = useStyleUtils(); + const theme = useTheme(); + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const {status, indicatorColor, policyIDWithErrors} = useIndicatorStatus(); + + const message = useMemo((): TranslationPaths | undefined => { + if (selectedTab === SCREENS.HOME) { + if (chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO) { + return 'debug.indicatorStatus.theresAReportAwaitingAction'; + } + if (chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR) { + return 'debug.indicatorStatus.theresAReportWithErrors'; + } + } + if (selectedTab === SCREENS.SETTINGS.ROOT) { + return getSettingsMessage(status); + } + }, [selectedTab, chatTabBrickRoad, status]); + + const indicator = useMemo(() => { + if (selectedTab === SCREENS.HOME) { + if (chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO) { + return theme.success; + } + if (chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR) { + return theme.danger; + } + } + if (selectedTab === SCREENS.SETTINGS.ROOT) { + if (status) { + return indicatorColor; + } + } + }, [selectedTab, chatTabBrickRoad, theme.success, theme.danger, status, indicatorColor]); + + const navigateTo = useCallback(() => { + if (selectedTab === SCREENS.HOME && !!chatTabBrickRoad) { + const report = getChatTabBrickRoadReport(activeWorkspaceID); + + if (report) { + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.reportID)); + } + } + if (selectedTab === SCREENS.SETTINGS.ROOT) { + const route = getSettingsRoute(status, reimbursementAccount, policyIDWithErrors); + + if (route) { + Navigation.navigate(route); + } + } + }, [selectedTab, chatTabBrickRoad, activeWorkspaceID, status, reimbursementAccount, policyIDWithErrors]); + + if (!([SCREENS.HOME, SCREENS.SETTINGS.ROOT] as string[]).includes(selectedTab) || !indicator) { + return null; + } + + return ( + + + + {message && {translate(message)}} + +