taler-typescript-core

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

commit 3e9ddf23b26a81ee2cf254ba58aa1430946a81f3
parent 2454609d847cf89d8fd4de622d607cc706de6e16
Author: Sebastian <sebasjm@taler-systems.com>
Date:   Sat,  7 Feb 2026 07:13:20 -0300

better form validation report

Diffstat:
Mpackages/web-util/src/forms/fields/InputDownloadLink.tsx | 78++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mpackages/web-util/src/forms/fields/InputLine.tsx | 2+-
Mpackages/web-util/src/forms/fields/InputToggle.tsx | 2+-
Mpackages/web-util/src/forms/forms-ui.tsx | 14+++++++-------
Mpackages/web-util/src/forms/gana/accept-tos.ts | 5++++-
5 files changed, 53 insertions(+), 48 deletions(-)

diff --git a/packages/web-util/src/forms/fields/InputDownloadLink.tsx b/packages/web-util/src/forms/fields/InputDownloadLink.tsx @@ -34,46 +34,48 @@ export function InputDownloadLink(props: Props & UIFormProps<boolean>): VNode { return ( <div class="col-span-6" data-downloaded={!!value}> {before !== undefined && <RenderAddon addon={before} />} - <a - href="#" - class="underline text-blue-600 hover:text-blue-900 visited:text-purple-600" - onClick={(e) => { - e.preventDefault(); - onChange(true); - return ( - fetch(url, { - headers: { - "Content-Type": media ?? "text/html", - }, - cache: "no-cache", - }) - // .then((r) => r.text()) - .then((r) => r.arrayBuffer()) - .then((r) => { - const b64 = window.btoa( - new Uint8Array(r).reduce( - (data, byte) => data + String.fromCharCode(byte), - "", - ), - ); - - const a = document.createElement("a"); - a.href = `data:${media ?? "text/html"};base64,${b64}`; - a.download = fileName ?? ""; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - return; + <label for={props.name}> + <a + href="#" + class="underline text-blue-600 hover:text-blue-900 visited:text-purple-600" + onClick={(e) => { + e.preventDefault(); + onChange(true); + return ( + fetch(url, { + headers: { + "Content-Type": media ?? "text/html", + }, + cache: "no-cache", }) - ); - }} - media={media} - download - > - {label} - </a> + // .then((r) => r.text()) + .then((r) => r.arrayBuffer()) + .then((r) => { + const b64 = window.btoa( + new Uint8Array(r).reduce( + (data, byte) => data + String.fromCharCode(byte), + "", + ), + ); + + const a = document.createElement("a"); + a.href = `data:${media ?? "text/html"};base64,${b64}`; + a.download = fileName ?? ""; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + return; + }) + ); + }} + media={media} + download + > + {label} + </a> + </label> {required ? ( - <span class="text-sm leading-6 text-red-600 pl-2">*</span> + <span class="text-xl bold leading-6 text-red-600 pl-2">*</span> ) : undefined} {after !== undefined && <RenderAddon addon={after} />} diff --git a/packages/web-util/src/forms/fields/InputLine.tsx b/packages/web-util/src/forms/fields/InputLine.tsx @@ -62,7 +62,7 @@ export function LabelWithTooltipMaybeRequired({ return ( <div class="flex justify-between w-fit"> {WithTooltip} - <span class="text-sm leading-6 text-red-600 pl-2">*</span> + <span class="text-xl bold leading-6 text-red-600 pl-2">*</span> </div> ); } diff --git a/packages/web-util/src/forms/fields/InputToggle.tsx b/packages/web-util/src/forms/fields/InputToggle.tsx @@ -40,7 +40,7 @@ export function InputToggle( } return ( - <div class="sm:col-span-6"> + <div class="col-span-6"> <div class="flex items-center justify-between"> <LabelWithTooltipMaybeRequired label={label} diff --git a/packages/web-util/src/forms/forms-ui.tsx b/packages/web-util/src/forms/forms-ui.tsx @@ -327,9 +327,9 @@ export function ErrorsSummary<T>({ } }} > - <div class="px-4 sm:px-0"> + <div class="px-0"> <h3 class="text-base/7 font-semibold text-gray-900"> - <i18n.Translate>Missing fields</i18n.Translate> + <i18n.Translate>List of fields with errors</i18n.Translate> </h3> </div> @@ -402,16 +402,16 @@ export function ErrorsSummary<T>({ }); el.classList.add("animate-pulse"); - el.classList.add("border-b"); + el.classList.add("border-b-2"); el.classList.add("border-red-700"); setTimeout(() => { el.classList.remove("animate-pulse"); - el.classList.remove("border-b"); + el.classList.remove("border-b-2"); el.classList.remove("border-red-700"); - }, 5000); + }, 6000); } }} - class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0 odd:bg-white even:bg-gray-100 cursor-pointer" + class="py-2 grid grid-cols-2 gap-4 px-0 odd:bg-white even:bg-gray-100 cursor-pointer" > {errHandler.section ? ( <dt class="underline pl-4 text-sm/6 font-medium text-gray-900"> @@ -422,7 +422,7 @@ export function ErrorsSummary<T>({ {errHandler.label} </dt> )} - <dd class="underline flex text-sm/6 text-red-700 sm:col-span-2 sm:mt-0"> + <dd class="underline flex text-sm/6 text-red-700 mt-0"> {errHandler.message} </dd> </span> diff --git a/packages/web-util/src/forms/gana/accept-tos.ts b/packages/web-util/src/forms/gana/accept-tos.ts @@ -81,7 +81,10 @@ export function acceptTos( id: TalerFormAttributes.DOWNLOADED_TERMS_OF_SERVICE, url: context.tos_url, label: i18n.str`Download PDF version`, - required: true, + // required: true, + validator(text, form) { + return !text ? i18n.str`Click to download & read` : undefined; + }, media: "application/pdf", fileName: tosFileName, help: i18n.str`You must download to proceed`,