taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit bcb1e0f11e6b43fd778987bc7b5bd20caaddb3ce
parent 280b5aeda21218cca2b3291bc92c9e1b1e58fd68
Author: Sebastian <sebasjm@gmail.com>
Date:   Tue, 23 Sep 2025 16:51:01 -0300

fixes #10426

Diffstat:
Mpackages/bank-ui/src/Routing.tsx | 14--------------
Mpackages/bank-ui/src/pages/SolveMFA.tsx | 196+------------------------------------------------------------------------------
Mpackages/merchant-backoffice-ui/src/paths/newAccount/index.tsx | 7++++---
3 files changed, 6 insertions(+), 211 deletions(-)

diff --git a/packages/bank-ui/src/Routing.tsx b/packages/bank-ui/src/Routing.tsx @@ -177,20 +177,6 @@ function PublicRounting({ <SolveMFAChallenges currentChallenge={mfa.pendingChallenge} description={i18n.str`New web session`} - // currentChallenge={{ - // challenges: [ - // { - // challenge_id: "123", - // tan_channel: TanChannel.EMAIL, - // tan_info: "asd@qwe.com" - // }, - // { - // challenge_id: "123", - // tan_channel: TanChannel.SMS, - // tan_info: "+54 89798" - // }], - // combi_and: false - // }} onCancel={mfa.doCancelChallenge} onCompleted={repeatLogin} /> diff --git a/packages/bank-ui/src/pages/SolveMFA.tsx b/packages/bank-ui/src/pages/SolveMFA.tsx @@ -10,17 +10,15 @@ import { ButtonBetter, LocalNotificationBanner, ShowInputErrorLabel, - Time, undefinedIfEmpty, useBankCoreApiContext, useLocalNotificationBetter, - useTranslationContext, + useTranslationContext } from "@gnu-taler/web-util/browser"; import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { useSessionState } from "../hooks/session.js"; import { doAutoFocus } from "./PaytoWireTransferForm.js"; -import { TalerCorebankApi } from "@gnu-taler/taler-util"; export interface Props { onCompleted(challenges: string[]): void; @@ -29,10 +27,6 @@ export interface Props { currentChallenge: ChallengeResponse; } -interface Form { - code: string; -} - function SolveChallenge({ challenge, onCancel, @@ -129,7 +123,6 @@ function SolveChallenge({ 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={tanCode ?? ""} - // disabled={fixedUser} enterkeyhint="next" placeholder="T-12345678" autocomplete="username" @@ -168,62 +161,6 @@ function SolveChallenge({ </div> </div> </div> - {/* <div class="columns is-centered" style={{ margin: "auto" }}> - <div class="column is-two-thirds "> - <div class="modal-card" style={{ width: "100%", margin: 0 }}> - <header - class="modal-card-head" - style={{ border: "1px solid", borderBottom: 0 }} - > - <p class="modal-card-title"> - <i18n.Translate>Validation code sent.</i18n.Translate> - </p> - </header> - <section - class="modal-card-body" - style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }} - > - {(function (): VNode { - switch (challenge.tan_channel) { - case TanChannel.SMS: - return ( - <i18n.Translate> - The verification code sent to the phone number starting - with "<b>{challenge.tan_info}</b>" - </i18n.Translate> - ); - case TanChannel.EMAIL: - return ( - <i18n.Translate> - The verification code sent to the email address starting - with "<b>{challenge.tan_info}</b>" - </i18n.Translate> - ); - } - })()} - </section> - <footer - class="modal-card-foot " - style={{ - justifyContent: "space-between", - border: "1px solid", - borderTop: 0, - }} - > - <button class="button" onClick={onCancel}> - <i18n.Translate>Back</i18n.Translate> - </button> - <ButtonBetter - type="is-info" - disabled={errors !== undefined} - onClick={doVerification} - > - <i18n.Translate>Verify</i18n.Translate> - </ButtonBetter> - </footer> - </div> - </div> - </div> */} </Fragment> ); } @@ -237,11 +174,6 @@ export function SolveMFAChallenges({ const { i18n } = useTranslationContext(); const [solved, setSolved] = useState<string[]>([]); - // const [selected, setSelected] = useState<Challenge | undefined>({ - // challenge_id: "123", - // tan_channel: TanChannel.EMAIL, - // tan_info: "asd@qwe.com", - // }); const [selected, setSelected] = useState<Challenge>(); const [notification, withErrorHandler] = useLocalNotificationBetter(); const session = useSessionState(); @@ -332,24 +264,7 @@ export function SolveMFAChallenges({ </h2> </div> </div> - {/* <dl class="divide-y divide-gray-100"> - <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> - <dt class="text-sm font-medium leading-6 text-gray-900"> - <i18n.Translate>Type</i18n.Translate> - </dt> - <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> - <i18n.Translate>Updating account settings</i18n.Translate> - </dd> - </div> - <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> - <dt class="text-sm font-medium leading-6 text-gray-900"> - <i18n.Translate>Account</i18n.Translate> - </dt> - <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> - asd - </dd> - </div> - </dl> */} + <h2 class="text-base leading-7 text-gray-900 "> <span class="text-sm leading-6 " id="availability-label"> {currentChallenge.challenges.length === 1 ? ( @@ -459,113 +374,6 @@ export function SolveMFAChallenges({ </div> </div> </div> - - {/* <div class="columns is-centered" style={{ margin: "auto" }}> - <div class="column is-two-thirds "> - <div class="modal-card" style={{ width: "100%", margin: 0 }}> - <header - class="modal-card-head" - style={{ border: "1px solid", borderBottom: 0 }} - > - <p class="modal-card-title"></p> - </header> - <section - class="modal-card-body" - style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }} - > - {currentChallenge.combi_and ? ( - <i18n.Translate> - You need to complete all of this requirements. - </i18n.Translate> - ) : ( - <i18n.Translate> - You need to complete at least one of this requirements. - </i18n.Translate> - )} - </section> - {currentChallenge.challenges.map((challenge) => { - return ( - <section - class="modal-card-body" - style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }} - > - {(function (): VNode { - switch (challenge.tan_channel) { - case TanChannel.SMS: - return ( - <i18n.Translate> - An SMS to the phone number starting with{" "} - {challenge.tan_info} - </i18n.Translate> - ); - case TanChannel.EMAIL: - return ( - <i18n.Translate> - An email to the address starting with{" "} - {challenge.tan_info} - </i18n.Translate> - ); - } - })()} - - <div - style={{ - justifyContent: "space-between", - display: "flex", - }} - > - <button - disabled={ - hasSolvedEnough || - solved.indexOf(challenge.challenge_id) !== -1 - } - class="button" - onClick={() => { - setSelected(challenge); - }} - > - <i18n.Translate>I have a code</i18n.Translate> - </button> - <ButtonBetter - disabled={ - hasSolvedEnough || - solved.indexOf(challenge.challenge_id) !== -1 - } - onClick={ - !username - ? undefined - : () => sendMessage(username, challenge) - } - > - <i18n.Translate>Send me a message</i18n.Translate> - </ButtonBetter> - </div> - </section> - ); - })} - <footer - class="modal-card-foot " - style={{ - justifyContent: "space-between", - border: "1px solid", - borderTop: 0, - }} - > - <button class="button" onClick={onCancel}> - <i18n.Translate>Cancel</i18n.Translate> - </button> - <ButtonBetter - type="is-info" - onClick={ - !hasSolvedEnough ? undefined : async () => onCompleted(solved) - } - > - <i18n.Translate>Complete</i18n.Translate> - </ButtonBetter> - </footer> - </div> - </div> - </div> */} </Fragment> ); } diff --git a/packages/merchant-backoffice-ui/src/paths/newAccount/index.tsx b/packages/merchant-backoffice-ui/src/paths/newAccount/index.tsx @@ -16,6 +16,7 @@ import { HttpStatusCode, MerchantAuthMethod } from "@gnu-taler/taler-util"; import { + undefinedIfEmpty, useChallengeHandler, useTranslationContext, } from "@gnu-taler/web-util/browser"; @@ -56,7 +57,7 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode { const [notif, setNotif] = useState<Notification | undefined>(undefined); const [value, setValue] = useState<Partial<Account>>({}); - const errors: FormErrors<Account> = { + const errors = undefinedIfEmpty<FormErrors<Account>>({ id: !value.id ? i18n.str`Required` : !INSTANCE_ID_REGEX.test(value.id) @@ -81,7 +82,7 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode { : !PHONE_JUST_NUMBERS_REGEX.test(value.phone) ? i18n.str`A phone number consists of numbers only` : undefined, - }; + }); function valueHandler(s: (d: Partial<Account>) => Partial<Account>): void { const next = s(value); @@ -231,7 +232,7 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode { <button class="button" onClick={onCancel}> <i18n.Translate>Cancel</i18n.Translate> </button> - <AsyncButton type="is-info" disabled={!errors} onClick={doCreate}> + <AsyncButton type="is-info" disabled={!!errors} onClick={doCreate}> <i18n.Translate>Create</i18n.Translate> </AsyncButton> </footer>