From c7aae0f98ea63c800b5969d5fab12fed5f24b91a Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Mon, 10 Jun 2024 23:30:48 +0530 Subject: [PATCH 01/11] Show year as well in date column --- src/components/SelectionList/Search/TransactionListItemRow.tsx | 2 +- src/styles/utils/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/SelectionList/Search/TransactionListItemRow.tsx b/src/components/SelectionList/Search/TransactionListItemRow.tsx index 50a34be86f617..f5a41000e57dd 100644 --- a/src/components/SelectionList/Search/TransactionListItemRow.tsx +++ b/src/components/SelectionList/Search/TransactionListItemRow.tsx @@ -93,7 +93,7 @@ function ReceiptCell({transactionItem, isHovered = false}: ReceiptCellProps) { function DateCell({transactionItem, showTooltip, isLargeScreenWidth}: TransactionCellProps) { const styles = useThemeStyles(); - const date = TransactionUtils.getCreated(transactionItem, CONST.DATE.MONTH_DAY_ABBR_FORMAT); + const date = TransactionUtils.getCreated(transactionItem, CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT); return ( ({ columnWidth = {...getWidthStyle(variables.w36), ...styles.alignItemsCenter}; break; case CONST.SEARCH_TABLE_COLUMNS.DATE: - columnWidth = getWidthStyle(variables.w44); + columnWidth = getWidthStyle(variables.w80); break; case CONST.SEARCH_TABLE_COLUMNS.MERCHANT: case CONST.SEARCH_TABLE_COLUMNS.FROM: From 920f4dd8ab3ffcfb57ced1011224d63ed62c03b5 Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Tue, 11 Jun 2024 23:09:19 +0530 Subject: [PATCH 02/11] Update --- src/components/Search.tsx | 3 ++ .../Search/TransactionListItemRow.tsx | 10 ++++- .../SelectionList/SearchTableHeader.tsx | 5 ++- src/components/SelectionList/types.ts | 3 ++ src/libs/DateUtils.ts | 6 +++ src/libs/SearchUtils.ts | 37 ++++++++++++++++++- src/styles/utils/index.ts | 4 +- 7 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/components/Search.tsx b/src/components/Search.tsx index 3d295e72c09e4..596b5f7aaa99a 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -122,6 +122,8 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { const isSortingAllowed = sortableSearchTabs.includes(query); + const doesAtleastOneExpenseBelongToAPastYear = SearchUtils.doesAtleastOneExpenseBelongToAPastYear(searchResults?.data as TransactionListItemType[] | ReportListItemType[]); + return ( customListHeader={ @@ -131,6 +133,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { sortOrder={sortOrder} isSortingAllowed={isSortingAllowed} sortBy={sortBy} + doesAtleastOneExpenseBelongToAPastYear={doesAtleastOneExpenseBelongToAPastYear} /> } // To enhance the smoothness of scrolling and minimize the risk of encountering blank spaces during scrolling, diff --git a/src/components/SelectionList/Search/TransactionListItemRow.tsx b/src/components/SelectionList/Search/TransactionListItemRow.tsx index f5a41000e57dd..efc290151f56a 100644 --- a/src/components/SelectionList/Search/TransactionListItemRow.tsx +++ b/src/components/SelectionList/Search/TransactionListItemRow.tsx @@ -18,6 +18,7 @@ import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import type {SearchTransactionType} from '@src/types/onyx/SearchResults'; +import DateUtils from "@libs/DateUtils"; import ExpenseItemHeaderNarrow from './ExpenseItemHeaderNarrow'; import TextWithIconCell from './TextWithIconCell'; import UserInfoCell from './UserInfoCell'; @@ -53,6 +54,7 @@ type TransactionListItemRowProps = { containerStyle?: StyleProp; isHovered?: boolean; isChildListItem?: boolean; + doesAtleastOneExpenseBelongToAPastYear: boolean; }; const getTypeIcon = (type?: SearchTransactionType) => { @@ -91,9 +93,13 @@ function ReceiptCell({transactionItem, isHovered = false}: ReceiptCellProps) { ); } +const getCreated = (item: TransactionListItemType) => item?.modifiedCreated ? item.modifiedCreated : item?.created || '' + function DateCell({transactionItem, showTooltip, isLargeScreenWidth}: TransactionCellProps) { const styles = useThemeStyles(); - const date = TransactionUtils.getCreated(transactionItem, CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT); + + const created = getCreated(transactionItem); + const date = DateUtils.formatWithUTCTimeZone(created, DateUtils.doesDateBelongToAPastYear(transactionItem) ? CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT : CONST.DATE.MONTH_DAY_ABBR_FORMAT); return ( - + void; + doesAtleastOneExpenseBelongToAPastYear: boolean; }; -function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPress}: SearchTableHeaderProps) { +function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPress, doesAtleastOneExpenseBelongToAPastYear}: SearchTableHeaderProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {isSmallScreenWidth, isMediumScreenWidth} = useWindowDimensions(); @@ -123,7 +124,7 @@ function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPre textStyle={textStyle} sortOrder={sortOrder ?? CONST.SORT_ORDER.ASC} isActive={isActive} - containerStyle={[StyleUtils.getSearchTableColumnStyles(columnName)]} + containerStyle={[StyleUtils.getSearchTableColumnStyles(columnName, doesAtleastOneExpenseBelongToAPastYear)]} isSortable={isSortable} onPress={(order: SortOrder) => onSortPress(columnName, order)} /> diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 5d5e7fc3891b9..b6894b889732a 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -168,6 +168,9 @@ type TransactionListItemType = ListItem & /** Whether we should show the tax column */ shouldShowTax: boolean; + + /** Info about whether there's atleast one transaction that doesn't belong to the present year */ + doesAtleastOneExpenseBelongToAPastYear: boolean; }; type ReportListItemType = ListItem & diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 50cb9a20dff6c..17f460f4cfc52 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -797,6 +797,11 @@ function getFormattedTransportDate(date: Date): string { return `${translateLocal('travel.departs')} ${format(date, 'EEEE, MMM d, yyyy')} ${translateLocal('common.conjunctionAt')} ${format(date, 'HH:MM')}`; } +function doesDateBelongToAPastYear(date: string): boolean { + const transactionYear = new Date(date).getFullYear(); + return transactionYear !== new Date().getFullYear(); +} + const DateUtils = { formatToDayOfWeek, formatToLongDateWithWeekday, @@ -840,6 +845,7 @@ const DateUtils = { getFormattedDateRange, getFormattedReservationRangeDate, getFormattedTransportDate, + doesDateBelongToAPastYear }; export default DateUtils; diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index a5d2ac1d9df27..8d42510fb4b54 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -6,6 +6,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; import type {SearchAccountDetails, SearchDataTypes, SearchPersonalDetails, SearchTransaction, SearchTypeToItemMap, SectionsType} from '@src/types/onyx/SearchResults'; +import DateUtils from "./DateUtils"; import getTopmostCentralPaneRoute from './Navigation/getTopmostCentralPaneRoute'; import navigationRef from './Navigation/navigationRef'; import type {CentralPaneNavigatorParamList, RootStackParamList, State} from './Navigation/types'; @@ -76,9 +77,39 @@ function getShouldShowMerchant(data: OnyxTypes.SearchResults['data']): boolean { }); } +function doesAtleastOneExpenseBelongToAPastYear(data: TransactionListItemType[] | ReportListItemType[] | OnyxTypes.SearchResults['data']): boolean { + if (Array.isArray(data)) { + return data.some((item: TransactionListItemType | ReportListItemType) => { + if ('transactions' in item) { + // If the item is a ReportListItemType, iterate over its transactions and check them + return item.transactions.some(transaction => { + const transactionYear = new Date(transaction?.modifiedCreated ? transaction.modifiedCreated : transaction?.created || '').getFullYear(); + return transactionYear !== new Date().getFullYear(); + }); + } + + const createdYear = new Date(item?.modifiedCreated ? item.modifiedCreated : item?.created || '').getFullYear(); + return createdYear !== new Date().getFullYear(); + }); + } + for (const [key, transactionItem] of Object.entries(data)) { + if (key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) { + const item = transactionItem as SearchTransaction; + const date = item?.modifiedCreated ? item.modifiedCreated : item?.created || ''; + + if (DateUtils.doesDateBelongToAPastYear(date)) { + return true; + } + } + } + return false; +} + function getTransactionsSections(data: OnyxTypes.SearchResults['data']): TransactionListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); + const doesDataContainAPastYearTransaction = doesAtleastOneExpenseBelongToAPastYear(data); + return Object.entries(data) .filter(([key]) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) .map(([, transactionItem]) => { @@ -104,6 +135,7 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data']): Transac shouldShowTag: true, shouldShowTax: true, keyForList: transactionItem.transactionID, + doesAtleastOneExpenseBelongToAPastYear: doesDataContainAPastYearTransaction, }; }); } @@ -111,6 +143,8 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data']): Transac function getReportSections(data: OnyxTypes.SearchResults['data']): ReportListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); + const doesDataContainAPastYearTransaction = doesAtleastOneExpenseBelongToAPastYear(data); + const reportIDToTransactions: Record = {}; for (const key in data) { if (key.startsWith(ONYXKEYS.COLLECTION.REPORT)) { @@ -146,6 +180,7 @@ function getReportSections(data: OnyxTypes.SearchResults['data']): ReportListIte shouldShowTag: true, shouldShowTax: true, keyForList: transactionItem.transactionID, + doesAtleastOneExpenseBelongToAPastYear: doesDataContainAPastYearTransaction, }; if (reportIDToTransactions[reportKey]?.transactions) { reportIDToTransactions[reportKey].transactions.push(transaction); @@ -230,5 +265,5 @@ function getSearchParams() { return topmostCentralPaneRoute?.params as CentralPaneNavigatorParamList['Search_Central_Pane']; } -export {getListItem, getQueryHash, getSections, getSortedSections, getShouldShowMerchant, getSearchType, getSearchParams}; +export {getListItem, getQueryHash, getSections, getSortedSections, getShouldShowMerchant, getSearchType, getSearchParams, doesAtleastOneExpenseBelongToAPastYear}; export type {SearchColumnType, SortOrder}; diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts index 915497e27d39f..844b6e2a6a230 100644 --- a/src/styles/utils/index.ts +++ b/src/styles/utils/index.ts @@ -1556,14 +1556,14 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({ return isDragging ? styles.cursorGrabbing : styles.cursorZoomOut; }, - getSearchTableColumnStyles: (columnName: string): ViewStyle => { + getSearchTableColumnStyles: (columnName: string, shouldExtendDateColumn = false): ViewStyle => { let columnWidth; switch (columnName) { case CONST.SEARCH_TABLE_COLUMNS.RECEIPT: columnWidth = {...getWidthStyle(variables.w36), ...styles.alignItemsCenter}; break; case CONST.SEARCH_TABLE_COLUMNS.DATE: - columnWidth = getWidthStyle(variables.w80); + columnWidth = getWidthStyle(shouldExtendDateColumn ? variables.w80 : variables.w44); break; case CONST.SEARCH_TABLE_COLUMNS.MERCHANT: case CONST.SEARCH_TABLE_COLUMNS.FROM: From bf1b1a8f5477263fe12b9f07462652d2623d2a91 Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Wed, 12 Jun 2024 00:09:43 +0530 Subject: [PATCH 03/11] Update --- src/components/SelectionList/Search/TransactionListItemRow.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/SelectionList/Search/TransactionListItemRow.tsx b/src/components/SelectionList/Search/TransactionListItemRow.tsx index efc290151f56a..72d8e07014ae8 100644 --- a/src/components/SelectionList/Search/TransactionListItemRow.tsx +++ b/src/components/SelectionList/Search/TransactionListItemRow.tsx @@ -54,7 +54,6 @@ type TransactionListItemRowProps = { containerStyle?: StyleProp; isHovered?: boolean; isChildListItem?: boolean; - doesAtleastOneExpenseBelongToAPastYear: boolean; }; const getTypeIcon = (type?: SearchTransactionType) => { @@ -99,7 +98,7 @@ function DateCell({transactionItem, showTooltip, isLargeScreenWidth}: Transactio const styles = useThemeStyles(); const created = getCreated(transactionItem); - const date = DateUtils.formatWithUTCTimeZone(created, DateUtils.doesDateBelongToAPastYear(transactionItem) ? CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT : CONST.DATE.MONTH_DAY_ABBR_FORMAT); + const date = DateUtils.formatWithUTCTimeZone(created, DateUtils.doesDateBelongToAPastYear(created) ? CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT : CONST.DATE.MONTH_DAY_ABBR_FORMAT); return ( Date: Wed, 12 Jun 2024 00:10:08 +0530 Subject: [PATCH 04/11] Update with type fixes --- src/components/Search.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Search.tsx b/src/components/Search.tsx index 596b5f7aaa99a..69bf82be7f551 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -122,7 +122,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { const isSortingAllowed = sortableSearchTabs.includes(query); - const doesAtleastOneExpenseBelongToAPastYear = SearchUtils.doesAtleastOneExpenseBelongToAPastYear(searchResults?.data as TransactionListItemType[] | ReportListItemType[]); + const doesAtleastOneExpenseBelongToAPastYear = SearchUtils.doesAtleastOneExpenseBelongToAPastYear(searchResults?.data); return ( From 840c2539d9f833832896bfa3b993e196371ff07b Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Wed, 12 Jun 2024 00:30:45 +0530 Subject: [PATCH 05/11] Update with lint fixes --- .../SelectionList/Search/TransactionListItemRow.tsx | 4 ++-- src/libs/DateUtils.ts | 2 +- src/libs/SearchUtils.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/SelectionList/Search/TransactionListItemRow.tsx b/src/components/SelectionList/Search/TransactionListItemRow.tsx index 72d8e07014ae8..6e0bdd3988bc7 100644 --- a/src/components/SelectionList/Search/TransactionListItemRow.tsx +++ b/src/components/SelectionList/Search/TransactionListItemRow.tsx @@ -13,12 +13,12 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as CurrencyUtils from '@libs/CurrencyUtils'; +import DateUtils from '@libs/DateUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import type {SearchTransactionType} from '@src/types/onyx/SearchResults'; -import DateUtils from "@libs/DateUtils"; import ExpenseItemHeaderNarrow from './ExpenseItemHeaderNarrow'; import TextWithIconCell from './TextWithIconCell'; import UserInfoCell from './UserInfoCell'; @@ -92,7 +92,7 @@ function ReceiptCell({transactionItem, isHovered = false}: ReceiptCellProps) { ); } -const getCreated = (item: TransactionListItemType) => item?.modifiedCreated ? item.modifiedCreated : item?.created || '' +const getCreated = (item: TransactionListItemType) => (item?.modifiedCreated ? item.modifiedCreated : item?.created || ''); function DateCell({transactionItem, showTooltip, isLargeScreenWidth}: TransactionCellProps) { const styles = useThemeStyles(); diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 17f460f4cfc52..f7ffbfc25300d 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -845,7 +845,7 @@ const DateUtils = { getFormattedDateRange, getFormattedReservationRangeDate, getFormattedTransportDate, - doesDateBelongToAPastYear + doesDateBelongToAPastYear, }; export default DateUtils; diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 8d42510fb4b54..69bee1183b2be 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -6,7 +6,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; import type {SearchAccountDetails, SearchDataTypes, SearchPersonalDetails, SearchTransaction, SearchTypeToItemMap, SectionsType} from '@src/types/onyx/SearchResults'; -import DateUtils from "./DateUtils"; +import DateUtils from './DateUtils'; import getTopmostCentralPaneRoute from './Navigation/getTopmostCentralPaneRoute'; import navigationRef from './Navigation/navigationRef'; import type {CentralPaneNavigatorParamList, RootStackParamList, State} from './Navigation/types'; @@ -82,7 +82,7 @@ function doesAtleastOneExpenseBelongToAPastYear(data: TransactionListItemType[] return data.some((item: TransactionListItemType | ReportListItemType) => { if ('transactions' in item) { // If the item is a ReportListItemType, iterate over its transactions and check them - return item.transactions.some(transaction => { + return item.transactions.some((transaction) => { const transactionYear = new Date(transaction?.modifiedCreated ? transaction.modifiedCreated : transaction?.created || '').getFullYear(); return transactionYear !== new Date().getFullYear(); }); From d80faaf500a508a8d5a97b65f3864203b8b1cd1c Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Wed, 12 Jun 2024 22:21:40 +0530 Subject: [PATCH 06/11] Update --- .../SelectionList/Search/TransactionListItemRow.tsx | 4 +--- src/libs/SearchUtils.ts | 11 +++++++---- src/libs/TransactionUtils.ts | 10 +++++++--- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/components/SelectionList/Search/TransactionListItemRow.tsx b/src/components/SelectionList/Search/TransactionListItemRow.tsx index 6e0bdd3988bc7..1bda7cd1ef652 100644 --- a/src/components/SelectionList/Search/TransactionListItemRow.tsx +++ b/src/components/SelectionList/Search/TransactionListItemRow.tsx @@ -92,12 +92,10 @@ function ReceiptCell({transactionItem, isHovered = false}: ReceiptCellProps) { ); } -const getCreated = (item: TransactionListItemType) => (item?.modifiedCreated ? item.modifiedCreated : item?.created || ''); - function DateCell({transactionItem, showTooltip, isLargeScreenWidth}: TransactionCellProps) { const styles = useThemeStyles(); - const created = getCreated(transactionItem); + const created = TransactionUtils.getCreatedDate(transactionItem); const date = DateUtils.formatWithUTCTimeZone(created, DateUtils.doesDateBelongToAPastYear(created) ? CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT : CONST.DATE.MONTH_DAY_ABBR_FORMAT); return ( diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 69bee1183b2be..05d92f40d3a0c 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -77,25 +77,28 @@ function getShouldShowMerchant(data: OnyxTypes.SearchResults['data']): boolean { }); } +const currentYear = new Date().getFullYear(); + function doesAtleastOneExpenseBelongToAPastYear(data: TransactionListItemType[] | ReportListItemType[] | OnyxTypes.SearchResults['data']): boolean { if (Array.isArray(data)) { return data.some((item: TransactionListItemType | ReportListItemType) => { if ('transactions' in item) { // If the item is a ReportListItemType, iterate over its transactions and check them return item.transactions.some((transaction) => { - const transactionYear = new Date(transaction?.modifiedCreated ? transaction.modifiedCreated : transaction?.created || '').getFullYear(); - return transactionYear !== new Date().getFullYear(); + const transactionYear = new Date(TransactionUtils.getCreatedDate(transaction)).getFullYear(); + return transactionYear !== currentYear; }); } const createdYear = new Date(item?.modifiedCreated ? item.modifiedCreated : item?.created || '').getFullYear(); - return createdYear !== new Date().getFullYear(); + return createdYear !== currentYear; }); } + for (const [key, transactionItem] of Object.entries(data)) { if (key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) { const item = transactionItem as SearchTransaction; - const date = item?.modifiedCreated ? item.modifiedCreated : item?.created || ''; + const date = TransactionUtils.getCreatedDate(item); if (DateUtils.doesDateBelongToAPastYear(date)) { return true; diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 6e2ee68b4effa..f7a32d60be52d 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -459,13 +459,16 @@ function getTagForDisplay(transaction: OnyxEntry, tagIndex?: number return getCleanedTagName(getTag(transaction, tagIndex)); } +function getCreatedDate(transaction: OnyxEntry): string { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + return transaction?.modifiedCreated ? transaction.modifiedCreated : transaction?.created || ''; +} + /** * Return the created field from the transaction, return the modifiedCreated if present. */ function getCreated(transaction: OnyxEntry, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING): string { - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const created = transaction?.modifiedCreated ? transaction.modifiedCreated : transaction?.created || ''; - + const created = getCreatedDate(transaction); return DateUtils.formatWithUTCTimeZone(created, dateFormat); } @@ -812,6 +815,7 @@ export { getOriginalAmount, getMerchant, getMCCGroup, + getCreatedDate, getCreated, getCategory, getBillable, From 93225310ac6b302abe845a76986eac231b6816d3 Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Fri, 14 Jun 2024 00:22:28 +0530 Subject: [PATCH 07/11] Update --- src/components/Search.tsx | 9 ++------ .../Search/TransactionListItemRow.tsx | 4 ++-- .../SelectionList/SearchTableHeader.tsx | 6 ++--- src/components/SelectionList/types.ts | 6 +++-- src/libs/ReportUtils.ts | 4 ++-- src/libs/SearchUtils.ts | 22 ++++++++++++------- src/libs/TransactionUtils.ts | 8 +++---- .../iou/request/step/IOURequestStepDate.tsx | 2 +- tests/unit/TransactionUtilsTest.ts | 6 ++--- 9 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/components/Search.tsx b/src/components/Search.tsx index 69bf82be7f551..5afd5d2b07a45 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -35,11 +35,6 @@ type SearchProps = { const sortableSearchTabs: SearchQuery[] = [CONST.TAB_SEARCH.ALL]; -function isTransactionListItemType(item: TransactionListItemType | ReportListItemType): item is TransactionListItemType { - const transactionListItem = item as TransactionListItemType; - return transactionListItem.transactionID !== undefined; -} - function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { const {isOffline} = useNetwork(); const styles = useThemeStyles(); @@ -122,7 +117,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { const isSortingAllowed = sortableSearchTabs.includes(query); - const doesAtleastOneExpenseBelongToAPastYear = SearchUtils.doesAtleastOneExpenseBelongToAPastYear(searchResults?.data); + const shouldShowYear = SearchUtils.shouldShowYear(searchResults?.data); return ( @@ -133,7 +128,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { sortOrder={sortOrder} isSortingAllowed={isSortingAllowed} sortBy={sortBy} - doesAtleastOneExpenseBelongToAPastYear={doesAtleastOneExpenseBelongToAPastYear} + shouldShowYear={shouldShowYear} /> } // To enhance the smoothness of scrolling and minimize the risk of encountering blank spaces during scrolling, diff --git a/src/components/SelectionList/Search/TransactionListItemRow.tsx b/src/components/SelectionList/Search/TransactionListItemRow.tsx index 1bda7cd1ef652..098fec37b0e64 100644 --- a/src/components/SelectionList/Search/TransactionListItemRow.tsx +++ b/src/components/SelectionList/Search/TransactionListItemRow.tsx @@ -95,7 +95,7 @@ function ReceiptCell({transactionItem, isHovered = false}: ReceiptCellProps) { function DateCell({transactionItem, showTooltip, isLargeScreenWidth}: TransactionCellProps) { const styles = useThemeStyles(); - const created = TransactionUtils.getCreatedDate(transactionItem); + const created = TransactionUtils.getCreated(transactionItem); const date = DateUtils.formatWithUTCTimeZone(created, DateUtils.doesDateBelongToAPastYear(created) ? CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT : CONST.DATE.MONTH_DAY_ABBR_FORMAT); return ( @@ -302,7 +302,7 @@ function TransactionListItemRow({ isHovered={isHovered} /> - + void; - doesAtleastOneExpenseBelongToAPastYear: boolean; + shouldShowYear: boolean; }; -function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPress, doesAtleastOneExpenseBelongToAPastYear}: SearchTableHeaderProps) { +function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPress, shouldShowYear}: SearchTableHeaderProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {isSmallScreenWidth, isMediumScreenWidth} = useWindowDimensions(); @@ -124,7 +124,7 @@ function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPre textStyle={textStyle} sortOrder={sortOrder ?? CONST.SORT_ORDER.ASC} isActive={isActive} - containerStyle={[StyleUtils.getSearchTableColumnStyles(columnName, doesAtleastOneExpenseBelongToAPastYear)]} + containerStyle={[StyleUtils.getSearchTableColumnStyles(columnName, shouldShowYear)]} isSortable={isSortable} onPress={(order: SortOrder) => onSortPress(columnName, order)} /> diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index b6894b889732a..2f1269247c859 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -169,8 +169,10 @@ type TransactionListItemType = ListItem & /** Whether we should show the tax column */ shouldShowTax: boolean; - /** Info about whether there's atleast one transaction that doesn't belong to the present year */ - doesAtleastOneExpenseBelongToAPastYear: boolean; + /** Whether we should show the transaction year. + * This is true if at least one transaction in the data set was create in a previous year + */ + shouldShowYear: boolean; }; type ReportListItemType = ListItem & diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index c27d4e38589f7..6dd67e21add27 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2558,7 +2558,7 @@ function getTransactionDetails(transaction: OnyxEntry, createdDateF } const report = getReport(transaction?.reportID); return { - created: TransactionUtils.getCreated(transaction, createdDateFormat), + created: TransactionUtils.getFormattedCreated(transaction, createdDateFormat), amount: TransactionUtils.getAmount(transaction, !isEmptyObject(report) && isExpenseReport(report)), taxAmount: TransactionUtils.getTaxAmount(transaction, !isEmptyObject(report) && isExpenseReport(report)), taxCode: TransactionUtils.getTaxCode(transaction), @@ -3011,7 +3011,7 @@ function getModifiedExpenseOriginalMessage( originalMessage.newComment = transactionChanges?.comment; } if ('created' in transactionChanges) { - originalMessage.oldCreated = TransactionUtils.getCreated(oldTransaction); + originalMessage.oldCreated = TransactionUtils.getFormattedCreated(oldTransaction); originalMessage.created = transactionChanges?.created; } if ('merchant' in transactionChanges) { diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 05d92f40d3a0c..e880738b29b1e 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -79,13 +79,19 @@ function getShouldShowMerchant(data: OnyxTypes.SearchResults['data']): boolean { const currentYear = new Date().getFullYear(); -function doesAtleastOneExpenseBelongToAPastYear(data: TransactionListItemType[] | ReportListItemType[] | OnyxTypes.SearchResults['data']): boolean { + +function isTransactionListItemType(item: TransactionListItemType | ReportListItemType): item is TransactionListItemType { + const transactionListItem = item as TransactionListItemType; + return transactionListItem.transactionID !== undefined; +} + +function shouldShowYear(data: TransactionListItemType[] | ReportListItemType[] | OnyxTypes.SearchResults['data']): boolean { if (Array.isArray(data)) { return data.some((item: TransactionListItemType | ReportListItemType) => { if ('transactions' in item) { // If the item is a ReportListItemType, iterate over its transactions and check them return item.transactions.some((transaction) => { - const transactionYear = new Date(TransactionUtils.getCreatedDate(transaction)).getFullYear(); + const transactionYear = new Date(TransactionUtils.getCreated(transaction)).getFullYear(); return transactionYear !== currentYear; }); } @@ -98,7 +104,7 @@ function doesAtleastOneExpenseBelongToAPastYear(data: TransactionListItemType[] for (const [key, transactionItem] of Object.entries(data)) { if (key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) { const item = transactionItem as SearchTransaction; - const date = TransactionUtils.getCreatedDate(item); + const date = TransactionUtils.getCreated(item); if (DateUtils.doesDateBelongToAPastYear(date)) { return true; @@ -111,7 +117,7 @@ function doesAtleastOneExpenseBelongToAPastYear(data: TransactionListItemType[] function getTransactionsSections(data: OnyxTypes.SearchResults['data']): TransactionListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); - const doesDataContainAPastYearTransaction = doesAtleastOneExpenseBelongToAPastYear(data); + const doesDataContainAPastYearTransaction = shouldShowYear(data); return Object.entries(data) .filter(([key]) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) @@ -138,7 +144,7 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data']): Transac shouldShowTag: true, shouldShowTax: true, keyForList: transactionItem.transactionID, - doesAtleastOneExpenseBelongToAPastYear: doesDataContainAPastYearTransaction, + shouldShowYear: doesDataContainAPastYearTransaction, }; }); } @@ -146,7 +152,7 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data']): Transac function getReportSections(data: OnyxTypes.SearchResults['data']): ReportListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); - const doesDataContainAPastYearTransaction = doesAtleastOneExpenseBelongToAPastYear(data); + const doesDataContainAPastYearTransaction = shouldShowYear(data); const reportIDToTransactions: Record = {}; for (const key in data) { @@ -183,7 +189,7 @@ function getReportSections(data: OnyxTypes.SearchResults['data']): ReportListIte shouldShowTag: true, shouldShowTax: true, keyForList: transactionItem.transactionID, - doesAtleastOneExpenseBelongToAPastYear: doesDataContainAPastYearTransaction, + shouldShowYear: doesDataContainAPastYearTransaction, }; if (reportIDToTransactions[reportKey]?.transactions) { reportIDToTransactions[reportKey].transactions.push(transaction); @@ -268,5 +274,5 @@ function getSearchParams() { return topmostCentralPaneRoute?.params as CentralPaneNavigatorParamList['Search_Central_Pane']; } -export {getListItem, getQueryHash, getSections, getSortedSections, getShouldShowMerchant, getSearchType, getSearchParams, doesAtleastOneExpenseBelongToAPastYear}; +export {getListItem, getQueryHash, getSections, getSortedSections, getShouldShowMerchant, getSearchType, getSearchParams, shouldShowYear}; export type {SearchColumnType, SortOrder}; diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index f7a32d60be52d..a4595ae8a1efb 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -459,7 +459,7 @@ function getTagForDisplay(transaction: OnyxEntry, tagIndex?: number return getCleanedTagName(getTag(transaction, tagIndex)); } -function getCreatedDate(transaction: OnyxEntry): string { +function getCreated(transaction: OnyxEntry): string { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing return transaction?.modifiedCreated ? transaction.modifiedCreated : transaction?.created || ''; } @@ -467,8 +467,8 @@ function getCreatedDate(transaction: OnyxEntry): string { /** * Return the created field from the transaction, return the modifiedCreated if present. */ -function getCreated(transaction: OnyxEntry, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING): string { - const created = getCreatedDate(transaction); +function getFormattedCreated(transaction: OnyxEntry, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING): string { + const created = getCreated(transaction); return DateUtils.formatWithUTCTimeZone(created, dateFormat); } @@ -815,8 +815,8 @@ export { getOriginalAmount, getMerchant, getMCCGroup, - getCreatedDate, getCreated, + getFormattedCreated, getCategory, getBillable, getTag, diff --git a/src/pages/iou/request/step/IOURequestStepDate.tsx b/src/pages/iou/request/step/IOURequestStepDate.tsx index 3a221b9a56db0..43ed7cbbdfd22 100644 --- a/src/pages/iou/request/step/IOURequestStepDate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDate.tsx @@ -70,7 +70,7 @@ function IOURequestStepDate({ const isEditing = action === CONST.IOU.ACTION.EDIT; // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value const isEditingSplitBill = iouType === CONST.IOU.TYPE.SPLIT && isEditing; - const currentCreated = isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? TransactionUtils.getCreated(splitDraftTransaction) : TransactionUtils.getCreated(transaction); + const currentCreated = isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? TransactionUtils.getFormattedCreated(splitDraftTransaction) : TransactionUtils.getFormattedCreated(transaction); const parentReportAction = reportActions?.[(isEditingSplitBill ? reportActionID : report?.parentReportActionID) ?? 0]; const canEditingSplitBill = isEditingSplitBill && session && parentReportAction && session.accountID === parentReportAction.actorAccountID && TransactionUtils.areRequiredFieldsEmpty(transaction); diff --git a/tests/unit/TransactionUtilsTest.ts b/tests/unit/TransactionUtilsTest.ts index e51ffede633b4..f23259eb568ce 100644 --- a/tests/unit/TransactionUtilsTest.ts +++ b/tests/unit/TransactionUtilsTest.ts @@ -23,7 +23,7 @@ describe('TransactionUtils', () => { it('returns the "modifiedCreated" date with the correct format', () => { const expectedResult = '2023-10-25'; - const result = TransactionUtils.getCreated(transaction); + const result = TransactionUtils.getFormattedCreated(transaction); expect(result).toEqual(expectedResult); }); @@ -39,7 +39,7 @@ describe('TransactionUtils', () => { it('returns the "created" date with the correct format', () => { const expectedResult = '2023-10-01'; - const result = TransactionUtils.getCreated(transaction); + const result = TransactionUtils.getFormattedCreated(transaction); expect(result).toEqual(expectedResult); }); @@ -54,7 +54,7 @@ describe('TransactionUtils', () => { it('returns an empty string', () => { const expectedResult = ''; - const result = TransactionUtils.getCreated(transaction); + const result = TransactionUtils.getFormattedCreated(transaction); expect(result).toEqual(expectedResult); }); From b1d44f4b234bddbea8bd0712a2994179fbf07245 Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Fri, 14 Jun 2024 01:56:52 +0530 Subject: [PATCH 08/11] Update to use type check --- src/components/Search.tsx | 5 +++++ src/libs/SearchUtils.ts | 7 +++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/Search.tsx b/src/components/Search.tsx index d3fc2951e8843..2de6aa8cfcef9 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -35,6 +35,11 @@ type SearchProps = { const sortableSearchTabs: SearchQuery[] = [CONST.TAB_SEARCH.ALL]; +function isTransactionListItemType(item: TransactionListItemType | ReportListItemType): item is TransactionListItemType { + const transactionListItem = item as TransactionListItemType; + return transactionListItem.transactionID !== undefined; +} + function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { const {isOffline} = useNetwork(); const styles = useThemeStyles(); diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index e880738b29b1e..09a2620d1fdf4 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -80,15 +80,14 @@ function getShouldShowMerchant(data: OnyxTypes.SearchResults['data']): boolean { const currentYear = new Date().getFullYear(); -function isTransactionListItemType(item: TransactionListItemType | ReportListItemType): item is TransactionListItemType { - const transactionListItem = item as TransactionListItemType; - return transactionListItem.transactionID !== undefined; +function isReportListItemType(item: TransactionListItemType | ReportListItemType): item is ReportListItemType { + return 'transactions' in item; } function shouldShowYear(data: TransactionListItemType[] | ReportListItemType[] | OnyxTypes.SearchResults['data']): boolean { if (Array.isArray(data)) { return data.some((item: TransactionListItemType | ReportListItemType) => { - if ('transactions' in item) { + if (isReportListItemType(item)) { // If the item is a ReportListItemType, iterate over its transactions and check them return item.transactions.some((transaction) => { const transactionYear = new Date(TransactionUtils.getCreated(transaction)).getFullYear(); From f04ac394a1236eed4706ad9887158cfdfb37a3a3 Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Fri, 14 Jun 2024 01:59:20 +0530 Subject: [PATCH 09/11] Lint fix --- src/libs/SearchUtils.ts | 1 - src/pages/iou/request/step/IOURequestStepDate.tsx | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 09a2620d1fdf4..2f90918a78b07 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -79,7 +79,6 @@ function getShouldShowMerchant(data: OnyxTypes.SearchResults['data']): boolean { const currentYear = new Date().getFullYear(); - function isReportListItemType(item: TransactionListItemType | ReportListItemType): item is ReportListItemType { return 'transactions' in item; } diff --git a/src/pages/iou/request/step/IOURequestStepDate.tsx b/src/pages/iou/request/step/IOURequestStepDate.tsx index c7a6ed3c81d81..63ac316970f88 100644 --- a/src/pages/iou/request/step/IOURequestStepDate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDate.tsx @@ -70,7 +70,8 @@ function IOURequestStepDate({ const isEditing = action === CONST.IOU.ACTION.EDIT; // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value const isEditingSplitBill = iouType === CONST.IOU.TYPE.SPLIT && isEditing; - const currentCreated = isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? TransactionUtils.getFormattedCreated(splitDraftTransaction) : TransactionUtils.getFormattedCreated(transaction); + const currentCreated = + isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? TransactionUtils.getFormattedCreated(splitDraftTransaction) : TransactionUtils.getFormattedCreated(transaction); const parentReportAction = reportActions?.[(isEditingSplitBill ? reportActionID : report?.parentReportActionID) ?? -1]; const canEditingSplitBill = isEditingSplitBill && session && parentReportAction && session.accountID === parentReportAction.actorAccountID && TransactionUtils.areRequiredFieldsEmpty(transaction); From d85b41835f94b847657ce716b640da9b3da8c867 Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Fri, 14 Jun 2024 02:06:55 +0530 Subject: [PATCH 10/11] Update TransactionUtils.ts --- src/libs/TransactionUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index f2b83dd0edea6..cfeb866e572f9 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -467,7 +467,7 @@ function getCreated(transaction: OnyxInputOrEntry): string { /** * Return the created field from the transaction, return the modifiedCreated if present. */ -function getFormattedCreated(transaction: OnyxEntry, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING): string { +function getFormattedCreated(transaction: OnyxInputOrEntry, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING): string { const created = getCreated(transaction); return DateUtils.formatWithUTCTimeZone(created, dateFormat); } From 0ed26144cb3bce653196550f38ec20de90b2ae9b Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Sat, 15 Jun 2024 00:48:40 +0530 Subject: [PATCH 11/11] Update src/components/SelectionList/types.ts Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/components/SelectionList/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 2f1269247c859..f70cac6284982 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -170,7 +170,7 @@ type TransactionListItemType = ListItem & shouldShowTax: boolean; /** Whether we should show the transaction year. - * This is true if at least one transaction in the data set was create in a previous year + * This is true if at least one transaction in the dataset was created in past years */ shouldShowYear: boolean; };