some DepositPage unit test
This commit is contained in:
parent
d881f4fd25
commit
cc18751e72
@ -25,7 +25,7 @@ function fromDir(startPath, regex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tests = fromDir('./src', /.test.ts$/)
|
const tests = fromDir('./src', /.test.ts$/)
|
||||||
.filter(t => t === 'src/wallet/CreateManualWithdraw.test.ts')
|
// .filter(t => t === 'src/wallet/DepositPage.test.ts')
|
||||||
.map(test => ({
|
.map(test => ({
|
||||||
input: test,
|
input: test,
|
||||||
output: {
|
output: {
|
||||||
|
@ -40,8 +40,7 @@ describe("CreateManualWithdraw states", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!result.current) {
|
if (!result.current) {
|
||||||
expect(result.current).not.to.be.undefined;
|
expect.fail("hook didn't render");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(result.current.noExchangeFound).equal(true)
|
expect(result.current.noExchangeFound).equal(true)
|
||||||
@ -53,8 +52,7 @@ describe("CreateManualWithdraw states", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!result.current) {
|
if (!result.current) {
|
||||||
expect(result.current).not.to.be.undefined;
|
expect.fail("hook didn't render");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(result.current.noExchangeFound).equal(true)
|
expect(result.current.noExchangeFound).equal(true)
|
||||||
@ -67,8 +65,7 @@ describe("CreateManualWithdraw states", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!result.current) {
|
if (!result.current) {
|
||||||
expect(result.current).not.to.be.undefined;
|
expect.fail("hook didn't render");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(result.current.exchange.value).equal("url1")
|
expect(result.current.exchange.value).equal("url1")
|
||||||
@ -80,8 +77,7 @@ describe("CreateManualWithdraw states", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!result.current) {
|
if (!result.current) {
|
||||||
expect(result.current).not.to.be.undefined;
|
expect.fail("hook didn't render");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(result.current.exchange.value).equal("url2")
|
expect(result.current.exchange.value).equal("url2")
|
||||||
|
@ -55,10 +55,12 @@ export interface State {
|
|||||||
export interface TextFieldHandler {
|
export interface TextFieldHandler {
|
||||||
onInput: (value: string) => void;
|
onInput: (value: string) => void;
|
||||||
value: string;
|
value: string;
|
||||||
|
error?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectFieldHandler {
|
export interface SelectFieldHandler {
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
|
error?: string;
|
||||||
value: string;
|
value: string;
|
||||||
list: Record<string, string>;
|
list: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Amounts, parsePaytoUri } from "@gnu-taler/taler-util";
|
import { Amounts, Balance, parsePaytoUri } from "@gnu-taler/taler-util";
|
||||||
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
|
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
|
||||||
import { createExample } from "../test-utils";
|
import { createExample } from "../test-utils";
|
||||||
import { View as TestedComponent } from "./DepositPage";
|
import { View as TestedComponent } from "./DepositPage";
|
||||||
@ -40,13 +40,21 @@ async function alwaysReturnFeeToOne(): Promise<DepositFee> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const WithEmptyAccountList = createExample(TestedComponent, {
|
export const WithEmptyAccountList = createExample(TestedComponent, {
|
||||||
knownBankAccounts: [],
|
accounts: [],
|
||||||
balance: Amounts.parseOrThrow("USD:10"),
|
balances: [
|
||||||
|
{
|
||||||
|
available: "USD:10",
|
||||||
|
} as Balance,
|
||||||
|
],
|
||||||
onCalculateFee: alwaysReturnFeeToOne,
|
onCalculateFee: alwaysReturnFeeToOne,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const WithSomeBankAccounts = createExample(TestedComponent, {
|
export const WithSomeBankAccounts = createExample(TestedComponent, {
|
||||||
knownBankAccounts: [parsePaytoUri("payto://iban/ES8877998399652238")!],
|
accounts: [parsePaytoUri("payto://iban/ES8877998399652238")!],
|
||||||
balance: Amounts.parseOrThrow("EUR:10"),
|
balances: [
|
||||||
|
{
|
||||||
|
available: "USD:10",
|
||||||
|
} as Balance,
|
||||||
|
],
|
||||||
onCalculateFee: alwaysReturnFeeToOne,
|
onCalculateFee: alwaysReturnFeeToOne,
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
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 { useComponentState } from "./DepositPage";
|
||||||
|
import { expect } from "chai";
|
||||||
|
import { mountHook } from "../test-utils";
|
||||||
|
import { Amounts, Balance } from "@gnu-taler/taler-util";
|
||||||
|
|
||||||
|
|
||||||
|
const currency = "EUR"
|
||||||
|
const feeCalculator = async () => ({
|
||||||
|
coin: Amounts.parseOrThrow(`${currency}:1`),
|
||||||
|
wire: Amounts.parseOrThrow(`${currency}:1`),
|
||||||
|
refresh: Amounts.parseOrThrow(`${currency}:1`)
|
||||||
|
})
|
||||||
|
|
||||||
|
const someBalance = [{
|
||||||
|
available: 'EUR:10'
|
||||||
|
} as Balance]
|
||||||
|
|
||||||
|
describe("DepositPage states", () => {
|
||||||
|
it("should have status 'no-balance' when balance is empty", () => {
|
||||||
|
const { result } = mountHook(() =>
|
||||||
|
useComponentState(currency, [], [], feeCalculator),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!result.current) {
|
||||||
|
expect.fail("hook didn't render");
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(result.current.status).equal("no-balance")
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have status 'no-accounts' when balance is not empty and accounts is empty", () => {
|
||||||
|
const { result } = mountHook(() =>
|
||||||
|
useComponentState(currency, [], someBalance, feeCalculator),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!result.current) {
|
||||||
|
expect.fail("hook didn't render");
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(result.current.status).equal("no-accounts")
|
||||||
|
});
|
||||||
|
});
|
@ -18,12 +18,15 @@ import {
|
|||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts,
|
Amounts,
|
||||||
AmountString,
|
AmountString,
|
||||||
|
Balance,
|
||||||
PaytoUri,
|
PaytoUri,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
|
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
|
||||||
|
import { saturate } from "polished";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { Loading } from "../components/Loading";
|
import { Loading } from "../components/Loading";
|
||||||
|
import { LoadingError } from "../components/LoadingError";
|
||||||
import { SelectList } from "../components/SelectList";
|
import { SelectList } from "../components/SelectList";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@ -37,6 +40,7 @@ import {
|
|||||||
import { useTranslationContext } from "../context/translation";
|
import { useTranslationContext } from "../context/translation";
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
import { SelectFieldHandler, TextFieldHandler } from "./CreateManualWithdraw";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
currency: string;
|
currency: string;
|
||||||
@ -45,45 +49,46 @@ interface Props {
|
|||||||
}
|
}
|
||||||
export function DepositPage({ currency, onCancel, onSuccess }: Props): VNode {
|
export function DepositPage({ currency, onCancel, onSuccess }: Props): VNode {
|
||||||
const state = useAsyncAsHook(async () => {
|
const state = useAsyncAsHook(async () => {
|
||||||
const balance = await wxApi.getBalance();
|
const { balances } = await wxApi.getBalance();
|
||||||
const bs = balance.balances.filter((b) => b.available.startsWith(currency));
|
const { accounts } = await wxApi.listKnownBankAccounts(currency);
|
||||||
const currencyBalance =
|
return { accounts, balances };
|
||||||
bs.length === 0
|
|
||||||
? Amounts.getZero(currency)
|
|
||||||
: Amounts.parseOrThrow(bs[0].available);
|
|
||||||
const knownAccounts = await wxApi.listKnownBankAccounts(currency);
|
|
||||||
return { accounts: knownAccounts.accounts, currencyBalance };
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const accounts =
|
const { i18n } = useTranslationContext();
|
||||||
state === undefined ? [] : state.hasError ? [] : state.response.accounts;
|
|
||||||
|
|
||||||
const currencyBalance =
|
async function doSend(p: PaytoUri, a: AmountJson): Promise<void> {
|
||||||
state === undefined
|
const account = `payto://${p.targetType}/${p.targetPath}`;
|
||||||
? Amounts.getZero(currency)
|
const amount = Amounts.stringify(a);
|
||||||
: state.hasError
|
|
||||||
? Amounts.getZero(currency)
|
|
||||||
: state.response.currencyBalance;
|
|
||||||
|
|
||||||
async function doSend(account: string, amount: AmountString): Promise<void> {
|
|
||||||
await wxApi.createDepositGroup(account, amount);
|
await wxApi.createDepositGroup(account, amount);
|
||||||
onSuccess(currency);
|
onSuccess(currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getFeeForAmount(
|
async function getFeeForAmount(
|
||||||
account: string,
|
p: PaytoUri,
|
||||||
amount: AmountString,
|
a: AmountJson,
|
||||||
): Promise<DepositFee> {
|
): Promise<DepositFee> {
|
||||||
|
const account = `payto://${p.targetType}/${p.targetPath}`;
|
||||||
|
const amount = Amounts.stringify(a);
|
||||||
return await wxApi.getFeeForDeposit(account, amount);
|
return await wxApi.getFeeForDeposit(account, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accounts.length === 0) return <Loading />;
|
if (state === undefined) return <Loading />;
|
||||||
|
|
||||||
|
if (state.hasError) {
|
||||||
|
return (
|
||||||
|
<LoadingError
|
||||||
|
title={<i18n.Translate>Could not load deposit balance</i18n.Translate>}
|
||||||
|
error={state}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
onCancel={onCancel}
|
onCancel={() => onCancel(currency)}
|
||||||
knownBankAccounts={accounts}
|
currency={currency}
|
||||||
balance={currencyBalance}
|
accounts={state.response.accounts}
|
||||||
|
balances={state.response.balances}
|
||||||
onSend={doSend}
|
onSend={doSend}
|
||||||
onCalculateFee={getFeeForAmount}
|
onCalculateFee={getFeeForAmount}
|
||||||
/>
|
/>
|
||||||
@ -91,25 +96,46 @@ export function DepositPage({ currency, onCancel, onSuccess }: Props): VNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ViewProps {
|
interface ViewProps {
|
||||||
knownBankAccounts: Array<PaytoUri>;
|
accounts: Array<PaytoUri>;
|
||||||
balance: AmountJson;
|
currency: string;
|
||||||
onCancel: (currency: string) => void;
|
balances: Balance[];
|
||||||
onSend: (account: string, amount: AmountString) => Promise<void>;
|
onCancel: () => void;
|
||||||
|
onSend: (account: PaytoUri, amount: AmountJson) => Promise<void>;
|
||||||
onCalculateFee: (
|
onCalculateFee: (
|
||||||
account: string,
|
account: PaytoUri,
|
||||||
amount: AmountString,
|
amount: AmountJson,
|
||||||
) => Promise<DepositFee>;
|
) => Promise<DepositFee>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function View({
|
type State = NoBalanceState | NoAccountsState | DepositState;
|
||||||
onCancel,
|
|
||||||
knownBankAccounts,
|
interface NoBalanceState {
|
||||||
balance,
|
status: "no-balance";
|
||||||
onSend,
|
}
|
||||||
onCalculateFee,
|
interface NoAccountsState {
|
||||||
}: ViewProps): VNode {
|
status: "no-accounts";
|
||||||
const { i18n } = useTranslationContext();
|
}
|
||||||
const accountMap = createLabelsForBankAccount(knownBankAccounts);
|
interface DepositState {
|
||||||
|
status: "deposit";
|
||||||
|
amount: TextFieldHandler;
|
||||||
|
account: SelectFieldHandler;
|
||||||
|
totalFee: AmountJson;
|
||||||
|
totalToDeposit: AmountJson;
|
||||||
|
unableToDeposit: boolean;
|
||||||
|
selectedAccount: PaytoUri;
|
||||||
|
parsedAmount: AmountJson | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useComponentState(
|
||||||
|
currency: string,
|
||||||
|
accounts: PaytoUri[],
|
||||||
|
balances: Balance[],
|
||||||
|
onCalculateFee: (
|
||||||
|
account: PaytoUri,
|
||||||
|
amount: AmountJson,
|
||||||
|
) => Promise<DepositFee>,
|
||||||
|
): State {
|
||||||
|
const accountMap = createLabelsForBankAccount(accounts);
|
||||||
const [accountIdx, setAccountIdx] = useState(0);
|
const [accountIdx, setAccountIdx] = useState(0);
|
||||||
const [amount, setAmount] = useState<number | undefined>(undefined);
|
const [amount, setAmount] = useState<number | undefined>(undefined);
|
||||||
const [fee, setFee] = useState<DepositFee | undefined>(undefined);
|
const [fee, setFee] = useState<DepositFee | undefined>(undefined);
|
||||||
@ -117,35 +143,108 @@ export function View({
|
|||||||
setAmount(num);
|
setAmount(num);
|
||||||
setFee(undefined);
|
setFee(undefined);
|
||||||
}
|
}
|
||||||
const currency = balance.currency;
|
|
||||||
const amountStr: AmountString = `${currency}:${amount}`;
|
const selectedAmountSTR: AmountString = `${currency}:${amount}`;
|
||||||
const feeSum =
|
const totalFee =
|
||||||
fee !== undefined
|
fee !== undefined
|
||||||
? Amounts.sum([fee.wire, fee.coin, fee.refresh]).amount
|
? Amounts.sum([fee.wire, fee.coin, fee.refresh]).amount
|
||||||
: Amounts.getZero(currency);
|
: Amounts.getZero(currency);
|
||||||
|
|
||||||
const account = knownBankAccounts.length
|
const selectedAccount = accounts.length ? accounts[accountIdx] : undefined;
|
||||||
? knownBankAccounts[accountIdx]
|
|
||||||
: undefined;
|
const parsedAmount =
|
||||||
const accountURI = !account
|
amount === undefined ? undefined : Amounts.parse(selectedAmountSTR);
|
||||||
? ""
|
|
||||||
: `payto://${account.targetType}/${account.targetPath}`;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (amount === undefined) return;
|
if (selectedAccount === undefined || parsedAmount === undefined) return;
|
||||||
onCalculateFee(accountURI, amountStr).then((result) => {
|
onCalculateFee(selectedAccount, parsedAmount).then((result) => {
|
||||||
setFee(result);
|
setFee(result);
|
||||||
});
|
});
|
||||||
}, [amount]);
|
}, [amount]);
|
||||||
|
|
||||||
if (!balance) {
|
const bs = balances.filter((b) => b.available.startsWith(currency));
|
||||||
|
const balance =
|
||||||
|
bs.length > 0
|
||||||
|
? Amounts.parseOrThrow(bs[0].available)
|
||||||
|
: Amounts.getZero(currency);
|
||||||
|
|
||||||
|
const isDirty = amount !== 0;
|
||||||
|
const amountError = !isDirty
|
||||||
|
? undefined
|
||||||
|
: !parsedAmount
|
||||||
|
? "Invalid amount"
|
||||||
|
: Amounts.cmp(balance, parsedAmount) === -1
|
||||||
|
? `Too much, your current balance is ${Amounts.stringifyValue(balance)}`
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const totalToDeposit = parsedAmount
|
||||||
|
? Amounts.sub(parsedAmount, totalFee).amount
|
||||||
|
: Amounts.getZero(currency);
|
||||||
|
|
||||||
|
const unableToDeposit =
|
||||||
|
Amounts.isZero(totalToDeposit) ||
|
||||||
|
fee === undefined ||
|
||||||
|
amountError !== undefined;
|
||||||
|
|
||||||
|
if (Amounts.isZero(balance)) {
|
||||||
|
return {
|
||||||
|
status: "no-balance",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!accounts || !accounts.length || !selectedAccount) {
|
||||||
|
return {
|
||||||
|
status: "no-accounts",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: "deposit",
|
||||||
|
amount: {
|
||||||
|
value: String(amount),
|
||||||
|
onInput: (e) => {
|
||||||
|
const num = parseFloat(e);
|
||||||
|
if (!Number.isNaN(num)) {
|
||||||
|
updateAmount(num);
|
||||||
|
} else {
|
||||||
|
updateAmount(undefined);
|
||||||
|
setFee(undefined);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: amountError,
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
list: accountMap,
|
||||||
|
value: String(accountIdx),
|
||||||
|
onChange: (s) => setAccountIdx(parseInt(s, 10)),
|
||||||
|
},
|
||||||
|
totalFee,
|
||||||
|
totalToDeposit,
|
||||||
|
unableToDeposit,
|
||||||
|
selectedAccount,
|
||||||
|
parsedAmount,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function View({
|
||||||
|
onCancel,
|
||||||
|
currency,
|
||||||
|
accounts,
|
||||||
|
balances,
|
||||||
|
onSend,
|
||||||
|
onCalculateFee,
|
||||||
|
}: ViewProps): VNode {
|
||||||
|
const { i18n } = useTranslationContext();
|
||||||
|
const state = useComponentState(currency, accounts, balances, onCalculateFee);
|
||||||
|
|
||||||
|
if (state.status === "no-balance") {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<i18n.Translate>no balance</i18n.Translate>
|
<i18n.Translate>no balance</i18n.Translate>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!knownBankAccounts || !knownBankAccounts.length) {
|
if (state.status === "no-accounts") {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<WarningBox>
|
<WarningBox>
|
||||||
@ -159,30 +258,13 @@ export function View({
|
|||||||
</ButtonBoxWarning>
|
</ButtonBoxWarning>
|
||||||
</WarningBox>
|
</WarningBox>
|
||||||
<footer>
|
<footer>
|
||||||
<Button onClick={() => onCancel(currency)}>
|
<Button onClick={onCancel}>
|
||||||
<i18n.Translate>Cancel</i18n.Translate>
|
<i18n.Translate>Cancel</i18n.Translate>
|
||||||
</Button>
|
</Button>
|
||||||
</footer>
|
</footer>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const parsedAmount =
|
|
||||||
amount === undefined ? undefined : Amounts.parse(amountStr);
|
|
||||||
const isDirty = amount !== 0;
|
|
||||||
const error = !isDirty
|
|
||||||
? undefined
|
|
||||||
: !parsedAmount
|
|
||||||
? "Invalid amount"
|
|
||||||
: Amounts.cmp(balance, parsedAmount) === -1
|
|
||||||
? `Too much, your current balance is ${Amounts.stringifyValue(balance)}`
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const totalToDeposit = parsedAmount
|
|
||||||
? Amounts.sub(parsedAmount, feeSum).amount
|
|
||||||
: Amounts.getZero(currency);
|
|
||||||
|
|
||||||
const unableToDeposit =
|
|
||||||
Amounts.isZero(totalToDeposit) || fee === undefined || error !== undefined;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
@ -193,13 +275,13 @@ export function View({
|
|||||||
<Input>
|
<Input>
|
||||||
<SelectList
|
<SelectList
|
||||||
label={<i18n.Translate>Bank account IBAN number</i18n.Translate>}
|
label={<i18n.Translate>Bank account IBAN number</i18n.Translate>}
|
||||||
list={accountMap}
|
list={state.account.list}
|
||||||
name="account"
|
name="account"
|
||||||
value={String(accountIdx)}
|
value={state.account.value}
|
||||||
onChange={(s) => setAccountIdx(parseInt(s, 10))}
|
onChange={state.account.onChange}
|
||||||
/>
|
/>
|
||||||
</Input>
|
</Input>
|
||||||
<InputWithLabel invalid={!!error}>
|
<InputWithLabel invalid={!!state.amount.error}>
|
||||||
<label>
|
<label>
|
||||||
<i18n.Translate>Amount</i18n.Translate>
|
<i18n.Translate>Amount</i18n.Translate>
|
||||||
</label>
|
</label>
|
||||||
@ -207,19 +289,11 @@ export function View({
|
|||||||
<span>{currency}</span>
|
<span>{currency}</span>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={amount}
|
value={state.amount.value}
|
||||||
onInput={(e) => {
|
onInput={(e) => state.amount.onInput(e.currentTarget.value)}
|
||||||
const num = parseFloat(e.currentTarget.value);
|
|
||||||
if (!Number.isNaN(num)) {
|
|
||||||
updateAmount(num);
|
|
||||||
} else {
|
|
||||||
updateAmount(undefined);
|
|
||||||
setFee(undefined);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{error && <ErrorText>{error}</ErrorText>}
|
{state.amount.error && <ErrorText>{state.amount.error}</ErrorText>}
|
||||||
</InputWithLabel>
|
</InputWithLabel>
|
||||||
{
|
{
|
||||||
<Fragment>
|
<Fragment>
|
||||||
@ -232,7 +306,7 @@ export function View({
|
|||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
disabled
|
disabled
|
||||||
value={Amounts.stringifyValue(feeSum)}
|
value={Amounts.stringifyValue(state.totalFee)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</InputWithLabel>
|
</InputWithLabel>
|
||||||
@ -246,7 +320,7 @@ export function View({
|
|||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
disabled
|
disabled
|
||||||
value={Amounts.stringifyValue(totalToDeposit)}
|
value={Amounts.stringifyValue(state.totalToDeposit)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</InputWithLabel>
|
</InputWithLabel>
|
||||||
@ -254,17 +328,19 @@ export function View({
|
|||||||
}
|
}
|
||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<Button onClick={() => onCancel(currency)}>
|
<Button onClick={onCancel}>
|
||||||
<i18n.Translate>Cancel</i18n.Translate>
|
<i18n.Translate>Cancel</i18n.Translate>
|
||||||
</Button>
|
</Button>
|
||||||
{unableToDeposit ? (
|
{state.unableToDeposit ? (
|
||||||
<ButtonPrimary disabled>
|
<ButtonPrimary disabled>
|
||||||
<i18n.Translate>Deposit</i18n.Translate>
|
<i18n.Translate>Deposit</i18n.Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
) : (
|
) : (
|
||||||
<ButtonPrimary onClick={() => onSend(accountURI, amountStr)}>
|
<ButtonPrimary
|
||||||
|
onClick={() => onSend(state.selectedAccount, state.parsedAmount!)}
|
||||||
|
>
|
||||||
<i18n.Translate>
|
<i18n.Translate>
|
||||||
Deposit {Amounts.stringifyValue(totalToDeposit)} {currency}
|
Deposit {Amounts.stringifyValue(state.totalToDeposit)} {currency}
|
||||||
</i18n.Translate>
|
</i18n.Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
)}
|
)}
|
||||||
|
Loading…
Reference in New Issue
Block a user