Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions src/components/ReportActionItem/TransactionPreview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type {TransactionDuplicateNavigatorParamList} from '@navigation/types';
import {clearWalletTermsError} from '@userActions/PaymentMethods';
import {clearIOUError} from '@userActions/Report';
import CONST from '@src/CONST';
import useTransactionsByID from '@src/hooks/useTransactionsByID';
import ONYXKEYS from '@src/ONYXKEYS';
import SCREENS from '@src/SCREENS';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
Expand Down Expand Up @@ -57,14 +58,7 @@ function TransactionPreview(props: TransactionPreviewProps) {

// Get transaction violations for given transaction id from onyx, find duplicated transactions violations and get duplicates
const allDuplicateIDs = useMemo(() => violations?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION)?.data?.duplicates ?? [], [violations]);
const [allDuplicates] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: (allTransactions) => allDuplicateIDs.map((id) => allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]),
canBeMissing: true,
},
[allDuplicateIDs],
);
const [allDuplicates] = useTransactionsByID(allDuplicateIDs);
const duplicates = useMemo(() => removeSettledAndApprovedTransactions(allDuplicates ?? []), [allDuplicates]);
const sessionAccountID = session?.accountID;
const areThereDuplicates = allDuplicateIDs.length > 0 && duplicates.length > 0 && allDuplicateIDs.length === duplicates.length;
Expand Down
19 changes: 15 additions & 4 deletions src/hooks/useReportTransactions.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {useCallback} from 'react';
import type {OnyxCollection} from 'react-native-onyx';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Transaction} from '@src/types/onyx';
import getEmptyArray from '@src/types/utils/getEmptyArray';
Expand All @@ -7,16 +9,25 @@ import useOnyx from './useOnyx';
* Hook to get all transactions for a specific report
*/
function useReportTransactions(reportID: string | undefined): Transaction[] {
const [reportTransactions = getEmptyArray<Transaction>()] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {
selector: (transactions) => {
const reportTransactionsSelector = useCallback(
(transactions: OnyxCollection<Transaction>) => {
if (!transactions || !reportID) {
return [];
}

return Object.values(transactions).filter((transaction): transaction is Transaction => !!transaction && transaction.reportID === reportID);
},
canBeMissing: true,
});
[reportID],
);

const [reportTransactions = getEmptyArray<Transaction>()] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: reportTransactionsSelector,
canBeMissing: true,
},
[reportTransactionsSelector],
);

return reportTransactions;
}
Expand Down
25 changes: 25 additions & 0 deletions src/hooks/useTransactionsByID.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {useCallback} from 'react';
import type {OnyxCollection} from 'react-native-onyx';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Transaction} from '@src/types/onyx';
import useOnyx from './useOnyx';

function useTransactionsByID(transactionIDs: string[] | undefined) {
const transactionsSelector = useCallback(
(transactions: OnyxCollection<Transaction>) => transactionIDs?.map((id) => transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]) ?? [],
[transactionIDs],
);

const [transactions] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: transactionsSelector,
canBeMissing: true,
},
[transactionsSelector],
);

return [transactions];
}

export default useTransactionsByID;
26 changes: 18 additions & 8 deletions src/hooks/useTripTransactions.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {useCallback} from 'react';
import type {OnyxCollection} from 'react-native-onyx';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Transaction} from '@src/types/onyx';
import getEmptyArray from '@src/types/utils/getEmptyArray';
Expand All @@ -19,19 +21,27 @@ function useTripTransactions(reportID: string | undefined): Transaction[] {
Object.values(reports ?? {})
.filter((report) => report && report.chatReportID === reportID)
.map((report) => report?.reportID),
canBeMissing: true,
});

const tripTransactionsSelector = useCallback(
(transactions: OnyxCollection<Transaction>) => {
if (!tripTransactionReportIDs.length) {
return [];
}

return Object.values(transactions ?? {}).filter((transaction): transaction is Transaction => !!transaction && tripTransactionReportIDs.includes(transaction.reportID));
},
[tripTransactionReportIDs],
);

const [tripTransactions = getEmptyArray<Transaction>()] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: (transactions) => {
if (!tripTransactionReportIDs.length) {
return [];
}

return Object.values(transactions ?? {}).filter((transaction): transaction is Transaction => !!transaction && tripTransactionReportIDs.includes(transaction.reportID));
},
selector: tripTransactionsSelector,
canBeMissing: true,
},
[tripTransactionReportIDs],
[tripTransactionsSelector],
);
return tripTransactions;
}
Expand Down
57 changes: 32 additions & 25 deletions src/pages/AddUnreportedExpense.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useEffect, useMemo, useRef, useState} from 'react';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {InteractionManager} from 'react-native';
import type {OnyxCollection} from 'react-native-onyx';
import EmptyStateComponent from '@components/EmptyStateComponent';
Expand Down Expand Up @@ -56,32 +56,39 @@ function AddUnreportedExpense({route}: AddUnreportedExpensePageType) {
const session = useSession();
const shouldShowUnreportedTransactionsSkeletons = isLoadingUnreportedTransactions && hasMoreUnreportedTransactionsResults && !isOffline;

function getUnreportedTransactions(transactions: OnyxCollection<Transaction>) {
if (!transactions) {
return [];
}
return Object.values(transactions || {}).filter((item) => {
const isUnreported = item?.reportID === CONST.REPORT.UNREPORTED_REPORT_ID || item?.reportID === '';
if (!isUnreported) {
return false;
}

if (isPerDiemRequest(item)) {
// Only show per diem expenses if the target workspace has per diem enabled and the per diem expense was created in the same workspace
const workspacePerDiemUnit = getPerDiemCustomUnit(policy);
const perDiemCustomUnitID = item?.comment?.customUnit?.customUnitID;

return canSubmitPerDiemExpenseFromWorkspace(policy) && (!perDiemCustomUnitID || perDiemCustomUnitID === workspacePerDiemUnit?.customUnitID);
const getUnreportedTransactions = useCallback(
(transactions: OnyxCollection<Transaction>) => {
if (!transactions) {
return [];
}
return Object.values(transactions || {}).filter((item) => {
const isUnreported = item?.reportID === CONST.REPORT.UNREPORTED_REPORT_ID || item?.reportID === '';
if (!isUnreported) {
return false;
}

if (isPerDiemRequest(item)) {
// Only show per diem expenses if the target workspace has per diem enabled and the per diem expense was created in the same workspace
const workspacePerDiemUnit = getPerDiemCustomUnit(policy);
const perDiemCustomUnitID = item?.comment?.customUnit?.customUnitID;

return canSubmitPerDiemExpenseFromWorkspace(policy) && (!perDiemCustomUnitID || perDiemCustomUnitID === workspacePerDiemUnit?.customUnitID);
}

return true;
});
},
[policy],
);

return true;
});
}

const [transactions = getEmptyArray<Transaction>()] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {
selector: (_transactions) => getUnreportedTransactions(_transactions),
canBeMissing: true,
});
const [transactions = getEmptyArray<Transaction>()] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: getUnreportedTransactions,
canBeMissing: true,
},
[getUnreportedTransactions],
);

const fetchMoreUnreportedTransactions = () => {
if (!hasMoreUnreportedTransactionsResults || isLoadingUnreportedTransactions) {
Expand Down
7 changes: 5 additions & 2 deletions src/pages/Search/EmptySearchView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {IntroSelected, PersonalDetails, Policy} from '@src/types/onyx';
import type {IntroSelected, PersonalDetails, Policy, Transaction} from '@src/types/onyx';
import type {SearchDataTypes} from '@src/types/onyx/SearchResults';

type EmptySearchViewProps = {
Expand Down Expand Up @@ -142,6 +142,9 @@ function EmptySearchView({similarSearchHash, type, groupBy, hasResults}: EmptySe
);
}

const hasTransactionsSelector = (transactions: OnyxCollection<Transaction>) =>
Object.values(transactions ?? {}).filter((transaction) => transaction?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE).length > 0;

function EmptySearchViewContent({
similarSearchHash,
type,
Expand All @@ -166,7 +169,7 @@ function EmptySearchViewContent({

const [hasTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {
canBeMissing: true,
selector: (transactions) => Object.values(transactions ?? {}).filter((transaction) => transaction?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE).length > 0,
selector: hasTransactionsSelector,
});
const [tryNewDot] = useOnyx(ONYXKEYS.NVP_TRY_NEW_DOT, {selector: tryNewDotOnyxSelector, canBeMissing: true});

Expand Down
20 changes: 4 additions & 16 deletions src/pages/TransactionDuplicate/Confirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation';
import useThemeStyles from '@hooks/useThemeStyles';
import useTransactionsByID from '@hooks/useTransactionsByID';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
Expand Down Expand Up @@ -52,14 +53,7 @@ function Confirmation() {
() => transactionViolations?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION)?.data?.duplicates ?? [],
[transactionViolations],
);
const [allDuplicates] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: (allTransactions) => allDuplicateIDs.map((id) => allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]),
canBeMissing: true,
},
[allDuplicateIDs],
);
const [allDuplicates] = useTransactionsByID(allDuplicateIDs);

const compareResult = TransactionUtils.compareDuplicateTransactionFields(transaction, allDuplicates, reviewDuplicates?.reportID);
const {goBack} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'confirmation', route.params.threadReportID, route.params.backTo);
Expand All @@ -69,14 +63,8 @@ function Confirmation() {
const reportAction = Object.values(reportActions ?? {}).find(
(action) => ReportActionsUtils.isMoneyRequestAction(action) && ReportActionsUtils.getOriginalMessage(action)?.IOUTransactionID === reviewDuplicates?.transactionID,
);
const [duplicates] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: (allTransactions) => reviewDuplicates?.duplicates.map((id) => allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]),
canBeMissing: true,
},
[reviewDuplicates?.duplicates],
);

const [duplicates] = useTransactionsByID(reviewDuplicates?.duplicates);
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`, {canBeMissing: true});
const transactionsMergeParams = useMemo(
() => TransactionUtils.buildMergeDuplicatesParams(reviewDuplicates, duplicates ?? [], newTransaction),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type DuplicateTransactionItemProps = {
policies: OnyxCollection<Policy>;
};

const linkedTransactionRouteErrorSelector = (transaction: OnyxEntry<Transaction>) => transaction?.errorFields?.route ?? null;

function DuplicateTransactionItem({transaction, index, allReports, policies}: DuplicateTransactionItemProps) {
const styles = useThemeStyles();
const [userWalletTierName] = useOnyx(ONYXKEYS.USER_WALLET, {selector: (wallet) => wallet?.tierName, canBeMissing: false});
Expand Down Expand Up @@ -50,7 +52,7 @@ function DuplicateTransactionItem({transaction, index, allReports, policies}: Du

const [linkedTransactionRouteError] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${isMoneyRequestAction(action) && getOriginalMessage(action)?.IOUTransactionID}`, {
canBeMissing: true,
selector: (transactionItem) => transactionItem?.errorFields?.route ?? null,
selector: linkedTransactionRouteErrorSelector,
});

const contextValue = useMemo(() => ({shouldOpenReportInRHP: true}), []);
Expand Down
11 changes: 3 additions & 8 deletions src/pages/TransactionDuplicate/ReviewBillable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation';
import useTransactionsByID from '@hooks/useTransactionsByID';
import {setReviewDuplicatesKey} from '@libs/actions/Transaction';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
Expand All @@ -29,14 +30,8 @@ function ReviewBillable() {
() => transactionViolations?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION)?.data?.duplicates ?? [],
[transactionViolations],
);
const [allDuplicates] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: (allTransactions) => allDuplicateIDs.map((id) => allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]),
canBeMissing: true,
},
[allDuplicateIDs],
);

const [allDuplicates] = useTransactionsByID(allDuplicateIDs);
const compareResult = compareDuplicateTransactionFields(transaction, allDuplicates, reviewDuplicates?.reportID);
const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString());
const {currentScreenIndex, goBack, navigateToNextScreen} = useReviewDuplicatesNavigation(
Expand Down
10 changes: 2 additions & 8 deletions src/pages/TransactionDuplicate/ReviewCategory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation';
import useTransactionsByID from '@hooks/useTransactionsByID';
import {setReviewDuplicatesKey} from '@libs/actions/Transaction';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
Expand All @@ -29,14 +30,7 @@ function ReviewCategory() {
() => transactionViolations?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION)?.data?.duplicates ?? [],
[transactionViolations],
);
const [allDuplicates] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: (allTransactions) => allDuplicateIDs.map((id) => allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]),
canBeMissing: true,
},
[allDuplicateIDs],
);
const [allDuplicates] = useTransactionsByID(allDuplicateIDs);

const compareResult = compareDuplicateTransactionFields(transaction, allDuplicates, reviewDuplicates?.reportID);
const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString());
Expand Down
10 changes: 2 additions & 8 deletions src/pages/TransactionDuplicate/ReviewDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation';
import useTransactionsByID from '@hooks/useTransactionsByID';
import {setReviewDuplicatesKey} from '@libs/actions/Transaction';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
Expand All @@ -31,14 +32,7 @@ function ReviewDescription() {
() => transactionViolations?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION)?.data?.duplicates ?? [],
[transactionViolations],
);
const [allDuplicates] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: (allTransactions) => allDuplicateIDs.map((id) => allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]),
canBeMissing: true,
},
[allDuplicateIDs],
);
const [allDuplicates] = useTransactionsByID(allDuplicateIDs);

const compareResult = compareDuplicateTransactionFields(transaction, allDuplicates, reviewDuplicates?.reportID);
const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString());
Expand Down
10 changes: 2 additions & 8 deletions src/pages/TransactionDuplicate/ReviewMerchant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation';
import useTransactionsByID from '@hooks/useTransactionsByID';
import {setReviewDuplicatesKey} from '@libs/actions/Transaction';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
Expand All @@ -29,14 +30,7 @@ function ReviewMerchant() {
() => transactionViolations?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION)?.data?.duplicates ?? [],
[transactionViolations],
);
const [allDuplicates] = useOnyx(
ONYXKEYS.COLLECTION.TRANSACTION,
{
selector: (allTransactions) => allDuplicateIDs.map((id) => allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]),
canBeMissing: true,
},
[allDuplicateIDs],
);
const [allDuplicates] = useTransactionsByID(allDuplicateIDs);

const compareResult = compareDuplicateTransactionFields(transaction, allDuplicates, reviewDuplicates?.reportID);
const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString());
Expand Down
Loading
Loading