diff options
author | Sebastian <sebasjm@gmail.com> | 2022-10-14 11:40:38 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2022-10-14 11:41:53 -0300 |
commit | da9ec5eb16298d8ca5690800eca1c15f5a6cfaa5 (patch) | |
tree | 56b637054c94462cada2a067cfb7cce46fefe651 /packages/taler-wallet-webextension/src/cta/Withdraw | |
parent | ca8da4ed380b308abdc894145c7e1a102bfd6cf0 (diff) | |
download | wallet-core-da9ec5eb16298d8ca5690800eca1c15f5a6cfaa5.tar.xz |
refactored terms of service to remove duplicated code
prettfied some sources
Diffstat (limited to 'packages/taler-wallet-webextension/src/cta/Withdraw')
5 files changed, 231 insertions, 238 deletions
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts index 9de9c693a..075b21dc3 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts @@ -14,27 +14,20 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { AmountJson } from "@gnu-taler/taler-util"; +import { AmountJson, ExchangeListItem } 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 { State as SelectExchangeState } from "../../hooks/useSelectedExchange.js"; import { ButtonHandler, SelectFieldHandler } from "../../mui/handlers.js"; import { compose, StateViewMap } from "../../utils/index.js"; import * as wxApi from "../../wxApi.js"; -import { Props as TermsOfServiceSectionProps } from "../TermsOfServiceSection.js"; import { useComponentStateFromParams, - useComponentStateFromURI + useComponentStateFromURI, } from "./state.js"; import { ExchangeSelectionPage } from "../../wallet/ExchangeSelection/index.js"; -import { - LoadingInfoView, - LoadingUriView, - SuccessView -} from "./views.js"; +import { LoadingInfoView, LoadingUriView, SuccessView } from "./views.js"; import { NoExchangesView } from "../../wallet/ExchangeSelection/views.js"; export interface PropsFromURI { @@ -75,7 +68,7 @@ export namespace State { status: "success"; error: undefined; - exchangeUrl: string; + currentExchange: ExchangeListItem; chosenAmount: AmountJson; withdrawalFee: AmountJson; @@ -83,13 +76,12 @@ export namespace State { doWithdrawal: ButtonHandler; doSelectExchange: ButtonHandler; - tosProps?: TermsOfServiceSectionProps; - mustAcceptFirst: boolean; ageRestriction?: SelectFieldHandler; talerWithdrawUri?: string; cancel: () => Promise<void>; + onTosUpdate: () => void; }; } diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts index 5b5c11182..c2b9e375f 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts @@ -15,17 +15,15 @@ */ /* eslint-disable react-hooks/rules-of-hooks */ -import { AmountJson, Amounts, ExchangeListItem, parsePaytoUri } from "@gnu-taler/taler-util"; +import { AmountJson, Amounts, ExchangeListItem } from "@gnu-taler/taler-util"; import { TalerError } from "@gnu-taler/taler-wallet-core"; import { useState } from "preact/hooks"; -import { Amount } from "../../components/Amount.js"; import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; import { useSelectedExchange } from "../../hooks/useSelectedExchange.js"; -import { buildTermsOfServiceState } from "../../utils/index.js"; import * as wxApi from "../../wxApi.js"; -import { PropsFromURI, PropsFromParams, State } from "./index.js"; +import { PropsFromParams, PropsFromURI, State } from "./index.js"; -type RecursiveState<S extends object> = S | (() => RecursiveState<S>) +type RecursiveState<S extends object> = S | (() => RecursiveState<S>); export function useComponentStateFromParams( { amount, cancel, onSuccess }: PropsFromParams, @@ -46,18 +44,38 @@ export function useComponentStateFromParams( } const chosenAmount = uriInfoHook.response.amount; - const exchangeList = uriInfoHook.response.exchanges.exchanges - - async function doManualWithdraw(exchange: string, ageRestricted: number | undefined): Promise<{ transactionId: string, confirmTransferUrl: string | undefined }> { - const res = await api.acceptManualWithdrawal(exchange, Amounts.stringify(chosenAmount), ageRestricted); + const exchangeList = uriInfoHook.response.exchanges.exchanges; + + async function doManualWithdraw( + exchange: string, + ageRestricted: number | undefined, + ): Promise<{ + transactionId: string; + confirmTransferUrl: string | undefined; + }> { + const res = await api.acceptManualWithdrawal( + exchange, + Amounts.stringify(chosenAmount), + ageRestricted, + ); return { confirmTransferUrl: undefined, - transactionId: res.transactionId + transactionId: res.transactionId, }; } - return () => exchangeSelectionState(doManualWithdraw, cancel, onSuccess, undefined, chosenAmount, exchangeList, undefined, api) - + return () => + exchangeSelectionState( + uriInfoHook.retry, + doManualWithdraw, + cancel, + onSuccess, + undefined, + chosenAmount, + exchangeList, + undefined, + api, + ); } export function useComponentStateFromURI( @@ -75,7 +93,12 @@ export function useComponentStateFromURI( }); const exchanges = await api.listExchanges(); const { amount, defaultExchangeBaseUrl } = uriInfo; - return { talerWithdrawUri, amount: Amounts.parseOrThrow(amount), thisExchange: defaultExchangeBaseUrl, exchanges }; + return { + talerWithdrawUri, + amount: Amounts.parseOrThrow(amount), + thisExchange: defaultExchangeBaseUrl, + exchanges, + }; }); if (!uriInfoHook) return { status: "loading", error: undefined }; @@ -90,53 +113,75 @@ export function useComponentStateFromURI( const uri = uriInfoHook.response.talerWithdrawUri; const chosenAmount = uriInfoHook.response.amount; const defaultExchange = uriInfoHook.response.thisExchange; - const exchangeList = uriInfoHook.response.exchanges.exchanges - - async function doManagedWithdraw(exchange: string, ageRestricted: number | undefined): Promise<{ transactionId: string, confirmTransferUrl: string | undefined }> { - const res = await api.acceptWithdrawal(uri, exchange, ageRestricted,); + const exchangeList = uriInfoHook.response.exchanges.exchanges; + + async function doManagedWithdraw( + exchange: string, + ageRestricted: number | undefined, + ): Promise<{ + transactionId: string; + confirmTransferUrl: string | undefined; + }> { + const res = await api.acceptWithdrawal(uri, exchange, ageRestricted); return { confirmTransferUrl: res.confirmTransferUrl, - transactionId: res.transactionId + transactionId: res.transactionId, }; } - return () => exchangeSelectionState(doManagedWithdraw, cancel, onSuccess, uri, chosenAmount, exchangeList, defaultExchange, api) - + return () => + exchangeSelectionState( + uriInfoHook.retry, + doManagedWithdraw, + cancel, + onSuccess, + uri, + chosenAmount, + exchangeList, + defaultExchange, + api, + ); } -type ManualOrManagedWithdrawFunction = (exchange: string, ageRestricted: number | undefined) => Promise<{ transactionId: string, confirmTransferUrl: string | undefined }> - -function exchangeSelectionState(doWithdraw: ManualOrManagedWithdrawFunction, cancel: () => Promise<void>, onSuccess: (txid: string) => Promise<void>, talerWithdrawUri: string | undefined, chosenAmount: AmountJson, exchangeList: ExchangeListItem[], defaultExchange: string | undefined, api: typeof wxApi,): RecursiveState<State> { - - const selectedExchange = useSelectedExchange({ currency: chosenAmount.currency, defaultExchange, list: exchangeList }) +type ManualOrManagedWithdrawFunction = ( + exchange: string, + ageRestricted: number | undefined, +) => Promise<{ transactionId: string; confirmTransferUrl: string | undefined }>; + +function exchangeSelectionState( + onTosUpdate: () => void, + doWithdraw: ManualOrManagedWithdrawFunction, + cancel: () => Promise<void>, + onSuccess: (txid: string) => Promise<void>, + talerWithdrawUri: string | undefined, + chosenAmount: AmountJson, + exchangeList: ExchangeListItem[], + defaultExchange: string | undefined, + api: typeof wxApi, +): RecursiveState<State> { + const selectedExchange = useSelectedExchange({ + currency: chosenAmount.currency, + defaultExchange, + list: exchangeList, + }); - if (selectedExchange.status !== 'ready') { - return selectedExchange + if (selectedExchange.status !== "ready") { + return selectedExchange; } return () => { - const [ageRestricted, setAgeRestricted] = useState(0); - const currentExchange = selectedExchange.selected - /** - * For the exchange selected, bring the status of the terms of service - */ - const terms = useAsyncAsHook(async () => { - const exchangeTos = await api.getExchangeTos(currentExchange.exchangeBaseUrl, [ - "text/xml", - ]); - - const state = buildTermsOfServiceState(exchangeTos); - - return { state }; - }, []); + const currentExchange = selectedExchange.selected; + const tosNeedToBeAccepted = + !currentExchange.tos.acceptedVersion || + currentExchange.tos.currentVersion !== + currentExchange.tos.acceptedVersion; /** * With the exchange and amount, ask the wallet the information * about the withdrawal */ const amountHook = useAsyncAsHook(async () => { - const info = await api.getExchangeWithdrawalInfo({ exchangeBaseUrl: currentExchange.exchangeBaseUrl, amount: chosenAmount, @@ -155,20 +200,18 @@ function exchangeSelectionState(doWithdraw: ManualOrManagedWithdrawFunction, can }; }, []); - const [reviewing, setReviewing] = useState<boolean>(false); - const [reviewed, setReviewed] = useState<boolean>(false); - const [withdrawError, setWithdrawError] = useState<TalerError | undefined>( undefined, ); const [doingWithdraw, setDoingWithdraw] = useState<boolean>(false); - async function doWithdrawAndCheckError(): Promise<void> { - try { setDoingWithdraw(true); - const res = await doWithdraw(currentExchange.exchangeBaseUrl, !ageRestricted ? undefined : ageRestricted) + const res = await doWithdraw( + currentExchange.exchangeBaseUrl, + !ageRestricted ? undefined : ageRestricted, + ); if (res.confirmTransferUrl) { document.location.href = res.confirmTransferUrl; } else { @@ -201,33 +244,6 @@ function exchangeSelectionState(doWithdraw: ManualOrManagedWithdrawFunction, can ).amount; const toBeReceived = amountHook.response.amount.effective; - const { state: termsState } = (!terms - ? undefined - : terms.hasError - ? undefined - : terms.response) || { state: undefined }; - - async function onAccept(accepted: boolean): Promise<void> { - if (!termsState) return; - - try { - await api.setExchangeTosAccepted( - currentExchange.exchangeBaseUrl, - accepted ? termsState.version : undefined, - ); - setReviewed(accepted); - } catch (e) { - if (e instanceof Error) { - //FIXME: uncomment this and display error - // setErrorAccepting(e.message); - } - } - } - - const mustAcceptFirst = - termsState !== undefined && - (termsState.status === "changed" || termsState.status === "new"); - const ageRestrictionOptions = amountHook.response.ageRestrictionOptions?.reduce( (p, c) => ({ ...p, [c]: `under ${c}` }), @@ -242,17 +258,17 @@ function exchangeSelectionState(doWithdraw: ManualOrManagedWithdrawFunction, can //TODO: calculate based on exchange info const ageRestriction = ageRestrictionEnabled ? { - list: ageRestrictionOptions, - value: String(ageRestricted), - onChange: async (v: string) => setAgeRestricted(parseInt(v, 10)), - } + list: ageRestrictionOptions, + value: String(ageRestricted), + onChange: async (v: string) => setAgeRestricted(parseInt(v, 10)), + } : undefined; return { status: "success", error: undefined, doSelectExchange: selectedExchange.doSelect, - exchangeUrl: currentExchange.exchangeBaseUrl, + currentExchange, toBeReceived, withdrawalFee, chosenAmount, @@ -260,22 +276,13 @@ function exchangeSelectionState(doWithdraw: ManualOrManagedWithdrawFunction, can ageRestriction, doWithdrawal: { onClick: - doingWithdraw || (mustAcceptFirst && !reviewed) + doingWithdraw || tosNeedToBeAccepted ? undefined : doWithdrawAndCheckError, error: withdrawError, }, - tosProps: !termsState - ? undefined - : { - onAccept, - onReview: setReviewing, - reviewed: reviewed, - reviewing: reviewing, - terms: termsState, - }, - mustAcceptFirst, + onTosUpdate, cancel, }; - } + }; } diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/stories.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw/stories.tsx index a3daeb5e9..1c3eaaf34 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/stories.tsx @@ -19,8 +19,9 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { ExchangeListItem } from "@gnu-taler/taler-util"; import { createExample } from "../../test-utils.js"; -import { TermsState } from "../../utils/index.js"; +// import { TermsState } from "../../utils/index.js"; import { SuccessView } from "./views.js"; export default { @@ -38,16 +39,16 @@ const nullHandler = { }, }; -const normalTosState = { - terms: { - status: "accepted", - version: "", - } as TermsState, - onAccept: () => null, - onReview: () => null, - reviewed: false, - reviewing: false, -}; +// const normalTosState = { +// terms: { +// status: "accepted", +// version: "", +// } as TermsState, +// onAccept: () => null, +// onReview: () => null, +// reviewed: false, +// reviewing: false, +// }; const ageRestrictionOptions: Record<string, string> = "6:12:18" .split(":") @@ -69,15 +70,16 @@ export const TermsOfServiceNotYetLoaded = createExample(SuccessView, { fraction: 10000000, }, doWithdrawal: nullHandler, - exchangeUrl: "https://exchange.demo.taler.net", - mustAcceptFirst: false, + currentExchange: { + exchangeBaseUrl: "https://exchange.demo.taler.net", + tos: {}, + } as Partial<ExchangeListItem> as any, withdrawalFee: { currency: "USD", fraction: 10000000, value: 1, }, - doSelectExchange: { - }, + doSelectExchange: {}, toBeReceived: { currency: "USD", fraction: 0, @@ -94,8 +96,10 @@ export const WithSomeFee = createExample(SuccessView, { fraction: 10000000, }, doWithdrawal: nullHandler, - exchangeUrl: "https://exchange.demo.taler.net", - mustAcceptFirst: false, + currentExchange: { + exchangeBaseUrl: "https://exchange.demo.taler.net", + tos: {}, + } as Partial<ExchangeListItem> as any, withdrawalFee: { currency: "USD", fraction: 10000000, @@ -106,9 +110,7 @@ export const WithSomeFee = createExample(SuccessView, { fraction: 0, value: 1, }, - doSelectExchange: { - }, - tosProps: normalTosState, + doSelectExchange: {}, }); export const WithoutFee = createExample(SuccessView, { @@ -120,21 +122,21 @@ export const WithoutFee = createExample(SuccessView, { fraction: 0, }, doWithdrawal: nullHandler, - exchangeUrl: "https://exchange.demo.taler.net", - mustAcceptFirst: false, + currentExchange: { + exchangeBaseUrl: "https://exchange.demo.taler.net", + tos: {}, + } as Partial<ExchangeListItem> as any, withdrawalFee: { currency: "USD", fraction: 0, value: 0, }, - doSelectExchange: { - }, + doSelectExchange: {}, toBeReceived: { currency: "USD", fraction: 0, value: 2, }, - tosProps: normalTosState, }); export const EditExchangeUntouched = createExample(SuccessView, { @@ -146,21 +148,21 @@ export const EditExchangeUntouched = createExample(SuccessView, { fraction: 10000000, }, doWithdrawal: nullHandler, - exchangeUrl: "https://exchange.demo.taler.net", - mustAcceptFirst: false, + currentExchange: { + exchangeBaseUrl: "https://exchange.demo.taler.net", + tos: {}, + } as Partial<ExchangeListItem> as any, withdrawalFee: { currency: "USD", fraction: 0, value: 0, }, - doSelectExchange: { - }, + doSelectExchange: {}, toBeReceived: { currency: "USD", fraction: 0, value: 2, }, - tosProps: normalTosState, }); export const EditExchangeModified = createExample(SuccessView, { @@ -172,21 +174,21 @@ export const EditExchangeModified = createExample(SuccessView, { fraction: 10000000, }, doWithdrawal: nullHandler, - exchangeUrl: "https://exchange.demo.taler.net", - mustAcceptFirst: false, + currentExchange: { + exchangeBaseUrl: "https://exchange.demo.taler.net", + tos: {}, + } as Partial<ExchangeListItem> as any, withdrawalFee: { currency: "USD", fraction: 0, value: 0, }, - doSelectExchange: { - }, + doSelectExchange: {}, toBeReceived: { currency: "USD", fraction: 0, value: 2, }, - tosProps: normalTosState, }); export const WithAgeRestriction = createExample(SuccessView, { @@ -198,11 +200,12 @@ export const WithAgeRestriction = createExample(SuccessView, { value: 2, fraction: 10000000, }, - doSelectExchange: { - }, + doSelectExchange: {}, doWithdrawal: nullHandler, - exchangeUrl: "https://exchange.demo.taler.net", - mustAcceptFirst: false, + currentExchange: { + exchangeBaseUrl: "https://exchange.demo.taler.net", + tos: {}, + } as Partial<ExchangeListItem> as any, withdrawalFee: { currency: "USD", fraction: 0, @@ -213,5 +216,4 @@ export const WithAgeRestriction = createExample(SuccessView, { fraction: 0, value: 2, }, - tosProps: normalTosState, }); diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts index 7ccf7f606..f3598b557 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts @@ -37,7 +37,8 @@ const exchanges: ExchangeFullDetails[] = [ exchangeBaseUrl: "http://exchange.demo.taler.net", paytoUris: [], tos: { - acceptedVersion: "", + acceptedVersion: "v1", + currentVersion: "v1", }, auditors: [ { @@ -58,7 +59,7 @@ const exchanges: ExchangeFullDetails[] = [ accounts: [], feesForType: {}, }, - }, + } as Partial<ExchangeFullDetails> as ExchangeFullDetails, ]; describe("Withdraw CTA states", () => { @@ -161,17 +162,20 @@ describe("Withdraw CTA states", () => { }, { listExchanges: async () => ({ exchanges }), - getWithdrawalDetailsForUri: async ({ talerWithdrawUri }: any) => ({ - amount: "ARS:2", - possibleExchanges: exchanges, - defaultExchangeBaseUrl: exchanges[0].exchangeBaseUrl, - }), + getWithdrawalDetailsForUri: async ({ + talerWithdrawUri, + }: any): Promise<ExchangeWithdrawDetails> => + ({ + amount: "ARS:2", + possibleExchanges: exchanges, + defaultExchangeBaseUrl: exchanges[0].exchangeBaseUrl, + } as Partial<ExchangeWithdrawDetails> as ExchangeWithdrawDetails), getExchangeWithdrawalInfo: async (): Promise<ExchangeWithdrawDetails> => - ({ - withdrawalAmountRaw: "ARS:2", - withdrawalAmountEffective: "ARS:2", - } as any), + ({ + withdrawalAmountRaw: "ARS:2", + withdrawalAmountEffective: "ARS:2", + } as any), getExchangeTos: async (): Promise<GetExchangeTosResult> => ({ contentType: "text", content: "just accept", @@ -205,25 +209,39 @@ describe("Withdraw CTA states", () => { expect(state.status).equals("success"); if (state.status !== "success") return; - // expect(state.exchange.isDirty).false; - // expect(state.exchange.value).equal("http://exchange.demo.taler.net"); - // expect(state.exchange.list).deep.equal({ - // "http://exchange.demo.taler.net": "http://exchange.demo.taler.net", - // }); - // expect(state.showExchangeSelection).false; - expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2")); expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0")); expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2")); expect(state.doWithdrawal.onClick).not.undefined; - expect(state.mustAcceptFirst).false; } await assertNoPendingUpdate(); }); it("should be accept the tos before withdraw", async () => { + const listExchangesResponse = { + exchanges: exchanges.map((e) => ({ + ...e, + tos: { + ...e.tos, + acceptedVersion: undefined, + }, + })) as ExchangeFullDetails[], + }; + + function updateAcceptedVersionToCurrentVersion(): void { + listExchangesResponse.exchanges = listExchangesResponse.exchanges.map( + (e) => ({ + ...e, + tos: { + ...e.tos, + acceptedVersion: e.tos.currentVersion, + }, + }), + ); + } + const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } = mountHook(() => useComponentStateFromURI( @@ -237,18 +255,19 @@ describe("Withdraw CTA states", () => { }, }, { - listExchanges: async () => ({ exchanges }), - getWithdrawalDetailsForUri: async ({ talerWithdrawUri }: any) => ({ - amount: "ARS:2", - possibleExchanges: exchanges, - defaultExchangeBaseUrl: exchanges[0].exchangeBaseUrl, - }), + listExchanges: async () => listExchangesResponse, + getWithdrawalDetailsForUri: async ({ talerWithdrawUri }: any) => + ({ + amount: "ARS:2", + possibleExchanges: exchanges, + defaultExchangeBaseUrl: exchanges[0].exchangeBaseUrl, + } as Partial<ExchangeWithdrawDetails> as ExchangeWithdrawDetails), getExchangeWithdrawalInfo: async (): Promise<ExchangeWithdrawDetails> => - ({ - withdrawalAmountRaw: "ARS:2", - withdrawalAmountEffective: "ARS:2", - } as any), + ({ + withdrawalAmountRaw: "ARS:2", + withdrawalAmountEffective: "ARS:2", + } as any), getExchangeTos: async (): Promise<GetExchangeTosResult> => ({ contentType: "text", content: "just accept", @@ -283,22 +302,14 @@ describe("Withdraw CTA states", () => { expect(state.status).equals("success"); if (state.status !== "success") return; - // expect(state.exchange.isDirty).false; - // expect(state.exchange.value).equal("http://exchange.demo.taler.net"); - // expect(state.exchange.list).deep.equal({ - // "http://exchange.demo.taler.net": "http://exchange.demo.taler.net", - // }); - // expect(state.showExchangeSelection).false; - expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2")); expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0")); expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2")); expect(state.doWithdrawal.onClick).undefined; - expect(state.mustAcceptFirst).true; - // accept TOS - state.tosProps?.onAccept(true); + updateAcceptedVersionToCurrentVersion(); + state.onTosUpdate(); } await waitNextUpdate(); @@ -308,19 +319,11 @@ describe("Withdraw CTA states", () => { expect(state.status).equals("success"); if (state.status !== "success") return; - // expect(state.exchange.isDirty).false; - // expect(state.exchange.value).equal("http://exchange.demo.taler.net"); - // expect(state.exchange.list).deep.equal({ - // "http://exchange.demo.taler.net": "http://exchange.demo.taler.net", - // }); - // expect(state.showExchangeSelection).false; - expect(state.toBeReceived).deep.equal(Amounts.parseOrThrow("ARS:2")); expect(state.withdrawalFee).deep.equal(Amounts.parseOrThrow("ARS:0")); expect(state.chosenAmount).deep.equal(Amounts.parseOrThrow("ARS:2")); expect(state.doWithdrawal.onClick).not.undefined; - expect(state.mustAcceptFirst).true; } await assertNoPendingUpdate(); diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx index 1e8284739..44c7db83f 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx @@ -15,30 +15,28 @@ */ import { Fragment, h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { Amount } from "../../components/Amount.js"; import { ErrorTalerOperation } from "../../components/ErrorTalerOperation.js"; import { LoadingError } from "../../components/LoadingError.js"; import { LogoHeader } from "../../components/LogoHeader.js"; import { Part } from "../../components/Part.js"; +import { QR } from "../../components/QR.js"; import { SelectList } from "../../components/SelectList.js"; import { Input, Link, LinkSuccess, SubTitle, - SuccessBox, SvgIcon, WalletAction, } from "../../components/styled/index.js"; import { useTranslationContext } from "../../context/translation.js"; import { Button } from "../../mui/Button.js"; +import editIcon from "../../svg/edit_24px.svg"; import { ExchangeDetails, WithdrawDetails } from "../../wallet/Transaction.js"; -import { TermsOfServiceSection } from "../TermsOfServiceSection.js"; +import { TermsOfService } from "../TermsOfService/index.js"; import { State } from "./index.js"; -import editIcon from "../../svg/edit_24px.svg"; -import { Amount } from "../../components/Amount.js"; -import { QR } from "../../components/QR.js"; -import { useState } from "preact/hooks"; -import { ErrorMessage } from "../../components/ErrorMessage.js"; export function LoadingUriView({ error }: State.LoadingUriError): VNode { const { i18n } = useTranslationContext(); @@ -66,6 +64,9 @@ export function LoadingInfoView({ error }: State.LoadingInfoError): VNode { export function SuccessView(state: State.Success): VNode { const { i18n } = useTranslationContext(); + const currentTosVersionIsAccepted = + state.currentExchange.tos.acceptedVersion === + state.currentExchange.tos.currentVersion; return ( <WalletAction> <LogoHeader /> @@ -103,7 +104,9 @@ export function SuccessView(state: State.Success): VNode { </Button> </div> } - text={<ExchangeDetails exchange={state.exchangeUrl} />} + text={ + <ExchangeDetails exchange={state.currentExchange.exchangeBaseUrl} /> + } kind="neutral" big /> @@ -130,43 +133,29 @@ export function SuccessView(state: State.Success): VNode { </Input> )} </section> - {state.tosProps && <TermsOfServiceSection {...state.tosProps} />} - {state.tosProps ? ( - <Fragment> - <section> - {(state.tosProps.terms.status === "accepted" || - (state.mustAcceptFirst && state.tosProps.reviewed)) && ( - <Button - variant="contained" - color="success" - disabled={!state.doWithdrawal.onClick} - onClick={state.doWithdrawal.onClick} - > - <i18n.Translate> - Withdraw <Amount value={state.toBeReceived} /> - </i18n.Translate> - </Button> - )} - {state.tosProps.terms.status === "notfound" && ( - <Button - variant="contained" - color="warning" - disabled={!state.doWithdrawal.onClick} - onClick={state.doWithdrawal.onClick} - > - <i18n.Translate>Withdraw anyway</i18n.Translate> - </Button> - )} - </section> - {state.talerWithdrawUri ? ( - <WithdrawWithMobile talerWithdrawUri={state.talerWithdrawUri} /> - ) : undefined} - </Fragment> - ) : ( - <section> - <i18n.Translate>Loading terms of service...</i18n.Translate> - </section> - )} + + <section> + {currentTosVersionIsAccepted ? ( + <Button + variant="contained" + color="success" + disabled={!state.doWithdrawal.onClick} + onClick={state.doWithdrawal.onClick} + > + <i18n.Translate> + Withdraw <Amount value={state.toBeReceived} /> + </i18n.Translate> + </Button> + ) : ( + <TermsOfService + exchangeUrl={state.currentExchange.exchangeBaseUrl} + onChange={state.onTosUpdate} + /> + )} + </section> + {state.talerWithdrawUri ? ( + <WithdrawWithMobile talerWithdrawUri={state.talerWithdrawUri} /> + ) : undefined} <section> <Link upperCased onClick={state.cancel}> <i18n.Translate>Cancel</i18n.Translate> |