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
02790a5
fix: Add the "Add expense" button to two areas of the product.
Krishna2323 Sep 25, 2025
84189d2
wrap total spend info on small screen.
Krishna2323 Sep 25, 2025
2a39dbe
calculate flex wrap layout.
Krishna2323 Sep 27, 2025
f7cf828
fix merge conflicts.
Krishna2323 Sep 27, 2025
ffe055c
fix merge conflicts.
Krishna2323 Sep 27, 2025
355be7b
Merge branch 'Expensify:main' into krishna2323/issue/69198-2
Krishna2323 Sep 27, 2025
b0fd66d
add changes back to TransactionGroupListItem.
Krishna2323 Sep 27, 2025
a37ac0b
updated approach to calculate flex wrap.
Krishna2323 Sep 27, 2025
9d9764e
Merge branch 'main' into krishna2323/issue/69198-2
Krishna2323 Oct 1, 2025
446738e
fix ESLint and prettier.
Krishna2323 Oct 1, 2025
77f0f8b
use window dimensions for column layout.
Krishna2323 Oct 1, 2025
3da0833
minor fixes.
Krishna2323 Oct 2, 2025
900e9c2
fix add button greyed out on new expense.
Krishna2323 Oct 2, 2025
8458902
fix crash on native devices.
Krishna2323 Oct 2, 2025
1c0507b
Merge branch 'Expensify:main' into krishna2323/issue/69198-2
Krishna2323 Oct 6, 2025
43a1783
fix merge conflicts.
Krishna2323 Oct 9, 2025
2ae4aa3
Merge branch 'main' into krishna2323/issue/69198-2
Krishna2323 Oct 9, 2025
1e4c1b2
fix lint errors.
Krishna2323 Oct 9, 2025
97e945f
remove add expense button from reports page.
Krishna2323 Oct 9, 2025
f17e588
Merge branch 'main' into krishna2323/issue/69198-2
Krishna2323 Oct 16, 2025
126385a
fix ESLint.
Krishna2323 Oct 16, 2025
6d2f2de
add comment.
Krishna2323 Oct 21, 2025
7ee4ade
Merge branch 'Expensify:main' into krishna2323/issue/69198-2
Krishna2323 Oct 21, 2025
a4be164
Merge branch 'Expensify:main' into krishna2323/issue/69198-2
Krishna2323 Oct 22, 2025
cb47a1e
Merge branch 'Expensify:main' into krishna2323/issue/69198-2
Krishna2323 Oct 22, 2025
33e9d97
fix ESlint.
Krishna2323 Oct 22, 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
62 changes: 5 additions & 57 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,7 @@ import useTransactionsAndViolationsForReport from '@hooks/useTransactionsAndViol
import useTransactionViolations from '@hooks/useTransactionViolations';
import {setupMergeTransactionData} from '@libs/actions/MergeTransaction';
import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
import {
createTransactionThreadReport,
deleteAppReport,
downloadReportPDF,
exportReportToCSV,
exportReportToPDF,
exportToIntegration,
markAsManuallyExported,
openUnreportedExpense,
} from '@libs/actions/Report';
import {createTransactionThreadReport, deleteAppReport, downloadReportPDF, exportReportToCSV, exportReportToPDF, exportToIntegration, markAsManuallyExported} from '@libs/actions/Report';
import {getExportTemplates, queueExportSearchWithTemplate, search} from '@libs/actions/Search';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import getPlatform from '@libs/getPlatform';
Expand All @@ -56,6 +47,7 @@ import {getAllExpensesToHoldIfApplicable, getReportPrimaryAction, isMarkAsResolv
import {getSecondaryExportReportActions, getSecondaryReportActions} from '@libs/ReportSecondaryActionUtils';
import {
changeMoneyRequestHoldStatus,
getAddExpenseDropdownOptions,
getIntegrationExportIcon,
getIntegrationNameFromExportMessage as getIntegrationNameFromExportMessageUtils,
getNextApproverAccountID,
Expand Down Expand Up @@ -103,7 +95,6 @@ import {
payMoneyRequest,
reopenReport,
retractReport,
startDistanceRequest,
startMoneyRequest,
submitReport,
unapproveExpenseReport,
Expand Down Expand Up @@ -638,52 +629,9 @@ function MoneyReportHeader({
onlyShowPayElsewhere,
});

const addExpenseDropdownOptions: Array<DropdownOption<ValueOf<typeof CONST.REPORT.ADD_EXPENSE_OPTIONS>>> = useMemo(
() => [
{
value: CONST.REPORT.ADD_EXPENSE_OPTIONS.CREATE_NEW_EXPENSE,
text: translate('iou.createExpense'),
icon: Expensicons.Plus,
onSelected: () => {
if (!moneyRequestReport?.reportID) {
return;
}
if (policy && shouldRestrictUserBillableActions(policy.id)) {
Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policy.id));
return;
}
startMoneyRequest(CONST.IOU.TYPE.SUBMIT, moneyRequestReport?.reportID);
},
},
{
value: CONST.REPORT.ADD_EXPENSE_OPTIONS.TRACK_DISTANCE_EXPENSE,
text: translate('iou.trackDistance'),
icon: Expensicons.Location,
onSelected: () => {
if (!moneyRequestReport?.reportID) {
return;
}
if (policy && shouldRestrictUserBillableActions(policy.id)) {
Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policy.id));
return;
}
startDistanceRequest(CONST.IOU.TYPE.SUBMIT, moneyRequestReport.reportID, lastDistanceExpenseType);
},
},
{
value: CONST.REPORT.ADD_EXPENSE_OPTIONS.ADD_UNREPORTED_EXPENSE,
text: translate('iou.addUnreportedExpense'),
icon: Expensicons.ReceiptPlus,
onSelected: () => {
if (policy && shouldRestrictUserBillableActions(policy.id)) {
Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policy.id));
return;
}
openUnreportedExpense(moneyRequestReport?.reportID);
},
},
],
[moneyRequestReport?.reportID, policy, lastDistanceExpenseType, translate],
const addExpenseDropdownOptions = useMemo(
() => getAddExpenseDropdownOptions(moneyRequestReport?.reportID, policy, undefined, undefined, lastDistanceExpenseType),
[moneyRequestReport?.reportID, policy, lastDistanceExpenseType],
);

const exportSubmenuOptions: Record<string, DropdownOption<string>> = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -610,8 +610,6 @@ function MoneyRequestReportActionsList({
readNewestAction(report.reportID);
}, [setIsFloatingMessageCounterVisible, hasNewestReportAction, reportScrollManager, report.reportID]);

const reportHasComments = visibleReportActions.length > 0;

const scrollToNewTransaction = useCallback(
(pageY: number) => {
wrapperViewRef.current?.measureInWindow((x, y, w, height) => {
Expand Down Expand Up @@ -751,8 +749,6 @@ function MoneyRequestReportActionsList({
hasPendingDeletionTransaction={hasPendingDeletionTransaction}
reportActions={reportActions}
violations={violations}
hasComments={reportHasComments}
isLoadingInitialReportActions={showReportActionsLoadingState}
scrollToNewTransaction={scrollToNewTransaction}
policy={policy}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {useIsFocused} from '@react-navigation/native';
import React from 'react';
import {View} from 'react-native';
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated';
import type {StyleProp, ViewStyle} from 'react-native';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
Expand All @@ -13,12 +12,6 @@ type MoneyRequestReportTotalSpendProps = {
/** Report for which the total spend is being displayed */
report: OnyxTypes.Report;

/** Whether the report has any comments */
hasComments: boolean;

/** Whether the report is loading report actions */
isLoadingReportActions: boolean;

/** Whether the report has any transactions */
isEmptyTransactions: boolean;

Expand All @@ -27,25 +20,20 @@ type MoneyRequestReportTotalSpendProps = {

/** Whether the report has any pending actions */
hasPendingAction: boolean;

/** Style for the text container of the total spend */
textContainerStyle?: StyleProp<ViewStyle>;
};

function MoneyRequestReportTotalSpend({hasComments, isLoadingReportActions, isEmptyTransactions, totalDisplaySpend, report, hasPendingAction}: MoneyRequestReportTotalSpendProps) {
function MoneyRequestReportTotalSpend({isEmptyTransactions, totalDisplaySpend, report, hasPendingAction, textContainerStyle}: MoneyRequestReportTotalSpendProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const isFocused = useIsFocused();

return (
<View style={[styles.dFlex, styles.flexRow, styles.ph5, styles.justifyContentBetween, styles.mb2]}>
<Animated.Text
style={[styles.textLabelSupporting]}
entering={hasComments ? undefined : FadeIn}
exiting={isFocused ? FadeOut : undefined}
>
{hasComments || isLoadingReportActions ? translate('common.comments') : ''}
</Animated.Text>
<View style={[styles.dFlex, styles.flexRow, styles.justifyContentEnd]}>
{!isEmptyTransactions && (
<View style={[styles.dFlex, styles.flexRow, styles.alignItemsCenter, styles.pr3]}>
<View style={[styles.dFlex, styles.flexRow, styles.alignItemsCenter, styles.pr3, textContainerStyle, shouldUseNarrowLayout && [styles.justifyContentBetween, styles.w100]]}>
<Text style={[styles.mr3, styles.textLabelSupporting]}>{translate('common.total')}</Text>
<Text style={[shouldUseNarrowLayout ? styles.mnw64p : styles.mnw100p, styles.textAlignRight, styles.textBold, hasPendingAction && styles.opacitySemiTransparent]}>
{convertToDisplayString(totalDisplaySpend, report?.currency)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import isEmpty from 'lodash/isEmpty';
import React, {memo, useCallback, useContext, useMemo, useState} from 'react';
import {View} from 'react-native';
import type {TupleToUnion} from 'type-fest';
import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
import Checkbox from '@components/Checkbox';
import * as Expensicons from '@components/Icon/Expensicons';
import MenuItem from '@components/MenuItem';
import Modal from '@components/Modal';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import {usePersonalDetails, useSession} from '@components/OnyxListItemProvider';
import {useSearchContext} from '@components/Search/SearchContext';
import type {SearchColumnType, SortOrder} from '@components/Search/types';
Expand All @@ -15,6 +17,7 @@ import {WideRHPContext} from '@components/WideRHPContextProvider';
import useCopySelectionHelper from '@hooks/useCopySelectionHelper';
import useLocalize from '@hooks/useLocalize';
import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
import useReportIsArchived from '@hooks/useReportIsArchived';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
Expand All @@ -26,7 +29,14 @@ import FS from '@libs/Fullstory';
import {navigationRef} from '@libs/Navigation/Navigation';
import Parser from '@libs/Parser';
import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
import {getMoneyRequestSpendBreakdown, isExpenseReport} from '@libs/ReportUtils';
import {
canAddTransaction,
getAddExpenseDropdownOptions,
getMoneyRequestSpendBreakdown,
getReportOfflinePendingActionAndErrors,
isCurrentUserSubmitter,
isExpenseReport,
} from '@libs/ReportUtils';
import {compareValues, getColumnsToShow, isTransactionAmountTooLong, isTransactionTaxAmountTooLong} from '@libs/SearchUIUtils';
import {getAmount, getCategory, getCreated, getMerchant, getTag, getTransactionPendingAction, isTransactionPendingDelete, shouldShowViolation} from '@libs/TransactionUtils';
import shouldShowTransactionYear from '@libs/TransactionUtils/shouldShowTransactionYear';
Expand Down Expand Up @@ -68,12 +78,6 @@ type MoneyRequestReportTransactionListProps = {
/** Violations indexed by transaction ID */
violations?: Record<string, OnyxTypes.TransactionViolation[]>;

/** Whether the report that these transactions belong to has any chat comments */
hasComments: boolean;

/** Whether the report actions are being loaded, used to show 'Comments' during loading state */
isLoadingInitialReportActions?: boolean;

/** scrollToNewTransaction callback used for scrolling to new transaction when it is created */
scrollToNewTransaction: (offset: number) => void;
};
Expand Down Expand Up @@ -128,8 +132,6 @@ function MoneyRequestReportTransactionList({
newTransactions,
reportActions,
violations,
hasComments,
isLoadingInitialReportActions: isLoadingReportActions,
hasPendingDeletionTransaction = false,
scrollToNewTransaction,
policy,
Expand All @@ -143,13 +145,17 @@ function MoneyRequestReportTransactionList({
const {markReportIDAsExpense} = useContext(WideRHPContext);
const [isModalVisible, setIsModalVisible] = useState(false);
const [selectedTransactionID, setSelectedTransactionID] = useState<string>('');
const {reportPendingAction} = getReportOfflinePendingActionAndErrors(report);

const {totalDisplaySpend, nonReimbursableSpend, reimbursableSpend} = getMoneyRequestSpendBreakdown(report);
const formattedOutOfPocketAmount = convertToDisplayString(reimbursableSpend, report?.currency);
const formattedCompanySpendAmount = convertToDisplayString(nonReimbursableSpend, report?.currency);
const shouldShowBreakdown = !!nonReimbursableSpend && !!reimbursableSpend;
const transactionsWithoutPendingDelete = useMemo(() => transactions.filter((t) => !isTransactionPendingDelete(t)), [transactions]);
const session = useSession();
const isReportArchived = useReportIsArchived(report?.reportID);
const shouldShowAddExpenseButton = canAddTransaction(report, isReportArchived) && isCurrentUserSubmitter(report);
const addExpenseDropdownOptions = useMemo(() => getAddExpenseDropdownOptions(report?.reportID, policy), [report?.reportID, policy]);

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.

Coming from #75479, we should lastDistanceExpenseType to getAddExpenseDropdownOptions


const hasPendingAction = useMemo(() => {
return hasPendingDeletionTransaction || transactions.some(getTransactionPendingAction);
Expand Down Expand Up @@ -317,8 +323,6 @@ function MoneyRequestReportTransactionList({
policy={policy}
/>
<MoneyRequestReportTotalSpend
hasComments={hasComments}
isLoadingReportActions={!!isLoadingReportActions}
isEmptyTransactions={isEmptyTransactions}
totalDisplaySpend={totalDisplaySpend}
report={report}
Expand Down Expand Up @@ -391,40 +395,79 @@ function MoneyRequestReportTransactionList({
);
})}
</View>
{shouldShowBreakdown && (
<View style={[styles.dFlex, styles.alignItemsEnd, listHorizontalPadding, styles.gap2, styles.mb2]}>
{[
{text: 'cardTransactions.outOfPocket', value: formattedOutOfPocketAmount},
{text: 'cardTransactions.companySpend', value: formattedCompanySpendAmount},
].map(({text, value}) => (
<View
key={text}
style={[styles.dFlex, styles.flexRow, styles.alignItemsCenter, styles.pr3]}
>
<Text
style={[styles.textLabelSupporting, styles.mr3]}
numberOfLines={1}
>
{translate(text as TranslationPaths)}
</Text>
<Text
numberOfLines={1}
style={[styles.textLabelSupporting, styles.textNormal, shouldUseNarrowLayout ? styles.mnw64p : styles.mnw100p, styles.textAlignRight]}
>
{value}
</Text>{' '}
<View
style={[
styles.dFlex,
styles.flexRow,
shouldShowAddExpenseButton ? styles.justifyContentBetween : styles.justifyContentEnd,
styles.gap6,
listHorizontalPadding,
styles.mb2,
styles.alignItemsStart,
styles.minHeight7,
shouldUseNarrowLayout && styles.flexColumn,
]}
>
{shouldShowAddExpenseButton && (
<OfflineWithFeedback pendingAction={reportPendingAction}>
<ButtonWithDropdownMenu
onPress={() => {}}
shouldAlwaysShowDropdownMenu
customText={translate('iou.addExpense')}
options={addExpenseDropdownOptions}
isSplitButton={false}
buttonSize={CONST.DROPDOWN_BUTTON_SIZE.SMALL}
success={false}
anchorAlignment={{
horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT,
vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP,
}}
/>
</OfflineWithFeedback>
)}
<View style={[styles.flexShrink1, shouldUseNarrowLayout && styles.w100]}>
{shouldShowBreakdown && (
<View style={[styles.dFlex, styles.alignItemsEnd, styles.gap2, styles.mb2, styles.flex1]}>
{[
{text: 'cardTransactions.outOfPocket', value: formattedOutOfPocketAmount},
{text: 'cardTransactions.companySpend', value: formattedCompanySpendAmount},
].map(({text, value}) => (
<View
key={text}
style={[
styles.dFlex,
styles.flexRow,
styles.alignItemsCenter,
styles.pr3,
styles.mw100,
shouldUseNarrowLayout && [styles.justifyContentBetween, styles.w100],
]}
>
<Text
style={[styles.textLabelSupporting, styles.mr3]}
numberOfLines={1}
>
{translate(text as TranslationPaths)}
</Text>
<Text
numberOfLines={1}
style={[styles.textLabelSupporting, styles.textNormal, shouldUseNarrowLayout ? styles.mnw64p : styles.mnw100p, styles.textAlignRight]}
>
{value}
</Text>
</View>
))}
</View>
))}
)}

<MoneyRequestReportTotalSpend
isEmptyTransactions={isEmptyTransactions}
totalDisplaySpend={totalDisplaySpend}
report={report}
hasPendingAction={hasPendingAction}
/>
</View>
)}
<MoneyRequestReportTotalSpend
hasComments={hasComments}
isLoadingReportActions={!!isLoadingReportActions}
isEmptyTransactions={isEmptyTransactions}
totalDisplaySpend={totalDisplaySpend}
report={report}
hasPendingAction={hasPendingAction}
/>
</View>
<Modal
isVisible={isModalVisible}
type={CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED}
Expand Down
Loading
Loading