aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/demobank-ui/src/components/Routing.tsx12
-rw-r--r--packages/demobank-ui/src/hooks/settings.ts8
-rw-r--r--packages/demobank-ui/src/pages/AccountPage/views.tsx50
-rw-r--r--packages/demobank-ui/src/pages/BankFrame.tsx133
-rw-r--r--packages/demobank-ui/src/pages/HomePage.tsx20
-rw-r--r--packages/demobank-ui/src/pages/PaymentOptions.tsx137
-rw-r--r--packages/demobank-ui/src/pages/QrCodeSection.tsx106
-rw-r--r--packages/demobank-ui/src/pages/WalletWithdrawForm.tsx183
-rw-r--r--packages/demobank-ui/src/pages/WithdrawalQRCode.tsx159
-rw-r--r--packages/demobank-ui/src/pages/admin/RemoveAccount.tsx2
10 files changed, 553 insertions, 257 deletions
diff --git a/packages/demobank-ui/src/components/Routing.tsx b/packages/demobank-ui/src/components/Routing.tsx
index b8e39948b..e1fd93737 100644
--- a/packages/demobank-ui/src/components/Routing.tsx
+++ b/packages/demobank-ui/src/components/Routing.tsx
@@ -76,9 +76,9 @@ export function Routing(): VNode {
onContinue={() => {
route("/account");
}}
- onLoadNotOk={() => {
- route("/account");
- }}
+ // onLoadNotOk={() => {
+ // route("/account");
+ // }}
/>
)}
/>
@@ -108,9 +108,9 @@ export function Routing(): VNode {
} else {
return <HomePage
account={username}
- onPendingOperationFound={(wopid) => {
- route(`/operation/${wopid}`);
- }}
+ // onPendingOperationFound={(wopid) => {
+ // route(`/operation/${wopid}`);
+ // }}
goToBusinessAccount={() => {
route("/business");
}}
diff --git a/packages/demobank-ui/src/hooks/settings.ts b/packages/demobank-ui/src/hooks/settings.ts
index 43e803726..c2fd93a0c 100644
--- a/packages/demobank-ui/src/hooks/settings.ts
+++ b/packages/demobank-ui/src/hooks/settings.ts
@@ -29,20 +29,26 @@ import { buildStorageKey, useLocalStorage } from "@gnu-taler/web-util/browser";
interface Settings {
currentWithdrawalOperationId: string | undefined;
showWithdrawalSuccess: boolean;
+ showDemoDescription: boolean;
maxWithdrawalAmount: number;
+ fastWithdrawal: boolean;
}
export const codecForSettings = (): Codec<Settings> =>
buildCodecForObject<Settings>()
.property("currentWithdrawalOperationId", codecOptional(codecForString()))
.property("showWithdrawalSuccess", (codecForBoolean()))
+ .property("showDemoDescription", (codecForBoolean()))
+ .property("fastWithdrawal", (codecForBoolean()))
.property("maxWithdrawalAmount", codecForNumber())
.build("Settings");
const defaultSettings: Settings = {
currentWithdrawalOperationId: undefined,
showWithdrawalSuccess: true,
- maxWithdrawalAmount: 25
+ showDemoDescription: true,
+ maxWithdrawalAmount: 25,
+ fastWithdrawal: false,
};
const DEMOBANK_SETTINGS_KEY = buildStorageKey(
diff --git a/packages/demobank-ui/src/pages/AccountPage/views.tsx b/packages/demobank-ui/src/pages/AccountPage/views.tsx
index abd14848f..0187989af 100644
--- a/packages/demobank-ui/src/pages/AccountPage/views.tsx
+++ b/packages/demobank-ui/src/pages/AccountPage/views.tsx
@@ -23,6 +23,7 @@ import { State } from "./index.js";
import { CopyButton } from "../../components/CopyButton.js";
import { bankUiSettings } from "../../settings.js";
import { useBusinessAccountDetails } from "../../hooks/circuit.js";
+import { useSettings } from "../../hooks/settings.js";
export function InvalidIbanView({ error }: State.InvalidIban) {
return (
@@ -78,9 +79,58 @@ function ImportantMessage(): VNode {
}
+function ShowDemoInfo():VNode {
+ const { i18n } = useTranslationContext();
+ const [settings, updateSettings] = useSettings();
+ if (!settings.showDemoDescription) return <Fragment />
+ return <div class="rounded-md bg-blue-50 p-4">
+ <div class="flex">
+ <div class="flex-shrink-0">
+ <svg class="h-5 w-5 text-blue-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
+ <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd" />
+ </svg>
+ </div>
+ <div class="ml-3">
+ <h3 class="text-sm font-bold text-blue-800">
+ <i18n.Translate>This is a demo bank!</i18n.Translate>
+ </h3>
+ <div class="mt-2 text-sm text-blue-700">
+ <p>
+ <i18n.Translate>
+ This part of the demo shows how a bank that supports Taler
+ directly would work. In addition to using your own bank
+ account, you can also see the transaction history of some{" "}
+ <a href="/public-accounts">Public Accounts</a>.
+ </i18n.Translate>
+ </p>
+ <p class="mt-3 text-sm flex justify-end">
+ <button type="button" class="inline-flex font-semibold items-center rounded bg-white px-2 py-1 text-xs text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
+ onClick={(e) => {
+ e.preventDefault();
+ updateSettings("showDemoDescription", false);
+ }}
+ >
+ Close
+ <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
+ <path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
+ </svg>
+ </button>
+ </p>
+
+ </div>
+ </div>
+ </div>
+</div>
+}
+
export function ReadyView({ account, limit, goToBusinessAccount }: State.Ready): VNode<{}> {
+ const { i18n } = useTranslationContext();
+
return <Fragment>
<MaybeBusinessButton account={account} onClick={goToBusinessAccount} />
+
+ <ShowDemoInfo />
+
<PaymentOptions limit={limit} />
<Transactions account={account} />
</Fragment>;
diff --git a/packages/demobank-ui/src/pages/BankFrame.tsx b/packages/demobank-ui/src/pages/BankFrame.tsx
index 4b23686d6..d1c94135b 100644
--- a/packages/demobank-ui/src/pages/BankFrame.tsx
+++ b/packages/demobank-ui/src/pages/BankFrame.tsx
@@ -27,7 +27,6 @@ import { CopyButton, CopyIcon } from "../components/CopyButton.js";
import logo from "../assets/logo-2021.svg";
import { useAccountDetails } from "../hooks/access.js";
-const IS_PUBLIC_ACCOUNT_ENABLED = false;
const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : undefined;
@@ -142,24 +141,40 @@ export function BankFrame({
<nav class="flex flex-1 flex-col" aria-label="Sidebar">
<ul role="list" class="flex flex-1 flex-col gap-y-7">
<li>
- <ul role="list" class="-mx-2 space-y-1">
- <li>
- <a href="#"
- class="text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold"
- onClick={() => {
- backend.logOut();
- setOpen(false)
- updateSettings("currentWithdrawalOperationId", undefined);
- }}
- >
- <svg class="h-6 w-6 shrink-0 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
- <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
- </svg>
- Log out
- {/* <span class="ml-auto w-9 min-w-max whitespace-nowrap rounded-full bg-gray-50 px-2.5 py-0.5 text-center text-xs font-medium leading-5 text-gray-600 ring-1 ring-inset ring-gray-200" aria-hidden="true">5</span> */}
- </a>
- </li>
- <li>
+ <a href="#"
+ class="text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold"
+ onClick={() => {
+ backend.logOut();
+ setOpen(false)
+ updateSettings("currentWithdrawalOperationId", undefined);
+ }}
+ >
+ <svg class="h-6 w-6 shrink-0 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
+ <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
+ </svg>
+ Log out
+ {/* <span class="ml-auto w-9 min-w-max whitespace-nowrap rounded-full bg-gray-50 px-2.5 py-0.5 text-center text-xs font-medium leading-5 text-gray-600 ring-1 ring-inset ring-gray-200" aria-hidden="true">5</span> */}
+ </a>
+ </li>
+ <li class="sm:hidden">
+ <div class="text-xs font-semibold leading-6 text-gray-400">
+ <i18n.Translate>Sites</i18n.Translate>
+ </div>
+ <ul role="list" class="-mx-2 mt-2 space-y-1">
+ {bankUiSettings.demoSites.map(([name, url]) => {
+ return <li>
+ <a href={url} target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold">
+ <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-lg border text-[0.625rem] font-medium bg-white text-gray-400 border-gray-200 group-hover:border-indigo-600 group-hover:text-indigo-600">&gt;</span>
+ <span class="truncate">{name}</span>
+ </a>
+ </li>
+ })}
+ </ul>
+ </li>
+
+ <li>
+ <ul role="list" class="space-y-1">
+ <li class="mt-2">
<div class="flex items-center justify-between">
<span class="flex flex-grow flex-col">
<span class="text-sm text-black font-medium leading-6 " id="availability-label">
@@ -169,29 +184,43 @@ export function BankFrame({
<button type="button" data-enabled={settings.showWithdrawalSuccess} class="bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description"
onClick={() => {
- console.log(settings.showWithdrawalSuccess)
updateSettings("showWithdrawalSuccess", !settings.showWithdrawalSuccess);
}}>
<span aria-hidden="true" data-enabled={settings.showWithdrawalSuccess} class="translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
</button>
</div>
</li>
- </ul>
- </li>
-
-
+ <li class="mt-2">
+ <div class="flex items-center justify-between">
+ <span class="flex flex-grow flex-col">
+ <span class="text-sm text-black font-medium leading-6 " id="availability-label">
+ <i18n.Translate>Show demo description</i18n.Translate>
+ </span>
+ </span>
+ <button type="button" data-enabled={settings.showDemoDescription} class="bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description"
- <li class="sm:hidden">
- <div class="text-xs font-semibold leading-6 text-gray-400">
- <i18n.Translate>Sites</i18n.Translate>
- </div>
- <ul role="list" class="-mx-2 mt-2 space-y-1">
- {bankUiSettings.demoSites.map(([name, url]) => {
- return <a href={url} target="_blank" rel="noopener noreferrer" class="text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold">
- <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-lg border text-[0.625rem] font-medium bg-white text-gray-400 border-gray-200 group-hover:border-indigo-600 group-hover:text-indigo-600">&gt;</span>
- <span class="truncate">{name}</span>
- </a>
- })}
+ onClick={() => {
+ updateSettings("showDemoDescription", !settings.showDemoDescription);
+ }}>
+ <span aria-hidden="true" data-enabled={settings.showDemoDescription} class="translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
+ </button>
+ </div>
+ </li>
+ <li class="mt-2">
+ <div class="flex items-center justify-between">
+ <span class="flex flex-grow flex-col">
+ <span class="text-sm text-black font-medium leading-6 " id="availability-label">
+ <i18n.Translate>Use fast withdrawal</i18n.Translate>
+ </span>
+ </span>
+ <button type="button" data-enabled={settings.fastWithdrawal} class="bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description"
+ onClick={() => {
+ updateSettings("fastWithdrawal", !settings.fastWithdrawal);
+ }}>
+ <span aria-hidden="true" data-enabled={settings.fastWithdrawal} class="translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
+ </button>
+ </div>
+ </li>
</ul>
</li>
</ul>
@@ -240,11 +269,6 @@ export function BankFrame({
// >
// <a href="#main" class="skip">{i18n.str`Skip to main content`}</a>
// <div style="max-width: 50em; margin-left: 2em; margin-right: 2em;">
- // <h1>
- // <span class="it">
- // <a href="/">{bankUiSettings.bankName}</a>
- // </span>
- // </h1>
// {maybeDemoContent(
// <p>
// {IS_PUBLIC_ACCOUNT_ENABLED ? (
@@ -298,33 +322,6 @@ export function BankFrame({
);
}
-// function maybeDemoContent(content: VNode): VNode {
-// if (bankUiSettings.showDemoNav) {
-// return content;
-// }
-// return <Fragment />;
-// }
-
-// export function ErrorBannerFloat({
-// error,
-// onClear,
-// }: {
-// error: ErrorMessage;
-// onClear?: () => void;
-// }): VNode {
-// return (
-// <div
-// style={{
-// position: "fixed",
-// top: 10,
-// zIndex: 200,
-// width: "90%",
-// }}
-// >
-// <ErrorBanner error={error} onClear={onClear} />
-// </div>
-// );
-// }
function StatusBanner(): VNode {
const notifs = useNotifications()
@@ -469,5 +466,5 @@ function AccountBalance({ account }: { account: string }): VNode {
{Amounts.currencyOf(result.data.balance.amount)}
&nbsp;{result.data.balance.credit_debit_indicator === "debit" ? "-" : ""}
{Amounts.stringifyValue(result.data.balance.amount)}
- </div>
+ </div>
}
diff --git a/packages/demobank-ui/src/pages/HomePage.tsx b/packages/demobank-ui/src/pages/HomePage.tsx
index 40cc147a6..2acfc9b57 100644
--- a/packages/demobank-ui/src/pages/HomePage.tsx
+++ b/packages/demobank-ui/src/pages/HomePage.tsx
@@ -52,21 +52,21 @@ const logger = new Logger("AccountPage");
export function HomePage({
onRegister,
account,
- onPendingOperationFound,
+ // onPendingOperationFound,
goToBusinessAccount,
}: {
account: string,
- onPendingOperationFound: (id: string) => void;
+ // onPendingOperationFound: (id: string) => void;
onRegister: () => void;
goToBusinessAccount: () => void;
}): VNode {
const [settings] = useSettings();
const { i18n } = useTranslationContext();
- if (settings.currentWithdrawalOperationId) {
- onPendingOperationFound(settings.currentWithdrawalOperationId);
- return <Loading />;
- }
+ // if (settings.currentWithdrawalOperationId) {
+ // onPendingOperationFound(settings.currentWithdrawalOperationId);
+ // return <Loading />;
+ // }
return (
<AccountPage
@@ -79,11 +79,9 @@ export function HomePage({
export function WithdrawalOperationPage({
operationId,
- onLoadNotOk,
onContinue,
}: {
operationId: string;
- onLoadNotOk: () => void;
onContinue: () => void;
}): VNode {
//FIXME: libeufin sandbox should return show to create the integration api endpoint
@@ -95,6 +93,7 @@ export function WithdrawalOperationPage({
});
const parsedUri = parseWithdrawUri(uri);
const { i18n } = useTranslationContext();
+ const [settings, updateSettings] = useSettings();
if (!parsedUri) {
notifyError(
@@ -107,8 +106,9 @@ export function WithdrawalOperationPage({
return (
<WithdrawalQRCode
withdrawUri={parsedUri}
- onContinue={onContinue}
- onLoadNotOk={onLoadNotOk}
+ onClose={() => {
+ updateSettings("currentWithdrawalOperationId", undefined)
+ }}
/>
);
}
diff --git a/packages/demobank-ui/src/pages/PaymentOptions.tsx b/packages/demobank-ui/src/pages/PaymentOptions.tsx
index 1728074a3..573f8c769 100644
--- a/packages/demobank-ui/src/pages/PaymentOptions.tsx
+++ b/packages/demobank-ui/src/pages/PaymentOptions.tsx
@@ -34,80 +34,83 @@ export function PaymentOptions({ limit }: { limit: AmountJson }): VNode {
// const [tab, setTab] = useState<"charge-wallet" | "wire-transfer" | undefined>(undefined);
return (
- <fieldset>
- <legend class="px-4 text-base font-semibold leading-6 text-gray-900">
- <i18n.Translate>Send money to</i18n.Translate>
- </legend>
+ <div class="mt-2">
- <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" + (tab === "charge-wallet" ? "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" onClick={() => {
- setTab("charge-wallet")
- }} />
- <span class="flex flex-1">
- <div class="text-lg mr-2">&#x1F4B5;</div>
- <span class="flex flex-col">
- <span id="project-type-0-label" class="block text-sm font-medium text-gray-900">
- <i18n.Translate>a <b>Taler</b> wallet</i18n.Translate>
- </span>
- <span id="project-type-0-description-0" class="mt-1 flex items-center text-sm text-gray-500">
- <i18n.Translate>Withdraw digital money into your mobile wallet or browser extension</i18n.Translate>
+ <fieldset>
+ <legend class="px-4 text-base font-semibold leading-6 text-gray-900">
+ <i18n.Translate>Send money to</i18n.Translate>
+ </legend>
+
+ <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" + (tab === "charge-wallet" ? "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" onClick={() => {
+ setTab("charge-wallet")
+ }} />
+ <span class="flex flex-1">
+ <div class="text-lg mr-2">&#x1F4B5;</div>
+ <span class="flex flex-col">
+ <span id="project-type-0-label" class="block text-sm font-medium text-gray-900">
+ <i18n.Translate>a <b>Taler</b> wallet</i18n.Translate>
+ </span>
+ <span id="project-type-0-description-0" class="mt-1 flex items-center text-sm text-gray-500">
+ <i18n.Translate>Withdraw digital money into your mobile wallet or browser extension</i18n.Translate>
+ </span>
</span>
</span>
- </span>
- <svg class="h-5 w-5 text-indigo-600" style={{ visibility: tab === "charge-wallet" ? "visible" : "hidden" }} viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
- <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
- </svg>
- </label>
+ <svg class="h-5 w-5 text-indigo-600" style={{ visibility: tab === "charge-wallet" ? "visible" : "hidden" }} viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
+ <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
+ </svg>
+ </label>
- <label class={"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none" + (tab === "wire-transfer" ? "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" onClick={() => {
- setTab("wire-transfer")
- }} />
- <span class="flex flex-1">
- <div class="text-lg mr-2">&#x2194;</div>
- <span class="flex flex-col">
- <span id="project-type-1-label" class="block text-sm font-medium text-gray-900">
- <i18n.Translate>another bank account</i18n.Translate>
- </span>
- <span id="project-type-1-description-0" class="mt-1 flex items-center text-sm text-gray-500">
- <i18n.Translate>Make a wire transfer to an account which you know the address.</i18n.Translate>
+ <label class={"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none" + (tab === "wire-transfer" ? "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" onClick={() => {
+ setTab("wire-transfer")
+ }} />
+ <span class="flex flex-1">
+ <div class="text-lg mr-2">&#x2194;</div>
+ <span class="flex flex-col">
+ <span id="project-type-1-label" class="block text-sm font-medium text-gray-900">
+ <i18n.Translate>another bank account</i18n.Translate>
+ </span>
+ <span id="project-type-1-description-0" class="mt-1 flex items-center text-sm text-gray-500">
+ <i18n.Translate>Make a wire transfer to an account which you know the address.</i18n.Translate>
+ </span>
</span>
</span>
- </span>
- <svg class="h-5 w-5 text-indigo-600" style={{ visibility: tab === "wire-transfer" ? "visible" : "hidden" }} viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
- <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
- </svg>
- </label>
- </div>
- {tab === "charge-wallet" && (
- <WalletWithdrawForm
- focus
- limit={limit}
- onSuccess={(id) => {
- updateSettings("currentWithdrawalOperationId", id);
- }}
- onCancel={() => {
- setTab(undefined)
- }}
- />
- )}
- {tab === "wire-transfer" && (
- <PaytoWireTransferForm
- focus
- title={i18n.str`Transfer details`}
- limit={limit}
- onSuccess={() => {
- notifyInfo(i18n.str`Wire transfer created!`);
- }}
- onCancel={() => {
- setTab(undefined)
- }}
- />
- )}
+ <svg class="h-5 w-5 text-indigo-600" style={{ visibility: tab === "wire-transfer" ? "visible" : "hidden" }} viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
+ <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
+ </svg>
+ </label>
+ </div>
+ {tab === "charge-wallet" && (
+ <WalletWithdrawForm
+ focus
+ limit={limit}
+ onSuccess={(id) => {
+ updateSettings("currentWithdrawalOperationId", id);
+ }}
+ onCancel={() => {
+ setTab(undefined)
+ }}
+ />
+ )}
+ {tab === "wire-transfer" && (
+ <PaytoWireTransferForm
+ focus
+ title={i18n.str`Transfer details`}
+ limit={limit}
+ onSuccess={() => {
+ notifyInfo(i18n.str`Wire transfer created!`);
+ }}
+ onCancel={() => {
+ setTab(undefined)
+ }}
+ />
+ )}
- </fieldset>
+ </fieldset>
+ </div>
)
}
diff --git a/packages/demobank-ui/src/pages/QrCodeSection.tsx b/packages/demobank-ui/src/pages/QrCodeSection.tsx
index 7c1b3bdc5..416c714e2 100644
--- a/packages/demobank-ui/src/pages/QrCodeSection.tsx
+++ b/packages/demobank-ui/src/pages/QrCodeSection.tsx
@@ -135,3 +135,109 @@ export function QrCodeSection({
</Fragment>
);
}
+
+
+export function QrCodeSectionSimpler({
+ withdrawUri,
+ onAborted,
+}: {
+ withdrawUri: WithdrawUriResult;
+ onAborted: () => void;
+}): VNode {
+ const { i18n } = useTranslationContext();
+ useEffect(() => {
+ //Taler Wallet WebExtension is listening to headers response and tab updates.
+ //In the SPA there is no header response with the Taler URI so
+ //this hack manually triggers the tab update after the QR is in the DOM.
+ // WebExtension will be using
+ // https://developer.chrome.com/docs/extensions/reference/tabs/#event-onUpdated
+ document.title = `${document.title} ${withdrawUri.withdrawalOperationId}`;
+ }, []);
+ const talerWithdrawUri = stringifyWithdrawUri(withdrawUri);
+
+ const { abortWithdrawal } = useAccessAnonAPI();
+
+ async function doAbort() {
+ try {
+ await abortWithdrawal(withdrawUri.withdrawalOperationId);
+ onAborted();
+ } catch (error) {
+ if (error instanceof RequestError) {
+ notify(
+ buildRequestErrorMessage(i18n, error.cause, {
+ onClientError: (status) =>
+ status === HttpStatusCode.Conflict
+ ? i18n.str`The reserve operation has been confirmed previously and can't be aborted`
+ : undefined,
+ }),
+ );
+ } else {
+ notifyError(
+ i18n.str`Operation failed, please report`,
+ (error instanceof Error
+ ? error.message
+ : JSON.stringify(error)) as TranslatedString
+ )
+ }
+ }
+ }
+
+ return (
+ <Fragment>
+ <div class="bg-white shadow-xl sm:rounded-lg">
+ <div class="p2 ">
+ <h3 class="text-base font-semibold leading-6 text-gray-900">
+ <i18n.Translate>If you have a Taler wallet installed in this device</i18n.Translate>
+ </h3>
+ <div class="mt-4">
+ <a href={talerWithdrawUri}
+ // class="text-sm font-semibold leading-6 text-gray-900 btn "
+ class="inline-flex items-center 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"
+ >
+ <i18n.Translate>Click here to start</i18n.Translate>
+ </a>
+ </div>
+ <div class="mt-4 max-w-xl text-sm text-gray-500">
+ <p><i18n.Translate>
+ You will see the details of the operation in your wallet including the fees (if applies).
+ If you still one you can install it from <a class="font-semibold text-gray-500 hover:text-gray-400" href="https://taler.net/en/wallet.html">here</a>.
+ </i18n.Translate></p>
+ </div>
+ <div class="flex items-center justify-between gap-x-6 border-t border-gray-900/10 pt-2 mt-2 ">
+ <div />
+ <button type="button"
+ class="disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600"
+ onClick={doAbort}
+ >
+ Cancel withdrawal
+ </button>
+ </div>
+ </div>
+ </div>
+
+ <div class="bg-white shadow-xl sm:rounded-lg mt-8">
+ <div class="px-4 py-5 sm:p-6">
+ <h3 class="text-base font-semibold leading-6 text-gray-900">
+ <i18n.Translate>Or if you have the wallet in another device</i18n.Translate>
+ </h3>
+ <div class="mt-4 max-w-xl text-sm text-gray-500">
+ <i18n.Translate>Scan the QR below to start the withdrawal</i18n.Translate>
+ </div>
+ <div class="mt-2 max-w-md ml-auto mr-auto">
+ <QR text={talerWithdrawUri} />
+ </div>
+ </div>
+ <div class="flex items-center justify-center gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8">
+ <button type="button"
+ class="disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600"
+ onClick={doAbort}
+ >
+ Cancel withdrawal
+ </button>
+ </div>
+ </div>
+
+ </Fragment>
+ );
+}
+
diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
index 8c41f7576..08f706919 100644
--- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
+++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
@@ -20,6 +20,7 @@ import {
HttpStatusCode,
Logger,
TranslatedString,
+ WithdrawUriResult,
parseWithdrawUri,
} from "@gnu-taler/taler-util";
import {
@@ -34,6 +35,9 @@ import { useEffect, useRef, useState } from "preact/hooks";
import { useAccessAPI } from "../hooks/access.js";
import { buildRequestErrorMessage, undefinedIfEmpty } from "../utils.js";
import { Amount } from "./PaytoWireTransferForm.js";
+import { useSettings } from "../hooks/settings.js";
+import { WithdrawalOperationState } from "./WithdrawalQRCode.js";
+import { Loading } from "../components/Loading.js";
const logger = new Logger("WalletWithdrawForm");
const RefAmount = forwardRef(Amount);
@@ -51,8 +55,9 @@ export function WalletWithdrawForm({
}): VNode {
const { i18n } = useTranslationContext();
const { createWithdrawal } = useAccessAPI();
+ const [settings, updateSettings] = useSettings()
- const [amountStr, setAmountStr] = useState<string | undefined>("5.00");
+ const [amountStr, setAmountStr] = useState<string | undefined>(`${settings.maxWithdrawalAmount}`);
const ref = useRef<HTMLInputElement>(null);
useEffect(() => {
if (focus) ref.current?.focus();
@@ -78,7 +83,6 @@ export function WalletWithdrawForm({
async function doStart() {
if (!parsedAmount) return;
try {
- console.log("ASDASD")
const result = await createWithdrawal({
amount: Amounts.stringify(parsedAmount),
});
@@ -109,7 +113,6 @@ export function WalletWithdrawForm({
)
}
}
-
}
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">
@@ -122,91 +125,103 @@ export function WalletWithdrawForm({
<i18n.Translate>After using your wallet you will be redirected here to confirm or cancel the operation.</i18n.Translate>
</p>
</div>
- <form
- 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()
- }}
- >
- <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-6 py-4 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-6 py-4 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")
- }}
- >
-
- 25.00
- </button>
- <button type="button"
- class="relative -ml-px -mr-px inline-flex px-6 py-4 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-6 py-4 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")
+
+ {!settings.fastWithdrawal ?
+ <form
+ 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()
+ }}
+ >
+ <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);
}}
- >
- 5.00
- </button>
- </span>
- </div>
+ 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-6 py-4 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-6 py-4 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")
+ }}
+ >
+
+ 25.00
+ </button>
+ <button type="button"
+ class="relative -ml-px -mr-px inline-flex px-6 py-4 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-6 py-4 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>
- </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>
- </form>
+ </form>
+ : settings.currentWithdrawalOperationId === undefined ?
+ <Loading /> :
+ <WithdrawalOperationState
+ currentOperation={settings.currentWithdrawalOperationId}
+ currency={limit.currency}
+ onClose={() => {
+ onCancel()
+ }}
+ />
+ }
</div>
);
}
diff --git a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
index 2a3a1ec2c..9976babdb 100644
--- a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
@@ -18,24 +18,29 @@ import {
Amounts,
HttpStatusCode,
Logger,
+ TranslatedString,
WithdrawUriResult,
parsePaytoUri,
+ parseWithdrawUri,
+ stringifyWithdrawUri,
} from "@gnu-taler/taler-util";
-import { ErrorType, notifyInfo, useTranslationContext } from "@gnu-taler/web-util/browser";
+import { ErrorType, RequestError, notify, notifyError, notifyInfo, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { Loading } from "../components/Loading.js";
-import { useWithdrawalDetails } from "../hooks/access.js";
+import { useAccessAPI, useWithdrawalDetails } from "../hooks/access.js";
import { useSettings } from "../hooks/settings.js";
import { handleNotOkResult } from "./HomePage.js";
-import { QrCodeSection } from "./QrCodeSection.js";
+import { QrCodeSection, QrCodeSectionSimpler } from "./QrCodeSection.js";
import { WithdrawalConfirmationQuestion } from "./WithdrawalConfirmationQuestion.js";
+import { useEffect, useState } from "preact/hooks";
+import { buildRequestErrorMessage } from "../utils.js";
+import { getInitialBackendBaseURL } from "../hooks/backend.js";
const logger = new Logger("WithdrawalQRCode");
interface Props {
withdrawUri: WithdrawUriResult;
- onContinue: () => void;
- onLoadNotOk: () => void;
+ onClose: () => void;
}
/**
* Offer the QR code (and a clickable taler://-link) to
@@ -44,14 +49,9 @@ interface Props {
*/
export function WithdrawalQRCode({
withdrawUri,
- onContinue,
- onLoadNotOk,
+ onClose,
}: Props): VNode {
const [settings, updateSettings] = useSettings();
- function clearCurrentWithdrawal(): void {
- updateSettings("currentWithdrawalOperationId", undefined);
- onContinue();
- }
const { i18n } = useTranslationContext();
const result = useWithdrawalDetails(withdrawUri.withdrawalOperationId);
if (!result.ok) {
@@ -62,7 +62,7 @@ export function WithdrawalQRCode({
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
) {
- clearCurrentWithdrawal()
+ onClose()
return <div>operation not found</div>;
}
// onLoadNotOk();
@@ -89,8 +89,7 @@ export function WithdrawalQRCode({
style={{ float: "right" }}
onClick={async (e) => {
e.preventDefault();
- clearCurrentWithdrawal()
- onContinue()
+ onClose()
}}>
{i18n.str`Continue`}
</a>
@@ -149,8 +148,7 @@ export function WithdrawalQRCode({
class="inline-flex w-full justify-center 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"
onClick={async (e) => {
e.preventDefault();
- clearCurrentWithdrawal()
- onContinue()
+ onClose()
}}>
<i18n.Translate>Continue</i18n.Translate>
</button>
@@ -165,8 +163,7 @@ export function WithdrawalQRCode({
withdrawUri={withdrawUri}
onAborted={() => {
notifyInfo(i18n.str`Operation canceled`);
- clearCurrentWithdrawal()
- onContinue()
+ onClose()
}}
/>
);
@@ -196,9 +193,131 @@ export function WithdrawalQRCode({
}}
onAborted={() => {
notifyInfo(i18n.str`Operation canceled`);
- clearCurrentWithdrawal()
- onContinue()
+ onClose()
}}
/>
);
+}
+
+
+export function WithdrawalOperationState({
+ currency,
+ currentOperation,
+ onClose,
+}: {currency:string, currentOperation: string, onClose: () => void}): VNode {
+ const { i18n } = useTranslationContext();
+ const [settings, updateSettings] = useSettings()
+ const { createWithdrawal } = useAccessAPI();
+
+ const amount = settings.maxWithdrawalAmount
+ async function doSilentStart() {
+ //FIXME: if amount is not enough use balance
+ const parsedAmount = Amounts.parseOrThrow(`${currency}:${amount}`)
+
+ 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 {
+ updateSettings("currentWithdrawalOperationId", 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
+ )
+ }
+ }
+ }
+
+ useEffect(() => {
+ doSilentStart()
+ }, [settings.fastWithdrawal, amount])
+
+ const result = useWithdrawalDetails(currentOperation);
+ if (!result.ok) {
+ if (result.loading) {
+ return <Loading />;
+ }
+ if (
+ result.type === ErrorType.CLIENT &&
+ result.status === HttpStatusCode.NotFound
+ ) {
+ onClose()
+ return <div>operation not found</div>;
+ }
+ // onLoadNotOk();
+ return handleNotOkResult(i18n)(result);
+ }
+ const { data } = result;
+
+ const baseUrl = getInitialBackendBaseURL()
+ const uri = stringifyWithdrawUri({
+ bankIntegrationApiBaseUrl: `${baseUrl}/integration-api`,
+ withdrawalOperationId: currentOperation,
+ });
+ const parsedUri = parseWithdrawUri(uri);
+
+ if (data.aborted) {
+ return <div>
+ the operation was aborted, you can create another one
+ </div>
+ }
+
+ if (data.confirmation_done) {
+ return <div>
+ the wire transfer is made, you coin should arrive shortly
+ </div>
+ }
+ if (!parsedUri) {
+ return <div>
+ the operation is not valid, create another one
+ </div>
+ }
+ if (!data.selection_done) {
+ return (
+ <QrCodeSectionSimpler
+ withdrawUri={parsedUri}
+ onAborted={() => {
+ notifyInfo(i18n.str`Operation canceled`);
+ onClose()
+ }}
+ />
+ );
+ }
+
+ if (!data.selected_reserve_pub) {
+ return <div>
+ the exchange is selcted but no reserve pub
+ </div>
+ }
+
+ const account = !data.selected_exchange_account ? undefined : parsePaytoUri(data.selected_exchange_account)
+
+ if (!account) {
+ return <div>
+ the exchange is selected but no account
+ </div>
+ }
+
+ return <div>
+ the operation is wating for the question to be answered
+ </div>;
} \ No newline at end of file
diff --git a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
index 050f1fb8a..1e5370afc 100644
--- a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
+++ b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
@@ -61,7 +61,7 @@ export function RemoveAccount({
</h3>
<div class="mt-2 text-sm text-yellow-700">
<p>
- <i18n.Translate>The account can be delete while still holding some balance. First make sure that the owner make a complete cashout.</i18n.Translate>
+ <i18n.Translate>The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.</i18n.Translate>
</p>
</div>
</div>