aboutsummaryrefslogtreecommitdiff
path: root/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx')
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx48
1 files changed, 36 insertions, 12 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
index 9fcfcc4bf..d12d1d2d3 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.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, WithId } 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.TemplatePatchDetails & WithId;
@@ -46,12 +53,8 @@ interface Props {
template: Entity;
}
-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 UpdatePage({ template, onUpdate, onBack }: Props): VNode {
const { i18n } = useTranslationContext();
@@ -60,6 +63,10 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode {
const [showKey, setShowKey] = useState(false);
const [state, setState] = useState<Partial<Entity>>(template);
+ const parsedPrice = !state.template_contract?.amount
+ ? undefined
+ : Amounts.parse(state.template_contract?.amount);
+
const errors: FormErrors<Entity> = {
template_description: !state.template_description
? i18n.str`should not be empty`
@@ -67,6 +74,13 @@ export function UpdatePage({ template, onUpdate, 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`
@@ -78,7 +92,16 @@ export function UpdatePage({ template, onUpdate, 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(
@@ -155,20 +178,21 @@ export function UpdatePage({ template, onUpdate, 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 ? (
<InputWithAddon<Entity>
name="pos_key"
label={i18n.str`Point-of-sale key`}
inputType={showKey ? "text" : "password"}
- help=""
+ help="Be sure to be very hard to guess or use the random generator"
expand
tooltip={i18n.str`Useful to validate the purchase`}
+ fromStr={(v) => v.toUpperCase()}
addonAfter={
<span class="icon">
{showKey ? (
@@ -179,7 +203,7 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode {
</span>
}
side={
- <span>
+ <span style={{ display: "flex" }}>
<button
data-tooltip={i18n.str`generate random secret key`}
class="button is-info mr-3"