Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show year as well in date column #43413

Merged
merged 12 commits into from
Jun 14, 2024
3 changes: 3 additions & 0 deletions src/components/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) {

const isSortingAllowed = sortableSearchTabs.includes(query);

const doesAtleastOneExpenseBelongToAPastYear = SearchUtils.doesAtleastOneExpenseBelongToAPastYear(searchResults?.data);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we just need to calculate doesAtleastOneExpenseBelongToAPastYear in this place (within useMemo) and then pass it to sortedData.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const doesAtleastOneExpenseBelongToAPastYear = SearchUtils.doesAtleastOneExpenseBelongToAPastYear(searchResults?.data);
const shouldShowYear = SearchUtils.shouldShowYear(searchResults?.data);


return (
<SelectionList<ReportListItemType | TransactionListItemType>
customListHeader={
Expand All @@ -131,6 +133,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) {
sortOrder={sortOrder}
isSortingAllowed={isSortingAllowed}
sortBy={sortBy}
doesAtleastOneExpenseBelongToAPastYear={doesAtleastOneExpenseBelongToAPastYear}
mountiny marked this conversation as resolved.
Show resolved Hide resolved
/>
}
// To enhance the smoothness of scrolling and minimize the risk of encountering blank spaces during scrolling,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ 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';
Expand Down Expand Up @@ -91,9 +92,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_ABBR_FORMAT);

const created = getCreated(transactionItem);
const date = DateUtils.formatWithUTCTimeZone(created, DateUtils.doesDateBelongToAPastYear(created) ? CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT : CONST.DATE.MONTH_DAY_ABBR_FORMAT);

return (
<TextWithTooltip
Expand Down Expand Up @@ -299,7 +304,7 @@ function TransactionListItemRow({
isHovered={isHovered}
/>
</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.DATE)]}>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.DATE, item.doesAtleastOneExpenseBelongToAPastYear)]}>
mountiny marked this conversation as resolved.
Show resolved Hide resolved
<DateCell
transactionItem={item}
showTooltip={showTooltip}
Expand Down
5 changes: 3 additions & 2 deletions src/components/SelectionList/SearchTableHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,10 @@ type SearchTableHeaderProps = {
sortOrder?: SortOrder;
isSortingAllowed: boolean;
onSortPress: (column: SearchColumnType, order: SortOrder) => void;
doesAtleastOneExpenseBelongToAPastYear: boolean;
mountiny marked this conversation as resolved.
Show resolved Hide resolved
};

function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPress}: SearchTableHeaderProps) {
function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPress, doesAtleastOneExpenseBelongToAPastYear}: SearchTableHeaderProps) {
mountiny marked this conversation as resolved.
Show resolved Hide resolved
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {isSmallScreenWidth, isMediumScreenWidth} = useWindowDimensions();
Expand Down Expand Up @@ -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)]}
mountiny marked this conversation as resolved.
Show resolved Hide resolved
isSortable={isSortable}
onPress={(order: SortOrder) => onSortPress(columnName, order)}
/>
Expand Down
3 changes: 3 additions & 0 deletions src/components/SelectionList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** Info about whether there's atleast one transaction that doesn't belong to the present year */
/** Info about whether there's at least one transaction that doesn't belong to the present year */

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** Info about whether there's atleast one transaction that doesn't belong to the present year */
/** 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 */

doesAtleastOneExpenseBelongToAPastYear: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
doesAtleastOneExpenseBelongToAPastYear: boolean;
shouldShowYear: boolean;

};

type ReportListItemType = ListItem &
Expand Down
6 changes: 6 additions & 0 deletions src/libs/DateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -840,6 +845,7 @@ const DateUtils = {
getFormattedDateRange,
getFormattedReservationRangeDate,
getFormattedTransportDate,
doesDateBelongToAPastYear,
};

export default DateUtils;
37 changes: 36 additions & 1 deletion src/libs/SearchUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -76,9 +77,39 @@ function getShouldShowMerchant(data: OnyxTypes.SearchResults['data']): boolean {
});
}

function doesAtleastOneExpenseBelongToAPastYear(data: TransactionListItemType[] | ReportListItemType[] | OnyxTypes.SearchResults['data']): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wonder why data has type of TransactionListItemType[] | ReportListItemType[]. I think it's OnyxTypes.SearchResults['data']

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesAtleastOneExpenseBelongToAPastYear is being used in two places, once OnyxTypes.SearchResults['data'] is being passed and at another place TransactionListItemType[] | ReportListItemType[] is being passed.

mountiny marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
function doesAtleastOneExpenseBelongToAPastYear(data: TransactionListItemType[] | ReportListItemType[] | OnyxTypes.SearchResults['data']): boolean {
function shouldShowYear(data: TransactionListItemType[] | ReportListItemType[] | OnyxTypes.SearchResults['data']): boolean {

if (Array.isArray(data)) {
return data.some((item: TransactionListItemType | ReportListItemType) => {
if ('transactions' in item) {
mountiny marked this conversation as resolved.
Show resolved Hide resolved
// 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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is a utility method to get created which already does this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

return transactionYear !== new Date().getFullYear();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can define the currentYear = new Date().getFullYear() out of this block

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

});
}

const createdYear = new Date(item?.modifiedCreated ? item.modifiedCreated : item?.created || '').getFullYear();
mountiny marked this conversation as resolved.
Show resolved Hide resolved
return createdYear !== new Date().getFullYear();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use currentYear ^

});
}
for (const [key, transactionItem] of Object.entries(data)) {
mountiny marked this conversation as resolved.
Show resolved Hide resolved
if (key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) {
const item = transactionItem as SearchTransaction;
const date = item?.modifiedCreated ? item.modifiedCreated : item?.created || '';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function getCreated(transaction: OnyxEntry<Transaction>, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING): string {


if (DateUtils.doesDateBelongToAPastYear(date)) {
return true;
}
}
}
return false;
}

function getTransactionsSections(data: OnyxTypes.SearchResults['data']): TransactionListItemType[] {
const shouldShowMerchant = getShouldShowMerchant(data);

const doesDataContainAPastYearTransaction = doesAtleastOneExpenseBelongToAPastYear(data);
mountiny marked this conversation as resolved.
Show resolved Hide resolved

return Object.entries(data)
.filter(([key]) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION))
.map(([, transactionItem]) => {
Expand All @@ -104,13 +135,16 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data']): Transac
shouldShowTag: true,
shouldShowTax: true,
keyForList: transactionItem.transactionID,
doesAtleastOneExpenseBelongToAPastYear: doesDataContainAPastYearTransaction,
mountiny marked this conversation as resolved.
Show resolved Hide resolved
};
});
}

function getReportSections(data: OnyxTypes.SearchResults['data']): ReportListItemType[] {
const shouldShowMerchant = getShouldShowMerchant(data);

const doesDataContainAPastYearTransaction = doesAtleastOneExpenseBelongToAPastYear(data);
mountiny marked this conversation as resolved.
Show resolved Hide resolved

const reportIDToTransactions: Record<string, ReportListItemType> = {};
for (const key in data) {
if (key.startsWith(ONYXKEYS.COLLECTION.REPORT)) {
Expand Down Expand Up @@ -146,6 +180,7 @@ function getReportSections(data: OnyxTypes.SearchResults['data']): ReportListIte
shouldShowTag: true,
shouldShowTax: true,
keyForList: transactionItem.transactionID,
doesAtleastOneExpenseBelongToAPastYear: doesDataContainAPastYearTransaction,
mountiny marked this conversation as resolved.
Show resolved Hide resolved
};
if (reportIDToTransactions[reportKey]?.transactions) {
reportIDToTransactions[reportKey].transactions.push(transaction);
Expand Down Expand Up @@ -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};
mountiny marked this conversation as resolved.
Show resolved Hide resolved
export type {SearchColumnType, SortOrder};
4 changes: 2 additions & 2 deletions src/styles/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
mountiny marked this conversation as resolved.
Show resolved Hide resolved
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.w44);
columnWidth = getWidthStyle(shouldExtendDateColumn ? variables.w80 : variables.w44);
mountiny marked this conversation as resolved.
Show resolved Hide resolved
break;
case CONST.SEARCH_TABLE_COLUMNS.MERCHANT:
case CONST.SEARCH_TABLE_COLUMNS.FROM:
Expand Down
Loading