Skip to content

Commit c1e232d

Browse files
authored
Merge pull request Expensify#67402 from shubham1206agra/refactor-onyx-13
Refactored localeCompare in PolicyUtils
2 parents 455e801 + 9134584 commit c1e232d

9 files changed

Lines changed: 67 additions & 13 deletions

File tree

src/hooks/useWorkspaceList.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {useMemo} from 'react';
22
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
33
import * as Expensicons from '@components/Icon/Expensicons';
4+
import type {LocaleContextProps} from '@components/LocaleContextProvider';
45
import type {ListItem, SectionListDataType} from '@components/SelectionList/types';
56
import {isPolicyAdmin, shouldShowPolicy, sortWorkspacesBySelected} from '@libs/PolicyUtils';
67
import {getDefaultWorkspaceAvatar} from '@libs/ReportUtils';
@@ -23,10 +24,11 @@ type UseWorkspaceListParams = {
2324
shouldShowPendingDeletePolicy: boolean;
2425
selectedPolicyIDs: string[] | undefined;
2526
searchTerm: string;
27+
localeCompare: LocaleContextProps['localeCompare'];
2628
additionalFilter?: (policy: OnyxEntry<Policy>) => boolean;
2729
};
2830

29-
function useWorkspaceList({policies, currentUserLogin, selectedPolicyIDs, searchTerm, shouldShowPendingDeletePolicy, additionalFilter}: UseWorkspaceListParams) {
31+
function useWorkspaceList({policies, currentUserLogin, selectedPolicyIDs, searchTerm, shouldShowPendingDeletePolicy, localeCompare, additionalFilter}: UseWorkspaceListParams) {
3032
const usersWorkspaces = useMemo(() => {
3133
if (!policies || isEmptyObject(policies)) {
3234
return [];
@@ -61,9 +63,9 @@ function useWorkspaceList({policies, currentUserLogin, selectedPolicyIDs, search
6163
const filteredAndSortedUserWorkspaces = useMemo<WorkspaceListItem[]>(
6264
() =>
6365
tokenizedSearch(usersWorkspaces, searchTerm, (policy) => [policy.text]).sort((policy1, policy2) =>
64-
sortWorkspacesBySelected({policyID: policy1.policyID, name: policy1.text}, {policyID: policy2.policyID, name: policy2.text}, selectedPolicyIDs),
66+
sortWorkspacesBySelected({policyID: policy1.policyID, name: policy1.text}, {policyID: policy2.policyID, name: policy2.text}, selectedPolicyIDs, localeCompare),
6567
),
66-
[searchTerm, usersWorkspaces, selectedPolicyIDs],
68+
[searchTerm, usersWorkspaces, selectedPolicyIDs, localeCompare],
6769
);
6870

6971
const sections = useMemo(() => {

src/libs/PolicyUtils.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import {hasSynchronizationErrorMessage, isAuthenticationError} from './actions/c
3636
import {shouldShowQBOReimbursableExportDestinationAccountError} from './actions/connections/QuickbooksOnline';
3737
import {getCurrentUserAccountID, getCurrentUserEmail} from './actions/Report';
3838
import {getCategoryApproverRule} from './CategoryUtils';
39-
import localeCompare from './LocaleCompare';
4039
import {translateLocal} from './Localize';
4140
import Navigation from './Navigation/Navigation';
4241
import {isOffline as isOfflineNetworkStore} from './Network/NetworkStore';
@@ -1091,6 +1090,7 @@ function getNetSuiteImportCustomFieldLabel(
10911090
policy: Policy | undefined,
10921091
importField: ValueOf<typeof CONST.NETSUITE_CONFIG.IMPORT_CUSTOM_FIELDS>,
10931092
translate: LocaleContextProps['translate'],
1093+
localeCompare: LocaleContextProps['localeCompare'],
10941094
): string | undefined {
10951095
const fieldData = policy?.connections?.netsuite?.options?.config.syncOptions?.[importField] ?? [];
10961096
if (fieldData.length === 0) {
@@ -1201,7 +1201,15 @@ function getSageIntacctCreditCards(policy?: Policy, selectedAccount?: string): S
12011201
* @param workspace2 Details of the second workspace to be compared.
12021202
* @param selectedWorkspaceID ID of the selected workspace which needs to be at the beginning.
12031203
*/
1204-
const sortWorkspacesBySelected = (workspace1: WorkspaceDetails, workspace2: WorkspaceDetails, selectedWorkspaceIDs: string[] | undefined): number => {
1204+
const sortWorkspacesBySelected = (
1205+
workspace1: WorkspaceDetails,
1206+
workspace2: WorkspaceDetails,
1207+
selectedWorkspaceIDs: string[] | undefined,
1208+
localeCompare: LocaleContextProps['localeCompare'],
1209+
): number => {
1210+
if (workspace1.policyID && selectedWorkspaceIDs?.includes(workspace1?.policyID) && workspace2.policyID && selectedWorkspaceIDs?.includes(workspace2.policyID)) {
1211+
return localeCompare(workspace1.name?.toLowerCase() ?? '', workspace2.name?.toLowerCase() ?? '');
1212+
}
12051213
if (workspace1.policyID && selectedWorkspaceIDs?.includes(workspace1?.policyID)) {
12061214
return -1;
12071215
}

src/pages/ReportChangeWorkspacePage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro
3131
const {isOffline} = useNetwork();
3232
const styles = useThemeStyles();
3333
const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState('');
34-
const {translate, formatPhoneNumber} = useLocalize();
34+
const {translate, formatPhoneNumber, localeCompare} = useLocalize();
3535

3636
const [policies, fetchStatus] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true});
3737
const [reportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${reportID}`, {canBeMissing: true});
@@ -70,6 +70,7 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro
7070
shouldShowPendingDeletePolicy: false,
7171
selectedPolicyIDs: report.policyID ? [report.policyID] : undefined,
7272
searchTerm: debouncedSearchTerm,
73+
localeCompare,
7374
additionalFilter: (newPolicy) => isWorkspaceEligibleForReportChange(newPolicy, report, policies),
7475
});
7576

src/pages/Search/AdvancedSearchFilters.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ function AdvancedSearchFilters() {
587587
shouldShowPendingDeletePolicy: false,
588588
selectedPolicyIDs: undefined,
589589
searchTerm: '',
590+
localeCompare,
590591
});
591592

592593
// When looking if a user has any categories to display, we want to ignore the policies that are of type PERSONAL

src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersWorkspacePage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const updateWorkspaceFilter = (policyID: string[] | null) => {
2727

2828
function SearchFiltersWorkspacePage() {
2929
const styles = useThemeStyles();
30-
const {translate} = useLocalize();
30+
const {translate, localeCompare} = useLocalize();
3131
const {isOffline} = useNetwork();
3232

3333
const [searchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {canBeMissing: true});
@@ -45,6 +45,7 @@ function SearchFiltersWorkspacePage() {
4545
shouldShowPendingDeletePolicy: false,
4646
selectedPolicyIDs: selectedOptions,
4747
searchTerm: debouncedSearchTerm,
48+
localeCompare,
4849
});
4950

5051
const selectWorkspace = useCallback(

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function IOURequestStepPerDiemWorkspace({
3131
},
3232
transaction,
3333
}: IOURequestStepPerDiemWorkspaceProps) {
34-
const {translate} = useLocalize();
34+
const {translate, localeCompare} = useLocalize();
3535
const {login: currentUserLogin, accountID} = useCurrentUserPersonalDetails();
3636
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true});
3737

@@ -46,6 +46,7 @@ function IOURequestStepPerDiemWorkspace({
4646
{policyID: policy1.id, name: policy1.name},
4747
{policyID: policy2.id, name: policy2.name},
4848
selectedWorkspace?.policyID ? [selectedWorkspace?.policyID] : [],
49+
localeCompare,
4950
),
5051
)
5152
.map((policy) => ({
@@ -63,7 +64,7 @@ function IOURequestStepPerDiemWorkspace({
6364
],
6465
isSelected: selectedWorkspace?.policyID === policy.id,
6566
}));
66-
}, [allPolicies, currentUserLogin, selectedWorkspace]);
67+
}, [allPolicies, currentUserLogin, selectedWorkspace, localeCompare]);
6768

6869
const selectWorkspace = (item: WorkspaceListItem) => {
6970
const policyExpenseReportID = getPolicyExpenseChat(accountID, item.value)?.reportID;

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type IOURequestStepSendFromProps = WithWritableReportOrNotFoundProps<typeof SCRE
2626
WithFullTransactionOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_SEND_FROM>;
2727

2828
function IOURequestStepSendFrom({route, transaction}: IOURequestStepSendFromProps) {
29-
const {translate} = useLocalize();
29+
const {translate, localeCompare} = useLocalize();
3030
const {transactionID, backTo} = route.params;
3131
const [currentUserLogin] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email, canBeMissing: false});
3232
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true});
@@ -42,6 +42,7 @@ function IOURequestStepSendFrom({route, transaction}: IOURequestStepSendFromProp
4242
{policyID: policy1.id, name: policy1.name},
4343
{policyID: policy2.id, name: policy2.name},
4444
selectedWorkspace?.policyID ? [selectedWorkspace?.policyID] : [],
45+
localeCompare,
4546
),
4647
)
4748
.map((policy) => ({
@@ -59,7 +60,7 @@ function IOURequestStepSendFrom({route, transaction}: IOURequestStepSendFromProp
5960
],
6061
isSelected: selectedWorkspace?.policyID === policy.id,
6162
}));
62-
}, [allPolicies, currentUserLogin, selectedWorkspace]);
63+
}, [allPolicies, currentUserLogin, selectedWorkspace, localeCompare]);
6364

6465
const navigateBack = () => {
6566
Navigation.goBack(backTo);

src/pages/workspace/accounting/netsuite/import/NetSuiteImportPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import CONST from '@src/CONST';
1818
import ROUTES from '@src/ROUTES';
1919

2020
function NetSuiteImportPage({policy}: WithPolicyConnectionsProps) {
21-
const {translate} = useLocalize();
21+
const {translate, localeCompare} = useLocalize();
2222
const styles = useThemeStyles();
2323
const {isBetaEnabled} = usePermissions();
2424

@@ -131,7 +131,7 @@ function NetSuiteImportPage({policy}: WithPolicyConnectionsProps) {
131131
shouldDisableStrikeThrough
132132
>
133133
<MenuItemWithTopDescription
134-
title={getNetSuiteImportCustomFieldLabel(policy, importField, translate)}
134+
title={getNetSuiteImportCustomFieldLabel(policy, importField, translate, localeCompare)}
135135
description={translate(`workspace.netsuite.import.importCustomFields.${importField}.title`)}
136136
shouldShowRightIcon
137137
onPress={() => {

tests/unit/PolicyUtilsTest.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
getUnitRateValue,
1414
isUserInvitedToWorkspace,
1515
shouldShowPolicy,
16+
sortWorkspacesBySelected,
1617
} from '@libs/PolicyUtils';
1718
import {isWorkspaceEligibleForReportChange} from '@libs/ReportUtils';
1819
import CONST from '@src/CONST';
@@ -854,4 +855,42 @@ describe('PolicyUtils', () => {
854855
expect(tagList.name).toEqual(expected);
855856
});
856857
});
858+
describe('sortWorkspacesBySelected', () => {
859+
it('should order workspaces with selected workspace first', () => {
860+
const workspace1 = {policyID: '1', name: 'Workspace 1'};
861+
const workspace2 = {policyID: '2', name: 'Workspace 2'};
862+
const selectedWorkspace1 = {policyID: '3', name: 'Workspace 3'};
863+
const selectedWorkspace2 = {policyID: '4', name: 'Workspace 4'};
864+
expect(sortWorkspacesBySelected(workspace1, workspace2, ['3', '4'], TestHelper.localeCompare)).toBe(-1);
865+
expect(sortWorkspacesBySelected(workspace1, selectedWorkspace1, ['3', '4'], TestHelper.localeCompare)).toBe(1);
866+
expect(sortWorkspacesBySelected(selectedWorkspace1, selectedWorkspace2, ['3', '4'], TestHelper.localeCompare)).toBe(-1);
867+
});
868+
869+
it('should order workspaces using name if no workspace is selected', () => {
870+
const workspace1 = {policyID: '1', name: 'Workspace 1'};
871+
const workspace2 = {policyID: '2', name: 'Workspace 2'};
872+
const workspace3 = {policyID: '3', name: 'Workspace 3'};
873+
const workspace4 = {policyID: '4', name: 'Workspace 4'};
874+
expect(sortWorkspacesBySelected(workspace1, workspace2, undefined, TestHelper.localeCompare)).toBe(-1);
875+
expect(sortWorkspacesBySelected(workspace1, workspace3, undefined, TestHelper.localeCompare)).toBe(-1);
876+
expect(sortWorkspacesBySelected(workspace3, workspace4, undefined, TestHelper.localeCompare)).toBe(-1);
877+
});
878+
879+
it('should sort workspaces when using this method correctly', () => {
880+
const unsortedWorkspaces = [
881+
{policyID: '2', name: 'Workspace 2'},
882+
{policyID: '1', name: 'Workspace 1'},
883+
{policyID: '4', name: 'Workspace 4'},
884+
{policyID: '3', name: 'Workspace 3'},
885+
];
886+
const selectedWorkspaceIDs = ['3', '4'];
887+
const sortedWorkspaces = unsortedWorkspaces.sort((a, b) => sortWorkspacesBySelected(a, b, selectedWorkspaceIDs, TestHelper.localeCompare));
888+
expect(sortedWorkspaces).toEqual([
889+
{policyID: '3', name: 'Workspace 3'},
890+
{policyID: '4', name: 'Workspace 4'},
891+
{policyID: '1', name: 'Workspace 1'},
892+
{policyID: '2', name: 'Workspace 2'},
893+
]);
894+
});
895+
});
857896
});

0 commit comments

Comments
 (0)