diff options
author | Sebastian <sebasjm@gmail.com> | 2023-03-13 11:12:46 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2023-03-13 11:27:52 -0300 |
commit | 96d110379e9bfbffedfeebf44c1c972b12fffff4 (patch) | |
tree | e7065608cd1561d000f9d2eef79a4ff3e4611e16 /packages/merchant-backoffice-ui/src/paths/instance/templates/create | |
parent | 5f681813cf1bb7bb5c0baa41f29011d0029d003d (diff) | |
download | wallet-core-96d110379e9bfbffedfeebf44c1c972b12fffff4.tar.xz |
some fixes and validations
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/templates/create')
-rw-r--r-- | packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx | 78 |
1 files changed, 65 insertions, 13 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx index 144e968c5..f6aa9a9ae 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx @@ -19,6 +19,10 @@ * @author Sebastian Javier Marchano (sebasjm) */ +import { + Amounts, + MerchantTemplateContractDetails, +} from "@gnu-taler/taler-util"; import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { h, VNode } from "preact"; import { useState } from "preact/hooks"; @@ -35,7 +39,10 @@ import { InputSelector } from "../../../../components/form/InputSelector.js"; import { InputWithAddon } from "../../../../components/form/InputWithAddon.js"; import { useBackendContext } from "../../../../context/backend.js"; import { MerchantBackend } from "../../../../declaration.js"; -import { randomBase32Key } from "../../../../utils/crypto.js"; +import { + isBase32RFC3548Charset, + randomBase32Key, +} from "../../../../utils/crypto.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; type Entity = MerchantBackend.Template.TemplateAddDetails; @@ -45,17 +52,14 @@ interface Props { onBack?: () => void; } -const algorithms = ["0", "1", "2"]; -const algorithmsNames = [ - "off", - "30s 8d TOTP-SHA1 without amount", - "30s 8d eTOTP-SHA1 with amount", -]; +const algorithms = [0, 1, 2]; +const algorithmsNames = ["off", "30s 8d TOTP-SHA1", "30s 8d eTOTP-SHA1"]; export function CreatePage({ onCreate, onBack }: Props): VNode { const { i18n } = useTranslationContext(); const backend = useBackendContext(); + const [showKey, setShowKey] = useState(false); const [state, setState] = useState<Partial<Entity>>({ template_contract: { minimum_age: 0, @@ -65,6 +69,10 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { }, }); + const parsedPrice = !state.template_contract?.amount + ? undefined + : Amounts.parse(state.template_contract?.amount); + const errors: FormErrors<Entity> = { template_id: !state.template_id ? i18n.str`should not be empty` : undefined, template_description: !state.template_description @@ -73,6 +81,13 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { template_contract: !state.template_contract ? undefined : undefinedIfEmpty({ + amount: !state.template_contract?.amount + ? undefined + : !parsedPrice + ? i18n.str`not valid` + : Amounts.isZero(parsedPrice) + ? i18n.str`must be greater than 0` + : undefined, minimum_age: state.template_contract.minimum_age < 0 ? i18n.str`should be greater that 0` @@ -84,7 +99,16 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { : state.template_contract.pay_duration.d_us < 1000 * 1000 //less than one second ? i18n.str`to short` : undefined, - }), + } as Partial<MerchantTemplateContractDetails>), + pos_key: !state.pos_key + ? !state.pos_algorithm + ? undefined + : i18n.str`required` + : !isBase32RFC3548Charset(state.pos_key) + ? i18n.str`just letters and numbers from 2 to 7` + : state.pos_key.length !== 32 + ? i18n.str`size of the key should be 32` + : undefined, }; const hasErrors = Object.keys(errors).some( @@ -144,21 +168,32 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { /> <InputSelector<Entity> name="pos_algorithm" - label={i18n.str`Veritifaction algorithm`} + label={i18n.str`Verification algorithm`} tooltip={i18n.str`Algorithm to use to verify transaction in offline mode`} values={algorithms} toStr={(v) => algorithmsNames[v]} - convert={(v) => Number(v)} + fromStr={(v) => Number(v)} /> {state.pos_algorithm && state.pos_algorithm > 0 ? ( - <Input<Entity> + <InputWithAddon<Entity> name="pos_key" label={i18n.str`Point-of-sale key`} - help="" + help="Be sure to be very hard to guess or use the random generator" tooltip={i18n.str`Useful to validate the purchase`} + fromStr={(v) => v.toUpperCase()} + addonAfter={ + <span class="icon"> + {showKey ? ( + <i class="mdi mdi-eye" /> + ) : ( + <i class="mdi mdi-eye-off" /> + )} + </span> + } side={ - <span data-tooltip={i18n.str`generate random secret key`}> + <span style={{ display: "flex" }}> <button + data-tooltip={i18n.str`generate random secret key`} class="button is-info mr-3" onClick={(e) => { const pos_key = randomBase32Key(); @@ -167,6 +202,23 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { > <i18n.Translate>random</i18n.Translate> </button> + <button + data-tooltip={ + showKey + ? i18n.str`show secret key` + : i18n.str`hide secret key` + } + class="button is-info mr-3" + onClick={(e) => { + setShowKey(!showKey); + }} + > + {showKey ? ( + <i18n.Translate>hide</i18n.Translate> + ) : ( + <i18n.Translate>show</i18n.Translate> + )} + </button> </span> } /> |