197 lines
5.7 KiB
TypeScript
197 lines
5.7 KiB
TypeScript
/*
|
|
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 {
|
|
HttpStatusCode,
|
|
Logger,
|
|
TranslatedString,
|
|
parseWithdrawUri,
|
|
stringifyWithdrawUri,
|
|
} from "@gnu-taler/taler-util";
|
|
import {
|
|
ErrorType,
|
|
HttpResponse,
|
|
HttpResponsePaginated,
|
|
notify,
|
|
notifyError,
|
|
useTranslationContext,
|
|
} from "@gnu-taler/web-util/browser";
|
|
import { Fragment, VNode, h } from "preact";
|
|
import { Loading } from "../components/Loading.js";
|
|
import { useBackendContext } from "../context/backend.js";
|
|
import { getInitialBackendBaseURL } from "../hooks/backend.js";
|
|
import { useSettings } from "../hooks/settings.js";
|
|
import { AccountPage } from "./AccountPage/index.js";
|
|
import { AdminPage } from "./AdminPage.js";
|
|
import { LoginForm } from "./LoginForm.js";
|
|
import { WithdrawalQRCode } from "./WithdrawalQRCode.js";
|
|
import { error } from "console";
|
|
|
|
const logger = new Logger("AccountPage");
|
|
|
|
/**
|
|
* show content based on state:
|
|
* - LoginForm if the user is not logged in
|
|
* - qr code if withdrawal in progress
|
|
* - else account information
|
|
* Use the handler to catch error cases
|
|
*
|
|
* @param param0
|
|
* @returns
|
|
*/
|
|
export function HomePage({
|
|
onRegister,
|
|
onPendingOperationFound,
|
|
}: {
|
|
onPendingOperationFound: (id: string) => void;
|
|
onRegister: () => void;
|
|
}): VNode {
|
|
const backend = useBackendContext();
|
|
const [settings] = useSettings();
|
|
const { i18n } = useTranslationContext();
|
|
|
|
if (backend.state.status === "loggedOut") {
|
|
return <LoginForm onRegister={onRegister} />;
|
|
}
|
|
|
|
if (settings.currentWithdrawalOperationId) {
|
|
onPendingOperationFound(settings.currentWithdrawalOperationId);
|
|
return <Loading />;
|
|
}
|
|
|
|
if (backend.state.isUserAdministrator) {
|
|
return <AdminPage onRegister={onRegister} />;
|
|
}
|
|
|
|
return (
|
|
<AccountPage
|
|
account={backend.state.username}
|
|
onLoadNotOk={handleNotOkResult(i18n, onRegister)}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export function WithdrawalOperationPage({
|
|
operationId,
|
|
onLoadNotOk,
|
|
onContinue,
|
|
}: {
|
|
operationId: string;
|
|
onLoadNotOk: () => void;
|
|
onContinue: () => void;
|
|
}): VNode {
|
|
//FIXME: libeufin sandbox should return show to create the integration api endpoint
|
|
//or return withdrawal uri from response
|
|
const baseUrl = getInitialBackendBaseURL()
|
|
const uri = stringifyWithdrawUri({
|
|
bankIntegrationApiBaseUrl: `${baseUrl}/integration-api`,
|
|
withdrawalOperationId: operationId,
|
|
});
|
|
const parsedUri = parseWithdrawUri(uri);
|
|
const { i18n } = useTranslationContext();
|
|
|
|
if (!parsedUri) {
|
|
notifyError(
|
|
i18n.str`The Withdrawal URI is not valid: "${uri}"`,
|
|
undefined
|
|
);
|
|
return <Loading />;
|
|
}
|
|
|
|
return (
|
|
<WithdrawalQRCode
|
|
withdrawUri={parsedUri}
|
|
onContinue={onContinue}
|
|
onLoadNotOk={onLoadNotOk}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export function handleNotOkResult(
|
|
i18n: ReturnType<typeof useTranslationContext>["i18n"],
|
|
onRegister?: () => void,
|
|
): <T>(
|
|
result:
|
|
| HttpResponsePaginated<T, SandboxBackend.SandboxError>
|
|
| HttpResponse<T, SandboxBackend.SandboxError>,
|
|
) => VNode {
|
|
return function handleNotOkResult2<T>(
|
|
result:
|
|
| HttpResponsePaginated<T, SandboxBackend.SandboxError>
|
|
| HttpResponse<T, SandboxBackend.SandboxError>,
|
|
): VNode {
|
|
if (result.loading) return <Loading />;
|
|
if (!result.ok) {
|
|
switch (result.type) {
|
|
case ErrorType.TIMEOUT: {
|
|
notifyError(i18n.str`Request timeout, try again later.`, undefined);
|
|
break;
|
|
}
|
|
case ErrorType.CLIENT: {
|
|
if (result.status === HttpStatusCode.Unauthorized) {
|
|
notifyError(i18n.str`Wrong credentials`, undefined);
|
|
return <LoginForm onRegister={onRegister} />;
|
|
}
|
|
const errorData = result.payload;
|
|
notify({
|
|
type: "error",
|
|
title: i18n.str`Could not load due to a client error`,
|
|
description: errorData.error.description as TranslatedString,
|
|
debug: JSON.stringify(result),
|
|
});
|
|
break;
|
|
}
|
|
case ErrorType.SERVER: {
|
|
notify({
|
|
type: "error",
|
|
title: i18n.str`Server returned with error`,
|
|
description: result.payload.error.description as TranslatedString,
|
|
debug: JSON.stringify(result.payload),
|
|
});
|
|
break;
|
|
}
|
|
case ErrorType.UNREADABLE: {
|
|
notify({
|
|
type: "error",
|
|
title: i18n.str`Unexpected error.`,
|
|
description: i18n.str`Response from ${result.info?.url} is unreadable, http status: ${result.status}`,
|
|
debug: JSON.stringify(result),
|
|
});
|
|
break;
|
|
}
|
|
case ErrorType.UNEXPECTED: {
|
|
notify({
|
|
type: "error",
|
|
title: i18n.str`Unexpected error.`,
|
|
description: i18n.str`Diagnostic from ${result.info?.url} is "${result.message}"`,
|
|
debug: JSON.stringify(result),
|
|
});
|
|
break;
|
|
}
|
|
default: {
|
|
assertUnreachable(result);
|
|
}
|
|
}
|
|
|
|
return <div>error</div>;
|
|
}
|
|
return <div />;
|
|
};
|
|
}
|
|
export function assertUnreachable(x: never): never {
|
|
throw new Error("Didn't expect to get here");
|
|
}
|