whisper-money/resources/js/components/onboarding
Víctor Falcón ca2e5c09b3
fix(balances): allow saving a zero balance (#664)
## Why

A balance of exactly **0** could not be saved. Zero is a perfectly valid
balance for any account (an emptied wallet, a paid-off loan, a closed
position), so the app was rejecting legitimate input.

## Root cause

The shared `AmountInput` renders a numeric value of `0` as an **empty
string** (so the field shows the `0.00` placeholder instead of a literal
"0.00"). Several balance forms combined that with the native HTML
`required` attribute — which then rejected the *only* value that renders
empty: `0`. `required` on this input never guarded against a missing
value (the state is always numeric; empty == 0), it only ever blocked
zero.

The backend already accepted `0` (`required|integer`, and Laravel's
`required` treats integer `0` as present), so this was purely a frontend
constraint.

## Changes

- Drop `required` from the balance `AmountInput` in the **Update
balance** dialog and the **Balance history** edit modal.
- Remove the explicit `balanceInCents === 0` guard (and `required`) in
the onboarding **Set balance** step.
- Extend the same fix to the CSV-import **reference balance** field
(identical root cause; the compute path already gates on
`referenceBalance !== null`, so an explicit `0` is a valid anchor).
- Remove the now-orphaned `"Please enter a balance"` translation from
`es.json` / `fr.json`.
- Add feature tests asserting a zero balance can be stored and set as
the current balance.

Transaction and budget amount inputs keep `required` — `0` is not a
meaningful value there, so they are intentionally untouched.

## QA

- **Onboarding balance step**: saving with an empty/zero field now
advances instead of showing "Please enter a balance". 
- **Update balance dialog**: set €1,000.00, then overwrote it with €0.00
→ dialog closed and the record persisted. Verified in the DB
(`account_balances.balance = 0`). 
- Backend contract locked by new tests in
`AccountBalanceControllerTest`.

## Demo

<!-- PLACEHOLDER: drag the video here -->

_Video to attach: `~/Downloads/allow-zero-balances-demo.mp4`_
2026-07-10 15:02:38 +02:00
..
ai-suggestion-card.tsx feat(ai): suggest automation rules during onboarding (#523) 2026-06-13 22:51:15 +02:00
step-account-types.tsx refactor(real-estate): remove Pennant gating (#308) 2026-04-20 13:31:49 +01:00
step-ai-suggestions-upgrade.test.tsx feat(onboarding): auto-enable AI for connected banks, ask the rest (#618) 2026-07-01 07:26:52 +00:00
step-ai-suggestions.test.tsx feat(onboarding): auto-enable AI for connected banks, ask the rest (#618) 2026-07-01 07:26:52 +00:00
step-ai-suggestions.tsx feat(onboarding): auto-enable AI for connected banks, ask the rest (#618) 2026-07-01 07:26:52 +00:00
step-button.tsx User Onboarding Flow (#23) 2025-12-12 13:06:08 +01:00
step-categorize-transactions.tsx feat(onboarding): clarify the "categorize at least 5" goal in the categorizer (#616) 2026-07-01 08:34:51 +02:00
step-category-types.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
step-complete.tsx feat(subscription): allow free plan for open banking users without connected banks (#188) 2026-03-03 22:28:50 +00:00
step-create-account.tsx refactor(js): extract shared getCsrfToken util (#475) 2026-06-03 17:26:09 +02:00
step-customize-categories.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
step-header.tsx User Onboarding Flow (#23) 2025-12-12 13:06:08 +01:00
step-import-balances.tsx fix(balances): allow saving a zero balance (#664) 2026-07-10 15:02:38 +02:00
step-import-transactions.tsx Fix transaction importer account preselect (#396) 2026-05-14 12:38:44 +02:00
step-smart-rules.tsx feat: (Onboarding) add categorization intro screen with benefit cards (#201) 2026-03-05 11:47:12 +01:00
step-syncing.tsx fix(browser-test): reload transactions in syncing step and fix Skip button selector (#203) 2026-03-05 11:29:06 +00:00
step-welcome.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00