diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 48819c93f275..cfb630ca73b5 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -6696,6 +6696,8 @@ const CONST = { TO: this.TABLE_COLUMNS.TO, CATEGORY: this.TABLE_COLUMNS.CATEGORY, TAG: this.TABLE_COLUMNS.TAG, + REIMBURSABLE: this.TABLE_COLUMNS.REIMBURSABLE, + BILLABLE: this.TABLE_COLUMNS.BILLABLE, STATUS: this.TABLE_COLUMNS.STATUS, ACTION: this.TABLE_COLUMNS.ACTION, }, @@ -6789,6 +6791,8 @@ const CONST = { TO: 'to', CATEGORY: 'category', TAG: 'tag', + REIMBURSABLE: 'reimbursable', + BILLABLE: 'billable', TOTAL_AMOUNT: 'amount', TOTAL: 'total', TYPE: 'type', diff --git a/src/components/SelectionListWithSections/SearchTableHeader.tsx b/src/components/SelectionListWithSections/SearchTableHeader.tsx index d55e102ac7ea..307a42931b8e 100644 --- a/src/components/SelectionListWithSections/SearchTableHeader.tsx +++ b/src/components/SelectionListWithSections/SearchTableHeader.tsx @@ -80,6 +80,16 @@ const getExpenseHeaders = (groupBy?: SearchGroupBy): SearchColumnConfig[] => [ translationKey: 'common.tag', canBeMissing: true, }, + { + columnName: CONST.SEARCH.TABLE_COLUMNS.REIMBURSABLE, + translationKey: 'common.reimbursable', + canBeMissing: true, + }, + { + columnName: CONST.SEARCH.TABLE_COLUMNS.BILLABLE, + translationKey: 'common.billable', + canBeMissing: true, + }, { columnName: CONST.SEARCH.TABLE_COLUMNS.WITHDRAWAL_ID, translationKey: 'common.withdrawalID', diff --git a/src/components/TransactionItemRow/index.tsx b/src/components/TransactionItemRow/index.tsx index 8b3606761416..6295983cbc78 100644 --- a/src/components/TransactionItemRow/index.tsx +++ b/src/components/TransactionItemRow/index.tsx @@ -311,6 +311,22 @@ function TransactionItemRow({ /> ), + [CONST.SEARCH.TABLE_COLUMNS.REIMBURSABLE]: ( + + {transactionItem.reimbursable ? translate('common.yes') : translate('common.no')} + + ), + [CONST.SEARCH.TABLE_COLUMNS.BILLABLE]: ( + + {transactionItem.billable ? translate('common.yes') : translate('common.no')} + + ), [CONST.SEARCH.TABLE_COLUMNS.ACTION]: ( { - const aValue = sortingProperty === 'comment' ? a.comment?.comment : a[sortingProperty as keyof TransactionListItemType]; - const bValue = sortingProperty === 'comment' ? b.comment?.comment : b[sortingProperty as keyof TransactionListItemType]; + const aValue = getTransactionSortValue(a, sortingProperty); + const bValue = getTransactionSortValue(b, sortingProperty); - return compareValues(aValue, bValue, sortOrder, sortingProperty, localeCompare); + const primaryComparison = compareValues(aValue, bValue, sortOrder, sortingProperty, localeCompare); + + if (primaryComparison !== 0) { + return primaryComparison; + } + + // If we have a tie in the primary comparison, we add a tie breaker on date and/or transactionID as a last resort to make the sort deterministic + const createdComparison = compareValues(a.created, b.created, sortOrder, 'created', localeCompare); + + if (createdComparison !== 0) { + return createdComparison; + } + + return compareValues(a.transactionID, b.transactionID, sortOrder, 'transactionID', localeCompare); }); } @@ -2246,6 +2279,10 @@ function getSearchColumnTranslationKey(columnId: SearchCustomColumnIds): Transla return 'common.receipt'; case CONST.SEARCH.TABLE_COLUMNS.TAG: return 'common.tag'; + case CONST.SEARCH.TABLE_COLUMNS.REIMBURSABLE: + return 'common.reimbursable'; + case CONST.SEARCH.TABLE_COLUMNS.BILLABLE: + return 'common.billable'; case CONST.SEARCH.TABLE_COLUMNS.ACTION: return 'common.action'; case CONST.SEARCH.TABLE_COLUMNS.TITLE: @@ -2711,6 +2748,8 @@ function getColumnsToShow( [CONST.SEARCH.TABLE_COLUMNS.TO]: false, [CONST.SEARCH.TABLE_COLUMNS.CATEGORY]: false, [CONST.SEARCH.TABLE_COLUMNS.TAG]: false, + [CONST.SEARCH.TABLE_COLUMNS.REIMBURSABLE]: false, + [CONST.SEARCH.TABLE_COLUMNS.BILLABLE]: false, [CONST.SEARCH.TABLE_COLUMNS.TAX_AMOUNT]: false, [CONST.SEARCH.TABLE_COLUMNS.TOTAL_AMOUNT]: true, [CONST.SEARCH.TABLE_COLUMNS.STATUS]: false, @@ -2920,6 +2959,8 @@ function getTableMinWidth(columns: SearchColumnType[]) { minWidth += 72; } else if (column === CONST.SEARCH.TABLE_COLUMNS.TYPE) { minWidth += 20; + } else if (column === CONST.SEARCH.TABLE_COLUMNS.REIMBURSABLE || column === CONST.SEARCH.TABLE_COLUMNS.BILLABLE) { + minWidth += 92; } else { minWidth += 200; } diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts index d1cb7ea5711c..ad0a69a8b65f 100644 --- a/src/styles/utils/index.ts +++ b/src/styles/utils/index.ts @@ -1771,6 +1771,10 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({ case CONST.SEARCH.TABLE_COLUMNS.TYPE: columnWidth = {...getWidthStyle(variables.w20), ...styles.alignItemsCenter}; break; + case CONST.SEARCH.TABLE_COLUMNS.REIMBURSABLE: + case CONST.SEARCH.TABLE_COLUMNS.BILLABLE: + columnWidth = {...getWidthStyle(variables.w92)}; + break; case CONST.SEARCH.TABLE_COLUMNS.ACTION: columnWidth = {...getWidthStyle(variables.w80), ...styles.alignItemsCenter}; break; diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index 8e273aa050bf..b4c1b566c49c 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -170,6 +170,12 @@ type SearchTransaction = { /** The group currency if the transaction is grouped. Defaults to the active policy currency if group has no target currency */ groupCurrency?: string; + /** Reimbursable status of the transaction */ + reimbursable?: boolean; + + /** Billable status of the transaction */ + billable?: boolean; + /** The card transaction's posted date */ posted?: string; };