From fd029a880b93fcee56509cf76065edd8b8a6a249 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Wed, 20 Nov 2024 21:35:58 +0700 Subject: [PATCH 01/12] fix: remove unreachable return --- .../workspace/companyCards/assignCard/AssignCardFeedPage.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx index 20c51b882054..1e75ee15abce 100644 --- a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx +++ b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx @@ -52,8 +52,6 @@ function AssignCardFeedPage({route, policy}: AssignCardFeedPageProps) { default: return ; } - - return ; } export default withPolicyAndFullscreenLoading(AssignCardFeedPage); From 1cd6d197734009e6744a24740b03c7991aaa1f0a Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Thu, 21 Nov 2024 15:40:32 +0700 Subject: [PATCH 02/12] feat: skip assignee step when only one workspace member --- ...WorkspaceCompanyCardsListHeaderButtons.tsx | 22 ++++++++++++++++++- .../assignCard/AssignCardFeedPage.tsx | 7 +----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx index 031ac309e155..b2e707170370 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx @@ -16,9 +16,12 @@ import * as CardUtils from '@libs/CardUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import variables from '@styles/variables'; +import * as CompanyCards from '@userActions/CompanyCards'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {CompanyCardFeed} from '@src/types/onyx'; +import type {AssignCardData, AssignCardStep} from '@src/types/onyx/AssignCard'; type WorkspaceCompanyCardsListHeaderButtonsProps = { /** Current policy id */ @@ -41,6 +44,23 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp const isCustomFeed = CardUtils.isCustomFeed(selectedFeed); const companyFeeds = CardUtils.getCompanyFeeds(cardFeeds); const currentFeedData = companyFeeds?.[selectedFeed]; + const policy = PolicyUtils.getPolicy(policyID); + + const handleAssignCard = () => { + const data: Partial = { + bankName: selectedFeed, + }; + + let currentStep: AssignCardStep = CONST.COMPANY_CARD.STEP.ASSIGNEE; + + if (Object.keys(policy?.employeeList ?? {}).length === 1) { + data.email = Object.keys(policy?.employeeList ?? {}).at(0); + currentStep = CONST.COMPANY_CARD.STEP.CARD; + } + + CompanyCards.setAssignCardStepAndData({data, currentStep}); + Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed)); + }; return ( Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed))} + onPress={handleAssignCard} icon={Expensicons.Plus} text={translate('workspace.companyCards.assignCard')} style={shouldChangeLayout && styles.flex1} diff --git a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx index 1e75ee15abce..ad1109f665f0 100644 --- a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx +++ b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx @@ -1,10 +1,9 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import React, {useEffect} from 'react'; +import React from 'react'; import {useOnyx} from 'react-native-onyx'; import type {SettingsNavigatorParamList} from '@navigation/types'; import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading'; import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading'; -import * as CompanyCards from '@userActions/CompanyCards'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; @@ -24,10 +23,6 @@ function AssignCardFeedPage({route, policy}: AssignCardFeedPageProps) { const backTo = route.params?.backTo; const policyID = policy?.id ?? '-1'; - useEffect(() => { - CompanyCards.setAssignCardStepAndData({data: {bankName: feed}}); - }, [feed]); - switch (currentStep) { case CONST.COMPANY_CARD.STEP.ASSIGNEE: return ; From 2396fc07d6d977f2dc8cd2fe2d46a1e8a07ddf90 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Thu, 21 Nov 2024 15:48:39 +0700 Subject: [PATCH 03/12] feat: skip the card selection step if only one card available --- .../companyCards/assignCard/AssigneeStep.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx index e8e8c81cba07..d09d8a51b301 100644 --- a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx @@ -35,6 +35,14 @@ function AssigneeStep({policy}: AssigneeStepProps) { const styles = useThemeStyles(); const {isOffline} = useNetwork(); const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD); + const workspaceAccountID = PolicyUtils.getWorkspaceAccountID(policy?.id ?? '-1'); + + const [list] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${assignCard?.data?.bankName ?? ''}`); + 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 isEditing = assignCard?.isEditing; @@ -57,8 +65,10 @@ function AssigneeStep({policy}: AssigneeStepProps) { const personalDetail = PersonalDetailsUtils.getPersonalDetailByEmail(selectedMember); const memberName = personalDetail?.firstName ? personalDetail.firstName : personalDetail?.login; + const nextStep = Object.keys(filteredCardList).length === 1 ? CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE : CONST.COMPANY_CARD.STEP.CARD; + CompanyCards.setAssignCardStepAndData({ - currentStep: isEditing ? CONST.COMPANY_CARD.STEP.CONFIRMATION : CONST.COMPANY_CARD.STEP.CARD, + currentStep: isEditing ? CONST.COMPANY_CARD.STEP.CONFIRMATION : nextStep, data: { email: selectedMember, cardName: `${memberName}'s card`, @@ -69,7 +79,10 @@ function AssigneeStep({policy}: AssigneeStepProps) { const handleBackButtonPress = () => { if (isEditing) { - CompanyCards.setAssignCardStepAndData({currentStep: CONST.COMPANY_CARD.STEP.CONFIRMATION, isEditing: false}); + CompanyCards.setAssignCardStepAndData({ + currentStep: CONST.COMPANY_CARD.STEP.CONFIRMATION, + isEditing: false, + }); return; } Navigation.goBack(); From d1b6ef5dd4ade301e6828a65968788f75d3de1c4 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Thu, 21 Nov 2024 16:19:57 +0700 Subject: [PATCH 04/12] feat: skip card selection step when only one card --- ...WorkspaceCompanyCardsListHeaderButtons.tsx | 13 ++++++++++ .../members/WorkspaceMemberNewCardPage.tsx | 24 +++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx index b2e707170370..0f6f93b63508 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx @@ -46,6 +46,13 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp const currentFeedData = companyFeeds?.[selectedFeed]; const policy = PolicyUtils.getPolicy(policyID); + const [list] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`); + 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 handleAssignCard = () => { const data: Partial = { bankName: selectedFeed, @@ -58,6 +65,12 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp currentStep = CONST.COMPANY_CARD.STEP.CARD; } + if (Object.keys(filteredCardList).length === 1) { + currentStep = CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE; + data.cardNumber = Object.keys(filteredCardList).at(0); + data.encryptedCardNumber = Object.values(filteredCardList).at(0); + } + CompanyCards.setAssignCardStepAndData({data, currentStep}); Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed)); }; diff --git a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx index 79dcdd37ce1f..4b1ab84ce732 100644 --- a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx @@ -26,6 +26,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {CompanyCardFeed} from '@src/types/onyx'; +import type {AssignCardData, AssignCardStep} from '@src/types/onyx/AssignCard'; type CardFeedListItem = ListItem & { /** Card feed value */ @@ -49,6 +50,13 @@ function WorkspaceMemberNewCardPage({route, personalDetails}: WorkspaceMemberNew const memberLogin = personalDetails?.[accountID]?.login ?? ''; const availableCompanyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds); + const [list] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`); + 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 handleSubmit = () => { if (!selectedFeed) { setShouldShowError(true); @@ -64,11 +72,19 @@ function WorkspaceMemberNewCardPage({route, personalDetails}: WorkspaceMemberNew }); Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.getRoute(policyID, ROUTES.WORKSPACE_MEMBER_DETAILS.getRoute(policyID, accountID))); } else { + const data: Partial = { + email: memberLogin, + }; + let currentStep: AssignCardStep = CONST.COMPANY_CARD.STEP.CARD; + + if (Object.keys(filteredCardList).length === 1) { + currentStep = CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE; + data.cardNumber = Object.keys(filteredCardList).at(0); + data.encryptedCardNumber = Object.values(filteredCardList).at(0); + } CompanyCards.setAssignCardStepAndData({ - currentStep: CONST.COMPANY_CARD.STEP.CARD, - data: { - email: memberLogin, - }, + currentStep, + data, isEditing: false, }); Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed, ROUTES.WORKSPACE_MEMBER_DETAILS.getRoute(policyID, accountID))); From 47a9f1239714678e0403baaf7dccdc4b3f9714fc Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Thu, 21 Nov 2024 16:40:36 +0700 Subject: [PATCH 05/12] chore: code cleanup --- src/libs/CardUtils.ts | 7 +++++++ .../WorkspaceCompanyCardsListHeaderButtons.tsx | 6 +----- .../workspace/companyCards/assignCard/AssigneeStep.tsx | 7 ++----- .../companyCards/assignCard/CardSelectionStep.tsx | 7 ++----- src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx | 6 +----- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index 77aeb8e0ecc3..00437bd76248 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -352,6 +352,12 @@ function getSelectedFeed(lastSelectedFeed: OnyxEntry, cardFeeds return lastSelectedFeed ?? defaultFeed; } +function getFilteredCardList(list?: WorkspaceCardsList) { + const {cardList, ...cards} = list ?? {}; + // We need to filter out cards which already has been assigned + return Object.fromEntries(Object.entries(cardList ?? {}).filter(([cardNumber]) => !Object.values(cards).find((card) => card.lastFourPAN && cardNumber.endsWith(card.lastFourPAN)))); +} + export { isExpensifyCard, isCorporateCard, @@ -378,4 +384,5 @@ export { getCorrectStepForSelectedBank, getCustomOrFormattedFeedName, removeExpensifyCardFromCompanyCards, + getFilteredCardList, }; diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx index 0f6f93b63508..3e778c870137 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx @@ -47,11 +47,7 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp const policy = PolicyUtils.getPolicy(policyID); const [list] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`); - 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 filteredCardList = CardUtils.getFilteredCardList(list); const handleAssignCard = () => { const data: Partial = { diff --git a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx index d09d8a51b301..0bcdbdfaeb29 100644 --- a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx @@ -13,6 +13,7 @@ import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as CardUtils from '@libs/CardUtils'; import {formatPhoneNumber} from '@libs/LocalePhoneNumber'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; @@ -38,11 +39,7 @@ function AssigneeStep({policy}: AssigneeStepProps) { const workspaceAccountID = PolicyUtils.getWorkspaceAccountID(policy?.id ?? '-1'); const [list] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${assignCard?.data?.bankName ?? ''}`); - 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 filteredCardList = CardUtils.getFilteredCardList(list); const isEditing = assignCard?.isEditing; diff --git a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx index 4b07e7a220b8..47bcbbd3ed6d 100644 --- a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx @@ -45,11 +45,8 @@ function CardSelectionStep({feed, policyID}: CardSelectionStepProps) { const isEditing = assignCard?.isEditing; const assigneeDisplayName = PersonalDetailsUtils.getPersonalDetailByEmail(assignCard?.data?.email ?? '')?.displayName ?? ''; - 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 filteredCardList = CardUtils.getFilteredCardList(list); + const [cardSelected, setCardSelected] = useState(assignCard?.data?.encryptedCardNumber ?? ''); const [shouldShowError, setShouldShowError] = useState(false); diff --git a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx index 4b1ab84ce732..ab2914d32600 100644 --- a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx @@ -51,11 +51,7 @@ function WorkspaceMemberNewCardPage({route, personalDetails}: WorkspaceMemberNew const availableCompanyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds); const [list] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`); - 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 filteredCardList = CardUtils.getFilteredCardList(list); const handleSubmit = () => { if (!selectedFeed) { From 6ee355137fdb61183eff7b26df53c6ee4def400e Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Thu, 21 Nov 2024 17:05:43 +0700 Subject: [PATCH 06/12] feat: create util functions --- src/libs/CardUtils.ts | 6 ++++++ .../companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx | 2 +- .../workspace/companyCards/assignCard/AssigneeStep.tsx | 2 +- src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx | 2 +- src/types/onyx/Card.ts | 5 ++++- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index 00437bd76248..f1f28ad348c8 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 {FilteredCardList} from '@src/types/onyx/Card'; import type {CompanyCardNicknames, CompanyFeeds} from '@src/types/onyx/CardFeeds'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; @@ -358,6 +359,10 @@ function getFilteredCardList(list?: WorkspaceCardsList) { return Object.fromEntries(Object.entries(cardList ?? {}).filter(([cardNumber]) => !Object.values(cards).find((card) => card.lastFourPAN && cardNumber.endsWith(card.lastFourPAN)))); } +function hasOnlyOneCardToAssign(list: FilteredCardList) { + return !!(Object.keys(list).length === 1); +} + export { isExpensifyCard, isCorporateCard, @@ -385,4 +390,5 @@ export { getCustomOrFormattedFeedName, removeExpensifyCardFromCompanyCards, getFilteredCardList, + hasOnlyOneCardToAssign, }; diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx index 3e778c870137..c220511dff8a 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx @@ -61,7 +61,7 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp currentStep = CONST.COMPANY_CARD.STEP.CARD; } - if (Object.keys(filteredCardList).length === 1) { + if (CardUtils.hasOnlyOneCardToAssign(filteredCardList)) { currentStep = CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE; data.cardNumber = Object.keys(filteredCardList).at(0); data.encryptedCardNumber = Object.values(filteredCardList).at(0); diff --git a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx index 0bcdbdfaeb29..1b2819fc380c 100644 --- a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx @@ -62,7 +62,7 @@ function AssigneeStep({policy}: AssigneeStepProps) { const personalDetail = PersonalDetailsUtils.getPersonalDetailByEmail(selectedMember); const memberName = personalDetail?.firstName ? personalDetail.firstName : personalDetail?.login; - const nextStep = Object.keys(filteredCardList).length === 1 ? CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE : CONST.COMPANY_CARD.STEP.CARD; + const nextStep = CardUtils.hasOnlyOneCardToAssign(filteredCardList) ? CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE : CONST.COMPANY_CARD.STEP.CARD; CompanyCards.setAssignCardStepAndData({ currentStep: isEditing ? CONST.COMPANY_CARD.STEP.CONFIRMATION : nextStep, diff --git a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx index ab2914d32600..e9ecf11a4dcd 100644 --- a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx @@ -73,7 +73,7 @@ function WorkspaceMemberNewCardPage({route, personalDetails}: WorkspaceMemberNew }; let currentStep: AssignCardStep = CONST.COMPANY_CARD.STEP.CARD; - if (Object.keys(filteredCardList).length === 1) { + if (CardUtils.hasOnlyOneCardToAssign(filteredCardList)) { currentStep = CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE; data.cardNumber = Object.keys(filteredCardList).at(0); data.encryptedCardNumber = Object.values(filteredCardList).at(0); diff --git a/src/types/onyx/Card.ts b/src/types/onyx/Card.ts index 8894db2723d1..7d3d252dd86b 100644 --- a/src/types/onyx/Card.ts +++ b/src/types/onyx/Card.ts @@ -180,5 +180,8 @@ type WorkspaceCardsList = Record & { cardList?: Record; }; +/** Card list with only available card */ +type FilteredCardList = Record; + export default Card; -export type {ExpensifyCardDetails, CardList, IssueNewCard, IssueNewCardStep, IssueNewCardData, WorkspaceCardsList, CardLimitType}; +export type {ExpensifyCardDetails, CardList, IssueNewCard, IssueNewCardStep, IssueNewCardData, WorkspaceCardsList, CardLimitType, FilteredCardList}; From 824ad5b5f44f96d28e86662042313371013735fc Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Thu, 21 Nov 2024 17:15:53 +0700 Subject: [PATCH 07/12] fix: minor fix --- src/libs/CardUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index f1f28ad348c8..46461edb5525 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -360,7 +360,7 @@ function getFilteredCardList(list?: WorkspaceCardsList) { } function hasOnlyOneCardToAssign(list: FilteredCardList) { - return !!(Object.keys(list).length === 1); + return Object.keys(list).length === 1; } export { From d71e7f1cd473598d5470fda5d9b1d12e335ae15e Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Thu, 21 Nov 2024 17:22:47 +0700 Subject: [PATCH 08/12] fix: minor fix --- .../WorkspaceCompanyCardsListHeaderButtons.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx index c220511dff8a..1e36881a68a0 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx @@ -59,12 +59,12 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp if (Object.keys(policy?.employeeList ?? {}).length === 1) { data.email = Object.keys(policy?.employeeList ?? {}).at(0); currentStep = CONST.COMPANY_CARD.STEP.CARD; - } - if (CardUtils.hasOnlyOneCardToAssign(filteredCardList)) { - currentStep = CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE; - data.cardNumber = Object.keys(filteredCardList).at(0); - data.encryptedCardNumber = Object.values(filteredCardList).at(0); + if (CardUtils.hasOnlyOneCardToAssign(filteredCardList)) { + currentStep = CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE; + data.cardNumber = Object.keys(filteredCardList).at(0); + data.encryptedCardNumber = Object.values(filteredCardList).at(0); + } } CompanyCards.setAssignCardStepAndData({data, currentStep}); From 5c82d2c0cdb6dfdb0ed30c2a98a810054459d1a3 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Fri, 22 Nov 2024 10:21:00 +0700 Subject: [PATCH 09/12] fix: clear the data when closing the flow --- .../companyCards/assignCard/AssignCardFeedPage.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx index ad1109f665f0..2fe757c4e36f 100644 --- a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx +++ b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx @@ -1,9 +1,10 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import React from 'react'; +import React, {useEffect} from 'react'; import {useOnyx} from 'react-native-onyx'; import type {SettingsNavigatorParamList} from '@navigation/types'; import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading'; import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading'; +import * as CompanyCards from '@userActions/CompanyCards'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; @@ -23,6 +24,12 @@ function AssignCardFeedPage({route, policy}: AssignCardFeedPageProps) { const backTo = route.params?.backTo; const policyID = policy?.id ?? '-1'; + useEffect(() => { + return () => { + CompanyCards.clearAssignCardStepAndData(); + }; + }, []); + switch (currentStep) { case CONST.COMPANY_CARD.STEP.ASSIGNEE: return ; From d9dd7a3f5895fd090c30a9d67626839076f05c46 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Fri, 22 Nov 2024 10:36:40 +0700 Subject: [PATCH 10/12] fix: add missing bank name --- src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx index e9ecf11a4dcd..e8c634a30f93 100644 --- a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx @@ -70,6 +70,7 @@ function WorkspaceMemberNewCardPage({route, personalDetails}: WorkspaceMemberNew } else { const data: Partial = { email: memberLogin, + bankName: selectedFeed, }; let currentStep: AssignCardStep = CONST.COMPANY_CARD.STEP.CARD; From 4137f2fcc4d0fce90b29437dcd9b304fc69376e8 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Fri, 22 Nov 2024 11:18:25 +0700 Subject: [PATCH 11/12] fix: add card name --- .../WorkspaceCompanyCardsListHeaderButtons.tsx | 7 ++++++- src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx index 1e36881a68a0..b2f6a993a18b 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx @@ -13,6 +13,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import * as CardUtils from '@libs/CardUtils'; +import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import variables from '@styles/variables'; @@ -57,7 +58,11 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp let currentStep: AssignCardStep = CONST.COMPANY_CARD.STEP.ASSIGNEE; if (Object.keys(policy?.employeeList ?? {}).length === 1) { - data.email = Object.keys(policy?.employeeList ?? {}).at(0); + const userEmail = Object.keys(policy?.employeeList ?? {}).at(0) ?? ''; + data.email = userEmail; + const personalDetails = PersonalDetailsUtils.getPersonalDetailByEmail(userEmail); + const memberName = personalDetails?.firstName ? personalDetails.firstName : personalDetails?.login; + data.cardName = `${memberName}'s card`; currentStep = CONST.COMPANY_CARD.STEP.CARD; if (CardUtils.hasOnlyOneCardToAssign(filteredCardList)) { diff --git a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx index e8c634a30f93..c5415521cd5c 100644 --- a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx @@ -48,6 +48,7 @@ function WorkspaceMemberNewCardPage({route, personalDetails}: WorkspaceMemberNew const accountID = Number(route.params.accountID); const memberLogin = personalDetails?.[accountID]?.login ?? ''; + const memberName = personalDetails?.[accountID]?.firstName ? personalDetails?.[accountID]?.firstName : personalDetails?.[accountID]?.login; const availableCompanyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds); const [list] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`); @@ -71,6 +72,7 @@ function WorkspaceMemberNewCardPage({route, personalDetails}: WorkspaceMemberNew const data: Partial = { email: memberLogin, bankName: selectedFeed, + cardName: `${memberName}'s card`, }; let currentStep: AssignCardStep = CONST.COMPANY_CARD.STEP.CARD; From 2570632ce5be0391db55a9b1c9f55a074361564f Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Fri, 22 Nov 2024 11:52:22 +0700 Subject: [PATCH 12/12] fix: delay navigation --- .../companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx | 2 +- src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx index b2f6a993a18b..22b17496040e 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx @@ -73,7 +73,7 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp } CompanyCards.setAssignCardStepAndData({data, currentStep}); - Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed)); + Navigation.setNavigationActionToMicrotaskQueue(() => Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed))); }; return ( diff --git a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx index c5415521cd5c..21e45516c95d 100644 --- a/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberNewCardPage.tsx @@ -86,7 +86,9 @@ function WorkspaceMemberNewCardPage({route, personalDetails}: WorkspaceMemberNew data, isEditing: false, }); - Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed, ROUTES.WORKSPACE_MEMBER_DETAILS.getRoute(policyID, accountID))); + Navigation.setNavigationActionToMicrotaskQueue(() => + Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed, ROUTES.WORKSPACE_MEMBER_DETAILS.getRoute(policyID, accountID))), + ); } };