aboutsummaryrefslogtreecommitdiff
path: root/src/webex/pages/withdraw.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/webex/pages/withdraw.tsx')
-rw-r--r--src/webex/pages/withdraw.tsx231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/webex/pages/withdraw.tsx b/src/webex/pages/withdraw.tsx
new file mode 100644
index 000000000..66617373b
--- /dev/null
+++ b/src/webex/pages/withdraw.tsx
@@ -0,0 +1,231 @@
+/*
+ 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 { canonicalizeBaseUrl } from "../../helpers";
+import * as i18n from "../../i18n";
+
+import { AmountJson } from "../../amounts";
+import * as Amounts from "../../amounts";
+
+import { CurrencyRecord } from "../../dbTypes";
+import {
+ CreateReserveResponse,
+ ReserveCreationInfo,
+ WithdrawDetails,
+} from "../../walletTypes";
+
+import { ImplicitStateComponent, StateHolder } from "../components";
+
+import { WithdrawDetailView, renderAmount } from "../renderHtml";
+
+import React, { useState, useEffect } from "react";
+import * as ReactDOM from "react-dom";
+import URI = require("urijs");
+import { getWithdrawDetails, acceptWithdrawal } from "../wxApi";
+
+function NewExchangeSelection(props: { talerWithdrawUri: string }) {
+ const [details, setDetails] = useState<WithdrawDetails | undefined>();
+ const [selectedExchange, setSelectedExchange] = useState<
+ string | undefined
+ >();
+ const talerWithdrawUri = props.talerWithdrawUri;
+ const [cancelled, setCancelled] = useState(false);
+ const [selecting, setSelecting] = useState(false);
+ const [customUrl, setCustomUrl] = useState<string>("");
+ const [errMsg, setErrMsg] = useState<string | undefined>("");
+
+ useEffect(() => {
+ const fetchData = async () => {
+ console.log("getting from", talerWithdrawUri);
+ let d: WithdrawDetails | undefined = undefined;
+ try {
+ d = await getWithdrawDetails(talerWithdrawUri, selectedExchange);
+ } catch (e) {
+ console.error("error getting withdraw details", e);
+ setErrMsg(e.message);
+ return;
+ }
+ console.log("got withdrawDetails", d);
+ if (!selectedExchange && d.withdrawInfo.suggestedExchange) {
+ console.log("setting selected exchange");
+ setSelectedExchange(d.withdrawInfo.suggestedExchange);
+ }
+ setDetails(d);
+ };
+ fetchData();
+ }, [selectedExchange, errMsg, selecting]);
+
+ if (errMsg) {
+ return (
+ <div>
+ <i18n.Translate wrap="p">
+ Could not get details for withdraw operation:
+ </i18n.Translate>
+ <p style={{ color: "red" }}>{errMsg}</p>
+ <p>
+ <span
+ role="button"
+ tabIndex={0}
+ style={{ textDecoration: "underline", cursor: "pointer" }}
+ onClick={() => {
+ setSelecting(true);
+ setErrMsg(undefined);
+ setSelectedExchange(undefined);
+ setDetails(undefined);
+ }}
+ >
+ {i18n.str`Chose different exchange provider`}
+ </span>
+ </p>
+ </div>
+ );
+ }
+
+ if (!details) {
+ return <span>Loading...</span>;
+ }
+
+ if (cancelled) {
+ return <span>Withdraw operation has been cancelled.</span>;
+ }
+
+ if (selecting) {
+ const bankSuggestion = details && details.withdrawInfo.suggestedExchange;
+ return (
+ <div>
+ {i18n.str`Please select an exchange. You can review the details before after your selection.`}
+ {bankSuggestion && (
+ <div>
+ <h2>Bank Suggestion</h2>
+ <button
+ className="pure-button button-success"
+ onClick={() => {
+ setDetails(undefined);
+ setSelectedExchange(bankSuggestion);
+ setSelecting(false);
+ }}
+ >
+ <i18n.Translate wrap="span">
+ Select <strong>{bankSuggestion}</strong>
+ </i18n.Translate>
+ </button>
+ </div>
+ )}
+ <h2>Custom Selection</h2>
+ <p>
+ <input
+ type="text"
+ onChange={e => setCustomUrl(e.target.value)}
+ value={customUrl}
+ />
+ </p>
+ <button
+ className="pure-button button-success"
+ onClick={() => {
+ setDetails(undefined);
+ setSelectedExchange(customUrl);
+ setSelecting(false);
+ }}
+ >
+ <i18n.Translate wrap="span">Select custom exchange</i18n.Translate>
+ </button>
+ </div>
+ );
+ }
+
+ const accept = async () => {
+ 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;
+ }
+ };
+
+ return (
+ <div>
+ <i18n.Translate wrap="p">
+ You are about to withdraw{" "}
+ <strong>{renderAmount(details.withdrawInfo.amount)}</strong> from your
+ bank account into your wallet.
+ </i18n.Translate>
+ <div>
+ <button
+ className="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>
+
+ {details.reserveCreationInfo ? (
+ <WithdrawDetailView rci={details.reserveCreationInfo} />
+ ) : null}
+ </div>
+ </div>
+ );
+}
+
+async function main() {
+ try {
+ const url = new URI(document.location.href);
+ const query: any = URI.parseQuery(url.query());
+ let talerWithdrawUri = query.talerWithdrawUri;
+ if (!talerWithdrawUri) {
+ throw Error("withdraw URI required");
+ }
+
+ ReactDOM.render(
+ <NewExchangeSelection talerWithdrawUri={talerWithdrawUri} />,
+ document.getElementById("exchange-selection")!,
+ );
+ } catch (e) {
+ // TODO: provide more context information, maybe factor it out into a
+ // TODO:generic error reporting function or component.
+ document.body.innerText = i18n.str`Fatal error: "${e.message}".`;
+ console.error("got error", e);
+ }
+}
+
+document.addEventListener("DOMContentLoaded", () => {
+ main();
+});