From b6836c229041f114e249e22b9241c0f4db5443a4 Mon Sep 17 00:00:00 2001
From: Nicolay Arefyeu <n.arefyev91@gmail.com>
Date: Wed, 3 Dec 2025 17:17:56 +0200
Subject: [PATCH 1/4] Fix broken connection visibility for Cards

---
 src/pages/settings/Wallet/PaymentMethodListItem.tsx          | 2 +-
 .../companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx  | 5 +----
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/src/pages/settings/Wallet/PaymentMethodListItem.tsx b/src/pages/settings/Wallet/PaymentMethodListItem.tsx
index 7beeff027b3e..d7a00d65cf6e 100644
--- a/src/pages/settings/Wallet/PaymentMethodListItem.tsx
+++ b/src/pages/settings/Wallet/PaymentMethodListItem.tsx
@@ -118,7 +118,7 @@ function PaymentMethodListItem({item, shouldShowDefaultBadge, threeDotsMenuItems
             errors={item.errors}
             errorRowStyles={styles.ph6}
             canDismissError={item.canDismissError}
-            shouldShowErrorMessages={false}
+            shouldShowErrorMessages={!!item.errors}
         >
             <MenuItem
                 onPress={handleRowPress}
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
index 9b4ede0670e1..3abeb63938af 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
@@ -23,7 +23,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import useWorkspaceAccountID from '@hooks/useWorkspaceAccountID';
 import {
     checkIfFeedConnectionIsBroken,
-    filterInactiveCards,
     flatAllCardsList,
     getBankName,
     getCardFeedIcon,
@@ -81,9 +80,8 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed, shouldS
     const currentFeedData = companyFeeds?.[selectedFeed];
     const bankName = plaidUrl && formattedFeedName ? formattedFeedName : getBankName(feed);
     const domainOrWorkspaceAccountID = getDomainOrWorkspaceAccountID(workspaceAccountID, currentFeedData);
-    const filteredFeedCards = filterInactiveCards(allFeedsCards?.[`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${domainOrWorkspaceAccountID}_${selectedFeed}`]);
     const hasFeedError = !!cardFeeds?.[selectedFeed]?.errors;
-    const isSelectedFeedConnectionBroken = checkIfFeedConnectionIsBroken(filteredFeedCards) || hasFeedError;
+    const isSelectedFeedConnectionBroken = checkIfFeedConnectionIsBroken(flatAllCardsList(allFeedsCards, domainOrWorkspaceAccountID), selectedFeed) || hasFeedError;
     const isAllowedToIssueCompanyCard = useIsAllowedToIssueCompanyCard({policyID});
     const [domain] = useOnyx(`${ONYXKEYS.COLLECTION.DOMAIN}${currentFeedData?.domainID}`, {canBeMissing: true});
 
@@ -140,7 +138,6 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed, shouldS
                     shouldChangeLayout={shouldChangeLayout}
                     feedName={formattedFeedName}
                     supportingText={supportingText}
-                    shouldShowRBR={checkIfFeedConnectionIsBroken(flatAllCardsList(allFeedsCards, domainOrWorkspaceAccountID), selectedFeed)}
                 />
                 <View style={[styles.flexRow, styles.gap2]}>
                     {!!shouldShowAssignCardButton && (

From 62edb29fa0a09fe6a2efe82ae85a952eab684335 Mon Sep 17 00:00:00 2001
From: Nicolay Arefyeu <n.arefyev91@gmail.com>
Date: Mon, 8 Dec 2025 10:50:17 +0200
Subject: [PATCH 2/4] do not show additional red for card broken connection

---
 src/libs/CardUtils.ts                           | 5 +++++
 src/pages/settings/Wallet/PaymentMethodList.tsx | 4 +++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts
index c23029b15ea4..04e0bf8be158 100644
--- a/src/libs/CardUtils.ts
+++ b/src/libs/CardUtils.ts
@@ -780,6 +780,10 @@ function getCompanyCardFeed(feedWithDomainID: string): CompanyCardFeed {
     return feed as CompanyCardFeed;
 }
 
+function isCardWithBrokenConnection(card: Card): boolean {
+    return !!card.lastScrapeResult && !CONST.COMPANY_CARDS.BROKEN_CONNECTION_IGNORED_STATUSES.includes(card.lastScrapeResult);
+}
+
 export {
     getAssignedCardSortKey,
     isExpensifyCard,
@@ -828,6 +832,7 @@ export {
     isCardPendingIssue,
     isCardPendingActivate,
     hasPendingExpensifyCardAction,
+    isCardWithBrokenConnection,
     isExpensifyCardPendingAction,
     getFundIdFromSettingsKey,
     isCardPendingReplace,
diff --git a/src/pages/settings/Wallet/PaymentMethodList.tsx b/src/pages/settings/Wallet/PaymentMethodList.tsx
index 016592c2d7b6..357bc44a19c8 100644
--- a/src/pages/settings/Wallet/PaymentMethodList.tsx
+++ b/src/pages/settings/Wallet/PaymentMethodList.tsx
@@ -22,6 +22,7 @@ import {
     getAssignedCardSortKey,
     getCardFeedIcon,
     getPlaidInstitutionIconUrl,
+    isCardWithBrokenConnection,
     isExpensifyCard,
     isExpensifyCardPendingAction,
     lastFourNumbersFromCardName,
@@ -203,6 +204,7 @@ function PaymentMethodList({
                     const pressHandler = onPress as CardPressHandler;
                     const lastFourPAN = lastFourNumbersFromCardName(card.cardName);
                     const plaidUrl = getPlaidInstitutionIconUrl(card.bank);
+                    const isCardBroken = isCardWithBrokenConnection(card);
                     assignedCardsGrouped.push({
                         key: card.cardID.toString(),
                         plaidUrl,
@@ -217,7 +219,7 @@ function PaymentMethodList({
                         errors: card.errors,
                         pendingAction: card.pendingAction,
                         brickRoadIndicator:
-                            card.fraud === CONST.EXPENSIFY_CARD.FRAUD_TYPES.DOMAIN || card.fraud === CONST.EXPENSIFY_CARD.FRAUD_TYPES.INDIVIDUAL || !!card.errors
+                            !isCardBroken && (card.fraud === CONST.EXPENSIFY_CARD.FRAUD_TYPES.DOMAIN || card.fraud === CONST.EXPENSIFY_CARD.FRAUD_TYPES.INDIVIDUAL || !!card.errors)
                                 ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR
                                 : undefined,
                         icon,

From 110e0ad0ae534183be6676286ad95c9480658457 Mon Sep 17 00:00:00 2001
From: Nicolay Arefyeu <n.arefyev91@gmail.com>
Date: Wed, 17 Dec 2025 16:09:59 +0200
Subject: [PATCH 3/4] use correct flow to identify broken connection for
 current feed

---
 .../settings/Wallet/PaymentMethodListItem.tsx | 17 ++++----
 ...WorkspaceCompanyCardsListHeaderButtons.tsx | 41 ++++++++-----------
 2 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/src/pages/settings/Wallet/PaymentMethodListItem.tsx b/src/pages/settings/Wallet/PaymentMethodListItem.tsx
index 437f01fa3fbf..dca15842fb54 100644
--- a/src/pages/settings/Wallet/PaymentMethodListItem.tsx
+++ b/src/pages/settings/Wallet/PaymentMethodListItem.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useRef} from 'react';
+import React, {useRef} from 'react';
 import type {GestureResponderEvent, StyleProp, ViewStyle} from 'react-native';
 import {View} from 'react-native';
 import type {ValueOf} from 'type-fest';
@@ -101,15 +101,12 @@ function PaymentMethodListItem({item, shouldShowDefaultBadge, threeDotsMenuItems
         }
     };
 
-    const getBadgeText = useCallback(
-        (listItem: PaymentMethodItem) => {
-            if (isAccountInSetupState(listItem)) {
-                return translate('common.actionRequired');
-            }
-            return shouldShowDefaultBadge ? translate('paymentMethodList.defaultPaymentMethod') : undefined;
-        },
-        [shouldShowDefaultBadge, translate],
-    );
+    const getBadgeText = (listItem: PaymentMethodItem) => {
+        if (isAccountInSetupState(listItem)) {
+            return translate('common.actionRequired');
+        }
+        return shouldShowDefaultBadge ? translate('paymentMethodList.defaultPaymentMethod') : undefined;
+    };
 
     return (
         <OfflineWithFeedback
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
index 5202d1acaa6b..7bc09ed24890 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
@@ -1,5 +1,5 @@
 import {Str} from 'expensify-common';
-import React, {useMemo} from 'react';
+import React from 'react';
 import {View} from 'react-native';
 import Button from '@components/Button';
 import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
@@ -11,6 +11,7 @@ import RenderHTML from '@components/RenderHTML';
 import Text from '@components/Text';
 import type {CompanyCardFeedWithDomainID} from '@hooks/useCardFeeds';
 import useCardFeeds from '@hooks/useCardFeeds';
+import useCardsList from '@hooks/useCardsList';
 import {useCompanyCardFeedIcons} from '@hooks/useCompanyCardIcons';
 import useIsAllowedToIssueCompanyCard from '@hooks/useIsAllowedToIssueCompanyCard';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
@@ -21,16 +22,13 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useTheme from '@hooks/useTheme';
 import useThemeIllustrations from '@hooks/useThemeIllustrations';
 import useThemeStyles from '@hooks/useThemeStyles';
-import useWorkspaceAccountID from '@hooks/useWorkspaceAccountID';
 import {
     checkIfFeedConnectionIsBroken,
-    flatAllCardsList,
     getBankName,
     getCardFeedIcon,
     getCompanyCardFeed,
     getCompanyFeeds,
     getCustomOrFormattedFeedName,
-    getDomainOrWorkspaceAccountID,
     getPlaidCountry,
     getPlaidInstitutionIconUrl,
     getPlaidInstitutionId,
@@ -67,10 +65,8 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed, shouldS
     const illustrations = useThemeIllustrations();
     const companyCardFeedIcons = useCompanyCardFeedIcons();
     const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
-    const workspaceAccountID = useWorkspaceAccountID(policyID);
     const [cardFeeds] = useCardFeeds(policyID);
     const policy = usePolicy(policyID);
-    const [allFeedsCards] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}`, {canBeMissing: false});
     const [currencyList = getEmptyObject<CurrencyList>()] = useOnyx(ONYXKEYS.CURRENCY_LIST, {canBeMissing: true});
     const [countryByIp] = useOnyx(ONYXKEYS.COUNTRY, {canBeMissing: false});
     const shouldChangeLayout = isMediumScreenWidth || shouldUseNarrowLayout;
@@ -81,9 +77,9 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed, shouldS
     const companyFeeds = getCompanyFeeds(cardFeeds);
     const currentFeedData = companyFeeds?.[selectedFeed];
     const bankName = plaidUrl && formattedFeedName ? formattedFeedName : getBankName(feed);
-    const domainOrWorkspaceAccountID = getDomainOrWorkspaceAccountID(workspaceAccountID, currentFeedData);
-    const hasFeedError = !!cardFeeds?.[selectedFeed]?.errors;
-    const isSelectedFeedConnectionBroken = checkIfFeedConnectionIsBroken(flatAllCardsList(allFeedsCards, domainOrWorkspaceAccountID), selectedFeed) || hasFeedError;
+    const [cardsList] = useCardsList(selectedFeed);
+    const {cardList, ...cards} = cardsList ?? {};
+    const isSelectedFeedConnectionBroken = checkIfFeedConnectionIsBroken(cards);
     const isAllowedToIssueCompanyCard = useIsAllowedToIssueCompanyCard({policyID});
     const [domain] = useOnyx(`${ONYXKEYS.COLLECTION.DOMAIN}${currentFeedData?.domainID}`, {canBeMissing: true});
 
@@ -111,24 +107,23 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed, shouldS
         Navigation.setNavigationActionToMicrotaskQueue(() => Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed)));
     };
 
-    const secondaryActions = useMemo(
-        () => [
-            {
-                icon: icons.Gear,
-                text: translate('common.settings'),
-                onSelected: () => Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_SETTINGS.getRoute(policyID)),
-                value: CONST.POLICY.SECONDARY_ACTIONS.SETTINGS,
-            },
-        ],
-        [policyID, icons.Gear, translate],
-    );
-
-    const supportingText = useMemo(() => {
+    const getSecondaryActions = () => [
+        {
+            icon: icons.Gear,
+            text: translate('common.settings'),
+            onSelected: () => Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_SETTINGS.getRoute(policyID)),
+            value: CONST.POLICY.SECONDARY_ACTIONS.SETTINGS,
+        },
+    ];
+    const getSupportingText = () => {
         const firstPart = translate(isCommercialFeed ? 'workspace.companyCards.commercialFeed' : 'workspace.companyCards.directFeed');
         const domainName = domain?.email ? Str.extractEmailDomain(domain.email) : undefined;
         const secondPart = ` (${domainName ?? policy?.name})`;
         return `${firstPart}${secondPart}`;
-    }, [domain?.email, isCommercialFeed, policy?.name, translate]);
+    };
+
+    const secondaryActions = getSecondaryActions();
+    const supportingText = getSupportingText();
 
     return (
         <View>

From f476612e426b26446cc1963fbc4f87a738ca7141 Mon Sep 17 00:00:00 2001
From: Nicolay Arefyeu <n.arefyev91@gmail.com>
Date: Thu, 18 Dec 2025 12:15:52 +0200
Subject: [PATCH 4/4] show correctly dot if any feed is broken

---
 src/components/FeedSelector.tsx                          | 4 +++-
 .../WorkspaceCompanyCardsListHeaderButtons.tsx           | 9 +++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/components/FeedSelector.tsx b/src/components/FeedSelector.tsx
index 7fa78bcbe262..a4f36cf9f374 100644
--- a/src/components/FeedSelector.tsx
+++ b/src/components/FeedSelector.tsx
@@ -1,5 +1,6 @@
 import React from 'react';
 import {View} from 'react-native';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import variables from '@styles/variables';
@@ -37,6 +38,7 @@ type Props = {
 function FeedSelector({onFeedSelect, cardIcon, shouldChangeLayout, feedName, supportingText, shouldShowRBR = false, plaidUrl = null}: Props) {
     const styles = useThemeStyles();
     const theme = useTheme();
+    const {shouldUseNarrowLayout} = useResponsiveLayout();
 
     return (
         <PressableWithFeedback
@@ -57,7 +59,7 @@ function FeedSelector({onFeedSelect, cardIcon, shouldChangeLayout, feedName, sup
             )}
             <View style={styles.flex1}>
                 <View style={[styles.flexRow, styles.gap1, styles.alignItemsCenter]}>
-                    <CaretWrapper style={styles.flex1}>
+                    <CaretWrapper style={[shouldUseNarrowLayout && styles.flex1]}>
                         <Text
                             numberOfLines={1}
                             style={[styles.textStrong, styles.flexShrink1]}
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
index 7bc09ed24890..f711f1c35b4f 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
@@ -22,13 +22,16 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useTheme from '@hooks/useTheme';
 import useThemeIllustrations from '@hooks/useThemeIllustrations';
 import useThemeStyles from '@hooks/useThemeStyles';
+import useWorkspaceAccountID from '@hooks/useWorkspaceAccountID';
 import {
     checkIfFeedConnectionIsBroken,
+    flatAllCardsList,
     getBankName,
     getCardFeedIcon,
     getCompanyCardFeed,
     getCompanyFeeds,
     getCustomOrFormattedFeedName,
+    getDomainOrWorkspaceAccountID,
     getPlaidCountry,
     getPlaidInstitutionIconUrl,
     getPlaidInstitutionId,
@@ -65,8 +68,10 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed, shouldS
     const illustrations = useThemeIllustrations();
     const companyCardFeedIcons = useCompanyCardFeedIcons();
     const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
+    const workspaceAccountID = useWorkspaceAccountID(policyID);
     const [cardFeeds] = useCardFeeds(policyID);
     const policy = usePolicy(policyID);
+    const [allFeedsCards] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}`, {canBeMissing: false});
     const [currencyList = getEmptyObject<CurrencyList>()] = useOnyx(ONYXKEYS.CURRENCY_LIST, {canBeMissing: true});
     const [countryByIp] = useOnyx(ONYXKEYS.COUNTRY, {canBeMissing: false});
     const shouldChangeLayout = isMediumScreenWidth || shouldUseNarrowLayout;
@@ -77,6 +82,9 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed, shouldS
     const companyFeeds = getCompanyFeeds(cardFeeds);
     const currentFeedData = companyFeeds?.[selectedFeed];
     const bankName = plaidUrl && formattedFeedName ? formattedFeedName : getBankName(feed);
+    const domainOrWorkspaceAccountID = getDomainOrWorkspaceAccountID(workspaceAccountID, currentFeedData);
+    const hasFeedError = !!cardFeeds?.[selectedFeed]?.errors;
+    const hasAnyFeedConnectionBroken = checkIfFeedConnectionIsBroken(flatAllCardsList(allFeedsCards, domainOrWorkspaceAccountID), selectedFeed) || hasFeedError;
     const [cardsList] = useCardsList(selectedFeed);
     const {cardList, ...cards} = cardsList ?? {};
     const isSelectedFeedConnectionBroken = checkIfFeedConnectionIsBroken(cards);
@@ -135,6 +143,7 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed, shouldS
                     shouldChangeLayout={shouldChangeLayout}
                     feedName={formattedFeedName}
                     supportingText={supportingText}
+                    shouldShowRBR={hasAnyFeedConnectionBroken}
                 />
                 <View style={[styles.flexRow, styles.gap2]}>
                     {!!shouldShowAssignCardButton && (
