wallet-core/packages/demobank-ui/src/pages/HomePage.tsx
2023-09-25 14:50:40 -03:00

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");
}