render amount and limit input

This commit is contained in:
Sebastian 2023-10-01 12:50:43 -03:00
parent 1708d49a2d
commit 372ddff917
No known key found for this signature in database
GPG Key ID: 173909D1A5F66069
14 changed files with 201 additions and 96 deletions

View File

@ -19,6 +19,7 @@ import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { State } from "./index.js"; import { State } from "./index.js";
import { format } from "date-fns"; import { format } from "date-fns";
import { Amounts } from "@gnu-taler/taler-util"; import { Amounts } from "@gnu-taler/taler-util";
import { RenderAmount } from "../../pages/PaytoWireTransferForm.js";
export function LoadingUriView({ error }: State.LoadingUriError): VNode { export function LoadingUriView({ error }: State.LoadingUriError): VNode {
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
@ -62,8 +63,8 @@ export function ReadyView({ cashouts, onSelected }: State.Ready): VNode {
? format(item.confirmation_time, "dd/MM/yyyy HH:mm:ss") ? format(item.confirmation_time, "dd/MM/yyyy HH:mm:ss")
: "-"} : "-"}
</td> </td>
<td>{Amounts.stringifyValue(item.amount_debit)}</td> <td><RenderAmount value={Amounts.parseOrThrow(item.amount_debit)} /></td>
<td>{Amounts.stringifyValue(item.amount_credit)}</td> <td><RenderAmount value={Amounts.parseOrThrow(item.amount_credit)} /></td>
<td>{item.status}</td> <td>{item.status}</td>
<td> <td>
<a <a

View File

@ -20,6 +20,7 @@ import { State } from "./index.js";
import { format, isToday } from "date-fns"; import { format, isToday } from "date-fns";
import { Amounts } from "@gnu-taler/taler-util"; import { Amounts } from "@gnu-taler/taler-util";
import { useEffect, useRef } from "preact/hooks"; import { useEffect, useRef } from "preact/hooks";
import { RenderAmount } from "../../pages/PaytoWireTransferForm.js";
export function LoadingUriView({ error }: State.LoadingUriError): VNode { export function LoadingUriView({ error }: State.LoadingUriError): VNode {
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
@ -72,13 +73,7 @@ export function ReadyView({ transactions, onNext, onPrev }: State.Ready): VNode
{txs.map(item => { {txs.map(item => {
const time = item.when.t_ms === "never" ? "" : format(item.when.t_ms, "HH:mm:ss") const time = item.when.t_ms === "never" ? "" : format(item.when.t_ms, "HH:mm:ss")
const amount = <Fragment> const amount = <Fragment>
{item.negative ? "-" : ""} { }
{item.amount ? (
`${Amounts.stringifyValue(item.amount)} ${item.amount.currency
}`
) : (
<span style={{ color: "grey" }}>&lt;{i18n.str`invalid value`}&gt;</span>
)}
</Fragment> </Fragment>
return (<tr key={idx}> return (<tr key={idx}>
<td class="relative py-2 pl-2 pr-2 text-sm "> <td class="relative py-2 pl-2 pr-2 text-sm ">
@ -86,20 +81,26 @@ export function ReadyView({ transactions, onNext, onPrev }: State.Ready): VNode
<dl class="font-normal sm:hidden"> <dl class="font-normal sm:hidden">
<dt class="sr-only sm:hidden"><i18n.Translate>Amount</i18n.Translate></dt> <dt class="sr-only sm:hidden"><i18n.Translate>Amount</i18n.Translate></dt>
<dd class="mt-1 truncate text-gray-700"> <dd class="mt-1 truncate text-gray-700">
{item.negative ? i18n.str`sent` : i18n.str`received`} {item.amount ? ( {item.negative ? i18n.str`sent` : i18n.str`received`}
`${Amounts.stringifyValue(item.amount)}`
{item.amount ? (
<RenderAmount value={item.amount} />
) : ( ) : (
<span style={{ color: "grey" }}>&lt;{i18n.str`invalid value`}&gt;</span> <span style={{ color: "grey" }}>&lt;{i18n.str`invalid value`}&gt;</span>
)}</dd> )}</dd>
<dt class="sr-only sm:hidden"><i18n.Translate>Counterpart</i18n.Translate></dt> <dt class="sr-only sm:hidden"><i18n.Translate>Counterpart</i18n.Translate></dt>
<dd class="mt-1 truncate text-gray-500 sm:hidden"> <dd class="mt-1 truncate text-gray-500 sm:hidden">
{item.negative ? i18n.str`to` : i18n.str`from`} {item.counterpart} {item.negative ? i18n.str`to` : i18n.str`from`} {item.counterpart}
</dd> </dd>
</dl> </dl>
</td> </td>
<td data-negative={item.negative ? "true" : "false"} <td data-negative={item.negative ? "true" : "false"}
class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 data-[negative=false]:text-green-600 data-[negative=true]:text-red-600"> class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 data-[negative=false]:text-green-600 data-[negative=true]:text-red-600">
{amount} {item.amount ? (<RenderAmount value={item.amount} negative={item.negative} />
) : (
<span style={{ color: "grey" }}>&lt;{i18n.str`invalid value`}&gt;</span>
)}
</td> </td>
<td class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500">{item.counterpart}</td> <td class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500">{item.counterpart}</td>
<td class="px-3 py-3.5 text-sm text-gray-500 break-all min-w-md">{item.subject}</td> <td class="px-3 py-3.5 text-sm text-gray-500 break-all min-w-md">{item.subject}</td>

View File

@ -31,6 +31,7 @@ import { getInitialBackendBaseURL } from "../hooks/backend.js";
import { BANK_INTEGRATION_PROTOCOL_VERSION, useConfigState } from "../hooks/config.js"; import { BANK_INTEGRATION_PROTOCOL_VERSION, useConfigState } from "../hooks/config.js";
import { ErrorLoading } from "./ErrorLoading.js"; import { ErrorLoading } from "./ErrorLoading.js";
import { BankFrame } from "../pages/BankFrame.js"; import { BankFrame } from "../pages/BankFrame.js";
import { ConfigStateProvider } from "../context/config.js";
const WITH_LOCAL_STORAGE_CACHE = false; const WITH_LOCAL_STORAGE_CACHE = false;
/** /**
@ -84,11 +85,11 @@ function VersionCheck({ children }: { children: ComponentChildren }): VNode {
</BankFrame> </BankFrame>
} }
if (checked.type === "ok") { if (checked.type === "ok") {
return <Fragment>{children}</Fragment> return <ConfigStateProvider value={checked.result}>{children}</ConfigStateProvider>
} }
return <BankFrame> return <BankFrame>
<ErrorLoading error={checked.result}/> <ErrorLoading error={checked.result} />
</BankFrame> </BankFrame>
} }

View File

@ -0,0 +1,52 @@
/*
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 { ComponentChildren, createContext, h, VNode } from "preact";
import { useContext } from "preact/hooks";
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
export type Type = Required<SandboxBackend.Config>;
const initial: Type = {
name: "",
version: "0:0:0",
currency_fraction_digits: 2,
currency_fraction_limit: 2,
fiat_currency: "",
have_cashout: false,
};
const Context = createContext<Type>(initial);
export const useConfigContext = (): Type => useContext(Context);
export const ConfigStateProvider = ({
value,
children,
}: {
value: Type,
children: ComponentChildren;
}): VNode => {
return h(Context.Provider, {
value,
children,
});
};

View File

@ -107,9 +107,27 @@ namespace SandboxBackend {
name: string; name: string;
// API version in the form $n:$n:$n // API version in the form $n:$n:$n
version: string; version: string;
// Contains ratios and fees related to buying // If 'true', the server provides local currency
// and selling the circuit currency. // conversion support.
ratios_and_fees: RatiosAndFees; // If missing or false, some parts of the API
// are not supported and return 404.
have_cashout?: boolean;
// Fiat currency. That is the currency in which
// cash-out operations ultimately wire money.
// Only applicable if have_cashout=true.
fiat_currency?: string;
// How many digits should the amounts be rendered
// with by default. Small capitals should
// be used to render fractions beyond the number
// given here (like on gas stations).
currency_fraction_digits?: number;
// How many decimal digits an operation can
// have. Wire transfers with more decimal
// digits will not be accepted.
currency_fraction_limit?: number;
} }
interface RatiosAndFees { interface RatiosAndFees {
// Exchange rate to buy the circuit currency from fiat. // Exchange rate to buy the circuit currency from fiat.

View File

@ -18,13 +18,13 @@ async function getConfigState(
return result.data; return result.data;
} }
type Result = undefined export type ConfigResult = undefined
| { type: "ok", result: SandboxBackend.Config } | { type: "ok", result: Required<SandboxBackend.Config> }
| { type: "wrong", result: SandboxBackend.Config } | { type: "wrong", result: SandboxBackend.Config }
| { type: "error", result: HttpError<SandboxBackend.SandboxError> } | { type: "error", result: HttpError<SandboxBackend.SandboxError> }
export function useConfigState(): Result { export function useConfigState(): ConfigResult {
const [checked, setChecked] = useState<Result>() const [checked, setChecked] = useState<ConfigResult>()
const { request } = useApiContext(); const { request } = useApiContext();
useEffect(() => { useEffect(() => {
@ -32,15 +32,23 @@ export function useConfigState(): Result {
.then((result) => { .then((result) => {
const r = LibtoolVersion.compare(BANK_INTEGRATION_PROTOCOL_VERSION, result.version) const r = LibtoolVersion.compare(BANK_INTEGRATION_PROTOCOL_VERSION, result.version)
if (r?.compatible) { if (r?.compatible) {
setChecked({ type: "ok",result }); const complete: Required<SandboxBackend.Config> = {
currency_fraction_digits: result.currency_fraction_digits ?? 2,
currency_fraction_limit: result.currency_fraction_limit ?? 2,
fiat_currency: "",
have_cashout: result.have_cashout ?? false,
name: result.name,
version: result.version,
}
setChecked({ type: "ok", result: complete });
} else { } else {
setChecked({ type: "wrong",result }) setChecked({ type: "wrong", result })
} }
}) })
.catch((error: unknown) => { .catch((error: unknown) => {
if (error instanceof RequestError) { if (error instanceof RequestError) {
const result = error.cause const result = error.cause
setChecked({ type:"error", result }); setChecked({ type: "error", result });
} }
}); });
}, []); }, []);

View File

@ -27,6 +27,7 @@ import { CopyButton, CopyIcon } from "../components/CopyButton.js";
import logo from "../assets/logo-2021.svg"; import logo from "../assets/logo-2021.svg";
import { useAccountDetails } from "../hooks/access.js"; import { useAccountDetails } from "../hooks/access.js";
import { Attention } from "../components/Attention.js"; import { Attention } from "../components/Attention.js";
import { RenderAmount } from "./PaytoWireTransferForm.js";
const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined; const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : undefined; const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : undefined;
@ -87,7 +88,7 @@ export function BankFrame({
class="h-8 w-auto" class="h-8 w-auto"
src={logo} src={logo}
alt="Taler" alt="Taler"
style={{ height: 35, margin: 10 }} style={{ height: "1.5rem", margin: ".5rem" }}
/> />
</a> </a>
</div> </div>
@ -322,10 +323,10 @@ function MaybeShowDebugInfo({ info }: { info: any }): VNode {
const [settings] = useSettings() const [settings] = useSettings()
if (settings.showDebugInfo) { if (settings.showDebugInfo) {
return <pre class="whitespace-break-spaces "> return <pre class="whitespace-break-spaces ">
{info} {info}
</pre> </pre>
} }
return <Fragment /> return <Fragment />
} }
@ -333,19 +334,19 @@ function StatusBanner(): VNode {
const notifs = useNotifications() const notifs = useNotifications()
if (notifs.length === 0) return <Fragment /> if (notifs.length === 0) return <Fragment />
return <div class="fixed z-20 w-full p-4"> { return <div class="fixed z-20 w-full p-4"> {
notifs.map(n => { notifs.map(n => {
switch (n.message.type) { switch (n.message.type) {
case "error": case "error":
return <Attention type="danger" title={n.message.title} onClose={() => { return <Attention type="danger" title={n.message.title} onClose={() => {
n.remove() n.remove()
}}> }}>
{n.message.description && {n.message.description &&
<div class="mt-2 text-sm text-red-700"> <div class="mt-2 text-sm text-red-700">
{n.message.description} {n.message.description}
</div> </div>
} }
<MaybeShowDebugInfo info={n.message.debug} /> <MaybeShowDebugInfo info={n.message.debug} />
{/* <a href="#" class="text-gray-500"> {/* <a href="#" class="text-gray-500">
show debug info show debug info
</a> </a>
{n.message.debug && {n.message.debug &&
@ -353,13 +354,13 @@ function StatusBanner(): VNode {
{n.message.debug} {n.message.debug}
</div> </div>
} */} } */}
</Attention> </Attention>
case "info": case "info":
return <Attention type="success" title={n.message.title} onClose={() => { return <Attention type="success" title={n.message.title} onClose={() => {
n.remove(); n.remove();
}} /> }} />
} }
})} })}
</div> </div>
} }
@ -430,9 +431,8 @@ function AccountBalance({ account }: { account: string }): VNode {
const result = useAccountDetails(account); const result = useAccountDetails(account);
if (!result.ok) return <div /> if (!result.ok) return <div />
return <div> return <RenderAmount
{Amounts.currencyOf(result.data.balance.amount)} value={Amounts.parseOrThrow(result.data.balance.amount)}
&nbsp;{result.data.balance.credit_debit_indicator === "debit" ? "-" : ""} negative={result.data.balance.credit_debit_indicator === "debit"}
{Amounts.stringifyValue(result.data.balance.amount)} />
</div>
} }

View File

@ -30,7 +30,7 @@ export function PaymentOptions({ limit, goToConfirmOperation }: { limit: AmountJ
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
const [settings] = useSettings(); const [settings] = useSettings();
const [tab, setTab] = useState<"charge-wallet" | "wire-transfer" | undefined>("wire-transfer"); const [tab, setTab] = useState<"charge-wallet" | "wire-transfer" | undefined>();
return ( return (
<div class="mt-2"> <div class="mt-2">
@ -47,7 +47,7 @@ export function PaymentOptions({ limit, goToConfirmOperation }: { limit: AmountJ
setTab("charge-wallet") setTab("charge-wallet")
}} /> }} />
<span class="flex flex-1"> <span class="flex flex-1">
<div class="text-lg mr-2">&#x1F4B5;</div> <div class="text-4xl mr-4 my-auto">&#x1F4B5;</div>
<span class="flex flex-col"> <span class="flex flex-col">
<span id="project-type-0-label" class="block text-sm font-medium text-gray-900"> <span id="project-type-0-label" class="block text-sm font-medium text-gray-900">
<i18n.Translate>a <b>Taler</b> wallet</i18n.Translate> <i18n.Translate>a <b>Taler</b> wallet</i18n.Translate>
@ -76,7 +76,7 @@ export function PaymentOptions({ limit, goToConfirmOperation }: { limit: AmountJ
setTab("wire-transfer") setTab("wire-transfer")
}} /> }} />
<span class="flex flex-1"> <span class="flex flex-1">
<div class="text-lg mr-2">&#x2194;</div> <div class="text-4xl mr-4 my-auto">&#x2194;</div>
<span class="flex flex-col"> <span class="flex flex-col">
<span id="project-type-1-label" class="block text-sm font-medium text-gray-900"> <span id="project-type-1-label" class="block text-sm font-medium text-gray-900">
<i18n.Translate>another bank account</i18n.Translate> <i18n.Translate>another bank account</i18n.Translate>

View File

@ -39,6 +39,8 @@ import {
undefinedIfEmpty, undefinedIfEmpty,
validateIBAN, validateIBAN,
} from "../utils.js"; } from "../utils.js";
import { useConfigState } from "../hooks/config.js";
import { useConfigContext } from "../context/config.js";
const logger = new Logger("PaytoWireTransferForm"); const logger = new Logger("PaytoWireTransferForm");
@ -55,7 +57,7 @@ export function PaytoWireTransferForm({
onCancel: (() => void) | undefined; onCancel: (() => void) | undefined;
limit: AmountJson; limit: AmountJson;
}): VNode { }): VNode {
const [isRawPayto, setIsRawPayto] = useState(true); const [isRawPayto, setIsRawPayto] = useState(false);
// FIXME: remove this // FIXME: remove this
const [iban, setIban] = useState<string | undefined>("DE4745461198061"); const [iban, setIban] = useState<string | undefined>("DE4745461198061");
const [subject, setSubject] = useState<string | undefined>("ASD"); const [subject, setSubject] = useState<string | undefined>("ASD");
@ -285,7 +287,7 @@ export function PaytoWireTransferForm({
<div class="sm:col-span-5"> <div class="sm:col-span-5">
<label for="amount" class="block text-sm font-medium leading-6 text-gray-900">{i18n.str`Amount`}</label> <label for="amount" class="block text-sm font-medium leading-6 text-gray-900">{i18n.str`Amount`}</label>
<Amount <InputAmount
name="amount" name="amount"
left left
currency={limit.currency} currency={limit.currency}
@ -372,7 +374,9 @@ export function doAutoFocus(element: HTMLElement | null) {
} }
} }
export function Amount( const FRAC_SEPARATOR = "."
export function InputAmount(
{ {
currency, currency,
name, name,
@ -390,6 +394,7 @@ export function Amount(
}, },
ref: Ref<HTMLInputElement>, ref: Ref<HTMLInputElement>,
): VNode { ): VNode {
const cfg = useConfigContext()
return ( return (
<div class="mt-2"> <div class="mt-2">
<div class="flex rounded-md shadow-sm border-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600"> <div class="flex rounded-md shadow-sm border-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600">
@ -409,10 +414,14 @@ export function Amount(
autocomplete="off" autocomplete="off"
value={value ?? ""} value={value ?? ""}
disabled={!onChange} disabled={!onChange}
onInput={(e): void => { onInput={(e) => {
if (onChange) { if (!onChange) return;
onChange(e.currentTarget.value); const l = e.currentTarget.value.length
const sep_pos = e.currentTarget.value.indexOf(FRAC_SEPARATOR)
if (sep_pos !== -1 && l - sep_pos - 1 > cfg.currency_fraction_limit) {
e.currentTarget.value = e.currentTarget.value.substring(0, sep_pos + cfg.currency_fraction_limit + 1)
} }
onChange(e.currentTarget.value);
}} }}
/> />
</div> </div>
@ -421,3 +430,21 @@ export function Amount(
); );
} }
export function RenderAmount({ value, negative }: { value: AmountJson, negative?: boolean }): VNode {
const cfg = useConfigContext()
const str = Amounts.stringifyValue(value)
const sep_pos = str.indexOf(FRAC_SEPARATOR)
if (sep_pos !== -1 && str.length - sep_pos - 1 > cfg.currency_fraction_digits) {
const limit = sep_pos + cfg.currency_fraction_digits + 1
const normal = str.substring(0, limit)
const small = str.substring(limit)
return <span class="whitespace-nowrap">
{negative ? "-" : undefined}
{value.currency} {normal} <sup class="-ml-2">{small}</sup>
</span>
}
return <span class="whitespace-nowrap">
{negative ? "-" : undefined}
{value.currency} {str}
</span>
}

View File

@ -34,13 +34,13 @@ import { forwardRef } from "preact/compat";
import { useEffect, useRef, useState } from "preact/hooks"; import { useEffect, useRef, useState } from "preact/hooks";
import { useAccessAPI } from "../hooks/access.js"; import { useAccessAPI } from "../hooks/access.js";
import { buildRequestErrorMessage, undefinedIfEmpty } from "../utils.js"; import { buildRequestErrorMessage, undefinedIfEmpty } from "../utils.js";
import { Amount, doAutoFocus } from "./PaytoWireTransferForm.js"; import { InputAmount, doAutoFocus } from "./PaytoWireTransferForm.js";
import { useSettings } from "../hooks/settings.js"; import { useSettings } from "../hooks/settings.js";
import { OperationState } from "./OperationState/index.js"; import { OperationState } from "./OperationState/index.js";
import { Attention } from "../components/Attention.js"; import { Attention } from "../components/Attention.js";
const logger = new Logger("WalletWithdrawForm"); const logger = new Logger("WalletWithdrawForm");
const RefAmount = forwardRef(Amount); const RefAmount = forwardRef(InputAmount);
function OldWithdrawalForm({ goToConfirmOperation, limit, onCancel, focus }: { function OldWithdrawalForm({ goToConfirmOperation, limit, onCancel, focus }: {

View File

@ -38,6 +38,7 @@ import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
import { useAccessAnonAPI } from "../hooks/access.js"; import { useAccessAnonAPI } from "../hooks/access.js";
import { buildRequestErrorMessage, undefinedIfEmpty } from "../utils.js"; import { buildRequestErrorMessage, undefinedIfEmpty } from "../utils.js";
import { useSettings } from "../hooks/settings.js"; import { useSettings } from "../hooks/settings.js";
import { RenderAmount } from "./PaytoWireTransferForm.js";
const logger = new Logger("WithdrawalConfirmationQuestion"); const logger = new Logger("WithdrawalConfirmationQuestion");
@ -318,7 +319,7 @@ export function WithdrawalConfirmationQuestion({
<div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt class="text-sm font-medium leading-6 text-gray-900">Amount</dt> <dt class="text-sm font-medium leading-6 text-gray-900">Amount</dt>
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0">
{Amounts.currencyOf(details.amount)} {Amounts.stringifyValue(details.amount)} <RenderAmount value={details.amount} />
</dd> </dd>
</div> </div>
</dl> </dl>

View File

@ -4,6 +4,7 @@ import { handleNotOkResult } from "../HomePage.js";
import { AccountAction } from "./Home.js"; import { AccountAction } from "./Home.js";
import { Amounts } from "@gnu-taler/taler-util"; import { Amounts } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { RenderAmount } from "../PaytoWireTransferForm.js";
interface Props { interface Props {
onAction: (type: AccountAction, account: string) => void; onAction: (type: AccountAction, account: string) => void;
@ -88,12 +89,7 @@ export function AccountList({ account, onAction, onCreateAccount }: Props): VNod
i18n.str`unknown` i18n.str`unknown`
) : ( ) : (
<span class="amount"> <span class="amount">
{balanceIsDebit ? <b>-</b> : null} <RenderAmount value={balance} negative={balanceIsDebit} />
<span class="value">{`${Amounts.stringifyValue(
balance,
)}`}</span>
&nbsp;
<span class="currency">{`${balance.currency}`}</span>
</span> </span>
)} )}
</td> </td>

View File

@ -45,7 +45,7 @@ import {
undefinedIfEmpty, undefinedIfEmpty,
} from "../../utils.js"; } from "../../utils.js";
import { handleNotOkResult } from "../HomePage.js"; import { handleNotOkResult } from "../HomePage.js";
import { Amount } from "../PaytoWireTransferForm.js"; import { InputAmount } from "../PaytoWireTransferForm.js";
import { ShowAccountDetails } from "../ShowAccountDetails.js"; import { ShowAccountDetails } from "../ShowAccountDetails.js";
import { UpdateAccountPassword } from "../UpdateAccountPassword.js"; import { UpdateAccountPassword } from "../UpdateAccountPassword.js";
@ -342,7 +342,7 @@ function CreateCashout({
</label> </label>
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
<Amount <InputAmount
name="amount" name="amount"
currency={amount.currency} currency={amount.currency}
value={form.amount} value={form.amount}
@ -372,7 +372,7 @@ function CreateCashout({
</fieldset> </fieldset>
<fieldset> <fieldset>
<label for="balance-now">{i18n.str`Balance now`}</label> <label for="balance-now">{i18n.str`Balance now`}</label>
<Amount <InputAmount
name="banace-now" name="banace-now"
currency={balance.currency} currency={balance.currency}
value={Amounts.stringifyValue(balance)} value={Amounts.stringifyValue(balance)}
@ -382,7 +382,7 @@ function CreateCashout({
<label for="total-cost" <label for="total-cost"
style={{ fontWeight: "bold", color: "red" }} style={{ fontWeight: "bold", color: "red" }}
>{i18n.str`Total cost`}</label> >{i18n.str`Total cost`}</label>
<Amount <InputAmount
name="total-cost" name="total-cost"
currency={balance.currency} currency={balance.currency}
value={Amounts.stringifyValue(calc.debit)} value={Amounts.stringifyValue(calc.debit)}
@ -390,7 +390,7 @@ function CreateCashout({
</fieldset> </fieldset>
<fieldset> <fieldset>
<label for="balance-after">{i18n.str`Balance after`}</label> <label for="balance-after">{i18n.str`Balance after`}</label>
<Amount <InputAmount
name="balance-after" name="balance-after"
currency={balance.currency} currency={balance.currency}
value={balanceAfter ? Amounts.stringifyValue(balanceAfter) : ""} value={balanceAfter ? Amounts.stringifyValue(balanceAfter) : ""}
@ -400,7 +400,7 @@ function CreateCashout({
<Fragment> <Fragment>
<fieldset> <fieldset>
<label for="amount-conversiojn">{i18n.str`Amount after conversion`}</label> <label for="amount-conversiojn">{i18n.str`Amount after conversion`}</label>
<Amount <InputAmount
name="amount-conversion" name="amount-conversion"
currency={fiatCurrency} currency={fiatCurrency}
value={Amounts.stringifyValue(calc.beforeFee)} value={Amounts.stringifyValue(calc.beforeFee)}
@ -409,7 +409,7 @@ function CreateCashout({
<fieldset> <fieldset>
<label form="cashout-fee">{i18n.str`Cashout fee`}</label> <label form="cashout-fee">{i18n.str`Cashout fee`}</label>
<Amount <InputAmount
name="cashout-fee" name="cashout-fee"
currency={fiatCurrency} currency={fiatCurrency}
value={Amounts.stringifyValue(sellFee)} value={Amounts.stringifyValue(sellFee)}
@ -421,7 +421,7 @@ function CreateCashout({
<label for="total" <label for="total"
style={{ fontWeight: "bold", color: "green" }} style={{ fontWeight: "bold", color: "green" }}
>{i18n.str`Total cashout transfer`}</label> >{i18n.str`Total cashout transfer`}</label>
<Amount <InputAmount
name="total" name="total"
currency={fiatCurrency} currency={fiatCurrency}
value={Amounts.stringifyValue(calc.credit)} value={Amounts.stringifyValue(calc.credit)}

View File

@ -62,10 +62,10 @@ export function HistoryItem(props: { tx: Transaction }): VNode {
WithdrawalType.TalerBankIntegrationApi WithdrawalType.TalerBankIntegrationApi
? !tx.withdrawalDetails.confirmed ? !tx.withdrawalDetails.confirmed
? i18n.str`Need approval in the Bank` ? i18n.str`Need approval in the Bank`
: i18n.str`Exchange is waiting the wire transfer` : i18n.str`Waiting for wire transfer to complete`
: tx.withdrawalDetails.type === WithdrawalType.ManualTransfer : tx.withdrawalDetails.type === WithdrawalType.ManualTransfer
? i18n.str`Exchange is waiting the wire transfer` ? i18n.str`Waiting for wire transfer to complete`
: "" //pending but no message : "" //pending but no message
: undefined : undefined
} }
/> />
@ -88,8 +88,8 @@ export function HistoryItem(props: { tx: Transaction }): VNode {
? i18n.str`Need approval in the Bank` ? i18n.str`Need approval in the Bank`
: i18n.str`Exchange is waiting the wire transfer` : i18n.str`Exchange is waiting the wire transfer`
: tx.withdrawalDetails.type === WithdrawalType.ManualTransfer : tx.withdrawalDetails.type === WithdrawalType.ManualTransfer
? i18n.str`Exchange is waiting the wire transfer` ? i18n.str`Exchange is waiting the wire transfer`
: "" //pending but no message : "" //pending but no message
: undefined : undefined
} }
/> />
@ -267,14 +267,14 @@ function Layout(props: LayoutProps): VNode {
style={{ style={{
backgroundColor: backgroundColor:
props.currentState === TransactionMajorState.Pending || props.currentState === TransactionMajorState.Pending ||
props.currentState === TransactionMajorState.Dialog props.currentState === TransactionMajorState.Dialog
? "lightcyan" ? "lightcyan"
: props.currentState === TransactionMajorState.Failed : props.currentState === TransactionMajorState.Failed
? "#ff000040" ? "#ff000040"
: props.currentState === TransactionMajorState.Aborted || : props.currentState === TransactionMajorState.Aborted ||
props.currentState === TransactionMajorState.Aborting props.currentState === TransactionMajorState.Aborting
? "#00000010" ? "#00000010"
: "inherit", : "inherit",
alignItems: "center", alignItems: "center",
}} }}
> >
@ -353,10 +353,10 @@ function TransactionAmount(props: TransactionAmountProps): VNode {
props.currentState !== TransactionMajorState.Done props.currentState !== TransactionMajorState.Done
? "gray" ? "gray"
: sign === "+" : sign === "+"
? "darkgreen" ? "darkgreen"
: sign === "-" : sign === "-"
? "darkred" ? "darkred"
: undefined, : undefined,
}} }}
> >
<ExtraLargeText> <ExtraLargeText>