/* This file is part of GNU Taler (C) 2021-2023 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 */ /** * * @author Sebastian Javier Marchano (sebasjm) */ import { HttpError, RequestError, useApiContext, useTranslationContext } from "@gnu-taler/web-util/browser"; import { Fragment, h, VNode } from "preact"; import { StateUpdater, useEffect, useState } from "preact/hooks"; import { AsyncButton } from "../../../../components/exception/AsyncButton.js"; import { FormErrors, FormProvider, } from "../../../../components/form/FormProvider.js"; import { Input } from "../../../../components/form/Input.js"; import { InputCurrency } from "../../../../components/form/InputCurrency.js"; import { InputSelector } from "../../../../components/form/InputSelector.js"; import { MerchantBackend } from "../../../../declaration.js"; import { PAYTO_WIRE_METHOD_LOOKUP, URL_REGEX, } from "../../../../utils/constants.js"; import { useBackendBaseRequest } from "../../../../hooks/backend.js"; import { parsePaytoUri } from "@gnu-taler/taler-util"; type Entity = MerchantBackend.Rewards.ReserveCreateRequest; interface Props { onCreate: (d: Entity) => Promise; onBack?: () => void; } enum Steps { EXCHANGE, WIRE_METHOD, } interface ViewProps { step: Steps; setCurrentStep: (s: Steps) => void; reserve: Partial; onBack?: () => void; submitForm: () => Promise; setReserve: StateUpdater>; } function ViewStep({ step, setCurrentStep, reserve, onBack, submitForm, setReserve, }: ViewProps): VNode { const { i18n } = useTranslationContext(); const {request} = useApiContext() const [wireMethods, setWireMethods] = useState>([]); const [exchangeQueryError, setExchangeQueryError] = useState< string | undefined >(undefined); useEffect(() => { setExchangeQueryError(undefined); }, [reserve.exchange_url]); switch (step) { case Steps.EXCHANGE: { const errors: FormErrors = { initial_balance: !reserve.initial_balance ? "cannot be empty" : !(parseInt(reserve.initial_balance.split(":")[1], 10) > 0) ? i18n.str`it should be greater than 0` : undefined, exchange_url: !reserve.exchange_url ? i18n.str`cannot be empty` : !URL_REGEX.test(reserve.exchange_url) ? i18n.str`must be a valid URL` : !exchangeQueryError ? undefined : exchangeQueryError, }; const hasErrors = Object.keys(errors).some( (k) => (errors as any)[k] !== undefined, ); return ( object={reserve} errors={errors} valueHandler={setReserve} > name="initial_balance" label={i18n.str`Initial balance`} tooltip={i18n.str`balance prior to deposit`} /> name="exchange_url" label={i18n.str`Exchange URL`} tooltip={i18n.str`URL of exchange`} />
{onBack && ( )} { if (!reserve.exchange_url) { return Promise.resolve(); } return request(reserve.exchange_url, "keys") .then((r) => { console.log(r) if (r.loading) return; if (r.ok) { const wireMethods = r.data.accounts.map((a: any) => { const p = parsePaytoUri(a.payto_uri); const r = p?.targetType return r }).filter((x:any) => !!x); setWireMethods(Array.from(new Set(wireMethods))); } setCurrentStep(Steps.WIRE_METHOD); return; }) .catch((r: RequestError<{}>) => { console.log(r.cause) setExchangeQueryError(r.cause.message); }); }} data-tooltip={ hasErrors ? i18n.str`Need to complete marked fields` : "confirm operation" } disabled={hasErrors} > Next
); } case Steps.WIRE_METHOD: { const errors: FormErrors = { wire_method: !reserve.wire_method ? i18n.str`cannot be empty` : undefined, }; const hasErrors = Object.keys(errors).some( (k) => (errors as any)[k] !== undefined, ); return ( object={reserve} errors={errors} valueHandler={setReserve} > name="initial_balance" label={i18n.str`Initial balance`} tooltip={i18n.str`balance prior to deposit`} readonly /> name="exchange_url" label={i18n.str`Exchange URL`} tooltip={i18n.str`URL of exchange`} readonly /> name="wire_method" label={i18n.str`Wire method`} tooltip={i18n.str`method to use for wire transfer`} values={wireMethods} placeholder={i18n.str`Select one wire method`} />
{onBack && ( )} Confirm
); } } } export function CreatePage({ onCreate, onBack }: Props): VNode { const [reserve, setReserve] = useState>({}); const submitForm = () => { return onCreate(reserve as Entity); }; const [currentStep, setCurrentStep] = useState(Steps.EXCHANGE); return ( ); }