import { ComponentChildren, Fragment, VNode, h } from "preact"; import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser"; import { PartialButDefined, RecursivePartial, WithIntermediate, undefinedIfEmpty, validateIBAN } from "../../utils.js"; import { useEffect, useRef, useState } from "preact/hooks"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { PaytoString, TalerCorebankApi, buildPayto, parsePaytoUri } from "@gnu-taler/taler-util"; import { doAutoFocus } from "../PaytoWireTransferForm.js"; import { CopyButton } from "@gnu-taler/web-util/browser"; import { assertUnreachable } from "../WithdrawalOperationPage.js"; const IBAN_REGEX = /^[A-Z][A-Z0-9]*$/; const EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; const REGEX_JUST_NUMBERS_REGEX = /^\+[0-9 ]*$/; export type AccountFormData = TalerCorebankApi.AccountData & { username: string } /** * Create valid account object to update or create * Take template as initial values for the form * Purpose indicate if all field al read only (show), part of them (update) * or none (create) * @param param0 * @returns */ export function AccountForm({ template, username, purpose, onChange, focus, children, }: { focus?: boolean, children: ComponentChildren, username?: string, template: TalerCorebankApi.AccountData | undefined; onChange: (a: AccountFormData | undefined) => void; purpose: "create" | "update" | "show"; }): VNode { const initial = initializeFromTemplate(username, template); const [form, setForm] = useState(initial); const [errors, setErrors] = useState< RecursivePartial | undefined >(undefined); const { i18n } = useTranslationContext(); function updateForm(newForm: typeof initial): void { const parsed = !newForm.cashout_payto_uri ? undefined : buildPayto("iban", newForm.cashout_payto_uri, undefined);; const errors = undefinedIfEmpty>({ cashout_payto_uri: (!newForm.cashout_payto_uri ? i18n.str`required` : !parsed ? i18n.str`does not follow the pattern` : !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` : validateIBAN(parsed.iban, i18n)) as PaytoString, contact_data: undefinedIfEmpty({ email: !newForm.contact_data?.email ? i18n.str`required` : !EMAIL_REGEX.test(newForm.contact_data.email) ? i18n.str`it should be an email` : undefined, phone: !newForm.contact_data?.phone ? i18n.str`required` : !newForm.contact_data.phone.startsWith("+") ? i18n.str`should start with +` : !REGEX_JUST_NUMBERS_REGEX.test(newForm.contact_data.phone) ? i18n.str`phone number can't have other than numbers` : undefined, }), name: !newForm.name ? i18n.str`required` : undefined, username: !newForm.username ? i18n.str`required` : undefined, }); setErrors(errors); setForm(newForm); onChange(errors === undefined ? (newForm as any) : undefined); } return (
{ e.preventDefault() }} >
{ form.username = e.currentTarget.value; updateForm(structuredClone(form)); }} // placeholder="" autocomplete="off" />

account identification in the bank

{ form.name = e.currentTarget.value; updateForm(structuredClone(form)); }} // placeholder="" autocomplete="off" />

name of the person owner the account

{purpose !== "create" && ()}
{ if (form.contact_data) { form.contact_data.email = e.currentTarget.value; updateForm(structuredClone(form)); } }} autocomplete="off" />
{ if (form.contact_data) { form.contact_data.phone = e.currentTarget.value; updateForm(structuredClone(form)); } }} // placeholder="" autocomplete="off" />
{ form.cashout_payto_uri = e.currentTarget.value as PaytoString; updateForm(structuredClone(form)); }} autocomplete="off" />

account number where the money is going to be sent when doing cashouts

{children}
); } function initializeFromTemplate( username: string | undefined, account: TalerCorebankApi.AccountData | undefined, ): WithIntermediate { const emptyAccount = { cashout_payto_uri: undefined, contact_data: undefined, payto_uri: undefined, balance: undefined, debit_threshold: undefined, name: undefined, }; const emptyContact = { email: undefined, phone: undefined, }; const initial: PartialButDefined = structuredClone(account) ?? emptyAccount; if (typeof initial.contact_data === "undefined") { initial.contact_data = emptyContact; } const result: WithIntermediate = initial as any // FIXME: check types result.username = username return initial as any; } function RenderPaytoDisabledField({ paytoURI }: { paytoURI: PaytoString | undefined }): VNode { const { i18n } = useTranslationContext() const payto = parsePaytoUri(paytoURI ?? ""); if (payto?.isKnown) { if (payto.targetType === "iban") { const value = payto.iban; return
value ?? ""} />

international bank account number

} if (payto.targetType === "x-taler-bank") { const value = payto.account; return
value ?? ""} />

internal account id

} if (payto.targetType === "bitcoin") { const value = payto.targetPath; return
value ?? ""} />

bitcoin address

} assertUnreachable(payto) } const value = paytoURI ?? "" return
value ?? ""} />

generic payto URI

}