Skip to content
Draft
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
4 changes: 4 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,9 @@ const ONYXKEYS = {
/** Is unreported transactions loading */
IS_LOADING_UNREPORTED_TRANSACTIONS: 'isLoadingUnreportedTransactions',

/** Is outstanding reports loading */
IS_LOADING_OUTSTANDING_REPORTS: 'isLoadingOutstandingReports',

/** List of transaction IDs used when navigating to prev/next transaction when viewing it in RHP */
TRANSACTION_THREAD_NAVIGATION_TRANSACTION_IDS: 'transactionThreadNavigationTransactionIDs',

Expand Down Expand Up @@ -1364,6 +1367,7 @@ type OnyxValuesMapping = {
[ONYXKEYS.IS_COMING_FROM_GLOBAL_REIMBURSEMENTS_FLOW]: boolean | undefined;
[ONYXKEYS.HAS_MORE_UNREPORTED_TRANSACTIONS_RESULTS]: boolean | undefined;
[ONYXKEYS.IS_LOADING_UNREPORTED_TRANSACTIONS]: boolean | undefined;
[ONYXKEYS.IS_LOADING_OUTSTANDING_REPORTS]: boolean | undefined;
[ONYXKEYS.NVP_LAST_ECASH_IOS_LOGIN]: string;
[ONYXKEYS.NVP_LAST_ECASH_ANDROID_LOGIN]: string;
[ONYXKEYS.NVP_LAST_IPHONE_LOGIN]: string;
Expand Down
6 changes: 6 additions & 0 deletions src/libs/API/parameters/GetOutstandingReportsParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type GetOutstandingReportsParams = {
policyID: string;
accountID: number;
};

export default GetOutstandingReportsParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export type {default as ResolveActionableMentionWhisperParams} from './ResolveAc
export type {default as ChangePolicyUberBillingAccountPageParams} from './ChangePolicyUberBillingAccountPageParams';
export type {default as ResolveActionableReportMentionWhisperParams} from './ResolveActionableReportMentionWhisperParams';
export type {default as RevealExpensifyCardDetailsParams} from './RevealExpensifyCardDetailsParams';
export type {default as GetOutstandingReportsParams} from './GetOutstandingReportsParams';
export type {default as SearchForReportsParams} from './SearchForReportsParams';
export type {default as SearchForRoomsToMentionParams} from './SearchForRoomsToMentionParams';
export type {default as SendPerformanceTimingParams} from './SendPerformanceTimingParams';
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,7 @@ const READ_COMMANDS = {
SEARCH: 'Search',
GET_OLDER_ACTIONS: 'GetOlderActions',
GET_NEWER_ACTIONS: 'GetNewerActions',
GET_OUTSTANDING_REPORTS: 'GetOutstandingReports',
EXPAND_URL_PREVIEW: 'ExpandURLPreview',
GET_REPORT_PRIVATE_NOTE: 'GetReportPrivateNote',
OPEN_ROOM_MEMBERS_PAGE: 'OpenRoomMembersPage',
Expand Down Expand Up @@ -1190,6 +1191,7 @@ type ReadCommandParameters = {
[READ_COMMANDS.OPEN_PLAID_BANK_ACCOUNT_SELECTOR]: Parameters.OpenPlaidBankAccountSelectorParams;
[READ_COMMANDS.GET_OLDER_ACTIONS]: Parameters.GetOlderActionsParams;
[READ_COMMANDS.GET_NEWER_ACTIONS]: Parameters.GetNewerActionsParams;
[READ_COMMANDS.GET_OUTSTANDING_REPORTS]: Parameters.GetOutstandingReportsParams;
[READ_COMMANDS.GET_CORPAY_BANK_ACCOUNT_FIELDS]: Parameters.GetCorpayBankAccountFieldsParams;
[READ_COMMANDS.EXPAND_URL_PREVIEW]: Parameters.ExpandURLPreviewParams;
[READ_COMMANDS.GET_REPORT_PRIVATE_NOTE]: Parameters.GetReportPrivateNoteParams;
Expand Down
51 changes: 51 additions & 0 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
FlagCommentParams,
GetNewerActionsParams,
GetOlderActionsParams,
GetOutstandingReportsParams,
GetReportPrivateNoteParams,
InviteToGroupChatParams,
InviteToRoomParams,
Expand Down Expand Up @@ -276,7 +277,7 @@
let currentUserAccountID = -1;
let currentUserEmail: string | undefined;

Onyx.connect({

Check warning on line 280 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
// When signed out, val is undefined
Expand All @@ -289,7 +290,7 @@
},
});

Onyx.connect({

Check warning on line 293 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.CONCIERGE_REPORT_ID,
callback: (value) => (conciergeReportID = value),
});
Expand All @@ -297,7 +298,7 @@
// map of reportID to all reportActions for that report
const allReportActions: OnyxCollection<ReportActions> = {};

Onyx.connect({

Check warning on line 301 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
callback: (actions, key) => {
if (!key || !actions) {
Expand All @@ -309,14 +310,14 @@
});

let allTransactionViolations: OnyxCollection<TransactionViolations> = {};
Onyx.connect({

Check warning on line 313 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
waitForCollectionCallback: true,
callback: (value) => (allTransactionViolations = value),
});

let allReports: OnyxCollection<Report>;
Onyx.connect({

Check warning on line 320 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -325,7 +326,7 @@
});

let allPersonalDetails: OnyxEntry<PersonalDetailsList> = {};
Onyx.connect({

Check warning on line 329 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
allPersonalDetails = value ?? {};
Expand All @@ -340,7 +341,7 @@
});

let onboarding: OnyxEntry<Onboarding>;
Onyx.connect({

Check warning on line 344 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_ONBOARDING,
callback: (val) => {
if (Array.isArray(val)) {
Expand All @@ -351,13 +352,13 @@
});

let introSelected: OnyxEntry<IntroSelected> = {};
Onyx.connect({

Check warning on line 355 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_INTRO_SELECTED,
callback: (val) => (introSelected = val),
});

let allReportDraftComments: Record<string, string | undefined> = {};
Onyx.connect({

Check warning on line 361 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT,
waitForCollectionCallback: true,
callback: (value) => (allReportDraftComments = value),
Expand Down Expand Up @@ -4534,6 +4535,55 @@
searchForReports(isOffline, searchInput, policyID);
}

/**
* Fetch all outstanding reports for a workspace to ensure they are available in Onyx
*/
function fetchOutstandingReportsForWorkspace(policyID: string, accountID: number) {
// We are not getting isOffline from components as useEffect change will re-trigger the search on network change
const isOffline = NetworkStore.isOffline();

// We do not try to make this request while offline because it sets a loading indicator optimistically
if (isOffline) {
Onyx.set(ONYXKEYS.IS_LOADING_OUTSTANDING_REPORTS, false);
return;
}

const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.IS_LOADING_OUTSTANDING_REPORTS>> = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.IS_LOADING_OUTSTANDING_REPORTS,
value: true,
},
];

const successData: Array<OnyxUpdate<typeof ONYXKEYS.IS_LOADING_OUTSTANDING_REPORTS>> = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.IS_LOADING_OUTSTANDING_REPORTS,
value: false,
},
];

const failureData: Array<OnyxUpdate<typeof ONYXKEYS.IS_LOADING_OUTSTANDING_REPORTS>> = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.IS_LOADING_OUTSTANDING_REPORTS,
value: false,
},
];

const parameters: GetOutstandingReportsParams = {
policyID,
accountID,
};

API.read(READ_COMMANDS.GET_OUTSTANDING_REPORTS, parameters, {
optimisticData,
successData,
failureData,
});
}

function updateLastVisitTime(reportID: string) {
if (!isValidReportIDFromPath(reportID)) {
return;
Expand Down Expand Up @@ -6360,6 +6410,7 @@
saveReportActionDraft,
saveReportDraftComment,
searchInServer,
fetchOutstandingReportsForWorkspace,
setDeleteTransactionNavigateBackUrl,
setGroupDraft,
setIsComposerFullSize,
Expand Down
18 changes: 17 additions & 1 deletion src/pages/iou/request/step/IOURequestEditReportCommon.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {createPoliciesSelector} from '@selectors/Policy';
import React, {useCallback, useMemo, useState} from 'react';
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import ConfirmModal from '@components/ConfirmModal';
// eslint-disable-next-line no-restricted-imports
Expand All @@ -17,6 +17,7 @@
import usePolicy from '@hooks/usePolicy';
import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses';
import useReportTransactions from '@hooks/useReportTransactions';
import {fetchOutstandingReportsForWorkspace} from '@libs/actions/Report';
import Navigation from '@libs/Navigation/Navigation';
import {getPersonalPolicy, isPolicyAdmin} from '@libs/PolicyUtils';
import {
Expand Down Expand Up @@ -104,6 +105,8 @@

const [allPoliciesID] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: policiesSelector, canBeMissing: false});

const [isLoadingOutstandingReports] = useOnyx(ONYXKEYS.IS_LOADING_OUTSTANDING_REPORTS);

Check failure on line 108 in src/pages/iou/request/step/IOURequestEditReportCommon.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

useOnyx() calls require you to pass the "canBeMissing" param

const [searchValue, debouncedSearchValue, setSearchValue] = useDebouncedState('');
const isSelectedReportUnreported = useMemo(() => !!(isUnreported ?? selectedReportID === CONST.REPORT.UNREPORTED_REPORT_ID), [isUnreported, selectedReportID]);
const isOwner = useMemo(
Expand All @@ -126,12 +129,24 @@
const shouldShowRemoveFromReport =
!!(selectedReportID && selectedReportID !== CONST.REPORT.UNREPORTED_REPORT_ID && selectedReport) && isEditing && isOwner && !isReportIOU && !isCardTransaction;

// Fetch all outstanding reports for the workspace when the component mounts
useEffect(() => {
const policyID = selectedPolicyID ?? selectedReport?.policyID;

if (!policyID || !resolvedReportOwnerAccountID) {
return;
}

// Fetch all outstanding reports for this policy and owner
fetchOutstandingReportsForWorkspace(policyID, resolvedReportOwnerAccountID);
}, [selectedPolicyID, selectedReport?.policyID, resolvedReportOwnerAccountID]);

const expenseReports = useMemo(() => {
// Early return if no reports are available to prevent useless loop
if (!outstandingReportsByPolicyID || isEmptyObject(outstandingReportsByPolicyID)) {
return [];
}
const personalPolicyID = getPersonalPolicy()?.id;

Check failure on line 149 in src/pages/iou/request/step/IOURequestEditReportCommon.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`getPersonalPolicy` is deprecated. Please use ONYXKEYS.PERSONAL_POLICY_ID to find the personal policyID
if (!selectedPolicyID || selectedPolicyID === personalPolicyID || isSelfDM(selectedReport)) {
return Object.values(allPoliciesID ?? {})
.filter((policyID) => personalPolicyID !== policyID)
Expand Down Expand Up @@ -317,6 +332,7 @@
<SelectionList
data={reportOptions}
onSelectRow={handleSelectReport}
isLoadingNewOptions={isLoadingOutstandingReports}
shouldShowTextInput={expenseReports.length >= CONST.STANDARD_LIST_ITEM_LIMIT}
textInputOptions={{
value: searchValue,
Expand Down
Loading