summaryrefslogtreecommitdiff
path: root/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx')
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx218
1 files changed, 118 insertions, 100 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 d27f6a022..b07582252 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
@@ -23,11 +23,12 @@ import {
AmountString,
Amounts,
Duration,
- MerchantTemplateContractDetails,
assertUnreachable,
} from "@gnu-taler/taler-util";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { Fragment, VNode, h } from "preact";
+import {
+ useTranslationContext
+} from "@gnu-taler/web-util/browser";
+import { VNode, h } from "preact";
import { useState } from "preact/hooks";
import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
import {
@@ -39,12 +40,11 @@ import { InputCurrency } from "../../../../components/form/InputCurrency.js";
import { InputDuration } from "../../../../components/form/InputDuration.js";
import { InputNumber } from "../../../../components/form/InputNumber.js";
import { InputSearchOnList } from "../../../../components/form/InputSearchOnList.js";
+import { InputTab } from "../../../../components/form/InputTab.js";
import { InputWithAddon } from "../../../../components/form/InputWithAddon.js";
-import { useBackendContext } from "../../../../context/backend.js";
+import { useSessionContext } from "../../../../context/session.js";
import { MerchantBackend } from "../../../../declaration.js";
import { useInstanceOtpDevices } from "../../../../hooks/otp.js";
-import { undefinedIfEmpty } from "../../../../utils/table.js";
-import { InputTab } from "../../../../components/form/InputTab.js";
enum Steps {
BOTH_FIXED,
@@ -55,14 +55,14 @@ enum Steps {
// type Entity = MerchantBackend.Template.TemplateAddDetails & { type: Steps };
type Entity = {
- id?: string,
- description?: string,
- otpId?: string,
- summary?: string,
- amount?: AmountString,
- minimum_age?: number,
- pay_duration?: Duration,
- type: Steps,
+ id?: string;
+ description?: string;
+ otpId?: string;
+ summary?: string;
+ amount?: AmountString;
+ minimum_age?: number;
+ pay_duration?: Duration;
+ type: Steps;
};
interface Props {
@@ -72,8 +72,10 @@ interface Props {
export function CreatePage({ onCreate, onBack }: Props): VNode {
const { i18n } = useTranslationContext();
- const { url: backendURL } = useBackendContext()
- const devices = useInstanceOtpDevices()
+ const {
+ state: { backendUrl },
+ } = useSessionContext();
+ const devices = useInstanceOtpDevices();
const [state, setState] = useState<Partial<Entity>>({
minimum_age: 0,
@@ -83,9 +85,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
type: Steps.NON_FIXED,
});
- const parsedPrice = !state.amount
- ? undefined
- : Amounts.parse(state.amount);
+ const parsedPrice = !state.amount ? undefined : Amounts.parse(state.amount);
const errors: FormErrors<Entity> = {
id: !state.id
@@ -93,10 +93,10 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
: !/[a-zA-Z0-9]*/.test(state.id)
? i18n.str`no valid. only characters and numbers`
: undefined,
- description: !state.description
- ? i18n.str`should not be empty`
- : undefined,
- amount: !(state.type === Steps.FIXED_PRICE || state.type === Steps.BOTH_FIXED)
+ description: !state.description ? i18n.str`should not be empty` : undefined,
+ amount: !(
+ state.type === Steps.FIXED_PRICE || state.type === Steps.BOTH_FIXED
+ )
? undefined
: !state.amount
? i18n.str`required`
@@ -105,7 +105,9 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
: Amounts.isZero(parsedPrice)
? i18n.str`must be greater than 0`
: undefined,
- summary: !(state.type === Steps.FIXED_SUMMARY || state.type === Steps.BOTH_FIXED)
+ summary: !(
+ state.type === Steps.FIXED_SUMMARY || state.type === Steps.BOTH_FIXED
+ )
? undefined
: !state.summary
? i18n.str`required`
@@ -130,55 +132,60 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
const submitForm = () => {
if (hasErrors || state.type === undefined) return Promise.reject();
switch (state.type) {
- case Steps.FIXED_PRICE: return onCreate({
- template_id: state.id!,
- template_description: state.description!,
- template_contract: {
- minimum_age: state.minimum_age!,
- pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!),
- amount: state.amount!,
- // summary: state.summary,
- },
- otp_id: state.otpId!
- })
- case Steps.FIXED_SUMMARY: return onCreate({
- template_id: state.id!,
- template_description: state.description!,
- template_contract: {
- minimum_age: state.minimum_age!,
- pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!),
- // amount: state.amount!,
- summary: state.summary,
- },
- otp_id: state.otpId!,
- })
- case Steps.NON_FIXED: return onCreate({
- template_id: state.id!,
- template_description: state.description!,
- template_contract: {
- minimum_age: state.minimum_age!,
- pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!),
- // amount: state.amount!,
- // summary: state.summary,
- },
- otp_id: state.otpId!,
- })
- case Steps.BOTH_FIXED: return onCreate({
- template_id: state.id!,
- template_description: state.description!,
- template_contract: {
- minimum_age: state.minimum_age!,
- pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!),
- amount: state.amount!,
- summary: state.summary,
- },
- otp_id: state.otpId!,
- })
- default: assertUnreachable(state.type)
+ case Steps.FIXED_PRICE:
+ return onCreate({
+ template_id: state.id!,
+ template_description: state.description!,
+ template_contract: {
+ minimum_age: state.minimum_age!,
+ pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!),
+ amount: state.amount!,
+ // summary: state.summary,
+ },
+ otp_id: state.otpId!,
+ });
+ case Steps.FIXED_SUMMARY:
+ return onCreate({
+ template_id: state.id!,
+ template_description: state.description!,
+ template_contract: {
+ minimum_age: state.minimum_age!,
+ pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!),
+ // amount: state.amount!,
+ summary: state.summary,
+ },
+ otp_id: state.otpId!,
+ });
+ case Steps.NON_FIXED:
+ return onCreate({
+ template_id: state.id!,
+ template_description: state.description!,
+ template_contract: {
+ minimum_age: state.minimum_age!,
+ pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!),
+ // amount: state.amount!,
+ // summary: state.summary,
+ },
+ otp_id: state.otpId!,
+ });
+ case Steps.BOTH_FIXED:
+ return onCreate({
+ template_id: state.id!,
+ template_description: state.description!,
+ template_contract: {
+ minimum_age: state.minimum_age!,
+ pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!),
+ amount: state.amount!,
+ summary: state.summary,
+ },
+ otp_id: state.otpId!,
+ });
+ default:
+ assertUnreachable(state.type);
// return onCreate(state);
- };
- }
- const deviceList = !devices.ok ? [] : devices.data.otp_devices
+ }
+ };
+ const deviceList = !devices.ok ? [] : devices.data.otp_devices;
return (
<div>
@@ -193,7 +200,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
>
<InputWithAddon<Entity>
name="id"
- help={`${backendURL}/templates/${state.id ?? ""}`}
+ help={new URL(`templates/${state.id ?? ""}`, backendUrl).href}
label={i18n.str`Identifier`}
tooltip={i18n.str`Name of the template in URLs.`}
/>
@@ -207,12 +214,16 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
name="type"
label={i18n.str`Type`}
help={(() => {
- if (state.type === undefined) return ""
+ if (state.type === undefined) return "";
switch (state.type) {
- case Steps.NON_FIXED: return i18n.str`User will be able to input price and summary before payment.`
- case Steps.FIXED_PRICE: return i18n.str`User will be able to add a summary before payment.`
- case Steps.FIXED_SUMMARY: return i18n.str`User will be able to set the price before payment.`
- case Steps.BOTH_FIXED: return i18n.str`User will not be able to change the price or the summary.`
+ case Steps.NON_FIXED:
+ return i18n.str`User will be able to input price and summary before payment.`;
+ case Steps.FIXED_PRICE:
+ return i18n.str`User will be able to add a summary before payment.`;
+ case Steps.FIXED_SUMMARY:
+ return i18n.str`User will be able to set the price before payment.`;
+ case Steps.BOTH_FIXED:
+ return i18n.str`User will not be able to change the price or the summary.`;
}
})()}
tooltip={i18n.str`Define what the user be allowed to modify`}
@@ -224,28 +235,34 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
]}
toStr={(v: Steps): string => {
switch (v) {
- case Steps.NON_FIXED: return i18n.str`Simple`
- case Steps.FIXED_PRICE: return i18n.str`With price`
- case Steps.FIXED_SUMMARY: return i18n.str`With summary`
- case Steps.BOTH_FIXED: return i18n.str`With price and summary`
+ case Steps.NON_FIXED:
+ return i18n.str`Simple`;
+ case Steps.FIXED_PRICE:
+ return i18n.str`With price`;
+ case Steps.FIXED_SUMMARY:
+ return i18n.str`With summary`;
+ case Steps.BOTH_FIXED:
+ return i18n.str`With price and summary`;
}
}}
/>
- {state.type === Steps.BOTH_FIXED || state.type === Steps.FIXED_SUMMARY ?
+ {state.type === Steps.BOTH_FIXED ||
+ state.type === Steps.FIXED_SUMMARY ? (
<Input<Entity>
name="summary"
inputType="multiline"
label={i18n.str`Fixed summary`}
tooltip={i18n.str`If specified, this template will create order with the same summary`}
/>
- : undefined}
- {state.type === Steps.BOTH_FIXED || state.type === Steps.FIXED_PRICE ?
+ ) : undefined}
+ {state.type === Steps.BOTH_FIXED ||
+ state.type === Steps.FIXED_PRICE ? (
<InputCurrency<Entity>
name="amount"
label={i18n.str`Fixed price`}
tooltip={i18n.str`If specified, this template will create order with the same price`}
/>
- : undefined}
+ ) : undefined}
<InputNumber<Entity>
name="minimum_age"
label={i18n.str`Minimum age`}
@@ -262,28 +279,29 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
name="otpId"
label={i18n.str`OTP device`}
readonly
- side={<button
- class="button is-danger"
- data-tooltip={i18n.str`without otp device`}
- onClick={(): void => {
- setState((v) => ({ ...v, otpId: undefined }));
- }}
- >
- <span>
- <i18n.Translate>remove</i18n.Translate>
- </span>
- </button>}
+ side={
+ <button
+ class="button is-danger"
+ data-tooltip={i18n.str`without otp device`}
+ onClick={(): void => {
+ setState((v) => ({ ...v, otpId: undefined }));
+ }}
+ >
+ <span>
+ <i18n.Translate>remove</i18n.Translate>
+ </span>
+ </button>
+ }
tooltip={i18n.str`Use to verify transaction in offline mode.`}
/>
<InputSearchOnList
label={i18n.str`Search device`}
onChange={(p) => setState((v) => ({ ...v, otpId: p?.id }))}
- list={deviceList.map(e => ({
+ list={deviceList.map((e) => ({
description: e.device_description,
- id: e.otp_device_id
+ id: e.otp_device_id,
}))}
/>
-
</FormProvider>
<div class="buttons is-right mt-5">