show deposit transaction info

This commit is contained in:
Sebastian 2023-01-15 17:49:57 -03:00
parent fc38d0da95
commit bd57fa46a4
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
3 changed files with 173 additions and 142 deletions

View File

@ -29,13 +29,14 @@ import { alertFromError, useAlertContext } from "../../context/alert.js";
import { useBackendContext } from "../../context/backend.js"; import { useBackendContext } from "../../context/backend.js";
import { useTranslationContext } from "../../context/translation.js"; import { useTranslationContext } from "../../context/translation.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { RecursiveState } from "../../utils/index.js";
import { Props, State } from "./index.js"; import { Props, State } from "./index.js";
export function useComponentState({ export function useComponentState({
amount: amountStr, amount: amountStr,
onCancel, onCancel,
onSuccess, onSuccess,
}: Props): State { }: Props): RecursiveState<State> {
const api = useBackendContext(); const api = useBackendContext();
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
const { pushAlertOnError } = useAlertContext(); const { pushAlertOnError } = useAlertContext();
@ -49,9 +50,7 @@ export function useComponentState({
); );
const { accounts } = await api.wallet.call( const { accounts } = await api.wallet.call(
WalletApiOperation.ListKnownBankAccounts, WalletApiOperation.ListKnownBankAccounts,
{ { currency },
currency,
},
); );
return { accounts, balances }; return { accounts, balances };
@ -64,10 +63,8 @@ export function useComponentState({
? Amounts.zeroOfCurrency(currency) ? Amounts.zeroOfCurrency(currency)
: undefined; : undefined;
// const [accountIdx, setAccountIdx] = useState<number>(0); // const [accountIdx, setAccountIdx] = useState<number>(0);
const [amount, setAmount] = useState<AmountJson>(initialValue ?? ({} as any));
const [selectedAccount, setSelectedAccount] = useState<PaytoUri>(); const [selectedAccount, setSelectedAccount] = useState<PaytoUri>();
const [fee, setFee] = useState<DepositGroupFees | undefined>(undefined);
const [addingAccount, setAddingAccount] = useState(false); const [addingAccount, setAddingAccount] = useState(false);
if (!currency) { if (!currency) {
@ -91,7 +88,12 @@ export function useComponentState({
} }
const { accounts, balances } = hook.response; const { accounts, balances } = hook.response;
// const parsedAmount = Amounts.parse(`${currency}:${amount}`); async function updateAccountFromList(accountStr: string): Promise<void> {
const uri = !accountStr ? undefined : parsePaytoUri(accountStr);
if (uri) {
setSelectedAccount(uri);
}
}
if (addingAccount) { if (addingAccount) {
return { return {
@ -139,48 +141,44 @@ 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) { return () => {
getFeeForAmount(currentAccount, amount, api.wallet).then((initialFee) => { // eslint-disable-next-line react-hooks/rules-of-hooks
setFee(initialFee); const [amount, setAmount] = useState<AmountJson>(
initialValue ?? ({} as any),
);
const amountStr = Amounts.stringify(amount);
const depositPaytoUri = `payto://${currentAccount.targetType}/${currentAccount.targetPath}`;
// eslint-disable-next-line react-hooks/rules-of-hooks
const hook = useAsyncAsHook(async () => {
const fee = await api.wallet.call(WalletApiOperation.GetFeeForDeposit, {
amount: amountStr,
depositPaytoUri,
}); });
return { fee };
}, [amountStr, depositPaytoUri]);
if (!hook) {
return { return {
status: "loading", status: "loading",
error: undefined, error: undefined,
}; };
} }
if (hook.hasError) {
return {
status: "error",
error: alertFromError(
i18n.str`Could not load fee for amount ${amountStr}`,
hook,
),
};
}
const { fee } = hook.response;
const accountMap = createLabelsForBankAccount(accounts); const accountMap = createLabelsForBankAccount(accounts);
async function updateAccountFromList(accountStr: string): Promise<void> {
const uri = !accountStr ? undefined : parsePaytoUri(accountStr);
if (uri) {
try {
const result = await getFeeForAmount(uri, amount, api.wallet);
setSelectedAccount(uri);
setFee(result);
} catch (e) {
setSelectedAccount(uri);
setFee(undefined);
}
}
}
async function updateAmount(newAmount: AmountJson): Promise<void> {
// const parsed = Amounts.parse(`${currency}:${numStr}`);
try {
const result = await getFeeForAmount(
currentAccount,
newAmount,
api.wallet,
);
setAmount(newAmount);
setFee(result);
} catch (e) {
setAmount(newAmount);
setFee(undefined);
}
}
const totalFee = const totalFee =
fee !== undefined fee !== undefined
? Amounts.sum([fee.wire, fee.coin, fee.refresh]).amount ? Amounts.sum([fee.wire, fee.coin, fee.refresh]).amount
@ -221,7 +219,7 @@ export function useComponentState({
currency, currency,
amount: { amount: {
value: amount, value: amount,
onInput: pushAlertOnError(updateAmount), onInput: pushAlertOnError(async (a) => setAmount(a)),
error: amountError, error: amountError,
}, },
onAddAccount: { onAddAccount: {
@ -245,22 +243,8 @@ export function useComponentState({
}, },
totalFee, totalFee,
totalToDeposit, totalToDeposit,
// currentAccount,
// parsedAmount,
}; };
} };
async function getFeeForAmount(
p: PaytoUri,
a: AmountJson,
wallet: ReturnType<typeof useBackendContext>["wallet"],
): Promise<DepositGroupFees> {
const depositPaytoUri = `payto://${p.targetType}/${p.targetPath}`;
const amount = Amounts.stringify(a);
return await wallet.call(WalletApiOperation.GetFeeForDeposit, {
amount,
depositPaytoUri,
});
} }
export function labelForAccountType(id: string): string { export function labelForAccountType(id: string): string {

View File

@ -264,6 +264,15 @@ describe("DepositPage states", () => {
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`)); expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
expect(state.depositHandler.onClick).undefined; expect(state.depositHandler.onClick).undefined;
}, },
(state) => {
if (state.status !== "ready") expect.fail();
expect(state.cancelHandler.onClick).not.undefined;
expect(state.currency).eq(currency);
expect(state.account.value).eq(accountSelected);
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
expect(state.depositHandler.onClick).undefined;
},
], ],
TestingContext, TestingContext,
); );
@ -341,7 +350,7 @@ describe("DepositPage states", () => {
expect(state.account.value).eq(accountSelected); expect(state.account.value).eq(accountSelected);
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0")); expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
expect(state.depositHandler.onClick).undefined; expect(state.depositHandler.onClick).undefined;
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`)); expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
expect(state.amount.onInput).not.undefined; expect(state.amount.onInput).not.undefined;
if (!state.amount.onInput) return; if (!state.amount.onInput) return;
@ -359,6 +368,18 @@ describe("DepositPage states", () => {
); );
expect(state.depositHandler.onClick).not.undefined; expect(state.depositHandler.onClick).not.undefined;
}, },
(state) => {
if (state.status !== "ready") expect.fail();
expect(state.cancelHandler.onClick).not.undefined;
expect(state.currency).eq(currency);
expect(state.account.value).eq(accountSelected);
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:10"));
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
expect(state.totalToDeposit).deep.eq(
Amounts.parseOrThrow(`${currency}:7`),
);
expect(state.depositHandler.onClick).not.undefined;
},
], ],
TestingContext, TestingContext,
); );

View File

@ -38,7 +38,7 @@ import {
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { styled } from "@linaria/react"; import { styled } from "@linaria/react";
import { differenceInSeconds } from "date-fns"; import { differenceInSeconds, isAfter, isFuture, isPast } from "date-fns";
import { ComponentChildren, Fragment, h, VNode } from "preact"; import { ComponentChildren, Fragment, h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks"; import { useEffect, useState } from "preact/hooks";
import emptyImg from "../../static/img/empty.png"; import emptyImg from "../../static/img/empty.png";
@ -641,6 +641,11 @@ export function TransactionView({
if (transaction.type === TransactionType.Deposit) { if (transaction.type === TransactionType.Deposit) {
const total = Amounts.parseOrThrow(transaction.amountRaw); const total = Amounts.parseOrThrow(transaction.amountRaw);
const payto = parsePaytoUri(transaction.targetPaytoUri); const payto = parsePaytoUri(transaction.targetPaytoUri);
const wireTime = AbsoluteTime.fromTimestamp(
transaction.wireTransferDeadline,
);
const shouldBeWired = wireTime.t_ms !== "never" && isPast(wireTime.t_ms);
return ( return (
<TransactionTemplate <TransactionTemplate
transaction={transaction} transaction={transaction}
@ -663,18 +668,39 @@ export function TransactionView({
text={<DepositDetails transaction={transaction} />} text={<DepositDetails transaction={transaction} />}
kind="neutral" kind="neutral"
/> />
{!shouldBeWired ? (
<Part <Part
title={i18n.str`Wire transfer deadline`} title={i18n.str`Wire transfer deadline`}
text={ text={
<Time <Time timestamp={wireTime} format="dd MMMM yyyy 'at' HH:mm" />
timestamp={AbsoluteTime.fromTimestamp(
transaction.wireTransferDeadline,
)}
format="dd MMMM yyyy 'at' HH:mm"
/>
} }
kind="neutral" kind="neutral"
/> />
) : transaction.wireTransferProgress === 0 ? (
<AlertView
alert={{
type: "warning",
message: i18n.str`Wire transfer is not initiated`,
description: i18n.str` `,
}}
/>
) : transaction.wireTransferProgress === 100 ? (
<AlertView
alert={{
type: "success",
message: i18n.str`Wire transfer completed`,
description: i18n.str` `,
}}
/>
) : (
<AlertView
alert={{
type: "info",
message: i18n.str`Wire transfer in progress`,
description: i18n.str` `,
}}
/>
)}
</TransactionTemplate> </TransactionTemplate>
); );
} }