From fbabcb91961af67be010d1f3ea769abb286543a9 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Wed, 17 Apr 2024 14:34:17 +0200 Subject: [PATCH 0001/1091] implement filtering in new chat page --- src/pages/NewChatPage.tsx | 56 ++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index 8137bb0e8515..b93f24b490b9 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -50,13 +50,14 @@ function useOptions({isGroupChat}: NewChatPageProps) { const {options: listOptions, areOptionsInitialized} = useOptionsList({ shouldInitialize: didScreenTransitionEnd, }); + const maxParticipantsReached = useMemo(() => selectedOptions.length === CONST.REPORT.MAXIMUM_PARTICIPANTS, [selectedOptions.length]); - const options = useMemo(() => { + const defaultOptions = useMemo(() => { const filteredOptions = OptionsListUtils.getFilteredOptions( listOptions.reports ?? [], listOptions.personalDetails ?? [], betas ?? [], - debouncedSearchTerm, + '', selectedOptions, isGroupChat ? excludedGroupEmails : [], false, @@ -69,25 +70,38 @@ function useOptions({isGroupChat}: NewChatPageProps) { [], true, ); - const maxParticipantsReached = selectedOptions.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; - - const headerMessage = OptionsListUtils.getHeaderMessage( - filteredOptions.personalDetails.length + filteredOptions.recentReports.length !== 0, - Boolean(filteredOptions.userToInvite), - debouncedSearchTerm.trim(), - maxParticipantsReached, - selectedOptions.some((participant) => participant?.searchText?.toLowerCase?.().includes(debouncedSearchTerm.trim().toLowerCase())), - ); - return {...filteredOptions, headerMessage, maxParticipantsReached}; - }, [betas, debouncedSearchTerm, isGroupChat, listOptions.personalDetails, listOptions.reports, selectedOptions]); + + return filteredOptions; + }, [betas, isGroupChat, listOptions.personalDetails, listOptions.reports, selectedOptions]); + + const options = useMemo(() => { + if (debouncedSearchTerm.trim() === '') { + return defaultOptions; + } + const filteredOptions = OptionsListUtils.filterOptions(defaultOptions, debouncedSearchTerm, {selectedOptions, excludeLogins: isGroupChat ? excludedGroupEmails : []}); + + return filteredOptions; + }, [debouncedSearchTerm, defaultOptions, isGroupChat, selectedOptions]); + + const headerMessage = useMemo( + () => + OptionsListUtils.getHeaderMessage( + options.personalDetails.length + options.recentReports.length !== 0, + Boolean(options.userToInvite), + debouncedSearchTerm.trim(), + maxParticipantsReached, + selectedOptions.some((participant) => participant?.searchText?.toLowerCase?.().includes(debouncedSearchTerm.trim().toLowerCase())), + ), + [debouncedSearchTerm, maxParticipantsReached, options.personalDetails.length, options.recentReports.length, options.userToInvite, selectedOptions], + ); useEffect(() => { - if (!debouncedSearchTerm.length || options.maxParticipantsReached) { + if (!debouncedSearchTerm.length || maxParticipantsReached) { return; } Report.searchInServer(debouncedSearchTerm); - }, [debouncedSearchTerm, options.maxParticipantsReached]); + }, [debouncedSearchTerm, maxParticipantsReached]); useEffect(() => { if (!newGroupDraft?.participants) { @@ -101,7 +115,17 @@ function useOptions({isGroupChat}: NewChatPageProps) { setSelectedOptions(newSelectedOptions); }, [newGroupDraft, personalData, personalDetails]); - return {...options, searchTerm, debouncedSearchTerm, setSearchTerm, areOptionsInitialized: areOptionsInitialized && didScreenTransitionEnd, selectedOptions, setSelectedOptions}; + return { + ...options, + searchTerm, + debouncedSearchTerm, + setSearchTerm, + areOptionsInitialized: areOptionsInitialized && didScreenTransitionEnd, + selectedOptions, + setSelectedOptions, + headerMessage, + maxParticipantsReached, + }; } function NewChatPage({isGroupChat}: NewChatPageProps) { From 6ab6a13fba69b8e87eae7d5c0ca1f39881578b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 25 Apr 2024 15:57:46 -0600 Subject: [PATCH 0002/1091] Display submitted message in report action --- src/pages/home/report/ReportActionItem.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/home/report/ReportActionItem.tsx b/src/pages/home/report/ReportActionItem.tsx index efb2d8ba73fb..cde76434f382 100644 --- a/src/pages/home/report/ReportActionItem.tsx +++ b/src/pages/home/report/ReportActionItem.tsx @@ -39,6 +39,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import ControlSelection from '@libs/ControlSelection'; +import * as CurrencyUtils from '@libs/CurrencyUtils'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import * as ErrorUtils from '@libs/ErrorUtils'; import focusTextInputAfterAnimation from '@libs/focusTextInputAfterAnimation'; @@ -580,6 +581,9 @@ function ReportActionItem({ } else if (ReportActionsUtils.isOldDotReportAction(action)) { // This handles all historical actions from OldDot that we just want to display the message text children = ; + } else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.SUBMITTED) { + const formattedAmount = CurrencyUtils.convertToDisplayString(Math.abs(report.total), report.currency); + children = ; } else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.HOLD) { children = ; } else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.HOLD_COMMENT) { From 8388c28b4d7c999b644efba595cfe3468a190e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 25 Apr 2024 16:11:57 -0600 Subject: [PATCH 0003/1091] Fix ts error --- src/pages/home/report/ReportActionItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionItem.tsx b/src/pages/home/report/ReportActionItem.tsx index cde76434f382..d3c0430ba02e 100644 --- a/src/pages/home/report/ReportActionItem.tsx +++ b/src/pages/home/report/ReportActionItem.tsx @@ -582,7 +582,7 @@ function ReportActionItem({ // This handles all historical actions from OldDot that we just want to display the message text children = ; } else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.SUBMITTED) { - const formattedAmount = CurrencyUtils.convertToDisplayString(Math.abs(report.total), report.currency); + const formattedAmount = CurrencyUtils.convertToDisplayString(Math.abs(report?.total ?? 0), report.currency); children = ; } else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.HOLD) { children = ; From 39d7f11c826e9a43295970c2ddbf857d0b161195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 1 May 2024 15:25:54 -0600 Subject: [PATCH 0004/1091] Set SUBMITTED message to clipboard --- src/pages/home/report/ContextMenu/ContextMenuActions.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index 013bc484fc63..8e0eddf7ceb6 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -30,6 +30,7 @@ import type {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; import type {Beta, ReportAction, ReportActionReactions, Transaction} from '@src/types/onyx'; import type IconAsset from '@src/types/utils/IconAsset'; +import * as CurrencyUtils from '@libs/CurrencyUtils'; import type {ContextMenuAnchor} from './ReportActionContextMenu'; import {hideContextMenu, showDeleteModal} from './ReportActionContextMenu'; @@ -360,6 +361,10 @@ const ContextMenuActions: ContextMenuAction[] = [ setClipboardMessage(mentionWhisperMessage); } else if (ReportActionsUtils.isActionableTrackExpense(reportAction)) { setClipboardMessage('What would you like to do with this expense?'); + } else if (reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.SUBMITTED) { + const expenseReport = ReportUtils.getReport(reportID); + const formattedAmount = CurrencyUtils.convertToDisplayString(Math.abs(expenseReport?.total ?? 0), expenseReport?.currency); + setClipboardMessage(Localize.translateLocal('iou.submittedAmount', {formattedAmount})); } else if (reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.HOLD) { Clipboard.setString(Localize.translateLocal('iou.heldExpense')); } else if (reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.UNHOLD) { From e7bb1533279afe058e97793d06a51087c7989e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 1 May 2024 15:34:45 -0600 Subject: [PATCH 0005/1091] Fix linting --- src/pages/home/report/ContextMenu/ContextMenuActions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index 8e0eddf7ceb6..5021e888ea84 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -12,6 +12,7 @@ import MiniQuickEmojiReactions from '@components/Reactions/MiniQuickEmojiReactio import QuickEmojiReactions from '@components/Reactions/QuickEmojiReactions'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; import Clipboard from '@libs/Clipboard'; +import * as CurrencyUtils from '@libs/CurrencyUtils'; import EmailUtils from '@libs/EmailUtils'; import * as Environment from '@libs/Environment/Environment'; import fileDownload from '@libs/fileDownload'; @@ -30,7 +31,6 @@ import type {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; import type {Beta, ReportAction, ReportActionReactions, Transaction} from '@src/types/onyx'; import type IconAsset from '@src/types/utils/IconAsset'; -import * as CurrencyUtils from '@libs/CurrencyUtils'; import type {ContextMenuAnchor} from './ReportActionContextMenu'; import {hideContextMenu, showDeleteModal} from './ReportActionContextMenu'; From 59d4c25a0ef65c993bab01796846eaef9912110f Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Fri, 10 May 2024 11:09:23 +0200 Subject: [PATCH 0006/1091] feat: add review fields screens, add function to detect which fields are the same across transaction which are different add navigation to screen of fields which we want to review --- src/ROUTES.ts | 32 ++++---- src/SCREENS.ts | 11 ++- .../MoneyRequestPreviewContent.tsx | 81 ++++++++++++++++++- .../ModalStackNavigators/index.tsx | 7 ++ .../DuplicateTransactionItem.tsx | 37 +++++---- .../DuplicateTransactionsList.tsx | 4 + src/pages/TransactionDuplicate/Review.tsx | 4 +- .../TransactionDuplicate/ReviewBillable.tsx | 7 ++ .../TransactionDuplicate/ReviewCategory.tsx | 8 ++ .../ReviewDescription.tsx | 7 ++ .../TransactionDuplicate/ReviewFields.tsx | 7 ++ .../TransactionDuplicate/ReviewMerchant.tsx | 14 ++++ .../ReviewReimbursable.tsx | 7 ++ src/pages/TransactionDuplicate/ReviewTag.tsx | 7 ++ .../TransactionDuplicate/ReviewTaxRate.tsx | 7 ++ 15 files changed, 199 insertions(+), 41 deletions(-) create mode 100644 src/pages/TransactionDuplicate/ReviewBillable.tsx create mode 100644 src/pages/TransactionDuplicate/ReviewCategory.tsx create mode 100644 src/pages/TransactionDuplicate/ReviewDescription.tsx create mode 100644 src/pages/TransactionDuplicate/ReviewFields.tsx create mode 100644 src/pages/TransactionDuplicate/ReviewMerchant.tsx create mode 100644 src/pages/TransactionDuplicate/ReviewReimbursable.tsx create mode 100644 src/pages/TransactionDuplicate/ReviewTag.tsx create mode 100644 src/pages/TransactionDuplicate/ReviewTaxRate.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 0a2274263fa5..fc9cda63a80f 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -776,22 +776,22 @@ const ROUTES = { route: 'r/:threadReportID/duplicates/review', getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review` as const, }, - // TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE: { - // route: 'r/:threadReportID/duplicates/review/merchant', - // getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review/merchant` as const, - // }, - // TRANSACTION_DUPLICATE_REVIEW_CATEGORY_PAGE: { - // route: 'r/:threadReportID/duplicates/review/category', - // getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review/category` as const, - // }, - // TRANSACTION_DUPLICATE_REVIEW_TAG_PAGE: { - // route: 'r/:threadReportID/duplicates/review/tag', - // getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review/tag` as const, - // }, - // TRANSACTION_DUPLICATE_REVIEW_DESCRIPTION_PAGE: { - // route: 'r/:threadReportID/duplicates/confirm', - // getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/confirm` as const, - // }, + TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE: { + route: 'r/:threadReportID/duplicates/review/merchant', + getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review/merchant` as const, + }, + TRANSACTION_DUPLICATE_REVIEW_CATEGORY_PAGE: { + route: 'r/:threadReportID/duplicates/review/category', + getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review/category` as const, + }, + TRANSACTION_DUPLICATE_REVIEW_TAG_PAGE: { + route: 'r/:threadReportID/duplicates/review/tag', + getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review/tag` as const, + }, + TRANSACTION_DUPLICATE_REVIEW_DESCRIPTION_PAGE: { + route: 'r/:threadReportID/duplicates/confirm', + getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/confirm` as const, + }, // TRANSACTION_DUPLICATE_CONFIRM: { // route: 'r/:threadReportID/duplicates/review/description', // getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review/description` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index bdc8fa19384e..92ce832be0c9 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -180,10 +180,13 @@ const SCREENS = { TRANSACTION_DUPLICATE: { REVIEW: 'Transaction_Duplicate_Review', - // MERCHANT: 'Transaction_Duplicate_Merchant', - // CATEGORY: 'Transaction_Duplicate_Category', - // TAG: 'Transaction_Duplicate_Tag', - // DESCRIPTION: 'Transaction_Duplicate_Description', + MERCHANT: 'Transaction_Duplicate_Merchant', + CATEGORY: 'Transaction_Duplicate_Category', + TAG: 'Transaction_Duplicate_Tag', + DESCRIPTION: 'Transaction_Duplicate_Description', + TAX_RATE: 'Transaction_Duplicate_Tax_Rate', + BILLABLE: 'Transaction_Duplicate_Billable', + REIMBURSABLE: 'Transaction_Duplicate_Reimburable', // CONFIRM: 'Transaction_Duplicate_Confirm', }, diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 1fe8694f1add..0d790b2bce58 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -1,9 +1,12 @@ +import type {RouteProp} from '@react-navigation/native'; import {useRoute} from '@react-navigation/native'; import {truncate} from 'lodash'; import lodashSortBy from 'lodash/sortBy'; import React, {useMemo} from 'react'; import {View} from 'react-native'; import type {GestureResponderEvent} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import Button from '@components/Button'; import ConfirmedRoute from '@components/ConfirmedRoute'; import Icon from '@components/Icon'; @@ -24,6 +27,8 @@ import ControlSelection from '@libs/ControlSelection'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import * as IOUUtils from '@libs/IOUUtils'; +import Navigation from '@libs/Navigation/Navigation'; +import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; @@ -35,7 +40,9 @@ import * as Report from '@userActions/Report'; import * as Transaction from '@userActions/Transaction'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; +import type {Transaction as OnyxTransaction} from '@src/types/onyx'; import type {IOUMessage} from '@src/types/onyx/OriginalMessage'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -105,8 +112,11 @@ function MoneyRequestPreviewContent({ const isFullyApproved = ReportUtils.isReportApproved(iouReport) && !isSettlementOrApprovalPartial; const shouldShowRBR = hasNoticeTypeViolations || hasViolations || hasFieldErrors || (!isFullySettled && !isFullyApproved && isOnHold); + const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params?.threadReportID as string}`); + const parentReportAction = ReportActionsUtils.getReportAction(report?.parentReportID ?? '', report?.parentReportActionID ?? ''); + const reviewingTransactionID = parentReportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.IOU ? parentReportAction?.originalMessage.IOUTransactionID ?? '0' : '0'; const duplicates = - transactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction?.transactionID}`]?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION) + transactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${reviewingTransactionID}`]?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION) ?.data?.duplicates ?? []; /* @@ -235,6 +245,71 @@ function MoneyRequestPreviewContent({ [shouldShowSplitShare, isPolicyExpenseChat, action.actorAccountID, participantAccountIDs.length, transaction?.comment?.splits, requestAmount, requestCurrency, sessionAccountID], ); + type FieldsToCompare = Record>; + + const compareFields = (transactions: Array>, fields: FieldsToCompare) => { + const keep: Record = {}; + const change: Record = {}; + + for (const fieldName in fields) { + if (Object.prototype.hasOwnProperty.call(fields, fieldName)) { + const keys = fields[fieldName]; + const firstTransaction = transactions[0]; + + if (transactions.every((item) => keys.every((key) => item && key in item && item[key] === firstTransaction?.[key]))) { + keep[fieldName] = firstTransaction?.[keys[0]]; + } else { + const differentValues = transactions + .map((item) => keys.map((key) => item?.[key])) + .flat() + .filter(Boolean); + + if (differentValues.length > 0) { + change[fieldName] = differentValues; + } + } + } + } + + return {keep, change}; + }; + + const navigateToReviewFields = () => { + const fieldsToCompare: FieldsToCompare = { + merchant: ['modifiedMerchant', 'merchant'], + category: ['category'], + tag: ['tag'], + description: ['comment'], + taxCode: ['taxCode'], + billable: ['billable'], + reimbursable: ['reimbursable'], + }; + const transactions = [reviewingTransactionID, ...duplicates].map((item) => TransactionUtils.getTransaction(item)); + const comparisonResult = compareFields(transactions, fieldsToCompare); + + console.log('transactions', transactions); + console.log(comparisonResult); + + Transaction.setReviewDuplicatesKey(transaction?.transactionID ?? '', {...comparisonResult.keep, duplicates}); + + if ('merchant' in comparisonResult.change) { + console.log('navigate to merchant'); + Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE.getRoute(route.params?.threadReportID)); + } else if ('category' in comparisonResult.change) { + console.log('navigate to category'); + Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_CATEGORY_PAGE.getRoute(route.params?.threadReportID)); + } else if ('tag' in comparisonResult.change) { + console.log('navigate to tag'); + Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_TAG_PAGE.getRoute(route.params.threadReportID)); + } else if ('description' in comparisonResult.change) { + console.log('navigate to description'); + Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_DESCRIPTION_PAGE.getRoute(route.params.threadReportID)); + } else { + console.log('navigate to summary'); + // Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_SUMMARY_PAGE.getRoute(route.params.threadReportID)); + } + }; + const childContainer = ( { - Transaction.setReviewDuplicatesKey(transaction?.transactionID ?? '', duplicates); - }} + onPress={navigateToReviewFields} /> )} diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 07cf6cb0f938..e8463eea3a2a 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -366,6 +366,13 @@ const ProcessMoneyRequestHoldStackNavigator = createModalStackNavigator({ const TransactionDuplicateStackNavigator = createModalStackNavigator({ [SCREENS.TRANSACTION_DUPLICATE.REVIEW]: () => require('../../../../pages/TransactionDuplicate/Review').default as React.ComponentType, + [SCREENS.TRANSACTION_DUPLICATE.MERCHANT]: () => require('../../../../pages/TransactionDuplicate/ReviewMerchant').default as React.ComponentType, + [SCREENS.TRANSACTION_DUPLICATE.CATEGORY]: () => require('../../../../pages/TransactionDuplicate/ReviewCategory').default as React.ComponentType, + [SCREENS.TRANSACTION_DUPLICATE.TAG]: () => require('../../../../pages/TransactionDuplicate/ReviewTag').default as React.ComponentType, + [SCREENS.TRANSACTION_DUPLICATE.DESCRIPTION]: () => require('../../../../pages/TransactionDuplicate/ReviewDescription').default as React.ComponentType, + [SCREENS.TRANSACTION_DUPLICATE.TAX_RATE]: () => require('../../../../pages/TransactionDuplicate/ReviewTaxRate').default as React.ComponentType, + [SCREENS.TRANSACTION_DUPLICATE.BILLABLE]: () => require('../../../../pages/TransactionDuplicate/ReviewBillable').default as React.ComponentType, + [SCREENS.TRANSACTION_DUPLICATE.REIMBURSABLE]: () => require('../../../../pages/TransactionDuplicate/ReviewReimbursable').default as React.ComponentType, }); const SearchReportModalStackNavigator = createModalStackNavigator({ diff --git a/src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx b/src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx index ee842dc0611f..4465411bcecc 100644 --- a/src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx +++ b/src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx @@ -1,6 +1,8 @@ import React from 'react'; +import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {useOnyx} from 'react-native-onyx'; +import useThemeStyles from '@hooks/useThemeStyles'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import ReportActionItem from '@pages/home/report/ReportActionItem'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -12,28 +14,31 @@ type DuplicateTransactionItemProps = { }; function DuplicateTransactionItem(props: DuplicateTransactionItemProps) { + const styles = useThemeStyles(); const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${props.transaction?.reportID}`); const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`); const parentReportAction = ReportActionsUtils.getReportAction(report?.parentReportID ?? '', report?.parentReportActionID ?? ''); return ( - + reportAction.actionName === 'IOU' && reportAction.originalMessage?.IOUTransactionID === props.transaction?.transactionID, + ) as ReportAction + } // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style - Object.values(reportActions ?? {})?.find( - (reportAction) => reportAction.actionName === 'IOU' && reportAction.originalMessage.IOUTransactionID === props.transaction?.transactionID, - ) as ReportAction - } - // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style - report={report as Report} - parentReportAction={parentReportAction} - index={props.index} - reportActions={Object.values(reportActions ?? {})} - displayAsGroup={false} - shouldDisplayNewMarker={false} - isMostRecentIOUReportAction={false} - isFirstVisibleReportAction={false} - /> + report={report as Report} + parentReportAction={parentReportAction} + index={props.index} + reportActions={Object.values(reportActions ?? {})} + displayAsGroup={false} + shouldDisplayNewMarker={false} + isMostRecentIOUReportAction={false} + isFirstVisibleReportAction={false} + /> + ); } diff --git a/src/pages/TransactionDuplicate/DuplicateTransactionsList.tsx b/src/pages/TransactionDuplicate/DuplicateTransactionsList.tsx index 3f2f158fe841..03b02c744154 100644 --- a/src/pages/TransactionDuplicate/DuplicateTransactionsList.tsx +++ b/src/pages/TransactionDuplicate/DuplicateTransactionsList.tsx @@ -2,6 +2,7 @@ import React from 'react'; import type {FlatListProps, ScrollViewProps} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import FlatList from '@components/FlatList'; +import useThemeStyles from '@hooks/useThemeStyles'; import type {Transaction} from '@src/types/onyx'; import DuplicateTransactionItem from './DuplicateTransactionItem'; @@ -23,12 +24,15 @@ const maintainVisibleContentPosition: ScrollViewProps['maintainVisibleContentPos }; function DuplicateTransactionsList({transactions}: DuplicateTransactionsListProps) { + const styles = useThemeStyles(); + return ( ); } diff --git a/src/pages/TransactionDuplicate/Review.tsx b/src/pages/TransactionDuplicate/Review.tsx index 49f2185ee446..239d1d0e8ed2 100644 --- a/src/pages/TransactionDuplicate/Review.tsx +++ b/src/pages/TransactionDuplicate/Review.tsx @@ -31,6 +31,8 @@ function TransactionDuplicateReview() { [transactionViolations], ); + console.log('transactionID', transactionID); + const transactions = [transactionID, ...duplicateTransactionIDs].map((item) => TransactionUtils.getTransaction(item)).sort((a, b) => new Date(a.created) - new Date(b.created)); const keepAll = () => { @@ -41,7 +43,7 @@ function TransactionDuplicateReview() { return ( - +