Skip to content

Commit da5f193

Browse files
authored
Merge pull request Expensify#67074 from shubham1206agra/refactor-onyx-8
Refactored localeCompare in OptionsListUtils
2 parents 9df24a1 + b5f8e1b commit da5f193

File tree

10 files changed

+58
-23
lines changed

10 files changed

+58
-23
lines changed

src/components/ApprovalWorkflowSection.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type ApprovalWorkflowSectionProps = {
2424
function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSectionProps) {
2525
const styles = useThemeStyles();
2626
const theme = useTheme();
27-
const {translate, toLocaleOrdinal} = useLocalize();
27+
const {translate, toLocaleOrdinal, localeCompare} = useLocalize();
2828
const {shouldUseNarrowLayout} = useResponsiveLayout();
2929

3030
const approverTitle = useCallback(
@@ -38,10 +38,10 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSe
3838
return translate('workspace.common.everyone');
3939
}
4040

41-
return sortAlphabetically(approvalWorkflow.members, 'displayName')
41+
return sortAlphabetically(approvalWorkflow.members, 'displayName', localeCompare)
4242
.map((m) => Str.removeSMSDomain(m.displayName))
4343
.join(', ');
44-
}, [approvalWorkflow.isDefault, approvalWorkflow.members, translate]);
44+
}, [approvalWorkflow.isDefault, approvalWorkflow.members, translate, localeCompare]);
4545

4646
return (
4747
<PressableWithoutFeedback

src/components/WorkspaceMembersSelectionList.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type WorkspaceMembersSelectionListProps = {
3535
};
3636

3737
function WorkspaceMembersSelectionList({policyID, selectedApprover, setApprover}: WorkspaceMembersSelectionListProps) {
38-
const {translate} = useLocalize();
38+
const {translate, localeCompare} = useLocalize();
3939
const {didScreenTransitionEnd} = useScreenWrapperTransitionStatus();
4040
const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState('');
4141
const personalDetails = usePersonalDetails();
@@ -83,11 +83,11 @@ function WorkspaceMembersSelectionList({policyID, selectedApprover, setApprover}
8383
return [
8484
{
8585
title: undefined,
86-
data: sortAlphabetically(filteredApprovers, 'text'),
86+
data: sortAlphabetically(filteredApprovers, 'text', localeCompare),
8787
shouldShow: true,
8888
},
8989
];
90-
}, [debouncedSearchTerm, personalDetails, policy?.employeeList, policy?.owner, selectedApprover]);
90+
}, [debouncedSearchTerm, personalDetails, policy?.employeeList, policy?.owner, selectedApprover, localeCompare]);
9191

9292
const handleOnSelectRow = (approver: SelectionListApprover) => {
9393
setApprover(approver.login);

src/libs/OptionsListUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
77
import Onyx from 'react-native-onyx';
88
import type {SetNonNullable} from 'type-fest';
99
import {FallbackAvatar} from '@components/Icon/Expensicons';
10+
import type {LocaleContextProps} from '@components/LocaleContextProvider';
1011
import type {PolicyTagList} from '@pages/workspace/tags/types';
1112
import type {IOUAction} from '@src/CONST';
1213
import CONST from '@src/CONST';
@@ -38,7 +39,6 @@ import Timing from './actions/Timing';
3839
import {getEnabledCategoriesCount} from './CategoryUtils';
3940
import filterArrayByMatch from './filterArrayByMatch';
4041
import {isReportMessageAttachment} from './isReportMessageAttachment';
41-
import localeCompare from './LocaleCompare';
4242
import {formatPhoneNumber} from './LocalePhoneNumber';
4343
import {translateLocal} from './Localize';
4444
import {appendCountryCode, getPhoneNumberWithoutSpecialChars} from './LoginUtils';
@@ -2680,7 +2680,7 @@ function filterSelectedOptions(options: Options, selectedOptions: Set<number | u
26802680
return filteredOptions;
26812681
}
26822682

2683-
function sortAlphabetically<T extends Partial<Record<TKey, string | undefined>>, TKey extends keyof T>(items: T[], key: TKey): T[] {
2683+
function sortAlphabetically<T extends Partial<Record<TKey, string | undefined>>, TKey extends keyof T>(items: T[], key: TKey, localeCompare: LocaleContextProps['localeCompare']): T[] {
26842684
return items.sort((a, b) => localeCompare(a[key]?.toLowerCase() ?? '', b[key]?.toLowerCase() ?? ''));
26852685
}
26862686

src/pages/workspace/WorkspaceMembersPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
483483
const normalizedSearchQuery = StringUtils.normalize(searchQuery);
484484
return memberText.includes(normalizedSearchQuery) || alternateText.includes(normalizedSearchQuery);
485485
}, []);
486-
const sortMembers = useCallback((memberOptions: MemberOption[]) => sortAlphabetically(memberOptions, 'text'), []);
486+
const sortMembers = useCallback((memberOptions: MemberOption[]) => sortAlphabetically(memberOptions, 'text', localeCompare), [localeCompare]);
487487
const [inputValue, setInputValue, filteredData] = useSearchResults(data, filterMember, sortMembers);
488488

489489
useEffect(() => {

src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type AssigneeStepProps = {
3838
};
3939

4040
function AssigneeStep({policy, feed}: AssigneeStepProps) {
41-
const {translate, formatPhoneNumber} = useLocalize();
41+
const {translate, formatPhoneNumber, localeCompare} = useLocalize();
4242
const styles = useThemeStyles();
4343
const {isOffline} = useNetwork();
4444
const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD, {canBeMissing: true});
@@ -137,10 +137,10 @@ function AssigneeStep({policy, feed}: AssigneeStepProps) {
137137
});
138138
});
139139

140-
membersList = sortAlphabetically(membersList, 'text');
140+
membersList = sortAlphabetically(membersList, 'text', localeCompare);
141141

142142
return membersList;
143-
}, [isOffline, policy?.employeeList, selectedMember, formatPhoneNumber]);
143+
}, [isOffline, policy?.employeeList, selectedMember, formatPhoneNumber, localeCompare]);
144144

145145
const sections = useMemo(() => {
146146
if (!debouncedSearchTerm) {

src/pages/workspace/expensifyCard/issueNew/AssigneeStep.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type AssigneeStepProps = {
3030
};
3131

3232
function AssigneeStep({policy}: AssigneeStepProps) {
33-
const {translate, formatPhoneNumber} = useLocalize();
33+
const {translate, formatPhoneNumber, localeCompare} = useLocalize();
3434
const styles = useThemeStyles();
3535
const {isOffline} = useNetwork();
3636
const policyID = policy?.id;
@@ -99,10 +99,10 @@ function AssigneeStep({policy}: AssigneeStepProps) {
9999
});
100100
});
101101

102-
membersList = sortAlphabetically(membersList, 'text');
102+
membersList = sortAlphabetically(membersList, 'text', localeCompare);
103103

104104
return membersList;
105-
}, [isOffline, policy?.employeeList, formatPhoneNumber]);
105+
}, [isOffline, policy?.employeeList, formatPhoneNumber, localeCompare]);
106106

107107
const sections = useMemo(() => {
108108
if (!debouncedSearchTerm) {

src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type ApprovalWorkflowEditorProps = {
3838

3939
function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, policy, policyID}: ApprovalWorkflowEditorProps, ref: ForwardedRef<ScrollViewRN>) {
4040
const styles = useThemeStyles();
41-
const {translate, toLocaleOrdinal} = useLocalize();
41+
const {translate, toLocaleOrdinal, localeCompare} = useLocalize();
4242
const approverCount = approvalWorkflow.approvers.length;
4343

4444
const approverDescription = useCallback(
@@ -67,10 +67,10 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
6767
return translate('workspace.common.everyone');
6868
}
6969

70-
return sortAlphabetically(approvalWorkflow.members, 'displayName')
70+
return sortAlphabetically(approvalWorkflow.members, 'displayName', localeCompare)
7171
.map((m) => Str.removeSMSDomain(m.displayName))
7272
.join(', ');
73-
}, [approvalWorkflow.isDefault, approvalWorkflow.members, translate]);
73+
}, [approvalWorkflow.isDefault, approvalWorkflow.members, translate, localeCompare]);
7474

7575
const approverErrorMessage = useCallback(
7676
(approver: Approver | undefined, approverIndex: number) => {

src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ type ApproverSection = SectionListData<SelectionListApprover, Section<SelectionL
5454

5555
function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoadingReportData = true, route}: WorkspaceWorkflowsApprovalsApproverPageProps) {
5656
const styles = useThemeStyles();
57-
const {translate} = useLocalize();
57+
const {translate, localeCompare} = useLocalize();
5858
const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState('');
5959
const [approvalWorkflow, approvalWorkflowMetadata] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true});
6060
const isApprovalWorkflowLoading = isLoadingOnyxValue(approvalWorkflowMetadata);
@@ -144,7 +144,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
144144
const filteredApprovers =
145145
debouncedSearchTerm !== '' ? tokenizedSearch(approvers, getSearchValueForPhoneOrEmail(debouncedSearchTerm), (option) => [option.text ?? '', option.login ?? '']) : approvers;
146146

147-
const data = sortAlphabetically(filteredApprovers, 'text');
147+
const data = sortAlphabetically(filteredApprovers, 'text', localeCompare);
148148
return [
149149
{
150150
title: undefined,
@@ -165,6 +165,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
165165
membersEmail,
166166
policy?.preventSelfApproval,
167167
policy?.owner,
168+
localeCompare,
168169
]);
169170

170171
const shouldShowListEmptyContent = !debouncedSearchTerm && !!approvalWorkflow && !sections.at(0)?.data.length && !isApprovalWorkflowLoading;

src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ type WorkspaceWorkflowsApprovalsExpensesFromPageProps = WithPolicyAndFullscreenL
5656

5757
function WorkspaceWorkflowsApprovalsExpensesFromPage({policy, isLoadingReportData = true, route}: WorkspaceWorkflowsApprovalsExpensesFromPageProps) {
5858
const styles = useThemeStyles();
59-
const {translate} = useLocalize();
59+
const {translate, localeCompare} = useLocalize();
6060
const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState('');
6161
const [approvalWorkflow, approvalWorkflowResults] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true});
6262
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false});
@@ -142,11 +142,21 @@ function WorkspaceWorkflowsApprovalsExpensesFromPage({policy, isLoadingReportDat
142142
return [
143143
{
144144
title: undefined,
145-
data: sortAlphabetically(filteredMembers, 'text'),
145+
data: sortAlphabetically(filteredMembers, 'text', localeCompare),
146146
shouldShow: true,
147147
},
148148
];
149-
}, [approvalWorkflow?.availableMembers, debouncedSearchTerm, policy?.preventSelfApproval, policy?.employeeList, policy?.owner, selectedMembers, approversEmail, personalDetailLogins]);
149+
}, [
150+
approvalWorkflow?.availableMembers,
151+
debouncedSearchTerm,
152+
policy?.preventSelfApproval,
153+
policy?.employeeList,
154+
policy?.owner,
155+
selectedMembers,
156+
approversEmail,
157+
personalDetailLogins,
158+
localeCompare,
159+
]);
150160

151161
const goBack = useCallback(() => {
152162
let backTo;

tests/unit/OptionsListUtilsTest.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
orderOptions,
2222
orderWorkspaceOptions,
2323
recentReportComparator,
24+
sortAlphabetically,
2425
} from '@libs/OptionsListUtils';
2526
import {canCreateTaskInReport, canUserPerformWriteAction, isCanceledTaskReport, isExpensifyOnlyParticipantInReport} from '@libs/ReportUtils';
2627
import type {OptionData} from '@libs/ReportUtils';
@@ -29,6 +30,7 @@ import IntlStore from '@src/languages/IntlStore';
2930
import ONYXKEYS from '@src/ONYXKEYS';
3031
import type {PersonalDetails, Policy, Report} from '@src/types/onyx';
3132
import {getFakeAdvancedReportAction} from '../utils/LHNTestUtils';
33+
import {localeCompare} from '../utils/TestHelper';
3234
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
3335

3436
jest.mock('@rnmapbox/maps', () => {
@@ -1944,4 +1946,26 @@ describe('OptionsListUtils', () => {
19441946
expect(result.at(1)!.reportID).toBe('3');
19451947
});
19461948
});
1949+
1950+
describe('sortAlphabetically', () => {
1951+
it('should sort options alphabetically by text', () => {
1952+
const options: OptionData[] = [{text: 'Banana', reportID: '1'} as OptionData, {text: 'Apple', reportID: '2'} as OptionData, {text: 'Cherry', reportID: '3'} as OptionData];
1953+
const sortedOptions = sortAlphabetically(options, 'text', localeCompare);
1954+
expect(sortedOptions.at(0)?.reportID).toBe('2');
1955+
expect(sortedOptions.at(1)?.reportID).toBe('1');
1956+
expect(sortedOptions.at(2)?.reportID).toBe('3');
1957+
});
1958+
1959+
it('should handle empty array', () => {
1960+
const sortedOptions = sortAlphabetically([], 'abc', localeCompare);
1961+
expect(sortedOptions).toEqual([]);
1962+
});
1963+
1964+
it('should handle single option', () => {
1965+
const options: OptionData[] = [{text: 'Single', reportID: '1'} as OptionData];
1966+
const sortedOptions = sortAlphabetically(options, 'text', localeCompare);
1967+
expect(sortedOptions.length).toBe(1);
1968+
expect(sortedOptions.at(0)?.text).toBe('Single');
1969+
});
1970+
});
19471971
});

0 commit comments

Comments
 (0)