Skip to content

Commit 7901e07

Browse files
Refactored localeCompare in CardUtils
1 parent 6284b90 commit 7901e07

5 files changed

Lines changed: 23 additions & 11 deletions

File tree

src/libs/CardUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Onyx from 'react-native-onyx';
44
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
55
import type {ValueOf} from 'type-fest';
66
import ExpensifyCardImage from '@assets/images/expensify-card.svg';
7+
import type {LocaleContextProps} from '@components/LocaleContextProvider';
78
import type IllustrationsType from '@styles/theme/illustrations/types';
89
import * as Illustrations from '@src/components/Icon/Illustrations';
910
import CONST from '@src/CONST';
@@ -15,7 +16,6 @@ import type {FilteredCardList} from '@src/types/onyx/Card';
1516
import type {CardFeedData, CompanyCardFeedWithNumber, CompanyCardNicknames, CompanyFeeds, DirectCardFeedData} from '@src/types/onyx/CardFeeds';
1617
import {isEmptyObject} from '@src/types/utils/EmptyObject';
1718
import type IconAsset from '@src/types/utils/IconAsset';
18-
import localeCompare from './LocaleCompare';
1919
import {translateLocal} from './Localize';
2020
import {filterObject} from './ObjectUtils';
2121
import {getDisplayNameOrDefault} from './PersonalDetailsUtils';
@@ -271,7 +271,7 @@ function getCardsByCardholderName(cardsList: OnyxEntry<WorkspaceCardsList>, poli
271271
return Object.values(cards).filter((card: Card) => card.accountID && policyMembersAccountIDs.includes(card.accountID));
272272
}
273273

274-
function sortCardsByCardholderName(cards: Card[], personalDetails: OnyxEntry<PersonalDetailsList>): Card[] {
274+
function sortCardsByCardholderName(cards: Card[], personalDetails: OnyxEntry<PersonalDetailsList>, localeCompare: LocaleContextProps['localeCompare']): Card[] {
275275
return cards.sort((cardA: Card, cardB: Card) => {
276276
const userA = cardA.accountID ? (personalDetails?.[cardA.accountID] ?? {}) : {};
277277
const userB = cardB.accountID ? (personalDetails?.[cardB.accountID] ?? {}) : {};

src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type WorkspaceCompanyCardsListProps = {
4040

4141
function WorkspaceCompanyCardsList({cardsList, policyID, handleAssignCard, isDisabledAssignCardButton, shouldShowGBDisclaimer}: WorkspaceCompanyCardsListProps) {
4242
const styles = useThemeStyles();
43-
const {translate} = useLocalize();
43+
const {translate, localeCompare} = useLocalize();
4444
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false});
4545
const [customCardNames] = useOnyx(ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES, {canBeMissing: true});
4646
const policy = usePolicy(policyID);
@@ -51,7 +51,7 @@ function WorkspaceCompanyCardsList({cardsList, policyID, handleAssignCard, isDis
5151
}, [cardsList, policy?.employeeList]);
5252

5353
const filterCard = useCallback((card: Card, searchInput: string) => filterCardsByPersonalDetails(card, searchInput, personalDetails), [personalDetails]);
54-
const sortCards = useCallback((cards: Card[]) => sortCardsByCardholderName(cards, personalDetails), [personalDetails]);
54+
const sortCards = useCallback((cards: Card[]) => sortCardsByCardholderName(cards, personalDetails, localeCompare), [personalDetails, localeCompare]);
5555
const [inputValue, setInputValue, filteredSortedCards] = useSearchResults(allCards, filterCard, sortCards, true);
5656

5757
const renderItem = useCallback(

src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ type WorkspaceExpensifyCardListPageProps = {
5858

5959
function WorkspaceExpensifyCardListPage({route, cardsList, fundID}: WorkspaceExpensifyCardListPageProps) {
6060
const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
61-
const {translate} = useLocalize();
61+
const {translate, localeCompare} = useLocalize();
6262
const styles = useThemeStyles();
6363

6464
const policyID = route.params.policyID;
@@ -89,7 +89,7 @@ function WorkspaceExpensifyCardListPage({route, cardsList, fundID}: WorkspaceExp
8989
}, [cardsList, policy?.employeeList]);
9090

9191
const filterCard = useCallback((card: Card, searchInput: string) => filterCardsByPersonalDetails(card, searchInput, personalDetails), [personalDetails]);
92-
const sortCards = useCallback((cards: Card[]) => sortCardsByCardholderName(cards, personalDetails), [personalDetails]);
92+
const sortCards = useCallback((cards: Card[]) => sortCardsByCardholderName(cards, personalDetails, localeCompare), [personalDetails, localeCompare]);
9393
const [inputValue, setInputValue, filteredSortedCards] = useSearchResults(allCards, filterCard, sortCards);
9494

9595
const handleIssueCardPress = () => {

tests/unit/CardUtilsTest.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
} from '@src/libs/CardUtils';
2929
import type {CardFeeds, CardList, CompanyCardFeed, ExpensifyCardSettings, PersonalDetailsList, Policy, WorkspaceCardsList} from '@src/types/onyx';
3030
import type {CompanyCardFeedWithNumber} from '@src/types/onyx/CardFeeds';
31+
import {localeCompare} from '../utils/TestHelper';
3132
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
3233

3334
const shortDate = '0924';
@@ -931,7 +932,7 @@ describe('CardUtils', () => {
931932
it('should sort cards by cardholder name in ascending order', () => {
932933
const policyMembersAccountIDs = [1, 2, 3];
933934
const cards = getCardsByCardholderName(mockCards, policyMembersAccountIDs);
934-
const sortedCards = sortCardsByCardholderName(cards, mockPersonalDetails);
935+
const sortedCards = sortCardsByCardholderName(cards, mockPersonalDetails, localeCompare);
935936

936937
expect(sortedCards).toHaveLength(3);
937938
expect(sortedCards.at(0)?.cardID).toBe(2);
@@ -942,7 +943,7 @@ describe('CardUtils', () => {
942943
it('should filter out cards that are not associated with policy members', () => {
943944
const policyMembersAccountIDs = [1, 2]; // Exclude accountID 3
944945
const cards = getCardsByCardholderName(mockCards, policyMembersAccountIDs);
945-
const sortedCards = sortCardsByCardholderName(cards, mockPersonalDetails);
946+
const sortedCards = sortCardsByCardholderName(cards, mockPersonalDetails, localeCompare);
946947

947948
expect(sortedCards).toHaveLength(2);
948949
expect(sortedCards.at(0)?.cardID).toBe(2);
@@ -952,15 +953,15 @@ describe('CardUtils', () => {
952953
it('should handle undefined cardsList', () => {
953954
const policyMembersAccountIDs = [1, 2, 3];
954955
const cards = getCardsByCardholderName(undefined, policyMembersAccountIDs);
955-
const sortedCards = sortCardsByCardholderName(cards, mockPersonalDetails);
956+
const sortedCards = sortCardsByCardholderName(cards, mockPersonalDetails, localeCompare);
956957

957958
expect(sortedCards).toHaveLength(0);
958959
});
959960

960961
it('should handle undefined personalDetails', () => {
961962
const policyMembersAccountIDs = [1, 2, 3];
962963
const cards = getCardsByCardholderName(mockCards, policyMembersAccountIDs);
963-
const sortedCards = sortCardsByCardholderName(cards, undefined);
964+
const sortedCards = sortCardsByCardholderName(cards, undefined, localeCompare);
964965

965966
expect(sortedCards).toHaveLength(3);
966967
// All cards should be sorted with default names
@@ -998,7 +999,7 @@ describe('CardUtils', () => {
998999

9991000
const policyMembersAccountIDs = [1, 2];
10001001
const cards = getCardsByCardholderName(cardsWithMissingAccountID, policyMembersAccountIDs);
1001-
const sortedCards = sortCardsByCardholderName(cards, mockPersonalDetails);
1002+
const sortedCards = sortCardsByCardholderName(cards, mockPersonalDetails, localeCompare);
10021003

10031004
expect(sortedCards).toHaveLength(1);
10041005
expect(sortedCards.at(0)?.cardID).toBe(1);

tests/utils/TestHelper.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,16 @@ async function navigateToSidebarOption(index: number): Promise<void> {
346346
await waitForBatchedUpdatesWithAct();
347347
}
348348

349+
/**
350+
* @private
351+
* This is a custom collator only for testing purposes.
352+
*/
353+
const customCollator = new Intl.Collator('en', {usage: 'sort', sensitivity: 'variant', numeric: true, caseFirst: 'upper'});
354+
355+
function localeCompare(a: string, b: string): number {
356+
return customCollator.compare(a, b);
357+
}
358+
349359
export type {MockFetch, FormData};
350360
export {
351361
assertFormDataMatchesObject,
@@ -363,4 +373,5 @@ export {
363373
navigateToSidebarOption,
364374
getOnyxData,
365375
getNavigateToChatHintRegex,
376+
localeCompare,
366377
};

0 commit comments

Comments
 (0)