diff --git a/src/CONST.ts b/src/CONST.ts index 3a198aca2c8c..c6ae9cc5928d 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1359,6 +1359,7 @@ const CONST = { MERCHANT: 'merchant', CATEGORY: 'category', RECEIPT: 'receipt', + TAG: 'tag', }, FOOTER: { EXPENSE_MANAGEMENT_URL: `${USE_EXPENSIFY_URL}/expense-management`, diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 6a71916588d9..0d554ff0eca4 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -38,6 +38,7 @@ import transactionPropTypes from './transactionPropTypes'; import DistanceRequestUtils from '../libs/DistanceRequestUtils'; import * as IOU from '../libs/actions/IOU'; import * as TransactionUtils from '../libs/TransactionUtils'; +import * as PolicyUtils from '../libs/PolicyUtils'; const propTypes = { /** Callback to inform parent modal of success */ @@ -142,13 +143,7 @@ const propTypes = { policyCategories: PropTypes.objectOf(categoryPropTypes), /** Collection of tags attached to a policy */ - policyTags: PropTypes.objectOf( - PropTypes.shape({ - name: PropTypes.string, - required: PropTypes.bool, - tags: PropTypes.objectOf(tagPropTypes), - }), - ), + policyTags: tagPropTypes, }; const defaultProps = { @@ -202,12 +197,12 @@ function MoneyRequestConfirmationList(props) { const shouldShowCategories = isPolicyExpenseChat && Permissions.canUseCategories(props.betas) && OptionsListUtils.hasEnabledOptions(_.values(props.policyCategories)); // Fetches the first tag list of the policy - const tagListKey = _.first(_.keys(props.policyTags)); - const tagList = lodashGet(props.policyTags, [tagListKey, 'tags'], []); - const tagListName = lodashGet(props.policyTags, [tagListKey, 'name'], ''); + const policyTag = PolicyUtils.getTag(props.policyTags); + const policyTagList = lodashGet(policyTag, 'tags', {}); + const policyTagListName = lodashGet(policyTag, 'name', translate('common.tag')); const canUseTags = Permissions.canUseTags(props.betas); // A flag for showing the tags field - const shouldShowTags = isPolicyExpenseChat && canUseTags && _.any(tagList, (tag) => tag.enabled); + const shouldShowTags = isPolicyExpenseChat && canUseTags && OptionsListUtils.hasEnabledOptions(_.values(policyTagList)); // A flag for showing the billable field const shouldShowBillable = canUseTags && !lodashGet(props.policy, 'disabledFields.defaultBillable', true); @@ -541,7 +536,7 @@ function MoneyRequestConfirmationList(props) { Navigation.navigate(ROUTES.MONEY_REQUEST_TAG.getRoute(props.iouType, props.reportID))} style={[styles.moneyRequestMenuItem, styles.mb2]} disabled={didConfirm || props.isReadOnly} diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index cbfa8e88d950..0220bbdf520a 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -17,6 +17,7 @@ import * as ReportUtils from '../../libs/ReportUtils'; import * as OptionsListUtils from '../../libs/OptionsListUtils'; import * as ReportActionsUtils from '../../libs/ReportActionsUtils'; import * as StyleUtils from '../../styles/StyleUtils'; +import * as PolicyUtils from '../../libs/PolicyUtils'; import CONST from '../../CONST'; import * as Expensicons from '../Icon/Expensicons'; import iouReportPropTypes from '../../pages/iouReportPropTypes'; @@ -32,6 +33,7 @@ import * as TransactionUtils from '../../libs/TransactionUtils'; import OfflineWithFeedback from '../OfflineWithFeedback'; import categoryPropTypes from '../categoryPropTypes'; import SpacerView from '../SpacerView'; +import tagPropTypes from '../tagPropTypes'; const propTypes = { /** The report currently being looked at */ @@ -53,6 +55,9 @@ const propTypes = { /** The transaction associated with the transactionThread */ transaction: transactionPropTypes, + /** Collection of tags attached to a policy */ + policyTags: tagPropTypes, + ...withCurrentUserPersonalDetailsPropTypes, }; @@ -65,9 +70,10 @@ const defaultProps = { currency: CONST.CURRENCY.USD, comment: {comment: ''}, }, + policyTags: {}, }; -function MoneyRequestView({betas, report, parentReport, policyCategories, shouldShowHorizontalRule, transaction}) { +function MoneyRequestView({report, betas, parentReport, policyCategories, shouldShowHorizontalRule, transaction, policyTags}) { const {isSmallScreenWidth} = useWindowDimensions(); const {translate} = useLocalize(); @@ -80,6 +86,7 @@ function MoneyRequestView({betas, report, parentReport, policyCategories, should comment: transactionDescription, merchant: transactionMerchant, category: transactionCategory, + tag: transactionTag, } = ReportUtils.getTransactionDetails(transaction); const isEmptyMerchant = transactionMerchant === '' || transactionMerchant === CONST.TRANSACTION.UNKNOWN_MERCHANT || transactionMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT; @@ -89,8 +96,14 @@ function MoneyRequestView({betas, report, parentReport, policyCategories, should const canEdit = ReportUtils.canEditMoneyRequest(parentReportAction); // A flag for verifying that the current report is a sub-report of a workspace chat const isPolicyExpenseChat = useMemo(() => ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)), [report]); - // A flag for showing categories + + // Fetches only the first tag, for now + const policyTag = PolicyUtils.getTag(policyTags); + const policyTagsList = lodashGet(policyTag, 'tags', {}); + + // Flags for showing categories and tags const shouldShowCategory = isPolicyExpenseChat && Permissions.canUseCategories(betas) && (transactionCategory || OptionsListUtils.hasEnabledOptions(lodashValues(policyCategories))); + const shouldShowTag = isPolicyExpenseChat && Permissions.canUseTags(betas) && (transactionTag || OptionsListUtils.hasEnabledOptions(lodashValues(policyTagsList))); let description = `${translate('iou.amount')} • ${translate('iou.cash')}`; if (isSettled) { @@ -200,6 +213,18 @@ function MoneyRequestView({betas, report, parentReport, policyCategories, should /> )} + {shouldShowTag && ( + + Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.TAG))} + /> + + )} `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report.policyID}`, + }, }), )(MoneyRequestView); diff --git a/src/components/TagPicker/index.js b/src/components/TagPicker/index.js index c46ca1b57b22..8e7cf11f7e5a 100644 --- a/src/components/TagPicker/index.js +++ b/src/components/TagPicker/index.js @@ -7,6 +7,7 @@ import ONYXKEYS from '../../ONYXKEYS'; import styles from '../../styles/styles'; import useLocalize from '../../hooks/useLocalize'; import * as OptionsListUtils from '../../libs/OptionsListUtils'; +import * as PolicyUtils from '../../libs/PolicyUtils'; import OptionsSelector from '../OptionsSelector'; import {propTypes, defaultProps} from './tagPickerPropTypes'; @@ -15,7 +16,7 @@ function TagPicker({selectedTag, tag, policyTags, policyRecentlyUsedTags, onSubm const [searchValue, setSearchValue] = useState(''); const policyRecentlyUsedTagsList = lodashGet(policyRecentlyUsedTags, tag, []); - const policyTagList = lodashGet(policyTags, [tag, 'tags'], {}); + const policyTagList = PolicyUtils.getTagList(policyTags, tag); const policyTagsCount = _.size(_.filter(policyTagList, (policyTag) => policyTag.enabled)); const isTagsCountBelowThreshold = policyTagsCount < CONST.TAG_LIST_THRESHOLD; diff --git a/src/components/TagPicker/tagPickerPropTypes.js b/src/components/TagPicker/tagPickerPropTypes.js index a5d94605a76a..011885fe0f81 100644 --- a/src/components/TagPicker/tagPickerPropTypes.js +++ b/src/components/TagPicker/tagPickerPropTypes.js @@ -16,12 +16,7 @@ const propTypes = { /* Onyx Props */ /** Collection of tags attached to a policy */ - policyTags: PropTypes.objectOf( - PropTypes.shape({ - name: PropTypes.string, - tags: PropTypes.objectOf(tagPropTypes), - }), - ), + policyTags: tagPropTypes, /** List of recently used tags */ policyRecentlyUsedTags: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.string)), diff --git a/src/components/tagPropTypes.js b/src/components/tagPropTypes.js index 29d913dcd035..2108b65ebbd5 100644 --- a/src/components/tagPropTypes.js +++ b/src/components/tagPropTypes.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types'; -export default PropTypes.shape({ +const tagListPropTypes = PropTypes.shape({ /** Name of a tag */ name: PropTypes.string.isRequired, @@ -10,3 +10,11 @@ export default PropTypes.shape({ /** "General Ledger code" that corresponds to this tag in an accounting system. Similar to an ID. */ 'GL Code': PropTypes.string, }); + +export default PropTypes.objectOf( + PropTypes.shape({ + name: PropTypes.string, + required: PropTypes.bool, + tags: PropTypes.objectOf(tagListPropTypes), + }), +); diff --git a/src/libs/PolicyUtils.js b/src/libs/PolicyUtils.js index 1f6e8a9bc1b5..347a825f59cc 100644 --- a/src/libs/PolicyUtils.js +++ b/src/libs/PolicyUtils.js @@ -203,6 +203,56 @@ function getIneligibleInvitees(policyMembers, personalDetails) { return memberEmailsToExclude; } +/** + * Gets the tag from policy tags, defaults to the first if no key is provided. + * + * @param {Object} policyTags + * @param {String} [tagKey] + * @returns {Object} + */ +function getTag(policyTags, tagKey) { + if (_.isEmpty(policyTags)) { + return {}; + } + + const policyTagKey = tagKey || _.first(_.keys(policyTags)); + + return lodashGet(policyTags, policyTagKey, {}); +} + +/** + * Gets the first tag name from policy tags. + * + * @param {Object} policyTags + * @returns {String} + */ +function getTagListName(policyTags) { + if (_.isEmpty(policyTags)) { + return ''; + } + + const policyTagKeys = _.keys(policyTags) || []; + + return lodashGet(policyTags, [_.first(policyTagKeys), 'name'], ''); +} + +/** + * Gets the tags of a policy for a specific key. Defaults to the first tag if no key is provided. + * + * @param {Object} policyTags + * @param {String} [tagKey] + * @returns {String} + */ +function getTagList(policyTags, tagKey) { + if (_.isEmpty(policyTags)) { + return {}; + } + + const policyTagKey = tagKey || _.first(_.keys(policyTags)); + + return lodashGet(policyTags, [policyTagKey, 'tags'], {}); +} + /** * @param {Object} policy * @returns {Boolean} @@ -226,5 +276,8 @@ export { isPolicyAdmin, getMemberAccountIDsForWorkspace, getIneligibleInvitees, + getTag, + getTagListName, + getTagList, isPendingDeletePolicy, }; diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 1d0f676e4116..fbc6f6a73033 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1341,6 +1341,7 @@ function getTransactionDetails(transaction) { comment: TransactionUtils.getDescription(transaction), merchant: TransactionUtils.getMerchant(transaction), category: TransactionUtils.getCategory(transaction), + tag: TransactionUtils.getTag(transaction), }; } @@ -1592,6 +1593,11 @@ function getModifiedExpenseMessage(reportAction) { if (hasModifiedCategory) { return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.category, reportActionOriginalMessage.oldCategory, Localize.translateLocal('common.category'), true); } + + const hasModifiedTag = _.has(reportActionOriginalMessage, 'oldTag') && _.has(reportActionOriginalMessage, 'tag'); + if (hasModifiedTag) { + return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.tag, reportActionOriginalMessage.oldTag, Localize.translateLocal('common.tag'), true); + } } /** @@ -1637,6 +1643,11 @@ function getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges, i originalMessage.category = transactionChanges.category; } + if (_.has(transactionChanges, 'tag')) { + originalMessage.oldTag = TransactionUtils.getTag(oldTransaction); + originalMessage.tag = transactionChanges.tag; + } + return originalMessage; } diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js index 5dcfbc467c20..58fb23a8811a 100644 --- a/src/libs/TransactionUtils.js +++ b/src/libs/TransactionUtils.js @@ -151,6 +151,10 @@ function getUpdatedTransaction(transaction, transactionChanges, isFromExpenseRep updatedTransaction.category = transactionChanges.category; } + if (_.has(transactionChanges, 'tag')) { + updatedTransaction.tag = transactionChanges.tag; + } + if (shouldStopSmartscan && _.has(transaction, 'receipt') && !_.isEmpty(transaction.receipt) && lodashGet(transaction, 'receipt.state') !== CONST.IOU.RECEIPT_STATE.OPEN) { updatedTransaction.receipt.state = CONST.IOU.RECEIPT_STATE.OPEN; } @@ -162,6 +166,7 @@ function getUpdatedTransaction(transaction, transactionChanges, isFromExpenseRep ...(_.has(transactionChanges, 'currency') && {currency: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), ...(_.has(transactionChanges, 'merchant') && {merchant: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), ...(_.has(transactionChanges, 'category') && {category: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), + ...(_.has(transactionChanges, 'tag') && {tag: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), }; return updatedTransaction; @@ -253,6 +258,16 @@ function getCategory(transaction) { return lodashGet(transaction, 'category', ''); } +/** + * Return the tag from the transaction. This "tag" field has no "modified" complement. + * + * @param {Object} transaction + * @return {String} + */ +function getTag(transaction) { + return lodashGet(transaction, 'tag', ''); +} + /** * Return the created field from the transaction, return the modifiedCreated if present. * @@ -399,6 +414,7 @@ export { getMerchant, getCreated, getCategory, + getTag, getLinkedTransaction, getAllReportTransactions, hasReceipt, diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 085842af18b9..413caee144eb 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -1136,6 +1136,17 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC updatedChatReport.lastMessageHtml = messageText; } + const optimisticPolicyRecentlyUsedTags = {}; + if (_.has(transactionChanges, 'tag')) { + const tagListName = transactionChanges.tagListName; + const recentlyUsedPolicyTags = allRecentlyUsedTags[`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport.policyID}`]; + + if (recentlyUsedPolicyTags) { + const uniquePolicyRecentlyUsedTags = _.filter(recentlyUsedPolicyTags[tagListName], (recentlyUsedPolicyTag) => recentlyUsedPolicyTag !== transactionChanges.tag); + optimisticPolicyRecentlyUsedTags[tagListName] = [transactionChanges.tag, ...uniquePolicyRecentlyUsedTags]; + } + } + // STEP 4: Compose the optimistic data const currentTime = DateUtils.getDBTime(); const optimisticData = [ @@ -1171,6 +1182,14 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC }, ]; + if (!_.isEmpty(optimisticPolicyRecentlyUsedTags)) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport.policyID}`, + value: optimisticPolicyRecentlyUsedTags, + }); + } + const successData = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -1190,6 +1209,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC currency: null, merchant: null, category: null, + tag: null, }, }, }, @@ -1236,7 +1256,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC ]; // STEP 6: Call the API endpoint - const {created, amount, currency, comment, merchant, category} = ReportUtils.getTransactionDetails(updatedTransaction); + const {created, amount, currency, comment, merchant, category, tag} = ReportUtils.getTransactionDetails(updatedTransaction); API.write( 'EditMoneyRequest', { @@ -1248,6 +1268,7 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC comment, merchant, category, + tag, }, {optimisticData, successData, failureData}, ); diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 3e7297082088..5e6e0dd3f17b 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -2,25 +2,28 @@ import React, {useEffect} from 'react'; import PropTypes from 'prop-types'; import lodashGet from 'lodash/get'; import {withOnyx} from 'react-native-onyx'; -import compose from '../libs/compose'; import CONST from '../CONST'; -import Navigation from '../libs/Navigation/Navigation'; import ONYXKEYS from '../ONYXKEYS'; +import compose from '../libs/compose'; +import Navigation from '../libs/Navigation/Navigation'; import * as ReportActionsUtils from '../libs/ReportActionsUtils'; import * as ReportUtils from '../libs/ReportUtils'; +import * as PolicyUtils from '../libs/PolicyUtils'; import * as TransactionUtils from '../libs/TransactionUtils'; import * as Policy from '../libs/actions/Policy'; +import * as IOU from '../libs/actions/IOU'; +import * as CurrencyUtils from '../libs/CurrencyUtils'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '../components/withCurrentUserPersonalDetails'; +import tagPropTypes from '../components/tagPropTypes'; +import FullPageNotFoundView from '../components/BlockingViews/FullPageNotFoundView'; import EditRequestDescriptionPage from './EditRequestDescriptionPage'; import EditRequestMerchantPage from './EditRequestMerchantPage'; import EditRequestCreatedPage from './EditRequestCreatedPage'; import EditRequestAmountPage from './EditRequestAmountPage'; import EditRequestReceiptPage from './EditRequestReceiptPage'; -import reportPropTypes from './reportPropTypes'; -import * as IOU from '../libs/actions/IOU'; -import * as CurrencyUtils from '../libs/CurrencyUtils'; -import FullPageNotFoundView from '../components/BlockingViews/FullPageNotFoundView'; import EditRequestCategoryPage from './EditRequestCategoryPage'; +import EditRequestTagPage from './EditRequestTagPage'; +import reportPropTypes from './reportPropTypes'; const propTypes = { /** Route from navigation */ @@ -35,6 +38,7 @@ const propTypes = { }), }).isRequired, + /** Onyx props */ /** The report object for the thread report */ report: reportPropTypes, @@ -56,6 +60,9 @@ const propTypes = { email: PropTypes.string, }), + /** Collection of tags attached to a policy */ + policyTags: tagPropTypes, + ...withCurrentUserPersonalDetailsPropTypes, }; @@ -66,9 +73,10 @@ const defaultProps = { session: { email: null, }, + policyTags: {}, }; -function EditRequestPage({report, route, parentReport, policy, session}) { +function EditRequestPage({report, route, parentReport, policy, session, policyTags}) { const parentReportAction = ReportActionsUtils.getParentReportAction(report); const transaction = TransactionUtils.getLinkedTransaction(parentReportAction); const { @@ -77,6 +85,7 @@ function EditRequestPage({report, route, parentReport, policy, session}) { comment: transactionDescription, merchant: transactionMerchant, category: transactionCategory, + tag: transactionTag, } = ReportUtils.getTransactionDetails(transaction); const defaultCurrency = lodashGet(route, 'params.currency', '') || transactionCurrency; @@ -92,6 +101,9 @@ function EditRequestPage({report, route, parentReport, policy, session}) { const isRequestor = ReportUtils.isMoneyRequestReport(parentReport) && lodashGet(session, 'accountID', null) === parentReportAction.actorAccountID; const canEdit = !isSettled && !isDeleted && (isAdmin || isRequestor); + // For now, it always defaults to the first tag of the policy + const tagListName = PolicyUtils.getTagListName(policyTags); + // Dismiss the modal when the request is paid or deleted useEffect(() => { if (canEdit) { @@ -105,7 +117,7 @@ function EditRequestPage({report, route, parentReport, policy, session}) { // Update the transaction object and close the modal function editMoneyRequest(transactionChanges) { IOU.editMoneyRequest(transaction.transactionID, report.reportID, transactionChanges); - Navigation.dismissModal(); + Navigation.dismissModal(report.reportID); } if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.DESCRIPTION) { @@ -196,6 +208,25 @@ function EditRequestPage({report, route, parentReport, policy, session}) { ); } + if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.TAG) { + return ( + { + let updatedTag = transactionChanges.tag; + + // In case the same tag has been selected, reset the tag. + if (transactionTag === updatedTag) { + updatedTag = ''; + } + editMoneyRequest({tag: updatedTag, tagListName}); + }} + /> + ); + } + if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.RECEIPT) { return ( `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, + policyTags: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, + }, }), )(EditRequestPage); diff --git a/src/pages/EditRequestTagPage.js b/src/pages/EditRequestTagPage.js new file mode 100644 index 000000000000..72ed072eec16 --- /dev/null +++ b/src/pages/EditRequestTagPage.js @@ -0,0 +1,53 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Navigation from '../libs/Navigation/Navigation'; +import useLocalize from '../hooks/useLocalize'; +import ScreenWrapper from '../components/ScreenWrapper'; +import HeaderWithBackButton from '../components/HeaderWithBackButton'; +import TagPicker from '../components/TagPicker'; + +const propTypes = { + /** Transaction default tag value */ + defaultTag: PropTypes.string.isRequired, + + /** The policyID we are getting tags for */ + policyID: PropTypes.string.isRequired, + + /** The tag name to which the default tag belongs to */ + tagName: PropTypes.string.isRequired, + + /** Callback to fire when the Save button is pressed */ + onSubmit: PropTypes.func.isRequired, +}; + +function EditRequestTagPage({defaultTag, policyID, tagName, onSubmit}) { + const {translate} = useLocalize(); + + const selectTag = (tag) => { + onSubmit({tag: tag.searchText}); + }; + + return ( + + + + + + ); +} + +EditRequestTagPage.propTypes = propTypes; +EditRequestTagPage.displayName = 'EditRequestTagPage'; + +export default EditRequestTagPage; diff --git a/src/pages/iou/MoneyRequestTagPage.js b/src/pages/iou/MoneyRequestTagPage.js index 32c21d949f2c..43c0cd9d1480 100644 --- a/src/pages/iou/MoneyRequestTagPage.js +++ b/src/pages/iou/MoneyRequestTagPage.js @@ -6,6 +6,7 @@ import {withOnyx} from 'react-native-onyx'; import compose from '../../libs/compose'; import ROUTES from '../../ROUTES'; import * as IOU from '../../libs/actions/IOU'; +import * as PolicyUtils from '../../libs/PolicyUtils'; import Navigation from '../../libs/Navigation/Navigation'; import useLocalize from '../../hooks/useLocalize'; import ScreenWrapper from '../../components/ScreenWrapper'; @@ -36,12 +37,7 @@ const propTypes = { report: reportPropTypes, /** Collection of tags attached to a policy */ - policyTags: PropTypes.objectOf( - PropTypes.shape({ - name: PropTypes.string, - tags: PropTypes.objectOf(tagPropTypes), - }), - ), + policyTags: tagPropTypes, /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ iou: iouPropTypes, @@ -60,8 +56,7 @@ function MoneyRequestTagPage({route, report, policyTags, iou}) { // Fetches the first tag list of the policy const tagListKey = _.first(_.keys(policyTags)); - const tagList = lodashGet(policyTags, tagListKey, {}); - const tagListName = lodashGet(tagList, 'name', translate('common.tag')); + const policyTagListName = PolicyUtils.getTagListName(policyTags) || translate('common.tag'); const navigateBack = () => { Navigation.goBack(ROUTES.MONEY_REQUEST_CONFIRMATION.getRoute(iouType, report.reportID)); @@ -83,10 +78,10 @@ function MoneyRequestTagPage({route, report, policyTags, iou}) { testID={MoneyRequestTagPage.displayName} > - {translate('iou.tagSelection', {tagName: tagListName})} + {translate('iou.tagSelection', {tagName: policyTagListName})}