Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
17ede8a
fix logic for showing Create report button
SzymczakJ Mar 14, 2025
b701d06
modify EmptyStateComponent to accept new styles
SzymczakJ Mar 14, 2025
ea89c3a
empty state
SzymczakJ Mar 14, 2025
f1fec3c
moving widget to correct place
sumo-slonik Mar 18, 2025
efd6879
moving widget to correct place
sumo-slonik Mar 19, 2025
c451508
work in progress
sumo-slonik Mar 19, 2025
4dac413
fix bug with duplicate report
sumo-slonik Mar 20, 2025
e3fd62d
Merge branch 'main' into @szymczak/Add-empty-State-to-Expense-View
sumo-slonik Mar 20, 2025
013aa45
add header state
sumo-slonik Mar 20, 2025
89828e5
add header state
sumo-slonik Mar 20, 2025
d7c0c5a
fix lint
sumo-slonik Mar 20, 2025
f89ed26
changes after review
sumo-slonik Mar 21, 2025
11a2d5c
Merge branch 'main' into feature/kuba-nowakowski/Add-empty-State-to-E…
sumo-slonik Mar 21, 2025
c4ea777
Merge branch 'main' into feature/kuba-nowakowski/Add-empty-State-to-E…
sumo-slonik Mar 24, 2025
9246657
resolve conflicts
sumo-slonik Mar 24, 2025
79b3c4d
fix position on empty stater component
sumo-slonik Mar 24, 2025
437fdbb
confirm spanish version
sumo-slonik Mar 24, 2025
f9ae2ea
fixes comments from review
sumo-slonik Mar 25, 2025
e2e322f
Merge branch 'main' into feature/kuba-nowakowski/Add-empty-State-to-E…
sumo-slonik Mar 25, 2025
f76c73c
fix report name population logic
SzymczakJ Mar 25, 2025
95009ad
fix report title optimistic value
SzymczakJ Mar 26, 2025
c1dd407
add next steps from onyx
sumo-slonik Mar 26, 2025
d9543f6
add display name
sumo-slonik Mar 26, 2025
8b3cac3
remove unnecessary translation
sumo-slonik Mar 26, 2025
9330f42
add header data to optimistic message
sumo-slonik Mar 27, 2025
71cbf7f
Merge branch 'main' into feature/kuba-nowakowski/Add-empty-State-to-E…
sumo-slonik Mar 28, 2025
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
38 changes: 20 additions & 18 deletions src/components/EmptyStateComponent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {VideoReadyForDisplayEvent} from 'expo-av';
import isEmpty from 'lodash/isEmpty';
import React, {useMemo, useState} from 'react';
import {View} from 'react-native';
import Button from '@components/Button';
Expand All @@ -24,6 +25,8 @@ function EmptyStateComponent({
subtitle,
children,
headerStyles,
cardStyles,
cardContentStyles,
headerContentStyles,
lottieWebViewStyles,
minModalHeight = 400,
Expand Down Expand Up @@ -83,37 +86,36 @@ function EmptyStateComponent({

return (
<View style={[{minHeight: minModalHeight}, styles.flexGrow1, styles.flexShrink0, containerStyles]}>
<View style={[styles.skeletonBackground, styles.overflowHidden]}>
<SkeletonComponent
gradientOpacityEnabled
shouldAnimate={false}
/>
</View>
{!!SkeletonComponent && (
<View style={[styles.skeletonBackground, styles.overflowHidden]}>
<SkeletonComponent
gradientOpacityEnabled
shouldAnimate={false}
/>
</View>
)}
<View style={styles.emptyStateForeground}>
<View style={styles.emptyStateContent}>
<View style={[styles.emptyStateContent, cardStyles]}>
<View style={[styles.emptyStateHeader(headerMediaType === CONST.EMPTY_STATE_MEDIA.ILLUSTRATION), headerStyles]}>{HeaderComponent}</View>
<View style={shouldUseNarrowLayout ? styles.p5 : styles.p8}>
<View style={[shouldUseNarrowLayout ? styles.p5 : styles.p8, cardContentStyles]}>
<Text style={[styles.textAlignCenter, styles.textHeadlineH1, styles.mb2, titleStyles]}>{title}</Text>
<Text style={[styles.textAlignCenter, styles.textSupporting, styles.textNormal]}>{subtitle}</Text>
{children}
<View style={[styles.gap2, styles.mt5, !shouldUseNarrowLayout ? styles.flexRow : undefined]}>
{buttons?.map(({buttonText, buttonAction, success, icon, isDisabled}, index) => (
<View
// eslint-disable-next-line react/no-array-index-key
key={index}
style={styles.flex1}
>
{!isEmpty(buttons) && (
<View style={[styles.gap2, styles.mt5, !shouldUseNarrowLayout ? styles.flexRow : undefined]}>
{buttons?.map(({buttonText, buttonAction, success, icon, isDisabled}) => (
<Button
success={success}
onPress={buttonAction}
text={buttonText}
icon={icon}
large
isDisabled={isDisabled}
style={styles.flex1}
/>
</View>
))}
</View>
))}
</View>
)}
</View>
</View>
</View>
Expand Down
4 changes: 3 additions & 1 deletion src/components/EmptyStateComponent/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ type MediaTypes = ValueOf<typeof CONST.EMPTY_STATE_MEDIA>;
type Button = {buttonText?: string; buttonAction?: () => void; success?: boolean; icon?: IconAsset; isDisabled?: boolean};

type SharedProps<T> = {
SkeletonComponent: ValidSkeletons;
SkeletonComponent?: ValidSkeletons;
title: string;
titleStyles?: StyleProp<TextStyle>;
subtitle?: string;
children?: React.ReactNode;
buttons?: Button[];
containerStyles?: StyleProp<ViewStyle>;
cardStyles?: StyleProp<ViewStyle>;
cardContentStyles?: StyleProp<ViewStyle>;
headerStyles?: StyleProp<ViewStyle>;
headerMediaType: T;
headerContentStyles?: StyleProp<ViewStyle & ImageStyle>;
Expand Down
2 changes: 1 addition & 1 deletion src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
const isSubmitterSameAsNextApprover = isReportOwner(moneyRequestReport) && nextApproverAccountID === moneyRequestReport?.ownerAccountID;
const optimisticNextStep = isSubmitterSameAsNextApprover && policy?.preventSelfApproval ? buildOptimisticNextStepForPreventSelfApprovalsEnabled() : nextStep;

const shouldShowNextStep = transactions?.length !== 0 && isFromPaidPolicy && !!optimisticNextStep?.message?.length && !shouldShowStatusBar;
const shouldShowNextStep = isFromPaidPolicy && !!optimisticNextStep?.message?.length && !shouldShowStatusBar;
const shouldShowAnyButton =
isDuplicate ||
shouldShowSettlementButton ||
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type {ListRenderItemInfo} from '@react-native/virtualized-lists/Lists/VirtualizedList';
import isEmpty from 'lodash/isEmpty';
import React, {useCallback, useMemo} from 'react';
import {InteractionManager, View} from 'react-native';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
import FlatList from '@components/FlatList';
import ReportActionsSkeletonView from '@components/ReportActionsSkeletonView';
import useLoadReportActions from '@hooks/useLoadReportActions';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
Expand All @@ -28,6 +28,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type * as OnyxTypes from '@src/types/onyx';
import type Transaction from '@src/types/onyx/Transaction';
import MoneyRequestReportTransactionList from './MoneyRequestReportTransactionList';
import SearchMoneyRequestReportEmptyState from './SearchMoneyRequestReportEmptyState';

/**
* In this view we are not handling the special single transaction case, we're just handling the report
Expand Down Expand Up @@ -184,7 +185,9 @@ function MoneyRequestReportActionsList({report, reportActions = [], hasNewerActi

return (
<View style={styles.flex1}>
{report ? (
{isEmpty(visibleReportActions) && isEmpty(transactions) ? (
<SearchMoneyRequestReportEmptyState />
) : (
<FlatList
accessibilityLabel="Test"
testID="report-actions-list"
Expand All @@ -200,8 +203,6 @@ function MoneyRequestReportActionsList({report, reportActions = [], hasNewerActi
ListHeaderComponent={<MoneyRequestReportTransactionList transactions={transactions} />}
keyboardShouldPersistTaps="handled"
/>
) : (
<ReportActionsSkeletonView />
)}
</View>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import isEmpty from 'lodash/isEmpty';
import React, {useEffect, useState} from 'react';
import {View} from 'react-native';
import type {TupleToUnion} from 'type-fest';
Expand All @@ -9,6 +10,7 @@ import {compareValues} from '@libs/SearchUIUtils';
import CONST from '@src/CONST';
import type * as OnyxTypes from '@src/types/onyx';
import MoneyRequestReportTableHeader from './MoneyRequestReportTableHeader';
import SearchMoneyRequestReportEmptyState from './SearchMoneyRequestReportEmptyState';

type MoneyRequestReportTransactionListProps = {
/** List of transactions belonging to one report */
Expand Down Expand Up @@ -72,7 +74,7 @@ function MoneyRequestReportTransactionList({transactions}: MoneyRequestReportTra
}));
}, [sortBy, sortOrder, transactions]);

return (
return !isEmpty(transactions) ? (
<>
{!displayNarrowVersion && (
<MoneyRequestReportTableHeader
Expand Down Expand Up @@ -104,6 +106,8 @@ function MoneyRequestReportTransactionList({transactions}: MoneyRequestReportTra
})}
</View>
</>
) : (
<SearchMoneyRequestReportEmptyState />
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import {View} from 'react-native';
import EmptyStateComponent from '@components/EmptyStateComponent';
import LottieAnimations from '@components/LottieAnimations';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';

function SearchMoneyRequestReportEmptyState() {
const {translate} = useLocalize();
const styles = useThemeStyles();

return (
<View style={styles.flex1}>
<EmptyStateComponent
cardStyles={[styles.appBG]}
cardContentStyles={[styles.pt5, styles.pb0]}
headerMediaType={CONST.EMPTY_STATE_MEDIA.ANIMATION}
headerMedia={LottieAnimations.GenericEmptyState}
title={translate('search.moneyRequestReport.emptyStateTitle')}
subtitle={translate('search.moneyRequestReport.emptyStateSubtitle')}
headerStyles={[styles.emptyStateMoneyRequestReport]}
lottieWebViewStyles={styles.emptyStateFolderWebStyles}
headerContentStyles={styles.emptyStateFolderWebStyles}
/>
</View>
);
}

SearchMoneyRequestReportEmptyState.displayName = 'SearchMoneyRequestReportEmptyState';

export default SearchMoneyRequestReportEmptyState;
4 changes: 4 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5129,6 +5129,10 @@ const translations = {
exported: 'Exported',
posted: 'Posted',
},
moneyRequestReport: {
emptyStateTitle: 'This report has no expenses',
emptyStateSubtitle: 'You can add expenses to this report \n using the button above.',
},
noCategory: 'No category',
noTag: 'No tag',
expenseType: 'Expense type',
Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5182,6 +5182,10 @@ const translations = {
exported: 'Exportado',
posted: 'Contabilizado',
},
moneyRequestReport: {
emptyStateTitle: 'Este informe no tiene gastos',
emptyStateSubtitle: 'Puedes añadir gastos a este informe usando el botón de arriba.',
},
noCategory: 'Sin categoría',
noTag: 'Sin etiqueta',
expenseType: 'Tipo de gasto',
Expand Down
1 change: 1 addition & 0 deletions src/libs/API/parameters/CreateAppReportParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ type CreateAppReportParams = {
type: string;
reportID: string;
reportActionID: string;
reportPreviewReportActionID: string;
};
export default CreateAppReportParams;
8 changes: 7 additions & 1 deletion src/libs/NextStepUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ function buildNextStep(report: OnyxEntry<Report>, predictedNextStatus: ValueOf<t
currentUserAccountID,
shouldChangeUserDisplayName: true,
});
const isReportContainingTransactions =
report &&
((report.total !== 0 && report.total !== undefined) ||
(report.unheldTotal !== 0 && report.unheldTotal !== undefined) ||
(report.unheldNonReimbursableTotal !== 0 && report.unheldNonReimbursableTotal !== undefined));

const ownerDisplayName = ownerPersonalDetails?.displayName ?? ownerPersonalDetails?.login ?? getDisplayNameForParticipant({accountID: ownerAccountID});
const policyOwnerDisplayName = policyOwnerPersonalDetails?.displayName ?? policyOwnerPersonalDetails?.login ?? getDisplayNameForParticipant({accountID: policy.ownerAccountID});
const nextApproverDisplayName = getNextApproverDisplayName(report, isUnapprove);
Expand Down Expand Up @@ -229,7 +235,7 @@ function buildNextStep(report: OnyxEntry<Report>, predictedNextStatus: ValueOf<t
};

// Scheduled submit enabled
if (harvesting?.enabled && autoReportingFrequency !== CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL) {
if (harvesting?.enabled && autoReportingFrequency !== CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL && isReportContainingTransactions) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should add test for NextStepsUtils for this - added here #59295

optimisticNextStep.message = [
{
text: 'Waiting for ',
Expand Down
4 changes: 4 additions & 0 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ type OptimisticNewReport = Pick<
| 'parentReportActionID'
| 'participants'
| 'managerID'
| 'pendingAction'
>;

type BuildOptimisticIOUReportActionParams = {
Expand Down Expand Up @@ -9793,6 +9794,9 @@ export {
buildOptimisticChangePolicyReportAction,
getPolicyChangeMessage,
getExpenseReportStateAndStatus,
populateOptimisticReportFormula,
getTitleReportField,
getReportFieldsByPolicyID,
};

export type {
Expand Down
Loading