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 { useTranslationContext } from "../../context/translation.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { RecursiveState } from "../../utils/index.js";
import { Props, State } from "./index.js";
export function useComponentState({
amount: amountStr,
onCancel,
onSuccess,
}: Props): State {
}: Props): RecursiveState<State> {
const api = useBackendContext();
const { i18n } = useTranslationContext();
const { pushAlertOnError } = useAlertContext();
@ -49,9 +50,7 @@ export function useComponentState({
);
const { accounts } = await api.wallet.call(
WalletApiOperation.ListKnownBankAccounts,
{
currency,
},
{ currency },
);
return { accounts, balances };
@ -64,10 +63,8 @@ export function useComponentState({
? Amounts.zeroOfCurrency(currency)
: undefined;
// const [accountIdx, setAccountIdx] = useState<number>(0);
const [amount, setAmount] = useState<AmountJson>(initialValue ?? ({} as any));
const [selectedAccount, setSelectedAccount] = useState<PaytoUri>();
const [fee, setFee] = useState<DepositGroupFees | undefined>(undefined);
const [addingAccount, setAddingAccount] = useState(false);
if (!currency) {
@ -91,7 +88,12 @@ export function useComponentState({
}
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) {
return {
@ -139,48 +141,44 @@ export function useComponentState({
const firstAccount = accounts[0].uri;
const currentAccount = !selectedAccount ? firstAccount : selectedAccount;
if (fee === undefined) {
getFeeForAmount(currentAccount, amount, api.wallet).then((initialFee) => {
setFee(initialFee);
return () => {
// eslint-disable-next-line react-hooks/rules-of-hooks
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 {
status: "loading",
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);
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 =
fee !== undefined
? Amounts.sum([fee.wire, fee.coin, fee.refresh]).amount
@ -221,7 +219,7 @@ export function useComponentState({
currency,
amount: {
value: amount,
onInput: pushAlertOnError(updateAmount),
onInput: pushAlertOnError(async (a) => setAmount(a)),
error: amountError,
},
onAddAccount: {
@ -245,22 +243,8 @@ export function useComponentState({
},
totalFee,
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 {

View File

@ -264,6 +264,15 @@ describe("DepositPage states", () => {
expect(state.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
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,
);
@ -341,7 +350,7 @@ describe("DepositPage states", () => {
expect(state.account.value).eq(accountSelected);
expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
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;
if (!state.amount.onInput) return;
@ -359,6 +368,18 @@ describe("DepositPage states", () => {
);
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,
);

View File

@ -38,7 +38,7 @@ import {
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
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 { useEffect, useState } from "preact/hooks";
import emptyImg from "../../static/img/empty.png";
@ -641,6 +641,11 @@ export function TransactionView({
if (transaction.type === TransactionType.Deposit) {
const total = Amounts.parseOrThrow(transaction.amountRaw);
const payto = parsePaytoUri(transaction.targetPaytoUri);
const wireTime = AbsoluteTime.fromTimestamp(
transaction.wireTransferDeadline,
);
const shouldBeWired = wireTime.t_ms !== "never" && isPast(wireTime.t_ms);
return (
<TransactionTemplate
transaction={transaction}
@ -663,18 +668,39 @@ export function TransactionView({
text={<DepositDetails transaction={transaction} />}
kind="neutral"
/>
{!shouldBeWired ? (
<Part
title={i18n.str`Wire transfer deadline`}
text={
<Time
timestamp={AbsoluteTime.fromTimestamp(
transaction.wireTransferDeadline,
)}
format="dd MMMM yyyy 'at' HH:mm"
/>
<Time timestamp={wireTime} format="dd MMMM yyyy 'at' HH:mm" />
}
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>
);
}