diff --git a/src/CONST.ts b/src/CONST.ts index 234171d6df25..1308c362b8ce 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -5244,6 +5244,7 @@ const CONST = { REPORT: 'report', EXPENSE: 'expense', INVOICE: 'invoice', + TRIP: 'trip', }, ACTION_TYPES: { VIEW: 'view', @@ -5278,6 +5279,13 @@ const CONST = { OUTSTANDING: 'outstanding', PAID: 'paid', }, + TRIP: { + ALL: 'all', + DRAFTS: 'drafts', + OUTSTANDING: 'outstanding', + APPROVED: 'approved', + PAID: 'paid', + }, }, TAB: { EXPENSE: { diff --git a/src/components/EmptyStateComponent/index.tsx b/src/components/EmptyStateComponent/index.tsx index 178267de8429..16ac51fba2e7 100644 --- a/src/components/EmptyStateComponent/index.tsx +++ b/src/components/EmptyStateComponent/index.tsx @@ -94,9 +94,9 @@ function EmptyStateComponent({ + text={buttonText} + style={[styles.mt5]} + /> )} diff --git a/src/components/Search/SearchPageHeader.tsx b/src/components/Search/SearchPageHeader.tsx index 039526923b3a..7e4b69c39596 100644 --- a/src/components/Search/SearchPageHeader.tsx +++ b/src/components/Search/SearchPageHeader.tsx @@ -100,11 +100,11 @@ type SearchPageHeaderProps = { type SearchHeaderOptionValue = DeepValueOf | undefined; -const headerContent: {[key in SearchStatus]: {icon: IconAsset; titleTx: TranslationPaths}} = { - all: {icon: Illustrations.MoneyReceipts, titleTx: 'common.expenses'}, - shared: {icon: Illustrations.SendMoney, titleTx: 'common.shared'}, - drafts: {icon: Illustrations.Pencil, titleTx: 'common.drafts'}, - finished: {icon: Illustrations.CheckmarkCircle, titleTx: 'common.finished'}, +const headerContent: {[key in SearchStatus]: {icon: IconAsset; titleText: TranslationPaths}} = { + all: {icon: Illustrations.MoneyReceipts, titleText: 'common.expenses'}, + shared: {icon: Illustrations.SendMoney, titleText: 'common.shared'}, + drafts: {icon: Illustrations.Pencil, titleText: 'common.drafts'}, + finished: {icon: Illustrations.CheckmarkCircle, titleText: 'common.finished'}, }; function SearchPageHeader({queryJSON, hash, onSelectDeleteOption, setOfflineModalOpen, setDownloadErrorModalOpen, isCustomQuery, data}: SearchPageHeaderProps) { @@ -132,7 +132,7 @@ function SearchPageHeader({queryJSON, hash, onSelectDeleteOption, setOfflineModa [data, selectedTransactions], ); const {status} = queryJSON; - const headerSubtitle = isCustomQuery ? SearchUtils.getSearchHeaderTitle(queryJSON) : translate(headerContent[status]?.titleTx); + const headerSubtitle = isCustomQuery ? SearchUtils.getSearchHeaderTitle(queryJSON) : translate(headerContent[status]?.titleText); const headerTitle = isCustomQuery ? translate('search.filtersHeader') : ''; const headerIcon = isCustomQuery ? Illustrations.Filters : headerContent[status]?.icon; diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 615c5823b660..e9b434ffa686 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -225,7 +225,7 @@ function Search({queryJSON, policyIDs, isCustomQuery}: SearchProps) { queryJSON={queryJSON} hash={hash} /> - + ); } diff --git a/src/components/SelectionList/SearchTableHeader.tsx b/src/components/SelectionList/SearchTableHeader.tsx index 3f8abb4e1faf..f68b3c6d17ff 100644 --- a/src/components/SelectionList/SearchTableHeader.tsx +++ b/src/components/SelectionList/SearchTableHeader.tsx @@ -92,6 +92,7 @@ function getSearchColumns(type: SearchDataTypes): SearchColumnConfig[] { case CONST.SEARCH.DATA_TYPES.REPORT: case CONST.SEARCH.DATA_TYPES.EXPENSE: case CONST.SEARCH.DATA_TYPES.INVOICE: + case CONST.SEARCH.DATA_TYPES.TRIP: return expenseHeaders; default: return expenseHeaders; diff --git a/src/languages/en.ts b/src/languages/en.ts index bfe0eef70178..248616db50ca 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3646,6 +3646,11 @@ export default { title: 'Nothing to show', subtitle: 'Try creating something using the green + button.', }, + emptyTripResults: { + title: 'No trips to display', + subtitle: 'Get started by booking your first trip below.', + buttonText: 'Book a trip', + }, }, groupedExpenses: 'grouped expenses', bulkActions: { diff --git a/src/languages/es.ts b/src/languages/es.ts index 76d55a096808..54a4da9e34b6 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -3700,6 +3700,11 @@ export default { title: 'No hay nada que ver aquí', subtitle: 'Por favor intenta crear algo usando el botón verde.', }, + emptyTripResults: { + title: 'No tienes viajes', + subtitle: 'Reserva tu primer viaje a continuación.', + buttonText: 'Reserva un viaje', + }, }, groupedExpenses: 'gastos agrupados', bulkActions: { diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 54220e06a0c9..de3b0444dc1b 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -239,6 +239,7 @@ function getListItem(type: SearchDataTypes, status: SearchStatus): ListItemType< case CONST.SEARCH.DATA_TYPES.EXPENSE: case CONST.SEARCH.DATA_TYPES.REPORT: case CONST.SEARCH.DATA_TYPES.INVOICE: + case CONST.SEARCH.DATA_TYPES.TRIP: return status === CONST.SEARCH.STATUS.EXPENSE.ALL ? TransactionListItem : ReportListItem; default: return TransactionListItem; @@ -251,6 +252,7 @@ function getSections(type: SearchDataTypes, status: SearchStatus, data: OnyxType case CONST.SEARCH.DATA_TYPES.EXPENSE: case CONST.SEARCH.DATA_TYPES.REPORT: case CONST.SEARCH.DATA_TYPES.INVOICE: + case CONST.SEARCH.DATA_TYPES.TRIP: return status === CONST.SEARCH.STATUS.EXPENSE.ALL ? getTransactionsSections(data, metadata) : getReportSections(data, metadata); default: return getTransactionsSections(data, metadata); @@ -263,6 +265,7 @@ function getSortedSections(type: SearchDataTypes, status: SearchStatus, data: Li case CONST.SEARCH.DATA_TYPES.EXPENSE: case CONST.SEARCH.DATA_TYPES.REPORT: case CONST.SEARCH.DATA_TYPES.INVOICE: + case CONST.SEARCH.DATA_TYPES.TRIP: return status === CONST.SEARCH.STATUS.EXPENSE.ALL ? getSortedTransactionData(data as TransactionListItemType[], sortBy, sortOrder) : getSortedReportData(data as ReportListItemType[]); diff --git a/src/pages/Search/EmptySearchView.tsx b/src/pages/Search/EmptySearchView.tsx index 474cbfc0aff8..eaa6c13bcad6 100644 --- a/src/pages/Search/EmptySearchView.tsx +++ b/src/pages/Search/EmptySearchView.tsx @@ -1,24 +1,65 @@ -import React from 'react'; +import React, {useMemo} from 'react'; import EmptyStateComponent from '@components/EmptyStateComponent'; import * as Illustrations from '@components/Icon/Illustrations'; import SearchRowSkeleton from '@components/Skeletons/SearchRowSkeleton'; import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; +import useStyleUtils from '@hooks/useStyleUtils'; +import useTheme from '@hooks/useTheme'; +import Navigation from '@libs/Navigation/Navigation'; +import variables from '@styles/variables'; import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; +import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; -function EmptySearchView() { +type EmptySearchViewProps = { + type: SearchDataTypes; +}; + +function EmptySearchView({type}: EmptySearchViewProps) { + const theme = useTheme(); + const StyleUtils = useStyleUtils(); const {translate} = useLocalize(); - const styles = useThemeStyles(); + + const content = useMemo(() => { + switch (type) { + case CONST.SEARCH.DATA_TYPES.TRIP: + return { + headerMedia: Illustrations.EmptyStateTravel, + headerStyles: StyleUtils.getBackgroundColorStyle(theme.travelBG), + headerContentStyles: StyleUtils.getWidthAndHeightStyle(variables.w191, variables.h172), + title: translate('search.searchResults.emptyTripResults.title'), + subtitle: translate('search.searchResults.emptyTripResults.subtitle'), + buttonText: translate('search.searchResults.emptyTripResults.buttonText'), + buttonAction: () => Navigation.navigate(ROUTES.TRAVEL_MY_TRIPS), + }; + case CONST.SEARCH.DATA_TYPES.TRANSACTION: + case CONST.SEARCH.DATA_TYPES.REPORT: + case CONST.SEARCH.DATA_TYPES.EXPENSE: + case CONST.SEARCH.DATA_TYPES.INVOICE: + default: + return { + headerMedia: Illustrations.EmptyState, + headerStyles: StyleUtils.getBackgroundColorStyle(theme.emptyFolderBG), + headerContentStyles: StyleUtils.getWidthAndHeightStyle(variables.w184, variables.h112), + title: translate('search.searchResults.emptyResults.title'), + subtitle: translate('search.searchResults.emptyResults.subtitle'), + buttonText: undefined, + buttonAction: undefined, + }; + } + }, [type, StyleUtils, translate, theme]); return ( ); } diff --git a/src/styles/theme/themes/dark.ts b/src/styles/theme/themes/dark.ts index 7ed23c7c0991..eedcca6199e4 100644 --- a/src/styles/theme/themes/dark.ts +++ b/src/styles/theme/themes/dark.ts @@ -94,6 +94,7 @@ const darkTheme = { videoPlayerBG: `${colors.productDark100}cc`, transparentWhite: `${colors.white}51`, emptyFolderBG: colors.yellow600, + travelBG: colors.blue600, // Adding a color here will animate the status bar to the right color when the screen is opened. // Note that it needs to be a screen name, not a route url. diff --git a/src/styles/theme/themes/light.ts b/src/styles/theme/themes/light.ts index 2ebb558ee20b..f578e6f48641 100644 --- a/src/styles/theme/themes/light.ts +++ b/src/styles/theme/themes/light.ts @@ -94,6 +94,7 @@ const lightTheme = { videoPlayerBG: `${colors.productDark100}cc`, transparentWhite: `${colors.white}51`, emptyFolderBG: colors.yellow600, + travelBG: colors.blue600, // Adding a color here will animate the status bar to the right color when the screen is opened. // Note that it needs to be a screen name, not a route url. diff --git a/src/styles/theme/types.ts b/src/styles/theme/types.ts index ffa42e99777d..bafeae6a3fee 100644 --- a/src/styles/theme/types.ts +++ b/src/styles/theme/types.ts @@ -98,6 +98,7 @@ type ThemeColors = { videoPlayerBG: Color; transparentWhite: Color; emptyFolderBG: Color; + travelBG: Color; PAGE_THEMES: Record; diff --git a/src/styles/variables.ts b/src/styles/variables.ts index ea838feee1a0..a71a5f2a9e63 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -252,6 +252,8 @@ export default { h20: 20, h28: 28, h36: 36, + h112: 112, + h172: 172, w20: 20, w28: 28, w36: 36, @@ -261,4 +263,6 @@ export default { w80: 80, w92: 92, w96: 96, + w184: 184, + w191: 191, } as const;