/*
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 { HttpStatusCode, TranslatedString } from "@gnu-taler/taler-util";
import { ErrorType, notifyError, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useEffect, useRef, useState } from "preact/hooks";
import { useBackendContext } from "../context/backend.js";
import { useCredentialsChecker } from "../hooks/backend.js";
import { bankUiSettings } from "../settings.js";
import { undefinedIfEmpty } from "../utils.js";
import { USERNAME_REGEX } from "./RegistrationPage.js";
import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
/**
* Collect and submit login data.
*/
export function LoginForm({ onRegister }: { onRegister?: () => void }): VNode {
const backend = useBackendContext();
const [username, setUsername] = useState();
const [password, setPassword] = useState();
const { i18n } = useTranslationContext();
const testLogin = useCredentialsChecker();
const ref = useRef(null);
useEffect(function focusInput() {
ref.current?.focus();
}, []);
const [busy, setBusy] = useState>()
const errors = undefinedIfEmpty({
username: !username
? i18n.str`Missing username`
: !USERNAME_REGEX.test(username)
? i18n.str`Use letters and numbers only, and start with a lowercase letter`
: undefined,
password: !password ? i18n.str`Missing password` : undefined,
}) ?? busy;
function saveError({ title, description, debug }: { title: TranslatedString, description?: TranslatedString, debug?: any }) {
notifyError(title, description, debug)
}
async function doLogin() {
if (!username || !password) return;
setBusy({})
const testResult = await testLogin(username, password);
if (testResult.valid) {
backend.logIn({ username, password });
} else {
if (testResult.requestError) {
const { cause } = testResult;
switch (cause.type) {
case ErrorType.CLIENT: {
if (cause.status === HttpStatusCode.Unauthorized) {
saveError({
title: i18n.str`Wrong credentials for "${username}"`,
});
} else
if (cause.status === HttpStatusCode.NotFound) {
saveError({
title: i18n.str`Account not found`,
});
} else {
saveError({
title: i18n.str`Could not load due to a client error`,
description: cause.payload.error.description,
debug: JSON.stringify(cause.payload),
});
}
break;
}
case ErrorType.SERVER: {
saveError({
title: i18n.str`Server had a problem, try again later or report.`,
description: cause.payload.error.description,
debug: JSON.stringify(cause.payload),
});
break;
}
case ErrorType.TIMEOUT: {
saveError({
title: i18n.str`Request timeout, try again later.`,
});
break;
}
case ErrorType.UNREADABLE: {
saveError({
title: i18n.str`Unexpected error.`,
description: `Response from ${cause.info?.url} is unreadable, http status: ${cause.status}` as TranslatedString,
debug: JSON.stringify(cause),
});
break;
}
default: {
saveError({
title: i18n.str`Unexpected error, please report.`,
description: `Diagnostic from ${cause.info?.url} is "${cause.message}"` as TranslatedString,
debug: JSON.stringify(cause),
});
break;
}
}
} else {
saveError({
title: i18n.str`Unexpected error, please report.`,
debug: JSON.stringify(testResult.error),
});
}
backend.logOut();
}
setPassword(undefined);
setBusy(undefined)
}
return (
{/* {error && (
saveError(undefined)} />
)} */}
{i18n.str`Welcome to ${bankUiSettings.bankName}!`}