diff --git a/src/CONST.ts b/src/CONST.ts index c5f8f06038d2..c3c93d780d42 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1351,6 +1351,7 @@ const CONST = { CREATE: 'create', MOVE: 'move', CATEGORIZE: 'categorize', + SHARE: 'share', }, DEFAULT_AMOUNT: 0, TYPE: { diff --git a/src/libs/API/parameters/CategorizeTrackedExpenseParams.ts b/src/libs/API/parameters/CategorizeTrackedExpenseParams.ts new file mode 100644 index 000000000000..ce5b6894fe97 --- /dev/null +++ b/src/libs/API/parameters/CategorizeTrackedExpenseParams.ts @@ -0,0 +1,12 @@ +type CategorizeTrackedExpenseParams = { + policyID: string; + transactionID: string; + moneyRequestPreviewReportActionID: string; + moneyRequestReportID: string; + moneyRequestCreatedReportActionID: string; + actionableWhisperReportActionID: string; + // making it optional for now + modifiedExpenseReportActionID?: string; +}; + +export default CategorizeTrackedExpenseParams; diff --git a/src/libs/API/parameters/ShareTrackedExpenseParams.ts b/src/libs/API/parameters/ShareTrackedExpenseParams.ts new file mode 100644 index 000000000000..b007206a4e73 --- /dev/null +++ b/src/libs/API/parameters/ShareTrackedExpenseParams.ts @@ -0,0 +1,12 @@ +type ShareTrackedExpenseParams = { + policyID: string; + transactionID: string; + moneyRequestPreviewReportActionID: string; + moneyRequestReportID: string; + moneyRequestCreatedReportActionID: string; + actionableWhisperReportActionID: string; + // making it optional for now + modifiedExpenseReportActionID?: string; +}; + +export default ShareTrackedExpenseParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 27d522fb1fef..45fb838a6de7 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -200,3 +200,5 @@ export type {default as SetPolicyCurrencyDefaultParams} from './SetPolicyCurrenc export type {default as RenamePolicyTaxParams} from './RenamePolicyTaxParams'; export type {default as DismissTrackExpenseActionableWhisperParams} from './DismissTrackExpenseActionableWhisperParams'; export type {default as ConvertTrackedExpenseToRequestParams} from './ConvertTrackedExpenseToRequestParams'; +export type {default as ShareTrackedExpenseParams} from './ShareTrackedExpenseParams'; +export type {default as CategorizeTrackedExpenseParams} from './CategorizeTrackedExpenseParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 9763fb57c54d..20a95d4e1656 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -198,6 +198,7 @@ const WRITE_COMMANDS = { DISMISS_ACTIONABLE_WHISPER: 'DismissActionableWhisper', CONVERT_TRACKED_EXPENSE_TO_REQUEST: 'ConvertTrackedExpenseToRequest', CATEGORIZE_TRACKED_TRANSACTION: 'CategorizeTrackedExpense', + SHARE_TRACKED_TRANSACTION: 'ShareTrackedExpense', } as const; type WriteCommand = ValueOf; @@ -394,6 +395,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.DISMISS_ACTIONABLE_WHISPER]: Parameters.DismissTrackExpenseActionableWhisperParams; [WRITE_COMMANDS.CONVERT_TRACKED_EXPENSE_TO_REQUEST]: Parameters.ConvertTrackedExpenseToRequestParams; [WRITE_COMMANDS.CATEGORIZE_TRACKED_TRANSACTION]: Parameters.CategorizeTrackedExpenseParams; + [WRITE_COMMANDS.SHARE_TRACKED_TRANSACTION]: Parameters.ShareTrackedExpenseParams; }; const READ_COMMANDS = { diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 4aaeb674167a..33e23d2881d4 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -995,7 +995,7 @@ function buildOnyxDataForTrackExpense( return [optimisticData, successData, failureData]; } -function getDeleteTrackExpenseInformation(chatReportID: string, transactionID: string, reportAction: OnyxTypes.ReportAction) { +function getDeleteTrackExpenseInformation(chatReportID: string, transactionID: string, reportAction: OnyxTypes.ReportAction, shouldDeleteTransactionFromOnyx = true) { // STEP 1: Get all collections we're updating const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`] ?? null; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; @@ -1037,13 +1037,15 @@ function getDeleteTrackExpenseInformation(chatReportID: string, transactionID: s const reportLastMessageText = ReportActionsUtils.getLastVisibleMessage(chatReport?.reportID ?? '', updatedReportAction).lastMessageText; // STEP 4: Build Onyx data - const optimisticData: OnyxUpdate[] = [ - { + const optimisticData: OnyxUpdate[] = []; + + if (shouldDeleteTransactionFromOnyx) { + optimisticData.push({ onyxMethod: Onyx.METHOD.SET, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, value: null, - }, - ]; + }); + } if (Permissions.canUseViolations(betas)) { optimisticData.push({ @@ -1097,13 +1099,15 @@ function getDeleteTrackExpenseInformation(chatReportID: string, transactionID: s }, ]; - const failureData: OnyxUpdate[] = [ - { + const failureData: OnyxUpdate[] = []; + + if (shouldDeleteTransactionFromOnyx) { + failureData.push({ onyxMethod: Onyx.METHOD.SET, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, value: transaction, - }, - ]; + }); + } if (Permissions.canUseViolations(betas)) { failureData.push({ @@ -1339,8 +1343,12 @@ function getMoneyRequestInformation( optimisticNextStep, ); - if(shouldDeleteLinkedTrackedExpense && linkedTrackedExpenseReportAction && linkedTrackedExpenseReportID) { - const {optimisticData: deleteOptimisticData, successData: deleteSuccessData, failureData: deleteFailureData} = getDeleteTrackExpenseInformation(linkedTrackedExpenseReportID, optimisticTransaction.transactionID, linkedTrackedExpenseReportAction); + if (shouldDeleteLinkedTrackedExpense && linkedTrackedExpenseReportAction && linkedTrackedExpenseReportID) { + const { + optimisticData: deleteOptimisticData, + successData: deleteSuccessData, + failureData: deleteFailureData, + } = getDeleteTrackExpenseInformation(linkedTrackedExpenseReportID, optimisticTransaction.transactionID, linkedTrackedExpenseReportAction, false); optimisticData.push(...deleteOptimisticData); successData.push(...deleteSuccessData); failureData.push(...deleteFailureData); @@ -2259,8 +2267,7 @@ function requestMoney( const currentChatReport = isMoneyRequestReport ? ReportUtils.getReport(report.chatReportID) : report; const moneyRequestReportID = isMoneyRequestReport ? report.reportID : ''; const currentCreated = DateUtils.enrichMoneyRequestTimestamp(created); - const isConvertingFromTrackExpenseToRequest = action === CONST.IOU.ACTION.MOVE; - const isCategorizing = action === CONST.IOU.ACTION.CATEGORIZE; + const isMovingTransactionFromTrackExpense = [CONST.IOU.ACTION.MOVE, CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.ACTION.SHARE].includes(action); const { payerAccountID, @@ -2276,7 +2283,7 @@ function requestMoney( createdReportActionIDForThread, onyxData, } = getMoneyRequestInformation( - isConvertingFromTrackExpenseToRequest || isCategorizing ? {} : currentChatReport, + isMovingTransactionFromTrackExpense ? {} : currentChatReport, participant, comment, amount, @@ -2284,7 +2291,7 @@ function requestMoney( currentCreated, merchant, receipt, - isConvertingFromTrackExpenseToRequest || isCategorizing ? (linkedTrackedExpenseReportAction?.originalMessage as IOUMessage)?.IOUTransactionID : undefined, + isMovingTransactionFromTrackExpense ? (linkedTrackedExpenseReportAction?.originalMessage as IOUMessage)?.IOUTransactionID : undefined, category, tag, billable, @@ -2296,7 +2303,7 @@ function requestMoney( moneyRequestReportID, linkedTrackedExpenseReportAction, linkedTrackedExpenseReportID, - isConvertingFromTrackExpenseToRequest || isCategorizing, + isMovingTransactionFromTrackExpense, ); const activeReportID = isMoneyRequestReport ? report.reportID : chatReport.reportID; @@ -2305,14 +2312,16 @@ function requestMoney( case CONST.IOU.ACTION.MOVE: { const parameters = { payerAccountID, - iouReportID: iouReport.reportID, chatReportID: chatReport.reportID, - transactionID: transaction.transactionID, - reportActionID: iouAction.reportActionID, + transactionID: (linkedTrackedExpenseReportAction?.originalMessage as IOUMessage)?.IOUTransactionID, + actionableWhisperReportActionID, createdChatReportActionID, - createdIOUReportActionID, - reportPreviewReportActionID: reportPreviewAction.reportActionID, + moneyRequestReportID: iouReport.reportID, + moneyRequestCreatedReportActionID: createdIOUReportActionID, + moneyRequestPreviewReportActionID: reportPreviewAction.reportActionID, + // modifiedExpenseReportActionID - not sure what need to be done here maybe `buildOptimisticModifiedExpenseReportAction` with transaction changes }; + API.write(WRITE_COMMANDS.CONVERT_TRACKED_EXPENSE_TO_REQUEST, parameters, onyxData); break; } @@ -2320,16 +2329,30 @@ function requestMoney( const parameters = { policyID: chatReport.policyID, transactionID: (linkedTrackedExpenseReportAction?.originalMessage as IOUMessage)?.IOUTransactionID, - actionableWhisperReportActionID, + moneyRequestPreviewReportActionID: reportPreviewAction.reportActionID, moneyRequestReportID: iouReport.reportID, - moneyRequestCreatedReportActionID: createdChatReportActionID, + moneyRequestCreatedReportActionID: createdIOUReportActionID, + actionableWhisperReportActionID, + // modifiedExpenseReportActionID - not sure what need to be done here maybe `buildOptimisticModifiedExpenseReportAction` with transaction changes }; - - console.log('Categorizing tracked expense', parameters); // eslint-disable-next-line rulesdir/no-multiple-api-calls API.write(WRITE_COMMANDS.CATEGORIZE_TRACKED_TRANSACTION, parameters, onyxData); break; } + case CONST.IOU.ACTION.SHARE: { + const parameters = { + policyID: chatReport.policyID, + transactionID: (linkedTrackedExpenseReportAction?.originalMessage as IOUMessage)?.IOUTransactionID, + moneyRequestPreviewReportActionID: reportPreviewAction.reportActionID, + moneyRequestReportID: iouReport.reportID, + moneyRequestCreatedReportActionID: createdIOUReportActionID, + actionableWhisperReportActionID, + // modifiedExpenseReportActionID - not sure what need to be done here maybe `buildOptimisticModifiedExpenseReportAction` with transaction changes + }; + // eslint-disable-next-line rulesdir/no-multiple-api-calls + API.write(WRITE_COMMANDS.SHARE_TRACKED_TRANSACTION, parameters, onyxData); + break; + } default: { const parameters: RequestMoneyParams = { debtorEmail: payerEmail, @@ -2364,7 +2387,14 @@ function requestMoney( resetMoneyRequestInfo(); } } + Navigation.dismissModal(activeReportID); + if (action === CONST.IOU.ACTION.SHARE) { + // not sure the correct way to navigate to the share should it be instant? todo: ask for clarification + setTimeout(() => { + Navigation.navigate(ROUTES.ROOM_MEMBERS.getRoute(activeReportID)); + }, 1000); + } Report.notifyNewAction(activeReportID, payeeAccountID); } diff --git a/src/pages/home/report/ReportActionItem.tsx b/src/pages/home/report/ReportActionItem.tsx index 06aad0f19a48..8e28ac6e3696 100644 --- a/src/pages/home/report/ReportActionItem.tsx +++ b/src/pages/home/report/ReportActionItem.tsx @@ -392,7 +392,7 @@ function ReportActionItem({ { text: 'actionableMentionTrackExpense.share', key: `${action.reportActionID}-actionableMentionTrackExpense-share`, - onPress: () => console.log('Share'), + onPress: () => ReportUtils.createDraftTransactionAndNavigateToParticipantSelector(transactionID, report.reportID, CONST.IOU.ACTION.SHARE, action.reportActionID), isMediumSized: true, }, { diff --git a/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js b/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js index 65d02f757930..2223c45e83cb 100644 --- a/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js +++ b/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js @@ -137,7 +137,7 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({ // sees the option to request money from their admin on their own Workspace Chat. iouType === CONST.IOU.TYPE.REQUEST && iouAction !== CONST.IOU.ACTION.MOVE, - (canUseP2PDistanceRequests || iouRequestType !== CONST.IOU.REQUEST_TYPE.DISTANCE) && iouAction !== CONST.IOU.ACTION.CATEGORIZE, + (canUseP2PDistanceRequests || iouRequestType !== CONST.IOU.REQUEST_TYPE.DISTANCE) && iouAction !== CONST.IOU.ACTION.CATEGORIZE && iouAction !== CONST.IOU.ACTION.SHARE, false, {}, [], @@ -188,7 +188,20 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({ } return [newSections, chatOptions]; - }, [didScreenTransitionEnd, reports, personalDetails, betas, debouncedSearchTerm, participants, iouType, canUseP2PDistanceRequests, iouRequestType, maxParticipantsReached, translate, iouAction]); + }, [ + didScreenTransitionEnd, + reports, + personalDetails, + betas, + debouncedSearchTerm, + participants, + iouType, + canUseP2PDistanceRequests, + iouRequestType, + maxParticipantsReached, + translate, + iouAction, + ]); /** * Adds a single participant to the request @@ -266,7 +279,11 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({ // the app from crashing on native when you try to do this, we'll going to hide the button if you have a workspace and other participants const hasPolicyExpenseChatParticipant = _.some(participants, (participant) => participant.isPolicyExpenseChat); const shouldShowSplitBillErrorMessage = participants.length > 1 && hasPolicyExpenseChatParticipant; - const isAllowedToSplit = (canUseP2PDistanceRequests || iouRequestType !== CONST.IOU.REQUEST_TYPE.DISTANCE) && iouType !== CONST.IOU.TYPE.SEND; + const isAllowedToSplit = + (canUseP2PDistanceRequests || iouRequestType !== CONST.IOU.REQUEST_TYPE.DISTANCE) && + iouType !== CONST.IOU.TYPE.SEND && + ![CONST.IOU.ACTION.SHARE, CONST.IOU.ACTION.MOVE, CONST.IOU.ACTION.CATEGORIZE].includes(iouAction) && + !shouldShowSplitBillErrorMessage; const handleConfirmSelection = useCallback( (keyEvent, option) => { @@ -376,7 +393,7 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({ const isAllSectionsEmpty = _.every(sections, (section) => section.data.length === 0); - if (iouAction === CONST.IOU.ACTION.CATEGORIZE && isAllSectionsEmpty && didScreenTransitionEnd && searchTerm.trim() === '') { + if ([CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.ACTION.SHARE].includes(iouAction) && isAllSectionsEmpty && didScreenTransitionEnd && searchTerm.trim() === '') { return renderEmptyWorkspaceView(); } diff --git a/src/pages/iou/request/step/withFullTransactionOrNotFound.js b/src/pages/iou/request/step/withFullTransactionOrNotFound.js index 1c7b4432254e..a3b028b73578 100644 --- a/src/pages/iou/request/step/withFullTransactionOrNotFound.js +++ b/src/pages/iou/request/step/withFullTransactionOrNotFound.js @@ -72,7 +72,7 @@ export default function (WrappedComponent) { const transactionID = lodashGet(route, 'params.transactionID', 0); const userAction = lodashGet(route, 'params.action', CONST.IOU.ACTION.CREATE); return `${ - [CONST.IOU.ACTION.CREATE, CONST.IOU.ACTION.MOVE, CONST.IOU.ACTION.CATEGORIZE].includes(userAction) + [CONST.IOU.ACTION.CREATE, CONST.IOU.ACTION.MOVE, CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.ACTION.SHARE].includes(userAction) ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION }${transactionID}`;