[AI] Fix clearing the payee when editing a transaction on mobile (#8926)

The mobile payee selector only allowed picking a payee, so once one was
selected there was no way to leave the transaction without a payee.

Add a "No payee" option to the payee autocomplete modal, mirroring the
category modal's "Uncategorized" button, and show it while editing a
transaction that already has a payee.
This commit is contained in:
Daniel Nieto
2026-10-02 18:03:49 +00:00
committed by GitHub
parent a74830ff8b
commit 34597d703f
7 changed files with 78 additions and 17 deletions
@@ -79,6 +79,36 @@ test.describe('Mobile Transactions', () => {
- textbox [disabled]: just a note`);
});
test('removes the payee from a new transaction', async () => {
const accountsPage = await navigation.goToAccountsPage();
const accountPage = await accountsPage.openNthAccount(2);
const transactionEntryPage = await accountPage.clickCreateTransaction();
await transactionEntryPage.fillAmount('12.34');
// Click anywhere to cancel active edit.
await transactionEntryPage.header.click();
await transactionEntryPage.fillField(
page.getByTestId('payee-field'),
'Kroger',
);
await expect(page.getByTestId('payee-field')).toContainText('Kroger');
// Reopen the payee selector and clear it with the "No payee" option.
await page.getByTestId('payee-field').click();
await page.getByRole('button', { name: 'No payee' }).click();
await expect(page.getByTestId('payee-field')).not.toContainText('Kroger');
await transactionEntryPage.fillField(
page.getByTestId('category-field'),
'Clothing',
);
await transactionEntryPage.createTransaction();
await expect(accountPage.transactions.nth(0)).toHaveText(
'(No payee)Clothing-12.34',
);
});
test('creates a transaction from `/accounts/:id` page', async () => {
const accountsPage = await navigation.goToAccountsPage();
const accountPage = await accountsPage.openNthAccount(2);
@@ -994,6 +994,7 @@ const TransactionEditInner = memo<TransactionEditInnerProps>(
modal: {
name: 'payee-autocomplete',
options: {
showNoneOption: !!transactionToEdit.payee,
onSelect: payeeId => {
void onUpdateInner(transactionToEdit, name, payeeId);
},
@@ -1,8 +1,10 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Trans, useTranslation } from 'react-i18next';
import { Button } from '@actual-app/components/button';
import { useResponsive } from '@actual-app/components/hooks/useResponsive';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { PayeeAutocomplete } from '#components/autocomplete/PayeeAutocomplete';
import {
@@ -23,6 +25,7 @@ type PayeeAutocompleteModalProps = Extract<
export function PayeeAutocompleteModal({
onSelect,
showNoneOption,
onClose,
}: PayeeAutocompleteModalProps) {
const { t } = useTranslation();
@@ -69,20 +72,37 @@ export function PayeeAutocompleteModal({
}
/>
)}
<PayeeAutocomplete
payees={payees}
accounts={accounts}
focused
embedded
closeOnBlur={false}
onClose={() => state.close()}
onManagePayees={onManagePayees}
showManagePayees={!isNarrowWidth}
showMakeTransfer={!isNarrowWidth}
{...defaultAutocompleteProps}
onSelect={onSelect}
value={null}
/>
<View>
<View style={{ flex: 1 }}>
<PayeeAutocomplete
payees={payees}
accounts={accounts}
focused
embedded
closeOnBlur={false}
onClose={() => state.close()}
onManagePayees={onManagePayees}
showManagePayees={!isNarrowWidth}
showMakeTransfer={!isNarrowWidth}
{...defaultAutocompleteProps}
onSelect={onSelect}
value={null}
/>
</View>
{showNoneOption && (
<View style={{ flexShrink: 0, padding: 5 }}>
<Button
variant="menu"
onPress={() => {
onSelect(null);
state.close();
}}
>
<Trans>No payee</Trans>
</Button>
</View>
)}
</View>
</>
)}
</Modal>
@@ -695,7 +695,7 @@ function PayeeCell({
modal: {
name: 'payee-autocomplete',
options: {
onSelect: (payeeId: PayeeEntity['id']) => {
onSelect: (payeeId: PayeeEntity['id'] | null) => {
onUpdate('payee', payeeId);
},
},
@@ -170,6 +170,9 @@ export const GenericInput = ({
name: 'payee-autocomplete',
options: {
onSelect: newValue => {
if (newValue === null) {
return;
}
if (props.multi === true) {
props.onChange([...props.value, newValue]);
return;
@@ -316,7 +316,8 @@ export type Modal =
| {
name: 'payee-autocomplete';
options: {
onSelect: (payeeId: string) => void;
onSelect: (payeeId: string | null) => void;
showNoneOption?: boolean;
onClose?: () => void;
};
}
@@ -0,0 +1,6 @@
---
category: Bugfix
authors: [danielnieto]
---
Fix clearing the payee when editing a transaction on mobile