/* 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 */ import { Amounts } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { useState } from "preact/hooks"; import { alertFromError, useAlertContext } from "../../context/alert.js"; import { useBackendContext } from "../../context/backend.js"; import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; import { AmountFieldHandler, TextFieldHandler } from "../../mui/handlers.js"; import { Props, State } from "./index.js"; export function useComponentState({ talerTemplateUri, cancel, goToWalletManualWithdraw, onSuccess, }: Props): State { const api = useBackendContext(); const { i18n } = useTranslationContext(); const { safely } = useAlertContext(); const url = talerTemplateUri ? new URL(talerTemplateUri) : undefined; const amountParam = !url ? undefined : url.searchParams.get("amount") ?? undefined; const summaryParam = !url ? undefined : url.searchParams.get("summary") ?? undefined; const parsedAmount = !amountParam ? undefined : Amounts.parse(amountParam); const currency = parsedAmount ? parsedAmount.currency : amountParam; const initialAmount = parsedAmount ?? (currency ? Amounts.zeroOfCurrency(currency) : undefined); const [amount, setAmount] = useState(initialAmount); const [summary, setSummary] = useState(summaryParam); const [newOrder, setNewOrder] = useState(""); const hook = useAsyncAsHook(async () => { if (!talerTemplateUri) throw Error("ERROR_NO-URI-FOR-PAYMENT-TEMPLATE"); let payStatus; if (!amountParam && !summaryParam) { payStatus = await api.wallet.call( WalletApiOperation.PreparePayForTemplate, { talerPayTemplateUri: talerTemplateUri, templateParams: {}, }, ); } const balance = await api.wallet.call(WalletApiOperation.GetBalances, {}); return { payStatus, balance, uri: talerTemplateUri }; }, []); if (!hook) { return { status: "loading", error: undefined, }; } if (hook.hasError) { return { status: "error", error: alertFromError( i18n.str`Could not load the status of the order template`, hook, ), }; } if (hook.response.payStatus) { return { status: "order-ready", error: undefined, cancel, goToWalletManualWithdraw, onSuccess, talerPayUri: hook.response.payStatus.talerUri!, }; } if (newOrder) { return { status: "order-ready", error: undefined, cancel, goToWalletManualWithdraw, onSuccess, talerPayUri: newOrder, }; } async function createOrder() { try { const templateParams: Record = {}; if (amount) { templateParams["amount"] = Amounts.stringify(amount); } if (summary) { templateParams["summary"] = summary; } const payStatus = await api.wallet.call( WalletApiOperation.PreparePayForTemplate, { talerPayTemplateUri: talerTemplateUri, templateParams, }, ); setNewOrder(payStatus.talerUri!); } catch (e) {} } const errors = undefinedIfEmpty({ amount: amount && Amounts.isZero(amount) ? i18n.str`required` : undefined, summary: !summary ? i18n.str`required` : undefined, }); return { status: "fill-template", error: undefined, currency: currency!, //currency is always not null amount: amount !== undefined ? ({ onInput: (a) => { setAmount(a); }, value: amount, error: errors?.amount, } as AmountFieldHandler) : undefined, summary: summary !== undefined ? ({ onInput: (t) => { setSummary(t); }, value: summary, error: errors?.summary, } as TextFieldHandler) : undefined, onCreate: { onClick: errors ? undefined : safely("create order for pay template", createOrder), }, }; } function undefinedIfEmpty(obj: T): T | undefined { return Object.keys(obj).some((k) => (obj as any)[k] !== undefined) ? obj : undefined; }