taler-typescript-core

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

commit caad862adc5369300692e7aab2975d49bea6dcbf
parent c86291631071bf01c5da9162fad14c37bb391cca
Author: Sebastian <sebasjm@gmail.com>
Date:   Thu,  1 May 2025 15:35:32 -0300

fix #9676

Diffstat:
Mpackages/aml-backoffice-ui/src/pages/decision/Properties.tsx | 2+-
Mpackages/aml-backoffice-ui/src/pages/decision/Summary.tsx | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mpackages/kyc-ui/src/Routing.tsx | 3---
Mpackages/kyc-ui/src/hooks/session.ts | 1+
Mpackages/kyc-ui/src/pages/Start.tsx | 6+-----
5 files changed, 77 insertions(+), 11 deletions(-)

diff --git a/packages/aml-backoffice-ui/src/pages/decision/Properties.tsx b/packages/aml-backoffice-ui/src/pages/decision/Properties.tsx @@ -179,7 +179,7 @@ function propertiesByDialect( return [ { id: TalerAmlProperties.FILE_NOTE, - label: i18n.str`Current note on the GQG File`, + label: i18n.str`Current note on the GWG File`, type: "text", }, { diff --git a/packages/aml-backoffice-ui/src/pages/decision/Summary.tsx b/packages/aml-backoffice-ui/src/pages/decision/Summary.tsx @@ -1,12 +1,17 @@ import { AbsoluteTime, + AML_EVENTS_INFO, AmlDecisionRequest, assertUnreachable, HttpStatusCode, + opEmptySuccess, + opFixedSuccess, parsePaytoUri, PaytoString, stringifyPaytoUri, + succeedOrThrow, TalerError, + TOPS_AmlEventsName, } from "@gnu-taler/taler-util"; import { Attention, @@ -22,7 +27,10 @@ import { useCurrentDecisionRequest, } from "../../hooks/decision-request.js"; import { useOfficer } from "../../hooks/officer.js"; -import { useServerMeasures } from "../../hooks/server-info.js"; +import { + useServerMeasures, + useServerStatistics, +} from "../../hooks/server-info.js"; import { computeAvailableMesaures, ShowDecisionLimitInfo, @@ -38,6 +46,7 @@ import { isRulesCompleted, WizardSteps, } from "./AmlDecisionRequestWizard.js"; +import { useState } from "preact/hooks"; /** * Mark for further investigation and explain decision @@ -63,7 +72,6 @@ export function Summary({ !measures || measures instanceof TalerError || measures.type === "fail" ? undefined : measures.body, - // custom, ); const d = decision.new_measures === undefined ? [] : decision.new_measures; @@ -85,6 +93,15 @@ export function Summary({ : !isJustificationCompleted(decision); const INVALID_ATTRIBUTES = !isAttributesCompleted(decision); + const MROS_REPORT_COMPLETED = !decision.triggering_events + ? false + : decision.triggering_events.includes( + TOPS_AmlEventsName.ACCOUNT_MROS_REPORTED_SUSPICION_SIMPLE, + ) || + decision.triggering_events.includes( + TOPS_AmlEventsName.ACCOUNT_MROS_REPORTED_SUSPICION_SUBSTANTIATED, + ); + const CANT_SUBMIT = INVALID_ACCOUNT || INVALID_RULES || @@ -158,6 +175,61 @@ export function Summary({ }, ); + const requiresConfirmation = MROS_REPORT_COMPLETED; + if (submitHandler && requiresConfirmation) { + const originalHandler = submitHandler.onClick; + submitHandler.onClick = async function d(): ReturnType< + typeof submitHandler.onClick + > { + if (!submitConfirmation) { + setSubmitConfirmation(true); + return opFixedSuccess(undefined); + } + return originalHandler(); + }; + } + + const [submitConfirmation, setSubmitConfirmation] = useState<boolean>(true); + + if (submitConfirmation) { + return ( + <div class="flex"> + <div + class="overflow-hidden rounded-lg bg-white shadow-lg" + style={{ width: 600, marign: "auto" }} + > + <div class="px-4 py-5 sm:p-6"> + <Attention type="warning" title={i18n.str`Confirmation required`}> + <i18n.Translate> + This decision declares that the MROS report have concluded. + Please make that this is the case + </i18n.Translate> + </Attention> + + <div class="mt-2 flex justify-between"> + <button + onClick={() => { + setSubmitConfirmation(false); + }} + class="mt-4 disabled:opacity-50 disabled:cursor-default rounded-md px-3 py-2 text-sm font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 " + > + <i18n.Translate>I want to check first!</i18n.Translate> + </button> + <Button + type="submit" + handler={submitHandler} + disabled={!submitHandler} + class="mt-4 disabled:opacity-50 disabled:cursor-default rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold 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" + > + <i18n.Translate>Confirm decision</i18n.Translate> + </Button> + </div> + </div> + </div> + </div> + ); + } + return ( <Fragment> <LocalNotificationBanner notification={notification} /> diff --git a/packages/kyc-ui/src/Routing.tsx b/packages/kyc-ui/src/Routing.tsx @@ -89,9 +89,6 @@ function PublicRounting(): VNode { return ( <Start token={currentToken} - onLoggedOut={() => { - navigateTo(publicPages.completed.url({})); - }} /> ); } diff --git a/packages/kyc-ui/src/hooks/session.ts b/packages/kyc-ui/src/hooks/session.ts @@ -55,6 +55,7 @@ export interface SessionStateHandler { start(s: AccessToken): void; } +// FIXME: adde expiration 1 week const SESSION_STATE_KEY = buildStorageKey( "kyc-session", codecForSessionState(), diff --git a/packages/kyc-ui/src/pages/Start.tsx b/packages/kyc-ui/src/pages/Start.tsx @@ -37,7 +37,6 @@ import { FillForm } from "./FillForm.js"; const TALER_SCREEN_ID = 104; type Props = { - onLoggedOut: () => void; token: AccessToken; }; @@ -59,9 +58,6 @@ export function ShowReqList({ result.body.requirements.length > 0 ? result.body.requirements[0] : undefined; - // useEffect(() => { - // if (firstAccount) onFormSelected(firstAccount); - // }, [firstAccount]); if (!result) { return <Loading />; @@ -211,7 +207,7 @@ export function ShowReqList({ </Fragment> ); } -export function Start({ token, onLoggedOut }: Props): VNode { +export function Start({ token }: Props): VNode { const [req, setReq] = useState<KycRequirementInformation>(); const { lib } = useExchangeApiContext(); const [notification, withErrorHandler] = useLocalNotificationHandler();