whisper-money/resources/js/components/transactions
Víctor Falcón 91ffeb917d
fix(amount-input): allow negative amounts via a sign toggle on iOS (#674)
## Problem

On the create/edit transaction form, the amount field uses
`inputMode="decimal"`. On iOS the numeric keypad that this triggers has
**no minus key**, so users cannot type the leading `-` the input relies
on to record a negative amount (e.g. an outgoing transfer).

## Fix

Add an opt-in `allowNegative` prop to `AmountInput` that renders a small
`+`/`−` sign-toggle button at the **start** of the field. It works with
any keyboard, so it does not depend on the OS keypad. It is enabled only
on the create-transaction amount input; budgets, balances and loan
fields keep their current UI.

- The button turns red with a `−` when the amount is negative, and shows
`+` otherwise (`aria-pressed` reflects the state).
- Toggle fires on `click` (works for both pointer and keyboard);
`onPointerDown` `preventDefault` keeps the input focused to avoid a
blur/reformat race.
- A leading `-` set via the toggle **before** typing is preserved on
focus, so the sign is not silently dropped.
- The currency symbol shifts right when the toggle is present so the two
never overlap; layout is unchanged when `allowNegative` is off.

## Refactor

Extracted the repeated `evaluateMathExpression(x) ?? parseInputValue(x)`
string→cents resolution (previously duplicated across blur, Enter, and
the new toggle) into a single `resolveCents()` helper.

## Tests

`resources/js/components/ui/amount-input.test.tsx` — the toggle is
hidden unless `allowNegative`, flips positive↔negative, and preserves
the sign when focusing after toggling an empty field.

## QA

Manually verified in the running app (create-transaction dialog): typing
an amount and toggling the sign both ways updates the value and the
button state correctly, on both prefix (USD `$`) and suffix (EUR `€`)
currency layouts.
2026-07-14 16:13:39 +00:00
..
ai-upsell-sample.test.ts AI auto-categorization: open to pro + consent, nudge free users (#561) 2026-06-19 14:08:40 +00:00
ai-upsell-sample.ts AI auto-categorization: open to pro + consent, nudge free users (#561) 2026-06-19 14:08:40 +00:00
bulk-actions-bar.tsx Fix label creation dropdown refresh (#363) 2026-05-07 10:26:43 +01:00
bulk-category-select.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
bulk-label-select.tsx Fix label creation dropdown refresh (#363) 2026-05-07 10:26:43 +01:00
categorizer-card.tsx feat(categorize): show debtor and creditor names (#454) 2026-05-30 12:27:59 +02:00
categorizer-command.tsx feat: parent/child category tree (#474) 2026-06-03 19:30:12 +02:00
category-cell.tsx feat(ai): learn from category corrections so the AI stops repeating the same mistake (#608) 2026-06-29 19:12:15 +02:00
category-select.tsx feat(shared): Add CategoryCombobox component 2025-11-14 16:05:53 +01:00
edit-transaction-dialog.test.tsx feat(transactions): refine new transaction form layout and balance toggle (#597) 2026-06-26 17:59:44 +00:00
edit-transaction-dialog.tsx fix(amount-input): allow negative amounts via a sign toggle on iOS (#674) 2026-07-14 16:13:39 +00:00
import-step-account.test.tsx Fix transaction importer account preselect (#396) 2026-05-14 12:38:44 +02:00
import-step-account.tsx Fix transaction importer account preselect (#396) 2026-05-14 12:38:44 +02:00
import-step-mapping.tsx fix(balances): allow saving a zero balance (#664) 2026-07-10 15:02:38 +02:00
import-step-preview.tsx feat(transactions): serve import dedup and account ledger from the backend (#631) 2026-07-03 16:49:59 +02:00
import-step-upload.test.tsx Fix transaction importer account preselect (#396) 2026-05-14 12:38:44 +02:00
import-step-upload.tsx Fix transaction importer account preselect (#396) 2026-05-14 12:38:44 +02:00
import-transactions-button.tsx refactor(encryption): strip client-side transaction encryption (#514) 2026-06-20 16:13:26 +00:00
import-transactions-drawer.tsx feat(transactions): serve import dedup and account ledger from the backend (#631) 2026-07-03 16:49:59 +02:00
saved-filters.tsx fix(transactions): keep saved-filter delete button visible on touch and confirm before deleting (#648) 2026-07-06 09:37:38 +00:00
transaction-actions-menu.test.tsx feat(transactions): release transaction analysis to all users (#579) 2026-06-22 16:09:09 +02:00
transaction-actions-menu.tsx feat(transactions): release transaction analysis to all users (#579) 2026-06-22 16:09:09 +02:00
transaction-analysis-drawer.test.tsx feat(analysis): shared bar-list breakdowns in transaction drawer (#517) 2026-06-10 12:36:20 +02:00
transaction-analysis-drawer.tsx feat(analysis): shared bar-list breakdowns in transaction drawer (#517) 2026-06-10 12:36:20 +02:00
transaction-columns.test.tsx fix(transactions): pad Category column when Date column is hidden (#584) 2026-06-22 16:51:50 +00:00
transaction-columns.tsx fix(transactions): let date column size to its content (#610) 2026-06-29 15:51:51 +00:00
transaction-description.test.tsx refactor(encryption): strip client-side transaction encryption (#514) 2026-06-20 16:13:26 +00:00
transaction-description.tsx refactor(encryption): strip client-side transaction encryption (#514) 2026-06-20 16:13:26 +00:00
transaction-filters.test.tsx feat(transactions): reorder filters and switch accounts to a logo dropdown (#598) 2026-06-26 20:09:02 +02:00
transaction-filters.tsx feat(transactions): reorder filters and switch accounts to a logo dropdown (#598) 2026-06-26 20:09:02 +02:00
transaction-list.test.tsx fix(accounts): remove double-skeleton flash on account show (#634) 2026-07-03 15:56:49 +00:00
transaction-list.tsx fix(accounts): remove double-skeleton flash on account show (#634) 2026-07-03 15:56:49 +00:00