Skip to content

[Due for payment 2025-05-14] [Better Expense Report View] [$250] Expense - No confirmation modal when deleting expense #60755

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
6 of 8 tasks
mitarachim opened this issue Apr 23, 2025 · 24 comments
Assignees
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor

Comments

@mitarachim
Copy link

mitarachim commented Apr 23, 2025

If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!


Version Number: 9.1.32-0
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught on HybridApp, is this reproducible on New Expensify Standalone?: No, reproducible on hybrid only
If this was caught during regression testing, add the test name, ID and link from TestRail: Exp
Email or phone of affected tester (no customers): [email protected]
Issue reported by: Applause Internal Team
Device used: Mac 15.3 / Chrome
App Component: Money Requests

Action Performed:

Precondition:

  • Log in with Expensifail account.
  1. Go to staging.new.expensify.com
  2. Go to workspace chat.
  3. Submit two expenses to the workspace chat.
  4. Click on the expense preview.
  5. Select an expense via checkbox.
  6. Click on the dropdown.
  7. Click Delete.

Expected Result:

There will be a confirmation modal after clicking Delete.

Actual Result:

There is no confirmation modal after clicking Delete. The expense is deleted directly.

Workaround:

Unknown

Platforms:

  • Android: Standalone
  • Android: HybridApp
  • Android: mWeb Chrome
  • iOS: Standalone
  • iOS: HybridApp
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Bug6811079_1745444460671.20250424_053653.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021915445077292325833
  • Upwork Job ID: 1915445077292325833
  • Last Price Increase: 2025-04-24
  • Automatic offers:
    • allgandalf | Contributor | 107061826
    • ishakakkad | Contributor | 107104752
Issue OwnerCurrent Issue Owner: @
Issue OwnerCurrent Issue Owner: @trjExpensify
@mitarachim mitarachim added Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 labels Apr 23, 2025
Copy link

melvin-bot bot commented Apr 23, 2025

Triggered auto assignment to @lschurr (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

@nkdengineer
Copy link
Contributor

nkdengineer commented Apr 24, 2025

Proposal

Please re-state the problem that we are trying to solve in this issue.

There is no confirmation modal after clicking Delete. The expense is deleted directly.

What is the root cause of that problem?

We call deleteMoneyRequest immediately without displaying confirm modal.

transactionsWithActions.forEach(({transactionID, action}) => action && deleteMoneyRequest(transactionID, action));

What changes do you think we should make in order to solve the problem?

  1. Change this hook to tsx file and create a confirm modal inside this.
function DeleteConfirmModal() {
    return (
        <ConfirmModal
            title={translate('iou.deleteExpense', {count: selectedTransactionsID.length})}
            isVisible={isDeleteModalVisible}
            onConfirm={handleDelete}
            onCancel={() => setIsDeleteModalVisible(false)}
            prompt={translate('iou.deleteConfirmation', {count: selectedTransactionsID.length})}
            confirmText={translate('common.delete')}
            cancelText={translate('common.cancel')}
            danger
            shouldEnableNewFocusManagement
        />
    );
}

transactionsWithActions.forEach(({transactionID, action}) => action && deleteMoneyRequest(transactionID, action));

  1. Update onSelected for the delete option here
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);

const handleDelete = () => {
    const iouActions = reportActions.filter((action) => isMoneyRequestAction(action));
    const selectedTransactions = selectedTransactionsID.map((transactionID) => getTransaction(transactionID)).filter((t) => !!t);

    const transactionsWithActions = selectedTransactions.map((t) => ({
        transactionID: t?.transactionID,
        action: iouActions.find((action) => {
            const IOUTransactionID = (getOriginalMessage(action) as OriginalMessageIOU)?.IOUTransactionID;
            return t?.transactionID === IOUTransactionID;
        }),
    }));

    transactionsWithActions.forEach(({transactionID, action}) => action && deleteMoneyRequest(transactionID, action));
    setSelectedTransactionsID([]);
    setIsDeleteModalVisible(false);
};


if (canRemoveReportTransaction && canAllSelectedTransactionsBeRemoved) {
    options.push({
        text: translate('common.delete'),
        icon: Expensicons.Trashcan,
        value: CONST.REPORT.SECONDARY_ACTIONS.DELETE,
        onSelected: () => {
            setIsDeleteModalVisible(true);
        },
    });
}

  1. Get the confirm modal here and use this
const {selectedTransactionsOptions, DeleteConfirmModal} = useSelectedTransactionsActions({report: moneyRequestReport, reportActions, session, onExportFailed: () => setIsDownloadErrorModalVisible(true)});
<DeleteConfirmModal />

const selectedTransactionsOptions = useSelectedTransactionsActions({report: moneyRequestReport, reportActions, session, onExportFailed: () => setIsDownloadErrorModalVisible(true)});

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

New UI

What alternative solutions did you explore? (Optional)

We can introduce new prop in this hook like onDelete that will show the confirm modal and will create the confirmal in each component that uses this hook

Result

Screen.Recording.2025-04-24.at.10.45.53.mov

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

@lschurr lschurr added the External Added to denote the issue can be worked on by a contributor label Apr 24, 2025
@melvin-bot melvin-bot bot changed the title Expense - No confirmation modal when deleting expense [$250] Expense - No confirmation modal when deleting expense Apr 24, 2025
Copy link

melvin-bot bot commented Apr 24, 2025

Job added to Upwork: https://www.upwork.com/jobs/~021915445077292325833

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Apr 24, 2025
Copy link

melvin-bot bot commented Apr 24, 2025

Triggered auto assignment to Contributor-plus team member for initial proposal review - @eh2077 (External)

@ishakakkad
Copy link
Contributor

Proposal

Please re-state the problem that we are trying to solve in this issue.

There is no confirmation modal after clicking Delete. The expense is deleted directly.

What is the root cause of that problem?

We don't have logic to show the modal before deleting modal.

transactionsWithActions.forEach(({transactionID, action}) => action && deleteMoneyRequest(transactionID, action));

What changes do you think we should make in order to solve the problem?

  1. As it is bad practice to return Component or HTML element from the hook, we should return the delete related logic from the hook. And use that inside the component. For this let's add following logic into hook here
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);

const handleDeleteTransactions = useCallback(() => {
    const iouActions = reportActions.filter((action) => isMoneyRequestAction(action));

    const transactionsWithActions = selectedTransactionsID.map((transactionID) => ({
        transactionID,
        action: iouActions.find((action) => {
            const IOUTransactionID = (getOriginalMessage(action) as OriginalMessageIOU)?.IOUTransactionID;
            return transactionID === IOUTransactionID;
        }),
    }));

    transactionsWithActions.forEach(({transactionID, action}) => action && deleteMoneyRequest(transactionID, action));
    setSelectedTransactionsID([]);
    setIsDeleteModalVisible(false);
}, [reportActions, selectedTransactionsID, setSelectedTransactionsID]);

const showDeleteModal = useCallback(() => {
    setIsDeleteModalVisible(true);
}, []);

const hideDeleteModal = useCallback(() => {
    setIsDeleteModalVisible(false);
}, []);
const options = useMemo(() => {
  if (!selectedTransactionsID.length) {
      return [];
  }
// All existing options logic
  1. Change delete onSelected logic here into following
onSelected: showDeleteModal,
  1. following data should be return from hook here
return {
        options,
        handleDeleteTransactions,
        isDeleteModalVisible,
        showDeleteModal,
        hideDeleteModal,
    };
  1. Replace this with following
const {options: selectedTransactionsOptions, handleDeleteTransactions, isDeleteModalVisible: hookDeleteModalVisible, hideDeleteModal} = useSelectedTransactionsActions({report: moneyRequestReport, reportActions, session, onExportFailed: () => setIsDownloadErrorModalVisible(true)});
  1. Add confirmation modal inside the MoneyReportHeader.tsx here same way we added other modals.
<ConfirmModal
      title={translate('iou.deleteExpense', {count: selectedTransactionsID.length})}
      isVisible={hookDeleteModalVisible}
      onConfirm={handleDeleteTransactions}
      onCancel={hideDeleteModal}
      prompt={translate('iou.deleteConfirmation', {count: selectedTransactionsID.length})}
      confirmText={translate('common.delete')}
      cancelText={translate('common.cancel')}
      danger
      shouldEnableNewFocusManagement
  />

Note: We can create new DeleteConfirmaTransactionModal component and use instead of above code. This is implementation detail we can discuss later on.
OR
Note: We may try to utilize this same modal if feasible during development

Same change we can add for other places where this hook used.

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

UI changes

What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

@nkdengineer
Copy link
Contributor

Note:

  1. We already do this for useDeleteSavedSearch.

  2. If we don't want to return an element in the hook, my alternative solution already mentioned another solution for each component.

We can introduce new prop in this hook like onDelete that will show the confirm modal and will create the confirmal in each component that uses this hook

@ishakakkad
Copy link
Contributor

ishakakkad commented Apr 25, 2025

We can introduce new prop in this hook like onDelete that will show the confirm modal and will create the confirmal in each component that uses this hook

This one line does not define the solution, but anyway it is upto C+ team member to decide.

Unlike other parts of the codebase, the useDeleteSavedSearch hook is currently returning JSX/HTML, whereas all other hooks are used solely for logic or state management.

To maintain consistency and follow React best practices, any UI rendering should be handled in a separate component.

@mountiny mountiny assigned allgandalf and unassigned eh2077 Apr 25, 2025
@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label Apr 25, 2025
@mountiny mountiny changed the title [$250] Expense - No confirmation modal when deleting expense [Better Expense Report View] [$250] Expense - No confirmation modal when deleting expense Apr 25, 2025
Copy link

melvin-bot bot commented Apr 25, 2025

📣 @allgandalf 🎉 An offer has been automatically sent to your Upwork account for the Contributor role 🎉 Thanks for contributing to the Expensify app!

Offer link
Upwork job
Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑‍💻
Keep in mind: Code of Conduct | Contributing 📖

@mountiny mountiny moved this to Second Cohort - CRITICAL in [#whatsnext] #migrate Apr 25, 2025
@trjExpensify trjExpensify added the Help Wanted Apply this label when an issue is open to proposals by contributors label Apr 25, 2025
@trjExpensify
Copy link
Contributor

Over to you @allgandalf for proposal reviews.

@allgandalf
Copy link
Contributor

Lets go with @ishakakkad 's proposal here, it looks more correct to me implementation wise!

🎀👀🎀 C+ reviewed

Copy link

melvin-bot bot commented Apr 28, 2025

Current assignee @mountiny is eligible for the choreEngineerContributorManagement assigner, not assigning anyone new.

@allgandalf
Copy link
Contributor

allgandalf commented Apr 28, 2025

@ishakakkad can you make sure that we fix this one throughout the application ?, using jsx/tsx components inside a hook is surely a wrong approach, we should fix it!

@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label Apr 29, 2025
Copy link

melvin-bot bot commented Apr 29, 2025

📣 @ishakakkad 🎉 An offer has been automatically sent to your Upwork account for the Contributor role 🎉 Thanks for contributing to the Expensify app!

Offer link
Upwork job
Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑‍💻
Keep in mind: Code of Conduct | Contributing 📖

@mountiny
Copy link
Contributor

@ishakakkad thanks! Can you please raise the PR for this one?

@trjExpensify
Copy link
Contributor

@ishakakkad can we get an ETA on the PR, please? Thanks!

@trjExpensify trjExpensify assigned trjExpensify and unassigned lschurr Apr 30, 2025
@ishakakkad
Copy link
Contributor

@trjExpensify will create PR max by tomorrow.

@allgandalf
Copy link
Contributor

@ishakakkad do you think you can raise the PR today?

@ishakakkad
Copy link
Contributor

Hi @allgandalf yes already on this, will create PR by today.

@melvin-bot melvin-bot bot added Reviewing Has a PR in review Weekly KSv2 and removed Daily KSv2 labels May 1, 2025
@ishakakkad
Copy link
Contributor

@allgandalf PR for Delete confirmation modal is ready.

@allgandalf
Copy link
Contributor

allgandalf commented May 6, 2025

PR was merged !

@melvin-bot melvin-bot bot added Weekly KSv2 Awaiting Payment Auto-added when associated PR is deployed to production and removed Weekly KSv2 labels May 7, 2025
@melvin-bot melvin-bot bot changed the title [Better Expense Report View] [$250] Expense - No confirmation modal when deleting expense [Due for payment 2025-05-14] [Better Expense Report View] [$250] Expense - No confirmation modal when deleting expense May 7, 2025
@melvin-bot melvin-bot bot removed the Reviewing Has a PR in review label May 7, 2025
Copy link

melvin-bot bot commented May 7, 2025

Reviewing label has been removed, please complete the "BugZero Checklist".

Copy link

melvin-bot bot commented May 7, 2025

The solution for this issue has been 🚀 deployed to production 🚀 in version 9.1.41-1 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2025-05-14. 🎊

For reference, here are some details about the assignees on this issue:

Copy link

melvin-bot bot commented May 7, 2025

@allgandalf @trjExpensify @allgandalf The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]

@trjExpensify trjExpensify moved this from Second Cohort - CRITICAL to Second Cohort - HIGH in [#whatsnext] #migrate May 9, 2025
@melvin-bot melvin-bot bot added Daily KSv2 and removed Weekly KSv2 labels May 14, 2025
@trjExpensify
Copy link
Contributor

Payment summary as follows:

Paid, closing!

@github-project-automation github-project-automation bot moved this from Second Cohort - HIGH to Done in [#whatsnext] #migrate May 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor
Projects
Development

No branches or pull requests

9 participants