summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/cta
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2021-08-19 00:34:47 -0300
committerSebastian <sebasjm@gmail.com>2021-08-19 00:35:21 -0300
commit97a05ff659af274dcfcd9c76bf19100bbd51ce0e (patch)
tree9cce837ec9a5ec06279dc48eac75e1993ede983f /packages/taler-wallet-webextension/src/cta
parentb015f76e7268cb5caff14a0ed88cb5e8fa53dc2e (diff)
downloadwallet-core-97a05ff659af274dcfcd9c76bf19100bbd51ce0e.tar.gz
wallet-core-97a05ff659af274dcfcd9c76bf19100bbd51ce0e.tar.bz2
wallet-core-97a05ff659af274dcfcd9c76bf19100bbd51ce0e.zip
new wallet history and view refactoring
Diffstat (limited to 'packages/taler-wallet-webextension/src/cta')
-rw-r--r--packages/taler-wallet-webextension/src/cta/Pay.stories.tsx96
-rw-r--r--packages/taler-wallet-webextension/src/cta/Pay.tsx253
-rw-r--r--packages/taler-wallet-webextension/src/cta/Refund.stories.tsx77
-rw-r--r--packages/taler-wallet-webextension/src/cta/Refund.tsx95
-rw-r--r--packages/taler-wallet-webextension/src/cta/Tip.stories.tsx59
-rw-r--r--packages/taler-wallet-webextension/src/cta/Tip.tsx110
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx45
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw.tsx172
-rw-r--r--packages/taler-wallet-webextension/src/cta/payback.tsx31
-rw-r--r--packages/taler-wallet-webextension/src/cta/reset-required.tsx97
-rw-r--r--packages/taler-wallet-webextension/src/cta/return-coins.tsx30
11 files changed, 1065 insertions, 0 deletions
diff --git a/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx b/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
new file mode 100644
index 000000000..38e3d0f35
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
@@ -0,0 +1,96 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { ContractTerms, PreparePayResultType } from '@gnu-taler/taler-util';
+import { createExample } from '../test-utils';
+import { PaymentRequestView as TestedComponent } from './Pay';
+
+export default {
+ title: 'cta/pay',
+ component: TestedComponent,
+ argTypes: {
+ },
+};
+
+export const InsufficientBalance = createExample(TestedComponent, {
+ payStatus: {
+ status: PreparePayResultType.InsufficientBalance,
+ proposalId: "proposal1234",
+ contractTerms: {
+ merchant: {
+ name: 'someone'
+ },
+ amount: 'USD:10',
+ } as Partial<ContractTerms> as any,
+ amountRaw: 'USD:10',
+ }
+});
+
+export const PaymentPossible = createExample(TestedComponent, {
+ payStatus: {
+ status: PreparePayResultType.PaymentPossible,
+ amountEffective: 'USD:10',
+ amountRaw: 'USD:10',
+ contractTerms: {
+ merchant: {
+ name: 'someone'
+ },
+ amount: 'USD:10',
+ } as Partial<ContractTerms> as any,
+ contractTermsHash: '123456',
+ proposalId: 'proposal1234'
+ }
+});
+
+export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
+ payStatus: {
+ status: PreparePayResultType.AlreadyConfirmed,
+ amountEffective: 'USD:10',
+ amountRaw: 'USD:10',
+ contractTerms: {
+ merchant: {
+ name: 'someone'
+ },
+ fulfillment_message: 'congratulations! you are looking at the fulfillment message! ',
+ amount: 'USD:10',
+ } as Partial<ContractTerms> as any,
+ contractTermsHash: '123456',
+ proposalId: 'proposal1234',
+ paid: false,
+ }
+});
+
+export const AlreadyConfirmedWithoutFullfilment = createExample(TestedComponent, {
+ payStatus: {
+ status: PreparePayResultType.AlreadyConfirmed,
+ amountEffective: 'USD:10',
+ amountRaw: 'USD:10',
+ contractTerms: {
+ merchant: {
+ name: 'someone'
+ },
+ amount: 'USD:10',
+ } as Partial<ContractTerms> as any,
+ contractTermsHash: '123456',
+ proposalId: 'proposal1234',
+ paid: false,
+ }
+});
diff --git a/packages/taler-wallet-webextension/src/cta/Pay.tsx b/packages/taler-wallet-webextension/src/cta/Pay.tsx
new file mode 100644
index 000000000..a5849bb28
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/Pay.tsx
@@ -0,0 +1,253 @@
+/*
+ This file is part of TALER
+ (C) 2015 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Page shown to the user to confirm entering
+ * a contract.
+ */
+
+/**
+ * Imports.
+ */
+// import * as i18n from "../i18n";
+
+import { renderAmount, ProgressButton } from "../renderHtml";
+import * as wxApi from "../wxApi";
+
+import { useState, useEffect } from "preact/hooks";
+
+import { ConfirmPayResultDone, getJsonI18n, i18n } from "@gnu-taler/taler-util";
+import {
+ PreparePayResult,
+ ConfirmPayResult,
+ AmountJson,
+ PreparePayResultType,
+ Amounts,
+ ContractTerms,
+ ConfirmPayResultType,
+} from "@gnu-taler/taler-util";
+import { JSX, VNode } from "preact";
+
+interface Props {
+ talerPayUri?: string
+}
+
+export function AlreadyPaid({ payStatus }: { payStatus: PreparePayResult }) {
+ const fulfillmentUrl = payStatus.contractTerms.fulfillment_url;
+ let message;
+ if (fulfillmentUrl) {
+ message = (
+ <span>
+ You have already paid for this article. Click{" "}
+ <a href={fulfillmentUrl} target="_bank" rel="external">here</a> to view it again.
+ </span>
+ );
+ } else {
+ message = <span>
+ You have already paid for this article:{" "}
+ <em>
+ {payStatus.contractTerms.fulfillment_message ?? "no message given"}
+ </em>
+ </span>;
+ }
+ return <section class="main">
+ <h1>GNU Taler Wallet</h1>
+ <article class="fade">
+ {message}
+ </article>
+ </section>
+}
+
+const doPayment = async (payStatus: PreparePayResult): Promise<ConfirmPayResultDone> => {
+ if (payStatus.status !== "payment-possible") {
+ throw Error(`invalid state: ${payStatus.status}`);
+ }
+ const proposalId = payStatus.proposalId;
+ const res = await wxApi.confirmPay(proposalId, undefined);
+ if (res.type !== ConfirmPayResultType.Done) {
+ throw Error("payment pending");
+ }
+ const fu = res.contractTerms.fulfillment_url;
+ if (fu) {
+ document.location.href = fu;
+ }
+ return res;
+};
+
+
+
+export function PayPage({ talerPayUri }: Props): JSX.Element {
+ const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>(undefined);
+ const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>(undefined);
+ const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
+
+ useEffect(() => {
+ if (!talerPayUri) return;
+ const doFetch = async (): Promise<void> => {
+ const p = await wxApi.preparePay(talerPayUri);
+ setPayStatus(p);
+ };
+ doFetch();
+ }, [talerPayUri]);
+
+ if (!talerPayUri) {
+ return <span>missing pay uri</span>
+ }
+
+ if (!payStatus) {
+ return <span>Loading payment information ...</span>;
+ }
+
+ if (payResult && payResult.type === ConfirmPayResultType.Done) {
+ if (payResult.contractTerms.fulfillment_message) {
+ const obj = {
+ fulfillment_message: payResult.contractTerms.fulfillment_message,
+ fulfillment_message_i18n:
+ payResult.contractTerms.fulfillment_message_i18n,
+ };
+ const msg = getJsonI18n(obj, "fulfillment_message");
+ return (
+ <div>
+ <p>Payment succeeded.</p>
+ <p>{msg}</p>
+ </div>
+ );
+ } else {
+ return <span>Redirecting ...</span>;
+ }
+ }
+
+ const onClick = async () => {
+ try {
+ const res = await doPayment(payStatus)
+ setPayResult(res);
+ } catch (e) {
+ console.error(e);
+ setPayErrMsg(e.message);
+ }
+
+ }
+
+ return <PaymentRequestView payStatus={payStatus} onClick={onClick} payErrMsg={payErrMsg} />;
+}
+
+export interface PaymentRequestViewProps {
+ payStatus: PreparePayResult;
+ onClick: () => void;
+ payErrMsg?: string;
+
+}
+export function PaymentRequestView({ payStatus, onClick, payErrMsg }: PaymentRequestViewProps) {
+ let totalFees: AmountJson | undefined = undefined;
+ let insufficientBalance = false;
+ const [loading, setLoading] = useState(false);
+ const contractTerms: ContractTerms = payStatus.contractTerms;
+
+ if (
+ payStatus.status === PreparePayResultType.AlreadyConfirmed
+ ) {
+ return <AlreadyPaid payStatus={payStatus} />
+ }
+
+ if (!contractTerms) {
+ return (
+ <span>
+ Error: did not get contract terms from merchant or wallet backend.
+ </span>
+ );
+ }
+
+ if (payStatus.status == PreparePayResultType.InsufficientBalance) {
+ insufficientBalance = true;
+ }
+
+ if (payStatus.status === PreparePayResultType.PaymentPossible) {
+ const amountRaw = Amounts.parseOrThrow(payStatus.amountRaw);
+ const amountEffective: AmountJson = Amounts.parseOrThrow(
+ payStatus.amountEffective,
+ );
+ totalFees = Amounts.sub(amountEffective, amountRaw).amount;
+ }
+
+ let merchantName: VNode;
+ if (contractTerms.merchant && contractTerms.merchant.name) {
+ merchantName = <strong>{contractTerms.merchant.name}</strong>;
+ } else {
+ merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>;
+ }
+
+ const amount = (
+ <strong>{renderAmount(Amounts.parseOrThrow(contractTerms.amount))}</strong>
+ );
+
+ return <section class="main">
+ <h1>GNU Taler Wallet</h1>
+ <article class="fade">
+ <div>
+ <p>
+ <i18n.Translate>
+ The merchant <span>{merchantName}</span> offers you to purchase:
+ </i18n.Translate>
+ <div style={{ textAlign: "center" }}>
+ <strong>{contractTerms.summary}</strong>
+ </div>
+ {totalFees ? (
+ <i18n.Translate>
+ The total price is <span>{amount} </span>
+ (plus <span>{renderAmount(totalFees)}</span> fees).
+ </i18n.Translate>
+ ) : (
+ <i18n.Translate>
+ The total price is <span>{amount}</span>.
+ </i18n.Translate>
+ )}
+ </p>
+
+ {insufficientBalance ? (
+ <div>
+ <p style={{ color: "red", fontWeight: "bold" }}>
+ Unable to pay: Your balance is insufficient.
+ </p>
+ </div>
+ ) : null}
+
+ {payErrMsg ? (
+ <div>
+ <p>Payment failed: {payErrMsg}</p>
+ <button
+ class="pure-button button-success"
+ onClick={onClick}
+ >
+ {i18n.str`Retry`}
+ </button>
+ </div>
+ ) : (
+ <div>
+ <ProgressButton
+ isLoading={loading}
+ disabled={insufficientBalance}
+ onClick={onClick}
+ >
+ {i18n.str`Confirm payment`}
+ </ProgressButton>
+ </div>
+ )}
+ </div>
+ </article>
+ </section>
+
+
+} \ No newline at end of file
diff --git a/packages/taler-wallet-webextension/src/cta/Refund.stories.tsx b/packages/taler-wallet-webextension/src/cta/Refund.stories.tsx
new file mode 100644
index 000000000..88e714cb7
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/Refund.stories.tsx
@@ -0,0 +1,77 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { OrderShortInfo } from '@gnu-taler/taler-util';
+import { createExample } from '../test-utils';
+import { View as TestedComponent } from './Refund';
+
+
+export default {
+ title: 'cta/refund',
+ component: TestedComponent,
+ argTypes: {
+ },
+};
+
+export const Complete = createExample(TestedComponent, {
+ applyResult: {
+ amountEffectivePaid: 'USD:10',
+ amountRefundGone: 'USD:0',
+ amountRefundGranted: 'USD:2',
+ contractTermsHash: 'QWEASDZXC',
+ info: {
+ summary: 'tasty cold beer',
+ contractTermsHash: 'QWEASDZXC',
+ } as Partial<OrderShortInfo> as any,
+ pendingAtExchange: false,
+ proposalId: "proposal123",
+ }
+});
+
+export const Partial = createExample(TestedComponent, {
+ applyResult: {
+ amountEffectivePaid: 'USD:10',
+ amountRefundGone: 'USD:1',
+ amountRefundGranted: 'USD:2',
+ contractTermsHash: 'QWEASDZXC',
+ info: {
+ summary: 'tasty cold beer',
+ contractTermsHash: 'QWEASDZXC',
+ } as Partial<OrderShortInfo> as any,
+ pendingAtExchange: false,
+ proposalId: "proposal123",
+ }
+});
+
+export const InProgress = createExample(TestedComponent, {
+ applyResult: {
+ amountEffectivePaid: 'USD:10',
+ amountRefundGone: 'USD:1',
+ amountRefundGranted: 'USD:2',
+ contractTermsHash: 'QWEASDZXC',
+ info: {
+ summary: 'tasty cold beer',
+ contractTermsHash: 'QWEASDZXC',
+ } as Partial<OrderShortInfo> as any,
+ pendingAtExchange: true,
+ proposalId: "proposal123",
+ }
+});
diff --git a/packages/taler-wallet-webextension/src/cta/Refund.tsx b/packages/taler-wallet-webextension/src/cta/Refund.tsx
new file mode 100644
index 000000000..bb26d933b
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/Refund.tsx
@@ -0,0 +1,95 @@
+/*
+ This file is part of TALER
+ (C) 2015-2016 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Page that shows refund status for purchases.
+ *
+ * @author Florian Dold
+ */
+
+import * as wxApi from "../wxApi";
+import { AmountView } from "../renderHtml";
+import {
+ ApplyRefundResponse,
+ Amounts,
+} from "@gnu-taler/taler-util";
+import { useEffect, useState } from "preact/hooks";
+import { JSX } from "preact/jsx-runtime";
+
+interface Props {
+ talerRefundUri?: string
+}
+export interface ViewProps {
+ applyResult: ApplyRefundResponse;
+}
+export function View({ applyResult }: ViewProps) {
+ return <section class="main">
+ <h1>GNU Taler Wallet</h1>
+ <article class="fade">
+ <h2>Refund Status</h2>
+ <p>
+ The product <em>{applyResult.info.summary}</em> has received a total
+ effective refund of{" "}
+ <AmountView amount={applyResult.amountRefundGranted} />.
+ </p>
+ {applyResult.pendingAtExchange ? (
+ <p>Refund processing is still in progress.</p>
+ ) : null}
+ {!Amounts.isZero(applyResult.amountRefundGone) ? (
+ <p>
+ The refund amount of{" "}
+ <AmountView amount={applyResult.amountRefundGone} />{" "}
+ could not be applied.
+ </p>
+ ) : null}
+ </article>
+ </section>
+}
+export function RefundPage({ talerRefundUri }: Props): JSX.Element {
+ const [applyResult, setApplyResult] = useState<ApplyRefundResponse | undefined>(undefined);
+ const [errMsg, setErrMsg] = useState<string | undefined>(undefined);
+
+ useEffect(() => {
+ if (!talerRefundUri) return;
+ const doFetch = async (): Promise<void> => {
+ try {
+ const result = await wxApi.applyRefund(talerRefundUri);
+ setApplyResult(result);
+ } catch (e) {
+ console.error(e);
+ setErrMsg(e.message);
+ console.log("err message", e.message);
+ }
+ };
+ doFetch();
+ }, [talerRefundUri]);
+
+ console.log("rendering");
+
+ if (!talerRefundUri) {
+ return <span>missing taler refund uri</span>;
+ }
+
+ if (errMsg) {
+ return <span>Error: {errMsg}</span>;
+ }
+
+ if (!applyResult) {
+ return <span>Updating refund status</span>;
+ }
+
+ return <View applyResult={applyResult} />;
+}
diff --git a/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx b/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx
new file mode 100644
index 000000000..389b183f0
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx
@@ -0,0 +1,59 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample } from '../test-utils';
+import { View as TestedComponent } from './Tip';
+
+
+export default {
+ title: 'cta/tip',
+ component: TestedComponent,
+ argTypes: {
+ },
+};
+
+export const Accepted = createExample(TestedComponent, {
+ prepareTipResult: {
+ accepted: true,
+ merchantBaseUrl: '',
+ exchangeBaseUrl: '',
+ expirationTimestamp : {
+ t_ms: 0
+ },
+ tipAmountEffective: 'USD:10',
+ tipAmountRaw: 'USD:5',
+ walletTipId: 'id'
+ }
+});
+
+export const NotYetAccepted = createExample(TestedComponent, {
+ prepareTipResult: {
+ accepted: false,
+ merchantBaseUrl: 'http://merchant.url/',
+ exchangeBaseUrl: 'http://exchange.url/',
+ expirationTimestamp : {
+ t_ms: 0
+ },
+ tipAmountEffective: 'USD:10',
+ tipAmountRaw: 'USD:5',
+ walletTipId: 'id'
+ }
+});
diff --git a/packages/taler-wallet-webextension/src/cta/Tip.tsx b/packages/taler-wallet-webextension/src/cta/Tip.tsx
new file mode 100644
index 000000000..69886668b
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/Tip.tsx
@@ -0,0 +1,110 @@
+/*
+ This file is part of TALER
+ (C) 2017 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Page shown to the user to accept or ignore a tip from a merchant.
+ *
+ * @author Florian Dold <dold@taler.net>
+ */
+
+import { useEffect, useState } from "preact/hooks";
+import { PrepareTipResult } from "@gnu-taler/taler-util";
+import { AmountView } from "../renderHtml";
+import * as wxApi from "../wxApi";
+import { JSX } from "preact/jsx-runtime";
+
+interface Props {
+ talerTipUri?: string
+}
+export interface ViewProps {
+ prepareTipResult: PrepareTipResult;
+ onAccept: () => void;
+ onIgnore: () => void;
+
+}
+export function View({ prepareTipResult, onAccept, onIgnore }: ViewProps) {
+ return <section class="main">
+ <h1>GNU Taler Wallet</h1>
+ <article class="fade">
+ {prepareTipResult.accepted ? (
+ <span>
+ Tip from <code>{prepareTipResult.merchantBaseUrl}</code> accepted. Check
+ your transactions list for more details.
+ </span>
+ ) : (
+ <div>
+ <p>
+ The merchant <code>{prepareTipResult.merchantBaseUrl}</code> is
+ offering you a tip of{" "}
+ <strong>
+ <AmountView amount={prepareTipResult.tipAmountEffective} />
+ </strong>{" "}
+ via the exchange <code>{prepareTipResult.exchangeBaseUrl}</code>
+ </p>
+ <button onClick={onAccept}>Accept tip</button>
+ <button onClick={onIgnore}>Ignore</button>
+ </div>
+ )}
+ </article>
+ </section>
+
+}
+
+export function TipPage({ talerTipUri }: Props): JSX.Element {
+ const [updateCounter, setUpdateCounter] = useState<number>(0);
+ const [prepareTipResult, setPrepareTipResult] = useState<
+ PrepareTipResult | undefined
+ >(undefined);
+
+ const [tipIgnored, setTipIgnored] = useState(false);
+
+ useEffect(() => {
+ if (!talerTipUri) return;
+ const doFetch = async (): Promise<void> => {
+ const p = await wxApi.prepareTip({ talerTipUri });
+ setPrepareTipResult(p);
+ };
+ doFetch();
+ }, [talerTipUri, updateCounter]);
+
+ const doAccept = async () => {
+ if (!prepareTipResult) {
+ return;
+ }
+ await wxApi.acceptTip({ walletTipId: prepareTipResult?.walletTipId });
+ setUpdateCounter(updateCounter + 1);
+ };
+
+ const doIgnore = () => {
+ setTipIgnored(true);
+ };
+
+ if (!talerTipUri) {
+ return <span>missing tip uri</span>;
+ }
+
+ if (tipIgnored) {
+ return <span>You've ignored the tip.</span>;
+ }
+
+ if (!prepareTipResult) {
+ return <span>Loading ...</span>;
+ }
+
+ return <View prepareTipResult={prepareTipResult}
+ onAccept={doAccept} onIgnore={doIgnore}
+ />
+}
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
new file mode 100644
index 000000000..747f855fa
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
@@ -0,0 +1,45 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample } from '../test-utils';
+import { View as TestedComponent } from './Withdraw';
+
+
+export default {
+ title: 'cta/withdraw',
+ component: TestedComponent,
+ argTypes: {
+ },
+};
+
+export const CompleteWithExchange = createExample(TestedComponent, {
+ details: {
+ amount: 'USD:2',
+ possibleExchanges: [],
+ },
+ selectedExchange: 'Some exchange'
+})
+export const CompleteWithoutExchange = createExample(TestedComponent, {
+ details: {
+ amount: 'USD:2',
+ possibleExchanges: [],
+ },
+})
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
new file mode 100644
index 000000000..b5182b070
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
@@ -0,0 +1,172 @@
+/*
+ This file is part of TALER
+ (C) 2015-2016 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Page shown to the user to confirm creation
+ * of a reserve, usually requested by the bank.
+ *
+ * @author Florian Dold
+ */
+
+import { i18n } from '@gnu-taler/taler-util'
+import { renderAmount } from "../renderHtml";
+
+import { useState, useEffect } from "preact/hooks";
+import {
+ acceptWithdrawal,
+ onUpdateNotification,
+ getWithdrawalDetailsForUri,
+} from "../wxApi";
+import { WithdrawUriInfoResponse } from "@gnu-taler/taler-util";
+import { JSX } from "preact/jsx-runtime";
+import { WalletAction } from '../components/styled';
+
+interface Props {
+ talerWithdrawUri?: string;
+}
+
+export interface ViewProps {
+ details: WithdrawUriInfoResponse;
+ selectedExchange?: string;
+ accept: () => Promise<void>;
+ setCancelled: (b: boolean) => void;
+ setSelecting: (b: boolean) => void;
+};
+
+export function View({ details, selectedExchange, accept, setCancelled, setSelecting }: ViewProps) {
+
+ return (
+ <WalletAction>
+ <div style="border-bottom: 3px dashed #aa3939; margin-bottom: 2em;">
+ <h1 style="font-family: monospace; font-size: 250%;">
+ <span style="color: #aa3939;">❰</span>Taler Wallet<span style="color: #aa3939;">❱</span>
+ </h1>
+ </div>
+ <div class="fade">
+ <div>
+ <h1><i18n.Translate>Digital Cash Withdrawal</i18n.Translate></h1>
+ <p><i18n.Translate>
+ You are about to withdraw{" "}
+ <strong>{renderAmount(details.amount)}</strong> from your bank account
+ into your wallet.
+ </i18n.Translate></p>
+ {selectedExchange ? (
+ <p><i18n.Translate>
+ The exchange <strong>{selectedExchange}</strong> will be used as the
+ Taler payment service provider.
+ </i18n.Translate></p>
+ ) : null}
+
+ <div>
+ <button
+ class="pure-button button-success"
+ disabled={!selectedExchange}
+ onClick={() => accept()}
+ >
+ {i18n.str`Accept fees and withdraw`}
+ </button>
+ <p>
+ <span
+ role="button"
+ tabIndex={0}
+ style={{ textDecoration: "underline", cursor: "pointer" }}
+ onClick={() => setSelecting(true)}
+ >
+ {i18n.str`Chose different exchange provider`}
+ </span>
+ <br />
+ <span
+ role="button"
+ tabIndex={0}
+ style={{ textDecoration: "underline", cursor: "pointer" }}
+ onClick={() => setCancelled(true)}
+ >
+ {i18n.str`Cancel withdraw operation`}
+ </span>
+ </p>
+ </div>
+ </div>
+ </div>
+ </WalletAction>
+ )
+}
+
+export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element {
+ const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined);
+ const [selectedExchange, setSelectedExchange] = useState<string | undefined>(undefined);
+ const [cancelled, setCancelled] = useState(false);
+ const [selecting, setSelecting] = useState(false);
+ const [error, setError] = useState<boolean>(false);
+ const [updateCounter, setUpdateCounter] = useState(1);
+ const [state, setState] = useState(1)
+
+ useEffect(() => {
+ return onUpdateNotification(() => {
+ console.log('updating...')
+ setUpdateCounter(updateCounter + 1);
+ });
+ }, []);
+
+ useEffect(() => {
+ console.log('on effect yes', talerWithdrawUri)
+ if (!talerWithdrawUri) return
+ const fetchData = async (): Promise<void> => {
+ try {
+ const res = await getWithdrawalDetailsForUri({ talerWithdrawUri });
+ setDetails(res);
+ if (res.defaultExchangeBaseUrl) {
+ setSelectedExchange(res.defaultExchangeBaseUrl);
+ }
+ } catch (e) {
+ console.error('error',JSON.stringify(e,undefined,2))
+ setError(true)
+ }
+ };
+ fetchData();
+ }, [selectedExchange, selecting, talerWithdrawUri, updateCounter, state]);
+
+ if (!talerWithdrawUri) {
+ return <span><i18n.Translate>missing withdraw uri</i18n.Translate></span>;
+ }
+
+ const accept = async (): Promise<void> => {
+ if (!selectedExchange) {
+ throw Error("can't accept, no exchange selected");
+ }
+ console.log("accepting exchange", selectedExchange);
+ const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange);
+ console.log("accept withdrawal response", res);
+ if (res.confirmTransferUrl) {
+ document.location.href = res.confirmTransferUrl;
+ }
+ };
+
+ if (!details) {
+ return <span><i18n.Translate>Loading...</i18n.Translate></span>;
+ }
+ if (cancelled) {
+ return <span><i18n.Translate>Withdraw operation has been cancelled.</i18n.Translate></span>;
+ }
+ if (error) {
+ return <span><i18n.Translate>This URI is not valid anymore.</i18n.Translate></span>;
+ }
+
+ return <View accept={accept}
+ setCancelled={setCancelled} setSelecting={setSelecting}
+ details={details} selectedExchange={selectedExchange}
+ />
+}
+
diff --git a/packages/taler-wallet-webextension/src/cta/payback.tsx b/packages/taler-wallet-webextension/src/cta/payback.tsx
new file mode 100644
index 000000000..4233b1f96
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/payback.tsx
@@ -0,0 +1,31 @@
+/*
+ This file is part of TALER
+ (C) 2017 Inria
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { JSX } from "preact/jsx-runtime";
+
+/**
+ * View and edit auditors.
+ *
+ * @author Florian Dold
+ */
+
+/**
+ * Imports.
+ */
+
+export function makePaybackPage(): JSX.Element {
+ return <div>not implemented</div>;
+}
diff --git a/packages/taler-wallet-webextension/src/cta/reset-required.tsx b/packages/taler-wallet-webextension/src/cta/reset-required.tsx
new file mode 100644
index 000000000..87751561c
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/reset-required.tsx
@@ -0,0 +1,97 @@
+/*
+ This file is part of TALER
+ (C) 2017 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Page to inform the user when a database reset is required.
+ *
+ * @author Florian Dold
+ */
+
+import { Component, JSX } from "preact";
+import * as wxApi from "../wxApi";
+
+interface State {
+ /**
+ * Did the user check the confirmation check box?
+ */
+ checked: boolean;
+
+ /**
+ * Do we actually need to reset the db?
+ */
+ resetRequired: boolean;
+}
+
+class ResetNotification extends Component<any, State> {
+ constructor(props: any) {
+ super(props);
+ this.state = { checked: false, resetRequired: true };
+ setInterval(() => this.update(), 500);
+ }
+ async update(): Promise<void> {
+ const res = await wxApi.checkUpgrade();
+ this.setState({ resetRequired: res.dbResetRequired });
+ }
+ render(): JSX.Element {
+ if (this.state.resetRequired) {
+ return (
+ <div>
+ <h1>Manual Reset Required</h1>
+ <p>
+ The wallet&apos;s database in your browser is incompatible with the{" "}
+ currently installed wallet. Please reset manually.
+ </p>
+ <p>
+ Once the database format has stabilized, we will provide automatic
+ upgrades.
+ </p>
+ <input
+ id="check"
+ type="checkbox"
+ checked={this.state.checked}
+ onChange={() => {
+ this.setState(prev => ({ checked: prev.checked }))
+ }}
+ />{" "}
+ <label htmlFor="check">
+ I understand that I will lose all my data
+ </label>
+ <br />
+ <button
+ class="pure-button"
+ disabled={!this.state.checked}
+ onClick={() => wxApi.resetDb()}
+ >
+ Reset
+ </button>
+ </div>
+ );
+ }
+ return (
+ <div>
+ <h1>Everything is fine!</h1>A reset is not required anymore, you can
+ close this page.
+ </div>
+ );
+ }
+}
+
+/**
+ * @deprecated to be removed
+ */
+export function createResetRequiredPage(): JSX.Element {
+ return <ResetNotification />;
+}
diff --git a/packages/taler-wallet-webextension/src/cta/return-coins.tsx b/packages/taler-wallet-webextension/src/cta/return-coins.tsx
new file mode 100644
index 000000000..2273d1454
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/cta/return-coins.tsx
@@ -0,0 +1,30 @@
+/*
+ This file is part of TALER
+ (C) 2017 Inria
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { JSX } from "preact/jsx-runtime";
+
+/**
+ * Return coins to own bank account.
+ *
+ * @author Florian Dold
+ */
+
+/**
+ * Imports.
+ */
+export function createReturnCoinsPage(): JSX.Element {
+ return <span>Not implemented yet.</span>;
+}