diff options
Diffstat (limited to 'packages/auditor-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx')
-rw-r--r-- | packages/auditor-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx b/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx new file mode 100644 index 000000000..6e4786a47 --- /dev/null +++ b/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx @@ -0,0 +1,173 @@ +/* + This file is part of GNU Taler + (C) 2021-2023 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** + * + * @author Sebastian Javier Marchano (sebasjm) + */ + +import { useTranslationContext } from "@gnu-taler/web-util/browser"; +import { Fragment, h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { AsyncButton } from "../../../../components/exception/AsyncButton.js"; +import { + FormErrors, + FormProvider, +} from "../../../../components/form/FormProvider.js"; +import { Input } from "../../../../components/form/Input.js"; +import { InputPaytoForm } from "../../../../components/form/InputPaytoForm.js"; +import { InputSelector } from "../../../../components/form/InputSelector.js"; +import { MerchantBackend } from "../../../../declaration.js"; +import { undefinedIfEmpty } from "../../../../utils/table.js"; + +type Entity = MerchantBackend.BankAccounts.AccountAddDetails & { repeatPassword: string }; + +interface Props { + onCreate: (d: Entity) => Promise<void>; + onBack?: () => void; +} + +const accountAuthType = ["none", "basic"]; + +function isValidURL(s: string): boolean { + try { + const u = new URL(s) + return true; + } catch (e) { + return false; + } +} + +export function CreatePage({ onCreate, onBack }: Props): VNode { + const { i18n } = useTranslationContext(); + + const [state, setState] = useState<Partial<Entity>>({}); + const errors: FormErrors<Entity> = { + payto_uri: !state.payto_uri ? i18n.str`required` : undefined, + + credit_facade_credentials: !state.credit_facade_credentials + ? undefined + : undefinedIfEmpty({ + username: + state.credit_facade_credentials.type === "basic" && !state.credit_facade_credentials.username + ? i18n.str`required` + : undefined, + password: + state.credit_facade_credentials.type === "basic" && !state.credit_facade_credentials.password + ? i18n.str`required` + : undefined, + }), + credit_facade_url: !state.credit_facade_url + ? undefined + : !isValidURL(state.credit_facade_url) ? i18n.str`not valid url` + : undefined, + repeatPassword: + !state.credit_facade_credentials + ? undefined + : state.credit_facade_credentials.type === "basic" && (!state.credit_facade_credentials.password || state.credit_facade_credentials.password !== state.repeatPassword) + ? i18n.str`is not the same` + : undefined, + }; + + const hasErrors = Object.keys(errors).some( + (k) => (errors as any)[k] !== undefined, + ); + + const submitForm = () => { + if (hasErrors) return Promise.reject(); + delete state.repeatPassword + return onCreate(state as any); + }; + + return ( + <div> + <section class="section is-main-section"> + <div class="columns"> + <div class="column" /> + <div class="column is-four-fifths"> + <FormProvider + object={state} + valueHandler={setState} + errors={errors} + > + <InputPaytoForm<Entity> + name="payto_uri" + label={i18n.str`Account`} + /> + <Input<Entity> + name="credit_facade_url" + label={i18n.str`Account info URL`} + help="https://bank.com" + expand + tooltip={i18n.str`From where the merchant can download information about incoming wire transfers to this account`} + /> + <InputSelector + name="credit_facade_credentials.type" + label={i18n.str`Auth type`} + tooltip={i18n.str`Choose the authentication type for the account info URL`} + values={accountAuthType} + toStr={(str) => { + if (str === "none") return "Without authentication"; + return "Username and password"; + }} + /> + {state.credit_facade_credentials?.type === "basic" ? ( + <Fragment> + <Input + name="credit_facade_credentials.username" + label={i18n.str`Username`} + tooltip={i18n.str`Username to access the account information.`} + /> + <Input + name="credit_facade_credentials.password" + inputType="password" + label={i18n.str`Password`} + tooltip={i18n.str`Password to access the account information.`} + /> + <Input + name="repeatPassword" + inputType="password" + label={i18n.str`Repeat password`} + /> + </Fragment> + ) : undefined} + </FormProvider> + + <div class="buttons is-right mt-5"> + {onBack && ( + <button class="button" onClick={onBack}> + <i18n.Translate>Cancel</i18n.Translate> + </button> + )} + <AsyncButton + disabled={hasErrors} + data-tooltip={ + hasErrors + ? i18n.str`Need to complete marked fields` + : "confirm operation" + } + onClick={submitForm} + > + <i18n.Translate>Confirm</i18n.Translate> + </AsyncButton> + </div> + </div> + <div class="column" /> + </div> + </section> + </div> + ); +} |