standard Amount field and add more validation (neg values)
This commit is contained in:
parent
3eafb64912
commit
6f3cd16343
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2022 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/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Fragment, h, VNode } from "preact";
|
||||||
|
import { TextFieldHandler } from "../mui/handlers.js";
|
||||||
|
import { TextField } from "../mui/TextField.js";
|
||||||
|
import { ErrorText } from "./styled/index.js";
|
||||||
|
|
||||||
|
export function AmountField({
|
||||||
|
label,
|
||||||
|
handler,
|
||||||
|
currency,
|
||||||
|
required,
|
||||||
|
}: {
|
||||||
|
label: VNode;
|
||||||
|
required?: boolean;
|
||||||
|
currency: string;
|
||||||
|
handler: TextFieldHandler;
|
||||||
|
}): VNode {
|
||||||
|
function positiveAmount(value: string): string {
|
||||||
|
if (!value) return "";
|
||||||
|
try {
|
||||||
|
const num = Number.parseFloat(value);
|
||||||
|
if (Number.isNaN(num) || num < 0) return handler.value;
|
||||||
|
if (handler.onInput) {
|
||||||
|
handler.onInput(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
} catch (e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
return handler.value;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<TextField
|
||||||
|
label={label}
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
step="0.1"
|
||||||
|
variant="filled"
|
||||||
|
error={!!handler.error}
|
||||||
|
required={required}
|
||||||
|
startAdornment={
|
||||||
|
<div style={{ padding: "25px 12px 8px 12px" }}>{currency}</div>
|
||||||
|
}
|
||||||
|
value={handler.value}
|
||||||
|
disabled={!handler.onInput}
|
||||||
|
onInput={positiveAmount}
|
||||||
|
/>
|
||||||
|
{handler.error && <ErrorText>{handler.error}</ErrorText>}
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
@ -40,7 +40,9 @@ export interface Props {
|
|||||||
minRows?: number;
|
minRows?: number;
|
||||||
multiline?: boolean;
|
multiline?: boolean;
|
||||||
onChange?: (s: string) => void;
|
onChange?: (s: string) => void;
|
||||||
|
onInput?: (s: string) => string;
|
||||||
min?: string;
|
min?: string;
|
||||||
|
step?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
import { TalerError } from "@gnu-taler/taler-wallet-core";
|
import { TalerError } from "@gnu-taler/taler-wallet-core";
|
||||||
|
|
||||||
export interface TextFieldHandler {
|
export interface TextFieldHandler {
|
||||||
onInput: (value: string) => Promise<void>;
|
onInput?: (value: string) => Promise<void>;
|
||||||
value: string;
|
value: string;
|
||||||
error?: string;
|
error?: string;
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,7 @@ export function InputBase({
|
|||||||
Root = InputBaseRoot,
|
Root = InputBaseRoot,
|
||||||
Input,
|
Input,
|
||||||
onChange,
|
onChange,
|
||||||
|
onInput,
|
||||||
name,
|
name,
|
||||||
placeholder,
|
placeholder,
|
||||||
readOnly,
|
readOnly,
|
||||||
@ -254,6 +255,19 @@ export function InputBase({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleInput = (
|
||||||
|
event: JSX.TargetedEvent<HTMLElement & { value?: string }>,
|
||||||
|
): void => {
|
||||||
|
// if (inputPropsProp.onChange) {
|
||||||
|
// inputPropsProp.onChange(event, ...args);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Perform in the willUpdate
|
||||||
|
if (onInput) {
|
||||||
|
event.currentTarget.value = onInput(event.currentTarget.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleClick = (
|
const handleClick = (
|
||||||
event: JSX.TargetedMouseEvent<HTMLElement & { value?: string }>,
|
event: JSX.TargetedMouseEvent<HTMLElement & { value?: string }>,
|
||||||
): void => {
|
): void => {
|
||||||
@ -290,6 +304,7 @@ export function InputBase({
|
|||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
onKeyUp={onKeyUp}
|
onKeyUp={onKeyUp}
|
||||||
type={type}
|
type={type}
|
||||||
|
onInput={handleInput}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
onFocus={handleFocus}
|
onFocus={handleFocus}
|
||||||
@ -345,6 +360,7 @@ export function TextareaAutoSize({
|
|||||||
// disabled,
|
// disabled,
|
||||||
// size,
|
// size,
|
||||||
onChange,
|
onChange,
|
||||||
|
onInput,
|
||||||
value,
|
value,
|
||||||
multiline,
|
multiline,
|
||||||
focused,
|
focused,
|
||||||
@ -480,7 +496,18 @@ export function TextareaAutoSize({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (onChange) {
|
if (onChange) {
|
||||||
onChange(event);
|
onChange(event.target.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleInput = (event: any): void => {
|
||||||
|
renders.current = 0;
|
||||||
|
|
||||||
|
if (!isControlled) {
|
||||||
|
syncHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onInput) {
|
||||||
|
event.currentTarget.value = onInput(event.currentTarget.value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -498,6 +525,7 @@ export function TextareaAutoSize({
|
|||||||
].join(" ")}
|
].join(" ")}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
onInput={handleInput}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
// Apply the rows prop to get a "correct" first SSR paint
|
// Apply the rows prop to get a "correct" first SSR paint
|
||||||
rows={minRows}
|
rows={minRows}
|
||||||
|
@ -129,6 +129,8 @@ describe("CreateManualWithdraw states", () => {
|
|||||||
|
|
||||||
expect(parsedAmount).equal(undefined);
|
expect(parsedAmount).equal(undefined);
|
||||||
|
|
||||||
|
expect(amount.onInput).not.undefined;
|
||||||
|
if (!amount.onInput) return;
|
||||||
amount.onInput("12");
|
amount.onInput("12");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +190,8 @@ async function defaultTestForInputText(
|
|||||||
const field = getField();
|
const field = getField();
|
||||||
const initialValue = field.value;
|
const initialValue = field.value;
|
||||||
nextValue = `${initialValue} something else`;
|
nextValue = `${initialValue} something else`;
|
||||||
|
expect(field.onInput).not.undefined;
|
||||||
|
if (!field.onInput) return;
|
||||||
field.onInput(nextValue);
|
field.onInput(nextValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ export function CreateManualWithdraw({
|
|||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={state.amount.value}
|
value={state.amount.value}
|
||||||
onInput={(e) => state.amount.onInput(e.currentTarget.value)}
|
// onInput={(e) => state.amount.onInput(e.currentTarget.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</InputWithLabel>
|
</InputWithLabel>
|
||||||
|
@ -49,7 +49,6 @@ export function useComponentState(
|
|||||||
parsed !== undefined ? Amounts.stringifyValue(parsed) : "0";
|
parsed !== undefined ? Amounts.stringifyValue(parsed) : "0";
|
||||||
// const [accountIdx, setAccountIdx] = useState<number>(0);
|
// const [accountIdx, setAccountIdx] = useState<number>(0);
|
||||||
const [amount, setAmount] = useState(initialValue);
|
const [amount, setAmount] = useState(initialValue);
|
||||||
|
|
||||||
const [selectedAccount, setSelectedAccount] = useState<PaytoUri>();
|
const [selectedAccount, setSelectedAccount] = useState<PaytoUri>();
|
||||||
|
|
||||||
const [fee, setFee] = useState<DepositGroupFees | undefined>(undefined);
|
const [fee, setFee] = useState<DepositGroupFees | undefined>(undefined);
|
||||||
@ -124,6 +123,16 @@ export function useComponentState(
|
|||||||
const firstAccount = accounts[0].uri
|
const firstAccount = accounts[0].uri
|
||||||
const currentAccount = !selectedAccount ? firstAccount : selectedAccount;
|
const currentAccount = !selectedAccount ? firstAccount : selectedAccount;
|
||||||
|
|
||||||
|
if (fee === undefined && parsedAmount) {
|
||||||
|
getFeeForAmount(currentAccount, parsedAmount, api).then(initialFee => {
|
||||||
|
setFee(initialFee)
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
status: "loading",
|
||||||
|
error: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const accountMap = createLabelsForBankAccount(accounts);
|
const accountMap = createLabelsForBankAccount(accounts);
|
||||||
|
|
||||||
async function updateAccountFromList(accountStr: string): Promise<void> {
|
async function updateAccountFromList(accountStr: string): Promise<void> {
|
||||||
|
@ -167,6 +167,11 @@ describe("DepositPage states", () => {
|
|||||||
accounts: [ibanPayto],
|
accounts: [ibanPayto],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
handler.addWalletCallResponse(
|
||||||
|
WalletApiOperation.GetFeeForDeposit,
|
||||||
|
undefined,
|
||||||
|
withoutFee(),
|
||||||
|
);
|
||||||
|
|
||||||
const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
|
const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } =
|
||||||
mountHook(() => useComponentState(props, mock));
|
mountHook(() => useComponentState(props, mock));
|
||||||
@ -176,6 +181,11 @@ describe("DepositPage states", () => {
|
|||||||
expect(status).equal("loading");
|
expect(status).equal("loading");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expect(await waitForStateUpdate()).true;
|
||||||
|
{
|
||||||
|
const { status } = pullLastResultOrThrow();
|
||||||
|
expect(status).equal("loading");
|
||||||
|
}
|
||||||
expect(await waitForStateUpdate()).true;
|
expect(await waitForStateUpdate()).true;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -214,6 +224,12 @@ describe("DepositPage states", () => {
|
|||||||
accounts: [talerBankPayto, ibanPayto],
|
accounts: [talerBankPayto, ibanPayto],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
handler.addWalletCallResponse(
|
||||||
|
WalletApiOperation.GetFeeForDeposit,
|
||||||
|
undefined,
|
||||||
|
withoutFee(),
|
||||||
|
);
|
||||||
|
|
||||||
handler.addWalletCallResponse(
|
handler.addWalletCallResponse(
|
||||||
WalletApiOperation.GetFeeForDeposit,
|
WalletApiOperation.GetFeeForDeposit,
|
||||||
undefined,
|
undefined,
|
||||||
@ -238,6 +254,12 @@ describe("DepositPage states", () => {
|
|||||||
expect(status).equal("loading");
|
expect(status).equal("loading");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expect(await waitForStateUpdate()).true;
|
||||||
|
{
|
||||||
|
const { status } = pullLastResultOrThrow();
|
||||||
|
expect(status).equal("loading");
|
||||||
|
}
|
||||||
|
|
||||||
expect(await waitForStateUpdate()).true;
|
expect(await waitForStateUpdate()).true;
|
||||||
const accountSelected = stringifyPaytoUri(ibanPayto.uri);
|
const accountSelected = stringifyPaytoUri(ibanPayto.uri);
|
||||||
|
|
||||||
@ -361,6 +383,11 @@ describe("DepositPage states", () => {
|
|||||||
accounts: [talerBankPayto, ibanPayto],
|
accounts: [talerBankPayto, ibanPayto],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
handler.addWalletCallResponse(
|
||||||
|
WalletApiOperation.GetFeeForDeposit,
|
||||||
|
undefined,
|
||||||
|
withoutFee(),
|
||||||
|
);
|
||||||
handler.addWalletCallResponse(
|
handler.addWalletCallResponse(
|
||||||
WalletApiOperation.GetFeeForDeposit,
|
WalletApiOperation.GetFeeForDeposit,
|
||||||
undefined,
|
undefined,
|
||||||
@ -380,6 +407,13 @@ describe("DepositPage states", () => {
|
|||||||
expect(status).equal("loading");
|
expect(status).equal("loading");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expect(await waitForStateUpdate()).true;
|
||||||
|
|
||||||
|
{
|
||||||
|
const { status } = pullLastResultOrThrow();
|
||||||
|
expect(status).equal("loading");
|
||||||
|
}
|
||||||
|
|
||||||
expect(await waitForStateUpdate()).true;
|
expect(await waitForStateUpdate()).true;
|
||||||
const accountSelected = stringifyPaytoUri(ibanPayto.uri);
|
const accountSelected = stringifyPaytoUri(ibanPayto.uri);
|
||||||
|
|
||||||
@ -409,6 +443,8 @@ describe("DepositPage states", () => {
|
|||||||
expect(r.depositHandler.onClick).undefined;
|
expect(r.depositHandler.onClick).undefined;
|
||||||
expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
|
expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
|
||||||
|
|
||||||
|
expect(r.amount.onInput).not.undefined;
|
||||||
|
if (!r.amount.onInput) return;
|
||||||
r.amount.onInput("10");
|
r.amount.onInput("10");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import { Amounts, PaytoUri } from "@gnu-taler/taler-util";
|
import { Amounts, PaytoUri } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
|
import { AmountField } from "../../components/AmountField.js";
|
||||||
import { ErrorMessage } from "../../components/ErrorMessage.js";
|
import { ErrorMessage } from "../../components/ErrorMessage.js";
|
||||||
import { LoadingError } from "../../components/LoadingError.js";
|
import { LoadingError } from "../../components/LoadingError.js";
|
||||||
import { SelectList } from "../../components/SelectList.js";
|
import { SelectList } from "../../components/SelectList.js";
|
||||||
@ -28,6 +29,7 @@ import {
|
|||||||
} from "../../components/styled/index.js";
|
} from "../../components/styled/index.js";
|
||||||
import { useTranslationContext } from "../../context/translation.js";
|
import { useTranslationContext } from "../../context/translation.js";
|
||||||
import { Button } from "../../mui/Button.js";
|
import { Button } from "../../mui/Button.js";
|
||||||
|
import { Grid } from "../../mui/Grid.js";
|
||||||
import { State } from "./index.js";
|
import { State } from "./index.js";
|
||||||
|
|
||||||
export function LoadingErrorView({ error }: State.LoadingUriError): VNode {
|
export function LoadingErrorView({ error }: State.LoadingUriError): VNode {
|
||||||
@ -167,48 +169,33 @@ export function ReadyView(state: State.Ready): VNode {
|
|||||||
<p>
|
<p>
|
||||||
<AccountDetails account={state.currentAccount} />
|
<AccountDetails account={state.currentAccount} />
|
||||||
</p>
|
</p>
|
||||||
<InputWithLabel invalid={!!state.amount.error}>
|
<Grid container spacing={2} columns={1}>
|
||||||
<label>
|
<Grid item xs={1}>
|
||||||
<i18n.Translate>Amount</i18n.Translate>
|
<AmountField
|
||||||
</label>
|
label={<i18n.Translate>Amount</i18n.Translate>}
|
||||||
<div>
|
currency={state.currency}
|
||||||
<span>{state.currency}</span>
|
handler={state.amount}
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
value={state.amount.value}
|
|
||||||
onInput={(e) => state.amount.onInput(e.currentTarget.value)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</Grid>
|
||||||
{state.amount.error && <ErrorText>{state.amount.error}</ErrorText>}
|
<Grid item xs={1}>
|
||||||
</InputWithLabel>
|
<AmountField
|
||||||
|
label={<i18n.Translate>Deposit fee</i18n.Translate>}
|
||||||
<InputWithLabel>
|
currency={state.currency}
|
||||||
<label>
|
handler={{
|
||||||
<i18n.Translate>Deposit fee</i18n.Translate>
|
value: Amounts.stringifyValue(state.totalFee),
|
||||||
</label>
|
}}
|
||||||
<div>
|
|
||||||
<span>{state.currency}</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
disabled
|
|
||||||
value={Amounts.stringifyValue(state.totalFee)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</Grid>
|
||||||
</InputWithLabel>
|
<Grid item xs={1}>
|
||||||
|
<AmountField
|
||||||
<InputWithLabel>
|
label={<i18n.Translate>Total deposit</i18n.Translate>}
|
||||||
<label>
|
currency={state.currency}
|
||||||
<i18n.Translate>Total deposit</i18n.Translate>
|
handler={{
|
||||||
</label>
|
value: Amounts.stringifyValue(state.totalToDeposit),
|
||||||
<div>
|
}}
|
||||||
<span>{state.currency}</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
disabled
|
|
||||||
value={Amounts.stringifyValue(state.totalToDeposit)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</Grid>
|
||||||
</InputWithLabel>
|
</Grid>
|
||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<Button
|
<Button
|
||||||
|
@ -19,6 +19,7 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
|||||||
import { styled } from "@linaria/react";
|
import { styled } from "@linaria/react";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
|
import { AmountField } from "../components/AmountField.js";
|
||||||
import { Loading } from "../components/Loading.js";
|
import { Loading } from "../components/Loading.js";
|
||||||
import { LoadingError } from "../components/LoadingError.js";
|
import { LoadingError } from "../components/LoadingError.js";
|
||||||
import { SelectList } from "../components/SelectList.js";
|
import { SelectList } from "../components/SelectList.js";
|
||||||
@ -32,6 +33,7 @@ import { useTranslationContext } from "../context/translation.js";
|
|||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
||||||
import { Button } from "../mui/Button.js";
|
import { Button } from "../mui/Button.js";
|
||||||
import { Grid } from "../mui/Grid.js";
|
import { Grid } from "../mui/Grid.js";
|
||||||
|
import { TextFieldHandler } from "../mui/handlers.js";
|
||||||
import { Paper } from "../mui/Paper.js";
|
import { Paper } from "../mui/Paper.js";
|
||||||
import { TextField } from "../mui/TextField.js";
|
import { TextField } from "../mui/TextField.js";
|
||||||
import { Pages } from "../NavigationBar.js";
|
import { Pages } from "../NavigationBar.js";
|
||||||
@ -283,11 +285,6 @@ export function DestinationSelectionGetCash({
|
|||||||
const [currency, setCurrency] = useState(parsedInitialAmount?.currency);
|
const [currency, setCurrency] = useState(parsedInitialAmount?.currency);
|
||||||
|
|
||||||
const [amount, setAmount] = useState(parsedInitialAmountValue);
|
const [amount, setAmount] = useState(parsedInitialAmountValue);
|
||||||
function positiveSetAmount(e: string):void {
|
|
||||||
const value = Number.parseInt(e, 10);
|
|
||||||
if (value < 0) return
|
|
||||||
setAmount(String(value))
|
|
||||||
}
|
|
||||||
const { i18n } = useTranslationContext();
|
const { i18n } = useTranslationContext();
|
||||||
const previous1: Contact[] = [];
|
const previous1: Contact[] = [];
|
||||||
const previous2: Contact[] = [
|
const previous2: Contact[] = [
|
||||||
@ -326,19 +323,13 @@ export function DestinationSelectionGetCash({
|
|||||||
<i18n.Translate>Specify the amount and the origin</i18n.Translate>
|
<i18n.Translate>Specify the amount and the origin</i18n.Translate>
|
||||||
</h1>
|
</h1>
|
||||||
<Grid container columns={2} justifyContent="space-between">
|
<Grid container columns={2} justifyContent="space-between">
|
||||||
<TextField
|
<AmountField
|
||||||
label="Amount"
|
label={<i18n.Translate>Amount</i18n.Translate>}
|
||||||
type="number"
|
currency={currency}
|
||||||
min="0"
|
|
||||||
variant="filled"
|
|
||||||
error={invalid}
|
|
||||||
required
|
required
|
||||||
startAdornment={
|
handler={{
|
||||||
<div style={{ padding: "25px 12px 8px 12px" }}>{currency}</div>
|
onInput: async (s) => setAmount(s),
|
||||||
}
|
value: amount,
|
||||||
value={amount}
|
|
||||||
onChange={(e) => {
|
|
||||||
setAmount(e);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button onClick={async () => setCurrency(undefined)}>
|
<Button onClick={async () => setCurrency(undefined)}>
|
||||||
@ -431,11 +422,6 @@ export function DestinationSelectionSendCash({
|
|||||||
const currency = parsedInitialAmount?.currency;
|
const currency = parsedInitialAmount?.currency;
|
||||||
|
|
||||||
const [amount, setAmount] = useState(parsedInitialAmountValue);
|
const [amount, setAmount] = useState(parsedInitialAmountValue);
|
||||||
function positiveSetAmount(e: string):void {
|
|
||||||
const value = Number.parseInt(e, 10);
|
|
||||||
if (value < 0) return
|
|
||||||
setAmount(String(value))
|
|
||||||
}
|
|
||||||
const { i18n } = useTranslationContext();
|
const { i18n } = useTranslationContext();
|
||||||
const previous1: Contact[] = [];
|
const previous1: Contact[] = [];
|
||||||
const previous2: Contact[] = [
|
const previous2: Contact[] = [
|
||||||
@ -474,19 +460,13 @@ export function DestinationSelectionSendCash({
|
|||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<AmountField
|
||||||
label="Amount"
|
label={<i18n.Translate>Amount</i18n.Translate>}
|
||||||
type="number"
|
currency={currency}
|
||||||
min="0"
|
|
||||||
variant="filled"
|
|
||||||
required
|
required
|
||||||
error={invalid}
|
handler={{
|
||||||
startAdornment={
|
onInput: async (s) => setAmount(s),
|
||||||
<div style={{ padding: "25px 12px 8px 12px" }}>{currency}</div>
|
value: amount,
|
||||||
}
|
|
||||||
value={amount}
|
|
||||||
onChange={(e) => {
|
|
||||||
positiveSetAmount(e);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -416,9 +416,10 @@ function BitcoinAddressAccount({ field }: { field: TextFieldHandler }): VNode {
|
|||||||
fullWidth
|
fullWidth
|
||||||
value={value}
|
value={value}
|
||||||
error={value !== undefined && !!errors?.value}
|
error={value !== undefined && !!errors?.value}
|
||||||
|
disabled={!field.onInput}
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v);
|
setValue(v);
|
||||||
if (!errors) {
|
if (!errors && field.onInput) {
|
||||||
field.onInput(`payto://bitcoin/${v}`);
|
field.onInput(`payto://bitcoin/${v}`);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -456,9 +457,10 @@ function TalerBankAddressAccount({
|
|||||||
fullWidth
|
fullWidth
|
||||||
value={host}
|
value={host}
|
||||||
error={host !== undefined && !!errors?.host}
|
error={host !== undefined && !!errors?.host}
|
||||||
|
disabled={!field.onInput}
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setHost(v);
|
setHost(v);
|
||||||
if (!errors) {
|
if (!errors && field.onInput) {
|
||||||
field.onInput(`payto://x-taler-bank/${v}/${account}`);
|
field.onInput(`payto://x-taler-bank/${v}/${account}`);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -470,11 +472,12 @@ function TalerBankAddressAccount({
|
|||||||
label="Bank account"
|
label="Bank account"
|
||||||
variant="standard"
|
variant="standard"
|
||||||
fullWidth
|
fullWidth
|
||||||
|
disabled={!field.onInput}
|
||||||
value={account}
|
value={account}
|
||||||
error={account !== undefined && !!errors?.account}
|
error={account !== undefined && !!errors?.account}
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setAccount(v || "");
|
setAccount(v || "");
|
||||||
if (!errors) {
|
if (!errors && field.onInput) {
|
||||||
field.onInput(`payto://x-taler-bank/${host}/${v}`);
|
field.onInput(`payto://x-taler-bank/${host}/${v}`);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -502,9 +505,10 @@ function IbanAddressAccount({ field }: { field: TextFieldHandler }): VNode {
|
|||||||
fullWidth
|
fullWidth
|
||||||
value={number}
|
value={number}
|
||||||
error={number !== undefined && !!errors?.number}
|
error={number !== undefined && !!errors?.number}
|
||||||
|
disabled={!field.onInput}
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setNumber(v);
|
setNumber(v);
|
||||||
if (!errors) {
|
if (!errors && field.onInput) {
|
||||||
field.onInput(`payto://iban/${v}?receiver-name=${name}`);
|
field.onInput(`payto://iban/${v}?receiver-name=${name}`);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -518,10 +522,13 @@ function IbanAddressAccount({ field }: { field: TextFieldHandler }): VNode {
|
|||||||
fullWidth
|
fullWidth
|
||||||
value={name}
|
value={name}
|
||||||
error={name !== undefined && !!errors?.name}
|
error={name !== undefined && !!errors?.name}
|
||||||
|
disabled={!field.onInput}
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setName(v);
|
setName(v);
|
||||||
if (!errors) {
|
if (!errors && field.onInput) {
|
||||||
field.onInput(`payto://iban/${number}?receiver-name=${encodeURIComponent(v)}`);
|
field.onInput(
|
||||||
|
`payto://iban/${number}?receiver-name=${encodeURIComponent(v)}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
Loading…
Reference in New Issue
Block a user