From 2a6efbe4eafaecfbdf582cf13438a90f1ce5367c Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Tue, 16 Dec 2025 12:45:51 -0500 Subject: [PATCH 01/15] import isLoadingOnyxValue and cardListMetada --- src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index b07564cea2eeb..839a4642bcca3 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -21,6 +21,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import WorkspaceCompanyCardPageEmptyState from './WorkspaceCompanyCardPageEmptyState'; import WorkspaceCompanyCardsFeedPendingPage from './WorkspaceCompanyCardsFeedPendingPage'; import WorkspaceCompanyCardsList from './WorkspaceCompanyCardsList'; @@ -43,7 +44,7 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { const [cardFeeds, , defaultFeed] = useCardFeeds(policyID); const selectedFeed = getSelectedFeed(lastSelectedFeed, cardFeeds); const feed = selectedFeed ? getCompanyCardFeed(selectedFeed) : undefined; - const [cardsList] = useCardsList(selectedFeed); + const [cardsList, cardsListMetadata] = useCardsList(selectedFeed); const [countryByIp] = useOnyx(ONYXKEYS.COUNTRY, {canBeMissing: false}); const hasNoAssignedCard = Object.keys(cardsList ?? {}).length === 0; From 92bd4cb898f2aaa6ea0472cc8bfaf9abf37cc22b Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Tue, 16 Dec 2025 14:59:45 -0500 Subject: [PATCH 02/15] check card feeds --- 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 839a4642bcca3..b0293fe79ffa4 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -60,7 +60,7 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { }, [policyID, domainOrWorkspaceAccountID]); const {isOffline} = useNetwork({onReconnect: fetchCompanyCards}); - const isLoading = !isOffline && (!cardFeeds || (!!defaultFeed?.isLoading && isEmptyObject(cardsList))); + const isLoading = !isOffline && !cardFeeds; const isGB = countryByIp === CONST.COUNTRY.GB; const shouldShowGBDisclaimer = isGB && isBetaEnabled(CONST.BETAS.PLAID_COMPANY_CARDS) && (isNoFeed || hasNoAssignedCard); From f85990b271941371ce46912521f69576f514e270 Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Tue, 16 Dec 2025 15:13:07 -0500 Subject: [PATCH 03/15] add isloadingCardsList --- .../workspace/companyCards/WorkspaceCompanyCardsList.tsx | 5 ++++- .../workspace/companyCards/WorkspaceCompanyCardsPage.tsx | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index f97c9f04d5e8e..2e703390a84a8 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -49,9 +49,12 @@ type WorkspaceCompanyCardsListProps = { /** Whether to show GB disclaimer */ shouldShowGBDisclaimer?: boolean; + + /** Whether the cards list is loading */ + isLoadingCardsList?: boolean; }; -function WorkspaceCompanyCardsList({selectedFeed, cardsList, policyID, onAssignCard, isAssigningCardDisabled, shouldShowGBDisclaimer}: WorkspaceCompanyCardsListProps) { +function WorkspaceCompanyCardsList({selectedFeed, cardsList, policyID, onAssignCard, isAssigningCardDisabled, shouldShowGBDisclaimer, isLoadingCardsList = false}: WorkspaceCompanyCardsListProps) { const styles = useThemeStyles(); const {translate, localeCompare} = useLocalize(); const listRef = useRef>(null); diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index b0293fe79ffa4..faf177a18d12d 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -61,6 +61,7 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { const {isOffline} = useNetwork({onReconnect: fetchCompanyCards}); const isLoading = !isOffline && !cardFeeds; + const isLoadingCardsList = (!isOffline && isLoadingOnyxValue(cardsListMetadata)) || testLoadingDelay; const isGB = countryByIp === CONST.COUNTRY.GB; const shouldShowGBDisclaimer = isGB && isBetaEnabled(CONST.BETAS.PLAID_COMPANY_CARDS) && (isNoFeed || hasNoAssignedCard); @@ -120,6 +121,7 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { policyID={policyID} onAssignCard={assignCard} isAssigningCardDisabled={isAssigningCardDisabled} + isLoadingCardsList={isLoadingCardsList} /> )} From c254b6bebf1c602136d00ee6cf6ca259016946be Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Tue, 16 Dec 2025 15:15:36 -0500 Subject: [PATCH 04/15] import skeleton elements --- src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index 2e703390a84a8..baf23a1440cb5 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -7,6 +7,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import {PressableWithFeedback} from '@components/Pressable'; import SearchBar from '@components/SearchBar'; import Text from '@components/Text'; +import TableRowSkeleton from '@components/Skeletons/TableRowSkeleton'; import useCardFeeds from '@hooks/useCardFeeds'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -14,6 +15,7 @@ import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSearchResults from '@hooks/useSearchResults'; import useThemeStyles from '@hooks/useThemeStyles'; +import useNetwork from '@hooks/useNetwork'; import { filterCardsByPersonalDetails, getCardsByCardholderName, @@ -56,6 +58,7 @@ type WorkspaceCompanyCardsListProps = { function WorkspaceCompanyCardsList({selectedFeed, cardsList, policyID, onAssignCard, isAssigningCardDisabled, shouldShowGBDisclaimer, isLoadingCardsList = false}: WorkspaceCompanyCardsListProps) { const styles = useThemeStyles(); + const {isOffline} = useNetwork(); const {translate, localeCompare} = useLocalize(); const listRef = useRef>(null); const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout(); From fafdcb4f32e7e22cd03eced17b8826803b439df1 Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Tue, 16 Dec 2025 15:18:37 -0500 Subject: [PATCH 05/15] implement skeleton when loading --- .../workspace/companyCards/WorkspaceCompanyCardsList.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index baf23a1440cb5..63a0131526785 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -215,8 +215,8 @@ function WorkspaceCompanyCardsList({selectedFeed, cardsList, policyID, onAssignC ); - // Show empty state when there are no cards - if (!cards?.length) { + // Show empty state when there are no cards (but not when loading) + if (!cards?.length && !isLoadingCardsList) { return ( : undefined} showsVerticalScrollIndicator={false} keyboardShouldPersistTaps="handled" contentContainerStyle={styles.flexGrow1} From 2562d109b18b06b4e68601ad5aa126db0539a80a Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Tue, 16 Dec 2025 16:28:47 -0500 Subject: [PATCH 06/15] polish skeleton loading --- .../companyCards/WorkspaceCompanyCardsList.tsx | 11 +++++++---- .../companyCards/WorkspaceCompanyCardsPage.tsx | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index 63a0131526785..50aacc681319c 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -15,6 +15,7 @@ import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSearchResults from '@hooks/useSearchResults'; import useThemeStyles from '@hooks/useThemeStyles'; +import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import useNetwork from '@hooks/useNetwork'; import { filterCardsByPersonalDetails, @@ -63,7 +64,9 @@ function WorkspaceCompanyCardsList({selectedFeed, cardsList, policyID, onAssignC const listRef = useRef>(null); const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout(); - const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); + const [personalDetails, personalDetailsMetadata] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); + const isLoadingPersonalDetails = !isOffline && isLoadingOnyxValue(personalDetailsMetadata); + const isLoadingCardsTableData = isLoadingCardsList || isLoadingPersonalDetails; const [customCardNames] = useOnyx(ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES, {canBeMissing: true}); const policy = usePolicy(policyID); @@ -216,7 +219,7 @@ function WorkspaceCompanyCardsList({selectedFeed, cardsList, policyID, onAssignC ); // Show empty state when there are no cards (but not when loading) - if (!cards?.length && !isLoadingCardsList) { + if (!cards?.length && !isLoadingCardsTableData) { return ( : undefined} + ListEmptyComponent={!isOffline && isLoadingCardsTableData ? : undefined} showsVerticalScrollIndicator={false} keyboardShouldPersistTaps="handled" contentContainerStyle={styles.flexGrow1} diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index faf177a18d12d..0dca766b7cba2 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -61,7 +61,7 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { const {isOffline} = useNetwork({onReconnect: fetchCompanyCards}); const isLoading = !isOffline && !cardFeeds; - const isLoadingCardsList = (!isOffline && isLoadingOnyxValue(cardsListMetadata)) || testLoadingDelay; + const isLoadingCardsList = (!isOffline && isLoadingOnyxValue(cardsListMetadata)); const isGB = countryByIp === CONST.COUNTRY.GB; const shouldShowGBDisclaimer = isGB && isBetaEnabled(CONST.BETAS.PLAID_COMPANY_CARDS) && (isNoFeed || hasNoAssignedCard); From fc0cb04ca9b25dac115ac8d367d38214e5c99044 Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Wed, 17 Dec 2025 21:27:14 -0500 Subject: [PATCH 07/15] move isLoadingCardsList to WorkspaceCompanyCardsList --- .../companyCards/WorkspaceCompanyCardsList.tsx | 11 ++++------- .../companyCards/WorkspaceCompanyCardsPage.tsx | 6 +----- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index 50aacc681319c..c267555e6c84f 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -9,6 +9,7 @@ import SearchBar from '@components/SearchBar'; import Text from '@components/Text'; import TableRowSkeleton from '@components/Skeletons/TableRowSkeleton'; import useCardFeeds from '@hooks/useCardFeeds'; +import useCardsList from '@hooks/useCardsList'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePolicy from '@hooks/usePolicy'; @@ -38,9 +39,6 @@ type WorkspaceCompanyCardsListProps = { /** Selected feed */ selectedFeed: CompanyCardFeedWithDomainID; - /** List of company cards */ - cardsList: OnyxEntry; - /** Current policy id */ policyID: string; @@ -52,18 +50,17 @@ type WorkspaceCompanyCardsListProps = { /** Whether to show GB disclaimer */ shouldShowGBDisclaimer?: boolean; - - /** Whether the cards list is loading */ - isLoadingCardsList?: boolean; }; -function WorkspaceCompanyCardsList({selectedFeed, cardsList, policyID, onAssignCard, isAssigningCardDisabled, shouldShowGBDisclaimer, isLoadingCardsList = false}: WorkspaceCompanyCardsListProps) { +function WorkspaceCompanyCardsList({selectedFeed, policyID, onAssignCard, isAssigningCardDisabled, shouldShowGBDisclaimer}: WorkspaceCompanyCardsListProps) { const styles = useThemeStyles(); const {isOffline} = useNetwork(); const {translate, localeCompare} = useLocalize(); const listRef = useRef>(null); const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout(); + const [cardsList, cardsListMetadata] = useCardsList(selectedFeed); + const isLoadingCardsList = !isOffline && isLoadingOnyxValue(cardsListMetadata); const [personalDetails, personalDetailsMetadata] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); const isLoadingPersonalDetails = !isOffline && isLoadingOnyxValue(personalDetailsMetadata); const isLoadingCardsTableData = isLoadingCardsList || isLoadingPersonalDetails; diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index 4e4eb10f0f2ac..b54c2e29f17c2 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -21,7 +21,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import WorkspaceCompanyCardPageEmptyState from './WorkspaceCompanyCardPageEmptyState'; import WorkspaceCompanyCardsFeedPendingPage from './WorkspaceCompanyCardsFeedPendingPage'; import WorkspaceCompanyCardsList from './WorkspaceCompanyCardsList'; @@ -43,7 +42,7 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { const [cardFeeds, , defaultFeed] = useCardFeeds(policyID); const selectedFeed = getSelectedFeed(lastSelectedFeed, cardFeeds); const feed = selectedFeed ? getCompanyCardFeed(selectedFeed) : undefined; - const [cardsList, cardsListMetadata] = useCardsList(selectedFeed); + const [cardsList] = useCardsList(selectedFeed); const [countryByIp] = useOnyx(ONYXKEYS.COUNTRY, {canBeMissing: false}); const hasNoAssignedCard = Object.keys(cardsList ?? {}).length === 0; @@ -60,7 +59,6 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { const {isOffline} = useNetwork({onReconnect: fetchCompanyCards}); const isLoading = !isOffline && !cardFeeds; - const isLoadingCardsList = (!isOffline && isLoadingOnyxValue(cardsListMetadata)); const isGB = countryByIp === CONST.COUNTRY.GB; const shouldShowGBDisclaimer = isGB && isBetaEnabled(CONST.BETAS.PLAID_COMPANY_CARDS) && (isNoFeed || hasNoAssignedCard); @@ -115,12 +113,10 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { {isFeedAdded && !isPending && ( )} From 70717ff424ca58aa1864d49909bac0531cd96e01 Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Wed, 17 Dec 2025 21:29:00 -0500 Subject: [PATCH 08/15] prettier --- .../workspace/companyCards/WorkspaceCompanyCardsList.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index c267555e6c84f..3351987c9cac6 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -6,18 +6,17 @@ import type {OnyxEntry} from 'react-native-onyx'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import {PressableWithFeedback} from '@components/Pressable'; import SearchBar from '@components/SearchBar'; -import Text from '@components/Text'; import TableRowSkeleton from '@components/Skeletons/TableRowSkeleton'; +import Text from '@components/Text'; import useCardFeeds from '@hooks/useCardFeeds'; import useCardsList from '@hooks/useCardsList'; import useLocalize from '@hooks/useLocalize'; +import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSearchResults from '@hooks/useSearchResults'; import useThemeStyles from '@hooks/useThemeStyles'; -import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; -import useNetwork from '@hooks/useNetwork'; import { filterCardsByPersonalDetails, getCardsByCardholderName, @@ -32,6 +31,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Card, CompanyCardFeed, CompanyCardFeedWithDomainID, WorkspaceCardsList} from '@src/types/onyx'; +import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import WorkspaceCompanyCardsFeedAddedEmptyPage from './WorkspaceCompanyCardsFeedAddedEmptyPage'; import WorkspaceCompanyCardsListRow from './WorkspaceCompanyCardsListRow'; From bb35bf7e0aebce4087b2ce8456c70b8713c5ca54 Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Wed, 17 Dec 2025 21:34:14 -0500 Subject: [PATCH 09/15] fix lint --- src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx | 3 +-- src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index 3351987c9cac6..234ee19c72c8b 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -2,7 +2,6 @@ import type {FlashListRef, ListRenderItemInfo} from '@shopify/flash-list'; import {FlashList} from '@shopify/flash-list'; import React, {useCallback, useMemo, useRef} from 'react'; import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import {PressableWithFeedback} from '@components/Pressable'; import SearchBar from '@components/SearchBar'; @@ -30,7 +29,7 @@ import Navigation from '@navigation/Navigation'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {Card, CompanyCardFeed, CompanyCardFeedWithDomainID, WorkspaceCardsList} from '@src/types/onyx'; +import type {Card, CompanyCardFeed, CompanyCardFeedWithDomainID} from '@src/types/onyx'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import WorkspaceCompanyCardsFeedAddedEmptyPage from './WorkspaceCompanyCardsFeedAddedEmptyPage'; import WorkspaceCompanyCardsListRow from './WorkspaceCompanyCardsListRow'; diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index b54c2e29f17c2..4c3e179601535 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -20,7 +20,6 @@ import {openPolicyCompanyCardsFeed, openPolicyCompanyCardsPage} from '@userActio import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; -import {isEmptyObject} from '@src/types/utils/EmptyObject'; import WorkspaceCompanyCardPageEmptyState from './WorkspaceCompanyCardPageEmptyState'; import WorkspaceCompanyCardsFeedPendingPage from './WorkspaceCompanyCardsFeedPendingPage'; import WorkspaceCompanyCardsList from './WorkspaceCompanyCardsList'; @@ -39,7 +38,7 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {canBeMissing: false}); const workspaceAccountID = policy?.workspaceAccountID ?? CONST.DEFAULT_NUMBER_ID; const [lastSelectedFeed] = useOnyx(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${policyID}`, {canBeMissing: true}); - const [cardFeeds, , defaultFeed] = useCardFeeds(policyID); + const [cardFeeds] = useCardFeeds(policyID); const selectedFeed = getSelectedFeed(lastSelectedFeed, cardFeeds); const feed = selectedFeed ? getCompanyCardFeed(selectedFeed) : undefined; const [cardsList] = useCardsList(selectedFeed); From 1c0e23f9f788cb2b165e5e92fed9393a1e417e58 Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Wed, 17 Dec 2025 21:42:12 -0500 Subject: [PATCH 10/15] remove unused method --- .../WorkspaceCompanyCardsList.tsx | 3 ++- .../members/WorkspaceMemberDetailsPage.tsx | 24 ------------------- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index 234ee19c72c8b..a283675e16ec1 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -63,6 +63,7 @@ function WorkspaceCompanyCardsList({selectedFeed, policyID, onAssignCard, isAssi const [personalDetails, personalDetailsMetadata] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); const isLoadingPersonalDetails = !isOffline && isLoadingOnyxValue(personalDetailsMetadata); const isLoadingCardsTableData = isLoadingCardsList || isLoadingPersonalDetails; + const [customCardNames] = useOnyx(ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES, {canBeMissing: true}); const policy = usePolicy(policyID); @@ -214,7 +215,7 @@ function WorkspaceCompanyCardsList({selectedFeed, policyID, onAssignCard, isAssi ); - // Show empty state when there are no cards (but not when loading) + // Show empty state when there are no cards if (!cards?.length && !isLoadingCardsTableData) { return ( { - if (isAccountLocked) { - showLockedAccountModal(); - return; - } - - if (hasMultipleFeeds) { - Navigation.navigate(ROUTES.WORKSPACE_MEMBER_NEW_CARD.getRoute(policyID, accountID)); - return; - } - const activeRoute = Navigation.getActiveRoute(); - - setIssueNewCardStepAndData({ - step: CONST.EXPENSIFY_CARD.STEP.CARD_TYPE, - data: { - assigneeEmail: memberLogin, - }, - isEditing: false, - isChangeAssigneeDisabled: true, - policyID, - }); - Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.getRoute(policyID, activeRoute)); - }, [accountID, hasMultipleFeeds, memberLogin, policyID, isAccountLocked, showLockedAccountModal]); - const startChangeOwnershipFlow = useCallback(() => { clearWorkspaceOwnerChangeFlow(policyID); Navigation.navigate(ROUTES.WORKSPACE_OWNER_CHANGE_CHECK.getRoute(policyID, accountID, 'amountOwed' as ValueOf)); From a7bfe9db6370adea3fefeed764d94dcc389149ff Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Wed, 17 Dec 2025 21:52:16 -0500 Subject: [PATCH 11/15] remove setIssueNewCardStepAndData --- src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx b/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx index 0870a2fd06b1e..87a1524c49070 100644 --- a/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx @@ -54,7 +54,6 @@ import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading'; import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading'; import variables from '@styles/variables'; -import {setIssueNewCardStepAndData} from '@userActions/Card'; import {clearWorkspaceOwnerChangeFlow, isApprover as isApproverUserAction, openPolicyMemberProfilePage, removeMembers} from '@userActions/Policy/Member'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; From 06ce70e5a0f414a9f5bd5c4d571f163b46fd0772 Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Wed, 17 Dec 2025 21:55:28 -0500 Subject: [PATCH 12/15] fix react compiler error --- .../workspace/companyCards/WorkspaceCompanyCardsPage.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index 4c3e179601535..37f0937795610 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useEffect, useState} from 'react'; +import React, {useEffect, useState} from 'react'; import ActivityIndicator from '@components/ActivityIndicator'; import DecisionModal from '@components/DecisionModal'; import useAssignCard from '@hooks/useAssignCard'; @@ -52,9 +52,9 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { const isFeedAdded = !isPending && !isNoFeed; const [shouldShowOfflineModal, setShouldShowOfflineModal] = useState(false); const domainOrWorkspaceAccountID = getDomainOrWorkspaceAccountID(workspaceAccountID, selectedFeedData); - const fetchCompanyCards = useCallback(() => { + const fetchCompanyCards = () => { openPolicyCompanyCardsPage(policyID, domainOrWorkspaceAccountID); - }, [policyID, domainOrWorkspaceAccountID]); + }; const {isOffline} = useNetwork({onReconnect: fetchCompanyCards}); const isLoading = !isOffline && !cardFeeds; From cdedee68e763a7a4ca548848d6ba6ba88683d98e Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Wed, 17 Dec 2025 22:45:07 -0500 Subject: [PATCH 13/15] more linting --- .../workspace/companyCards/WorkspaceCompanyCardsList.tsx | 4 ++-- .../workspace/companyCards/WorkspaceCompanyCardsPage.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index a283675e16ec1..6fd16d979b972 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -96,7 +96,7 @@ function WorkspaceCompanyCardsList({selectedFeed, policyID, onAssignCard, isAssi ({item: cardName, index}: ListRenderItemInfo) => { const assignedCard = Object.values(assignedCards ?? {}).find((card) => card.cardName === cardName); - const customCardName = customCardNames?.[assignedCard?.cardID ?? CONST.DEFAULT_NUMBER_ID]; + const customCardName = assignedCard?.cardID ? customCardNames?.[assignedCard.cardID] : undefined; const isCardDeleted = assignedCard?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; @@ -134,7 +134,7 @@ function WorkspaceCompanyCardsList({selectedFeed, policyID, onAssignCard, isAssi > {({hovered}) => ( { fetchCompanyCards(); - }, [fetchCompanyCards]); + }, [policyID, domainOrWorkspaceAccountID]); useEffect(() => { if (isLoading || !feed || isPending) { From 2296422742ccad6c0ff0871a9f96a627ec621752 Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Thu, 18 Dec 2025 10:07:01 -0500 Subject: [PATCH 14/15] Update src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx Co-authored-by: Hans --- src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index 421e3b9b29bdb..67837e662aa38 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -69,7 +69,7 @@ function WorkspaceCompanyCardsList({selectedFeed, policyID, onAssignCard, isAssi const [customCardNames] = useOnyx(ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES, {canBeMissing: true}); const policy = usePolicy(policyID); - const cardListTyped: Record | undefined = (cardsList as {cardList?: Record})?.cardList; + const cardListTyped: Record | undefined = (cardsList as {cardList?: Record})?.cardList ?? {}; const assignedCards = Object.fromEntries(Object.entries(cardsList ?? {}).filter(([key]) => key !== 'cardList')) as Record; const [cardFeeds] = useCardFeeds(policyID); From f5ce09c4daf3ba4906008efbd9ea6a4c08da0d43 Mon Sep 17 00:00:00 2001 From: Carlos Miceli Date: Thu, 18 Dec 2025 11:19:11 -0500 Subject: [PATCH 15/15] fix flashing assign card screen --- .../companyCards/WorkspaceCompanyCardsPage.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index 69ead9d8134ef..b0bf0bd30452b 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -20,6 +20,7 @@ import {openPolicyCompanyCardsFeed, openPolicyCompanyCardsPage} from '@userActio import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; +import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import WorkspaceCompanyCardPageEmptyState from './WorkspaceCompanyCardPageEmptyState'; import WorkspaceCompanyCardsFeedPendingPage from './WorkspaceCompanyCardsFeedPendingPage'; import WorkspaceCompanyCardsList from './WorkspaceCompanyCardsList'; @@ -41,7 +42,7 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { const [cardFeeds] = useCardFeeds(policyID); const selectedFeed = getSelectedFeed(lastSelectedFeed, cardFeeds); const feed = selectedFeed ? getCompanyCardFeed(selectedFeed) : undefined; - const [cardsList] = useCardsList(selectedFeed); + const [cardsList, cardsListMetadata] = useCardsList(selectedFeed); const [countryByIp] = useOnyx(ONYXKEYS.COUNTRY, {canBeMissing: false}); const hasNoAssignedCard = Object.keys(cardsList ?? {}).length === 0; @@ -52,17 +53,16 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) { const isFeedAdded = !isPending && !isNoFeed; const [shouldShowOfflineModal, setShouldShowOfflineModal] = useState(false); const domainOrWorkspaceAccountID = getDomainOrWorkspaceAccountID(workspaceAccountID, selectedFeedData); - const fetchCompanyCards = () => { - openPolicyCompanyCardsPage(policyID, domainOrWorkspaceAccountID); - }; - const {isOffline} = useNetwork({onReconnect: fetchCompanyCards}); - const isLoading = !isOffline && !cardFeeds; + const {isOffline} = useNetwork({ + onReconnect: () => openPolicyCompanyCardsPage(policyID, domainOrWorkspaceAccountID), + }); + const isLoading = !isOffline && (!cardFeeds || (isFeedAdded && isLoadingOnyxValue(cardsListMetadata))); const isGB = countryByIp === CONST.COUNTRY.GB; const shouldShowGBDisclaimer = isGB && isBetaEnabled(CONST.BETAS.PLAID_COMPANY_CARDS) && (isNoFeed || hasNoAssignedCard); useEffect(() => { - fetchCompanyCards(); + openPolicyCompanyCardsPage(policyID, domainOrWorkspaceAccountID); }, [policyID, domainOrWorkspaceAccountID]); useEffect(() => {