From edf769283d129642d2b135616108b950a0d934b8 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Mon, 23 Jun 2025 15:59:29 +0300 Subject: [PATCH 01/15] Add correct name and image to Search card filter --- .../SelectionList/Search/CardListItem.tsx | 28 ++++++++++++++----- src/libs/CardFeedUtils.ts | 17 +++++++---- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/components/SelectionList/Search/CardListItem.tsx b/src/components/SelectionList/Search/CardListItem.tsx index a11da62979cd6..0ce61c5a1f77c 100644 --- a/src/components/SelectionList/Search/CardListItem.tsx +++ b/src/components/SelectionList/Search/CardListItem.tsx @@ -4,6 +4,7 @@ import {View} from 'react-native'; import Avatar from '@components/Avatar'; import Icon from '@components/Icon'; import {FallbackAvatar} from '@components/Icon/Expensicons'; +import PlaidCardFeedIcon from '@components/PlaidCardFeedIcon'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import SelectCircle from '@components/SelectCircle'; import BaseListItem from '@components/SelectionList/BaseListItem'; @@ -19,7 +20,15 @@ import CONST from '@src/CONST'; import type {PersonalDetails} from '@src/types/onyx'; import type {BankIcon} from '@src/types/onyx/Bank'; -type AdditionalCardProps = {shouldShowOwnersAvatar?: boolean; cardOwnerPersonalDetails?: PersonalDetails; bankIcon?: BankIcon; lastFourPAN?: string; isVirtual?: boolean; cardName?: string}; +type AdditionalCardProps = { + shouldShowOwnersAvatar?: boolean; + cardOwnerPersonalDetails?: PersonalDetails; + bankIcon?: BankIcon; + lastFourPAN?: string; + isVirtual?: boolean; + cardName?: string; + plaidUrl?: string; +}; type CardListItemProps = BaseListItemProps; function CardListItem({ @@ -112,12 +121,17 @@ function CardListItem({ ) : ( - + <> + {!!item?.plaidUrl && } + {!item?.plaidUrl && ( + + )} + )} )} diff --git a/src/libs/CardFeedUtils.ts b/src/libs/CardFeedUtils.ts index 66c0909cead44..e2e5f719076d9 100644 --- a/src/libs/CardFeedUtils.ts +++ b/src/libs/CardFeedUtils.ts @@ -5,11 +5,11 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Card, CardList, CompanyCardFeed, PersonalDetailsList, WorkspaceCardsList} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import {getBankName, getCardFeedIcon, isCard, isCardClosed, isCardHiddenFromSearch} from './CardUtils'; +import {getBankName, getCardFeedIcon, getPlaidInstitutionIconUrl, getPlaidInstitutionId, isCard, isCardClosed, isCardHiddenFromSearch} from './CardUtils'; import {getDescriptionForPolicyDomainCard, getPolicy} from './PolicyUtils'; import type {OptionData} from './ReportUtils'; -type CardFilterItem = Partial & AdditionalCardProps & {isCardFeed?: boolean; correspondingCards?: string[]; cardFeedKey: string}; +type CardFilterItem = Partial & AdditionalCardProps & {isCardFeed?: boolean; correspondingCards?: string[]; cardFeedKey: string; plaidUrl?: string}; type DomainFeedData = {bank: string; domainName: string; correspondingCardIDs: string[]; fundID?: string}; type ItemsGroupedBySelection = {selected: CardFilterItem[]; unselected: CardFilterItem[]}; type CardFeedNamesWithType = Record; @@ -162,21 +162,24 @@ function getWorkspaceCardFeedData(cardFeed: WorkspaceCardsList | undefined, repe if (!representativeCard || !cardFeedArray.some((cardFeedItem) => isCard(cardFeedItem) && !isCardHiddenFromSearch(cardFeedItem))) { return; } - const {domainName, bank} = representativeCard; + const {domainName, bank, cardName} = representativeCard; const isBankRepeating = repeatingBanks.includes(bank); const policyID = domainName.match(CONST.REGEX.EXPENSIFY_POLICY_DOMAIN_NAME)?.[1] ?? ''; // This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850 // eslint-disable-next-line deprecation/deprecation const correspondingPolicy = getPolicy(policyID?.toUpperCase()); const cardFeedLabel = isBankRepeating ? correspondingPolicy?.name : undefined; - const cardFeedBankName = bank === CONST.EXPENSIFY_CARD.BANK ? translate('search.filters.card.expensify') : getBankName(bank as CompanyCardFeed); - const cardName = + const isPlaid = !!getPlaidInstitutionId(bank); + const companyCardBank = isPlaid && cardName ? cardName : getBankName(bank as CompanyCardFeed); + + const cardFeedBankName = bank === CONST.EXPENSIFY_CARD.BANK ? translate('search.filters.card.expensify') : companyCardBank; + const fullCardName = cardFeedBankName === CONST.COMPANY_CARDS.CARD_TYPE.CSV ? translate('search.filters.card.cardFeedNameCSV', {cardFeedLabel}) : translate('search.filters.card.cardFeedName', {cardFeedBankName, cardFeedLabel}); return { - cardName, + cardName: fullCardName, bank, label: cardFeedLabel, type: 'workspace', @@ -268,6 +271,7 @@ function createCardFeedItem({ illustrations: IllustrationsType; }): CardFilterItem { const isSelected = correspondingCardIDs.every((card) => selectedCards.includes(card)); + const plaidUrl = getPlaidInstitutionIconUrl(bank); const icon = getCardFeedIcon(bank as CompanyCardFeed, illustrations); return { @@ -278,6 +282,7 @@ function createCardFeedItem({ bankIcon: { icon, }, + plaidUrl, cardFeedKey, isCardFeed: true, correspondingCards: correspondingCardIDs, From e73921342ca594b1e12a0734ee5199546b51bdff Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Wed, 25 Jun 2025 15:56:15 +0300 Subject: [PATCH 02/15] fix search based on feed --- src/components/SelectionList/Search/CardListItem.tsx | 4 ++-- src/types/form/SearchAdvancedFiltersForm.ts | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/SelectionList/Search/CardListItem.tsx b/src/components/SelectionList/Search/CardListItem.tsx index 0ce61c5a1f77c..3be0cf98ad8c5 100644 --- a/src/components/SelectionList/Search/CardListItem.tsx +++ b/src/components/SelectionList/Search/CardListItem.tsx @@ -59,7 +59,7 @@ function CardListItem({ const ownersAvatar = { source: item.cardOwnerPersonalDetails?.avatar ?? FallbackAvatar, - id: item.cardOwnerPersonalDetails?.accountID ?? -1, + id: item.cardOwnerPersonalDetails?.accountID ?? CONST.DEFAULT_NUMBER_ID, type: CONST.ICON_TYPE_AVATAR, name: item.cardOwnerPersonalDetails?.displayName ?? '', fallbackIcon: item.cardOwnerPersonalDetails?.fallbackIcon, @@ -94,7 +94,7 @@ function CardListItem({ Date: Wed, 25 Jun 2025 16:08:42 +0300 Subject: [PATCH 03/15] fix border for images --- assets/images/companyCards/card-plaid.svg | 2 +- assets/images/companyCards/large/card-plaid-large.svg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/images/companyCards/card-plaid.svg b/assets/images/companyCards/card-plaid.svg index c4ed528778ae6..ff56156638e79 100644 --- a/assets/images/companyCards/card-plaid.svg +++ b/assets/images/companyCards/card-plaid.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/assets/images/companyCards/large/card-plaid-large.svg b/assets/images/companyCards/large/card-plaid-large.svg index db61a2cd76ee4..8dd4ed29a80c8 100644 --- a/assets/images/companyCards/large/card-plaid-large.svg +++ b/assets/images/companyCards/large/card-plaid-large.svg @@ -1 +1 @@ - \ No newline at end of file + From 192b3424de8b83bdf3f11ed436b8e7532582f13f Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Thu, 26 Jun 2025 14:45:20 +0300 Subject: [PATCH 04/15] fix visibility of the very small cards --- assets/images/companyCards/card-plaid.svg | 2 +- src/components/PlaidCardFeedIcon.tsx | 24 ++++++++++++------- .../SelectionList/Search/CardListItem.tsx | 20 +++++++++++----- src/libs/CardFeedUtils.ts | 2 ++ src/styles/index.ts | 9 +++++++ 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/assets/images/companyCards/card-plaid.svg b/assets/images/companyCards/card-plaid.svg index ff56156638e79..7b9b4aeb4c630 100644 --- a/assets/images/companyCards/card-plaid.svg +++ b/assets/images/companyCards/card-plaid.svg @@ -1 +1 @@ - + diff --git a/src/components/PlaidCardFeedIcon.tsx b/src/components/PlaidCardFeedIcon.tsx index 0588315948501..813cff7b44f5b 100644 --- a/src/components/PlaidCardFeedIcon.tsx +++ b/src/components/PlaidCardFeedIcon.tsx @@ -13,9 +13,10 @@ type PlaidCardFeedIconProps = { plaidUrl: string; style?: StyleProp; isLarge?: boolean; + isSmall?: boolean; }; -function PlaidCardFeedIcon({plaidUrl, style, isLarge}: PlaidCardFeedIconProps) { +function PlaidCardFeedIcon({plaidUrl, style, isLarge, isSmall}: PlaidCardFeedIconProps) { const [isBrokenImage, setIsBrokenImage] = useState(false); const styles = useThemeStyles(); const illustrations = useThemeIllustrations(); @@ -23,6 +24,10 @@ function PlaidCardFeedIcon({plaidUrl, style, isLarge}: PlaidCardFeedIconProps) { const width = isLarge ? variables.cardPreviewWidth : variables.cardIconWidth; const height = isLarge ? variables.cardPreviewHeight : variables.cardIconHeight; const [loading, setLoading] = useState(true); + const plaidImageStyle = isLarge ? styles.plaidIcon : styles.plaidIconSmall; + const iconWidth = isSmall ? variables.cardMiniatureWidth : width; + const iconHeight = isSmall ? variables.cardMiniatureHeight : height; + const plaidLoadedStyle = isSmall ? styles.plaidIconExtraSmall : plaidImageStyle; useEffect(() => { if (!plaidUrl) { @@ -37,31 +42,32 @@ function PlaidCardFeedIcon({plaidUrl, style, isLarge}: PlaidCardFeedIconProps) { {isBrokenImage ? ( ) : ( <> setIsBrokenImage(true)} onLoadEnd={() => setLoading(false)} /> {loading ? ( - + ) : ( )} diff --git a/src/components/SelectionList/Search/CardListItem.tsx b/src/components/SelectionList/Search/CardListItem.tsx index 3be0cf98ad8c5..ad5bd8e7c3013 100644 --- a/src/components/SelectionList/Search/CardListItem.tsx +++ b/src/components/SelectionList/Search/CardListItem.tsx @@ -112,12 +112,20 @@ function CardListItem({ - + {!!item?.plaidUrl && ( + + )} + {!item?.plaidUrl && ( + + )} ) : ( diff --git a/src/libs/CardFeedUtils.ts b/src/libs/CardFeedUtils.ts index e2e5f719076d9..11e934d19fc15 100644 --- a/src/libs/CardFeedUtils.ts +++ b/src/libs/CardFeedUtils.ts @@ -66,6 +66,7 @@ function createCardFilterItem(card: Card, personalDetailsList: PersonalDetailsLi const icon = getCardFeedIcon(card?.bank as CompanyCardFeed, illustrations); const cardName = card?.nameValuePairs?.cardTitle; const text = personalDetails?.displayName ?? cardName; + const plaidUrl = getPlaidInstitutionIconUrl(card?.bank); return { lastFourPAN: card.lastFourPAN, @@ -74,6 +75,7 @@ function createCardFilterItem(card: Card, personalDetailsList: PersonalDetailsLi cardName, cardOwnerPersonalDetails: personalDetails ?? undefined, text, + plaidUrl, keyForList: card.cardID.toString(), isSelected, bankIcon: { diff --git a/src/styles/index.ts b/src/styles/index.ts index 4128b65b8fb7a..d2c02b606e5e0 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -5215,6 +5215,15 @@ const styles = (theme: ThemeColors) => top: 4, }, + plaidIconExtraSmall: { + height: variables.iconSizeXSmall, + width: variables.iconSizeXSmall, + position: 'absolute', + right: 1, + zIndex: 1, + top: 1, + }, + walletCardNumber: { color: theme.text, fontSize: variables.fontSizeNormal, From 9dae27b8d32e02bb6ba36767f97cc1c217d744e4 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Mon, 30 Jun 2025 09:53:31 +0300 Subject: [PATCH 05/15] add card name in reports --- src/libs/CardFeedUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/CardFeedUtils.ts b/src/libs/CardFeedUtils.ts index 11e934d19fc15..a59ebd3675e96 100644 --- a/src/libs/CardFeedUtils.ts +++ b/src/libs/CardFeedUtils.ts @@ -64,7 +64,7 @@ function createCardFilterItem(card: Card, personalDetailsList: PersonalDetailsLi const personalDetails = personalDetailsList[card?.accountID ?? CONST.DEFAULT_NUMBER_ID]; const isSelected = selectedCards.includes(card.cardID.toString()); const icon = getCardFeedIcon(card?.bank as CompanyCardFeed, illustrations); - const cardName = card?.nameValuePairs?.cardTitle; + const cardName = card?.nameValuePairs?.cardTitle ?? card?.cardName; const text = personalDetails?.displayName ?? cardName; const plaidUrl = getPlaidInstitutionIconUrl(card?.bank); From b54821f5026b6eecc005d4409f79bae80fedf4b0 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 1 Jul 2025 16:03:55 +0300 Subject: [PATCH 06/15] rollback card name --- src/libs/CardFeedUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/CardFeedUtils.ts b/src/libs/CardFeedUtils.ts index a59ebd3675e96..11e934d19fc15 100644 --- a/src/libs/CardFeedUtils.ts +++ b/src/libs/CardFeedUtils.ts @@ -64,7 +64,7 @@ function createCardFilterItem(card: Card, personalDetailsList: PersonalDetailsLi const personalDetails = personalDetailsList[card?.accountID ?? CONST.DEFAULT_NUMBER_ID]; const isSelected = selectedCards.includes(card.cardID.toString()); const icon = getCardFeedIcon(card?.bank as CompanyCardFeed, illustrations); - const cardName = card?.nameValuePairs?.cardTitle ?? card?.cardName; + const cardName = card?.nameValuePairs?.cardTitle; const text = personalDetails?.displayName ?? cardName; const plaidUrl = getPlaidInstitutionIconUrl(card?.bank); From de3ba9a878436aeb9c3075aef6355eb8fa6f0834 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Thu, 3 Jul 2025 14:43:48 +0300 Subject: [PATCH 07/15] filters for removed feed --- src/libs/CardFeedUtils.ts | 2 +- src/libs/SearchQueryUtils.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libs/CardFeedUtils.ts b/src/libs/CardFeedUtils.ts index 11e934d19fc15..8292cc52e6272 100644 --- a/src/libs/CardFeedUtils.ts +++ b/src/libs/CardFeedUtils.ts @@ -95,7 +95,7 @@ function buildCardsData( isClosedCards = false, ): ItemsGroupedBySelection { // Filter condition to build different cards data for closed cards and individual cards based on the isClosedCards flag, we don't want to show closed cards in the individual cards section - const filterCondition = (card: Card) => (isClosedCards ? isCardClosed(card) : !isCardHiddenFromSearch(card) && !isCardClosed(card)); + const filterCondition = (card: Card) => (isClosedCards ? isCardClosed(card) : !isCardHiddenFromSearch(card) && !isCardClosed(card) && isCard(card)); const userAssignedCards: CardFilterItem[] = Object.values(userCardList ?? {}) .filter((card) => filterCondition(card)) .map((card) => createCardFilterItem(card, personalDetailsList, selectedCards, illustrations)); diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index 52fb60daeaa7c..bf3af51b983d1 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -802,6 +802,21 @@ function buildUserReadableQueryString( operator: queryFilter.at(0)?.operator ?? CONST.SEARCH.SYNTAX_OPERATORS.AND, value: taxRate, })); + } else if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.FEED) { + displayQueryFilters = queryFilter.reduce((acc, filter) => { + const feedKey = filter.value.toString(); + const workspaceFeedKey = getWorkspaceCardFeedKey(feedKey); + + const workspaceValue = cardFeedNamesWithType[workspaceFeedKey]; + const domainValue = cardFeedNamesWithType[feedKey]; + + if ((workspaceValue && workspaceValue.type === 'workspace') || (domainValue && domainValue.type === 'domain')) { + const value = workspaceValue?.type === 'workspace' ? workspaceValue.name : domainValue.name; + acc.push({operator: filter.operator, value}); + } + + return acc; + }, [] as QueryFilter[]); } else { displayQueryFilters = queryFilter.map((filter) => ({ operator: filter.operator, From a46274aad37afd8711539e248f0d56e642d4ffe6 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Mon, 7 Jul 2025 12:27:38 +0300 Subject: [PATCH 08/15] filters for remove card --- src/libs/SearchQueryUtils.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index 34dcaaa489602..f364107446186 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -810,6 +810,20 @@ function buildUserReadableQueryString( acc.push({operator: filter.operator, value}); } + return acc; + }, [] as QueryFilter[]); + } else if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID) { + displayQueryFilters = queryFilter.reduce((acc, filter) => { + const cardValue = filter.value.toString(); + const cardID = parseInt(cardValue, 10); + + if (cardList?.[cardID]) { + if (Number.isNaN(cardID)) { + acc.push({operator: filter.operator, value: cardID}); + } else { + acc.push({operator: filter.operator, value: getCardDescription(cardID, cardList) || cardID}); + } + } return acc; }, [] as QueryFilter[]); } else { From cb6809e407b78f02404406eefc63d8d82b7147d5 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 8 Jul 2025 09:30:29 +0300 Subject: [PATCH 09/15] fix merge conflicts --- src/libs/CardFeedUtils.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libs/CardFeedUtils.ts b/src/libs/CardFeedUtils.ts index 7109e3fe15563..d1b01a1a05b1d 100644 --- a/src/libs/CardFeedUtils.ts +++ b/src/libs/CardFeedUtils.ts @@ -1,4 +1,4 @@ -import type {OnyxCollection} from 'react-native-onyx/dist/types'; +import type {OnyxCollection} from 'react-native-onyx'; import type {LocaleContextProps} from '@components/LocaleContextProvider'; import type {AdditionalCardProps} from '@components/SelectionList/Search/CardListItem'; import type IllustrationsType from '@styles/theme/illustrations/types'; @@ -6,7 +6,17 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Card, CardFeeds, CardList, CompanyCardFeed, PersonalDetailsList, WorkspaceCardsList} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import {getBankName, getCardFeedIcon, getCompanyFeeds, getCustomOrFormattedFeedName, getPlaidInstitutionIconUrl, getPlaidInstitutionId, isCard, isCardClosed, isCardHiddenFromSearch} from './CardUtils'; +import { + getBankName, + getCardFeedIcon, + getCompanyFeeds, + getCustomOrFormattedFeedName, + getPlaidInstitutionIconUrl, + getPlaidInstitutionId, + isCard, + isCardClosed, + isCardHiddenFromSearch, +} from './CardUtils'; import {getDescriptionForPolicyDomainCard, getPolicy} from './PolicyUtils'; import type {OptionData} from './ReportUtils'; From 235396f3c08558d51b69d775b5be96467c74faf5 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 8 Jul 2025 10:45:46 +0300 Subject: [PATCH 10/15] fix broken feeds --- src/libs/SearchQueryUtils.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index f59ca5d0a047b..41e267bd3625f 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -771,15 +771,18 @@ function buildUserReadableQueryString( } else if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.FEED) { displayQueryFilters = queryFilter.reduce((acc, filter) => { const feedKey = filter.value.toString(); - const workspaceFeedKey = getWorkspaceCardFeedKey(feedKey); - - const workspaceValue = cardFeedNamesWithType[workspaceFeedKey]; - const domainValue = cardFeedNamesWithType[feedKey]; - - if ((workspaceValue && workspaceValue.type === 'workspace') || (domainValue && domainValue.type === 'domain')) { - const value = workspaceValue?.type === 'workspace' ? workspaceValue.name : domainValue.name; - acc.push({operator: filter.operator, value}); + const cardFeedsForDisplay = getCardFeedsForDisplay(cardFeeds, cardList); + const plaidFeedName = feedKey?.split(CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID)?.at(1); + const regularBank = feedKey?.split('_')?.at(1) ?? CONST.DEFAULT_NUMBER_ID; + const plaidValue = cardFeedsForDisplay[`${CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID}${plaidFeedName}` as OnyxTypes.CompanyCardFeed]?.name; + if (plaidFeedName) { + if (plaidValue) { + acc.push({operator: filter.operator, value: plaidValue}); + } + return acc; } + const value = cardFeedsForDisplay[regularBank as OnyxTypes.CompanyCardFeed]?.name ?? feedKey; + acc.push({operator: filter.operator, value}); return acc; }, [] as QueryFilter[]); @@ -806,6 +809,9 @@ function buildUserReadableQueryString( title += buildFilterValuesString(getUserFriendlyKey(key), displayQueryFilters); } + console.log('title'); + console.log(title); + return title; } From a47e9cef20331002e9dc15c2f62a84f2f3974c8e Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 8 Jul 2025 10:48:32 +0300 Subject: [PATCH 11/15] clean up --- src/libs/SearchQueryUtils.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index 41e267bd3625f..18f4c303ca3e1 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -809,9 +809,6 @@ function buildUserReadableQueryString( title += buildFilterValuesString(getUserFriendlyKey(key), displayQueryFilters); } - console.log('title'); - console.log(title); - return title; } From 7dad69796a6148087d3f8d2f511542d86497dcbf Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 8 Jul 2025 12:31:27 +0300 Subject: [PATCH 12/15] fix navigation back from commercial feed --- src/pages/workspace/companyCards/addNew/SelectBankStep.tsx | 4 ++-- src/types/onyx/CardFeeds.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx b/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx index a5c72b8ce9509..828f96ea41c1b 100644 --- a/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx +++ b/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx @@ -32,7 +32,7 @@ function SelectBankStep() { const {isBetaEnabled} = usePermissions(); const [addNewCard] = useOnyx(ONYXKEYS.ADD_NEW_COMPANY_CARD, {canBeMissing: true}); - const [bankSelected, setBankSelected] = useState>(); + const [bankSelected, setBankSelected] = useState | null>(); const [hasError, setHasError] = useState(false); const isOtherBankSelected = bankSelected === CONST.COMPANY_CARDS.BANKS.OTHER; @@ -65,7 +65,7 @@ function SelectBankStep() { return; } if (isBetaEnabled(CONST.BETAS.PLAID_COMPANY_CARDS)) { - setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.SELECT_FEED_TYPE}); + setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.SELECT_FEED_TYPE, data: {selectedBank: null}}); } else { Navigation.goBack(); } diff --git a/src/types/onyx/CardFeeds.ts b/src/types/onyx/CardFeeds.ts index df6ca03425c4a..88ecfb9093c36 100644 --- a/src/types/onyx/CardFeeds.ts +++ b/src/types/onyx/CardFeeds.ts @@ -137,7 +137,7 @@ type AddNewCardFeedData = { cardTitle: string; /** Selected bank */ - selectedBank: ValueOf; + selectedBank: ValueOf | null; /** Selected feed type */ selectedFeedType: ValueOf; From ddb94a560272df20379cacca6085ea1f96ce4c17 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 8 Jul 2025 12:36:12 +0300 Subject: [PATCH 13/15] fix navigation back from commercial feed --- src/libs/actions/getCompanyCardBankConnection/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/getCompanyCardBankConnection/index.tsx b/src/libs/actions/getCompanyCardBankConnection/index.tsx index fbecc1a68106d..b593774f7f0d4 100644 --- a/src/libs/actions/getCompanyCardBankConnection/index.tsx +++ b/src/libs/actions/getCompanyCardBankConnection/index.tsx @@ -23,7 +23,7 @@ type CompanyCardPlaidConnection = { plaidAccounts: string; }; -function getCompanyCardBankConnection(policyID?: string, bankName?: string) { +function getCompanyCardBankConnection(policyID?: string, bankName?: string | null) { const bankConnection = Object.keys(CONST.COMPANY_CARDS.BANKS).find((key) => CONST.COMPANY_CARDS.BANKS[key as keyof typeof CONST.COMPANY_CARDS.BANKS] === bankName); if (!bankName || !bankConnection || !policyID) { From 085d974bcc4d9bae78cf0fb206ec442115b12868 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Thu, 10 Jul 2025 13:04:44 +0300 Subject: [PATCH 14/15] add plaid import accounts when feed broken connection --- .../OpenPlaidCompanyCardLoginParams.ts | 2 ++ src/libs/actions/Plaid.ts | 4 ++- .../companyCards/BankConnection/index.tsx | 1 - .../addNew/PlaidConnectionStep.tsx | 36 +++++++++++++++---- .../assignCard/AssignCardFeedPage.tsx | 7 +++- 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/libs/API/parameters/OpenPlaidCompanyCardLoginParams.ts b/src/libs/API/parameters/OpenPlaidCompanyCardLoginParams.ts index b4d62d78ea526..80720eb37e878 100644 --- a/src/libs/API/parameters/OpenPlaidCompanyCardLoginParams.ts +++ b/src/libs/API/parameters/OpenPlaidCompanyCardLoginParams.ts @@ -2,6 +2,8 @@ type OpenPlaidCompanyCardLoginParams = { redirectURI: string | undefined; androidPackage?: string; country: string; + domain?: string; + feed?: string; }; export default OpenPlaidCompanyCardLoginParams; diff --git a/src/libs/actions/Plaid.ts b/src/libs/actions/Plaid.ts index 3d1f75fc01815..8190a1fcf9afa 100644 --- a/src/libs/actions/Plaid.ts +++ b/src/libs/actions/Plaid.ts @@ -47,13 +47,15 @@ function openPlaidBankLogin(allowDebit: boolean, bankAccountID: number) { /** * Gets the Plaid Link token used to initialize the Plaid SDK for Company card */ -function openPlaidCompanyCardLogin(country: string) { +function openPlaidCompanyCardLogin(country: string, domain?: string, feed?: string) { const {redirectURI, androidPackage} = getPlaidLinkTokenParameters(); const params: OpenPlaidCompanyCardLoginParams = { redirectURI, androidPackage, country, + domain, + feed, }; const optimisticData = [ diff --git a/src/pages/workspace/companyCards/BankConnection/index.tsx b/src/pages/workspace/companyCards/BankConnection/index.tsx index 600d14f770001..6ae17dd42b04d 100644 --- a/src/pages/workspace/companyCards/BankConnection/index.tsx +++ b/src/pages/workspace/companyCards/BankConnection/index.tsx @@ -130,7 +130,6 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti return; } if (isPlaid) { - onImportPlaidAccounts(); return; } if (url) { diff --git a/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx b/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx index 53a992343fa27..3e75c38eee75a 100644 --- a/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx +++ b/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useEffect, useRef} from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import {ActivityIndicator, InteractionManager, View} from 'react-native'; import type {LinkSuccessMetadata} from 'react-native-plaid-link-sdk'; import type {PlaidLinkOnSuccessMetadata} from 'react-plaid-link/src/types'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; @@ -15,16 +15,17 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {setAddNewCompanyCardStepAndData, setAssignCardStepAndData} from '@libs/actions/CompanyCards'; import KeyboardShortcut from '@libs/KeyboardShortcut'; import Log from '@libs/Log'; +import {getDomainNameForPolicy} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import {handleRestrictedEvent} from '@userActions/App'; import {setPlaidEvent} from '@userActions/BankAccounts'; -import {openPlaidCompanyCardLogin} from '@userActions/Plaid'; +import {importPlaidAccounts, openPlaidCompanyCardLogin} from '@userActions/Plaid'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {CompanyCardFeed} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -function PlaidConnectionStep({feed}: {feed?: CompanyCardFeed}) { +function PlaidConnectionStep({feed, policyID}: {feed?: CompanyCardFeed; policyID?: string}) { const {translate} = useLocalize(); const styles = useThemeStyles(); const theme = useTheme(); @@ -39,6 +40,7 @@ function PlaidConnectionStep({feed}: {feed?: CompanyCardFeed}) { // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style const plaidDataErrorMessage = !isEmptyObject(plaidErrors) ? (Object.values(plaidErrors).at(0) as string) : ''; const {isOffline} = useNetwork(); + const domain = getDomainNameForPolicy(policyID); const isAuthenticatedWithPlaid = useCallback(() => !!plaidData?.bankAccounts?.length || !isEmptyObject(plaidData?.errors), [plaidData]); @@ -76,7 +78,7 @@ function PlaidConnectionStep({feed}: {feed?: CompanyCardFeed}) { return unsubscribeToNavigationShortcuts; } if (addNewCard?.data?.selectedCountry) { - openPlaidCompanyCardLogin(addNewCard.data.selectedCountry); + openPlaidCompanyCardLogin(addNewCard.data.selectedCountry, domain, feed); return unsubscribeToNavigationShortcuts; } @@ -88,10 +90,10 @@ function PlaidConnectionStep({feed}: {feed?: CompanyCardFeed}) { // If we are coming back from offline and we haven't authenticated with Plaid yet, we need to re-run our call to kick off Plaid // previousNetworkState.current also makes sure that this doesn't run on the first render. if (previousNetworkState.current && !isOffline && !isAuthenticatedWithPlaid() && addNewCard?.data?.selectedCountry) { - openPlaidCompanyCardLogin(addNewCard.data.selectedCountry); + openPlaidCompanyCardLogin(addNewCard.data.selectedCountry, domain, feed); } previousNetworkState.current = isOffline; - }, [addNewCard?.data?.selectedCountry, isAuthenticatedWithPlaid, isOffline]); + }, [addNewCard?.data?.selectedCountry, domain, feed, isAuthenticatedWithPlaid, isOffline]); const handleBackButtonPress = () => { if (feed) { @@ -119,6 +121,28 @@ function PlaidConnectionStep({feed}: {feed?: CompanyCardFeed}) { (metadata?.institution as PlaidLinkOnSuccessMetadata['institution'])?.name ?? (metadata?.institution as LinkSuccessMetadata['institution'])?.name; if (feed) { + if (plaidConnectedFeed && addNewCard?.data?.selectedCountry && plaidConnectedFeedName) { + importPlaidAccounts( + publicToken, + plaidConnectedFeed, + plaidConnectedFeedName, + addNewCard.data.selectedCountry, + getDomainNameForPolicy(policyID), + JSON.stringify(metadata?.accounts), + ); + InteractionManager.runAfterInteractions(() => { + setAssignCardStepAndData({ + data: { + plaidAccessToken: publicToken, + institutionId: plaidConnectedFeed, + plaidConnectedFeedName, + plaidAccounts: metadata?.accounts, + }, + currentStep: CONST.COMPANY_CARD.STEP.BANK_CONNECTION, + }); + }); + return; + } setAssignCardStepAndData({ data: { plaidAccessToken: publicToken, diff --git a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx index f95dd37fa3ebb..ade4bc367b089 100644 --- a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx +++ b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx @@ -60,7 +60,12 @@ function AssignCardFeedPage({route, policy}: AssignCardFeedPageProps) { /> ); case CONST.COMPANY_CARD.STEP.PLAID_CONNECTION: - return ; + return ( + + ); case CONST.COMPANY_CARD.STEP.ASSIGNEE: return ( Date: Wed, 16 Jul 2025 14:41:21 +0200 Subject: [PATCH 15/15] fix: show correct feed name in search query --- src/libs/SearchQueryUtils.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index 4c7f280c6c219..f0c64ff026421 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -793,14 +793,15 @@ function buildUserReadableQueryString( const cardFeedsForDisplay = getCardFeedsForDisplay(cardFeeds, cardList); const plaidFeedName = feedKey?.split(CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID)?.at(1); const regularBank = feedKey?.split('_')?.at(1) ?? CONST.DEFAULT_NUMBER_ID; - const plaidValue = cardFeedsForDisplay[`${CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID}${plaidFeedName}` as OnyxTypes.CompanyCardFeed]?.name; + const idPrefix = feedKey?.split('_')?.at(0) ?? CONST.DEFAULT_NUMBER_ID; + const plaidValue = cardFeedsForDisplay[`${idPrefix}_${CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID}${plaidFeedName}` as OnyxTypes.CompanyCardFeed]?.name; if (plaidFeedName) { if (plaidValue) { acc.push({operator: filter.operator, value: plaidValue}); } return acc; } - const value = cardFeedsForDisplay[regularBank as OnyxTypes.CompanyCardFeed]?.name ?? feedKey; + const value = cardFeedsForDisplay[`${idPrefix}_${regularBank}` as OnyxTypes.CompanyCardFeed]?.name ?? feedKey; acc.push({operator: filter.operator, value}); return acc;