commit f51fd65ad2d0227ac84b1b5e28c774f79f9d7188
parent 843d70ed8cf4921decfd0339a4420daba33d0ab4
Author: Sebastian <sebasjm@gmail.com>
Date: Wed, 16 Apr 2025 11:58:01 -0300
adding validation of account before jump into details
Diffstat:
1 file changed, 69 insertions(+), 30 deletions(-)
diff --git a/packages/aml-backoffice-ui/src/pages/Cases.tsx b/packages/aml-backoffice-ui/src/pages/Cases.tsx
@@ -23,15 +23,17 @@ import {
InputToggle,
Loading,
RouteDefinition,
+ useExchangeApiContext,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useCurrentDecisions } from "../hooks/decisions.js";
-import { useState } from "preact/hooks";
+import { useState, useEffect } from "preact/hooks";
import { privatePages } from "../Routing.js";
import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js";
import { Officer } from "./Officer.js";
+import { useOfficer } from "../hooks/officer.js";
type FormType = {
// state: TalerExchangeApi.AmlState;
@@ -338,6 +340,8 @@ export function Pagination({
);
}
+let latestTimeout: undefined | ReturnType<typeof setTimeout> = undefined;
+
function JumpByIdForm({
caseByIdRoute,
fitered,
@@ -349,38 +353,73 @@ function JumpByIdForm({
}): VNode {
const { i18n } = useTranslationContext();
const [account, setAccount] = useState<string>("");
+ const officer = useOfficer();
+ const session = officer.state === "ready" ? officer.account : undefined;
+ const { lib } = useExchangeApiContext();
+ const [valid, setValid] = useState(false);
+ const [error, setError] = useState<string>();
+ useEffect(() => {
+ if (!session || !account) return;
+ const activeSession = session;
+ if (latestTimeout) {
+ clearTimeout(latestTimeout);
+ }
+ setError(undefined)
+ setValid(false)
+ latestTimeout = setTimeout(async function checkAccouunt() {
+ let found = false
+ try {
+ const result = await lib.exchange.getAmlAttributesForAccount(
+ activeSession,
+ account,
+ { limit: 1 },
+ );
+ found = (result.type === "ok");
+ } catch (e) {
+ console.log(e)
+ }
+ setValid(found)
+ if (!found) {
+ setError(i18n.str`account not found`);
+ }
+ }, 500);
+ }, [account, session]);
return (
<form class="mt-5 grid grid-cols-1">
- <div class="flex flex-row">
- <div class="w-full sm:max-w-xs">
- <input
- name="account"
- onChange={(e) => {
- setAccount(e.currentTarget.value);
- }}
- class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6"
- placeholder={i18n.str`Search by ID`}
- />
- </div>
- <a
- href={caseByIdRoute.url({ cid: account })}
- class="mt-3 inline-flex w-full items-center justify-center 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 sm:ml-3 sm:mt-0 sm:w-auto"
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- fill="none"
- viewBox="0 0 24 24"
- stroke-width="1.5"
- stroke="currentColor"
- class="size-6 w-6 h-6"
- >
- <path
- stroke-linecap="round"
- stroke-linejoin="round"
- d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"
+ <div>
+ <div class="flex flex-row">
+ <div class="w-full sm:max-w-xs">
+ <input
+ name="account"
+ onChange={(e) => {
+ setAccount(e.currentTarget.value);
+ }}
+ class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6"
+ placeholder={i18n.str`Search by ID`}
/>
- </svg>
- </a>
+ </div>
+ <a
+ href={!valid ? undefined : caseByIdRoute.url({ cid: account })}
+ data-disabled={!valid}
+ class="data-[disabled=true]:bg-gray-400 mt-3 inline-flex w-full items-center justify-center 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 sm:ml-3 sm:mt-0 sm:w-auto"
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ fill="none"
+ viewBox="0 0 24 24"
+ stroke-width="1.5"
+ stroke="currentColor"
+ class="size-6 w-6 h-6"
+ >
+ <path
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"
+ />
+ </svg>
+ </a>
+ </div>
+ {!error ? undefined : <p class="mt-2 text-sm text-red-600">{error}</p>}
</div>
<div class="mt-2 cursor-default">
<InputToggle