diff options
5 files changed, 134 insertions, 91 deletions
diff --git a/packages/taler-wallet-webextension/src/mui/input/FormLabel.tsx b/packages/taler-wallet-webextension/src/mui/input/FormLabel.tsx index fb2df1cc3..1d4b5eff5 100644 --- a/packages/taler-wallet-webextension/src/mui/input/FormLabel.tsx +++ b/packages/taler-wallet-webextension/src/mui/input/FormLabel.tsx @@ -68,7 +68,7 @@ export function FormLabel({ return ( <label data-focused={fcs.focused} - data-error={fcs.error} + data-error={!fcs.error ? undefined : true} data-disabled={fcs.disabled} class={[_class, root, theme.typography.body1].join(" ")} {...rest} @@ -77,7 +77,9 @@ export function FormLabel({ }} > {children} - {fcs.required && <span data-error={fcs.error}> {"*"}</span>} + {fcs.required && ( + <span data-error={!fcs.error ? undefined : true}> {"*"}</span> + )} </label> ); } diff --git a/packages/taler-wallet-webextension/src/mui/input/InputBase.tsx b/packages/taler-wallet-webextension/src/mui/input/InputBase.tsx index fce82f9d2..80f5bd44e 100644 --- a/packages/taler-wallet-webextension/src/mui/input/InputBase.tsx +++ b/packages/taler-wallet-webextension/src/mui/input/InputBase.tsx @@ -65,7 +65,7 @@ export function InputBaseRoot({ data-multiline={multiline} data-hasStart={!!startAdornment} data-hasEnd={!!endAdornment} - data-error={error} + data-error={!error ? undefined : true} class={[ _class, rootStyle, diff --git a/packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts b/packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts index a9e8dfb30..6c113d732 100644 --- a/packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts @@ -67,15 +67,11 @@ export function useComponentState( } const paytoUriError = - payto === "" - ? undefined - : !uri - ? "the uri is not ok" - : found - ? "that account is already present" - : undefined; + found + ? "that account is already present" + : undefined; - const unableToAdd = !type || !alias || paytoUriError; + const unableToAdd = !type || !alias || !!paytoUriError || !uri; return { status: "ready", diff --git a/packages/taler-wallet-webextension/src/wallet/AddAccount/views.tsx b/packages/taler-wallet-webextension/src/wallet/AddAccount/views.tsx index fa7014d70..d6ab7e967 100644 --- a/packages/taler-wallet-webextension/src/wallet/AddAccount/views.tsx +++ b/packages/taler-wallet-webextension/src/wallet/AddAccount/views.tsx @@ -105,7 +105,11 @@ export function ReadyView({ > <i18n.Translate>Cancel</i18n.Translate> </Button> - <Button variant="contained" onClick={onAccountAdded.onClick}> + <Button + variant="contained" + onClick={onAccountAdded.onClick} + disabled={!onAccountAdded.onClick} + > <i18n.Translate>Add</i18n.Translate> </Button> </footer> @@ -113,6 +117,118 @@ export function ReadyView({ ); } +function BitcoinAddressAccount({ field }: { field: TextFieldHandler }): VNode { + const { i18n } = useTranslationContext(); + const [value, setValue] = useState<string | undefined>(undefined); + const errors = undefinedIfEmpty({ + value: !value ? i18n.str`Can't be empty` : undefined, + }); + return ( + <Fragment> + <TextField + label="Bitcoin address" + variant="standard" + fullWidth + value={value} + error={value !== undefined && !!errors?.value} + onChange={(v) => { + setValue(v); + if (!errors) { + field.onInput(`payto://bitcoin/${value}`); + } + }} + /> + {value !== undefined && errors?.value && ( + <ErrorMessage title={<span>{errors?.value}</span>} /> + )} + </Fragment> + ); +} + +function undefinedIfEmpty<T extends object>(obj: T): T | undefined { + return Object.keys(obj).some((k) => (obj as any)[k] !== undefined) + ? obj + : undefined; +} + +function TalerBankAddressAccount({ + field, +}: { + field: TextFieldHandler; +}): VNode { + const { i18n } = useTranslationContext(); + const [host, setHost] = useState<string | undefined>(undefined); + const [account, setAccount] = useState<string | undefined>(undefined); + const errors = undefinedIfEmpty({ + host: !host ? i18n.str`Can't be empty` : undefined, + account: !account ? i18n.str`Can't be empty` : undefined, + }); + return ( + <Fragment> + <TextField + label="Bank host" + variant="standard" + fullWidth + value={host} + error={host !== undefined && !!errors?.host} + onChange={(v) => { + setHost(v); + if (!errors) { + field.onInput(`payto://x-taler-bank/${host}/${account}`); + } + }} + />{" "} + {host !== undefined && errors?.host && ( + <ErrorMessage title={<span>{errors?.host}</span>} /> + )} + <TextField + label="Bank account" + variant="standard" + fullWidth + value={account} + error={account !== undefined && !!errors?.account} + onChange={(v) => { + setAccount(v || ""); + if (!errors) { + field.onInput(`payto://x-taler-bank/${host}/${account}`); + } + }} + />{" "} + {account !== undefined && errors?.account && ( + <ErrorMessage title={<span>{errors?.account}</span>} /> + )} + </Fragment> + ); +} + +function IbanAddressAccount({ field }: { field: TextFieldHandler }): VNode { + const { i18n } = useTranslationContext(); + const [value, setValue] = useState<string | undefined>(undefined); + const errors = undefinedIfEmpty({ + value: !value ? i18n.str`Can't be empty` : undefined, + }); + return ( + <Fragment> + <TextField + label="IBAN number" + variant="standard" + fullWidth + value={value} + error={value !== undefined && !!errors?.value} + onChange={(v) => { + setValue(v); + if (!errors) { + field.onInput(`payto://iba/${value}`); + } + }} + /> + {value !== undefined && errors?.value && ( + <ErrorMessage title={<span>{errors?.value}</span>} /> + )} + </Fragment> + ); +} + function CustomFieldByAccountType({ type, field, @@ -120,84 +236,14 @@ function CustomFieldByAccountType({ type: string; field: TextFieldHandler; }): VNode { - const p = parsePaytoUri(field.value); - const parts = !p ? [] : p.targetPath.split("/"); - const initialPart1 = parts.length > 0 ? parts[0] : ""; - const initialPart2 = parts.length > 1 ? parts[1] : ""; - const [part1, setPart1] = useState(initialPart1); - const [part2, setPart2] = useState(initialPart2); - function updateField(): void { - if (part1 && part2) { - field.onInput(`payto://${type}/${part1}/${part2}`); - } else { - if (part1) field.onInput(`payto://${type}/${part1}`); - } - } - if (type === "bitcoin") { - return ( - <Fragment> - {field.error && <ErrorMessage title={<span>{field.error}</span>} />} - <TextField - label="Bitcoin address" - variant="standard" - required - fullWidth - value={part1} - onChange={(v) => { - setPart1(v); - updateField(); - }} - /> - </Fragment> - ); + return <BitcoinAddressAccount field={field} />; } if (type === "x-taler-bank") { - return ( - <Fragment> - {field.error && <ErrorMessage title={<span>{field.error}</span>} />} - <TextField - label="Bank host" - variant="standard" - required - fullWidth - value={part1} - onChange={(v) => { - setPart1(v); - updateField(); - }} - />{" "} - <TextField - label="Bank account" - variant="standard" - required - fullWidth - value={part2} - onChange={(v) => { - setPart2(v); - updateField(); - }} - /> - </Fragment> - ); + return <TalerBankAddressAccount field={field} />; } if (type === "iban") { - return ( - <Fragment> - {field.error && <ErrorMessage title={<span>{field.error}</span>} />} - <TextField - label="IBAN number" - variant="standard" - required - fullWidth - value={part1} - onChange={(v) => { - setPart1(v); - updateField(); - }} - /> - </Fragment> - ); + return <IbanAddressAccount field={field} />; } return <Fragment />; } diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts index 686cfb4b4..b3a377040 100644 --- a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts @@ -178,12 +178,11 @@ export function useComponentState( : undefined; const unableToDeposit = - !parsedAmount || - selectedAccount === undefined || - Amounts.isZero(totalToDeposit) || - fee === undefined || - amountError !== undefined; - // console.log(parsedAmount, selectedAccount, fee, totalToDeposit, amountError) + !parsedAmount || //no amount specified + selectedAccount === undefined || //no account selected + Amounts.isZero(totalToDeposit) || //deposit may be zero because of fee + fee === undefined || //no fee calculated yet + amountError !== undefined; //amount field may be invalid async function doSend(): Promise<void> { if (!selectedAccount || !parsedAmount || !currency) return; |