diff --git a/docs/context.xml b/docs/context.xml
index b38e1a5f9e8a..f62520153883 100644
--- a/docs/context.xml
+++ b/docs/context.xml
@@ -25,7 +25,7 @@
-
+
diff --git a/package-lock.json b/package-lock.json
index acfa4a420290..1ce9aee50531 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -113,7 +113,7 @@
"react-web-config": "^1.0.0",
"react-window": "^1.8.9",
"save": "^2.4.0",
- "semver": "^7.3.8",
+ "semver": "^7.5.2",
"shim-keyboard-event-key": "^1.0.3",
"underscore": "^1.13.1"
},
diff --git a/package.json b/package.json
index 03773ecd9f91..252b45912502 100644
--- a/package.json
+++ b/package.json
@@ -153,7 +153,7 @@
"react-web-config": "^1.0.0",
"react-window": "^1.8.9",
"save": "^2.4.0",
- "semver": "^7.3.8",
+ "semver": "^7.5.2",
"shim-keyboard-event-key": "^1.0.3",
"underscore": "^1.13.1"
},
diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js
index 7ef5c68c3850..5a00c49db0a0 100755
--- a/src/ONYXKEYS.js
+++ b/src/ONYXKEYS.js
@@ -221,8 +221,9 @@ export default {
NEW_TASK_FORM: 'newTaskForm',
EDIT_TASK_FORM: 'editTaskForm',
MONEY_REQUEST_DESCRIPTION_FORM: 'moneyRequestDescriptionForm',
+ MONEY_REQUEST_MERCHANT_FORM: 'moneyRequestMerchantForm',
MONEY_REQUEST_AMOUNT_FORM: 'moneyRequestAmountForm',
- MONEY_REQUEST_CREATED_FORM: 'moneyRequestCreatedForm',
+ MONEY_REQUEST_DATE_FORM: 'moneyRequestCreatedForm',
NEW_CONTACT_METHOD_FORM: 'newContactMethodForm',
PAYPAL_FORM: 'payPalForm',
WAYPOINT_FORM: 'waypointForm',
diff --git a/src/ROUTES.js b/src/ROUTES.js
index 9063cd275d68..3f96d77d477e 100644
--- a/src/ROUTES.js
+++ b/src/ROUTES.js
@@ -89,8 +89,10 @@ export default {
MONEY_REQUEST_AMOUNT: ':iouType/new/amount/:reportID?',
MONEY_REQUEST_PARTICIPANTS: ':iouType/new/participants/:reportID?',
MONEY_REQUEST_CONFIRMATION: ':iouType/new/confirmation/:reportID?',
+ MONEY_REQUEST_DATE: ':iouType/new/date/:reportID?',
MONEY_REQUEST_CURRENCY: ':iouType/new/currency/:reportID?',
MONEY_REQUEST_DESCRIPTION: ':iouType/new/description/:reportID?',
+ MONEY_REQUEST_MERCHANT: ':iouType/new/merchant/:reportID?',
MONEY_REQUEST_MANUAL_TAB: ':iouType/new/:reportID?/manual',
MONEY_REQUEST_SCAN_TAB: ':iouType/new/:reportID?/scan',
MONEY_REQUEST_DISTANCE_TAB: ':iouType/new/:reportID?/distance',
@@ -102,8 +104,10 @@ export default {
getMoneyRequestAmountRoute: (iouType, reportID = '') => `${iouType}/new/amount/${reportID}`,
getMoneyRequestParticipantsRoute: (iouType, reportID = '') => `${iouType}/new/participants/${reportID}`,
getMoneyRequestConfirmationRoute: (iouType, reportID = '') => `${iouType}/new/confirmation/${reportID}`,
+ getMoneyRequestCreatedRoute: (iouType, reportID = '') => `${iouType}/new/date/${reportID}`,
getMoneyRequestCurrencyRoute: (iouType, reportID = '', currency, backTo) => `${iouType}/new/currency/${reportID}?currency=${currency}&backTo=${backTo}`,
getMoneyRequestDescriptionRoute: (iouType, reportID = '') => `${iouType}/new/description/${reportID}`,
+ getMoneyRequestMerchantRoute: (iouType, reportID = '') => `${iouType}/new/merchant/${reportID}`,
getMoneyRequestDistanceTabRoute: (iouType, reportID = '') => `${iouType}/new/${reportID}/distance`,
getMoneyRequestWaypointRoute: (iouType, waypointIndex) => `${iouType}/new/waypoint/${waypointIndex}`,
SPLIT_BILL_DETAILS: `r/:reportID/split/:reportActionID`,
diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js
index 2cc458d0e4ad..832be75c1317 100755
--- a/src/components/MoneyRequestConfirmationList.js
+++ b/src/components/MoneyRequestConfirmationList.js
@@ -1,6 +1,7 @@
import React, {useCallback, useMemo, useReducer, useState} from 'react';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
+import {format} from 'date-fns';
import _ from 'underscore';
import {View} from 'react-native';
import Str from 'expensify-common/lib/str';
@@ -58,7 +59,7 @@ const propTypes = {
iouType: PropTypes.string,
/** IOU date */
- iouDate: PropTypes.string,
+ iouCreated: PropTypes.string,
/** IOU merchant */
iouMerchant: PropTypes.string,
@@ -125,6 +126,7 @@ function MoneyRequestConfirmationList(props) {
// A flag and a toggler for showing the rest of the form fields
const [showAllFields, toggleShowAllFields] = useReducer((state) => !state, false);
+ const isTypeRequest = props.iouType === CONST.IOU.MONEY_REQUEST_TYPE.REQUEST;
/**
* Returns the participants with amount
@@ -406,18 +408,20 @@ function MoneyRequestConfirmationList(props) {
{showAllFields && (
<>
Navigation.navigate(ROUTES.getMoneyRequestCreatedRoute(props.iouType, props.reportID))}
+ disabled={didConfirm || props.isReadOnly || !isTypeRequest}
/>
Navigation.navigate(ROUTES.getMoneyRequestMerchantRoute(props.iouType, props.reportID))}
+ disabled={didConfirm || props.isReadOnly || !isTypeRequest}
/>
>
)}
diff --git a/src/components/OfflineWithFeedback.js b/src/components/OfflineWithFeedback.js
index 820cce252205..2f99b21b6523 100644
--- a/src/components/OfflineWithFeedback.js
+++ b/src/components/OfflineWithFeedback.js
@@ -94,10 +94,10 @@ function OfflineWithFeedback(props) {
const errorMessages = _.omit(props.errors, (e) => e === null);
const hasErrorMessages = !_.isEmpty(errorMessages);
const isOfflinePendingAction = props.network.isOffline && props.pendingAction;
- const isUpdateOrDeleteError = hasErrors && (props.pendingAction === 'delete' || props.pendingAction === 'update');
- const isAddError = hasErrors && props.pendingAction === 'add';
+ const isUpdateOrDeleteError = hasErrors && (props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE);
+ const isAddError = hasErrors && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD;
const needsOpacity = (isOfflinePendingAction && !isUpdateOrDeleteError) || isAddError;
- const needsStrikeThrough = props.network.isOffline && props.pendingAction === 'delete';
+ const needsStrikeThrough = props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
const hideChildren = props.shouldHideOnDelete && !props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !hasErrors;
let children = props.children;
diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js
index 0d8a38ede4e2..c36eaf5db368 100644
--- a/src/components/ReportActionItem/MoneyRequestView.js
+++ b/src/components/ReportActionItem/MoneyRequestView.js
@@ -23,6 +23,7 @@ import * as CurrencyUtils from '../../libs/CurrencyUtils';
import EmptyStateBackgroundImage from '../../../assets/images/empty-state_background-fade.png';
import useLocalize from '../../hooks/useLocalize';
import useWindowDimensions from '../../hooks/useWindowDimensions';
+import OfflineWithFeedback from '../OfflineWithFeedback';
const propTypes = {
/** The report currently being looked at */
@@ -67,7 +68,13 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic
const parentReportAction = ReportActionsUtils.getParentReportAction(report);
const moneyRequestReport = parentReport;
const transaction = TransactionUtils.getLinkedTransaction(parentReportAction);
- const {created: transactionDate, amount: transactionAmount, currency: transactionCurrency, comment: transactionDescription} = ReportUtils.getTransactionDetails(transaction);
+ const {
+ created: transactionDate,
+ amount: transactionAmount,
+ currency: transactionCurrency,
+ comment: transactionDescription,
+ merchant: transactionMerchant,
+ } = ReportUtils.getTransactionDetails(transaction);
const formattedTransactionAmount = transactionAmount && transactionCurrency && CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency);
const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID);
@@ -97,30 +104,44 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic
style={[StyleUtils.getReportWelcomeBackgroundImageStyle(true)]}
/>
- Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))}
- />
- Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))}
- />
- Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))}
- />
+
+ Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))}
+ />
+
+
+ Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))}
+ />
+
+
+ Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))}
+ />
+
+
+
+
{shouldShowHorizontalRule && }
);
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
index d1ac97d09e9c..aa4fcc02c906 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
@@ -69,6 +69,13 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator([
},
name: 'Money_Request_Currency',
},
+ {
+ getComponent: () => {
+ const MoneyRequestDatePage = require('../../../pages/iou/MoneyRequestDatePage').default;
+ return MoneyRequestDatePage;
+ },
+ name: 'Money_Request_Date',
+ },
{
getComponent: () => {
const MoneyRequestDescriptionPage = require('../../../pages/iou/MoneyRequestDescriptionPage').default;
@@ -76,6 +83,13 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator([
},
name: 'Money_Request_Description',
},
+ {
+ getComponent: () => {
+ const MoneyRequestMerchantPage = require('../../../pages/iou/MoneyRequestMerchantPage').default;
+ return MoneyRequestMerchantPage;
+ },
+ name: 'Money_Request_Merchant',
+ },
{
getComponent: () => {
const AddPersonalBankAccountPage = require('../../../pages/AddPersonalBankAccountPage').default;
diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js
index 573eb71836d3..a76ebbf776da 100644
--- a/src/libs/Navigation/linkingConfig.js
+++ b/src/libs/Navigation/linkingConfig.js
@@ -307,8 +307,10 @@ export default {
Money_Request_Amount: ROUTES.MONEY_REQUEST_AMOUNT,
Money_Request_Participants: ROUTES.MONEY_REQUEST_PARTICIPANTS,
Money_Request_Confirmation: ROUTES.MONEY_REQUEST_CONFIRMATION,
+ Money_Request_Date: ROUTES.MONEY_REQUEST_DATE,
Money_Request_Currency: ROUTES.MONEY_REQUEST_CURRENCY,
Money_Request_Description: ROUTES.MONEY_REQUEST_DESCRIPTION,
+ Money_Request_Merchant: ROUTES.MONEY_REQUEST_MERCHANT,
Money_Request_Waypoint: ROUTES.MONEY_REQUEST_WAYPOINT,
IOU_Send_Enable_Payments: ROUTES.IOU_SEND_ENABLE_PAYMENTS,
IOU_Send_Add_Bank_Account: ROUTES.IOU_SEND_ADD_BANK_ACCOUNT,
diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js
index 654bc7054cb2..a5185d8352aa 100644
--- a/src/libs/OptionsListUtils.js
+++ b/src/libs/OptionsListUtils.js
@@ -758,8 +758,17 @@ function getOptions(
// Finally check to see if this option is a match for the provided search string if we have one
const {searchText, participantsList, isChatRoom} = reportOption;
const participantNames = getParticipantNames(participantsList);
- if (searchValue && !isSearchStringMatch(searchValue, searchText, participantNames, isChatRoom)) {
- continue;
+
+ if (searchValue) {
+ // Determine if the search is happening within a chat room and starts with the report ID
+ const isReportIdSearch = isChatRoom && Str.startsWith(reportOption.reportID, searchValue);
+
+ // Check if the search string matches the search text or participant names considering the type of the room
+ const isSearchMatch = isSearchStringMatch(searchValue, searchText, participantNames, isChatRoom);
+
+ if (!isReportIdSearch && !isSearchMatch) {
+ continue;
+ }
}
recentReportOptions.push(reportOption);
@@ -1044,7 +1053,7 @@ function getHeaderMessage(hasSelectableOptions, hasUserToInvite, searchValue, ma
const isValidEmail = Str.isValidEmail(searchValue);
- if (searchValue && CONST.REGEX.DIGITS_AND_PLUS.test(searchValue) && !isValidPhone) {
+ if (searchValue && CONST.REGEX.DIGITS_AND_PLUS.test(searchValue) && !isValidPhone && !hasSelectableOptions) {
return Localize.translate(preferredLocale, 'messages.errorMessageInvalidPhone');
}
diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js
index b24a5ea37aa0..0b96c1d1120b 100644
--- a/src/libs/ReportUtils.js
+++ b/src/libs/ReportUtils.js
@@ -1,5 +1,5 @@
import _ from 'underscore';
-import {format} from 'date-fns';
+import {format, parseISO} from 'date-fns';
import Str from 'expensify-common/lib/str';
import lodashGet from 'lodash/get';
import lodashIntersection from 'lodash/intersection';
@@ -1205,7 +1205,10 @@ function getPolicyExpenseChatName(report, policy = undefined) {
function getMoneyRequestReportName(report, policy = undefined) {
const formattedAmount = CurrencyUtils.convertToDisplayString(getMoneyRequestTotal(report), report.currency);
const payerName = isExpenseReport(report) ? getPolicyName(report, false, policy) : getDisplayNameForParticipant(report.managerID);
- const payerPaidAmountMesssage = Localize.translateLocal('iou.payerPaidAmount', {payer: payerName, amount: formattedAmount});
+ const payerPaidAmountMesssage = Localize.translateLocal('iou.payerPaidAmount', {
+ payer: payerName,
+ amount: formattedAmount,
+ });
if (report.isWaitingOnBankAccount) {
return `${payerPaidAmountMesssage} • ${Localize.translateLocal('iou.pending')}`;
@@ -1241,6 +1244,7 @@ function getTransactionDetails(transaction) {
amount: TransactionUtils.getAmount(transaction, isExpenseReport(report)),
currency: TransactionUtils.getCurrency(transaction),
comment: TransactionUtils.getDescription(transaction),
+ merchant: TransactionUtils.getMerchant(transaction),
};
}
@@ -1303,6 +1307,29 @@ function getReportPreviewMessage(report, reportAction = {}) {
return Localize.translateLocal('iou.payerOwesAmount', {payer: payerName, amount: formattedAmount});
}
+/**
+ * Get the proper message schema for modified expense message.
+ *
+ * @param {String} newValue
+ * @param {String} oldValue
+ * @param {String} valueName
+ * @param {Boolean} valueInQuotes
+ * @returns {String}
+ */
+
+function getProperSchemaForModifiedExpenseMessage(newValue, oldValue, valueName, valueInQuotes) {
+ const newValueToDisplay = valueInQuotes ? `"${newValue}"` : newValue;
+ const oldValueToDisplay = valueInQuotes ? `"${oldValue}"` : oldValue;
+
+ if (!oldValue) {
+ return `set the ${valueName} to ${newValueToDisplay}`;
+ }
+ if (!newValue) {
+ return `removed the ${valueName} (previously ${oldValueToDisplay})`;
+ }
+ return `changed the ${valueName} to ${newValueToDisplay} (previously ${oldValueToDisplay})`;
+}
+
/**
* Get the report action message when expense has been modified.
*
@@ -1327,25 +1354,25 @@ function getModifiedExpenseMessage(reportAction) {
const currency = reportActionOriginalMessage.currency;
const amount = CurrencyUtils.convertToDisplayString(reportActionOriginalMessage.amount, currency);
- return `changed the request to ${amount} (previously ${oldAmount})`;
+ return getProperSchemaForModifiedExpenseMessage(amount, oldAmount, 'amount', false);
}
const hasModifiedComment = _.has(reportActionOriginalMessage, 'oldComment') && _.has(reportActionOriginalMessage, 'newComment');
if (hasModifiedComment) {
- return `changed the request description to "${reportActionOriginalMessage.newComment}" (previously "${reportActionOriginalMessage.oldComment}")`;
+ return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.newComment, reportActionOriginalMessage.oldComment, 'description', true);
}
const hasModifiedMerchant = _.has(reportActionOriginalMessage, 'oldMerchant') && _.has(reportActionOriginalMessage, 'merchant');
if (hasModifiedMerchant) {
- return `changed the request merchant to "${reportActionOriginalMessage.merchant}" (previously "${reportActionOriginalMessage.oldMerchant}")`;
+ return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.merchant, reportActionOriginalMessage.oldMerchant, 'merchant', true);
}
const hasModifiedCreated = _.has(reportActionOriginalMessage, 'oldCreated') && _.has(reportActionOriginalMessage, 'created');
if (hasModifiedCreated) {
// Take only the YYYY-MM-DD value as the original date includes timestamp
- let formattedOldCreated = new Date(reportActionOriginalMessage.oldCreated);
+ let formattedOldCreated = parseISO(reportActionOriginalMessage.oldCreated);
formattedOldCreated = format(formattedOldCreated, CONST.DATE.FNS_FORMAT_STRING);
- return `changed the request date to ${reportActionOriginalMessage.created} (previously ${formattedOldCreated})`;
+ return getProperSchemaForModifiedExpenseMessage(reportActionOriginalMessage.created, formattedOldCreated, 'date', false);
}
}
diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js
index 90b6ca72bd4a..f7e3e644d7b8 100644
--- a/src/libs/TransactionUtils.js
+++ b/src/libs/TransactionUtils.js
@@ -1,5 +1,5 @@
import Onyx from 'react-native-onyx';
-import {format} from 'date-fns';
+import {format, parseISO, isValid} from 'date-fns';
import lodashGet from 'lodash/get';
import _ from 'underscore';
import CONST from '../CONST';
@@ -26,6 +26,7 @@ Onyx.connect({
* @param {String} currency
* @param {String} reportID
* @param {String} [comment]
+ * @param {String} [created]
* @param {String} [source]
* @param {String} [originalTransactionID]
* @param {String} [merchant]
@@ -38,6 +39,7 @@ function buildOptimisticTransaction(
currency,
reportID,
comment = '',
+ created = '',
source = '',
originalTransactionID = '',
merchant = CONST.REPORT.TYPE.IOU,
@@ -62,8 +64,8 @@ function buildOptimisticTransaction(
currency,
reportID,
comment: commentJSON,
- merchant,
- created: DateUtils.getDBTime(),
+ merchant: merchant || CONST.REPORT.TYPE.IOU,
+ created: created || DateUtils.getDBTime(),
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
receipt,
};
@@ -97,7 +99,12 @@ function getUpdatedTransaction(transaction, transactionChanges, isFromExpenseRep
if (_.has(transactionChanges, 'currency')) {
updatedTransaction.modifiedCurrency = transactionChanges.currency;
}
- updatedTransaction.pendingAction = CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE;
+ updatedTransaction.pendingFields = {
+ ...(_.has(transactionChanges, 'comment') && {comment: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}),
+ ...(_.has(transactionChanges, 'created') && {created: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}),
+ ...(_.has(transactionChanges, 'amount') && {amount: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}),
+ ...(_.has(transactionChanges, 'currency') && {currency: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}),
+ };
return updatedTransaction;
}
@@ -167,6 +174,16 @@ function getCurrency(transaction) {
return lodashGet(transaction, 'currency', CONST.CURRENCY.USD);
}
+/**
+ * Return the merchant field from the transaction, return the modifiedMerchant if present.
+ *
+ * @param {Object} transaction
+ * @returns {String}
+ */
+function getMerchant(transaction) {
+ return lodashGet(transaction, 'modifiedMerchant', null) || lodashGet(transaction, 'merchant', '');
+}
+
/**
* Return the created field from the transaction, return the modifiedCreated if present.
*
@@ -175,9 +192,11 @@ function getCurrency(transaction) {
*/
function getCreated(transaction) {
const created = lodashGet(transaction, 'modifiedCreated', '') || lodashGet(transaction, 'created', '');
- if (created) {
- return format(new Date(created), CONST.DATE.FNS_FORMAT_STRING);
+ const createdDate = parseISO(created);
+ if (isValid(createdDate)) {
+ return format(createdDate, CONST.DATE.FNS_FORMAT_STRING);
}
+
return '';
}
@@ -196,4 +215,4 @@ function getAllReportTransactions(reportID) {
return _.filter(allTransactions, (transaction) => transaction.reportID === reportID);
}
-export {buildOptimisticTransaction, getUpdatedTransaction, getTransaction, getDescription, getAmount, getCurrency, getCreated, getLinkedTransaction, getAllReportTransactions};
+export {buildOptimisticTransaction, getUpdatedTransaction, getTransaction, getDescription, getAmount, getCurrency, getMerchant, getCreated, getLinkedTransaction, getAllReportTransactions};
diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js
index b6caac0345cd..7244d14fe273 100644
--- a/src/libs/actions/IOU.js
+++ b/src/libs/actions/IOU.js
@@ -72,7 +72,7 @@ Onyx.connect({
* @param {String} id
*/
function resetMoneyRequestInfo(id = '') {
- const date = currentDate || moment().format('YYYY-MM-DD');
+ const created = currentDate || moment().format('YYYY-MM-DD');
Onyx.merge(ONYXKEYS.IOU, {
id,
amount: 0,
@@ -80,7 +80,7 @@ function resetMoneyRequestInfo(id = '') {
comment: '',
participants: [],
merchant: '',
- date,
+ created,
receiptPath: '',
receiptSource: '',
});
@@ -310,6 +310,8 @@ function buildOnyxDataForMoneyRequest(
* @param {String} comment
* @param {Number} amount
* @param {String} currency
+ * @param {String} created
+ * @param {String} merchant
* @param {Number} payeeAccountID
* @param {String} payeeEmail
* @param {Object} [receipt]
@@ -328,7 +330,7 @@ function buildOnyxDataForMoneyRequest(
* @returns {Object} data.onyxData.failureData
* @param {String} [existingTransactionID]
*/
-function getMoneyRequestInformation(report, participant, comment, amount, currency, payeeAccountID, payeeEmail, receipt = undefined, existingTransactionID = null) {
+function getMoneyRequestInformation(report, participant, comment, amount, currency, created, merchant, payeeAccountID, payeeEmail, receipt = undefined, existingTransactionID = null) {
const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login);
const payerAccountID = Number(participant.accountID);
const isPolicyExpenseChat = participant.isPolicyExpenseChat;
@@ -383,9 +385,10 @@ function getMoneyRequestInformation(report, participant, comment, amount, curren
currency,
iouReport.reportID,
comment,
+ created,
'',
'',
- undefined,
+ merchant,
receiptObject,
existingTransactionID,
);
@@ -495,6 +498,8 @@ function createDistanceRequest(report, payeeEmail, payeeAccountID, participant,
comment,
0,
'USD',
+ created,
+ '',
payeeAccountID,
payeeEmail,
null,
@@ -526,19 +531,23 @@ function createDistanceRequest(report, payeeEmail, payeeAccountID, participant,
* @param {Object} report
* @param {Number} amount - always in the smallest unit of the currency
* @param {String} currency
+ * @param {String} created
+ * @param {String} merchant
* @param {String} payeeEmail
* @param {Number} payeeAccountID
* @param {Object} participant
* @param {String} comment
* @param {Object} [receipt]
*/
-function requestMoney(report, amount, currency, payeeEmail, payeeAccountID, participant, comment, receipt = undefined) {
+function requestMoney(report, amount, currency, created, merchant, payeeEmail, payeeAccountID, participant, comment, receipt = undefined) {
const {payerEmail, iouReport, chatReport, transaction, iouAction, createdChatReportActionID, createdIOUReportActionID, reportPreviewAction, onyxData} = getMoneyRequestInformation(
report,
participant,
comment,
amount,
currency,
+ created,
+ merchant,
payeeAccountID,
payeeEmail,
receipt,
@@ -551,6 +560,8 @@ function requestMoney(report, amount, currency, payeeEmail, payeeAccountID, part
amount,
currency,
comment,
+ created,
+ merchant,
iouReportID: iouReport.reportID,
chatReportID: chatReport.reportID,
transactionID: transaction.transactionID,
@@ -609,6 +620,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
comment,
'',
'',
+ '',
`${Localize.translateLocal('iou.splitBill')} ${Localize.translateLocal('common.with')} ${formattedParticipants} [${DateUtils.getDBTime().slice(0, 10)}]`,
);
@@ -782,6 +794,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
currency,
oneOnOneIOUReport.reportID,
comment,
+ '',
CONST.IOU.MONEY_REQUEST_TYPE.SPLIT,
splitTransaction.transactionID,
);
@@ -982,7 +995,14 @@ function editMoneyRequest(transactionID, transactionThreadReportID, transactionC
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
- value: {pendingAction: null},
+ value: {
+ pendingFields: {
+ comment: null,
+ amount: null,
+ created: null,
+ currency: null,
+ },
+ },
},
];
@@ -1691,6 +1711,13 @@ function setMoneyRequestAmount(amount) {
Onyx.merge(ONYXKEYS.IOU, {amount});
}
+/**
+ * @param {String} created
+ */
+function setMoneyRequestCreated(created) {
+ Onyx.merge(ONYXKEYS.IOU, {created});
+}
+
/**
* @param {String} currency
*/
@@ -1705,6 +1732,13 @@ function setMoneyRequestDescription(comment) {
Onyx.merge(ONYXKEYS.IOU, {comment: comment.trim()});
}
+/**
+ * @param {String} merchant
+ */
+function setMoneyRequestMerchant(merchant) {
+ Onyx.merge(ONYXKEYS.IOU, {merchant: merchant.trim()});
+}
+
/**
* @param {Object[]} participants
*/
@@ -1778,8 +1812,10 @@ export {
resetMoneyRequestInfo,
setMoneyRequestId,
setMoneyRequestAmount,
+ setMoneyRequestCreated,
setMoneyRequestCurrency,
setMoneyRequestDescription,
+ setMoneyRequestMerchant,
setMoneyRequestParticipants,
setMoneyRequestReceipt,
createEmptyTransaction,
diff --git a/src/pages/EditRequestCreatedPage.js b/src/pages/EditRequestCreatedPage.js
index 4e4fce308e5b..79633c214486 100644
--- a/src/pages/EditRequestCreatedPage.js
+++ b/src/pages/EditRequestCreatedPage.js
@@ -31,7 +31,7 @@ function EditRequestCreatedPage({defaultCreated, onSubmit}) {
/>
+
+ );
}
MoneyRequestDescriptionPage.propTypes = propTypes;
MoneyRequestDescriptionPage.defaultProps = defaultProps;
-export default compose(
- withLocalize,
- withOnyx({
- iou: {key: ONYXKEYS.IOU},
- }),
-)(MoneyRequestDescriptionPage);
+export default withOnyx({
+ iou: {
+ key: ONYXKEYS.IOU,
+ },
+})(MoneyRequestDescriptionPage);
diff --git a/src/pages/iou/MoneyRequestMerchantPage.js b/src/pages/iou/MoneyRequestMerchantPage.js
new file mode 100644
index 000000000000..bec9bcb419f7
--- /dev/null
+++ b/src/pages/iou/MoneyRequestMerchantPage.js
@@ -0,0 +1,130 @@
+import React, {useEffect, useRef} from 'react';
+import {View} from 'react-native';
+import {withOnyx} from 'react-native-onyx';
+import PropTypes from 'prop-types';
+import _ from 'underscore';
+import lodashGet from 'lodash/get';
+import TextInput from '../../components/TextInput';
+import ScreenWrapper from '../../components/ScreenWrapper';
+import HeaderWithBackButton from '../../components/HeaderWithBackButton';
+import Form from '../../components/Form';
+import ONYXKEYS from '../../ONYXKEYS';
+import styles from '../../styles/styles';
+import Navigation from '../../libs/Navigation/Navigation';
+import ROUTES from '../../ROUTES';
+import * as IOU from '../../libs/actions/IOU';
+import optionPropTypes from '../../components/optionPropTypes';
+import CONST from '../../CONST';
+import useLocalize from '../../hooks/useLocalize';
+
+const propTypes = {
+ /** Onyx Props */
+ /** Holds data related to Money Request view state, rather than the underlying Money Request data. */
+ iou: PropTypes.shape({
+ id: PropTypes.string,
+ amount: PropTypes.number,
+ comment: PropTypes.string,
+ created: PropTypes.string,
+ merchant: PropTypes.string,
+ participants: PropTypes.arrayOf(optionPropTypes),
+ receiptPath: PropTypes.string,
+ }),
+
+ /** Route from navigation */
+ route: PropTypes.shape({
+ /** Params from the route */
+ params: PropTypes.shape({
+ /** Which field we are editing */
+ field: PropTypes.string,
+
+ /** reportID for the "transaction thread" */
+ threadReportID: PropTypes.string,
+ }),
+ }).isRequired,
+};
+
+const defaultProps = {
+ iou: {
+ id: '',
+ amount: 0,
+ comment: '',
+ merchant: '',
+ participants: [],
+ receiptPath: '',
+ },
+};
+
+function MoneyRequestMerchantPage({iou, route}) {
+ const {translate} = useLocalize();
+ const inputRef = useRef(null);
+ const iouType = lodashGet(route, 'params.iouType', '');
+ const reportID = lodashGet(route, 'params.reportID', '');
+
+ useEffect(() => {
+ const moneyRequestId = `${iouType}${reportID}`;
+ const shouldReset = iou.id !== moneyRequestId;
+ if (shouldReset) {
+ IOU.resetMoneyRequestInfo(moneyRequestId);
+ }
+
+ if (_.isEmpty(iou.participants) || (iou.amount === 0 && !iou.receiptPath) || shouldReset) {
+ Navigation.goBack(ROUTES.getMoneyRequestRoute(iouType, reportID), true);
+ }
+ }, [iou.id, iou.participants, iou.amount, iou.receiptPath, iouType, reportID]);
+
+ function navigateBack() {
+ Navigation.goBack(ROUTES.getMoneyRequestConfirmationRoute(iouType, reportID));
+ }
+
+ /**
+ * Sets the money request comment by saving it to Onyx.
+ *
+ * @param {Object} value
+ * @param {String} value.moneyRequestMerchant
+ */
+ function updateMerchant(value) {
+ IOU.setMoneyRequestMerchant(value.moneyRequestMerchant);
+ navigateBack();
+ }
+
+ return (
+ inputRef.current && inputRef.current.focus()}
+ >
+ navigateBack()}
+ />
+
+
+ );
+}
+
+MoneyRequestMerchantPage.propTypes = propTypes;
+MoneyRequestMerchantPage.defaultProps = defaultProps;
+
+export default withOnyx({
+ iou: {
+ key: ONYXKEYS.IOU,
+ },
+})(MoneyRequestMerchantPage);
diff --git a/src/pages/iou/ReceiptSelector/index.native.js b/src/pages/iou/ReceiptSelector/index.native.js
index 7eeab6e493bd..730e5d1e1dfb 100644
--- a/src/pages/iou/ReceiptSelector/index.native.js
+++ b/src/pages/iou/ReceiptSelector/index.native.js
@@ -38,7 +38,9 @@ const propTypes = {
iou: PropTypes.shape({
id: PropTypes.string,
amount: PropTypes.number,
- currency: PropTypes.string,
+ comment: PropTypes.string,
+ created: PropTypes.string,
+ merchant: PropTypes.string,
participants: PropTypes.arrayOf(participantPropTypes),
}),
};
@@ -54,6 +56,8 @@ const defaultProps = {
iou: {
id: '',
amount: 0,
+ merchant: '',
+ created: '',
currency: CONST.CURRENCY.USD,
participants: [],
},
diff --git a/src/pages/iou/steps/MoneyRequestConfirmPage.js b/src/pages/iou/steps/MoneyRequestConfirmPage.js
index a81e3a8bf825..c22a81cd7299 100644
--- a/src/pages/iou/steps/MoneyRequestConfirmPage.js
+++ b/src/pages/iou/steps/MoneyRequestConfirmPage.js
@@ -30,9 +30,10 @@ const propTypes = {
iou: PropTypes.shape({
id: PropTypes.string,
amount: PropTypes.number,
- receiptPath: PropTypes.string,
- currency: PropTypes.string,
comment: PropTypes.string,
+ created: PropTypes.string,
+ currency: PropTypes.string,
+ merchant: PropTypes.string,
participants: PropTypes.arrayOf(
PropTypes.shape({
accountID: PropTypes.number,
@@ -42,6 +43,7 @@ const propTypes = {
selected: PropTypes.bool,
}),
),
+ receiptPath: PropTypes.string,
}),
/** Personal details of all users */
@@ -58,6 +60,8 @@ const defaultProps = {
amount: 0,
currency: CONST.CURRENCY.USD,
comment: '',
+ merchant: '',
+ created: '',
participants: [],
},
...withCurrentUserPersonalDetailsDefaultProps,
@@ -130,6 +134,8 @@ function MoneyRequestConfirmPage(props) {
props.report,
props.iou.amount,
props.iou.currency,
+ props.iou.created,
+ props.iou.merchant,
props.currentUserPersonalDetails.login,
props.currentUserPersonalDetails.accountID,
selectedParticipants[0],
@@ -137,7 +143,7 @@ function MoneyRequestConfirmPage(props) {
receipt,
);
},
- [props.report, props.iou.amount, props.iou.currency, props.currentUserPersonalDetails.login, props.currentUserPersonalDetails.accountID],
+ [props.report, props.iou.amount, props.iou.currency, props.iou.created, props.iou.merchant, props.currentUserPersonalDetails.login, props.currentUserPersonalDetails.accountID],
);
const createTransaction = useCallback(
@@ -259,8 +265,7 @@ function MoneyRequestConfirmPage(props) {
policyID={props.report.policyID}
bankAccountRoute={ReportUtils.getBankAccountRoute(props.report)}
iouMerchant={props.iou.merchant}
- iouModifiedMerchant={props.iou.modifiedMerchant}
- iouDate={props.iou.date}
+ iouCreated={props.iou.created}
/>
)}
diff --git a/src/pages/iou/steps/NewRequestAmountPage.js b/src/pages/iou/steps/NewRequestAmountPage.js
index 6eda79654e77..e0199d72b01a 100644
--- a/src/pages/iou/steps/NewRequestAmountPage.js
+++ b/src/pages/iou/steps/NewRequestAmountPage.js
@@ -37,6 +37,8 @@ const propTypes = {
id: PropTypes.string,
amount: PropTypes.number,
currency: PropTypes.string,
+ merchant: PropTypes.string,
+ created: PropTypes.string,
participants: PropTypes.arrayOf(
PropTypes.shape({
accountID: PropTypes.number,
@@ -60,6 +62,8 @@ const defaultProps = {
iou: {
id: '',
amount: 0,
+ created: '',
+ merchant: '',
currency: CONST.CURRENCY.USD,
participants: [],
},
diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.js b/src/pages/tasks/TaskAssigneeSelectorModal.js
index 4803fc5b200e..37f9d8815324 100644
--- a/src/pages/tasks/TaskAssigneeSelectorModal.js
+++ b/src/pages/tasks/TaskAssigneeSelectorModal.js
@@ -76,6 +76,7 @@ function TaskAssigneeSelectorModal(props) {
const [filteredPersonalDetails, setFilteredPersonalDetails] = useState([]);
const [filteredUserToInvite, setFilteredUserToInvite] = useState(null);
const [filteredCurrentUserOption, setFilteredCurrentUserOption] = useState(null);
+ const [isLoading, setIsLoading] = React.useState(true);
const updateOptions = useCallback(() => {
const {recentReports, personalDetails, userToInvite, currentUserOption} = OptionsListUtils.getNewChatOptions(
@@ -94,7 +95,10 @@ function TaskAssigneeSelectorModal(props) {
setFilteredRecentReports(recentReports);
setFilteredPersonalDetails(personalDetails);
setFilteredCurrentUserOption(currentUserOption);
- }, [props, searchValue]);
+ if (isLoading) {
+ setIsLoading(false);
+ }
+ }, [props, searchValue, isLoading]);
useEffect(() => {
const debouncedSearch = _.debounce(updateOptions, 200);
@@ -195,7 +199,7 @@ function TaskAssigneeSelectorModal(props) {
onChangeText={onChangeText}
headerMessage={headerMessage}
showTitleTooltip
- shouldShowOptions={didScreenTransitionEnd}
+ shouldShowOptions={didScreenTransitionEnd && !isLoading}
textInputLabel={props.translate('optionsSelector.nameEmailOrPhoneNumber')}
safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle}
/>
diff --git a/tests/actions/IOUTest.js b/tests/actions/IOUTest.js
index 93648aa8ea74..bf32c2ef8f9a 100644
--- a/tests/actions/IOUTest.js
+++ b/tests/actions/IOUTest.js
@@ -35,12 +35,13 @@ describe('actions/IOU', () => {
it('creates new chat if needed', () => {
const amount = 10000;
const comment = 'Giv money plz';
+ const merchant = 'KFC';
let iouReportID;
let createdAction;
let iouAction;
let transactionID;
fetch.pause();
- IOU.requestMoney({}, amount, CONST.CURRENCY.USD, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment);
+ IOU.requestMoney({}, amount, CONST.CURRENCY.USD, '', merchant, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment);
return waitForPromisesToResolve()
.then(
() =>
@@ -141,7 +142,7 @@ describe('actions/IOU', () => {
// The transactionID on the iou action should match the one from the transactions collection
expect(iouAction.originalMessage.IOUTransactionID).toBe(transactionID);
- expect(transaction.merchant).toBe(CONST.REPORT.TYPE.IOU);
+ expect(transaction.merchant).toBe(merchant);
resolve();
},
@@ -205,7 +206,7 @@ describe('actions/IOU', () => {
}),
)
.then(() => {
- IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment);
+ IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment);
return waitForPromisesToResolve();
})
.then(
@@ -396,7 +397,7 @@ describe('actions/IOU', () => {
)
.then(() => Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${existingTransaction.transactionID}`, existingTransaction))
.then(() => {
- IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment);
+ IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment);
return waitForPromisesToResolve();
})
.then(
@@ -528,7 +529,7 @@ describe('actions/IOU', () => {
let iouAction;
let transactionID;
fetch.pause();
- IOU.requestMoney({}, amount, CONST.CURRENCY.USD, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment);
+ IOU.requestMoney({}, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment);
return (
waitForPromisesToResolve()
.then(
@@ -1183,7 +1184,7 @@ describe('actions/IOU', () => {
let createIOUAction;
let payIOUAction;
let transaction;
- IOU.requestMoney({}, amount, CONST.CURRENCY.USD, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment);
+ IOU.requestMoney({}, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment);
return waitForPromisesToResolve()
.then(
() =>