Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2698,6 +2698,7 @@ const CONST = {
STEP: {
ASSIGNEE: 'Assignee',
CARD: 'Card',
CARD_NAME: 'CardName',
TRANSACTION_START_DATE: 'TransactionStartDate',
CONFIRMATION: 'Confirmation',
},
Expand Down
1 change: 1 addition & 0 deletions src/libs/API/parameters/AssignCompanyCardParams.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
type AssignCompanyCardParams = {
policyID: string;
bankName: string;
cardName: string;
encryptedCardNumber: string;
email: string;
startDate: string;
Expand Down
2 changes: 1 addition & 1 deletion src/libs/CardUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ function getCompanyCardNumber(cardList: Record<string, string>, lastFourPAN?: st
return '';
}

return Object.keys(cardList).find((card) => card.endsWith(lastFourPAN)) ?? '';
return Object.keys(cardList).find((card) => card.endsWith(lastFourPAN)) ?? maskCard(lastFourPAN);
}

function getCardFeedIcon(cardFeed: CompanyCardFeed | typeof CONST.EXPENSIFY_CARD.BANK): IconAsset {
Expand Down
3 changes: 2 additions & 1 deletion src/libs/actions/CompanyCards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,15 @@ function assignWorkspaceCompanyCard(policyID: string, data?: Partial<AssignCardD
if (!data) {
return;
}
const {bankName = '', email = '', encryptedCardNumber = '', startDate = ''} = data;
const {bankName = '', email = '', encryptedCardNumber = '', startDate = '', cardName = ''} = data;
const assigneeDetails = PersonalDetailsUtils.getPersonalDetailByEmail(email);
const optimisticCardAssignedReportAction = ReportUtils.buildOptimisticCardAssignedReportAction(assigneeDetails?.accountID ?? -1);

const parameters: AssignCompanyCardParams = {
policyID,
bankName,
encryptedCardNumber,
cardName,
email,
startDate,
reportActionID: optimisticCardAssignedReportAction.reportActionID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type SCREENS from '@src/SCREENS';
import AssigneeStep from './AssigneeStep';
import CardNameStep from './CardNameStep';
import CardSelectionStep from './CardSelectionStep';
import ConfirmationStep from './ConfirmationStep';
import TransactionStartDateStep from './TransactionStartDateStep';
Expand Down Expand Up @@ -39,6 +40,8 @@ function AssignCardFeedPage({route, policy}: AssignCardFeedPageProps) {
);
case CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE:
return <TransactionStartDateStep />;
case CONST.COMPANY_CARD.STEP.CARD_NAME:
return <CardNameStep policyID={policyID} />;
case CONST.COMPANY_CARD.STEP.CONFIRMATION:
return (
<ConfirmationStep
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,15 @@ function AssigneeStep({policy}: AssigneeStepProps) {
setShouldShowError(true);
return;
}

const personalDetail = PersonalDetailsUtils.getPersonalDetailByEmail(selectedMember);
const memberName = personalDetail?.firstName ? personalDetail.firstName : personalDetail?.login;
Comment thread
mountiny marked this conversation as resolved.

CompanyCards.setAssignCardStepAndData({
currentStep: isEditing ? CONST.COMPANY_CARD.STEP.CONFIRMATION : CONST.COMPANY_CARD.STEP.CARD,
data: {
email: selectedMember,
cardName: `${memberName}'s card`,
},
isEditing: false,
});
Expand Down
95 changes: 95 additions & 0 deletions src/pages/workspace/companyCards/assignCard/CardNameStep.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React from 'react';
import {useOnyx} from 'react-native-onyx';
import FormProvider from '@components/Form/FormProvider';
import InputWrapper from '@components/Form/InputWrapper';
import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
import * as CompanyCards from '@userActions/CompanyCards';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import INPUT_IDS from '@src/types/form/EditExpensifyCardNameForm';

type CardNameStepProps = {
/** Current policy id */
policyID: string;
};

function CardNameStep({policyID}: CardNameStepProps) {
const {translate} = useLocalize();
const {inputCallbackRef} = useAutoFocusInput();
const styles = useThemeStyles();
const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD);

const data = assignCard?.data;

const submit = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.EDIT_WORKSPACE_COMPANY_CARD_NAME_FORM>) => {
CompanyCards.setAssignCardStepAndData({
currentStep: CONST.COMPANY_CARD.STEP.CONFIRMATION,
data: {
cardName: values.name,
},
isEditing: false,
});
};

const validate = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.EDIT_WORKSPACE_COMPANY_CARD_NAME_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.EDIT_WORKSPACE_COMPANY_CARD_NAME_FORM> => {
const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.NAME]);
const length = values.name.length;

if (length > CONST.STANDARD_LENGTH_LIMIT) {
ErrorUtils.addErrorMessage(errors, INPUT_IDS.NAME, translate('common.error.characterLimitExceedCounter', {length, limit: CONST.STANDARD_LENGTH_LIMIT}));
}

return errors;
};

return (
<AccessOrNotFoundWrapper
policyID={policyID}
featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
>
<ScreenWrapper
testID={CardNameStep.displayName}
shouldEnablePickerAvoiding={false}
includeSafeAreaPaddingBottom={false}
>
<HeaderWithBackButton
title={translate('workspace.moreFeatures.companyCards.cardName')}
onBackButtonPress={() => CompanyCards.setAssignCardStepAndData({currentStep: CONST.COMPANY_CARD.STEP.CONFIRMATION, isEditing: false})}
/>
<Text style={[styles.mh5, styles.mt3, styles.mb5]}>{translate('workspace.moreFeatures.companyCards.giveItNameInstruction')}</Text>
<FormProvider
formID={ONYXKEYS.FORMS.EDIT_WORKSPACE_COMPANY_CARD_NAME_FORM}
submitButtonText={translate('common.confirm')}
onSubmit={submit}
style={[styles.flex1, styles.mh5]}
enabledWhenOffline
validate={validate}
>
<InputWrapper
InputComponent={TextInput}
inputID={INPUT_IDS.NAME}
label={translate('workspace.moreFeatures.companyCards.cardName')}
aria-label={translate('workspace.moreFeatures.companyCards.cardName')}
role={CONST.ROLE.PRESENTATION}
defaultValue={data?.cardName}
ref={inputCallbackRef}
/>
</FormProvider>
</ScreenWrapper>
</AccessOrNotFoundWrapper>
);
}

CardNameStep.displayName = 'CardNameStep';

export default CardNameStep;
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ function CardSelectionStep({feed, policyID}: CardSelectionStepProps) {
return;
}

const cardName =
const cardNumber =
Object.entries(filteredCardList)
.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: accountCardList?.length > 0 ? cardSelected : cardName},
data: {encryptedCardNumber: cardSelected, cardNumber: accountCardList?.length > 0 ? cardSelected : cardNumber},
isEditing: false,
});
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function ConfirmationStep({policyID, backTo}: ConfirmationStepProps) {
/>
<MenuItemWithTopDescription
description={translate('workspace.companyCards.card')}
title={data?.cardName}
title={data?.cardNumber}
shouldShowRightIcon
onPress={() => editStep(CONST.COMPANY_CARD.STEP.CARD)}
/>
Expand All @@ -85,6 +85,12 @@ function ConfirmationStep({policyID, backTo}: ConfirmationStepProps) {
shouldShowRightIcon
onPress={() => editStep(CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE)}
/>
<MenuItemWithTopDescription
description={translate('workspace.companyCards.cardName')}
title={data?.cardName}
shouldShowRightIcon
onPress={() => editStep(CONST.COMPANY_CARD.STEP.CARD_NAME)}
/>
<View style={[styles.mh5, styles.pb5, styles.mt3, styles.flexGrow1, styles.justifyContentEnd]}>
<Button
isDisabled={isOffline}
Expand Down
5 changes: 4 additions & 1 deletion src/types/onyx/AssignCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ type AssignCardData = {
/** The email address of the assignee */
email: string;

/** Number of the selected card */
/** Encrypted number of the selected card */
encryptedCardNumber: string;

/** Number of the selected card */
cardNumber: string;

/** The name of the feed */
bankName: string;

Expand Down