aboutsummaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2023-09-19 08:31:08 -0300
committerSebastian <sebasjm@gmail.com>2023-09-25 14:50:38 -0300
commita5406c5a5dc437e036168eb068db11d88e05bb0f (patch)
tree74ad5e0d858a5afb3e76ac0c692fdba866fed38f /packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
parente628ca1af851259e609a16d0b53b8d7abfc33716 (diff)
downloadwallet-core-a5406c5a5dc437e036168eb068db11d88e05bb0f.tar.xz
some ui
Diffstat (limited to 'packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx')
-rw-r--r--packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx581
1 files changed, 304 insertions, 277 deletions
diff --git a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
index d16dc70f8..1107360bd 100644
--- a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
+++ b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
@@ -17,26 +17,24 @@
import {
AmountJson,
Amounts,
- buildPayto,
HttpStatusCode,
Logger,
- parsePaytoUri,
- stringifyPaytoUri,
+ parsePaytoUri
} from "@gnu-taler/taler-util";
import {
RequestError,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
-import { h, VNode } from "preact";
+import { h, VNode, Fragment } from "preact";
import { useEffect, useRef, useState } from "preact/hooks";
-import { notifyError } from "../hooks/notification.js";
+import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
import { useAccessAPI } from "../hooks/access.js";
+import { notifyError } from "../hooks/notification.js";
import {
buildRequestErrorMessage,
undefinedIfEmpty,
validateIBAN,
} from "../utils.js";
-import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
const logger = new Logger("PaytoWireTransferForm");
@@ -72,293 +70,322 @@ export function PaytoWireTransferForm({
iban: !iban
? i18n.str`Missing IBAN`
: !IBAN_REGEX.test(iban)
- ? i18n.str`IBAN should have just uppercased letters and numbers`
- : validateIBAN(iban, i18n),
+ ? i18n.str`IBAN should have just uppercased letters and numbers`
+ : validateIBAN(iban, i18n),
subject: !subject ? i18n.str`Missing subject` : undefined,
amount: !trimmedAmountStr
? i18n.str`Missing amount`
: !parsedAmount
- ? i18n.str`Amount is not valid`
- : Amounts.isZero(parsedAmount)
- ? i18n.str`Should be greater than 0`
- : Amounts.cmp(limit, parsedAmount) === -1
- ? i18n.str`balance is not enough`
- : undefined,
+ ? i18n.str`Amount is not valid`
+ : Amounts.isZero(parsedAmount)
+ ? i18n.str`Should be greater than 0`
+ : Amounts.cmp(limit, parsedAmount) === -1
+ ? i18n.str`balance is not enough`
+ : undefined,
});
const { createTransaction } = useAccessAPI();
- if (!isRawPayto)
- return (
- <div>
- <form
- class="pure-form"
- name="wire-transfer-form"
- onSubmit={(e) => {
- e.preventDefault();
- }}
- autoCapitalize="none"
- autoCorrect="off"
- >
- <label for="iban">{i18n.str`Receiver IBAN:`}</label>&nbsp;
- <input
- ref={ref}
- type="text"
- id="iban"
- name="iban"
- value={iban ?? ""}
- placeholder="CC0123456789"
- required
- pattern={ibanRegex}
- onInput={(e): void => {
- setIban(e.currentTarget.value);
- }}
- />
- <ShowInputErrorLabel
- message={errorsWire?.iban}
- isDirty={iban !== undefined}
- />
- <label for="subject">{i18n.str`Transfer subject:`}</label>&nbsp;
- <input
- type="text"
- name="subject"
- id="subject"
- placeholder="subject"
- value={subject ?? ""}
- required
- onInput={(e): void => {
- setSubject(e.currentTarget.value);
- }}
- />
- <ShowInputErrorLabel
- message={errorsWire?.subject}
- isDirty={subject !== undefined}
- />
- <label for="amount">{i18n.str`Amount:`}</label>&nbsp;
- <div style={{ width: "max-content", display: "flex" }}>
- <input
- type="text"
- readonly
- class="currency-indicator"
- size={limit.currency.length}
- maxLength={limit.currency.length}
- tabIndex={-1}
- style={{
- borderTopRightRadius: 0,
- borderBottomRightRadius: 0,
- borderRight: 0,
- }}
- value={limit.currency}
- />
- <input
- type="number"
- name="amount"
- id="amount"
- placeholder="amount"
- required
- style={{
- borderTopLeftRadius: 0,
- borderBottomLeftRadius: 0,
- borderLeft: 0,
- width: 150,
- }}
- value={amount ?? ""}
- onInput={(e): void => {
- setAmount(e.currentTarget.value);
- }}
- />
- </div>
- <ShowInputErrorLabel
- message={errorsWire?.amount}
- isDirty={amount !== undefined}
- />
- <p style={{ display: "flex", justifyContent: "space-between" }}>
- <input
- type="submit"
- class="pure-button pure-button-primary"
- disabled={!!errorsWire}
- value="Send"
- onClick={async (e) => {
- e.preventDefault();
- if (!(iban && subject && amount)) {
- return;
- }
- const ibanPayto = buildPayto("iban", iban, undefined);
- ibanPayto.params.message = encodeURIComponent(subject);
- const paytoUri = stringifyPaytoUri(ibanPayto);
-
- try {
- await createTransaction({
- paytoUri,
- amount: `${limit.currency}:${amount}`,
- });
- onSuccess();
- setAmount(undefined);
- setIban(undefined);
- setSubject(undefined);
- } catch (error) {
- if (error instanceof RequestError) {
- notifyError(
- buildRequestErrorMessage(i18n, error.cause, {
- onClientError: (status) =>
- status === HttpStatusCode.BadRequest
- ? i18n.str`The request was invalid or the payto://-URI used unacceptable features.`
- : undefined,
- }),
- );
- } else {
- notifyError({
- title: i18n.str`Operation failed, please report`,
- description:
- error instanceof Error
- ? error.message
- : JSON.stringify(error),
- });
- }
- }
- }}
- />
- <input
- type="button"
- class="pure-button"
- value="Clear"
- onClick={async (e) => {
- e.preventDefault();
- setAmount(undefined);
- setIban(undefined);
- setSubject(undefined);
- }}
- />
- </p>
- </form>
- <p>
- <a
- href="#"
- onClick={(e) => {
- setIsRawPayto(true);
- e.preventDefault();
- }}
- >
- {i18n.str`Want to try the raw payto://-format?`}
- </a>
- </p>
- </div>
- );
-
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`
- : validateIBAN(parsed.iban, i18n),
+ ? 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`
+ : validateIBAN(parsed.iban, i18n),
});
+ // if (!isRawPayto) {
+ return (<div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-10 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg">
+ <div class="px-4 sm:px-0">
+ <h2 class="text-base font-semibold leading-7 text-gray-900"><i18n.Translate>Transfer details</i18n.Translate></h2>
+ <div>
+ <div class="px-4 mt-4 grid grid-cols-1 gap-y-6 sm:grid-cols-2 sm:gap-x-4">
+ {/* <!-- Active: "border-indigo-600 ring-2 ring-indigo-600", Not Active: "border-gray-300" --> */}
+ <label class={"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none" + (!isRawPayto ? "border-indigo-600 ring-2 ring-indigo-600" : "border-gray-300")}>
+ <input type="radio" name="project-type" value="Newsletter" class="sr-only" aria-labelledby="project-type-0-label" aria-describedby="project-type-0-description-0 project-type-0-description-1" onChange={() => {
+ setIsRawPayto(false)
+ }} />
+ <span class="flex flex-1">
+ <span class="flex flex-col">
+ <span id="project-type-0-label" class="block text-sm font-medium text-gray-900">
+ <i18n.Translate>form</i18n.Translate>
+ </span>
+ </span>
+ </span>
+ </label>
- return (
- <div>
- <p>{i18n.str`Transfer money to account identified by payto:// URI:`}</p>
- <form
- class="pure-form"
- name="payto-form"
- onSubmit={(e) => {
- e.preventDefault();
- }}
- autoCapitalize="none"
- autoCorrect="off"
- >
- <p>
- <label for="address">{i18n.str`payto URI:`}</label>&nbsp;
- <input
- name="address"
- type="text"
- size={50}
- ref={ref}
- id="address"
- value={rawPaytoInput ?? ""}
- required
- placeholder={i18n.str`payto address`}
- // pattern={`payto://iban/[A-Z][A-Z][0-9]+?message=[a-zA-Z0-9 ]+&amount=${currency}:[0-9]+(.[0-9]+)?`}
- onInput={(e): void => {
- rawPaytoInputSetter(e.currentTarget.value);
- }}
- />
- <ShowInputErrorLabel
- message={errorsPayto?.rawPaytoInput}
- isDirty={rawPaytoInput !== undefined}
- />
- <br />
- <div style={{ fontSize: "small", marginTop: 4 }}>
- Hint:
- <code>
- payto://iban/[receiver-iban]?message=[subject]&amount=[
- {limit.currency}
- :X.Y]
- </code>
- </div>
- </p>
- <p>
- <input
- class="pure-button pure-button-primary"
- type="button"
- disabled={!!errorsPayto}
- value={i18n.str`Send`}
- onClick={async () => {
- 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) {
- notifyError(
- buildRequestErrorMessage(i18n, error.cause, {
- onClientError: (status) =>
- status === HttpStatusCode.BadRequest
- ? i18n.str`The request was invalid or the payto://-URI used unacceptable features.`
- : undefined,
- }),
- );
- } else {
- notifyError({
- title: i18n.str`Operation failed, please report`,
- description:
- error instanceof Error
- ? error.message
- : JSON.stringify(error),
- });
- }
- }
- }}
- />
- </p>
- <p>
- <a
- href="/account"
- onClick={() => {
- setIsRawPayto(false);
- }}
- >
- {i18n.str`Use wire-transfer form?`}
- </a>
- </p>
- </form>
+ {/* <!-- Active: "border-indigo-600 ring-2 ring-indigo-600", Not Active: "border-gray-300" --> */}
+ <label class={"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none" + (isRawPayto ? "border-indigo-600 ring-2 ring-indigo-600" : "border-gray-300")}>
+ <input type="radio" name="project-type" value="Existing Customers" class="sr-only" aria-labelledby="project-type-1-label" aria-describedby="project-type-1-description-0 project-type-1-description-1" onChange={() => {
+ setIsRawPayto(true)
+ }} />
+ <span class="flex flex-1">
+ <span class="flex flex-col">
+ <span id="project-type-1-label" class="block text-sm font-medium text-gray-900">
+ <i18n.Translate>payto://</i18n.Translate>
+ </span>
+ </span>
+ </span>
+ </label>
+ </div>
+ </div>
</div>
- );
+
+ <form class="bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2">
+ <div class="px-4 py-6 sm:p-8">
+ <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
+ {!isRawPayto ?
+ <Fragment>
+
+ <div class="sm:col-span-3">
+ <label for="first-name" class="block text-sm font-medium leading-6 text-gray-900">{i18n.str`Account number`}</label>
+ <div class="mt-2">
+ <input
+ ref={ref}
+ type="text"
+ class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
+ id="iban"
+ name="iban"
+ value={iban ?? ""}
+ placeholder="CC0123456789"
+ required
+ pattern={ibanRegex}
+ onInput={(e): void => {
+ setIban(e.currentTarget.value);
+ }}
+ />
+ <ShowInputErrorLabel
+ message={errorsWire?.iban}
+ isDirty={iban !== undefined}
+ />
+ </div>
+ <p class="mt-2 text-sm text-gray-500" id="email-description">the receiver of the money</p>
+ </div>
+
+ <div class="sm:col-span-3">
+ </div>
+
+ <div class="sm:col-span-3">
+ <label for="first-name" class="block text-sm font-medium leading-6 text-gray-900">{i18n.str`Transfer subject`}</label>
+ <div class="mt-2">
+
+ <input
+ type="text"
+ class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
+ name="subject"
+ id="subject"
+ placeholder="subject"
+ value={subject ?? ""}
+ required
+ onInput={(e): void => {
+ setSubject(e.currentTarget.value);
+ }}
+ />
+ <ShowInputErrorLabel
+ message={errorsWire?.subject}
+ isDirty={subject !== undefined}
+ />
+ </div>
+ <p class="mt-2 text-sm text-gray-500" id="email-description">some text to identify the transfer</p>
+
+ </div>
+
+ <div class="sm:col-span-3">
+ </div>
+
+ <div class="sm:col-span-3">
+ <label for="first-name" class="block text-sm font-medium leading-6 text-gray-900">{i18n.str`Amount`}</label>
+ <div class="mt-2">
+ <input type="text" name="first-name" id="first-name" autocomplete="given-name" class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" />
+ </div>
+ </div>
+
+ <div class="sm:col-span-3">
+ </div>
+ </Fragment> :
+ <Fragment>
+ <div class="sm:col-span-6">
+ <label for="first-name" class="block text-sm font-medium leading-6 text-gray-900">{i18n.str`payto URI:`}</label>
+ <div class="mt-2">
+ <input
+ name="address"
+ type="text"
+ size={50}
+ class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" ref={ref}
+ id="address"
+ value={rawPaytoInput ?? ""}
+ required
+ placeholder={i18n.str`payto://iban/[receiver-iban]?message=[subject]&amount=[${limit.currency}:X.Y]`}
+ // pattern={`payto://iban/[A-Z][A-Z][0-9]+?message=[a-zA-Z0-9 ]+&amount=${currency}:[0-9]+(.[0-9]+)?`}
+ onInput={(e): void => {
+ rawPaytoInputSetter(e.currentTarget.value);
+ }}
+ />
+ <ShowInputErrorLabel
+ message={errorsPayto?.rawPaytoInput}
+ isDirty={rawPaytoInput !== undefined}
+ />
+ </div>
+ </div>
+
+ </Fragment>
+ }
+ </div>
+ </div>
+ <div class="flex items-center justify-end gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8">
+ <button type="button" class="text-sm font-semibold leading-6 text-gray-900">Cancel</button>
+ <button type="submit" class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
+ <i18n.Translate>Send</i18n.Translate>
+ </button>
+ </div>
+ </form>
+ </div >
+ )
+ // }
+ // return (
+ // <div>
+ // <form
+ // class="pure-form"
+ // name="wire-transfer-form"
+ // onSubmit={(e) => {
+ // e.preventDefault();
+ // }}
+ // autoCapitalize="none"
+ // autoCorrect="off"
+ // >
+ // <label for="iban">{i18n.str`Receiver IBAN:`}</label>&nbsp;
+
+ // <label for="subject">{i18n.str`Transfer subject:`}</label>&nbsp;
+
+ // <label for="amount">{i18n.str`Amount:`}</label>&nbsp;
+ // <div style={{ width: "max-content", display: "flex" }}>
+ // <input
+ // type="text"
+ // readonly
+ // class="currency-indicator"
+ // size={limit.currency.length}
+ // maxLength={limit.currency.length}
+ // tabIndex={-1}
+ // style={{
+ // borderTopRightRadius: 0,
+ // borderBottomRightRadius: 0,
+ // borderRight: 0,
+ // }}
+ // value={limit.currency}
+ // />
+ // <input
+ // type="number"
+ // name="amount"
+ // id="amount"
+ // placeholder="amount"
+ // required
+ // style={{
+ // borderTopLeftRadius: 0,
+ // borderBottomLeftRadius: 0,
+ // borderLeft: 0,
+ // width: 150,
+ // }}
+ // value={amount ?? ""}
+ // onInput={(e): void => {
+ // setAmount(e.currentTarget.value);
+ // }}
+ // />
+ // </div>
+ // <ShowInputErrorLabel
+ // message={errorsWire?.amount}
+ // isDirty={amount !== undefined}
+ // />
+ // <p style={{ display: "flex", justifyContent: "space-between" }}>
+ // <input
+ // type="submit"
+ // class="pure-button pure-button-primary"
+ // disabled={!!errorsWire}
+ // value="Send"
+ // onClick={async (e) => {
+ // e.preventDefault();
+ // if (!(iban && subject && amount)) {
+ // return;
+ // }
+ // const ibanPayto = buildPayto("iban", iban, undefined);
+ // ibanPayto.params.message = encodeURIComponent(subject);
+ // const paytoUri = stringifyPaytoUri(ibanPayto);
+
+ // try {
+ // await createTransaction({
+ // paytoUri,
+ // amount: `${limit.currency}:${amount}`,
+ // });
+ // onSuccess();
+ // setAmount(undefined);
+ // setIban(undefined);
+ // setSubject(undefined);
+ // } catch (error) {
+ // if (error instanceof RequestError) {
+ // notifyError(
+ // buildRequestErrorMessage(i18n, error.cause, {
+ // onClientError: (status) =>
+ // status === HttpStatusCode.BadRequest
+ // ? i18n.str`The request was invalid or the payto://-URI used unacceptable features.`
+ // : undefined,
+ // }),
+ // );
+ // } else {
+ // notifyError({
+ // title: i18n.str`Operation failed, please report`,
+ // description:
+ // error instanceof Error
+ // ? error.message
+ // : JSON.stringify(error),
+ // });
+ // }
+ // }
+ // }}
+ // />
+ // <input
+ // type="button"
+ // class="pure-button"
+ // value="Clear"
+ // onClick={async (e) => {
+ // e.preventDefault();
+ // setAmount(undefined);
+ // setIban(undefined);
+ // setSubject(undefined);
+ // }}
+ // />
+ // </p>
+ // </form>
+ // <p>
+ // <a
+ // href="#"
+ // onClick={(e) => {
+ // setIsRawPayto(true);
+ // e.preventDefault();
+ // }}
+ // >
+ // {i18n.str`Want to try the raw payto://-format?`}
+ // </a>
+ // </p>
+ // </div>
+ // );
+
+
+
+ // return (
+ // <div>
+ // <p>{i18n.str`Transfer money to account identified by payto:// URI:`}</p>
+
+ // </div>
+ // );
}