diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx index af970a2b92f5f..3722a08aafaf3 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx @@ -1,6 +1,6 @@ import React from 'react'; import {View} from 'react-native'; -import type {SearchColumnType, SortOrder} from '@components/Search/types'; +import type {SortOrder} from '@components/Search/types'; import SortableTableHeader from '@components/SelectionList/SortableTableHeader'; import type {SortableColumnName} from '@components/SelectionList/types'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -52,7 +52,7 @@ const columnConfig: ColumnConfig[] = [ ]; type SearchTableHeaderProps = { - sortBy?: SearchColumnType; + sortBy?: SortableColumnName; sortOrder?: SortOrder; onSortPress: (column: SortableColumnName, order: SortOrder) => void; shouldShowSorting: boolean; diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx index a1fa22a7863c9..25b7351769a87 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx @@ -1,8 +1,12 @@ -import React from 'react'; +import React, {useEffect, useState} from 'react'; import {View} from 'react-native'; +import type {TupleToUnion} from 'type-fest'; +import type {SortOrder} from '@components/Search/types'; import TransactionItemRow from '@components/TransactionItemRow'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; +import {compareValues} from '@libs/SearchUIUtils'; +import CONST from '@src/CONST'; import type * as OnyxTypes from '@src/types/onyx'; import MoneyRequestReportTableHeader from './MoneyRequestReportTableHeader'; @@ -11,24 +15,81 @@ type MoneyRequestReportTransactionListProps = { transactions: OnyxTypes.Transaction[]; }; +const sortableColumnNames = [ + CONST.SEARCH.TABLE_COLUMNS.DATE, + CONST.SEARCH.TABLE_COLUMNS.MERCHANT, + CONST.SEARCH.TABLE_COLUMNS.CATEGORY, + CONST.SEARCH.TABLE_COLUMNS.TAG, + CONST.SEARCH.TABLE_COLUMNS.TOTAL_AMOUNT, +]; + +type SortableColumnName = TupleToUnion; + +type SortedTransactions = { + transactions: OnyxTypes.Transaction[]; + sortBy: SortableColumnName; + sortOrder: SortOrder; +}; + +const isSortableColumnName = (key: unknown): key is SortableColumnName => !!sortableColumnNames.find((val) => val === key); + +const getTransactionKey = (transaction: OnyxTypes.Transaction, key: SortableColumnName) => { + const dateKey = transaction.modifiedCreated ? 'modifiedCreated' : 'created'; + return key === CONST.SEARCH.TABLE_COLUMNS.DATE ? dateKey : key; +}; + +const areTransactionValuesEqual = (transactions: OnyxTypes.Transaction[], key: SortableColumnName) => { + const firstValidTransaction = transactions.find((transaction) => transaction !== undefined); + if (!firstValidTransaction) { + return true; + } + + const keyOfFirstValidTransaction = getTransactionKey(firstValidTransaction, key); + return transactions.every((transaction) => transaction[getTransactionKey(transaction, key)] === firstValidTransaction[keyOfFirstValidTransaction]); +}; + function MoneyRequestReportTransactionList({transactions}: MoneyRequestReportTransactionListProps) { const styles = useThemeStyles(); const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout(); - const displayNarrowVersion = isMediumScreenWidth || shouldUseNarrowLayout; + const [sortedData, setSortedData] = useState({ + transactions, + sortBy: CONST.SEARCH.TABLE_COLUMNS.DATE, + sortOrder: CONST.SEARCH.SORT_ORDER.DESC, + }); + + const {sortBy, sortOrder} = sortedData; + + useEffect(() => { + if (areTransactionValuesEqual(transactions, sortBy)) { + return; + } + + setSortedData((prevState) => ({ + ...prevState, + transactions: [...transactions].sort((a, b) => compareValues(a[getTransactionKey(a, sortBy)], b[getTransactionKey(b, sortBy)], sortOrder, sortBy)), + })); + }, [sortBy, sortOrder, transactions]); + return ( <> {!displayNarrowVersion && ( {}} + sortBy={sortBy} + sortOrder={sortOrder} + onSortPress={(selectedSortBy, selectedSortOrder) => { + if (!isSortableColumnName(selectedSortBy)) { + return; + } + + setSortedData((prevState) => ({...prevState, sortBy: selectedSortBy, sortOrder: selectedSortOrder})); + }} /> )} - {transactions.map((transaction) => { + {sortedData.transactions.map((transaction) => { return (