Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
5b6e8ee
initial Report Submit To
hungvu193 Apr 15, 2026
0a6657b
Merge remote-tracking branch 'origin/main' into feat-87264
hungvu193 Apr 17, 2026
0cddb7c
merge main
hungvu193 Apr 23, 2026
7304ccd
only show report to with submit policy
hungvu193 Apr 23, 2026
e2d1cb2
prettier
hungvu193 Apr 23, 2026
0b7c8e3
update other submit function
hungvu193 Apr 23, 2026
e4c3b2a
merge main
hungvu193 May 6, 2026
3ee4df0
fix ts
hungvu193 May 6, 2026
74734d9
use new radio item
hungvu193 May 6, 2026
2db1cb0
merge main
hungvu193 May 18, 2026
7310f78
revert unnessary change
hungvu193 May 18, 2026
ce05ce7
fix test adn ts
hungvu193 May 18, 2026
eeb74b7
clean the varibale name
hungvu193 May 19, 2026
441000e
update submodule
hungvu193 May 19, 2026
420ee96
remove unsage of custom header and fix warning
hungvu193 May 19, 2026
c9730f0
merge main
hungvu193 May 19, 2026
6f63597
fix eslint
hungvu193 May 19, 2026
9dc2275
change the approach to use the Popover instead
hungvu193 May 19, 2026
8cba767
merge main
hungvu193 May 25, 2026
2e337b4
resolve conflicts
hungvu193 May 25, 2026
918a8df
prettier
hungvu193 May 25, 2026
726ed24
linting
hungvu193 May 25, 2026
50fc061
prettier
hungvu193 May 25, 2026
86a8eb7
add basic styling
hungvu193 May 25, 2026
e836c19
merge main
hungvu193 May 26, 2026
4ae29c9
remove redundant changes
hungvu193 May 26, 2026
980426f
fix linting
hungvu193 May 26, 2026
724f0f7
styling and logic
hungvu193 May 26, 2026
1907895
Remove redundant translations
hungvu193 May 26, 2026
144fa2f
update show bulk submit option
hungvu193 May 26, 2026
9c74b58
Update the manager email to search
hungvu193 May 26, 2026
d7292c7
revert unnecessary changes
hungvu193 May 26, 2026
e6feebc
merge main
hungvu193 May 26, 2026
3e63cef
update translations
hungvu193 May 26, 2026
d37bace
merge main
hungvu193 May 27, 2026
0055733
fix ts
hungvu193 May 27, 2026
5e77f37
fix eslint
hungvu193 May 27, 2026
37d188b
handle anchor alignment
hungvu193 May 27, 2026
c634d90
remove redundant code
hungvu193 May 27, 2026
6881fde
prettier
hungvu193 May 27, 2026
0e4c425
fix native popover
hungvu193 May 27, 2026
3f628c9
update styling
hungvu193 May 27, 2026
c81cba2
resolve conflicts
hungvu193 May 27, 2026
cb79715
merge main
hungvu193 May 27, 2026
ca9bcab
update translations
hungvu193 May 27, 2026
dd10b08
merge main
hungvu193 Jun 1, 2026
993e036
Add ReportSubmitToPopoverAnchor for TransactionListItem
hungvu193 Jun 1, 2026
e816fd1
Update content
hungvu193 Jun 1, 2026
35476d0
update translactions
hungvu193 Jun 1, 2026
8791398
Remove bulk logic
hungvu193 Jun 1, 2026
ade4292
Address review comments
hungvu193 Jun 1, 2026
d612897
merge main
hungvu193 Jun 2, 2026
76091b0
prettier
hungvu193 Jun 2, 2026
c777940
remove unnecessary export
hungvu193 Jun 3, 2026
161b7a0
exclude the submit option from bulk option
hungvu193 Jun 3, 2026
8cf2406
Knip check
hungvu193 Jun 3, 2026
4398cbb
fix test
hungvu193 Jun 3, 2026
82747e1
update managerEmail logic
hungvu193 Jun 3, 2026
5f1e27a
Update search submit
hungvu193 Jun 3, 2026
1558469
address position of popover, fix duplicate onClick
hungvu193 Jun 3, 2026
92b989d
eslint check
hungvu193 Jun 3, 2026
761bd56
re-implement SubmitPrimaryAction
hungvu193 Jun 3, 2026
79c422e
fix melvin comment
hungvu193 Jun 3, 2026
4fd1459
Update the props
hungvu193 Jun 3, 2026
58c6f07
Fix linting
hungvu193 Jun 3, 2026
f97eb63
Address Melvin comment
hungvu193 Jun 3, 2026
2438630
only clear option when submit sucessfully
hungvu193 Jun 3, 2026
84b574f
Fix test
hungvu193 Jun 4, 2026
0255149
merge main
hungvu193 Jun 6, 2026
2d282c3
merge main
hungvu193 Jun 8, 2026
6c73787
merge main
hungvu193 Jun 10, 2026
083dada
sync submodule
hungvu193 Jun 10, 2026
fd0e9be
fix ts
hungvu193 Jun 10, 2026
53c3b80
fix Melvin comments
hungvu193 Jun 10, 2026
4138c3a
Fix nested popup issue on small screen
hungvu193 Jun 10, 2026
7317127
fix prettier
hungvu193 Jun 10, 2026
df7b4b9
Update src/hooks/useSelectionModeReportActions.ts
hungvu193 Jun 10, 2026
a4774dc
address melvin comments
hungvu193 Jun 11, 2026
3070abd
merge main
hungvu193 Jun 11, 2026
70a328e
Resolve conflicts
hungvu193 Jun 14, 2026
b77b7a3
update submodule
hungvu193 Jun 14, 2026
2e01c8f
prettier
hungvu193 Jun 14, 2026
c1c09d9
Fix Eslint
hungvu193 Jun 14, 2026
c2b776b
fix ts
hungvu193 Jun 14, 2026
61ae223
Fix melvin comments
hungvu193 Jun 14, 2026
c368322
remove redundant changes
hungvu193 Jun 14, 2026
53e26da
fix: sync manageremail and managerID
hungvu193 Jun 14, 2026
98a57e0
merge main
hungvu193 Jun 16, 2026
8789008
Fix ESLint: narrow useCallback dependency to selectedSubmitToMember?.…
MelvinBot Jun 17, 2026
b290b99
resolve conflicts
hungvu193 Jun 17, 2026
f7f76f7
prettier
hungvu193 Jun 17, 2026
b24d0a5
remove submodule change
hungvu193 Jun 17, 2026
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
1 change: 1 addition & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ const CONST = {
POPOVER_DATE_RANGE_WIDTH: 672,
POPOVER_DATE_MAX_HEIGHT: 366,
POPOVER_DATE_MIN_HEIGHT: 322,
POPOVER_REPORT_SUBMIT_TO_CONTENT_HEIGHT: 416,
ADVANCED_FILTERS_POPOVER_HEIGHT: 520,
ADVANCED_FILTERS_POPOVER_WIDTH: 582,
ADVANCED_FILTERS_CONTENT_WIDTH: 331,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {useMoneyReportHeaderModals} from '@components/MoneyReportHeaderModalsCon
import NavigationDeferredMount from '@components/NavigationDeferredMount';
import {usePaymentAnimationsContext} from '@components/PaymentAnimationsContext';
import type {PopoverMenuItem} from '@components/PopoverMenu';
import {ReportSubmitToPopoverAnchor} from '@components/ReportSubmitToPopoverAnchor';
import {useSearchQueryContext, useSearchResultsContext} from '@components/Search/SearchContext';
import type {PaymentActionParams} from '@components/SettlementButton/types';
import useActiveAdminPolicies from '@hooks/useActiveAdminPolicies';
Expand Down Expand Up @@ -76,7 +77,7 @@ type MoneyReportHeaderSecondaryActionsProps = {
dropdownMenuRef?: React.RefObject<ButtonWithDropdownMenuRef>;
};

function MoneyReportHeaderSecondaryActionsInner({reportID, primaryAction, isReportInSearch, backTo, dropdownMenuRef}: MoneyReportHeaderSecondaryActionsProps) {
function MoneyReportHeaderSecondaryActionsContent({reportID, primaryAction, isReportInSearch, backTo, dropdownMenuRef}: MoneyReportHeaderSecondaryActionsProps) {
const {isPaidAnimationRunning, isApprovedAnimationRunning, startAnimation, startApprovedAnimation, startSubmittingAnimation} = usePaymentAnimationsContext();
const {openHoldMenu, openPDFDownload, openHoldEducational, openRejectModal} = useMoneyReportHeaderModals();

Expand Down Expand Up @@ -418,6 +419,14 @@ function MoneyReportHeaderSecondaryActionsInner({reportID, primaryAction, isRepo
);
}

function MoneyReportHeaderSecondaryActionsInner(props: MoneyReportHeaderSecondaryActionsProps) {
return (
<ReportSubmitToPopoverAnchor reportID={props.reportID}>
<MoneyReportHeaderSecondaryActionsContent {...props} />
</ReportSubmitToPopoverAnchor>
);
}

function MoneyReportHeaderSecondaryActionsPlaceholder({primaryAction}: {primaryAction: ValueOf<typeof CONST.REPORT.PRIMARY_ACTIONS> | ''}) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import React from 'react';
import AnimatedSubmitButton from '@components/AnimatedSubmitButton';
import {usePaymentAnimationsContext} from '@components/PaymentAnimationsContext';
import {ReportSubmitToPopoverAnchor, useOpenReportSubmitToPopover} from '@components/ReportSubmitToPopoverAnchor';
import {useSearchQueryContext, useSearchResultsContext} from '@components/Search/SearchContext';
import useConfirmModal from '@hooks/useConfirmModal';
import useConfirmPendingRTERAndProceed from '@hooks/useConfirmPendingRTERAndProceed';
Expand All @@ -17,7 +18,8 @@
import useTransactionsAndViolationsForReport from '@hooks/useTransactionsAndViolationsForReport';
import {search} from '@libs/actions/Search';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import {isSubmitPolicy} from '@libs/PolicyUtils';

Check failure on line 21 in src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx

View workflow job for this annotation

GitHub Actions / ESLint check

'@libs/PolicyUtils' imported multiple times

Check failure on line 21 in src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx

View workflow job for this annotation

GitHub Actions / ESLint check

'@libs/PolicyUtils' imported multiple times
import {hasDynamicExternalWorkflow} from '@libs/PolicyUtils';

Check failure on line 22 in src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx

View workflow job for this annotation

GitHub Actions / ESLint check

'@libs/PolicyUtils' imported multiple times

Check failure on line 22 in src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx

View workflow job for this annotation

GitHub Actions / ESLint check

'@libs/PolicyUtils' imported multiple times
import {getFilteredReportActionsForReportView} from '@libs/ReportActionsUtils';
import {hasViolations as hasViolationsReportUtils, shouldBlockSubmitDueToPreventSelfApproval, shouldBlockSubmitDueToStrictPolicyRules, shouldShowMarkAsDone} from '@libs/ReportUtils';
import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils, hasOnlyPendingCardTransactions, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
Expand All @@ -26,17 +28,37 @@
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';

const ANCHOR_ALIGNMENT = {
horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT,
vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP,
};

type SubmitPrimaryActionProps = {
reportID: string | undefined;
};

function SubmitPrimaryAction({reportID}: SubmitPrimaryActionProps) {
const {startSubmittingAnimation} = usePaymentAnimationsContext();

return (
<ReportSubmitToPopoverAnchor
reportID={reportID}
onSubmitSuccess={startSubmittingAnimation}
anchorAlignment={ANCHOR_ALIGNMENT}
>
<SubmitPrimaryActionContent reportID={reportID} />
</ReportSubmitToPopoverAnchor>
);
}

function SubmitPrimaryActionContent({reportID}: SubmitPrimaryActionProps) {
const {isSubmittingAnimationRunning, stopAnimation, startSubmittingAnimation} = usePaymentAnimationsContext();
const {translate} = useLocalize();
const {isOffline} = useNetwork();
const {accountID, email} = useCurrentUserPersonalDetails();
const {isBetaEnabled} = usePermissions();
const {areStrictPolicyRulesEnabled} = useStrictPolicyRules();
const openReportSubmitToPopover = useOpenReportSubmitToPopover();

const [moneyRequestReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(moneyRequestReport?.policyID)}`);
Expand Down Expand Up @@ -95,6 +117,11 @@
}

confirmPendingRTERAndProceed(() => {
if (isSubmitPolicy(policy) && reportID) {
openReportSubmitToPopover();
return;
}

submitReport({
expenseReport: moneyRequestReport,
policy,
Expand Down
27 changes: 15 additions & 12 deletions src/components/MoneyRequestReportView/SelectionToolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import HoldOrRejectEducationalModal from '@components/HoldOrRejectEducationalMod
import {ModalActions} from '@components/Modal/Global/ModalContext';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import ProcessMoneyReportHoldMenu from '@components/ProcessMoneyReportHoldMenu';
import {ReportSubmitToPopoverAnchor} from '@components/ReportSubmitToPopoverAnchor';
import BulkDuplicateHandler from '@components/Search/BulkDuplicateHandler';
import {useSearchSelectionActions, useSearchSelectionContext} from '@components/Search/SearchContext';
import useConfirmModal from '@hooks/useConfirmModal';
Expand Down Expand Up @@ -250,18 +251,20 @@ function SelectionToolbar({reportID, transactions, reportActions}: SelectionTool
<View
style={[isInLandscapeMode ? [styles.flexRowReverse, styles.justifyContentBetween, styles.alignItemsCenter, styles.gap6, styles.pb3, styles.ph5] : styles.flexColumn]}
>
<SelectionDropdown
hasPayInSelectionMode={hasPayInSelectionMode}
chatReport={chatReport}
report={report}
onSelectionModePaymentSelect={onSelectionModePaymentSelect}
selectionModeKYCSuccess={selectionModeKYCSuccess}
primaryAction={primaryAction}
selectedTransactionsOptions={selectedTransactionsOptions}
selectedTransactionIDs={selectedTransactionIDs}
kycWallRef={kycWallRef}
shouldPopoverUseScrollView={popoverUseScrollView}
/>
<ReportSubmitToPopoverAnchor reportID={reportID}>
<SelectionDropdown
hasPayInSelectionMode={hasPayInSelectionMode}
chatReport={chatReport}
report={report}
onSelectionModePaymentSelect={onSelectionModePaymentSelect}
selectionModeKYCSuccess={selectionModeKYCSuccess}
primaryAction={primaryAction}
selectedTransactionsOptions={selectedTransactionsOptions}
selectedTransactionIDs={selectedTransactionIDs}
kycWallRef={kycWallRef}
shouldPopoverUseScrollView={popoverUseScrollView}
/>
</ReportSubmitToPopoverAnchor>

<SelectAllCheckbox
isSelectAllChecked={isSelectAllChecked}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import {isTrackIntentUserSelector} from '@selectors/Onboarding';
import React from 'react';
import AnimatedSubmitButton from '@components/AnimatedSubmitButton';
import {ReportSubmitToPopoverAnchor, useOpenReportSubmitToPopover} from '@components/ReportSubmitToPopoverAnchor';
import useConfirmModal from '@hooks/useConfirmModal';
import useConfirmPendingRTERAndProceed from '@hooks/useConfirmPendingRTERAndProceed';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
Expand All @@ -10,7 +11,8 @@
import useOnyx from '@hooks/useOnyx';
import usePermissions from '@hooks/usePermissions';
import useReportTransactionsCollection from '@hooks/useReportTransactionsCollection';
import {isSubmitPolicy} from '@libs/PolicyUtils';

Check failure on line 14 in src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx

View workflow job for this annotation

GitHub Actions / ESLint check

'@libs/PolicyUtils' imported multiple times

Check failure on line 14 in src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx

View workflow job for this annotation

GitHub Actions / ESLint check

'@libs/PolicyUtils' imported multiple times
import {hasDynamicExternalWorkflow} from '@libs/PolicyUtils';

Check failure on line 15 in src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx

View workflow job for this annotation

GitHub Actions / ESLint check

'@libs/PolicyUtils' imported multiple times

Check failure on line 15 in src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx

View workflow job for this annotation

GitHub Actions / ESLint check

'@libs/PolicyUtils' imported multiple times
import {hasViolations as hasViolationsReportUtils, shouldShowMarkAsDone} from '@libs/ReportUtils';
import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils, hasOnlyPendingCardTransactions, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
import {submitReport} from '@userActions/IOU/ReportWorkflow';
Expand All @@ -19,6 +21,11 @@
import ONYXKEYS from '@src/ONYXKEYS';
import type {Transaction} from '@src/types/onyx';

const ANCHOR_ALIGNMENT = {
horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.CENTER,
vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM,
};

type SubmitActionButtonProps = {
iouReportID: string | undefined;
isSubmittingAnimationRunning: boolean;
Expand All @@ -27,12 +34,30 @@
};

function SubmitActionButton({iouReportID, isSubmittingAnimationRunning, stopAnimation, startSubmittingAnimation}: SubmitActionButtonProps) {
return (
<ReportSubmitToPopoverAnchor
reportID={iouReportID}
onSubmitSuccess={startSubmittingAnimation}
anchorAlignment={ANCHOR_ALIGNMENT}
>
<SubmitActionButtonContent
iouReportID={iouReportID}
isSubmittingAnimationRunning={isSubmittingAnimationRunning}
stopAnimation={stopAnimation}
startSubmittingAnimation={startSubmittingAnimation}
/>
</ReportSubmitToPopoverAnchor>
);
}

function SubmitActionButtonContent({iouReportID, isSubmittingAnimationRunning, stopAnimation, startSubmittingAnimation}: SubmitActionButtonProps) {
const {translate} = useLocalize();
const {showConfirmModal} = useConfirmModal();
const currentUserDetails = useCurrentUserPersonalDetails();
const currentUserAccountID = currentUserDetails.accountID;
const currentUserEmail = currentUserDetails.email ?? '';
const {isBetaEnabled} = usePermissions();
const openReportSubmitToPopover = useOpenReportSubmitToPopover();

const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`);
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${iouReport?.policyID}`);
Expand All @@ -45,7 +70,6 @@
const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
const [delegateEmail] = useOnyx(ONYXKEYS.ACCOUNT, {selector: delegateEmailSelector});
const {isOffline} = useNetwork();
const isDEWSubmission = hasDynamicExternalWorkflow(policy);
const reportTransactionsCollection = useReportTransactionsCollection(iouReportID);
const transactions = Object.values(reportTransactionsCollection ?? {}).filter(
(t): t is Transaction => !!t && (isOffline || t.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE),
Expand All @@ -54,49 +78,60 @@
const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
const hasViolations = hasViolationsReportUtils(iouReport?.reportID, transactionViolations, currentUserAccountID, currentUserEmail);
const hasAnyPendingRTERViolation = hasAnyPendingRTERViolationTransactionUtils(transactions, transactionViolations, currentUserEmail, currentUserAccountID, iouReport, policy);
const isDEWSubmission = hasDynamicExternalWorkflow(policy);

const handleMarkPendingRTERTransactionsAsCash = () => {
markPendingRTERTransactionsAsCash(transactions, transactionViolations, Object.values(reportActions ?? {}));
};

const confirmPendingRTERAndProceed = useConfirmPendingRTERAndProceed(hasAnyPendingRTERViolation, handleMarkPendingRTERTransactionsAsCash);

const handleSubmit = () => {
if (hasOnlyPendingCardTransactions(transactions)) {
showPendingCardTransactionsBlockModal(showConfirmModal, translate);
return;
}

confirmPendingRTERAndProceed(() => {
if (isSubmitPolicy(policy) && iouReportID) {
openReportSubmitToPopover();
return;
}

submitReport({
expenseReport: iouReport,
policy,
currentUserAccountIDParam: currentUserAccountID,
currentUserEmailParam: currentUserEmail,
hasViolations,
isASAPSubmitBetaEnabled,
expenseReportCurrentNextStepDeprecated: iouReportNextStep,
userBillingGracePeriodEnds,
amountOwed,
onSubmitted: startSubmittingAnimation,
ownerBillingGracePeriodEnd,
delegateEmail,
});
});
};

const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
isTrackIntentUser,
report: iouReport,
policy,
});

return (
<AnimatedSubmitButton
success
text={shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('common.submit')}
isMarkAsDone={shouldUseMarkAsDoneCopy}
onPress={() => {
if (hasOnlyPendingCardTransactions(transactions)) {
showPendingCardTransactionsBlockModal(showConfirmModal, translate);
return;
}
confirmPendingRTERAndProceed(() => {
submitReport({
expenseReport: iouReport,
policy,
currentUserAccountIDParam: currentUserAccountID,
currentUserEmailParam: currentUserEmail,
hasViolations,
isASAPSubmitBetaEnabled,
expenseReportCurrentNextStepDeprecated: iouReportNextStep,
userBillingGracePeriodEnds,
amountOwed,
onSubmitted: startSubmittingAnimation,
ownerBillingGracePeriodEnd,
delegateEmail,
});
});
}}
onPress={handleSubmit}
isSubmittingAnimationRunning={isSubmittingAnimationRunning}
onAnimationFinish={stopAnimation}
sentryLabel={CONST.SENTRY_LABEL.REPORT_PREVIEW.SUBMIT_BUTTON}
isDEWSubmission={isDEWSubmission}
reportID={iouReportID}
sentryLabel={CONST.SENTRY_LABEL.REPORT_PREVIEW.SUBMIT_BUTTON}
/>
);
}
Expand Down
Loading
Loading