whisper-money/resources/js/components/accounts
Víctor Falcón 6e6433c6ad
feat(open-banking): disable already-connected banks in the connect picker (#556)
## Why

Several production users ended up with **two connections to the same
bank** (or duplicate accounts for the same IBAN) with EnableBanking. The
auto-invalidation we assumed exists only happens on the dedicated
*reconnect* flow, which reuses the same `BankingConnection` row.
`AuthorizationController::store()` always creates a brand-new connection
and never checks for an existing one, so re-adding an already-connected
bank from scratch silently duplicates it.

## What

- In the connect picker, already-connected EnableBanking banks are no
longer **hidden** — they are shown **disabled with a tooltip**: *"You
already have a connection with this bank. Reconnect it."* This both
prevents the duplicate and guides the user to the right action.
- Connections in `pending` state are excluded, so a stale/abandoned
attempt no longer hides a bank forever (a latent bug in the old
hide-based filter).
- The same dialog opened from the **create-account flow**
(`settings/accounts`) received no `connections`, so nothing was
deduplicated there. The user's banking connections are now shared as a
lightweight global Inertia prop (`bankingConnections`) and fed into both
entry points, so they behave identically. As a bonus, crypto providers
(Binance, etc.) are now also de-duplicated in that flow.

## Notes / follow-ups

- Existing dirty data (the ~10 affected users) is intentionally left
as-is per product decision.
- The onboarding inline variant (`connect-account-inline.tsx`) still
hides rather than disables; unifying the two near-duplicate connect
components is a deliberate follow-up.
- No backend guard was added to `store()`; this is UI-level prevention.
A server-side guard is the robust follow-up if needed.

## Tests

- `tests/Feature/InertiaSharedDataTest.php` — new shared prop is present
and shaped correctly.
- `resources/js/components/open-banking/connect-account-dialog.test.tsx`
— `alreadyConnectedBankNames` includes active/error/expired, excludes
pending and non-EnableBanking providers.
2026-06-18 15:08:09 +02:00
..
import-balances feat(importer): support YYYYMMDD date format (#470) 2026-06-01 16:44:46 +02:00
account-balance-chart.tsx feat(accounts): show projection on real estate chart (#338) 2026-04-27 08:08:12 +01:00
account-form.tsx feat(real-estate): auto-calculate revaluation % and generate historical balances (#253) 2026-04-15 12:18:33 +00:00
account-list-card.tsx feat(settings): centralize currency options and split profile/account support (#256) 2026-04-02 19:23:10 +02:00
account-name.tsx fix(dashboard): treat loans as debt in net worth (#238) 2026-03-20 09:55:53 +00:00
balances-modal.tsx refactor(js): extract shared getCsrfToken util (#475) 2026-06-03 17:26:09 +02:00
bank-combobox.tsx feat(settings): centralize currency options and split profile/account support (#256) 2026-04-02 19:23:10 +02:00
create-account-dialog.tsx feat(open-banking): disable already-connected banks in the connect picker (#556) 2026-06-18 15:08:09 +02:00
custom-bank-form.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
delete-account-dialog.tsx fix(ux): improve status badge, hide balance update for connected accounts, localize delete confirm (#159) 2026-02-27 22:37:16 +00:00
edit-account-dialog.test.tsx Move account delete into edit modal (#410) 2026-05-20 16:46:13 +01:00
edit-account-dialog.tsx refactor(js): extract shared getCsrfToken util (#475) 2026-06-03 17:26:09 +02:00
edit-loan-detail-dialog.tsx feat(accounts): merge real estate accounts with linked mortgages in UI (#248) 2026-03-26 20:54:12 +01:00
import-balances-drawer.tsx fix(import): honor selected date format for CSV imports (#494) 2026-06-05 15:10:48 +02:00
update-balance-dialog.tsx refactor(js): extract shared getCsrfToken util (#475) 2026-06-03 17:26:09 +02:00