Skip to content

Commit 818ad5e

Browse files
authored
Merge pull request Expensify#87716 from shubham1206agra/refactor-MoneyRequestAccountantSelector
[NoQA] Migrated MoneyRequestAccountantSelector.tsx from useOptionsList to usePersonalDetailOptions
2 parents f951e1c + 942db29 commit 818ad5e

2 files changed

Lines changed: 58 additions & 179 deletions

File tree

src/pages/iou/request/MoneyRequestAccountantSelector.tsx

Lines changed: 58 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,35 @@ import lodashPick from 'lodash/pick';
22
import React, {memo, useCallback, useEffect, useMemo} from 'react';
33
import type {GestureResponderEvent} from 'react-native';
44
import EmptySelectionListContent from '@components/EmptySelectionListContent';
5-
import {usePersonalDetails} from '@components/OnyxListItemProvider';
6-
import {useOptionsList} from '@components/OptionListContextProvider';
75
import InviteMemberListItem from '@components/SelectionList/ListItem/InviteMemberListItem';
86
import SelectionListWithSections from '@components/SelectionList/SelectionListWithSections';
7+
import type {Section} from '@components/SelectionList/SelectionListWithSections/types';
98
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
109
import useDebouncedState from '@hooks/useDebouncedState';
1110
import useLocalize from '@hooks/useLocalize';
1211
import useNetwork from '@hooks/useNetwork';
1312
import useOnyx from '@hooks/useOnyx';
14-
import usePrivateIsArchivedMap from '@hooks/usePrivateIsArchivedMap';
15-
import useReportAttributes from '@hooks/useReportAttributes';
13+
import usePersonalDetailOptions from '@hooks/usePersonalDetailOptions';
1614
import useScreenWrapperTransitionStatus from '@hooks/useScreenWrapperTransitionStatus';
17-
import useUserToInviteReports from '@hooks/useUserToInviteReports';
1815
import {canUseTouchScreen} from '@libs/DeviceCapabilities';
1916
import memoize from '@libs/memoize';
20-
import {
21-
filterAndOrderOptions,
22-
formatSectionsFromSearchTerm,
23-
getEmptyOptions,
24-
getHeaderMessage,
25-
getParticipantsOption,
26-
getPolicyExpenseReportOption,
27-
getValidOptions,
28-
isCurrentUser,
29-
orderOptions,
30-
} from '@libs/OptionsListUtils';
31-
import type {SelectionListSections} from '@libs/OptionsListUtils/types';
17+
import {getHeaderMessage, getValidOptions} from '@libs/PersonalDetailOptionsListUtils';
18+
import type {OptionData} from '@libs/PersonalDetailOptionsListUtils/types';
3219
import {searchUserInServer} from '@userActions/Report';
33-
import type {IOUAction, IOUType} from '@src/CONST';
20+
import type {IOUType} from '@src/CONST';
3421
import CONST from '@src/CONST';
3522
import ONYXKEYS from '@src/ONYXKEYS';
3623
import type {Accountant} from '@src/types/onyx/IOU';
3724

3825
const memoizedGetValidOptions = memoize(getValidOptions, {maxSize: 5, monitoringName: 'MoneyRequestAccountantSelector.getValidOptions'});
3926

27+
const defaultListOptions = {
28+
userToInvite: null,
29+
recentOptions: [] as OptionData[],
30+
personalDetails: [] as OptionData[],
31+
selectedOptions: [] as OptionData[],
32+
};
33+
4034
type MoneyRequestAccountantSelectorProps = {
4135
/** Callback to request parent modal to go to next step */
4236
onFinish: (value?: string) => void;
@@ -46,196 +40,71 @@ type MoneyRequestAccountantSelectorProps = {
4640

4741
/** The type of IOU report, i.e. split, request, send, track */
4842
iouType: IOUType;
49-
50-
/** The action of the IOU, i.e. create, split, move */
51-
action: IOUAction;
5243
};
5344

54-
function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType, action}: MoneyRequestAccountantSelectorProps) {
55-
const {translate} = useLocalize();
45+
function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType}: MoneyRequestAccountantSelectorProps) {
46+
const {translate, formatPhoneNumber} = useLocalize();
5647
const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState('');
5748
const {isOffline} = useNetwork();
58-
const personalDetails = usePersonalDetails();
5949
const {didScreenTransitionEnd} = useScreenWrapperTransitionStatus();
6050
const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE);
61-
const [betas] = useOnyx(ONYXKEYS.BETAS);
6251
const [isSearchingForReports] = useOnyx(ONYXKEYS.RAM_ONLY_IS_SEARCHING_FOR_REPORTS);
63-
const {options, areOptionsInitialized} = useOptionsList({
64-
shouldInitialize: didScreenTransitionEnd,
65-
});
66-
const offlineMessage: string = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : '';
67-
const reportAttributesDerived = useReportAttributes();
68-
const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT);
69-
const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING);
7052
const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST);
7153
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
7254
const currentUserEmail = currentUserPersonalDetails.email ?? '';
73-
const currentUserAccountID = currentUserPersonalDetails.accountID;
74-
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
75-
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
76-
const privateIsArchivedMap = usePrivateIsArchivedMap();
55+
const {options: personalDetailOptions} = usePersonalDetailOptions({enabled: didScreenTransitionEnd});
56+
const areOptionsInitialized = (personalDetailOptions?.length ?? 0) > 0;
57+
const offlineMessage: string = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : '';
7758

7859
useEffect(() => {
7960
searchUserInServer(debouncedSearchTerm.trim());
8061
}, [debouncedSearchTerm]);
8162

82-
const defaultOptions = useMemo(() => {
63+
const optionsList = useMemo(() => {
8364
if (!areOptionsInitialized || !didScreenTransitionEnd) {
84-
getEmptyOptions();
65+
return defaultListOptions;
8566
}
8667

87-
const optionList = memoizedGetValidOptions(
88-
{
89-
reports: options.reports,
90-
personalDetails: options.personalDetails,
91-
},
92-
allPolicies,
93-
draftComments,
94-
nvpDismissedProductTraining,
95-
loginList,
96-
currentUserAccountID,
97-
currentUserEmail,
98-
conciergeReportID,
99-
{
100-
betas,
101-
excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT,
102-
action,
103-
personalDetails,
104-
countryCode,
105-
},
106-
);
107-
108-
const orderedOptions = orderOptions(optionList);
109-
110-
return {
111-
...optionList,
112-
...orderedOptions,
113-
};
114-
}, [
115-
areOptionsInitialized,
116-
didScreenTransitionEnd,
117-
options.reports,
118-
options.personalDetails,
119-
allPolicies,
120-
draftComments,
121-
nvpDismissedProductTraining,
122-
loginList,
123-
betas,
124-
action,
125-
countryCode,
126-
currentUserAccountID,
127-
currentUserEmail,
128-
conciergeReportID,
129-
personalDetails,
130-
]);
131-
132-
const chatOptions = useMemo(() => {
133-
if (!areOptionsInitialized) {
134-
return {
135-
userToInvite: null,
136-
recentReports: [],
137-
personalDetails: [],
138-
currentUserOption: null,
139-
headerMessage: '',
140-
};
141-
}
142-
const newOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, personalDetails, {
68+
return memoizedGetValidOptions(personalDetailOptions ?? [], currentUserEmail, formatPhoneNumber, countryCode, loginList, {
14369
excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT,
144-
maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW,
70+
searchString: debouncedSearchTerm,
71+
includeUserToInvite: true,
14572
});
146-
return newOptions;
147-
}, [areOptionsInitialized, defaultOptions, debouncedSearchTerm, countryCode, loginList, currentUserAccountID, currentUserEmail, personalDetails]);
148-
149-
const {userToInviteExpenseReport} = useUserToInviteReports(chatOptions?.userToInvite);
150-
const userToInviteExpenseReportPolicy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${userToInviteExpenseReport?.policyID}`];
73+
}, [areOptionsInitialized, didScreenTransitionEnd, personalDetailOptions, currentUserEmail, formatPhoneNumber, countryCode, loginList, debouncedSearchTerm]);
15174

152-
/**
153-
* Returns the sections needed for the OptionsSelector
154-
*/
155-
const [sections, header] = useMemo(() => {
156-
const newSections: SelectionListSections = [];
75+
const sections = useMemo(() => {
76+
const newSections: Array<Section<OptionData>> = [];
15777
if (!areOptionsInitialized || !didScreenTransitionEnd) {
158-
return [newSections, ''];
78+
return newSections;
15979
}
160-
const fiveRecents = [...chatOptions.recentReports].slice(0, 5);
161-
const restOfRecents = [...chatOptions.recentReports].slice(5);
162-
const contactsWithRestOfRecents = [...restOfRecents, ...chatOptions.personalDetails];
163-
164-
const formatResults = formatSectionsFromSearchTerm(
165-
debouncedSearchTerm,
166-
[],
167-
chatOptions.recentReports,
168-
chatOptions.personalDetails,
169-
privateIsArchivedMap,
170-
currentUserAccountID,
171-
allPolicies,
172-
personalDetails,
173-
true,
174-
undefined,
175-
reportAttributesDerived,
176-
);
177-
newSections.push({...formatResults.section, sectionIndex: 0});
17880

179-
newSections.push({
180-
title: translate('common.recents'),
181-
data: fiveRecents,
182-
sectionIndex: 1,
183-
});
81+
let sectionIndex = 0;
18482

185-
newSections.push({
186-
title: translate('common.contacts'),
187-
data: contactsWithRestOfRecents,
188-
sectionIndex: 2,
189-
});
83+
if (optionsList.recentOptions.length > 0) {
84+
newSections.push({
85+
title: translate('common.recents'),
86+
data: optionsList.recentOptions,
87+
sectionIndex: sectionIndex++,
88+
});
89+
}
19090

191-
if (
192-
chatOptions.userToInvite &&
193-
!isCurrentUser(
194-
{...chatOptions.userToInvite, accountID: chatOptions.userToInvite?.accountID ?? CONST.DEFAULT_NUMBER_ID, status: chatOptions.userToInvite?.status ?? undefined},
195-
loginList,
196-
currentUserEmail,
197-
)
198-
) {
91+
if (optionsList.personalDetails.length > 0) {
19992
newSections.push({
200-
data: [chatOptions.userToInvite].map((participant) => {
201-
const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false;
202-
const privateIsArchived = privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${userToInviteExpenseReport?.reportID}`];
203-
return isPolicyExpenseChat
204-
? getPolicyExpenseReportOption(participant, privateIsArchived, personalDetails, userToInviteExpenseReport, userToInviteExpenseReportPolicy, reportAttributesDerived)
205-
: getParticipantsOption(participant, personalDetails);
206-
}),
207-
sectionIndex: 3,
93+
title: translate('common.contacts'),
94+
data: optionsList.personalDetails,
95+
sectionIndex: sectionIndex++,
20896
});
20997
}
21098

211-
const headerMessage = getHeaderMessage(
212-
(chatOptions.personalDetails ?? []).length + (chatOptions.recentReports ?? []).length !== 0,
213-
!!chatOptions?.userToInvite,
214-
debouncedSearchTerm.trim(),
215-
countryCode,
216-
false,
217-
);
99+
if (optionsList.userToInvite) {
100+
newSections.push({
101+
data: [optionsList.userToInvite],
102+
sectionIndex: sectionIndex++,
103+
});
104+
}
218105

219-
return [newSections, headerMessage];
220-
}, [
221-
areOptionsInitialized,
222-
didScreenTransitionEnd,
223-
chatOptions.recentReports,
224-
chatOptions.personalDetails,
225-
chatOptions.userToInvite,
226-
debouncedSearchTerm,
227-
personalDetails,
228-
userToInviteExpenseReport,
229-
userToInviteExpenseReportPolicy,
230-
reportAttributesDerived,
231-
translate,
232-
loginList,
233-
countryCode,
234-
privateIsArchivedMap,
235-
currentUserAccountID,
236-
currentUserEmail,
237-
allPolicies,
238-
]);
106+
return newSections;
107+
}, [areOptionsInitialized, didScreenTransitionEnd, optionsList.recentOptions, optionsList.personalDetails, optionsList.userToInvite, translate]);
239108

240109
const selectAccountant = useCallback(
241110
(option: Accountant) => {
@@ -256,6 +125,17 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType
256125
[selectAccountant],
257126
);
258127

128+
const getHeaderMessageText = () => {
129+
if (sections.length > 0) {
130+
return '';
131+
}
132+
const searchValue = debouncedSearchTerm.trim().toLowerCase();
133+
if (CONST.EXPENSIFY_EMAILS_OBJECT[searchValue]) {
134+
return translate('messages.errorMessageInvalidEmail');
135+
}
136+
return getHeaderMessage(translate, debouncedSearchTerm, countryCode);
137+
};
138+
259139
const shouldShowLoadingPlaceholder = useMemo(() => !areOptionsInitialized || !didScreenTransitionEnd, [areOptionsInitialized, didScreenTransitionEnd]);
260140

261141
const optionLength = useMemo(() => {
@@ -271,7 +151,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType
271151
value: searchTerm,
272152
label: translate('selectionList.nameEmailOrPhoneNumber'),
273153
onChangeText: setSearchTerm,
274-
headerMessage: header,
154+
headerMessage: getHeaderMessageText(),
275155
hint: offlineMessage,
276156
};
277157

src/pages/iou/request/step/IOURequestStepAccountant.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ function IOURequestStepAccountant({
7878
onFinish={navigateToNextStep}
7979
onAccountantSelected={setAccountant}
8080
iouType={iouType}
81-
action={action}
8281
/>
8382
</StepScreenWrapper>
8483
);

0 commit comments

Comments
 (0)