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 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}
shouldShowYear={shouldShowYear}
/>
}
// 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 @@ -87,7 +88,9 @@ function ReceiptCell({transactionItem}: TransactionCellProps) {

function DateCell({transactionItem, showTooltip, isLargeScreenWidth}: TransactionCellProps) {
const styles = useThemeStyles();
const date = TransactionUtils.getCreated(transactionItem, CONST.DATE.MONTH_DAY_ABBR_FORMAT);

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 (
<TextWithTooltip
Expand Down Expand Up @@ -283,7 +286,7 @@ function TransactionListItemRow({item, showTooltip, onButtonPress, showItemHeade
showTooltip={false}
/>
</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.DATE)]}>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.DATE, item.shouldShowYear)]}>
<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;
shouldShowYear: boolean;
};

function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPress}: SearchTableHeaderProps) {
function SearchTableHeader({data, sortBy, sortOrder, isSortingAllowed, onSortPress, shouldShowYear}: SearchTableHeaderProps) {
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, shouldShowYear)]}
isSortable={isSortable}
onPress={(order: SortOrder) => onSortPress(columnName, order)}
/>
Expand Down
5 changes: 5 additions & 0 deletions src/components/SelectionList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ type TransactionListItemType = ListItem &

/** Whether we should show the tax column */
shouldShowTax: boolean;

/** Whether we should show the transaction year.
* This is true if at least one transaction in the dataset was created in past years
*/
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 @@ -789,6 +789,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 @@ -831,6 +836,7 @@ const DateUtils = {
getFormattedDateRange,
getFormattedReservationRangeDate,
getFormattedTransportDate,
doesDateBelongToAPastYear,
};

export default DateUtils;
4 changes: 2 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2567,7 +2567,7 @@ function getTransactionDetails(transaction: OnyxInputOrEntry<Transaction>, creat
}
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),
Expand Down Expand Up @@ -3085,7 +3085,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) {
Expand Down
44 changes: 43 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,46 @@ function getShouldShowMerchant(data: OnyxTypes.SearchResults['data']): boolean {
});
}

const currentYear = new Date().getFullYear();

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 (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();
return transactionYear !== currentYear;
});
}

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

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 = TransactionUtils.getCreated(item);

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

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

const doesDataContainAPastYearTransaction = shouldShowYear(data);

return Object.entries(data)
.filter(([key]) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION))
.map(([, transactionItem]) => {
Expand All @@ -104,13 +142,16 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data']): Transac
shouldShowTag: true,
shouldShowTax: true,
keyForList: transactionItem.transactionID,
shouldShowYear: doesDataContainAPastYearTransaction,
};
});
}

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

const doesDataContainAPastYearTransaction = shouldShowYear(data);

const reportIDToTransactions: Record<string, ReportListItemType> = {};
for (const key in data) {
if (key.startsWith(ONYXKEYS.COLLECTION.REPORT)) {
Expand Down Expand Up @@ -146,6 +187,7 @@ function getReportSections(data: OnyxTypes.SearchResults['data']): ReportListIte
shouldShowTag: true,
shouldShowTax: true,
keyForList: transactionItem.transactionID,
shouldShowYear: doesDataContainAPastYearTransaction,
};
if (reportIDToTransactions[reportKey]?.transactions) {
reportIDToTransactions[reportKey].transactions.push(transaction);
Expand Down Expand Up @@ -230,5 +272,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, shouldShowYear};
export type {SearchColumnType, SortOrder};
12 changes: 8 additions & 4 deletions src/libs/TransactionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,13 +459,16 @@ function getTagForDisplay(transaction: OnyxEntry<Transaction>, tagIndex?: number
return getCleanedTagName(getTag(transaction, tagIndex));
}

function getCreated(transaction: OnyxInputOrEntry<Transaction>): 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: OnyxInputOrEntry<Transaction>, 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 || '';

function getFormattedCreated(transaction: OnyxInputOrEntry<Transaction>, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING): string {
const created = getCreated(transaction);
return DateUtils.formatWithUTCTimeZone(created, dateFormat);
}

Expand Down Expand Up @@ -813,6 +816,7 @@ export {
getMerchant,
getMCCGroup,
getCreated,
getFormattedCreated,
getCategory,
getBillable,
getTag,
Expand Down
3 changes: 2 additions & 1 deletion src/pages/iou/request/step/IOURequestStepDate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.getCreated(splitDraftTransaction) : TransactionUtils.getCreated(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);
Expand Down
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
6 changes: 3 additions & 3 deletions tests/unit/TransactionUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand All @@ -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);
});
Expand All @@ -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);
});
Expand Down
Loading