/* This file is part of GNU Taler (C) 2022 Taler Systems S.A. GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Taler; see the file COPYING. If not, see */ import { Amounts, buildPayto, Logger, parsePaytoUri, stringifyPaytoUri, } from "@gnu-taler/taler-util"; import { InternationalizationAPI, RequestError, useTranslationContext, } from "@gnu-taler/web-util/lib/index.browser"; import { h, VNode } from "preact"; import { StateUpdater, useEffect, useRef, useState } from "preact/hooks"; import { useBackendContext } from "../context/backend.js"; import { PageStateType, usePageContext } from "../context/pageState.js"; import { useAccessAPI } from "../hooks/access.js"; import { BackendState } from "../hooks/backend.js"; import { undefinedIfEmpty } from "../utils.js"; import { ShowInputErrorLabel } from "./ShowInputErrorLabel.js"; const logger = new Logger("PaytoWireTransferForm"); export function PaytoWireTransferForm({ focus, onError, onSuccess, currency, }: { focus?: boolean; onError: (e: PageStateType["error"]) => void; onSuccess: () => void; currency: string; }): VNode { const backend = useBackendContext(); // const { pageState, pageStateSetter } = usePageContext(); // NOTE: used for go-back button? const [isRawPayto, setIsRawPayto] = useState(false); // const [submitData, submitDataSetter] = useWireTransferRequestType(); const [iban, setIban] = useState(undefined); const [subject, setSubject] = useState(undefined); const [amount, setAmount] = useState(undefined); const [rawPaytoInput, rawPaytoInputSetter] = useState( undefined, ); const { i18n } = useTranslationContext(); const ibanRegex = "^[A-Z][A-Z][0-9]+$"; const ref = useRef(null); useEffect(() => { if (focus) ref.current?.focus(); }, [focus, isRawPayto]); let parsedAmount = undefined; const IBAN_REGEX = /^[A-Z][A-Z0-9]*$/; const errorsWire = undefinedIfEmpty({ iban: !iban ? i18n.str`Missing IBAN` : !IBAN_REGEX.test(iban) ? i18n.str`IBAN should have just uppercased letters and numbers` : undefined, subject: !subject ? i18n.str`Missing subject` : undefined, amount: !amount ? i18n.str`Missing amount` : !(parsedAmount = Amounts.parse(`${currency}:${amount}`)) ? i18n.str`Amount is not valid` : Amounts.isZero(parsedAmount) ? i18n.str`Should be greater than 0` : undefined, }); const { createTransaction } = useAccessAPI(); if (!isRawPayto) return (
{ e.preventDefault(); }} autoCapitalize="none" autoCorrect="off" >

  { setIban(e.currentTarget.value); }} />

  { setSubject(e.currentTarget.value); }} />

 

  { setAmount(e.currentTarget.value); }} />

{ e.preventDefault(); if (!(iban && subject && amount)) { return; } const ibanPayto = buildPayto("iban", iban, undefined); ibanPayto.params.message = encodeURIComponent(subject); const paytoUri = stringifyPaytoUri(ibanPayto); await createTransaction({ paytoUri, amount: `${currency}:${amount}`, }); // return await createTransactionCall( // transactionData, // backend.state, // pageStateSetter, // () => { // setAmount(undefined); // setIban(undefined); // setSubject(undefined); // }, // i18n, // ); }} /> { e.preventDefault(); setAmount(undefined); setIban(undefined); setSubject(undefined); }} />

{ setIsRawPayto(true); }} > {i18n.str`Want to try the raw payto://-format?`}

); const parsed = !rawPaytoInput ? undefined : parsePaytoUri(rawPaytoInput); const errorsPayto = undefinedIfEmpty({ rawPaytoInput: !rawPaytoInput ? i18n.str`required` : !parsed ? i18n.str`does not follow the pattern` : !parsed.params.amount ? i18n.str`use the "amount" parameter to specify the amount to be transferred` : Amounts.parse(parsed.params.amount) === undefined ? i18n.str`the amount is not valid` : !parsed.params.message ? i18n.str`use the "message" parameter to specify a reference text for the transfer` : !parsed.isKnown || parsed.targetType !== "iban" ? i18n.str`only "IBAN" target are supported` : !IBAN_REGEX.test(parsed.iban) ? i18n.str`IBAN should have just uppercased letters and numbers` : undefined, }); return (

{i18n.str`Transfer money to account identified by payto:// URI:`}

{ e.preventDefault(); }} autoCapitalize="none" autoCorrect="off" >

  { rawPaytoInputSetter(e.currentTarget.value); }} />

Hint: payto://iban/[receiver-iban]?message=[subject]&amount=[{currency} :X.Y]

{ if (!rawPaytoInput) { logger.error("Didn't get any raw Payto string!"); return; } try { await createTransaction({ paytoUri: rawPaytoInput, }); onSuccess(); rawPaytoInputSetter(undefined); } catch (error) { if (error instanceof RequestError) { const errorData: SandboxBackend.SandboxError = error.info.error; onError({ title: i18n.str`Transfer creation gave response error`, description: errorData.error.description, debug: JSON.stringify(errorData), }); } } }} />

{ setIsRawPayto(false); }} > {i18n.str`Use wire-transfer form?`}

); }