aboutsummaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/pages/RegistrationPage.tsx
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-01-23 18:00:42 -0300
committerSebastian <sebasjm@gmail.com>2024-01-24 17:14:02 -0300
commit236d4347f5884bb1d9ca1d3bb4ad0ba776577fd2 (patch)
treea38823a73006c38bd54cb438da81f13bb513dce5 /packages/demobank-ui/src/pages/RegistrationPage.tsx
parent579128ce40c7e56f390cadaf2fc2fd4cc6290d68 (diff)
downloadwallet-core-236d4347f5884bb1d9ca1d3bb4ad0ba776577fd2.tar.xz
many changes
activate eslint update file headers removed history and preact-router remove eslint errors and more applied prettier
Diffstat (limited to 'packages/demobank-ui/src/pages/RegistrationPage.tsx')
-rw-r--r--packages/demobank-ui/src/pages/RegistrationPage.tsx257
1 files changed, 135 insertions, 122 deletions
diff --git a/packages/demobank-ui/src/pages/RegistrationPage.tsx b/packages/demobank-ui/src/pages/RegistrationPage.tsx
index b3a49a178..931a9b700 100644
--- a/packages/demobank-ui/src/pages/RegistrationPage.tsx
+++ b/packages/demobank-ui/src/pages/RegistrationPage.tsx
@@ -13,29 +13,33 @@
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 { AccessToken, HttpStatusCode, Logger, TalerErrorCode, TranslatedString } from "@gnu-taler/taler-util";
+import {
+ AccessToken,
+ HttpStatusCode,
+ TalerErrorCode,
+ TranslatedString,
+ assertUnreachable,
+} from "@gnu-taler/taler-util";
import {
LocalNotificationBanner,
ShowInputErrorLabel,
useLocalNotification,
- useTranslationContext
+ useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { useBankCoreApiContext } from "../context/config.js";
-import { useBackendState } from "../hooks/backend.js";
+import { useSettingsContext } from "../context/settings.js";
+import { RouteDefinition } from "../route.js";
import { undefinedIfEmpty } from "../utils.js";
import { getRandomPassword, getRandomUsername } from "./rnd.js";
-import { useSettingsContext } from "../context/settings.js";
-
-const logger = new Logger("RegistrationPage");
export function RegistrationPage({
- onComplete,
- onCancel
+ onRegistrationSuccesful,
+ routeCancel,
}: {
- onComplete: () => void;
- onCancel: () => void;
+ onRegistrationSuccesful: (user: string, password: string) => void;
+ routeCancel: RouteDefinition<Record<string, never>>;
}): VNode {
const { i18n } = useTranslationContext();
const { config } = useBankCoreApiContext();
@@ -44,50 +48,58 @@ export function RegistrationPage({
<p>{i18n.str`Currently, the bank is not accepting new registrations!`}</p>
);
}
- return <RegistrationForm onComplete={onComplete} onCancel={onCancel} />;
+ return (
+ <RegistrationForm
+ onRegistrationSuccesful={onRegistrationSuccesful}
+ routeCancel={routeCancel}
+ />
+ );
}
export const USERNAME_REGEX = /^[a-z][a-zA-Z0-9-]*$/;
export const PHONE_REGEX = /^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/;
-export const EMAIL_REGEX = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
+export const EMAIL_REGEX = /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/;
-/**
+/**
* Collect and submit registration data.
*/
-function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, onCancel: () => void }): VNode {
- const backend = useBackendState();
+function RegistrationForm({
+ onRegistrationSuccesful,
+ routeCancel,
+}: {
+ onRegistrationSuccesful: (user: string, password: string) => void;
+ routeCancel: RouteDefinition<Record<string, never>>;
+}): VNode {
const [username, setUsername] = useState<string | undefined>();
const [name, setName] = useState<string | undefined>();
const [password, setPassword] = useState<string | undefined>();
- const [phone, setPhone] = useState<string | undefined>();
- const [email, setEmail] = useState<string | undefined>();
+ // const [phone, setPhone] = useState<string | undefined>();
+ // const [email, setEmail] = useState<string | undefined>();
const [repeatPassword, setRepeatPassword] = useState<string | undefined>();
- const [notification, notify, handleError] = useLocalNotification()
+ const [notification, notify, handleError] = useLocalNotification();
const settings = useSettingsContext();
- const { api } = useBankCoreApiContext()
+ const { api } = useBankCoreApiContext();
// const { register } = useTestingAPI();
const { i18n } = useTranslationContext();
const errors = undefinedIfEmpty({
- name: !name
- ? i18n.str`Missing name`
- : undefined,
+ name: !name ? i18n.str`Missing name` : undefined,
username: !username
? i18n.str`Missing username`
: !USERNAME_REGEX.test(username)
? i18n.str`Use letters and numbers only, and start with a lowercase letter`
: undefined,
- phone: !phone
- ? undefined
- : !PHONE_REGEX.test(phone)
- ? i18n.str`Use letters and numbers only, and start with a lowercase letter`
- : undefined,
- email: !email
- ? undefined
- : !EMAIL_REGEX.test(email)
- ? i18n.str`Use letters and numbers only, and start with a lowercase letter`
- : undefined,
+ // phone: !phone
+ // ? undefined
+ // : !PHONE_REGEX.test(phone)
+ // ? i18n.str`Use letters and numbers only, and start with a lowercase letter`
+ // : undefined,
+ // email: !email
+ // ? undefined
+ // : !EMAIL_REGEX.test(email)
+ // ? i18n.str`Use letters and numbers only, and start with a lowercase letter`
+ // : undefined,
password: !password ? i18n.str`Missing password` : undefined,
repeatPassword: !repeatPassword
? i18n.str`Missing password`
@@ -96,106 +108,97 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on
: undefined,
});
- async function doRegistrationAndLogin(name: string, username: string, password: string, onComplete: () => void) {
+ async function doRegistrationAndLogin(
+ name: string,
+ username: string,
+ password: string,
+ onComplete: () => void,
+ ) {
await handleError(async () => {
- createAccount: {
- const resp = await api.createAccount("" as AccessToken, { name, username, password });
- if (resp.type === "fail") {
- switch (resp.case) {
- case HttpStatusCode.BadRequest: return notify({
+ const resp = await api.createAccount("" as AccessToken, {
+ name,
+ username,
+ password,
+ });
+ if (resp.type === "ok") {
+ onComplete();
+ } else {
+ switch (resp.case) {
+ case HttpStatusCode.BadRequest:
+ return notify({
type: "error",
title: i18n.str`Server replied with invalid phone or email.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
- })
- case TalerErrorCode.BANK_UNALLOWED_DEBIT: return notify({
+ });
+ case TalerErrorCode.BANK_UNALLOWED_DEBIT:
+ return notify({
type: "error",
title: i18n.str`Registration is disabled because the bank ran out of bonus credit.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
- })
- case HttpStatusCode.Unauthorized: return notify({
+ });
+ case HttpStatusCode.Unauthorized:
+ return notify({
type: "error",
title: i18n.str`No enough permission to create that account.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
- })
- case TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE: return notify({
+ });
+ case TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE:
+ return notify({
type: "error",
title: i18n.str`That account id is already taken.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
- })
- case TalerErrorCode.BANK_REGISTER_USERNAME_REUSE: return notify({
+ });
+ case TalerErrorCode.BANK_REGISTER_USERNAME_REUSE:
+ return notify({
type: "error",
title: i18n.str`That username is already taken.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
- })
- case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: return notify({
+ });
+ case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT:
+ return notify({
type: "error",
title: i18n.str`That username can't be used because is reserved.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
- })
- case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return notify({
+ });
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT:
+ return notify({
type: "error",
title: i18n.str`Only admin is allow to set debt limit.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
- })
- case TalerErrorCode.BANK_MISSING_TAN_INFO: return notify({
+ });
+ case TalerErrorCode.BANK_MISSING_TAN_INFO:
+ return notify({
type: "error",
title: i18n.str`No information for the selected authentication channel.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
- })
- case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED: return notify({
+ });
+ case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED:
+ return notify({
type: "error",
title: i18n.str`Authentication channel is not supported.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
- })
- case TalerErrorCode.BANK_NON_ADMIN_SET_TAN_CHANNEL: return notify({
+ });
+ case TalerErrorCode.BANK_NON_ADMIN_SET_TAN_CHANNEL:
+ return notify({
type: "error",
title: i18n.str`Only admin can create accounts with second factor authentication.`,
description: resp.detail.hint as TranslatedString,
debug: resp.detail,
- })
- default: assertUnreachable(resp)
- }
- }
- }
- login: {
- const resp = await api.getAuthenticationAPI(username).createAccessToken(password, {
- scope: "readwrite",
- duration: { d_us: "forever" },
- refreshable: true,
- })
-
- if (resp.type === "ok") {
- backend.logIn({ username, token: resp.body.access_token });
- } else {
- switch (resp.case) {
- case HttpStatusCode.Unauthorized: return notify({
- type: "error",
- title: i18n.str`Wrong credentials for "${username}"`,
- description: resp.detail.hint as TranslatedString,
- debug: resp.detail,
- })
- case HttpStatusCode.NotFound: return notify({
- type: "error",
- title: i18n.str`Account not found`,
- description: resp.detail.hint as TranslatedString,
- debug: resp.detail,
- })
- default: assertUnreachable(resp)
- }
+ });
+ default:
+ assertUnreachable(resp);
}
-
}
- onComplete()
- })
+ });
}
async function doRegistrationStep() {
@@ -204,18 +207,21 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on
setUsername(undefined);
setPassword(undefined);
setRepeatPassword(undefined);
- onComplete();
- })
+ onRegistrationSuccesful(username, password);
+ });
}
- async function doRandomRegistration(tries: number = 3) {
+ async function doRandomRegistration() {
const user = getRandomUsername();
- const pass = settings.simplePasswordForRandomAccounts ? "123" : getRandomPassword();
- const username = `_${user.first}-${user.second}_`
- const name = `${user.first}, ${user.second}`
- await doRegistrationAndLogin(name, username, pass, onComplete)
-
+ const password = settings.simplePasswordForRandomAccounts
+ ? "123"
+ : getRandomPassword();
+ const username = `_${user.first}-${user.second}_`;
+ const name = `${user.first}, ${user.second}`;
+ await doRegistrationAndLogin(name, username, password, () => {
+ onRegistrationSuccesful(username, password);
+ });
}
return (
@@ -228,7 +234,9 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on
</div>
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
- <form class="space-y-6" noValidate
+ <form
+ class="space-y-6"
+ noValidate
onSubmit={(e) => {
e.preventDefault();
}}
@@ -236,7 +244,10 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on
autoCorrect="off"
>
<div>
- <label for="username" class="block text-sm font-medium leading-6 text-gray-900">
+ <label
+ for="username"
+ class="block text-sm font-medium leading-6 text-gray-900"
+ >
<i18n.Translate>Username</i18n.Translate>
<b style={{ color: "red" }}> *</b>
</label>
@@ -265,7 +276,10 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on
<div>
<div class="flex items-center justify-between">
- <label for="password" class="block text-sm font-medium leading-6 text-gray-900">
+ <label
+ for="password"
+ class="block text-sm font-medium leading-6 text-gray-900"
+ >
<i18n.Translate>Password</i18n.Translate>
<b style={{ color: "red" }}> *</b>
</label>
@@ -294,7 +308,10 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on
<div>
<div class="flex items-center justify-between">
- <label for="register-repeat" class="block text-sm font-medium leading-6 text-gray-900">
+ <label
+ for="register-repeat"
+ class="block text-sm font-medium leading-6 text-gray-900"
+ >
<i18n.Translate>Repeat password</i18n.Translate>
<b style={{ color: "red" }}> *</b>
</label>
@@ -323,7 +340,10 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on
<div>
<div class="flex items-center justify-between">
- <label for="name" class="block text-sm font-medium leading-6 text-gray-900">
+ <label
+ for="name"
+ class="block text-sm font-medium leading-6 text-gray-900"
+ >
<i18n.Translate>Name</i18n.Translate>
<b style={{ color: "red" }}> *</b>
</label>
@@ -403,50 +423,43 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on
</div> */}
<div class="flex w-full justify-between">
- <button type="submit"
+ <a
+ href={routeCancel.url({})}
class="ring-1 ring-gray-600 rounded-md bg-white disabled:bg-gray-300 px-3 py-1.5 text-sm font-semibold leading-6 text-black shadow-sm hover:bg-white-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"
- onClick={(e) => {
- e.preventDefault()
- onCancel()
- }}
>
<i18n.Translate>Cancel</i18n.Translate>
- </button>
- <button type="submit"
+ </a>
+ <button
+ type="submit"
class=" rounded-md bg-indigo-600 disabled:bg-gray-300 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
disabled={!!errors}
onClick={async (e) => {
- e.preventDefault()
+ e.preventDefault();
- doRegistrationStep()
+ doRegistrationStep();
}}
>
<i18n.Translate>Register</i18n.Translate>
</button>
</div>
-
</form>
- {settings.allowRandomAccountCreation &&
+ {settings.allowRandomAccountCreation && (
<p class="mt-10 text-center text-sm text-gray-500 border-t">
- <button type="submit"
+ <button
+ type="submit"
class="flex mt-4 w-full justify-center rounded-md bg-green-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600"
onClick={(e) => {
- e.preventDefault()
- doRandomRegistration()
+ e.preventDefault();
+ doRandomRegistration();
}}
>
<i18n.Translate>Create a random temporary user</i18n.Translate>
</button>
</p>
- }
+ )}
</div>
</div>
-
</Fragment>
);
}
-
-export function assertUnreachable(x: never): never {
- throw new Error("Didn't expect to get here");
-}