diff options
author | Sebastian <sebasjm@gmail.com> | 2024-08-09 13:19:17 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-08-09 13:19:17 -0300 |
commit | 78d6fdb04de336fab8fe85210c7f76c90eb2d424 (patch) | |
tree | b1c973506a630769021651ae6137d39837107b6b | |
parent | 93f1f9867a6f5681df847d60efca4828f5d49deb (diff) | |
download | wallet-core-78d6fdb04de336fab8fe85210c7f76c90eb2d424.tar.xz |
fix #8871
16 files changed, 249 insertions, 219 deletions
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index d045bc1e3..7d469ed7e 100644 --- a/packages/taler-wallet-webextension/src/NavigationBar.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -112,6 +112,9 @@ export const Pages = { balanceTransaction: pageDefinition<{ tid: string }>( "/balance/transaction/:tid", ), + bankManange: pageDefinition<{ scope: CrockEncodedString}>( + "/bank/manage/:scope", + ), balanceDeposit: pageDefinition<{ scope: CrockEncodedString; }>("/balance/deposit/:scope"), @@ -151,7 +154,10 @@ export const Pages = { ctaRecovery: "/cta/recovery", ctaRefund: "/cta/refund", ctaWithdraw: "/cta/withdraw", - ctaDeposit: "/cta/deposit", + ctaDeposit: pageDefinition<{ + scope: CrockEncodedString; + account: CrockEncodedString, + }>("/cta/deposit/:scope/:account"), ctaExperiment: "/cta/experiment", ctaAddExchange: "/cta/add/exchange", ctaInvoiceCreate: pageDefinition<{ diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/index.ts b/packages/taler-wallet-webextension/src/cta/Deposit/index.ts index 6b228188b..d6a14f3dc 100644 --- a/packages/taler-wallet-webextension/src/cta/Deposit/index.ts +++ b/packages/taler-wallet-webextension/src/cta/Deposit/index.ts @@ -14,18 +14,18 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { AmountJson, AmountString } from "@gnu-taler/taler-util"; +import { AmountJson, AmountString, PaytoUri, ScopeInfo } from "@gnu-taler/taler-util"; import { ErrorAlertView } from "../../components/CurrentAlerts.js"; import { Loading } from "../../components/Loading.js"; import { ErrorAlert } from "../../context/alert.js"; -import { ButtonHandler } from "../../mui/handlers.js"; +import { AmountFieldHandler, ButtonHandler } from "../../mui/handlers.js"; import { compose, StateViewMap } from "../../utils/index.js"; import { useComponentState } from "./state.js"; import { ReadyView } from "./views.js"; export interface Props { - talerDepositUri: string | undefined; - amountStr: AmountString | undefined; + account: PaytoUri; + scope: ScopeInfo; cancel: () => Promise<void>; onSuccess: (tx: string) => Promise<void>; } @@ -44,7 +44,9 @@ export namespace State { export interface Ready { status: "ready"; error: undefined; + amount: AmountFieldHandler; fee: AmountJson; + account: PaytoUri; cost: AmountJson; effective: AmountJson; confirm: ButtonHandler; diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/state.ts b/packages/taler-wallet-webextension/src/cta/Deposit/state.ts index efcef8c28..e599b03f0 100644 --- a/packages/taler-wallet-webextension/src/cta/Deposit/state.ts +++ b/packages/taler-wallet-webextension/src/cta/Deposit/state.ts @@ -14,52 +14,54 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { Amounts } from "@gnu-taler/taler-util"; +import { Amounts, stringifyPaytoUri } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { alertFromError, useAlertContext } from "../../context/alert.js"; import { useBackendContext } from "../../context/backend.js"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; import { Props, State } from "./index.js"; +import { useState } from "preact/hooks"; export function useComponentState({ - talerDepositUri, - amountStr, + account, + scope, cancel, onSuccess, }: Props): State { const api = useBackendContext(); const { pushAlertOnError } = useAlertContext(); - const info = useAsyncAsHook(async () => { - if (!talerDepositUri) throw Error("ERROR_NO-URI-FOR-DEPOSIT"); - if (!amountStr) throw Error("ERROR_NO-AMOUNT-FOR-DEPOSIT"); - const amount = Amounts.parse(amountStr); - if (!amount) throw Error("ERROR_INVALID-AMOUNT-FOR-DEPOSIT"); + const [amount, setAmount] = useState(Amounts.zeroOfCurrency(scope.currency)) + const amountStr = Amounts.stringify(amount); + + const hook = useAsyncAsHook(async () => { const deposit = await api.wallet.call(WalletApiOperation.PrepareDeposit, { - amount: Amounts.stringify(amount), - depositPaytoUri: talerDepositUri, + amount: amountStr, + depositPaytoUri: stringifyPaytoUri(account), }); - return { deposit, uri: talerDepositUri, amount }; - }); - const { i18n } = useTranslationContext(); + return deposit; + }, [amountStr]); + // const { i18n } = useTranslationContext(); - if (!info) return { status: "loading", error: undefined }; - if (info.hasError) { - return { - status: "error", - error: alertFromError( - i18n, - i18n.str`Could not load the status of deposit`, - info, - ), - }; - } + // if (!hook) return { status: "loading", error: undefined }; + // if (hook.hasError) { + // return { + // status: "error", + // error: alertFromError( + // i18n, + // i18n.str`Could not load the status of deposit`, + // hook, + // ), + // }; + // } - const { deposit, uri, amount } = info.response; + const debitAmount = !hook || hook.hasError ? Amounts.zeroOfCurrency(scope.currency) : Amounts.parseOrThrow(hook.response.effectiveDepositAmount); + const toBeReceived = !hook || hook.hasError ? Amounts.zeroOfCurrency(scope.currency) : Amounts.parseOrThrow(hook.response.totalDepositCost); + // const { deposit, uri, amount } = hook.response; async function doDeposit(): Promise<void> { const resp = await api.wallet.call(WalletApiOperation.CreateDepositGroup, { - amount: Amounts.stringify(amount), - depositPaytoUri: uri, + amount: amountStr, + depositPaytoUri: stringifyPaytoUri(account), }); onSuccess(resp.transactionId); } @@ -67,13 +69,19 @@ export function useComponentState({ return { status: "ready", error: undefined, + account, + amount: { + value: amount, + onInput: pushAlertOnError(async (e) => setAmount(e)), + error: Amounts.isZero(amount) ? "Can't be zero" : undefined, + }, confirm: { onClick: pushAlertOnError(doDeposit), }, - fee: Amounts.sub(deposit.totalDepositCost, deposit.effectiveDepositAmount) + fee: Amounts.sub(toBeReceived, debitAmount) .amount, - cost: Amounts.parseOrThrow(deposit.totalDepositCost), - effective: Amounts.parseOrThrow(deposit.effectiveDepositAmount), + cost: Amounts.parseOrThrow(toBeReceived), + effective: Amounts.parseOrThrow(debitAmount), cancel, }; } diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/stories.tsx b/packages/taler-wallet-webextension/src/cta/Deposit/stories.tsx index cd65ce8e1..aacb7b03d 100644 --- a/packages/taler-wallet-webextension/src/cta/Deposit/stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/Deposit/stories.tsx @@ -19,7 +19,7 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { Amounts } from "@gnu-taler/taler-util"; +import { Amounts, parsePaytoUri } from "@gnu-taler/taler-util"; import * as tests from "@gnu-taler/web-util/testing"; import { ReadyView } from "./views.js"; @@ -30,6 +30,10 @@ export default { export const Ready = tests.createExample(ReadyView, { status: "ready", confirm: {}, + amount: { + value: Amounts.parseOrThrow("EUR:1") + }, + account: parsePaytoUri("payto://iban/DE1231231231")!, cost: Amounts.parseOrThrow("EUR:1.2"), effective: Amounts.parseOrThrow("EUR:1"), fee: Amounts.parseOrThrow("EUR:0.2"), diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/test.ts b/packages/taler-wallet-webextension/src/cta/Deposit/test.ts index 100929918..be4c1edd1 100644 --- a/packages/taler-wallet-webextension/src/cta/Deposit/test.ts +++ b/packages/taler-wallet-webextension/src/cta/Deposit/test.ts @@ -19,7 +19,7 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { AmountString, Amounts } from "@gnu-taler/taler-util"; +import { AmountString, Amounts, ScopeType, parsePayUri, parsePaytoUri } from "@gnu-taler/taler-util"; import { expect } from "chai"; import { createWalletApiMock } from "../../test-utils.js"; import { useComponentState } from "./state.js"; @@ -28,42 +28,6 @@ import { Props } from "./index.js"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; describe("Deposit CTA states", () => { - it("should tell the user that the URI is missing", async () => { - const { handler, TestingContext } = createWalletApiMock(); - - const props: Props = { - talerDepositUri: undefined, - amountStr: undefined, - cancel: async () => { - null; - }, - onSuccess: async () => { - null; - }, - }; - - const hookBehavior = await tests.hookBehaveLikeThis( - useComponentState, - props, - [ - ({ status }) => { - expect(status).equals("loading"); - }, - ({ status, error }) => { - expect(status).equals("error"); - - if (!error) expect.fail(); - // if (!error.hasError) expect.fail(); - // if (error.operational) expect.fail(); - expect(error.description).eq("ERROR_NO-URI-FOR-DEPOSIT"); - }, - ], - TestingContext, - ); - - expect(hookBehavior).deep.equal({ result: "ok" }); - expect(handler.getCallingQueueState()).eq("empty"); - }); it("should be ready after loading", async () => { const { handler, TestingContext } = createWalletApiMock(); @@ -72,19 +36,22 @@ describe("Deposit CTA states", () => { WalletApiOperation.PrepareDeposit, undefined, { - effectiveDepositAmount: "EUR:1" as AmountString, - totalDepositCost: "EUR:1.2" as AmountString, + effectiveDepositAmount: "EUR:0" as AmountString, + totalDepositCost: "EUR:0" as AmountString, fees: { coin: "EUR:0" as AmountString, - refresh: "EUR:0.2" as AmountString, + refresh: "EUR:0" as AmountString, wire: "EUR:0" as AmountString, }, }, ); const props = { - talerDepositUri: "payto://refund/asdasdas", - amountStr: "EUR:1" as AmountString, + account: parsePaytoUri("payto://refund/asdasdas")!, + scope: { + type: ScopeType.Global as const, + currency: "EUR", + }, cancel: async () => { null; }, @@ -97,16 +64,26 @@ describe("Deposit CTA states", () => { useComponentState, props, [ - ({ status }) => { - expect(status).equals("loading"); + // ({ status }) => { + // expect(status).equals("loading"); + // }, + (state) => { + if (state.status !== "ready") expect.fail(); + if (state.error) expect.fail(); + expect(state.confirm.onClick).not.undefined; + expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0")); + expect(state.cost).deep.eq(Amounts.parseOrThrow("EUR:0")); + expect(state.fee).deep.eq(Amounts.parseOrThrow("EUR:0")); + expect(state.effective).deep.eq(Amounts.parseOrThrow("EUR:0")); }, (state) => { if (state.status !== "ready") expect.fail(); if (state.error) expect.fail(); expect(state.confirm.onClick).not.undefined; - expect(state.cost).deep.eq(Amounts.parseOrThrow("EUR:1.2")); - expect(state.fee).deep.eq(Amounts.parseOrThrow("EUR:0.2")); - expect(state.effective).deep.eq(Amounts.parseOrThrow("EUR:1")); + expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0")); + expect(state.cost).deep.eq(Amounts.parseOrThrow("EUR:0")); + expect(state.fee).deep.eq(Amounts.parseOrThrow("EUR:0")); + expect(state.effective).deep.eq(Amounts.parseOrThrow("EUR:0")); }, ], TestingContext, diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/views.tsx b/packages/taler-wallet-webextension/src/cta/Deposit/views.tsx index c683a755c..3e76b4789 100644 --- a/packages/taler-wallet-webextension/src/cta/Deposit/views.tsx +++ b/packages/taler-wallet-webextension/src/cta/Deposit/views.tsx @@ -14,12 +14,13 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { Amounts } from "@gnu-taler/taler-util"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { Fragment, h, VNode } from "preact"; import { Amount } from "../../components/Amount.js"; -import { Part } from "../../components/Part.js"; +import { AmountField } from "../../components/AmountField.js"; +import { Part, PartPayto } from "../../components/Part.js"; import { Button } from "../../mui/Button.js"; +import { DepositDetails, getAmountWithFee } from "../../wallet/Transaction.js"; import { State } from "./index.js"; /** @@ -32,29 +33,24 @@ export function ReadyView(state: State.Ready): VNode { return ( <Fragment> - <section> - {Amounts.isNonZero(state.cost) && ( - <Part - big - title={i18n.str`Cost`} - text={<Amount value={state.cost} />} - kind="negative" - /> - )} - {Amounts.isNonZero(state.fee) && ( - <Part - big - title={i18n.str`Fee`} - text={<Amount value={state.fee} />} - kind="negative" + <section style={{ textAlign: "left" }}> + <p> + <AmountField + label={i18n.str`Amount`} + handler={state.amount} + required /> - )} + </p> + <PartPayto kind="neutral" payto={state.account} /> <Part - big - title={i18n.str`To be received`} - text={<Amount value={state.effective} />} - kind="positive" + title={i18n.str`Details`} + text={ + <DepositDetails + amount={getAmountWithFee(state.cost, state.effective, "debit")} + /> + } /> + </section> <section> <Button diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx b/packages/taler-wallet-webextension/src/wallet/Application.tsx index 1b14236d5..b4044beca 100644 --- a/packages/taler-wallet-webextension/src/wallet/Application.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx @@ -26,8 +26,10 @@ import { TalerUri, TalerUriAction, TranslatedString, + parsePaytoUri, parseScopeInfoShort, parseTalerUri, + stringifyPaytoUri, stringifyScopeInfoShort, stringifyTalerUri, } from "@gnu-taler/taler-util"; @@ -92,6 +94,7 @@ import { WalletActivity } from "../components/WalletActivity.js"; import { EnabledBySettings } from "../components/EnabledBySettings.js"; import { DevExperimentPage } from "../cta/DevExperiment/index.js"; import { ConfirmAddExchangeView } from "./AddExchange/views.js"; +import { ManageAccountPage } from "./ManageAccount/index.js"; export function Application(): VNode { const { i18n } = useTranslationContext(); @@ -249,9 +252,17 @@ export function Application(): VNode { <DestinationSelectionPage type="send" scope={s} - goToWalletBankDeposit={(s) => + goToWalletKnownBankDeposit={(s, p) => redirectTo( - Pages.balanceDeposit({ + Pages.ctaDeposit({ + scope: encodeCrockForURI(stringifyScopeInfoShort(s)), + account: encodeCrockForURI(stringifyPaytoUri(p)), + }), + ) + } + goToWalletNewBankDeposit={(s) => + redirectTo( + Pages.bankManange({ scope: encodeCrockForURI(stringifyScopeInfoShort(s)), }), ) @@ -269,6 +280,34 @@ export function Application(): VNode { }} /> <Route + path={Pages.bankManange.pattern} + component={({ + scope, + }: { + scope?: string; + }) => { + const s = !scope ? undefined : parseScopeInfoShort(decodeCrockFromURI(scope)); + if (!s) return <div>missing scope</div> + + return ( + <WalletTemplate path="balance" goToURL={redirectToURL}> + <ManageAccountPage + scope={s} + onAccountAdded={(account) => redirectTo(Pages.ctaDeposit({ + scope: encodeCrockForURI(stringifyScopeInfoShort(s)), + account: encodeCrockForURI(stringifyPaytoUri(account)), + }))} + onCancel={() => { + redirectTo(Pages.balanceHistory({ + scope: encodeCrockForURI(stringifyScopeInfoShort(s)), + })) + }} + /> + </WalletTemplate> + ); + }} + /> + <Route path={Pages.receiveCashForPurchase.pattern} component={({ id: _purchaseId }: { id?: string }) => { return ( @@ -354,24 +393,24 @@ export function Application(): VNode { return <div>missing scope</div> } return <WalletTemplate path="balance" goToURL={redirectToURL}> - <DepositPage - scope={s} - onCancel={(scope: ScopeInfo) => { - redirectTo( - Pages.balanceHistory({ - scope: encodeCrockForURI(stringifyScopeInfoShort(scope)), - }), - ); - }} - onSuccess={(scope: ScopeInfo) => { - redirectTo( - Pages.balanceHistory({ - scope: encodeCrockForURI(stringifyScopeInfoShort(scope)), - }), - ); - }} - /> - </WalletTemplate> + <DepositPage + scope={s} + onCancel={(scope: ScopeInfo) => { + redirectTo( + Pages.balanceHistory({ + scope: encodeCrockForURI(stringifyScopeInfoShort(scope)), + }), + ); + }} + onSuccess={(scope: ScopeInfo) => { + redirectTo( + Pages.balanceHistory({ + scope: encodeCrockForURI(stringifyScopeInfoShort(scope)), + }), + ); + }} + /> + </WalletTemplate> }} /> @@ -564,25 +603,35 @@ export function Application(): VNode { }} /> <Route - path={Pages.ctaDeposit} + path={Pages.ctaDeposit.pattern} component={({ - amount, - talerUri, + scope, + account, }: { - amount: string; - talerUri: string; - }) => ( - <CallToActionTemplate title={i18n.str`Digital cash deposit`}> + scope: string, + account: string; + }) => { + const s = parseScopeInfoShort(decodeCrockFromURI(scope)) + if (!s) { + return <div>missing scope</div> + } + const p = parsePaytoUri(decodeCrockFromURI(account)) + if (!p) { + return <div>missing account</div> + } + + return <CallToActionTemplate title={i18n.str`Digital cash deposit`} > <DepositPageCTA - amountStr={Amounts.stringify(Amounts.parseOrThrow(amount))} - talerDepositUri={decodeCrockFromURI(talerUri)} + scope={s} + account={p} cancel={() => redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> </CallToActionTemplate> - )} + } + } /> <Route path={Pages.ctaInvoiceCreate.pattern} @@ -711,7 +760,7 @@ export function Application(): VNode { <WalletActivity /> </EnabledBySettings> </IoCProviderForRuntime> - </TranslationProvider> + </TranslationProvider > ); } diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts index e26992688..22ad1c1e7 100644 --- a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts +++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts @@ -62,8 +62,8 @@ export namespace State { export interface AddingAccount { status: "manage-account"; error: undefined; - currency: string; - onAccountAdded: (p: string) => void; + scope: ScopeInfo; + onAccountAdded: (p: PaytoUri) => void; onCancel: () => void; } diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts index 37f078ff6..29f533385 100644 --- a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts @@ -42,7 +42,6 @@ export function useComponentState({ const zero = Amounts.zeroOfCurrency(scope.currency); - const hook = useAsyncAsHook(async () => { const { balances } = await api.wallet.call( WalletApiOperation.GetBalances, @@ -91,9 +90,9 @@ export function useComponentState({ return { status: "manage-account", error: undefined, - currency: scope.currency, - onAccountAdded: (p: string) => { - updateAccountFromList(p); + scope, + onAccountAdded: (p: PaytoUri) => { + updateAccountFromList(stringifyPaytoUri(p)); setAddingAccount(false); hook.retry(); }, diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts index befff87ff..eeb972c08 100644 --- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts +++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { AmountJson, ScopeInfo } from "@gnu-taler/taler-util"; +import { AmountJson, KnownBankAccountsInfo, PaytoUri, ScopeInfo } from "@gnu-taler/taler-util"; import { ErrorAlertView } from "../../components/CurrentAlerts.js"; import { Loading } from "../../components/Loading.js"; import { ErrorAlert } from "../../context/alert.js"; @@ -37,7 +37,8 @@ interface PropsGet { interface PropsSend { type: "send"; scope: ScopeInfo; - goToWalletBankDeposit: (s:ScopeInfo) => void; + goToWalletKnownBankDeposit: (s:ScopeInfo, p: PaytoUri) => void; + goToWalletNewBankDeposit: (s:ScopeInfo) => void; goToWalletWalletSend: (s:ScopeInfo) => void; } @@ -69,18 +70,13 @@ export namespace State { status: "ready"; error: undefined; type: Props["type"]; - selectCurrency: ButtonHandler; - previous: Contact[]; + onSelectAccount: (p:PaytoUri) => void; + previous: KnownBankAccountsInfo[]; goToBank: ButtonHandler; goToWallet: ButtonHandler; } } -export type Contact = { - icon_type: string; - name: string; - description: string; -}; const viewMapping: StateViewMap<State> = { loading: Loading, diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts index e138b28fb..de2d439b6 100644 --- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts @@ -15,9 +15,9 @@ */ import { - AmountJson, - Amounts, ExchangeUpdateStatus, + KnownBankAccountsInfo, + PaytoUri, ScopeType, parseScopeInfoShort, stringifyScopeInfoShort @@ -29,43 +29,24 @@ import { alertFromError, useAlertContext } from "../../context/alert.js"; import { useBackendContext } from "../../context/backend.js"; import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; import { RecursiveState, assertUnreachable } from "../../utils/index.js"; -import { Contact, Props, State } from "./index.js"; +import { Props, State } from "./index.js"; export function useComponentState(props: Props): RecursiveState<State> { const api = useBackendContext(); const { pushAlertOnError } = useAlertContext(); + const { i18n } = useTranslationContext(); const [scope, setScope] = useState(props.scope); - // const scopeStr = !scope ? undefined : stringifyScopeInfoShort(scope); - // useEffect(() => { - // if (!scope) return; - // if (!amount) { - // setAmount(Amounts.zeroOfCurrency(scope.currency)); - // } - // }, [scopeStr]); + const hook = useAsyncAsHook(async () => { + const resp = await api.wallet.call( + WalletApiOperation.ListKnownBankAccounts, + {}, + ); + return resp + }); - //FIXME: get this information from wallet - // eslint-disable-next-line no-constant-condition - const previous: Contact[] = true - ? [] - : [ - { - name: "International Bank", - icon_type: "bank", - description: "account ending with 3454", - }, - { - name: "Max", - icon_type: "bank", - description: "account ending with 3454", - }, - { - name: "Alex", - icon_type: "bank", - description: "account ending with 3454", - }, - ]; + const previous: KnownBankAccountsInfo[] = props.type === "send" && hook && !hook.hasError ? hook.response.accounts : []; if (!scope) { return () => { @@ -144,14 +125,12 @@ export function useComponentState(props: Props): RecursiveState<State> { status: "ready", error: undefined, previous, - selectCurrency: { - onClick: pushAlertOnError(async () => { - setScope(undefined); - }), - }, + onSelectAccount: pushAlertOnError(async (account: PaytoUri) => { + props.goToWalletKnownBankDeposit(scope, account); + }), goToBank: { onClick: pushAlertOnError(async () => { - props.goToWalletBankDeposit(scope); + props.goToWalletNewBankDeposit(scope); }), }, goToWallet: { @@ -166,16 +145,12 @@ export function useComponentState(props: Props): RecursiveState<State> { status: "ready", error: undefined, previous, - selectCurrency: { - onClick: pushAlertOnError(async () => { - setScope(undefined); - }), - }, goToBank: { onClick: pushAlertOnError(async () => { props.goToWalletManualWithdraw(scope); }), }, + onSelectAccount: () => { }, goToWallet: { onClick: pushAlertOnError(async () => { props.goToWalletWalletInvoice(scope); diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/stories.tsx b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/stories.tsx index 0e68f2019..c530a7020 100644 --- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/stories.tsx @@ -30,14 +30,12 @@ export const GetCash = tests.createExample(ReadyView, { goToBank: {}, goToWallet: {}, previous: [], - selectCurrency: {}, type: "get", }); export const SendCash = tests.createExample(ReadyView, { goToBank: {}, goToWallet: {}, previous: [], - selectCurrency: {}, type: "send", }); diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx index cc368992d..cf34ceb35 100644 --- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx @@ -14,11 +14,10 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ +import { KnownBankAccountsInfo, PaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { styled } from "@linaria/react"; import { Fragment, h, VNode } from "preact"; -import { AmountField } from "../../components/AmountField.js"; -import { EnabledBySettings } from "../../components/EnabledBySettings.js"; import { SelectList } from "../../components/SelectList.js"; import { Input, @@ -33,7 +32,7 @@ import { Pages } from "../../NavigationBar.js"; import arrowIcon from "../../svg/chevron-down.inline.svg"; import bankIcon from "../../svg/ri-bank-line.inline.svg"; import { assertUnreachable } from "../../utils/index.js"; -import { Contact, State } from "./index.js"; +import { State } from "./index.js"; export function SelectCurrencyView({ currencies, @@ -81,7 +80,6 @@ const Container = styled.div` const ContactTable = styled.table` width: 100%; & > tr > td { - padding: 8px; & > div:not([data-disabled]):hover { background-color: lightblue; } @@ -266,6 +264,7 @@ export function ReadyGetView({ } export function ReadySendView({ goToBank, + onSelectAccount, goToWallet, previous, }: State.Ready): VNode { @@ -291,6 +290,9 @@ export function ReadySendView({ <td> <RowExample info={info} + onClick={() => { + onSelectAccount(info.uri) + }} // disabled={!amountHandler.onInput} /> </td> @@ -331,31 +333,31 @@ export function ReadySendView({ function RowExample({ info, disabled, + onClick }: { - info: Contact; + info: KnownBankAccountsInfo; disabled?: boolean; + onClick?: () => void; }): VNode { - const icon = info.icon_type === "bank" ? bankIcon : undefined; + + return ( - <MediaExample data-disabled={disabled}> + <MediaExample data-disabled={disabled} onClick={onClick}> <MediaLeft> <CircleDiv> - {icon !== undefined ? ( <SvgIcon - title={info.name} + title={info.alias} dangerouslySetInnerHTML={{ - __html: icon, + __html: bankIcon, }} color="currentColor" /> - ) : ( - <span>A</span> - )} + </CircleDiv> </MediaLeft> <MediaBody> - <span>{info.name}</span> - <LightText>{info.description}</LightText> + <span>{info.alias}</span> + <LightText>{describeAccount(info.uri)}</LightText> </MediaBody> <MediaRight> <SvgIcon @@ -368,3 +370,21 @@ function RowExample({ </MediaExample> ); } + + +function describeAccount(p: PaytoUri): string { + if (!p.isKnown) { + return stringifyPaytoUri(p) + } + switch (p.targetType) { + case "iban": { + return p.iban + } + case "x-taler-bank": { + return `${p.host}/${p.account}` + } + case "bitcoin": { + return `${p.address}` + } + } +}
\ No newline at end of file diff --git a/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts b/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts index 3a00d48ce..a76d77709 100644 --- a/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts +++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { KnownBankAccountsInfo } from "@gnu-taler/taler-util"; +import { KnownBankAccountsInfo, PaytoUri, ScopeInfo } from "@gnu-taler/taler-util"; import { ErrorAlertView } from "../../components/CurrentAlerts.js"; import { Loading } from "../../components/Loading.js"; import { ErrorAlert } from "../../context/alert.js"; @@ -28,8 +28,8 @@ import { useComponentState } from "./state.js"; import { ReadyView } from "./views.js"; export interface Props { - currency: string; - onAccountAdded: (uri: string) => void; + scope: ScopeInfo; + onAccountAdded: (uri: PaytoUri) => void; onCancel: () => void; } diff --git a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts index a7b2fe90f..09abf92ac 100644 --- a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts @@ -29,7 +29,7 @@ import { AccountByType, Props, State } from "./index.js"; import { useSettings } from "../../hooks/useSettings.js"; export function useComponentState({ - currency, + scope, onAccountAdded, onCancel, }: Props): State { @@ -37,7 +37,7 @@ export function useComponentState({ const { pushAlertOnError } = useAlertContext(); const { i18n } = useTranslationContext(); const hook = useAsyncAsHook(() => - api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }), + api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency: scope.currency }), ); const accountType: Record<string, string> = { iban: "IBAN", @@ -80,10 +80,10 @@ export function useComponentState({ const normalizedPayto = stringifyPaytoUri(uri); await api.wallet.call(WalletApiOperation.AddKnownBankAccounts, { alias, - currency, + currency: scope.currency, payto: normalizedPayto, }); - onAccountAdded(payto); + onAccountAdded(uri); } const paytoUriError = found ? "that account is already present" : undefined; @@ -112,7 +112,7 @@ export function useComponentState({ return { status: "ready", error: undefined, - currency, + currency:scope.currency, accountType: { list: accountType, value: type, diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx index df025f570..73c26eaef 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx @@ -1799,7 +1799,7 @@ function TrackingDepositDetails({ ); } -function DepositDetails({ amount }: { amount: AmountWithFee }): VNode { +export function DepositDetails({ amount }: { amount: AmountWithFee }): VNode { const { i18n } = useTranslationContext(); return ( |