diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/components/TermsOfService/state.ts')
-rw-r--r-- | packages/taler-wallet-webextension/src/components/TermsOfService/state.ts | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts b/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts new file mode 100644 index 000000000..76524f0f4 --- /dev/null +++ b/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts @@ -0,0 +1,160 @@ +/* + This file is part of GNU Taler + (C) 2022 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { useTranslationContext } from "@gnu-taler/web-util/browser"; +import { useState } from "preact/hooks"; +import { alertFromError, useAlertContext } from "../../context/alert.js"; +import { useBackendContext } from "../../context/backend.js"; +import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; +import { Props, State } from "./index.js"; +import { buildTermsOfServiceState } from "./utils.js"; + +const supportedFormats = { + "text/html": "HTML", + "text/xml" : "XML", + "text/markdown" : "Markdown", + "text/plain" : "Plain text", + "text/pdf" : "PDF", +} + +export function useComponentState({ showEvenIfaccepted, exchangeUrl, readOnly, children }: Props): State { + const api = useBackendContext(); + const [showContent, setShowContent] = useState<boolean>(!!readOnly); + const { i18n, lang } = useTranslationContext(); + const [tosLang, setTosLang] = useState<string>() + const { pushAlertOnError } = useAlertContext(); + + const [format, setFormat] = useState("text/html") + + const acceptedLang = tosLang ?? lang + /** + * For the exchange selected, bring the status of the terms of service + */ + const terms = useAsyncAsHook(async () => { + const exchangeTos = await api.wallet.call( + WalletApiOperation.GetExchangeTos, + { + exchangeBaseUrl: exchangeUrl, + acceptedFormat: [format], + acceptLanguage: acceptedLang, + }, + ); + + const supportedLangs = exchangeTos.tosAvailableLanguages.reduce((prev, cur) => { + prev[cur] = cur + return prev; + }, {} as Record<string, string>) + + const state = buildTermsOfServiceState(exchangeTos); + + return { state, supportedLangs }; + }, [acceptedLang, format]); + + if (!terms) { + return { + status: "loading", + error: undefined, + }; + } + if (terms.hasError) { + return { + status: "error", + error: alertFromError( + i18n, + i18n.str`Could not load the status of the term of service`, + terms, + ), + }; + } + const { state, supportedLangs } = terms.response; + + async function onUpdate(accepted: boolean): Promise<void> { + if (!state) return; + + if (accepted) { + await api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, { + exchangeBaseUrl: exchangeUrl, + }); + } else { + // mark as not accepted + } + terms?.retry() + } + + const accepted = state.status === "accepted"; + + const base = { + error: undefined, + showingTermsOfService: { + value: showContent && (!accepted || showEvenIfaccepted), + button: { + onClick: accepted && !showEvenIfaccepted ? undefined : pushAlertOnError(async () => { + setShowContent(!showContent); + }), + }, + }, + terms: state, + termsAccepted: { + value: accepted, + button: { + onClick: readOnly ? undefined : pushAlertOnError(async () => { + const newValue = !accepted; //toggle + await onUpdate(newValue); + setShowContent(false); + }), + }, + }, + }; + + if (accepted) { + return { + status: "show-buttons-accepted", + ...base, + children, + }; + } + + if ((accepted && showEvenIfaccepted) || showContent) { + return { + status: "show-content", + error: undefined, + terms: state, + showingTermsOfService: readOnly ? undefined : base.showingTermsOfService, + termsAccepted: base.termsAccepted, + tosFormat: { + onChange: pushAlertOnError(async (s) => { + setFormat(s) + }), + list: supportedFormats, + value: format ?? "" + }, + tosLang: { + onChange: pushAlertOnError(async (s) => { + setTosLang(s) + }), + list: supportedLangs, + value: tosLang ?? lang + } + }; + } + //showing buttons + return { + status: "show-buttons-not-accepted", + ...base, + }; + +} |