diff options
author | Sebastian <sebasjm@gmail.com> | 2021-09-08 15:30:32 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2021-09-08 15:35:44 -0300 |
commit | 217f34397f95fc988280eee9c376efe0781c69ea (patch) | |
tree | 8cfb4011a7ddcb7409b7617ec8ac1425d08b1512 /packages/taler-wallet-webextension/src/cta | |
parent | a72ec5971e7c65e13a22627fc52983b75d4bea71 (diff) | |
download | wallet-core-217f34397f95fc988280eee9c376efe0781c69ea.tar.xz |
first approach to new design for withdraw
Diffstat (limited to 'packages/taler-wallet-webextension/src/cta')
3 files changed, 98 insertions, 88 deletions
diff --git a/packages/taler-wallet-webextension/src/cta/Pay.tsx b/packages/taler-wallet-webextension/src/cta/Pay.tsx index 24c76ce6c..758bc4b54 100644 --- a/packages/taler-wallet-webextension/src/cta/Pay.tsx +++ b/packages/taler-wallet-webextension/src/cta/Pay.tsx @@ -136,7 +136,9 @@ export function PayPage({ talerPayUri }: Props): JSX.Element { setPayResult(res); } catch (e) { console.error(e); - setPayErrMsg(e.message); + if (e instanceof Error) { + setPayErrMsg(e.message); + } } } diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx index 747f855fa..a89a18c15 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx @@ -19,6 +19,9 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { amountFractionalBase, Amounts } from '@gnu-taler/taler-util'; +import { ExchangeRecord } from '@gnu-taler/taler-wallet-core'; +import { ExchangeWithdrawDetails } from '@gnu-taler/taler-wallet-core/src/operations/withdraw'; import { createExample } from '../test-utils'; import { View as TestedComponent } from './Withdraw'; @@ -30,16 +33,29 @@ export default { }, }; -export const CompleteWithExchange = createExample(TestedComponent, { +export const WithdrawWithFee = createExample(TestedComponent, { details: { - amount: 'USD:2', - possibleExchanges: [], - }, - selectedExchange: 'Some exchange' + exchangeInfo: { + baseUrl: 'exchange.demo.taler.net' + } as ExchangeRecord, + withdrawFee: { + currency: 'USD', + fraction: amountFractionalBase*0.5, + value: 0 + }, + } as ExchangeWithdrawDetails, + amount: 'USD:2', }) -export const CompleteWithoutExchange = createExample(TestedComponent, { +export const WithdrawWithoutFee = createExample(TestedComponent, { details: { - amount: 'USD:2', - possibleExchanges: [], - }, + exchangeInfo: { + baseUrl: 'exchange.demo.taler.net' + } as ExchangeRecord, + withdrawFee: { + currency: 'USD', + fraction: 0, + value: 0 + }, + } as ExchangeWithdrawDetails, + amount: 'USD:2', }) diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx index d5f3c89ae..9719b8f5e 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx @@ -21,98 +21,78 @@ * @author Florian Dold */ -import { i18n } from '@gnu-taler/taler-util' -import { renderAmount } from "../renderHtml"; - -import { useState, useEffect } from "preact/hooks"; +import { AmountLike, Amounts, i18n, WithdrawUriInfoResponse } from '@gnu-taler/taler-util'; +import { ExchangeWithdrawDetails } from '@gnu-taler/taler-wallet-core/src/operations/withdraw'; +import { useEffect, useState } from "preact/hooks"; +import { JSX } from "preact/jsx-runtime"; +import { LogoHeader } from '../components/LogoHeader'; +import { Part } from '../components/Part'; +import { ButtonSuccess, WalletAction } from '../components/styled'; import { - acceptWithdrawal, - onUpdateNotification, - getWithdrawalDetailsForUri, + acceptWithdrawal, getExchangeWithdrawalInfo, getWithdrawalDetailsForUri, onUpdateNotification } from "../wxApi"; -import { h } from 'preact'; -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; + details: ExchangeWithdrawDetails; + amount: string; accept: () => Promise<void>; setCancelled: (b: boolean) => void; setSelecting: (b: boolean) => void; }; -export function View({ details, selectedExchange, accept, setCancelled, setSelecting }: ViewProps) { +function amountToString(text: AmountLike) { + const aj = Amounts.jsonifyAmount(text) + const amount = Amounts.stringifyValue(aj) + return `${amount} ${aj.currency}` +} + + +export function View({ details, amount, 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"> + <WalletAction style={{ textAlign: 'center' }}> + <LogoHeader /> + <h2> + {i18n.str`Digital cash withdrawal`} + </h2> + <section> + <div> + <Part title="Total to withdraw" text={amountToString(Amounts.sub(Amounts.parseOrThrow(amount), details.withdrawFee).amount)} kind='positive' /> + <Part title="Chosen amount" text={amountToString(amount)} kind='neutral' /> + {Amounts.isNonZero(details.withdrawFee) && + <Part title="Exchange fee" text={amountToString(details.withdrawFee)} kind='negative' /> + } + <Part title="Exchange" text={details.exchangeInfo.baseUrl} kind='neutral' big /> + </div> + </section> + <section> + <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> + <ButtonSuccess + upperCased + disabled={!details.exchangeInfo.baseUrl} + onClick={accept} + > + {i18n.str`Accept fees and withdraw`} + </ButtonSuccess> </div> - </div> + </section> </WalletAction> ) } export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element { - const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined); - const [selectedExchange, setSelectedExchange] = useState<string | undefined>(undefined); + const [uriInfo, setUriInfo] = useState<WithdrawUriInfoResponse | undefined>(undefined); + const [details, setDetails] = useState<ExchangeWithdrawDetails | 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(() => { @@ -127,47 +107,59 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element const fetchData = async (): Promise<void> => { try { const res = await getWithdrawalDetailsForUri({ talerWithdrawUri }); - setDetails(res); - if (res.defaultExchangeBaseUrl) { - setSelectedExchange(res.defaultExchangeBaseUrl); - } + setUriInfo(res); } catch (e) { console.error('error', JSON.stringify(e, undefined, 2)) setError(true) } }; fetchData(); - }, [selectedExchange, selecting, talerWithdrawUri, updateCounter, state]); + }, [selecting, talerWithdrawUri, updateCounter]); + + useEffect(() => { + async function fetchData() { + if (!uriInfo || !uriInfo.defaultExchangeBaseUrl) return + const res = await getExchangeWithdrawalInfo({ + exchangeBaseUrl: uriInfo.defaultExchangeBaseUrl, + amount: Amounts.parseOrThrow(uriInfo.amount) + }) + setDetails(res) + } + fetchData() + }, [uriInfo]) if (!talerWithdrawUri) { return <span><i18n.Translate>missing withdraw uri</i18n.Translate></span>; } const accept = async (): Promise<void> => { - if (!selectedExchange) { + if (!details) { throw Error("can't accept, no exchange selected"); } - console.log("accepting exchange", selectedExchange); - const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange); + console.log("accepting exchange", details.exchangeInfo.baseUrl); + const res = await acceptWithdrawal(talerWithdrawUri, details.exchangeInfo.baseUrl); 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>; } + if (!uriInfo) { + return <span><i18n.Translate>Loading...</i18n.Translate></span>; + } + if (!details) { + return <span><i18n.Translate>Getting withdrawal details.</i18n.Translate></span>; + } return <View accept={accept} setCancelled={setCancelled} setSelecting={setSelecting} - details={details} selectedExchange={selectedExchange} + details={details} amount={uriInfo.amount} /> } |