From 206eb2bd297a23eefb49f833f33e1ab8b79e66c4 Mon Sep 17 00:00:00 2001
From: Agata Kosior <agata.kosior57@gmail.com>
Date: Thu, 17 Aug 2023 09:00:05 +0200
Subject: [PATCH 1/5] feat: grey out the headers as soon as the user goes
 offline

---
 src/components/OfflineWithFeedback.js         |  6 +-
 .../ReportActionItem/MoneyRequestView.js      | 55 +++++++++++--------
 src/pages/home/report/ReportActionItem.js     | 10 ++--
 3 files changed, 38 insertions(+), 33 deletions(-)

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 c05cf14f2fc1..17d219dce4fd 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 */
@@ -97,30 +98,36 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic
                     style={[StyleUtils.getReportWelcomeBackgroundImageStyle(true)]}
                 />
             </View>
-            <MenuItemWithTopDescription
-                title={formattedTransactionAmount}
-                shouldShowTitleIcon={isSettled}
-                titleIcon={Expensicons.Checkmark}
-                description={description}
-                titleStyle={styles.newKansasLarge}
-                disabled={isSettled || !canEdit}
-                shouldShowRightIcon={canEdit}
-                onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))}
-            />
-            <MenuItemWithTopDescription
-                description={translate('common.description')}
-                title={transactionDescription}
-                disabled={isSettled || !canEdit}
-                shouldShowRightIcon={canEdit}
-                onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))}
-            />
-            <MenuItemWithTopDescription
-                description={translate('common.date')}
-                title={transactionDate}
-                disabled={isSettled || !canEdit}
-                shouldShowRightIcon={canEdit}
-                onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))}
-            />
+            <OfflineWithFeedback
+                // wrapping only the menu items - we don't want the background image to be greyed out;
+                // we want to grey out the items as soon as the user goes offline
+                pendingAction={CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}
+            >
+                <MenuItemWithTopDescription
+                    title={formattedTransactionAmount}
+                    shouldShowTitleIcon={isSettled}
+                    titleIcon={Expensicons.Checkmark}
+                    description={description}
+                    titleStyle={styles.newKansasLarge}
+                    disabled={isSettled || !canEdit}
+                    shouldShowRightIcon={canEdit}
+                    onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))}
+                />
+                <MenuItemWithTopDescription
+                    description={translate('common.description')}
+                    title={transactionDescription}
+                    disabled={isSettled || !canEdit}
+                    shouldShowRightIcon={canEdit}
+                    onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))}
+                />
+                <MenuItemWithTopDescription
+                    description={translate('common.date')}
+                    title={transactionDate}
+                    disabled={isSettled || !canEdit}
+                    shouldShowRightIcon={canEdit}
+                    onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))}
+                />
+            </OfflineWithFeedback>
             {shouldShowHorizontalRule && <View style={styles.reportHorizontalRule} />}
         </View>
     );
diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js
index 8700327a168a..323329590f3d 100644
--- a/src/pages/home/report/ReportActionItem.js
+++ b/src/pages/home/report/ReportActionItem.js
@@ -468,12 +468,10 @@ function ReportActionItem(props) {
         const parentReportAction = ReportActionsUtils.getParentReportAction(props.report);
         if (ReportActionsUtils.isTransactionThread(parentReportAction)) {
             return (
-                <OfflineWithFeedback pendingAction={props.action.pendingAction}>
-                    <MoneyRequestView
-                        report={props.report}
-                        shouldShowHorizontalRule={!props.shouldHideThreadDividerLine}
-                    />
-                </OfflineWithFeedback>
+                <MoneyRequestView
+                    report={props.report}
+                    shouldShowHorizontalRule={!props.shouldHideThreadDividerLine}
+                />
             );
         }
         if (ReportUtils.isTaskReport(props.report)) {

From 2d254888c9abf4758f19df6acd5b56f6575fd579 Mon Sep 17 00:00:00 2001
From: Agata Kosior <agata.kosior57@gmail.com>
Date: Thu, 17 Aug 2023 15:50:06 +0200
Subject: [PATCH 2/5] feat: create a function for getting a proper message
 schema

---
 src/libs/ReportUtils.js | 36 +++++++++++++++++++++++++++++++-----
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js
index 1baf6eacb9da..db4a210845bf 100644
--- a/src/libs/ReportUtils.js
+++ b/src/libs/ReportUtils.js
@@ -1190,7 +1190,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')}`;
@@ -1288,6 +1291,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 request ${valueName} to ${newValueToDisplay}`;
+    }
+    if (!newValue) {
+        return `removed the request ${valueName} (previously ${oldValueToDisplay})`;
+    }
+    return `changed the request ${valueName} to ${newValueToDisplay} (previously ${oldValueToDisplay})`;
+}
+
 /**
  * Get the report action message when expense has been modified.
  *
@@ -1312,17 +1338,17 @@ 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');
@@ -1330,7 +1356,7 @@ function getModifiedExpenseMessage(reportAction) {
         // Take only the YYYY-MM-DD value as the original date includes timestamp
         let formattedOldCreated = new Date(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);
     }
 }
 

From f776dc5bc9c7ac8859c65977ff350b9071c24e91 Mon Sep 17 00:00:00 2001
From: Agata Kosior <agata.kosior57@gmail.com>
Date: Thu, 17 Aug 2023 18:24:22 +0200
Subject: [PATCH 3/5] fix: remove request word from the message

---
 src/libs/ReportUtils.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js
index db4a210845bf..54aee8ab4742 100644
--- a/src/libs/ReportUtils.js
+++ b/src/libs/ReportUtils.js
@@ -1306,12 +1306,12 @@ function getProperSchemaForModifiedExpenseMessage(newValue, oldValue, valueName,
     const oldValueToDisplay = valueInQuotes ? `"${oldValue}"` : oldValue;
 
     if (!oldValue) {
-        return `set the request ${valueName} to ${newValueToDisplay}`;
+        return `set the ${valueName} to ${newValueToDisplay}`;
     }
     if (!newValue) {
-        return `removed the request ${valueName} (previously ${oldValueToDisplay})`;
+        return `removed the ${valueName} (previously ${oldValueToDisplay})`;
     }
-    return `changed the request ${valueName} to ${newValueToDisplay} (previously ${oldValueToDisplay})`;
+    return `changed the ${valueName} to ${newValueToDisplay} (previously ${oldValueToDisplay})`;
 }
 
 /**

From 782ae858504df880e10ea843ba9feedb86b83f33 Mon Sep 17 00:00:00 2001
From: Ana Margarida Silva <ana.margarida.silva@callstack.com>
Date: Fri, 18 Aug 2023 12:00:49 +0100
Subject: [PATCH 4/5] feat: only grey out updated fields

---
 src/components/ReportActionItem/MoneyRequestView.js | 10 +++++-----
 src/libs/TransactionUtils.js                        |  7 ++++++-
 src/libs/actions/IOU.js                             |  9 ++++++++-
 3 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js
index 17d219dce4fd..e992f16ba409 100644
--- a/src/components/ReportActionItem/MoneyRequestView.js
+++ b/src/components/ReportActionItem/MoneyRequestView.js
@@ -98,11 +98,7 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic
                     style={[StyleUtils.getReportWelcomeBackgroundImageStyle(true)]}
                 />
             </View>
-            <OfflineWithFeedback
-                // wrapping only the menu items - we don't want the background image to be greyed out;
-                // we want to grey out the items as soon as the user goes offline
-                pendingAction={CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}
-            >
+            <OfflineWithFeedback pendingAction={lodashGet(transaction, 'pendingFields.amount')}>
                 <MenuItemWithTopDescription
                     title={formattedTransactionAmount}
                     shouldShowTitleIcon={isSettled}
@@ -113,6 +109,8 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic
                     shouldShowRightIcon={canEdit}
                     onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))}
                 />
+            </OfflineWithFeedback>
+            <OfflineWithFeedback pendingAction={lodashGet(transaction, 'pendingFields.comment')}>
                 <MenuItemWithTopDescription
                     description={translate('common.description')}
                     title={transactionDescription}
@@ -120,6 +118,8 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic
                     shouldShowRightIcon={canEdit}
                     onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))}
                 />
+            </OfflineWithFeedback>
+            <OfflineWithFeedback pendingAction={lodashGet(transaction, 'pendingFields.created')}>
                 <MenuItemWithTopDescription
                     description={translate('common.date')}
                     title={transactionDate}
diff --git a/src/libs/TransactionUtils.js b/src/libs/TransactionUtils.js
index a8fd828d07d4..e5dbce41e654 100644
--- a/src/libs/TransactionUtils.js
+++ b/src/libs/TransactionUtils.js
@@ -86,7 +86,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;
 }
diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js
index c5e2c532a888..a404a483af78 100644
--- a/src/libs/actions/IOU.js
+++ b/src/libs/actions/IOU.js
@@ -841,7 +841,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,
+                },
+            },
         },
     ];
 

From 54cb2c41c5aa3661bb70551cb67bd447fc479237 Mon Sep 17 00:00:00 2001
From: Ana Margarida Silva <ana.margarida.silva@callstack.com>
Date: Fri, 18 Aug 2023 16:42:06 +0100
Subject: [PATCH 5/5] fix: grey out when pendingAction is ADD

---
 src/components/ReportActionItem/MoneyRequestView.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js
index e992f16ba409..fdaa558dfd0b 100644
--- a/src/components/ReportActionItem/MoneyRequestView.js
+++ b/src/components/ReportActionItem/MoneyRequestView.js
@@ -98,7 +98,7 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic
                     style={[StyleUtils.getReportWelcomeBackgroundImageStyle(true)]}
                 />
             </View>
-            <OfflineWithFeedback pendingAction={lodashGet(transaction, 'pendingFields.amount')}>
+            <OfflineWithFeedback pendingAction={lodashGet(transaction, 'pendingFields.amount') || lodashGet(transaction, 'pendingAction')}>
                 <MenuItemWithTopDescription
                     title={formattedTransactionAmount}
                     shouldShowTitleIcon={isSettled}
@@ -110,7 +110,7 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic
                     onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))}
                 />
             </OfflineWithFeedback>
-            <OfflineWithFeedback pendingAction={lodashGet(transaction, 'pendingFields.comment')}>
+            <OfflineWithFeedback pendingAction={lodashGet(transaction, 'pendingFields.comment') || lodashGet(transaction, 'pendingAction')}>
                 <MenuItemWithTopDescription
                     description={translate('common.description')}
                     title={transactionDescription}
@@ -119,7 +119,7 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic
                     onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))}
                 />
             </OfflineWithFeedback>
-            <OfflineWithFeedback pendingAction={lodashGet(transaction, 'pendingFields.created')}>
+            <OfflineWithFeedback pendingAction={lodashGet(transaction, 'pendingFields.created') || lodashGet(transaction, 'pendingAction')}>
                 <MenuItemWithTopDescription
                     description={translate('common.date')}
                     title={transactionDate}
