From f2e215be555602f50176209470435d71359b644a Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Mon, 3 Jun 2024 11:41:34 +0200 Subject: [PATCH 1/5] refactor getting search transaction item data --- src/CONST.ts | 2 +- src/libs/SearchUtils.ts | 46 +++++++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index de4e3305edd..1f0788181a1 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -4779,7 +4779,7 @@ const CONST = { SEARCH_RESULTS_PAGE_SIZE: 50, SEARCH_DATA_TYPES: { - TRANSACTION: 'transaction', + TRANSACTION: 'transactions', REPORT: 'report', }, diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index c1f4de2e5e3..33ef6a38286 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -5,7 +5,7 @@ import type {ReportListItemType, TransactionListItemType} from '@components/Sele import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; -import type {SearchAccountDetails, SearchDataTypes, SearchTypeToItemMap, SectionsType} from '@src/types/onyx/SearchResults'; +import type {SearchAccountDetails, SearchDataTypes, SearchPersonalDetails, SearchTransaction, SearchTypeToItemMap, SectionsType} from '@src/types/onyx/SearchResults'; import getTopmostCentralPaneRoute from './Navigation/getTopmostCentralPaneRoute'; import navigationRef from './Navigation/navigationRef'; import type {RootStackParamList, State} from './Navigation/types'; @@ -30,6 +30,32 @@ const columnNamesToSortingProperty = { [CONST.SEARCH_TABLE_COLUMNS.RECEIPT]: null, }; +/** + * @private + */ +function getTransactionItemCommonFormattedProperties( + transactionItem: SearchTransaction, + from: SearchPersonalDetails, + to: SearchAccountDetails, +): Pick { + const isExpenseReport = transactionItem.reportType === CONST.REPORT.TYPE.EXPENSE; + + 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; + const merchant = TransactionUtils.getMerchant(transactionItem); + const formattedMerchant = merchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT || merchant === CONST.TRANSACTION.DEFAULT_MERCHANT ? '' : merchant; + + return { + formattedFrom, + formattedTo, + date, + formattedTotal, + formattedMerchant, + }; +} + function isSearchDataType(type: string): type is SearchDataTypes { const searchDataTypes: string[] = Object.values(CONST.SEARCH_DATA_TYPES); return searchDataTypes.includes(type); @@ -69,12 +95,7 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data']): Transac ? (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; - const merchant = TransactionUtils.getMerchant(transactionItem); - const formattedMerchant = merchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT || merchant === CONST.TRANSACTION.DEFAULT_MERCHANT ? '' : merchant; + const {formattedFrom, formattedTo, formattedTotal, formattedMerchant, date} = getTransactionItemCommonFormattedProperties(transactionItem, from, to); return { ...transactionItem, @@ -82,9 +103,9 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data']): Transac to, formattedFrom, formattedTo, - date, formattedTotal, formattedMerchant, + date, shouldShowMerchant, shouldShowCategory, shouldShowTag, @@ -119,12 +140,7 @@ function getReportSections(data: OnyxTypes.SearchResults['data']): ReportListIte ? (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; - const merchant = TransactionUtils.getMerchant(transactionItem); - const formattedMerchant = merchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT || merchant === CONST.TRANSACTION.DEFAULT_MERCHANT ? '' : merchant; + const {formattedFrom, formattedTo, formattedTotal, formattedMerchant, date} = getTransactionItemCommonFormattedProperties(transactionItem, from, to); const transaction = { ...transactionItem, @@ -133,8 +149,8 @@ function getReportSections(data: OnyxTypes.SearchResults['data']): ReportListIte formattedFrom, formattedTo, formattedTotal, - date, formattedMerchant, + date, shouldShowMerchant, shouldShowCategory, shouldShowTag, From 1bc65f986c87567fe4f26da4ee62c093834ecf96 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Mon, 3 Jun 2024 12:34:05 +0200 Subject: [PATCH 2/5] make category and tag Search columns thinner --- src/styles/utils/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts index 82602efa88b..47e5f2651d6 100644 --- a/src/styles/utils/index.ts +++ b/src/styles/utils/index.ts @@ -1568,9 +1568,11 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({ case CONST.SEARCH_TABLE_COLUMNS.MERCHANT: case CONST.SEARCH_TABLE_COLUMNS.FROM: case CONST.SEARCH_TABLE_COLUMNS.TO: + columnWidth = styles.flex1; + break; case CONST.SEARCH_TABLE_COLUMNS.CATEGORY: case CONST.SEARCH_TABLE_COLUMNS.TAG: - columnWidth = styles.flex1; + columnWidth = {...getWidthStyle(variables.w36), ...styles.flex1}; break; case CONST.SEARCH_TABLE_COLUMNS.TAX_AMOUNT: case CONST.SEARCH_TABLE_COLUMNS.TOTAL: From deb5917c1332112ae10a18b59c9c981d48a5f01a Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Tue, 4 Jun 2024 17:36:31 +0200 Subject: [PATCH 3/5] remove temporary transaction key rename --- src/CONST.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CONST.ts b/src/CONST.ts index 1f0788181a1..de4e3305edd 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -4779,7 +4779,7 @@ const CONST = { SEARCH_RESULTS_PAGE_SIZE: 50, SEARCH_DATA_TYPES: { - TRANSACTION: 'transactions', + TRANSACTION: 'transaction', REPORT: 'report', }, From 3e23b0e83f10f3ca95befccac7f41b5203530912 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Wed, 5 Jun 2024 09:03:18 +0200 Subject: [PATCH 4/5] disable sorting on Search tabs other than ALL --- src/components/Search.tsx | 6 +++++- .../SelectionList/SearchTableHeader.tsx | 16 +++++++++----- .../SelectionList/SortableHeaderText.tsx | 21 ++++++++++++++----- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/components/Search.tsx b/src/components/Search.tsx index fcb91537918..2ae13fb7bd5 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -32,6 +32,8 @@ type SearchProps = { sortOrder?: SortOrder; }; +const sortableSearchTabs: SearchQuery[] = [CONST.TAB_SEARCH.ALL]; + function isReportListItemType(item: TransactionListItemType | ReportListItemType): item is ReportListItemType { const reportListItem = item as ReportListItemType; return reportListItem.transactions !== undefined; @@ -100,6 +102,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { const ListItem = SearchUtils.getListItem(type); const data = SearchUtils.getSections(searchResults?.data ?? {}, type); + const sortedData = SearchUtils.getSortedSections(type, data, sortBy, sortOrder); const onSortPress = (column: SearchColumnType, order: SortOrder) => { navigation.setParams({ @@ -108,7 +111,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { }); }; - const sortedData = SearchUtils.getSortedSections(type, data, sortBy, sortOrder); + const isSortingAllowed = sortableSearchTabs.includes(query); return ( @@ -117,6 +120,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { data={searchResults?.data} onSortPress={onSortPress} sortOrder={sortOrder} + isSortingAllowed={isSortingAllowed} sortBy={sortBy} /> } diff --git a/src/components/SelectionList/SearchTableHeader.tsx b/src/components/SelectionList/SearchTableHeader.tsx index ab930936ec9..d2f020d774c 100644 --- a/src/components/SelectionList/SearchTableHeader.tsx +++ b/src/components/SelectionList/SearchTableHeader.tsx @@ -14,7 +14,7 @@ import SortableHeaderText from './SortableHeaderText'; type SearchColumnConfig = { columnName: SearchColumnType; translationKey: TranslationPaths; - isSortable?: boolean; + isColumnSortable?: boolean; shouldShow: (data: OnyxTypes.SearchResults['data']) => boolean; }; @@ -23,7 +23,7 @@ const SearchColumns: SearchColumnConfig[] = [ columnName: CONST.SEARCH_TABLE_COLUMNS.RECEIPT, translationKey: 'common.receipt', shouldShow: () => true, - isSortable: false, + isColumnSortable: false, }, { columnName: CONST.SEARCH_TABLE_COLUMNS.DATE, @@ -79,6 +79,7 @@ const SearchColumns: SearchColumnConfig[] = [ columnName: CONST.SEARCH_TABLE_COLUMNS.ACTION, translationKey: 'common.action', shouldShow: () => true, + isColumnSortable: false, }, ]; @@ -86,10 +87,11 @@ type SearchTableHeaderProps = { data: OnyxTypes.SearchResults['data']; sortBy?: SearchColumnType; sortOrder?: SortOrder; + isSortingAllowed: boolean; onSortPress: (column: SearchColumnType, order: SortOrder) => void; }; -function SearchTableHeader({data, sortBy, sortOrder, onSortPress}: SearchTableHeaderProps) { +function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPress}: SearchTableHeaderProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {isSmallScreenWidth, isMediumScreenWidth} = useWindowDimensions(); @@ -103,9 +105,14 @@ function SearchTableHeader({data, sortBy, sortOrder, onSortPress}: SearchTableHe return ( - {SearchColumns.map(({columnName, translationKey, shouldShow, isSortable}) => { + {SearchColumns.map(({columnName, translationKey, shouldShow, isColumnSortable}) => { + if (!shouldShow(data)) { + return null; + } + const isActive = sortBy === columnName; const textStyle = columnName === CONST.SEARCH_TABLE_COLUMNS.RECEIPT ? StyleUtils.getTextOverflowStyle('clip') : null; + const isSortable = isSortingAllowed && isColumnSortable; return ( onSortPress(columnName, order)} /> diff --git a/src/components/SelectionList/SortableHeaderText.tsx b/src/components/SelectionList/SortableHeaderText.tsx index d84d438b374..bd5f4873bbb 100644 --- a/src/components/SelectionList/SortableHeaderText.tsx +++ b/src/components/SelectionList/SortableHeaderText.tsx @@ -14,23 +14,34 @@ type SearchTableHeaderColumnProps = { text: string; isActive: boolean; sortOrder: SortOrder; - shouldShow?: boolean; isSortable?: boolean; containerStyle?: StyleProp; textStyle?: StyleProp; onPress: (order: SortOrder) => void; }; -export default function SortableHeaderText({text, sortOrder, isActive, textStyle, containerStyle, shouldShow = true, isSortable = true, onPress}: SearchTableHeaderColumnProps) { +export default function SortableHeaderText({text, sortOrder, isActive, textStyle, containerStyle, isSortable = true, onPress}: SearchTableHeaderColumnProps) { const styles = useThemeStyles(); const theme = useTheme(); - if (!shouldShow) { - return null; + if (!isSortable) { + return ( + + + + {text} + + + + ); } const icon = sortOrder === CONST.SORT_ORDER.ASC ? Expensicons.ArrowUpLong : Expensicons.ArrowDownLong; const displayIcon = isActive; + const activeColumnStyle = isSortable && isActive && styles.searchTableHeaderActive; const nextSortOrder = isActive && sortOrder === CONST.SORT_ORDER.DESC ? CONST.SORT_ORDER.ASC : CONST.SORT_ORDER.DESC; @@ -46,7 +57,7 @@ export default function SortableHeaderText({text, sortOrder, isActive, textStyle {text} From 38c129366a848480e25969849d0a0e7aa966804b Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Wed, 5 Jun 2024 17:30:54 +0200 Subject: [PATCH 5/5] rename total to amount --- src/CONST.ts | 2 +- src/components/SelectionList/Search/TransactionListItemRow.tsx | 2 +- src/components/SelectionList/SearchTableHeader.tsx | 3 ++- src/libs/SearchUtils.ts | 2 +- src/styles/utils/index.ts | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index aa3ade14b04..96aca66ee42 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -937,7 +937,7 @@ const CONST = { TO: 'to', CATEGORY: 'category', TAG: 'tag', - TOTAL: 'total', + TOTAL_AMOUNT: 'amount', TYPE: 'type', ACTION: 'action', TAX_AMOUNT: 'taxAmount', diff --git a/src/components/SelectionList/Search/TransactionListItemRow.tsx b/src/components/SelectionList/Search/TransactionListItemRow.tsx index cb1ef3fdc6e..2b32706c98f 100644 --- a/src/components/SelectionList/Search/TransactionListItemRow.tsx +++ b/src/components/SelectionList/Search/TransactionListItemRow.tsx @@ -362,7 +362,7 @@ function TransactionListItemRow({item, showTooltip, onButtonPress, showItemHeade )} - + SearchUtils.getShouldShowColumn(data, CONST.SEARCH_TABLE_COLUMNS.TAX_AMOUNT), }, { - columnName: CONST.SEARCH_TABLE_COLUMNS.TOTAL, + columnName: CONST.SEARCH_TABLE_COLUMNS.TOTAL_AMOUNT, translationKey: 'common.total', shouldShow: () => true, }, @@ -74,6 +74,7 @@ const SearchColumns: SearchColumnConfig[] = [ columnName: CONST.SEARCH_TABLE_COLUMNS.TYPE, translationKey: 'common.type', shouldShow: () => true, + isColumnSortable: false, }, { columnName: CONST.SEARCH_TABLE_COLUMNS.ACTION, diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 33ef6a38286..6d0b9ab0867 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -21,7 +21,7 @@ const columnNamesToSortingProperty = { [CONST.SEARCH_TABLE_COLUMNS.DATE]: 'date' as const, [CONST.SEARCH_TABLE_COLUMNS.TAG]: 'tag' as const, [CONST.SEARCH_TABLE_COLUMNS.MERCHANT]: 'formattedMerchant' as const, - [CONST.SEARCH_TABLE_COLUMNS.TOTAL]: 'formattedTotal' as const, + [CONST.SEARCH_TABLE_COLUMNS.TOTAL_AMOUNT]: 'formattedTotal' as const, [CONST.SEARCH_TABLE_COLUMNS.CATEGORY]: 'category' as const, [CONST.SEARCH_TABLE_COLUMNS.TYPE]: 'type' as const, [CONST.SEARCH_TABLE_COLUMNS.ACTION]: 'action' as const, diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts index 47e5f2651d6..7fcd30bb19e 100644 --- a/src/styles/utils/index.ts +++ b/src/styles/utils/index.ts @@ -1575,7 +1575,7 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({ columnWidth = {...getWidthStyle(variables.w36), ...styles.flex1}; break; case CONST.SEARCH_TABLE_COLUMNS.TAX_AMOUNT: - case CONST.SEARCH_TABLE_COLUMNS.TOTAL: + case CONST.SEARCH_TABLE_COLUMNS.TOTAL_AMOUNT: columnWidth = {...getWidthStyle(variables.w96), ...styles.alignItemsEnd}; break; case CONST.SEARCH_TABLE_COLUMNS.TYPE: