From af29a02e5b08c05ffe41fc8eae5775a385d85173 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 26 Oct 2022 16:04:12 -0300 Subject: using util to parse uri, some more fixs --- packages/demobank-ui/package.json | 1 + packages/demobank-ui/src/pages/home/index.tsx | 120 ++++++++++++++++++++------ packages/demobank-ui/src/scss/bank.scss | 5 +- 3 files changed, 98 insertions(+), 28 deletions(-) (limited to 'packages') diff --git a/packages/demobank-ui/package.json b/packages/demobank-ui/package.json index 0f0c6f8e1..a8f390611 100644 --- a/packages/demobank-ui/package.json +++ b/packages/demobank-ui/package.json @@ -14,6 +14,7 @@ "jed": "1.1.1", "preact": "10.6.5", "preact-router": "3.2.1", + "@gnu-taler/taler-util": "workspace:*", "qrcode-generator": "^1.4.4", "react": "npm:@preact/compat@^17.1.2", "swr": "1.3.0" diff --git a/packages/demobank-ui/src/pages/home/index.tsx b/packages/demobank-ui/src/pages/home/index.tsx index 6fbb00ce4..8ab815efd 100644 --- a/packages/demobank-ui/src/pages/home/index.tsx +++ b/packages/demobank-ui/src/pages/home/index.tsx @@ -31,6 +31,7 @@ import { QR } from "../../components/QR.js"; import { useLocalStorage, useNotNullLocalStorage } from "../../hooks/index.js"; import { Translate, useTranslator } from "../../i18n/index.js"; import "../../scss/main.scss"; +import { parsePaytoUri } from "@gnu-taler/taler-util"; /** * If the first argument does not look like a placeholder, return it. @@ -113,6 +114,7 @@ interface TransactionRequestType { interface CredentialsRequestType { username: string; password: string; + repeatPassword: string; } /** @@ -336,14 +338,16 @@ type RawPaytoInputType = string; type RawPaytoInputTypeOpt = RawPaytoInputType | undefined; function useRawPaytoInputType( state?: RawPaytoInputType, -): [RawPaytoInputTypeOpt, StateUpdater] { +): [RawPaytoInputTypeOpt, StateUpdater, boolean] { const ret = useLocalStorage("raw-payto-input-state", state); + const [dirty, setDirty] = useState(false); const retObj: RawPaytoInputTypeOpt = ret[0]; const retSetter: StateUpdater = function (val) { const newVal = val instanceof Function ? val(retObj) : val; + setDirty(true); ret[1](newVal); }; - return [retObj, retSetter]; + return [retObj, retSetter, dirty]; } /** @@ -1012,12 +1016,24 @@ function BankFrame(Props: any): VNode { ); } +function ShowInputErrorLabel({ + isDirty, + message, +}: { + message: string | undefined; + isDirty: boolean; +}): VNode { + if (message && isDirty) + return

{message}

; + return ; +} function PaytoWireTransfer(Props: any): VNode { const currency = useContext(CurrencyContext); const [pageState, pageStateSetter] = useContext(PageContext); // NOTE: used for go-back button? const [submitData, submitDataSetter] = useWireTransferRequestType(); - const [rawPaytoInput, rawPaytoInputSetter] = useRawPaytoInputType(); + const [rawPaytoInput, rawPaytoInputSetter, rawPaytoInputDirty] = + useRawPaytoInputType(); const i18n = useTranslator(); const { focus, backendState } = Props; const amountRegex = "^[0-9]+(.[0-9]+)?$"; @@ -1159,6 +1175,14 @@ function PaytoWireTransfer(Props: any): VNode { ); + const errors = undefinedIfEmpty({ + rawPaytoInput: !rawPaytoInput + ? i18n`Missing payto address` + : !parsePaytoUri(rawPaytoInput) + ? i18n`Payto does not follow the pattern` + : undefined, + }); + return (

{i18n`Transfer money to account identified by payto:// URI:`}

@@ -1168,17 +1192,21 @@ function PaytoWireTransfer(Props: any): VNode { { rawPaytoInputSetter(e.currentTarget.value); }} /> +
Hint: @@ -1192,6 +1220,7 @@ function PaytoWireTransfer(Props: any): VNode { { // empty string evaluates to false. @@ -1593,6 +1622,11 @@ function RegistrationButton(Props: any): VNode { return ; } +function undefinedIfEmpty(obj: T): T | undefined { + return Object.keys(obj).some((k) => (obj as any)[k] !== undefined) + ? obj + : undefined; +} /** * Collect and submit login data. */ @@ -1604,6 +1638,16 @@ function LoginForm(Props: any): VNode { useEffect(() => { ref.current?.focus(); }, []); + + const errors = undefinedIfEmpty({ + username: !(submitData && submitData.username) + ? i18n`Missing username` + : undefined, + password: !(submitData && submitData.password) + ? i18n`Missing password` + : undefined, + }); + return (