diff --git a/src/ROUTES.ts b/src/ROUTES.ts index cc270d6e8751..ed8582228761 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -2198,10 +2198,7 @@ const ROUTES = { route: 'workspaces/:policyID/company-cards/:feed/assign-card/:cardID/assignee', getRoute: (params: WorkspaceCompanyCardsAssignCardParams, backTo?: string) => // eslint-disable-next-line no-restricted-syntax -- Legacy route generation - getUrlWithBackToParam( - `workspaces/${params.policyID}/company-cards/${encodeURIComponent(params.feed)}/assign-card/${encodeURIComponent(params.cardID)}/assignee`, - backTo, - ), + getUrlWithBackToParam(`workspaces/${params.policyID}/company-cards/${encodeURIComponent(params.feed)}/assign-card/${encodeURIComponent(params.cardID)}/assignee`, backTo), }, WORKSPACE_COMPANY_CARDS_ASSIGN_CARD_CARD_SELECTION: { route: 'workspaces/:policyID/company-cards/:feed/assign-card/:cardID/card-selection', @@ -2222,10 +2219,7 @@ const ROUTES = { route: 'workspaces/:policyID/company-cards/:feed/assign-card/:cardID/confirmation', getRoute: (params: WorkspaceCompanyCardsAssignCardParams, backTo?: string) => // eslint-disable-next-line no-restricted-syntax -- Legacy route generation - getUrlWithBackToParam( - `workspaces/${params.policyID}/company-cards/${encodeURIComponent(params.feed)}/assign-card/${encodeURIComponent(params.cardID)}/confirmation`, - backTo, - ), + getUrlWithBackToParam(`workspaces/${params.policyID}/company-cards/${encodeURIComponent(params.feed)}/assign-card/${encodeURIComponent(params.cardID)}/confirmation`, backTo), }, WORKSPACE_COMPANY_CARDS_ASSIGN_CARD_INVITE_NEW_MEMBER: { route: 'workspaces/:policyID/company-cards/:feed/assign-card/:cardID/invite-new-member', diff --git a/src/components/Table/TableBody.tsx b/src/components/Table/TableBody.tsx index c7f5d7389126..f0069c3dd802 100644 --- a/src/components/Table/TableBody.tsx +++ b/src/components/Table/TableBody.tsx @@ -81,8 +81,10 @@ function TableBody({contentContainerStyle, ...props}: TableBodyProps) { ); return ( - // eslint-disable-next-line react/jsx-props-no-spreading - + data={filteredAndSortedData} ListEmptyComponent={isEmptyResult ? EmptyResultComponent : ListEmptyComponent} diff --git a/src/hooks/useAssignCard.ts b/src/hooks/useAssignCard.ts index 361270d58e62..601e0683b16a 100644 --- a/src/hooks/useAssignCard.ts +++ b/src/hooks/useAssignCard.ts @@ -149,7 +149,7 @@ function useAssignCard({selectedFeed, policyID, setShouldShowOfflineModal}: UseA setAssignCardStepAndData({data}); Navigation.setNavigationActionToMicrotaskQueue(() => { - const routeParams = {policyID, feed: selectedFeed, cardID: cardID ?? ''}; + const routeParams = {policyID, feed: selectedFeed, cardID}; switch (currentStep) { case CONST.COMPANY_CARD.STEP.PLAID_CONNECTION: diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 99d460af5870..48e21851dc4b 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -701,7 +701,8 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/companyCards/assignCard/AssignCardFeedPage').default, [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_ASSIGNEE]: () => require('../../../../pages/workspace/companyCards/assignCard/AssigneeStep').default, [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_CARD_SELECTION]: () => require('../../../../pages/workspace/companyCards/assignCard/CardSelectionStep').default, - [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_TRANSACTION_START_DATE]: () => require('../../../../pages/workspace/companyCards/assignCard/TransactionStartDateStep').default, + [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_TRANSACTION_START_DATE]: () => + require('../../../../pages/workspace/companyCards/assignCard/TransactionStartDateStep').default, [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_CARD_NAME]: () => require('../../../../pages/workspace/companyCards/assignCard/CardNameStep').default, [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_CONFIRMATION]: () => require('../../../../pages/workspace/companyCards/assignCard/ConfirmationStep').default, [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_INVITE_NEW_MEMBER]: () => require('../../../../pages/workspace/companyCards/assignCard/InviteNewMemberStep').default, diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsTableItem.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsTableItem.tsx index 45f4b7d41621..46f54f9db9ff 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsTableItem.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsTableItem.tsx @@ -97,7 +97,7 @@ function WorkspaceCompanyCardTableItem({ const companyCardFeedIcons = useCompanyCardFeedIcons(); const Expensicons = useMemoizedLazyExpensifyIcons(['ArrowRight']); - const cardFeedIcon = !plaidIconUrl && getCardFeedIcon(selectedFeed as CompanyCardFeed, illustrations, companyCardFeedIcons) : null; + const cardFeedIcon = !plaidIconUrl && getCardFeedIcon(selectedFeed as CompanyCardFeed, illustrations, companyCardFeedIcons); const {failedCompanyCardAssignment} = item; let {cardName, customCardName, cardholder, assignedCard, isAssigned, isCardDeleted} = item; diff --git a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx index af541bf18dba..d81f37f476f6 100644 --- a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx +++ b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx @@ -101,11 +101,7 @@ function AssignCardFeedPage({route, policy}: AssignCardFeedPageProps) { case CONST.COMPANY_CARD.STEP.CARD_NAME: return ; case CONST.COMPANY_CARD.STEP.CONFIRMATION: - return ( - - ); + return ; case CONST.COMPANY_CARD.STEP.INVITE_NEW_MEMBER: return ( ; @@ -32,8 +31,6 @@ function CardNameStep({route}: CardNameStepProps) { const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD, {canBeMissing: true}); const policyID = route.params.policyID; - const feed = route.params.feed; - const cardID = route.params.cardID; const data = assignCard?.data; diff --git a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx index d0ecdf263f7d..5228dbd9611b 100644 --- a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx @@ -30,7 +30,7 @@ import variables from '@styles/variables'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import SCREENS from '@src/SCREENS'; +import type SCREENS from '@src/SCREENS'; import type {CompanyCardFeedWithDomainID} from '@src/types/onyx'; type CardSelectionStepProps = PlatformStackScreenProps; diff --git a/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx b/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx index 0d34f101e7c0..fc95f9893916 100644 --- a/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx @@ -9,16 +9,13 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScrollView from '@components/ScrollView'; import Text from '@components/Text'; import useCardFeeds from '@hooks/useCardFeeds'; -import useInitial from '@hooks/useInitial'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; import usePolicy from '@hooks/usePolicy'; -import useRootNavigationState from '@hooks/useRootNavigationState'; import useThemeStyles from '@hooks/useThemeStyles'; import useWorkspaceAccountID from '@hooks/useWorkspaceAccountID'; import {getCompanyCardFeed, getDomainOrWorkspaceAccountID, getPlaidCountry, getPlaidInstitutionId, isSelectedFeedExpired, maskCardNumber} from '@libs/CardUtils'; -import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils'; @@ -28,7 +25,7 @@ import {assignWorkspaceCompanyCard, clearAssignCardStepAndData, setAddNewCompany import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import SCREENS from '@src/SCREENS'; +import type SCREENS from '@src/SCREENS'; import type {CompanyCardFeedWithDomainID, CurrencyList} from '@src/types/onyx'; import {getEmptyObject} from '@src/types/utils/EmptyObject'; @@ -43,9 +40,6 @@ function ConfirmationStep({route}: ConfirmationStepProps) { const {isOffline} = useNetwork(); const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD, {canBeMissing: false}); - const firstAssigneeEmail = useInitial(assignCard?.data?.email); - const shouldUseBackToParam = !firstAssigneeEmail || firstAssigneeEmail === assignCard?.data?.email; - const backTo = shouldUseBackToParam ? route.params?.backTo : undefined; const policy = usePolicy(policyID); const [countryByIp] = useOnyx(ONYXKEYS.COUNTRY, {canBeMissing: false}); const [currencyList = getEmptyObject()] = useOnyx(ONYXKEYS.CURRENCY_LIST, {canBeMissing: true}); @@ -64,23 +58,15 @@ function ConfirmationStep({route}: ConfirmationStepProps) { const cardholderEmail = data?.email ?? ''; const cardholderAccountID = cardholder?.accountID; - const currentFullScreenRoute = useRootNavigationState((state) => state?.routes?.findLast((route) => isFullScreenName(route.name))); - useEffect(() => { if (!assignCard?.isAssignmentFinished) { return; } - if (backTo) { - Navigation.goBack(backTo); - } else if (!shouldUseBackToParam && route.params?.backTo) { - Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(policyID), {forceReplace: true}); - } else { - Navigation.dismissModal(); - } + Navigation.dismissModal(); // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => clearAssignCardStepAndData()); - }, [assignCard?.isAssignmentFinished, backTo, policyID, shouldUseBackToParam, route.params?.backTo, currentFullScreenRoute?.state?.routes]); + }, [assignCard?.isAssignmentFinished]); const submit = () => { if (!policyID) { @@ -113,7 +99,7 @@ function ConfirmationStep({route}: ConfirmationStepProps) { switch (step) { case CONST.COMPANY_CARD.STEP.ASSIGNEE: - Navigation.goBack(); + Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD_ASSIGNEE.getRoute(routeParams)); break; case CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE: Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD_TRANSACTION_START_DATE.getRoute(routeParams)); @@ -121,11 +107,13 @@ function ConfirmationStep({route}: ConfirmationStepProps) { case CONST.COMPANY_CARD.STEP.CARD_NAME: Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD_CARD_NAME.getRoute(routeParams)); break; + default: + break; } }; const handleBackButtonPress = () => { - Navigation.goBack(); + Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD_ASSIGNEE.getRoute({policyID, feed, cardID})); }; return ( diff --git a/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx b/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx index ae20ae014ddd..3af12b6cf8a4 100644 --- a/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx @@ -13,12 +13,12 @@ import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavig import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import Navigation from '@navigation/Navigation'; import WorkspaceInviteMessageComponent from '@pages/workspace/members/WorkspaceInviteMessageComponent'; -import {clearInviteDraft} from '@userActions/Policy/Member'; import {setAssignCardStepAndData} from '@userActions/CompanyCards'; +import {clearInviteDraft} from '@userActions/Policy/Member'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import SCREENS from '@src/SCREENS'; +import type SCREENS from '@src/SCREENS'; import type {AssignCardData} from '@src/types/onyx/AssignCard'; type InviteeNewMemberStepProps = PlatformStackScreenProps & @@ -28,11 +28,10 @@ function InviteNewMemberStep({route, currentUserPersonalDetails}: InviteeNewMemb const {translate} = useLocalize(); const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD, {canBeMissing: true}); const [workspaceCardFeeds] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST, {canBeMissing: false}); - const isEditing = assignCard?.isEditing; const policyID = route.params.policyID; const feed = route.params.feed as CompanyCardFeedWithDomainID; const cardID = route.params.cardID; - const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {canBeMissing: true}); const [list] = useCardsList(feed); const [cardFeeds] = useCardFeeds(policy?.id); const filteredCardList = getFilteredCardList(list, cardFeeds?.[feed]?.accountList, workspaceCardFeeds); @@ -63,7 +62,7 @@ function InviteNewMemberStep({route, currentUserPersonalDetails}: InviteeNewMemb if (assignCard?.data?.encryptedCardNumber) { data.encryptedCardNumber = assignCard.data.encryptedCardNumber; data.cardNumber = assignCard.data.cardNumber; - data.startDate = assignCard?.data?.startDate ?? new Date().toISOString().split('T')[0]; + data.startDate = assignCard?.data?.startDate ?? new Date().toISOString().split('T').at(0); data.dateOption = assignCard?.data?.dateOption ?? CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.CUSTOM; setAssignCardStepAndData({ currentStep: CONST.COMPANY_CARD.STEP.CONFIRMATION, @@ -74,7 +73,7 @@ function InviteNewMemberStep({route, currentUserPersonalDetails}: InviteeNewMemb } else if (hasOnlyOneCardToAssign(filteredCardList)) { data.cardNumber = Object.keys(filteredCardList).at(0); data.encryptedCardNumber = Object.values(filteredCardList).at(0); - data.startDate = assignCard?.data?.startDate ?? new Date().toISOString().split('T')[0]; + data.startDate = assignCard?.data?.startDate ?? new Date().toISOString().split('T').at(0); data.dateOption = assignCard?.data?.dateOption ?? CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.CUSTOM; setAssignCardStepAndData({ currentStep: CONST.COMPANY_CARD.STEP.CONFIRMATION, diff --git a/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx b/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx index f7765080df8e..8086c60b08d2 100644 --- a/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx @@ -1,5 +1,4 @@ import {format, subDays} from 'date-fns'; -import {Str} from 'expensify-common'; import React, {useState} from 'react'; import {View} from 'react-native'; import Button from '@components/Button'; @@ -11,29 +10,19 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; -import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; -import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils'; import {isRequiredFulfilled} from '@libs/ValidationUtils'; import Navigation from '@navigation/Navigation'; import {setAssignCardStepAndData} from '@userActions/CompanyCards'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import SCREENS from '@src/SCREENS'; -function TransactionStartDateStep({route}: {route: PlatformStackRouteProp}) { +function TransactionStartDateStep() { const {translate} = useLocalize(); const styles = useThemeStyles(); - const policyID = route.params.policyID; - const feed = route.params.feed; - const cardID = route.params.cardID; - const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD, {canBeMissing: true}); const isEditing = assignCard?.isEditing; const data = assignCard?.data; - const assigneeDisplayName = Str.removeSMSDomain(getPersonalDetailByEmail(data?.email ?? '')?.displayName ?? ''); const [dateOptionSelected, setDateOptionSelected] = useState(data?.dateOption ?? CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.CUSTOM); const [errorText, setErrorText] = useState(''); @@ -96,7 +85,6 @@ function TransactionStartDateStep({route}: {route: PlatformStackRouteProp {translate('workspace.companyCards.startDateDescription')} diff --git a/src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx b/src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx index e39fa72b2deb..e09be4aec02f 100644 --- a/src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx +++ b/src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx @@ -23,16 +23,15 @@ import {clearDraftValues} from '@libs/actions/FormActions'; import {openExternalLink} from '@libs/actions/Link'; import {addMembersToWorkspace, clearWorkspaceInviteRoleDraft} from '@libs/actions/Policy/Member'; import {setWorkspaceInviteMessageDraft} from '@libs/actions/Policy/Policy'; -import {setAssignCardStepAndData} from '@userActions/CompanyCards'; -import {clearInviteDraft} from '@userActions/Policy/Member'; import getIsNarrowLayout from '@libs/getIsNarrowLayout'; import Navigation from '@libs/Navigation/Navigation'; import {getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils'; import {getDisplayNameOrDefault, getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils'; import {getMemberAccountIDsForWorkspace, goBackFromInvalidPolicy} from '@libs/PolicyUtils'; -import {getDefaultAvatarURL} from '@libs/UserAvatarUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import variables from '@styles/variables'; +import {setAssignCardStepAndData} from '@userActions/CompanyCards'; +import {clearInviteDraft} from '@userActions/Policy/Member'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import AccessOrNotFoundWrapper from '@src/pages/workspace/AccessOrNotFoundWrapper'; @@ -252,14 +251,14 @@ function WorkspaceInviteMessageComponent({ - {isInviteNewMemberStep && ( - - )} + {isInviteNewMemberStep && ( + + )} {shouldShowMemberNames && !isInviteNewMemberStep && ( ; +function isNameValuePairsObject(value: unknown): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + function WorkspaceMemberDetailsPage({personalDetails, policy, route}: WorkspaceMemberDetailsPageProps) { const policyID = route.params.policyID; const workspaceAccountID = policy?.workspaceAccountID ?? CONST.DEFAULT_NUMBER_ID; @@ -407,23 +409,26 @@ function WorkspaceMemberDetailsPage({personalDetails, policy, route}: WorkspaceM {memberCards.map((memberCard) => { const isCardDeleted = memberCard.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; const plaidUrl = getPlaidInstitutionIconUrl(memberCard?.bank); + const nameValuePairs = isNameValuePairsObject(memberCard.nameValuePairs) ? memberCard.nameValuePairs : null; + const unapprovedExpenseLimit = nameValuePairs?.unapprovedExpenseLimit; + const cardTitle = nameValuePairs?.cardTitle; return (