/*
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 {
canonicalizeBaseUrl,
TalerConfigResponse,
} from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
import { ErrorMessage } from "../components/ErrorMessage.js";
import {
Input,
LightText,
SubTitle,
Title,
WarningBox,
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
export interface Props {
initialValue?: string;
expectedCurrency?: string;
onCancel: () => Promise;
onVerify: (s: string) => Promise;
onConfirm: (url: string) => Promise;
withError?: string;
}
function useEndpointStatus(
endpoint: string,
onVerify: (e: string) => Promise,
): {
loading: boolean;
error?: string;
endpoint: string;
result: T | undefined;
updateEndpoint: (s: string) => void;
} {
const [value, setValue] = useState(endpoint);
const [dirty, setDirty] = useState(false);
const [loading, setLoading] = useState(false);
const [result, setResult] = useState(undefined);
const [error, setError] = useState(undefined);
const [handler, setHandler] = useState(undefined);
useEffect(() => {
if (!value) return;
window.clearTimeout(handler);
const h = window.setTimeout(async () => {
setDirty(true);
setLoading(true);
try {
const url = canonicalizeBaseUrl(value);
const result = await onVerify(url);
setResult(result);
setError(undefined);
setLoading(false);
} catch (e) {
const errorMessage =
e instanceof Error ? e.message : `unknown error: ${e}`;
setError(errorMessage);
setLoading(false);
setResult(undefined);
}
}, 500);
setHandler(h);
}, [value, setHandler, onVerify]);
return {
error: dirty ? error : undefined,
loading: loading,
result: result,
endpoint: value,
updateEndpoint: setValue,
};
}
export function ExchangeSetUrlPage({
initialValue,
expectedCurrency,
onCancel,
onVerify,
onConfirm,
}: Props): VNode {
const { i18n } = useTranslationContext();
const { loading, result, endpoint, updateEndpoint, error } =
useEndpointStatus(initialValue ?? "", onVerify);
const [confirmationError, setConfirmationError] = useState<
string | undefined
>(undefined);
return (
{!expectedCurrency ? (
Add new exchange
) : (
Add exchange for {expectedCurrency}
)}
{!result && (
Enter the URL of an exchange you trust.
)}
{result && (
An exchange has been found! Review the information and click next
)}
{result && expectedCurrency && expectedCurrency !== result.currency && (
This exchange doesn't match the expected currency
{expectedCurrency}
)}
{error && (
Unable to verify this exchange
}
description={error}
/>
)}
{confirmationError && (
Unable to add this exchange}
description={confirmationError}
/>
)}