summaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2023-09-20 15:18:36 -0300
committerSebastian <sebasjm@gmail.com>2023-09-25 14:50:39 -0300
commite39d5c488e2e425bd7febf694caadc17d5126401 (patch)
tree0431fcaeebf8e515f21f7f1ff607cb4f12fcd509 /packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
parentfdbe623e1060efc4b074d213a96e8f5a2ab7498b (diff)
downloadwallet-core-e39d5c488e2e425bd7febf694caadc17d5126401.tar.gz
wallet-core-e39d5c488e2e425bd7febf694caadc17d5126401.tar.bz2
wallet-core-e39d5c488e2e425bd7febf694caadc17d5126401.zip
more ui
Diffstat (limited to 'packages/demobank-ui/src/pages/WalletWithdrawForm.tsx')
-rw-r--r--packages/demobank-ui/src/pages/WalletWithdrawForm.tsx319
1 files changed, 191 insertions, 128 deletions
diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
index da624f61b..6574ec934 100644
--- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
+++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
@@ -19,19 +19,21 @@ import {
Amounts,
HttpStatusCode,
Logger,
+ TranslatedString,
parseWithdrawUri,
} from "@gnu-taler/taler-util";
import {
RequestError,
+ notify,
+ notifyError,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
-import { Ref, VNode, h } from "preact";
+import { VNode, h } from "preact";
+import { forwardRef } from "preact/compat";
import { useEffect, useRef, useState } from "preact/hooks";
import { useAccessAPI } from "../hooks/access.js";
-import { notifyError } from "../hooks/notification.js";
import { buildRequestErrorMessage, undefinedIfEmpty } from "../utils.js";
-import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
-import { forwardRef } from "preact/compat";
+import { Amount } from "./PaytoWireTransferForm.js";
const logger = new Logger("WalletWithdrawForm");
const RefAmount = forwardRef(Amount);
@@ -40,10 +42,12 @@ export function WalletWithdrawForm({
focus,
limit,
onSuccess,
+ onCancel,
}: {
limit: AmountJson;
focus?: boolean;
onSuccess: (operationId: string) => void;
+ onCancel: () => void;
}): VNode {
const { i18n } = useTranslationContext();
const { createWithdrawal } = useAccessAPI();
@@ -71,136 +75,195 @@ export function WalletWithdrawForm({
: undefined,
});
- return (
+ async function doStart() {
+ if (!parsedAmount) return;
+ try {
+ const result = await createWithdrawal({
+ amount: Amounts.stringify(parsedAmount),
+ });
+ const uri = parseWithdrawUri(result.data.taler_withdraw_uri);
+ if (!uri) {
+ return notifyError(
+ i18n.str`Server responded with an invalid withdraw URI`,
+ i18n.str`Withdraw URI: ${result.data.taler_withdraw_uri}`);
+ } else {
+ onSuccess(uri.withdrawalOperationId);
+ }
+ } catch (error) {
+ if (error instanceof RequestError) {
+ notify(
+ buildRequestErrorMessage(i18n, error.cause, {
+ onClientError: (status) =>
+ status === HttpStatusCode.Forbidden
+ ? i18n.str`The operation was rejected due to insufficient funds`
+ : undefined,
+ }),
+ );
+ } else {
+ notifyError(
+ i18n.str`Operation failed, please report`,
+ (error instanceof Error
+ ? error.message
+ : JSON.stringify(error)) as TranslatedString
+ )
+}
+ }
+
+ }
+
+ 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>Prepare your wallet</i18n.Translate></h2>
+ <p class="mt-1 text-sm text-gray-500">
+ <i18n.Translate>Upon starting you will receive the money in your digital wallet, if you don't have one please <a class="font-semibold text-gray-500 hover:text-gray-400" href="https://taler.net/en/wallet.html">install one from here</a></i18n.Translate>.
+ </p>
+ <p class="mt-1 text-sm text-gray-500">
+ <i18n.Translate>After using your wallet you will be redirected here to confirm or cancel the operation.</i18n.Translate>
+ </p>
+ </div>
<form
- id="reserve-form"
- class="pure-form"
- name="tform"
- onSubmit={(e) => {
- e.preventDefault();
- }}
+ class="bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2"
autoCapitalize="none"
autoCorrect="off"
+ onSubmit={e => {
+ e.preventDefault()
+ }}
>
- <p>
- <label for="withdraw-amount">{i18n.str`Amount to withdraw:`}</label>
- &nbsp;
- <RefAmount
- currency={limit.currency}
- value={amountStr}
- onChange={(v) => {
- setAmountStr(v);
- }}
- error={errors?.amount}
- ref={ref}
- />
- </p>
- <p>
- <div>
- <input
- id="select-exchange"
- class="pure-button pure-button-primary"
- type="submit"
- disabled={!!errors}
- value={i18n.str`Withdraw`}
- onClick={async (e) => {
- e.preventDefault();
- if (!parsedAmount) return;
- try {
- const result = await createWithdrawal({
- amount: Amounts.stringify(parsedAmount),
- });
- const uri = parseWithdrawUri(result.data.taler_withdraw_uri);
- if (!uri) {
- return notifyError({
- title: i18n.str`Server responded with an invalid withdraw URI`,
- description: i18n.str`Withdraw URI: ${result.data.taler_withdraw_uri}`,
- });
- } else {
- onSuccess(uri.withdrawalOperationId);
- }
- } catch (error) {
- if (error instanceof RequestError) {
- notifyError(
- buildRequestErrorMessage(i18n, error.cause, {
- onClientError: (status) =>
- status === HttpStatusCode.Forbidden
- ? i18n.str`The operation was rejected due to insufficient funds`
- : undefined,
- }),
- );
- } else {
- notifyError({
- title: i18n.str`Operation failed, please report`,
- description:
- error instanceof Error
- ? error.message
- : JSON.stringify(error),
- });
- }
- }
- }}
- />
- </div>
- </p>
- </form>
- );
-}
+ <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">
+ <div class="sm:col-span-5">
+ <label for="withdraw-amount">{i18n.str`Amount`}</label>
+ <RefAmount
+ currency={limit.currency}
+ value={amountStr}
+ name="withdraw-amount"
+ onChange={(v) => {
+ setAmountStr(v);
+ }}
+ error={errors?.amount}
+ ref={ref}
+ />
+ </div>
+ <div class="sm:col-span-5">
+ <span class="isolate inline-flex rounded-md shadow-sm">
+ <button type="button"
+ class="relative inline-flex px-3 py-2 text-sm items-center rounded-l-md bg-white text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10"
+ onClick={(e) => {
+ e.preventDefault();
+ setAmountStr("50.00")
+ }}
+ >
+ 50.00
+ </button>
+ <button type="button"
+ class="relative -ml-px -mr-px inline-flex px-3 py-2 text-sm items-center bg-white text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10"
+ onClick={(e) => {
+ e.preventDefault();
+ setAmountStr("25.00")
+ }}
+ >
-export function Amount(
- {
- currency,
- value,
- error,
- onChange,
- }: {
- error?: string;
- currency: string;
- value: string | undefined;
- onChange?: (s: string) => void;
- },
- ref: Ref<HTMLInputElement>,
-): VNode {
- return (
- <div style={{ width: "max-content" }}>
- <div>
- <input
- type="text"
- readonly
- class="currency-indicator"
- size={currency.length}
- maxLength={currency.length}
- tabIndex={-1}
- style={{
- borderTopRightRadius: 0,
- borderBottomRightRadius: 0,
- borderRight: 0,
- }}
- value={currency}
- />
- <input
- type="number"
- ref={ref}
- name="amount"
- id="amount"
- placeholder="0"
- style={{
- borderTopLeftRadius: 0,
- borderBottomLeftRadius: 0,
- borderLeft: 0,
- width: 150,
- color: "black",
- }}
- value={value ?? ""}
- disabled={!onChange}
- onInput={(e): void => {
- if (onChange) {
- onChange(e.currentTarget.value);
- }
+ 25.00
+ </button>
+ <button type="button"
+ class="relative -ml-px -mr-px inline-flex px-3 py-2 text-sm items-center bg-white text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10"
+ onClick={(e) => {
+ e.preventDefault();
+ setAmountStr("10.00")
+ }}
+ >
+ 10.00
+ </button>
+ <button type="button"
+ class="relative inline-flex px-3 py-2 text-sm items-center rounded-r-md bg-white text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10"
+ onClick={(e) => {
+ e.preventDefault();
+ setAmountStr("5.00")
+ }}
+ >
+ 5.00
+ </button>
+ </span>
+ </div>
+
+ </div>
+ </div>
+ <div class="flex items-center justify-between 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"
+ onClick={onCancel}
+ >
+ <i18n.Translate>Cancel</i18n.Translate></button>
+ <button type="submit"
+ class="disabled:opacity-50 disabled:cursor-default cursor-pointer 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"
+ // disabled={isRawPayto ? !!errorsPayto : !!errorsWire}
+ onClick={(e) => {
+ e.preventDefault()
+ doStart()
}}
- />
+ >
+ <i18n.Translate>Continue</i18n.Translate>
+ </button>
</div>
- <ShowInputErrorLabel message={error} isDirty={value !== undefined} />
- </div>
+
+ </form>
+ </div>
);
}
+
+// export function Amount(
+// {
+// currency,
+// value,
+// error,
+// onChange,
+// }: {
+// error?: string;
+// currency: string;
+// value: string | undefined;
+// onChange?: (s: string) => void;
+// },
+// ref: Ref<HTMLInputElement>,
+// ): VNode {
+// return (
+// <div style={{ width: "max-content" }}>
+// <div>
+// <input
+// type="text"
+// readonly
+// class="currency-indicator"
+// size={currency.length}
+// maxLength={currency.length}
+// tabIndex={-1}
+// style={{
+// borderTopRightRadius: 0,
+// borderBottomRightRadius: 0,
+// borderRight: 0,
+// }}
+// value={currency}
+// />
+// <input
+// type="number"
+// ref={ref}
+// name="amount"
+// id="amount"
+// placeholder="0"
+// style={{
+// borderTopLeftRadius: 0,
+// borderBottomLeftRadius: 0,
+// borderLeft: 0,
+// width: 150,
+// color: "black",
+// }}
+// value={value ?? ""}
+// disabled={!onChange}
+// onInput={(e): void => {
+// if (onChange) {
+// onChange(e.currentTarget.value);
+// }
+// }}
+// />
+// </div>
+// <ShowInputErrorLabel message={error} isDirty={value !== undefined} />
+// </div>
+// );
+// }