diff --git a/src/components/Search.tsx b/src/components/Search.tsx index a1ca673d3890..43a0428ecd45 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -25,13 +25,13 @@ import type {TransactionListItemType} from './SelectionList/types'; import TableListItemSkeleton from './Skeletons/TableListItemSkeleton'; const columnNamesToPropertyMap = { - [CONST.SEARCH_TABLE_COLUMNS.TO]: 'to', - [CONST.SEARCH_TABLE_COLUMNS.FROM]: 'from', - [CONST.SEARCH_TABLE_COLUMNS.DATE]: 'created', - [CONST.SEARCH_TABLE_COLUMNS.TAG]: '', - [CONST.SEARCH_TABLE_COLUMNS.MERCHANT]: 'merchant', - [CONST.SEARCH_TABLE_COLUMNS.TOTAL]: 'amount', - [CONST.SEARCH_TABLE_COLUMNS.CATEGORY]: 'category', + [CONST.SEARCH_TABLE_COLUMNS.TO]: 'formattedTo' as const, + [CONST.SEARCH_TABLE_COLUMNS.FROM]: 'formattedFrom' as const, + [CONST.SEARCH_TABLE_COLUMNS.DATE]: 'date' as const, + [CONST.SEARCH_TABLE_COLUMNS.TAG]: 'tag' as const, + [CONST.SEARCH_TABLE_COLUMNS.MERCHANT]: 'merchant' as const, + [CONST.SEARCH_TABLE_COLUMNS.TOTAL]: 'formattedTotal' as const, + [CONST.SEARCH_TABLE_COLUMNS.CATEGORY]: 'category' as const, [CONST.SEARCH_TABLE_COLUMNS.TYPE]: null, [CONST.SEARCH_TABLE_COLUMNS.ACTION]: null, [CONST.SEARCH_TABLE_COLUMNS.DESCRIPTION]: null, @@ -43,13 +43,12 @@ function getSortedData(data: TransactionListItemType[], sortBy?: SearchColumnTyp return data; } - const sortingProp = columnNamesToPropertyMap[sortBy] as keyof TransactionListItemType; + const sortingProp = columnNamesToPropertyMap[sortBy]; if (!sortingProp) { return data; } - // Todo sorting needs more work return data.sort((a, b) => { const aValue = a[sortingProp]; const bValue = b[sortingProp]; @@ -58,13 +57,15 @@ function getSortedData(data: TransactionListItemType[], sortBy?: SearchColumnTyp return 0; } + // We are guaranteed that both a and b will be string or number at the same time if (typeof aValue === 'string' && typeof bValue === 'string') { return sortOrder === 'asc' ? aValue.toLowerCase().localeCompare(bValue) : bValue.toLowerCase().localeCompare(aValue); } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - return sortOrder === 'asc' ? aValue - bValue : bValue - aValue; + const aNum = aValue as number; + const bNum = bValue as number; + + return sortOrder === 'asc' ? aNum - bNum : bNum - aNum; }); } diff --git a/src/components/SelectionList/SearchTableHeader.tsx b/src/components/SelectionList/SearchTableHeader.tsx index 31a5c032ce86..9cd44e6716fa 100644 --- a/src/components/SelectionList/SearchTableHeader.tsx +++ b/src/components/SelectionList/SearchTableHeader.tsx @@ -67,6 +67,7 @@ const SearchColumns: SearchColumnConfig[] = [ { columnName: CONST.SEARCH_TABLE_COLUMNS.TYPE, translationKey: 'common.type', + isSortable: false, shouldShowFn: () => true, }, { diff --git a/src/components/SelectionList/TransactionListItem.tsx b/src/components/SelectionList/TransactionListItem.tsx index 5af32e05f2ac..1612216816cc 100644 --- a/src/components/SelectionList/TransactionListItem.tsx +++ b/src/components/SelectionList/TransactionListItem.tsx @@ -60,11 +60,10 @@ function TransactionListItem({ } const isFromExpenseReport = transactionItem.reportType === CONST.REPORT.TYPE.EXPENSE; - const date = TransactionUtils.getCreated(transactionItem as OnyxEntry, CONST.DATE.MONTH_DAY_ABBR_FORMAT); - const amount = TransactionUtils.getAmount(transactionItem as OnyxEntry, isFromExpenseReport); - const taxAmount = TransactionUtils.getTaxAmount(transactionItem as OnyxEntry, isFromExpenseReport); - const currency = TransactionUtils.getCurrency(transactionItem as OnyxEntry); - const description = TransactionUtils.getDescription(transactionItem as OnyxEntry); + const date = TransactionUtils.getCreated(transactionItem, CONST.DATE.MONTH_DAY_ABBR_FORMAT); + const taxAmount = TransactionUtils.getTaxAmount(transactionItem, isFromExpenseReport); + const currency = TransactionUtils.getCurrency(transactionItem); + const description = TransactionUtils.getDescription(transactionItem); const merchant = getMerchant(); const typeIcon = getTypeIcon(transactionItem.type); @@ -84,8 +83,7 @@ function TransactionListItem({ /> ); - const userCell = (participant: SearchAccountDetails) => { - const displayName = participant?.name ?? participant?.displayName ?? participant?.login; + const userCell = (participant: SearchAccountDetails, displayName: string) => { const avatarURL = participant?.avatarURL ?? participant?.avatar; const isWorkspace = participant?.avatarURL !== undefined; const iconType = isWorkspace ? CONST.ICON_TYPE_WORKSPACE : CONST.ICON_TYPE_AVATAR; @@ -149,7 +147,7 @@ function TransactionListItem({ const totalCell = ( ); @@ -202,14 +200,14 @@ function TransactionListItem({ <> - {userCell(transactionItem.from)} + {userCell(transactionItem.from, transactionItem.formattedFrom)} - {userCell(transactionItem.to)} + {userCell(transactionItem.to, transactionItem.formattedTo)} {actionCell} @@ -259,8 +257,8 @@ function TransactionListItem({ {dateCell} {merchantCell} - {userCell(transactionItem.from)} - {userCell(transactionItem.to)} + {userCell(transactionItem.from, transactionItem.formattedFrom)} + {userCell(transactionItem.to, transactionItem.formattedTo)} {transactionItem.shouldShowCategory && {categoryCell}} {transactionItem.shouldShowTag && {tagCell}} {transactionItem.shouldShowTax && {taxCell}} diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 0a4b0532b581..ad2a2fe96bce 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -135,6 +135,18 @@ type TransactionListItemType = ListItem & /** The personal details of the user paying the request */ to: SearchAccountDetails; + /** final and formatted "from" value used for displaying and sorting */ + formattedFrom: string; + + /** final and formatted "to" value used for displaying and sorting */ + formattedTo: string; + + /** final and formatted "total" value used for displaying and sorting */ + formattedTotal: number; + + /** final "date" value used for sorting */ + date: string; + /** Whether we should show the merchant column */ shouldShowMerchant: boolean; diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index af75479cc313..2d480f00f98d 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -4,7 +4,8 @@ import type {TransactionListItemType} from '@components/SelectionList/types'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; -import type {SearchDataTypes, SearchTypeToItemMap} from '@src/types/onyx/SearchResults'; +import type {SearchAccountDetails, SearchDataTypes, SearchTypeToItemMap} from '@src/types/onyx/SearchResults'; +import * as TransactionUtils from './TransactionUtils'; import * as UserUtils from './UserUtils'; type SortOrder = 'asc' | 'desc'; @@ -36,19 +37,34 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data']): Transac const shouldShowCategory = getShouldShowColumn(data, CONST.SEARCH_TABLE_COLUMNS.CATEGORY); const shouldShowTag = getShouldShowColumn(data, CONST.SEARCH_TABLE_COLUMNS.TAG); const shouldShowTax = getShouldShowColumn(data, CONST.SEARCH_TABLE_COLUMNS.TAX_AMOUNT); + return Object.entries(data) .filter(([key]) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) - .map(([, value]) => { - const isExpenseReport = value.reportType === CONST.REPORT.TYPE.EXPENSE; + .map(([, transactionItem]) => { + const isExpenseReport = transactionItem.reportType === CONST.REPORT.TYPE.EXPENSE; + const from = data.personalDetailsList?.[transactionItem.accountID]; + const to = isExpenseReport + ? (data[`${ONYXKEYS.COLLECTION.POLICY}${transactionItem.policyID}`] as SearchAccountDetails) + : (data.personalDetailsList?.[transactionItem.managerID] as SearchAccountDetails); + + const formattedFrom = from.displayName ?? from.login ?? ''; + const formattedTo = to.name ?? to.displayName ?? to.login ?? ''; + const formattedTotal = TransactionUtils.getAmount(transactionItem, isExpenseReport); + const date = transactionItem?.modifiedCreated ? transactionItem.modifiedCreated : transactionItem?.created; + return { - ...value, - from: data.personalDetailsList?.[value.accountID], - to: isExpenseReport ? data[`${ONYXKEYS.COLLECTION.POLICY}${value.policyID}`] : data.personalDetailsList?.[value.managerID], + ...transactionItem, + from, + to, + formattedFrom, + formattedTo, + date, + formattedTotal, shouldShowMerchant, shouldShowCategory, shouldShowTag, shouldShowTax, - keyForList: value.transactionID, + keyForList: transactionItem.transactionID, }; }) .sort((a, b) => {