From 90f136cb0df23994a02175031f223ec124f251e9 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Thu, 31 Oct 2024 15:44:37 +0200 Subject: [PATCH 1/6] Add new object to pick Assigned cards --- src/libs/CardUtils.ts | 8 ++++++- .../workspace/WorkspaceMoreFeaturesPage.tsx | 3 ++- .../WorkspaceCompanyCardFeedSelectorPage.tsx | 3 ++- .../WorkspaceCompanyCardsPage.tsx | 2 +- .../assignCard/CardSelectionStep.tsx | 17 +++++---------- .../members/WorkspaceMemberNewCardPage.tsx | 3 ++- src/types/onyx/CardFeeds.ts | 21 +++++++++++++++++++ 7 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index 9fda616557a8..c6f9e6b7d8a6 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -9,6 +9,7 @@ import type {TranslationPaths} from '@src/languages/types'; import type {OnyxValues} from '@src/ONYXKEYS'; import ONYXKEYS from '@src/ONYXKEYS'; import type {BankAccountList, Card, CardFeeds, CardList, CompanyCardFeed, PersonalDetailsList, WorkspaceCardsList} from '@src/types/onyx'; +import type {CardFeedData} from '@src/types/onyx/CardFeeds'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; import localeCompare from './LocaleCompare'; @@ -226,6 +227,10 @@ function getCardFeedIcon(cardFeed: CompanyCardFeed | typeof CONST.EXPENSIFY_CARD return Illustrations.AmexCompanyCards; } +function removeExpensifyCardFromCompanyCards(companyCards: Record) { + return Object.fromEntries(Object.entries(companyCards).filter(([key]) => key !== CONST.EXPENSIFY_CARD.BANK)); +} + function getCardFeedName(feedType: CompanyCardFeed): string { const feedNamesMapping = { [CONST.COMPANY_CARD.FEED_BANK_NAME.VISA]: 'Visa', @@ -293,7 +298,7 @@ const getCorrectStepForSelectedBank = (selectedBank: ValueOf, cardFeeds: OnyxEntry): CompanyCardFeed { - const defaultFeed = Object.keys(cardFeeds?.settings?.companyCards ?? {}).at(0) as CompanyCardFeed; + const defaultFeed = Object.keys(removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards ?? {})).at(0) as CompanyCardFeed; return lastSelectedFeed ?? defaultFeed; } @@ -318,4 +323,5 @@ export { getBankCardDetailsImage, getSelectedFeed, getCorrectStepForSelectedBank, + removeExpensifyCardFromCompanyCards, }; diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx index 0bc44a1d2298..c3a6e1698134 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx @@ -15,6 +15,7 @@ import useNetwork from '@hooks/useNetwork'; import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as CardUtils from '@libs/CardUtils'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {FullScreenNavigatorParamList} from '@libs/Navigation/types'; @@ -126,7 +127,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro subtitleTranslationKey: 'workspace.moreFeatures.companyCards.subtitle', isActive: policy?.areCompanyCardsEnabled ?? false, pendingAction: policy?.pendingFields?.areCompanyCardsEnabled, - disabled: !isEmptyObject(cardFeeds?.settings?.companyCards), + disabled: !isEmptyObject(CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards ?? {})), action: (isEnabled: boolean) => { if (!policyID) { return; diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx index a6f9599c18d9..88fbfad550ec 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx @@ -41,8 +41,9 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS const [cardFeeds] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`); const [lastSelectedFeed] = useOnyx(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${policyID}`); const selectedFeed = CardUtils.getSelectedFeed(lastSelectedFeed, cardFeeds); + const availableCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards ?? {}); - const feeds: CardFeedListItem[] = (Object.keys(cardFeeds?.settings?.companyCards ?? {}) as CompanyCardFeed[]).map((feed) => ({ + const feeds: CardFeedListItem[] = (Object.keys(availableCards) as CompanyCardFeed[]).map((feed) => ({ value: feed, text: cardFeeds?.settings?.companyCardNicknames?.[feed] ?? CardUtils.getCardFeedName(feed), keyForList: feed, diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index 4d3e5a347266..015b8a228456 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -35,7 +35,7 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) { const [cardsList] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`); const isLoading = !cardFeeds || !!(cardFeeds.isLoading && !cardFeeds.settings); - const companyCards = cardFeeds?.settings?.companyCards ?? {}; + const companyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards ?? {}); const selectedCompanyCard = companyCards[selectedFeed ?? ''] ?? null; const isNoFeed = !selectedCompanyCard; const isPending = !!selectedCompanyCard?.pending; diff --git a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx index ef5c51927a9b..9b175b374353 100644 --- a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx @@ -37,15 +37,11 @@ function CardSelectionStep({feed, policyID}: CardSelectionStepProps) { const styles = useThemeStyles(); const {environmentURL} = useEnvironment(); const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD); - const [list] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${feed}`); + const [cardFeeds] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`); + const cardList = cardFeeds?.settings?.oAuthAccountDetails?.[feed]?.accountList ?? []; const isEditing = assignCard?.isEditing; const assignee = assignCard?.data?.email ?? ''; - const {cardList, ...cards} = list ?? {}; - // We need to filter out cards which already has been assigned - const filteredCardList = Object.fromEntries( - Object.entries(cardList ?? {}).filter(([cardNumber]) => !Object.values(cards).find((card) => card.lastFourPAN && cardNumber.endsWith(card.lastFourPAN))), - ); const [cardSelected, setCardSelected] = useState(assignCard?.data?.encryptedCardNumber ?? ''); const [shouldShowError, setShouldShowError] = useState(false); @@ -72,10 +68,7 @@ function CardSelectionStep({feed, policyID}: CardSelectionStepProps) { return; } - const cardName = - Object.entries(filteredCardList) - .find(([, encryptedCardNumber]) => encryptedCardNumber === cardSelected) - ?.at(0) ?? ''; + const cardName = cardList.find((encryptedCardNumber) => encryptedCardNumber === cardSelected)?.at(0) ?? ''; CompanyCards.setAssignCardStepAndData({ currentStep: isEditing ? CONST.COMPANY_CARD.STEP.CONFIRMATION : CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE, @@ -84,10 +77,10 @@ function CardSelectionStep({feed, policyID}: CardSelectionStepProps) { }); }; - const cardListOptions = Object.entries(filteredCardList).map(([cardNumber, encryptedCardNumber]) => ({ + const cardListOptions = cardList.map((encryptedCardNumber) => ({ keyForList: encryptedCardNumber, value: encryptedCardNumber, - text: cardNumber, + text: encryptedCardNumber, isSelected: cardSelected === encryptedCardNumber, leftElement: ( { if (!selectedFeed) { @@ -78,7 +79,7 @@ function WorkspaceMemberNewCardPage({route, personalDetails}: WorkspaceMemberNew setShouldShowError(false); }; - const companyCardFeeds: CardFeedListItem[] = (Object.keys(cardFeeds?.settings?.companyCards ?? {}) as CompanyCardFeed[]).map((key) => ({ + const companyCardFeeds: CardFeedListItem[] = (Object.keys(availableCompanyCards) as CompanyCardFeed[]).map((key) => ({ value: key, text: cardFeeds?.settings?.companyCardNicknames?.[key] ?? CardUtils.getCardFeedName(key), keyForList: key, diff --git a/src/types/onyx/CardFeeds.ts b/src/types/onyx/CardFeeds.ts index 10938f710b5c..6a8592a7a9f6 100644 --- a/src/types/onyx/CardFeeds.ts +++ b/src/types/onyx/CardFeeds.ts @@ -48,6 +48,27 @@ type CardFeeds = { /** Company cards feeds */ companyCards: Record; + + /** + * Account details + */ + oAuthAccountDetails: Record< + ValueOf, + { + /** + * List of accounts + */ + accountList: string[]; + /** + * Credentials info + */ + credentials: string; + /** + * Expiration number + */ + expiration: number; + } + >; }; /** Whether we are loading the data via the API */ From 21ebfb3cfeeadb969bf7ed3855d9061dd3f62c5b Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Thu, 31 Oct 2024 15:55:31 +0200 Subject: [PATCH 2/6] add earlier return --- src/libs/CardUtils.ts | 7 +++++-- src/pages/workspace/WorkspaceMoreFeaturesPage.tsx | 2 +- .../companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx | 2 +- .../workspace/companyCards/WorkspaceCompanyCardsPage.tsx | 2 +- src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index c6f9e6b7d8a6..80b784a162cf 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -227,7 +227,10 @@ function getCardFeedIcon(cardFeed: CompanyCardFeed | typeof CONST.EXPENSIFY_CARD return Illustrations.AmexCompanyCards; } -function removeExpensifyCardFromCompanyCards(companyCards: Record) { +function removeExpensifyCardFromCompanyCards(companyCards?: Record) { + if (!companyCards) { + return {}; + } return Object.fromEntries(Object.entries(companyCards).filter(([key]) => key !== CONST.EXPENSIFY_CARD.BANK)); } @@ -298,7 +301,7 @@ const getCorrectStepForSelectedBank = (selectedBank: ValueOf, cardFeeds: OnyxEntry): CompanyCardFeed { - const defaultFeed = Object.keys(removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards ?? {})).at(0) as CompanyCardFeed; + const defaultFeed = Object.keys(removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards)).at(0) as CompanyCardFeed; return lastSelectedFeed ?? defaultFeed; } diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx index c3a6e1698134..1f2f46be6a4a 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx @@ -127,7 +127,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro subtitleTranslationKey: 'workspace.moreFeatures.companyCards.subtitle', isActive: policy?.areCompanyCardsEnabled ?? false, pendingAction: policy?.pendingFields?.areCompanyCardsEnabled, - disabled: !isEmptyObject(CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards ?? {})), + disabled: !isEmptyObject(CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards)), action: (isEnabled: boolean) => { if (!policyID) { return; diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx index 88fbfad550ec..684ee0660d28 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx @@ -41,7 +41,7 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS const [cardFeeds] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`); const [lastSelectedFeed] = useOnyx(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${policyID}`); const selectedFeed = CardUtils.getSelectedFeed(lastSelectedFeed, cardFeeds); - const availableCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards ?? {}); + const availableCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards); const feeds: CardFeedListItem[] = (Object.keys(availableCards) as CompanyCardFeed[]).map((feed) => ({ value: feed, diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index 015b8a228456..1ea431b170cb 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -35,7 +35,7 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) { const [cardsList] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`); const isLoading = !cardFeeds || !!(cardFeeds.isLoading && !cardFeeds.settings); - const companyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards ?? {}); + const companyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards); const selectedCompanyCard = companyCards[selectedFeed ?? ''] ?? null; const isNoFeed = !selectedCompanyCard; const isPending = !!selectedCompanyCard?.pending; diff --git a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx index 17456bceed5a..9bee3108c7e5 100644 --- a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx @@ -46,7 +46,7 @@ function WorkspaceMemberNewCardPage({route, personalDetails}: WorkspaceMemberNew const accountID = Number(route.params.accountID); const memberLogin = personalDetails?.[accountID]?.login ?? ''; - const availableCompanyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards ?? {}); + const availableCompanyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards); const handleSubmit = () => { if (!selectedFeed) { From 83dd5136c4cede1d0c730ae0b821ee898aac158f Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Thu, 31 Oct 2024 15:59:36 +0200 Subject: [PATCH 3/6] update card name --- .../workspace/companyCards/assignCard/CardSelectionStep.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx index 9b175b374353..b53125f5d48e 100644 --- a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx @@ -68,11 +68,9 @@ function CardSelectionStep({feed, policyID}: CardSelectionStepProps) { return; } - const cardName = cardList.find((encryptedCardNumber) => encryptedCardNumber === cardSelected)?.at(0) ?? ''; - CompanyCards.setAssignCardStepAndData({ currentStep: isEditing ? CONST.COMPANY_CARD.STEP.CONFIRMATION : CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE, - data: {encryptedCardNumber: cardSelected, cardName}, + data: {encryptedCardNumber: cardSelected, cardName: cardSelected}, isEditing: false, }); }; From 000e44d98d0e2125cd4134420688d33cf95417ca Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Thu, 31 Oct 2024 16:24:49 +0200 Subject: [PATCH 4/6] update comments --- src/types/onyx/CardFeeds.ts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/types/onyx/CardFeeds.ts b/src/types/onyx/CardFeeds.ts index 6a8592a7a9f6..ce06ed076a15 100644 --- a/src/types/onyx/CardFeeds.ts +++ b/src/types/onyx/CardFeeds.ts @@ -49,23 +49,17 @@ type CardFeeds = { /** Company cards feeds */ companyCards: Record; - /** - * Account details - */ + /** Account details */ oAuthAccountDetails: Record< ValueOf, { - /** - * List of accounts - */ + /** List of accounts */ accountList: string[]; - /** - * Credentials info - */ + + /** Credentials info */ credentials: string; - /** - * Expiration number - */ + + /** Expiration number */ expiration: number; } >; From 94bc81b907ae4bba155cbbfa3b7a22a2fab2f725 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Thu, 31 Oct 2024 17:56:37 +0200 Subject: [PATCH 5/6] combine v1 and v2 --- ...WorkspaceCompanyCardsListHeaderButtons.tsx | 1 - .../assignCard/CardSelectionStep.tsx | 45 +++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx index 4b8f34897076..93131ca8ce0f 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx @@ -78,7 +78,6 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp