summaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/pages
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2022-10-26 16:04:12 -0300
committerSebastian <sebasjm@gmail.com>2022-10-26 16:04:12 -0300
commitaf29a02e5b08c05ffe41fc8eae5775a385d85173 (patch)
treefd712e74111f761205838852f3cd9c409e035b7b /packages/demobank-ui/src/pages
parentb4bad2deaf93eff5858d903cd68b8fdd5a5eecd3 (diff)
downloadwallet-core-af29a02e5b08c05ffe41fc8eae5775a385d85173.tar.gz
wallet-core-af29a02e5b08c05ffe41fc8eae5775a385d85173.tar.bz2
wallet-core-af29a02e5b08c05ffe41fc8eae5775a385d85173.zip
using util to parse uri, some more fixs
Diffstat (limited to 'packages/demobank-ui/src/pages')
-rw-r--r--packages/demobank-ui/src/pages/home/index.tsx120
1 files changed, 93 insertions, 27 deletions
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>] {
+): [RawPaytoInputTypeOpt, StateUpdater<RawPaytoInputTypeOpt>, boolean] {
const ret = useLocalStorage("raw-payto-input-state", state);
+ const [dirty, setDirty] = useState(false);
const retObj: RawPaytoInputTypeOpt = ret[0];
const retSetter: StateUpdater<RawPaytoInputTypeOpt> = 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 {
</Fragment>
);
}
+function ShowInputErrorLabel({
+ isDirty,
+ message,
+}: {
+ message: string | undefined;
+ isDirty: boolean;
+}): VNode {
+ if (message && isDirty)
+ return <p class="informational informational-fail">{message}</p>;
+ return <Fragment />;
+}
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 {
</div>
);
+ const errors = undefinedIfEmpty({
+ rawPaytoInput: !rawPaytoInput
+ ? i18n`Missing payto address`
+ : !parsePaytoUri(rawPaytoInput)
+ ? i18n`Payto does not follow the pattern`
+ : undefined,
+ });
+
return (
<div>
<p>{i18n`Transfer money to account identified by payto:// URI:`}</p>
@@ -1168,17 +1192,21 @@ function PaytoWireTransfer(Props: any): VNode {
<input
name="address"
type="text"
- size={90}
+ size={50}
ref={ref}
id="address"
value={rawPaytoInput}
required
placeholder={i18n`payto address`}
- pattern={`payto://iban/[A-Z][A-Z][0-9]+?message=[a-zA-Z0-9 ]+&amount=${currency}:[0-9]+(.[0-9]+)?`}
+ // pattern={`payto://iban/[A-Z][A-Z][0-9]+?message=[a-zA-Z0-9 ]+&amount=${currency}:[0-9]+(.[0-9]+)?`}
onInput={(e): void => {
rawPaytoInputSetter(e.currentTarget.value);
}}
/>
+ <ShowInputErrorLabel
+ message={errors?.rawPaytoInput}
+ isDirty={rawPaytoInputDirty}
+ />
<br />
<div class="hint">
Hint:
@@ -1192,6 +1220,7 @@ function PaytoWireTransfer(Props: any): VNode {
<input
class="pure-button pure-button-primary"
type="submit"
+ disabled={!!errors}
value={i18n`Send`}
onClick={async () => {
// empty string evaluates to false.
@@ -1593,6 +1622,11 @@ function RegistrationButton(Props: any): VNode {
return <span />;
}
+function undefinedIfEmpty<T extends object>(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 (
<div class="login-div">
<form action="javascript:void(0);" class="login-form">
@@ -1649,6 +1693,7 @@ function LoginForm(Props: any): VNode {
<button
type="submit"
class="pure-button pure-button-primary"
+ disabled={!!errors}
onClick={() => {
if (typeof submitData === "undefined") {
console.log("login data is undefined", submitData);
@@ -1691,7 +1736,19 @@ function RegistrationForm(Props: any): VNode {
const [pageState, pageStateSetter] = useContext(PageContext);
const [submitData, submitDataSetter] = useCredentialsRequestType();
const i18n = useTranslator();
- // https://stackoverflow.com/questions/36683770/how-to-get-the-value-of-an-input-field-using-reactjs
+
+ const errors = !submitData
+ ? undefined
+ : undefinedIfEmpty({
+ username: !submitData.username ? i18n`Missing username` : undefined,
+ password: !submitData.password ? i18n`Missing password` : undefined,
+ repeatPassword: !submitData.repeatPassword
+ ? i18n`Missing password`
+ : submitData.repeatPassword !== submitData.password
+ ? i18n`Password don't match`
+ : undefined,
+ });
+
return (
<Fragment>
<h1 class="nav">{i18n`Welcome to ${UI_BANK_NAME}!`}</h1>
@@ -1735,6 +1792,24 @@ function RegistrationForm(Props: any): VNode {
}));
}}
/>
+ <p class="unameFieldLabel registerFieldLabel formFieldLabel">
+ <label for="register-repeat">{i18n`Repeat Password:`}</label>
+ </p>
+ <input
+ type="password"
+ style={{ marginBottom: 8 }}
+ name="register-repeat"
+ id="register-repeat"
+ placeholder="Same password"
+ value={submitData && submitData.repeatPassword}
+ required
+ onInput={(e): void => {
+ submitDataSetter((submitData: any) => ({
+ ...submitData,
+ repeatPassword: e.currentTarget.value,
+ }));
+ }}
+ />
<br />
{/*
<label for="phone">{i18n`Phone number:`}</label>
@@ -1755,28 +1830,10 @@ function RegistrationForm(Props: any): VNode {
*/}
<button
class="pure-button pure-button-primary btn-register"
+ disabled={!!errors}
onClick={() => {
console.log("maybe submitting the registration..");
- console.log(submitData);
- if (typeof submitData === "undefined") {
- console.log(`submit data ${submitData} is undefined`);
- return;
- }
- if (
- typeof submitData.password === "undefined" ||
- typeof submitData.username === "undefined"
- ) {
- console.log("username or password is undefined");
- return;
- }
- if (
- submitData.password.length === 0 ||
- submitData.username.length === 0
- ) {
- console.log("username or password are the empty string");
- return;
- }
- console.log("submitting the registration..");
+ if (!submitData) return;
registrationCall(
{ ...submitData },
Props.backendStateSetter, // will store BE URL, if OK.
@@ -1790,7 +1847,11 @@ function RegistrationForm(Props: any): VNode {
* strings due to a non lively update of the <input> fields
* after setting to undefined.
*/
- submitDataSetter({ username: "", password: "" });
+ submitDataSetter({
+ username: "",
+ password: "",
+ repeatPassword: "",
+ });
}}
>
{i18n`Register`}
@@ -1799,6 +1860,11 @@ function RegistrationForm(Props: any): VNode {
<button
class="pure-button pure-button-secondary btn-cancel"
onClick={() => {
+ submitDataSetter({
+ username: "",
+ password: "",
+ repeatPassword: "",
+ });
pageStateSetter((prevState: PageStateType) => ({
...prevState,
tryRegister: false,