commit caad862adc5369300692e7aab2975d49bea6dcbf
parent c86291631071bf01c5da9162fad14c37bb391cca
Author: Sebastian <sebasjm@gmail.com>
Date: Thu, 1 May 2025 15:35:32 -0300
fix #9676
Diffstat:
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();