From 7f21700576b4de0f5479ea258b75fb141d18a41b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 4 Dec 2023 13:45:03 -0300 Subject: account creation and show login when required --- packages/demobank-ui/src/pages/LoginForm.tsx | 22 +-- packages/demobank-ui/src/pages/WireTransfer.tsx | 4 +- .../src/pages/WithdrawalConfirmationQuestion.tsx | 17 ++- .../src/pages/account/ShowAccountDetails.tsx | 4 +- .../demobank-ui/src/pages/admin/AccountForm.tsx | 167 +++++++++++++-------- .../demobank-ui/src/pages/admin/RemoveAccount.tsx | 4 +- .../src/pages/business/CreateCashout.tsx | 4 +- packages/demobank-ui/src/utils.ts | 37 +++-- 8 files changed, 155 insertions(+), 104 deletions(-) (limited to 'packages') diff --git a/packages/demobank-ui/src/pages/LoginForm.tsx b/packages/demobank-ui/src/pages/LoginForm.tsx index 02ec75dbf..e0ff77417 100644 --- a/packages/demobank-ui/src/pages/LoginForm.tsx +++ b/packages/demobank-ui/src/pages/LoginForm.tsx @@ -28,9 +28,9 @@ import { assertUnreachable } from "./WithdrawalOperationPage.js"; /** * Collect and submit login data. */ -export function LoginForm({ reason, onRegister }: { reason?: "not-found" | "forbidden", onRegister?: () => void }): VNode { +export function LoginForm({ currentUser, fixedUser, onRegister }: { fixedUser?: boolean, currentUser?: string, onRegister?: () => void }): VNode { const backend = useBackendState(); - const currentUser = backend.state.status !== "loggedOut" ? backend.state.username : undefined + const [username, setUsername] = useState(currentUser); const [password, setPassword] = useState(); const { i18n } = useTranslationContext(); @@ -38,21 +38,11 @@ export function LoginForm({ reason, onRegister }: { reason?: "not-found" | "forb const [notification, notify, handleError] = useLocalNotification() const {config} = useBankCoreApiContext(); - /** - * Register form may be shown in the initialization step. - * If no register handler then this is invoke - * to show a session expired or unauthorized - */ - const isLogginAgain = !onRegister - const ref = useRef(null); useEffect(function focusInput() { - if (isLogginAgain && backend.state.status !== "expired") { - backend.expired() - window.location.reload() - } ref.current?.focus(); }, []); + const [busy, setBusy] = useState>() const errors = undefinedIfEmpty({ @@ -128,7 +118,7 @@ export function LoginForm({ reason, onRegister }: { reason?: "not-found" | "forb id="username" class="block w-full disabled:bg-gray-200 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" value={username ?? ""} - disabled={isLogginAgain} + disabled={fixedUser} enterkeyhint="next" placeholder="identification" autocomplete="username" @@ -170,7 +160,7 @@ export function LoginForm({ reason, onRegister }: { reason?: "not-found" | "forb - {isLogginAgain ?
+ {currentUser ?
:
} -
- - { - setDebitAmount(e); - }} - /> - -

allow user debt

-
+ {admin ? +
+ + { + form.debitAmount = e + updateForm(structuredClone(form)) + }} + /> + +

how much is user able to transfer

+
-
-
- - - Is an exchange +
+
+ + + Is an exchange + - - + onClick={() => { + form.isExchange = !form.isExchange + updateForm(structuredClone(form)) + }}> + + +
-
+ : + undefined + } -
-
- - - Is public + {purpose === "create" ? +
+
+ + + Is public + - - + onClick={() => { + form.isPublic = !form.isPublic + updateForm(structuredClone(form)) + }}> + + +
+

+ public accounts have their balance publicly accesible +

-
+ : undefined + }
@@ -386,7 +427,7 @@ export function AccountForm({ ); } - +// JNTMECG7RM3AAQB6SRAZNWDSM8 function initializeFromTemplate( username: string | undefined, account: TalerCorebankApi.AccountData | undefined, diff --git a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx index 5ee887128..57144177c 100644 --- a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx +++ b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx @@ -39,8 +39,8 @@ export function RemoveAccount({ } if (result.type === "fail") { switch (result.case) { - case "unauthorized": return - case "not-found": return + case "unauthorized": return + case "not-found": return default: assertUnreachable(result) } } diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx b/packages/demobank-ui/src/pages/business/CreateCashout.tsx index b2ff41e63..ce1a6cf49 100644 --- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx +++ b/packages/demobank-ui/src/pages/business/CreateCashout.tsx @@ -102,8 +102,8 @@ export function CreateCashout({ } if (resultAccount.type === "fail") { switch (resultAccount.case) { - case "unauthorized": return - case "not-found": return + case "unauthorized": return + case "not-found": return default: assertUnreachable(resultAccount) } } diff --git a/packages/demobank-ui/src/utils.ts b/packages/demobank-ui/src/utils.ts index 805d68660..7cdd8a861 100644 --- a/packages/demobank-ui/src/utils.ts +++ b/packages/demobank-ui/src/utils.ts @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see */ -import { HttpStatusCode, TalerError, TalerErrorCode, TranslatedString } from "@gnu-taler/taler-util"; +import { AmountString, HttpStatusCode, PaytoString, TalerError, TalerErrorCode, TranslatedString } from "@gnu-taler/taler-util"; import { ErrorNotification, ErrorType, @@ -62,17 +62,36 @@ export type PartialButDefined = { [P in keyof T]: T[P] | undefined; }; -export type WithIntermediate = { - [prop in keyof Type]: Type[prop] extends object +/** + * every non-map field can be undefined + */ +export type WithIntermediate = { + [prop in keyof Type]: + Type[prop] extends PaytoString ? Type[prop] | undefined : + Type[prop] extends AmountString ? Type[prop] | undefined : + Type[prop] extends TranslatedString ? Type[prop] | undefined : + Type[prop] extends object ? WithIntermediate : Type[prop] | undefined; }; -export type RecursivePartial = { - [P in keyof T]?: T[P] extends (infer U)[] +export type RecursivePartial = { + [P in keyof Type]?: Type[P] extends (infer U)[] ? RecursivePartial[] - : T[P] extends object - ? RecursivePartial - : T[P]; + : Type[P] extends object + ? RecursivePartial + : Type[P]; +}; +export type ErrorMessageMappingFor = { + [prop in keyof Type]+?: + //enumerate known object + Exclude extends PaytoString ? TranslatedString : + Exclude extends AmountString ? TranslatedString : + Exclude extends TranslatedString ? TranslatedString : + // arrays: every element + Exclude extends (infer U)[] ? ErrorMessageMappingFor[] : + // map: every field + Exclude extends object ? ErrorMessageMappingFor + : TranslatedString; }; export enum TanChannel { @@ -337,7 +356,7 @@ export const COUNTRY_TABLE = { export function validateIBAN( iban: string, i18n: ReturnType["i18n"], -): string | undefined { +): TranslatedString | undefined { // Check total length if (iban.length < 4) return i18n.str`IBAN numbers usually have more that 4 digits`; -- cgit v1.2.3