/* 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, PreparePayResult } from "@gnu-taler/taler-util"; 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 { AmountFieldHandler, TextFieldHandler } from "../../mui/handlers.js"; import { RecursiveState } from "../../utils/index.js"; import { Props, State } from "./index.js"; export function useComponentState({ talerTemplateUri, cancel, goToWalletManualWithdraw, onSuccess, }: Props): RecursiveState { const api = useBackendContext(); const { i18n } = useTranslationContext(); const { safely } = useAlertContext(); // const url = talerTemplateUri ? new URL(talerTemplateUri) : undefined; // const parsedAmount = !amountParam ? undefined : Amounts.parse(amountParam); // const currency = parsedAmount ? parsedAmount.currency : amountParam; // const initialAmount = // parsedAmount ?? (currency ? Amounts.zeroOfCurrency(currency) : undefined); const [newOrder, setNewOrder] = useState(""); const hook = useAsyncAsHook(async () => { if (!talerTemplateUri) throw Error("ERROR_NO-URI-FOR-PAYMENT-TEMPLATE"); const templateP = await api.wallet.call( WalletApiOperation.CheckPayForTemplate, { talerPayTemplateUri: talerTemplateUri }, ); const requireMoreInfo = !templateP.templateDetails.template_contract.amount || !templateP.templateDetails.template_contract.summary; let payStatus: PreparePayResult | undefined = undefined; if (!requireMoreInfo) { payStatus = await api.wallet.call(WalletApiOperation.PreparePayForTemplate, { talerPayTemplateUri: talerTemplateUri }); } const balance = await api.wallet.call(WalletApiOperation.GetBalances, {}); return { payStatus, balance, uri: talerTemplateUri, templateP }; }, []); if (!hook) { return { status: "loading", error: undefined, }; } if (hook.hasError) { return { status: "error", error: alertFromError( i18n, 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, }; } return () => { const cfg = hook.response.templateP.templateDetails.template_contract; const def = hook.response.templateP.templateDetails.editable_defaults; const fixedAmount = cfg.amount !== undefined ? Amounts.parseOrThrow(cfg.amount) : undefined; const fixedSummary = cfg.summary !== undefined ? cfg.summary : undefined; const defaultAmount = def?.amount !== undefined ? Amounts.parseOrThrow(def.amount) : undefined; const defaultSummary = def?.summary !== undefined ? def.summary : undefined; const zero = fixedAmount ? Amounts.zeroOfAmount(fixedAmount) : cfg.currency !== undefined ? Amounts.zeroOfCurrency(cfg.currency) : defaultAmount !== undefined ? Amounts.zeroOfAmount(defaultAmount) : def?.currency !== undefined ? Amounts.zeroOfCurrency(def.currency) : Amounts.zeroOfCurrency(hook.response.templateP.supportedCurrencies[0]); const [amount, setAmount] = useState(defaultAmount ?? zero); const [summary, setSummary] = useState(defaultSummary ?? ""); async function createOrder() { try { const templateParams: Record = {}; if (amount && !fixedAmount) { templateParams["amount"] = Amounts.stringify(amount); } if (summary && !fixedSummary) { templateParams["summary"] = summary; } const payStatus = await api.wallet.call( WalletApiOperation.PreparePayForTemplate, { talerPayTemplateUri: talerTemplateUri, templateParams, }, ); setNewOrder(payStatus.talerUri!); } catch (e) { console.error(e); } } const errors = undefinedIfEmpty({ amount: fixedAmount !== undefined ? undefined : amount && Amounts.isZero(amount) ? i18n.str`required` : undefined, summary: fixedSummary !== undefined ? undefined : summary !== undefined && !summary ? i18n.str`required` : undefined, }); return { status: "fill-template", error: undefined, minAge: cfg.minimum_age ?? 0, amount: fixedAmount === undefined ? ({ onInput: (a) => { setAmount(a); }, value: amount, error: errors?.amount, } as AmountFieldHandler) : undefined, summary: fixedSummary === 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 Record)[k] !== undefined, ) ? obj : undefined; }