Skip to content

Commit b23c478

Browse files
authored
Merge pull request #53760 from callstack-internal/JKobrynski/feat/tweaks-to-create-expense-flow
2 parents 81186aa + 3c27b60 commit b23c478

File tree

7 files changed

+157
-64
lines changed

7 files changed

+157
-64
lines changed

src/components/MoneyRequestConfirmationList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ function MoneyRequestConfirmationList({
429429
text = translate('common.next');
430430
}
431431
} else if (isTypeTrackExpense) {
432-
text = translate('iou.trackExpense');
432+
text = translate('iou.createExpenseWithAmount', {amount: formattedAmount});
433433
} else if (isTypeSplit && iouAmount === 0) {
434434
text = translate('iou.splitExpense');
435435
} else if ((receiptPath && isTypeRequest) || isDistanceRequestWithPendingRoute || isPerDiemRequest) {
@@ -438,7 +438,7 @@ function MoneyRequestConfirmationList({
438438
text = translate('iou.submitAmount', {amount: formattedAmount});
439439
}
440440
} else {
441-
const translationKey = isTypeSplit ? 'iou.splitAmount' : 'iou.submitAmount';
441+
const translationKey = isTypeSplit ? 'iou.splitAmount' : 'iou.createExpenseWithAmount';
442442
text = translate(translationKey, {amount: formattedAmount});
443443
}
444444
return [

src/languages/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,7 @@ const translations = {
870870
createExpense: 'Create expense',
871871
trackExpense: 'Track expense',
872872
chooseRecipient: 'Choose recipient',
873+
createExpenseWithAmount: ({amount}: {amount: string}) => `Create ${amount} expense`,
873874
confirmDetails: 'Confirm details',
874875
pay: 'Pay',
875876
cancelPayment: 'Cancel payment',

src/languages/es.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,7 @@ const translations = {
866866
trackExpense: 'Seguimiento de gastos',
867867
chooseRecipient: 'Elige destinatario',
868868
confirmDetails: 'Confirma los detalles',
869+
createExpenseWithAmount: ({amount}: {amount: string}) => `Crear un gasto de ${amount}`,
869870
pay: 'Pagar',
870871
cancelPayment: 'Cancelar el pago',
871872
cancelPaymentConfirmation: '¿Estás seguro de que quieres cancelar este pago?',

src/libs/OptionsListUtils.ts

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ type GetOptionsConfig = {
108108
action?: IOUAction;
109109
recentAttendees?: Attendee[];
110110
shouldBoldTitleByDefault?: boolean;
111+
shouldSeparateWorkspaceChat?: boolean;
112+
shouldSeparateSelfDMChat?: boolean;
111113
};
112114

113115
type GetUserToInviteConfig = {
@@ -138,6 +140,8 @@ type Options = {
138140
personalDetails: ReportUtils.OptionData[];
139141
userToInvite: ReportUtils.OptionData | null;
140142
currentUserOption: ReportUtils.OptionData | null | undefined;
143+
workspaceChats?: ReportUtils.OptionData[];
144+
selfDMChat?: ReportUtils.OptionData | undefined;
141145
};
142146

143147
type PreviewConfig = {showChatPreviewLine?: boolean; forcePolicyNamePreview?: boolean; showPersonalDetails?: boolean};
@@ -165,7 +169,7 @@ type OrderReportOptionsConfig = {
165169
preferRecentExpenseReports?: boolean;
166170
};
167171

168-
type ReportAndPersonalDetailOptions = Pick<Options, 'recentReports' | 'personalDetails'>;
172+
type ReportAndPersonalDetailOptions = Pick<Options, 'recentReports' | 'personalDetails' | 'workspaceChats'>;
169173

170174
/**
171175
* OptionsListUtils is used to build a list options passed to the OptionsList component. Several different UI views can
@@ -1001,6 +1005,23 @@ function orderReportOptionsWithSearch(
10011005
);
10021006
}
10031007

1008+
function orderWorkspaceOptions(options: ReportUtils.OptionData[]): ReportUtils.OptionData[] {
1009+
return lodashOrderBy(
1010+
options,
1011+
[
1012+
(option) => {
1013+
// Put default workspace on top
1014+
if (option.isPolicyExpenseChat && option.policyID === activePolicyID) {
1015+
return 0;
1016+
}
1017+
1018+
return 1;
1019+
},
1020+
],
1021+
['asc'],
1022+
);
1023+
}
1024+
10041025
function sortComparatorReportOptionByArchivedStatus(option: ReportUtils.OptionData) {
10051026
return option.private_isArchived ? 1 : 0;
10061027
}
@@ -1028,10 +1049,12 @@ function orderOptions(options: ReportAndPersonalDetailOptions, searchValue?: str
10281049
orderedReportOptions = orderReportOptions(options.recentReports);
10291050
}
10301051
const orderedPersonalDetailsOptions = orderPersonalDetailsOptions(options.personalDetails);
1052+
const orderedWorkspaceChats = orderWorkspaceOptions(options?.workspaceChats ?? []);
10311053

10321054
return {
10331055
recentReports: orderedReportOptions,
10341056
personalDetails: orderedPersonalDetailsOptions,
1057+
workspaceChats: orderedWorkspaceChats,
10351058
};
10361059
}
10371060

@@ -1140,6 +1163,8 @@ function getValidOptions(
11401163
action,
11411164
recentAttendees,
11421165
shouldBoldTitleByDefault = true,
1166+
shouldSeparateSelfDMChat = false,
1167+
shouldSeparateWorkspaceChat = false,
11431168
}: GetOptionsConfig = {},
11441169
): Options {
11451170
const topmostReportId = Navigation.getTopmostReportId() ?? '-1';
@@ -1215,6 +1240,12 @@ function getValidOptions(
12151240
return true;
12161241
});
12171242

1243+
let workspaceChats: ReportUtils.OptionData[] = [];
1244+
1245+
if (shouldSeparateWorkspaceChat) {
1246+
workspaceChats = allReportOptions.filter((option) => option.isOwnPolicyExpenseChat && !option.private_isArchived);
1247+
}
1248+
12181249
const allPersonalDetailsOptions = includeP2P
12191250
? options.personalDetails.filter((detail) => !!detail?.login && !!detail.accountID && !detail?.isOptimisticPersonalDetail && (includeDomainEmail || !Str.isDomainEmail(detail.login)))
12201251
: [];
@@ -1325,6 +1356,15 @@ function getValidOptions(
13251356
}
13261357

13271358
const currentUserOption = allPersonalDetailsOptions.find((personalDetailsOption) => personalDetailsOption.login === currentUserLogin);
1359+
let selfDMChat: ReportUtils.OptionData | undefined;
1360+
1361+
if (shouldSeparateWorkspaceChat) {
1362+
recentReportOptions = recentReportOptions.filter((option) => !option.isPolicyExpenseChat);
1363+
}
1364+
if (shouldSeparateSelfDMChat) {
1365+
selfDMChat = recentReportOptions.find((option) => option.isSelfDM);
1366+
recentReportOptions = recentReportOptions.filter((option) => !option.isSelfDM);
1367+
}
13281368

13291369
return {
13301370
personalDetails: personalDetailsOptions,
@@ -1333,6 +1373,8 @@ function getValidOptions(
13331373
// User to invite is generated by the search input of a user.
13341374
// As this function isn't concerned with any search input yet, this is null (will be set when using filterOptions).
13351375
userToInvite: null,
1376+
workspaceChats,
1377+
selfDMChat,
13361378
};
13371379
}
13381380

@@ -1573,6 +1615,7 @@ function formatSectionsFromSearchTerm(
15731615
filteredPersonalDetails: ReportUtils.OptionData[],
15741616
personalDetails: OnyxEntry<PersonalDetailsList> = {},
15751617
shouldGetOptionDetails = false,
1618+
filteredWorkspaceChats: ReportUtils.OptionData[] = [],
15761619
): SectionForSearchTerm {
15771620
// We show the selected participants at the top of the list when there is no search term or maximum number of participants has already been selected
15781621
// However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results
@@ -1598,8 +1641,9 @@ function formatSectionsFromSearchTerm(
15981641
const selectedParticipantsWithoutDetails = selectedOptions.filter((participant) => {
15991642
const accountID = participant.accountID ?? null;
16001643
const isPartOfSearchTerm = getPersonalDetailSearchTerms(participant).join(' ').toLowerCase().includes(cleanSearchTerm);
1601-
const isReportInRecentReports = filteredRecentReports.some((report) => report.accountID === accountID);
1644+
const isReportInRecentReports = filteredRecentReports.some((report) => report.accountID === accountID) || filteredWorkspaceChats.some((report) => report.accountID === accountID);
16021645
const isReportInPersonalDetails = filteredPersonalDetails.some((personalDetail) => personalDetail.accountID === accountID);
1646+
16031647
return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails;
16041648
});
16051649

@@ -1685,6 +1729,23 @@ function filterReports(reports: ReportUtils.OptionData[], searchTerms: string[])
16851729
return filteredReports;
16861730
}
16871731

1732+
function filterWorkspaceChats(reports: ReportUtils.OptionData[], searchTerms: string[]): ReportUtils.OptionData[] {
1733+
const filteredReports = searchTerms.reduceRight(
1734+
(items, term) =>
1735+
filterArrayByMatch(items, term, (item) => {
1736+
const values: string[] = [];
1737+
if (item.text) {
1738+
values.push(item.text);
1739+
}
1740+
return uniqFast(values);
1741+
}),
1742+
// We start from all unfiltered reports:
1743+
reports,
1744+
);
1745+
1746+
return filteredReports;
1747+
}
1748+
16881749
function filterPersonalDetails(personalDetails: ReportUtils.OptionData[], searchTerms: string[]): ReportUtils.OptionData[] {
16891750
return searchTerms.reduceRight(
16901751
(items, term) =>
@@ -1736,6 +1797,34 @@ function filterUserToInvite(options: Omit<Options, 'userToInvite'>, searchValue:
17361797
});
17371798
}
17381799

1800+
function filterSelfDMChat(report: ReportUtils.OptionData, searchTerms: string[]): ReportUtils.OptionData | undefined {
1801+
const isMatch = searchTerms.every((term) => {
1802+
const values: string[] = [];
1803+
1804+
if (report.text) {
1805+
values.push(report.text);
1806+
}
1807+
if (report.login) {
1808+
values.push(report.login);
1809+
values.push(report.login.replace(CONST.EMAIL_SEARCH_REGEX, ''));
1810+
}
1811+
if (report.isThread) {
1812+
if (report.alternateText) {
1813+
values.push(report.alternateText);
1814+
}
1815+
} else if (!!report.isChatRoom || !!report.isPolicyExpenseChat) {
1816+
if (report.subtitle) {
1817+
values.push(report.subtitle);
1818+
}
1819+
}
1820+
1821+
// Remove duplicate values and check if the term matches any value
1822+
return uniqFast(values).some((value) => value.includes(term));
1823+
});
1824+
1825+
return isMatch ? report : undefined;
1826+
}
1827+
17391828
function filterOptions(options: Options, searchInputValue: string, config?: FilterUserToInviteConfig): Options {
17401829
const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(searchInputValue)));
17411830
const searchValue = parsedPhoneNumber.possible && parsedPhoneNumber.number?.e164 ? parsedPhoneNumber.number.e164 : searchInputValue.toLowerCase();
@@ -1753,12 +1842,17 @@ function filterOptions(options: Options, searchInputValue: string, config?: Filt
17531842
searchValue,
17541843
config,
17551844
);
1845+
const workspaceChats = filterWorkspaceChats(options.workspaceChats ?? [], searchTerms);
1846+
1847+
const selfDMChat = options.selfDMChat ? filterSelfDMChat(options.selfDMChat, searchTerms) : undefined;
17561848

17571849
return {
17581850
personalDetails,
17591851
recentReports,
17601852
userToInvite,
17611853
currentUserOption,
1854+
workspaceChats,
1855+
selfDMChat,
17621856
};
17631857
}
17641858

src/libs/ReportUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6463,7 +6463,7 @@ function isReportNotFound(report: OnyxEntry<Report>): boolean {
64636463
/**
64646464
* Check if the report is the parent report of the currently viewed report or at least one child report has report action
64656465
*/
6466-
function shouldHideReport(report: OnyxEntry<Report>, currentReportId: string): boolean {
6466+
function shouldHideReport(report: OnyxEntry<Report>, currentReportId: string | undefined): boolean {
64676467
const currentReport = getReportOrDraftReport(currentReportId);
64686468
const parentReport = getParentReport(!isEmptyObject(currentReport) ? currentReport : undefined);
64696469
const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`] ?? {};
@@ -6633,7 +6633,7 @@ function hasReportErrorsOtherThanFailedReceipt(report: Report, doesReportHaveVio
66336633

66346634
type ShouldReportBeInOptionListParams = {
66356635
report: OnyxEntry<Report>;
6636-
currentReportId: string;
6636+
currentReportId: string | undefined;
66376637
isInFocusMode: boolean;
66386638
betas: OnyxEntry<Beta[]>;
66396639
policies: OnyxCollection<Policy>;

0 commit comments

Comments
 (0)