Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -937,9 +937,12 @@ const CONST = {
MERCHANT: 'merchant',
FROM: 'from',
TO: 'to',
CATEGORY: 'category',
TAG: 'tag',
TOTAL: 'total',
TYPE: 'type',
ACTION: 'action',
TAX_AMOUNT: 'taxAmount',
},
PRIORITY_MODE: {
GSD: 'gsd',
Expand Down
3 changes: 1 addition & 2 deletions src/components/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,10 @@ function Search({query}: SearchProps) {

const ListItem = SearchUtils.getListItem(type);
const data = SearchUtils.getSections(searchResults?.data ?? {}, type);
const shouldShowMerchant = SearchUtils.getShouldShowMerchant(searchResults?.data ?? {});

return (
<SelectionList
customListHeader={<SearchTableHeader shouldShowMerchant={shouldShowMerchant} />}
customListHeader={<SearchTableHeader data={searchResults?.data} />}
ListItem={ListItem}
sections={[{data, isDisabled: false}]}
onSelectRow={(item) => {
Expand Down
79 changes: 54 additions & 25 deletions src/components/SelectionList/SearchTableHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,81 @@
import React from 'react';
import {View} from 'react-native';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as SearchUtils from '@libs/SearchUtils';
import CONST from '@src/CONST';
import type * as OnyxTypes from '@src/types/onyx';
import SearchTableHeaderColumn from './SearchTableHeaderColumn';

type SearchTableHeaderProps = {
/** Whether we should show the merchant or description column */
shouldShowMerchant: boolean;
data: OnyxTypes.SearchResults['data'];
};

function SearchTableHeader({shouldShowMerchant}: SearchTableHeaderProps) {
function SearchTableHeader({data}: SearchTableHeaderProps) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {isSmallScreenWidth, isMediumScreenWidth} = useWindowDimensions();
const {translate} = useLocalize();
const displayNarrowVersion = isMediumScreenWidth || isSmallScreenWidth;

const shouldShowCategoryColumn = SearchUtils.getShouldShowColumn(data, CONST.SEARCH_TABLE_COLUMNS.CATEGORY);
const shouldShowTagColumn = SearchUtils.getShouldShowColumn(data, CONST.SEARCH_TABLE_COLUMNS.TAG);
const shouldShowTaxColumn = SearchUtils.getShouldShowColumn(data, CONST.SEARCH_TABLE_COLUMNS.TAX_AMOUNT);
const shouldShowMerchant = SearchUtils.getShouldShowMerchant(data);

if (displayNarrowVersion) {
return;
}

return (
<View style={[styles.ph5, styles.pb3]}>
<View style={[styles.flex1, styles.flexRow, styles.gap3, styles.ph4]}>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.DATE)]}>
<Text style={[styles.mutedNormalTextLabel]}>{translate('common.date')}</Text>
</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.MERCHANT)]}>
<Text style={[styles.mutedNormalTextLabel]}>{translate(shouldShowMerchant ? 'common.merchant' : 'common.description')}</Text>
</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.FROM)]}>
<Text style={[styles.mutedNormalTextLabel]}>{translate('common.from')}</Text>
</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TO)]}>
<Text style={[styles.mutedNormalTextLabel]}>{translate('common.to')}</Text>
</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TOTAL)]}>
<Text style={[styles.mutedNormalTextLabel]}>{translate('common.total')}</Text>
</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TYPE)]}>
<Text style={[styles.mutedNormalTextLabel]}>{translate('common.type')}</Text>
</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.ACTION)]}>
<Text style={[styles.mutedNormalTextLabel, styles.textAlignCenter]}>{translate('common.action')}</Text>
</View>
<SearchTableHeaderColumn
containerStyle={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.DATE)]}
text={translate('common.date')}
/>
<SearchTableHeaderColumn
containerStyle={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.MERCHANT)]}
text={translate(shouldShowMerchant ? 'common.merchant' : 'common.description')}
/>
<SearchTableHeaderColumn
containerStyle={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.FROM)]}
text={translate('common.from')}
/>
<SearchTableHeaderColumn
containerStyle={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TO)]}
text={translate('common.to')}
/>
<SearchTableHeaderColumn
shouldShow={shouldShowCategoryColumn}
containerStyle={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.CATEGORY)]}
text={translate('common.category')}
/>
<SearchTableHeaderColumn
shouldShow={shouldShowTagColumn}
containerStyle={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TAG)]}
text={translate('common.tag')}
/>
<SearchTableHeaderColumn
shouldShow={shouldShowTaxColumn}
containerStyle={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TAX_AMOUNT)]}
text={translate('common.tax')}
/>
<SearchTableHeaderColumn
containerStyle={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TOTAL)]}
text={translate('common.total')}
/>
<SearchTableHeaderColumn
containerStyle={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TYPE)]}
text={translate('common.type')}
/>
<SearchTableHeaderColumn
containerStyle={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.ACTION)]}
text={translate('common.action')}
textStyle={styles.textAlignCenter}
/>
</View>
</View>
);
Expand Down
31 changes: 31 additions & 0 deletions src/components/SelectionList/SearchTableHeaderColumn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import {View} from 'react-native';
import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
import Text from '@components/Text';
import useThemeStyles from '@hooks/useThemeStyles';

type SearchTableHeaderColumnProps = {
shouldShow?: boolean;
containerStyle?: StyleProp<ViewStyle>;
text: string;
textStyle?: StyleProp<TextStyle>;
};

export default function SearchTableHeaderColumn({containerStyle, text, textStyle, shouldShow = true}: SearchTableHeaderColumnProps) {
const styles = useThemeStyles();

if (!shouldShow) {
return null;
}

return (
<View style={containerStyle}>
<Text
numberOfLines={1}
style={[styles.mutedNormalTextLabel, textStyle]}
>
{text}
</Text>
</View>
);
}
45 changes: 45 additions & 0 deletions src/components/SelectionList/TextWithIconCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import {View} from 'react-native';
import Icon from '@components/Icon';
import Text from '@components/Text';
import Tooltip from '@components/Tooltip';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import type IconAsset from '@src/types/utils/IconAsset';

type TextWithIconCellProps = {
icon: IconAsset;
text?: string;
showTooltip: boolean;
};

export default function TextWithIconCell({icon, text, showTooltip}: TextWithIconCellProps) {
const styles = useThemeStyles();
const theme = useTheme();

if (!text) {
return null;
}

return (
<Tooltip
shouldRender={showTooltip}
text={text}
>
<View style={[styles.flexRow, styles.flexShrink1, styles.gap1]}>
Comment on lines +25 to +29
Copy link
Contributor

Choose a reason for hiding this comment

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

If we use Tooltip here, the tooltip will show even when the text is not truncated, which causes #68212

We fixed it here:
#68849

<Icon
src={icon}
fill={theme.icon}
height={12}
width={12}
/>
<Text
numberOfLines={1}
style={[styles.optionDisplayName, styles.label, styles.pre, styles.justifyContentCenter, styles.textMicro, styles.textSupporting, styles.flexShrink1]}
>
{text}
</Text>
</View>
</Tooltip>
);
}
61 changes: 54 additions & 7 deletions src/components/SelectionList/TransactionListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import * as TransactionUtils from '@libs/TransactionUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import type {Transaction} from '@src/types/onyx';
import type {SearchPersonalDetails, SearchPolicyDetails, SearchTransactionType} from '@src/types/onyx/SearchResults';
import type {SearchAccountDetails, SearchTransactionType} from '@src/types/onyx/SearchResults';
import BaseListItem from './BaseListItem';
import TextWithIconCell from './TextWithIconCell';
import type {ListItem, TransactionListItemProps, TransactionListItemType} from './types';

const getTypeIcon = (type?: SearchTransactionType) => {
Expand Down Expand Up @@ -61,6 +62,7 @@ function TransactionListItem<TItem extends ListItem>({
const isFromExpenseReport = transactionItem.reportType === CONST.REPORT.TYPE.EXPENSE;
const date = TransactionUtils.getCreated(transactionItem as OnyxEntry<Transaction>, CONST.DATE.MONTH_DAY_ABBR_FORMAT);
const amount = TransactionUtils.getAmount(transactionItem as OnyxEntry<Transaction>, isFromExpenseReport);
const taxAmount = TransactionUtils.getTaxAmount(transactionItem as OnyxEntry<Transaction>, isFromExpenseReport);
const currency = TransactionUtils.getCurrency(transactionItem as OnyxEntry<Transaction>);
const description = TransactionUtils.getDescription(transactionItem as OnyxEntry<Transaction>);
const merchant = getMerchant();
Expand All @@ -82,7 +84,7 @@ function TransactionListItem<TItem extends ListItem>({
/>
);

const userCell = (participant: SearchPersonalDetails & SearchPolicyDetails) => {
const userCell = (participant: SearchAccountDetails) => {
const displayName = participant?.name ?? participant?.displayName ?? participant?.login;
const avatarURL = participant?.avatarURL ?? participant?.avatar;
const isWorkspace = participant?.avatarURL !== undefined;
Expand All @@ -108,6 +110,42 @@ function TransactionListItem<TItem extends ListItem>({
);
};

const categoryCell = isLargeScreenWidth ? (
<TextWithTooltip
shouldShowTooltip={showTooltip}
text={transactionItem?.category}
style={[styles.optionDisplayName, styles.label, styles.pre, styles.justifyContentCenter]}
/>
) : (
<TextWithIconCell
icon={Expensicons.Folder}
showTooltip={showTooltip}
text={transactionItem?.category}
/>
);

const tagCell = isLargeScreenWidth ? (
<TextWithTooltip
shouldShowTooltip={showTooltip}
text={transactionItem?.tag}
style={[styles.optionDisplayName, styles.label, styles.pre, styles.justifyContentCenter]}
/>
) : (
<TextWithIconCell
icon={Expensicons.Tag}
showTooltip={showTooltip}
text={transactionItem?.tag}
/>
);

const taxCell = (
<TextWithTooltip
shouldShowTooltip={showTooltip}
text={CurrencyUtils.convertToDisplayString(taxAmount, currency)}
style={[styles.optionDisplayName, styles.label, styles.pre, styles.justifyContentCenter, styles.textAlignRight]}
/>
);

const totalCell = (
<TextWithTooltip
shouldShowTooltip={showTooltip}
Expand Down Expand Up @@ -162,7 +200,7 @@ function TransactionListItem<TItem extends ListItem>({
>
{() => (
<>
<View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween, styles.mb2, styles.gap2]}>
<View style={[styles.flex1, styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween, styles.mb2, styles.gap2]}>
<View style={[styles.flexRow, styles.alignItemsCenter, styles.gap1, styles.flex1]}>
<View style={[styles.mw50]}>{userCell(transactionItem.from)}</View>
<Icon
Expand All @@ -171,13 +209,19 @@ function TransactionListItem<TItem extends ListItem>({
height={variables.iconSizeXXSmall}
fill={theme.icon}
/>
<View style={[styles.mw50]}>{userCell(transactionItem.to)}</View>
<View style={[styles.flex1, styles.mw50]}>{userCell(transactionItem.to)}</View>
</View>
<View style={[StyleUtils.getWidthStyle(variables.w80)]}>{actionCell}</View>
</View>
<View style={[styles.flexRow, styles.justifyContentBetween, styles.gap1]}>
<View style={[styles.flex1]}>{merchantCell}</View>
<View style={[styles.alignItemsEnd, styles.gap1]}>
<View style={[styles.flex2, styles.gap1]}>
{merchantCell}
<View style={[styles.flexRow, styles.flex1, styles.alignItemsEnd, styles.gap3]}>
{categoryCell}
{tagCell}
</View>
</View>
<View style={[styles.alignItemsEnd, styles.flex1, styles.gap1]}>
{totalCell}
<View style={[styles.flexRow, styles.gap1, styles.justifyContentCenter]}>
{typeCell}
Expand Down Expand Up @@ -216,7 +260,10 @@ function TransactionListItem<TItem extends ListItem>({
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.DATE)]}>{dateCell}</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.MERCHANT)]}>{merchantCell}</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.FROM)]}>{userCell(transactionItem.from)}</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.FROM)]}>{userCell(transactionItem.to)}</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TO)]}>{userCell(transactionItem.to)}</View>
{transactionItem.shouldShowCategory && <View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.CATEGORY)]}>{categoryCell}</View>}
{transactionItem.shouldShowTag && <View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TAG)]}>{tagCell}</View>}
{transactionItem.shouldShowTax && <View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TAX_AMOUNT)]}>{taxCell}</View>}
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TOTAL)]}>{totalCell}</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.TYPE)]}>{typeCell}</View>
<View style={[StyleUtils.getSearchTableColumnStyles(CONST.SEARCH_TABLE_COLUMNS.ACTION)]}>{actionCell}</View>
Expand Down
Loading