diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/cta/InvoiceCreate')
-rw-r--r-- | packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts | 20 | ||||
-rw-r--r-- | packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts | 120 |
2 files changed, 81 insertions, 59 deletions
diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts index 2bee51669..61f286d1f 100644 --- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts +++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts @@ -14,14 +14,19 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ +import { AmountJson, TalerErrorDetail } from "@gnu-taler/taler-util"; import { Loading } from "../../components/Loading.js"; import { HookError } from "../../hooks/useAsyncAsHook.js"; +import { + State as SelectExchangeState +} from "../../hooks/useSelectedExchange.js"; +import { ButtonHandler, TextFieldHandler } from "../../mui/handlers.js"; import { compose, StateViewMap } from "../../utils/index.js"; -import { LoadingUriView, ReadyView } from "./views.js"; +import { ExchangeSelectionPage } from "../../wallet/ExchangeSelection/index.js"; +import { NoExchangesView } from "../../wallet/ExchangeSelection/views.js"; import * as wxApi from "../../wxApi.js"; import { useComponentState } from "./state.js"; -import { AmountJson, TalerErrorDetail } from "@gnu-taler/taler-util"; -import { ButtonHandler, TextFieldHandler } from "../../mui/handlers.js"; +import { LoadingUriView, ReadyView } from "./views.js"; export interface Props { amount: string; @@ -29,7 +34,12 @@ export interface Props { onSuccess: (tx: string) => Promise<void>; } -export type State = State.Loading | State.LoadingUriError | State.Ready; +export type State = State.Loading + | State.LoadingUriError + | State.Ready + | SelectExchangeState.Selecting + | SelectExchangeState.NoExchange + ; export namespace State { export interface Loading { @@ -63,6 +73,8 @@ export namespace State { const viewMapping: StateViewMap<State> = { loading: Loading, "loading-uri": LoadingUriView, + "no-exchange": NoExchangesView, + "selecting-exchange": ExchangeSelectionPage, ready: ReadyView, }; diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts index 9b67b4414..4f75e982d 100644 --- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts +++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts @@ -14,26 +14,24 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ +/* eslint-disable react-hooks/rules-of-hooks */ import { Amounts, TalerErrorDetail } from "@gnu-taler/taler-util"; import { TalerError } from "@gnu-taler/taler-wallet-core"; import { useState } from "preact/hooks"; import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; +import { useSelectedExchange } from "../../hooks/useSelectedExchange.js"; import * as wxApi from "../../wxApi.js"; import { Props, State } from "./index.js"; +type RecursiveState<S extends object> = S | (() => RecursiveState<S>) + export function useComponentState( { amount: amountStr, onClose, onSuccess }: Props, api: typeof wxApi, -): State { +): RecursiveState<State> { const amount = Amounts.parseOrThrow(amountStr); - const [subject, setSubject] = useState(""); - const hook = useAsyncAsHook(api.listExchanges); - const [exchangeIdx, setExchangeIdx] = useState("0"); - const [operationError, setOperationError] = useState< - TalerErrorDetail | undefined - >(undefined); if (!hook) { return { @@ -48,56 +46,68 @@ export function useComponentState( }; } - const exchanges = hook.response.exchanges.filter( - (e) => e.currency === amount.currency, - ); - const exchangeMap = exchanges.reduce( - (prev, cur, idx) => ({ ...prev, [String(idx)]: cur.exchangeBaseUrl }), - {} as Record<string, string>, - ); - const selected = exchanges[Number(exchangeIdx)]; - - async function accept(): Promise<void> { - try { - const resp = await api.initiatePeerPullPayment({ - amount: Amounts.stringify(amount), - exchangeBaseUrl: selected.exchangeBaseUrl, - partialContractTerms: { - summary: subject, - }, - }); - - onSuccess(resp.transactionId); - } catch (e) { - if (e instanceof TalerError) { - setOperationError(e.errorDetail); + const exchangeList = hook.response.exchanges + + return () => { + const [subject, setSubject] = useState(""); + + const [operationError, setOperationError] = useState< + TalerErrorDetail | undefined + >(undefined); + + + const selectedExchange = useSelectedExchange({ currency: amount.currency, defaultExchange: undefined, list: exchangeList }) + + if (selectedExchange.status !== 'ready') { + return selectedExchange + } + + const exchange = selectedExchange.selected + + async function accept(): Promise<void> { + try { + const resp = await api.initiatePeerPullPayment({ + amount: Amounts.stringify(amount), + exchangeBaseUrl: exchange.exchangeBaseUrl, + partialContractTerms: { + summary: subject, + }, + }); + + onSuccess(resp.transactionId); + } catch (e) { + if (e instanceof TalerError) { + setOperationError(e.errorDetail); + } + console.error(e); + throw Error("error trying to accept"); } - console.error(e); - throw Error("error trying to accept"); } + + return { + status: "ready", + subject: { + error: !subject ? "cant be empty" : undefined, + value: subject, + onInput: async (e) => setSubject(e), + }, + doSelectExchange: selectedExchange.doSelect, + invalid: !subject || Amounts.isZero(amount), + exchangeUrl: exchange.exchangeBaseUrl, + create: { + onClick: accept, + }, + cancel: { + onClick: onClose, + }, + chosenAmount: amount, + toBeReceived: amount, + error: undefined, + operationError, + }; } - return { - status: "ready", - subject: { - error: !subject ? "cant be empty" : undefined, - value: subject, - onInput: async (e) => setSubject(e), - }, - doSelectExchange: { - //FIX - }, - invalid: !subject || Amounts.isZero(amount), - exchangeUrl: selected.exchangeBaseUrl, - create: { - onClick: accept, - }, - cancel: { - onClick: onClose, - }, - chosenAmount: amount, - toBeReceived: amount, - error: undefined, - operationError, - }; + + + } |