feat: Bank ueber alle Laender suchen

Unter "Deutschland" liessen sich N26 und Revolut nicht finden – und bei
Revolut kann das gar nicht klappen: Die Bank vergibt deutsche IBANs, ist aber
die Revolut Bank UAB in Litauen. Das Sitzland einer Bank steht nicht in der
IBAN, also ist die Laenderauswahl der falsche Einstieg.

Jetzt ein Suchfeld, das ohne Land ueber alle sucht; das Land ist nur noch ein
optionaler Filter. Der Treffer zeigt sein Land mit an, und verbunden wird mit
dem Land der BANK statt dem des Filters – sonst schluege die Autorisierung
fehl, sobald ohne Land gesucht wurde.

Ohne Land UND ohne Begriff wird abgelehnt: Sonst kaemen alle Banken Europas
ins Formular.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Guido
2026-08-26 21:42:08 +02:00
co-authored by Claude Opus 5
parent cba7ec31e3
commit 71e8419634
8 changed files with 134 additions and 38 deletions
+29 -14
View File
@@ -31,7 +31,8 @@ export default function Bankanbindung() {
const [konten, setKonten] = useState([]);
const [verbindungen, setVerbindungen] = useState([]);
const [links, setLinks] = useState([]);
const [land, setLand] = useState("DE");
const [land, setLand] = useState("");
const [suche, setSuche] = useState("");
const [banken, setBanken] = useState(null);
const [busy, setBusy] = useState(false);
@@ -72,10 +73,11 @@ export default function Bankanbindung() {
}
}
async function bankenLaden() {
async function bankenLaden(e) {
e?.preventDefault();
setBusy(true);
try {
setBanken(await api.listBanks(land));
setBanken(await api.listBanks(land, suche));
} catch (e) {
toast(e.message, "error");
setBanken(null);
@@ -87,7 +89,9 @@ export default function Bankanbindung() {
async function verbinden(bank) {
setBusy(true);
try {
const r = await api.connectBank({ aspsp_name: bank.name, country: land });
// Das Land der BANK, nicht das des Filters – bei einer Suche über alle
// Länder ist das Filterfeld leer.
const r = await api.connectBank({ aspsp_name: bank.name, country: bank.country });
// Weiter zur Bank. Von dort kommt der Nutzer auf /bank/rueckkehr zurück.
window.location.href = r.url;
} catch (e) {
@@ -237,15 +241,24 @@ export default function Bankanbindung() {
{/* Schritt 3: neue Bank verbinden */}
{app && (
<div style={{ marginTop: "var(--sp-3)" }}>
<label className="field">
<span>{t("bank.country")}</span>
<select value={land} onChange={(e) => { setLand(e.target.value); setBanken(null); }}>
{LAENDER.map((l) => <option key={l} value={l}>{l}</option>)}
</select>
</label>
<button className="btn" disabled={busy} onClick={bankenLaden}>
<Icon name="search" size={15} /> {t("bank.findBanks")}
</button>
<form onSubmit={bankenLaden}>
<label className="field">
<span>{t("bank.search")}</span>
<input value={suche} placeholder={t("bank.searchPlaceholder")}
onChange={(e) => setSuche(e.target.value)} />
</label>
<p className="muted small">{t("bank.searchHint")}</p>
<label className="field">
<span>{t("bank.country")}</span>
<select value={land} onChange={(e) => setLand(e.target.value)}>
<option value="">{t("bank.allCountries")}</option>
{LAENDER.map((l) => <option key={l} value={l}>{l}</option>)}
</select>
</label>
<button className="btn" disabled={busy || (!suche.trim() && !land)}>
<Icon name="search" size={15} /> {t("bank.findBanks")}
</button>
</form>
{banken && (
<div style={{ marginTop: "var(--sp-2)" }}>
@@ -257,7 +270,9 @@ export default function Bankanbindung() {
<div className="account-list">
{banken.map((b) => (
<div className="account-row" key={`${b.name}-${b.country}`}>
<span className="grow ellipsis">{b.name}</span>
<span className="grow ellipsis">
{b.name} <span className="muted small">{b.country}</span>
</span>
<button className="btn sm primary" disabled={busy}
onClick={() => verbinden(b)}>
{t("bank.connect")}