diff options
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/templates/update')
-rw-r--r-- | packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx | 153 |
1 files changed, 93 insertions, 60 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 f9e2a3b01..3a32409a0 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 @@ -25,10 +25,13 @@ import { Duration, TalerError, TalerMerchantApi, - TranslatedString + TranslatedString, } from "@gnu-taler/taler-util"; -import { useMerchantApiContext, useTranslationContext } from "@gnu-taler/web-util/browser"; -import { VNode, h } from "preact"; +import { + useMerchantApiContext, + useTranslationContext, +} from "@gnu-taler/web-util/browser"; +import { Fragment, VNode, h } from "preact"; import { useState } from "preact/hooks"; import { AsyncButton } from "../../../../components/exception/AsyncButton.js"; import { @@ -45,12 +48,12 @@ import { TextField } from "../../../../components/form/TextField.js"; import { useInstanceOtpDevices } from "../../../../hooks/otp.js"; type Entity = { - description?: string, - otpId?: string | null, - summary?: string, - amount?: AmountString, - minimum_age?: number, - pay_duration?: Duration, + description?: string; + otpId?: string | null; + summary?: string; + amount?: AmountString; + minimum_age?: number; + pay_duration?: Duration; summary_editable?: boolean; amount_editable?: boolean; currency_editable?: boolean; @@ -64,17 +67,22 @@ interface Props { export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { const { i18n } = useTranslationContext(); - const { url: backendUrl } = useMerchantApiContext(); - - + const { url: backendUrl, config } = useMerchantApiContext(); const [state, setState] = useState<Partial<Entity>>({ description: template.template_description, minimum_age: template.template_contract.minimum_age, otpId: template.otp_id, - pay_duration: template.template_contract.pay_duration ? Duration.fromTalerProtocolDuration(template.template_contract.pay_duration) : undefined, - summary: template.editable_defaults?.summary ?? template.template_contract.summary, - amount: template.editable_defaults?.amount ?? template.template_contract.amount as AmountString | undefined, + pay_duration: template.template_contract.pay_duration + ? Duration.fromTalerProtocolDuration( + template.template_contract.pay_duration, + ) + : undefined, + summary: + template.editable_defaults?.summary ?? template.template_contract.summary, + amount: + template.editable_defaults?.amount ?? + (template.template_contract.amount as AmountString | undefined), currency_editable: !!template.editable_defaults?.currency, summary_editable: !!template.editable_defaults?.summary, amount_editable: !!template.editable_defaults?.amount, @@ -82,37 +90,38 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { function updateState(up: (s: Partial<Entity>) => Partial<Entity>) { setState((old) => { - const newState = up(old) + const newState = up(old); if (!newState.amount_editable) { - newState.currency_editable = false + newState.currency_editable = false; } - return newState - }) + return newState; + }); } - const devices = useInstanceOtpDevices() - const deviceList = !devices || devices instanceof TalerError || devices.type === "fail" ? [] : devices.body - const deviceMap = deviceList.reduce((prev, cur) => { - prev[cur.otp_device_id] = cur.device_description as TranslatedString - return prev - }, {} as Record<string, TranslatedString>) + const devices = useInstanceOtpDevices(); + const deviceList = + !devices || devices instanceof TalerError || devices.type === "fail" + ? [] + : devices.body; + const deviceMap = deviceList.reduce( + (prev, cur) => { + prev[cur.otp_device_id] = cur.device_description as TranslatedString; + return prev; + }, + {} as Record<string, TranslatedString>, + ); - const parsedPrice = !state.amount - ? undefined - : Amounts.parse(state.amount); + const parsedPrice = !state.amount ? undefined : Amounts.parse(state.amount); const errors: FormErrors<Entity> = { - description: !state.description - ? i18n.str`should not be empty` - : undefined, - amount: - !state.amount - ? undefined - : !parsedPrice - ? i18n.str`not valid` - : Amounts.isZero(parsedPrice) - ? i18n.str`must be greater than 0` - : undefined, + description: !state.description ? i18n.str`should not be empty` : undefined, + amount: !state.amount + ? undefined + : !parsedPrice + ? i18n.str`not valid` + : Amounts.isZero(parsedPrice) + ? i18n.str`must be greater than 0` + : undefined, minimum_age: state.minimum_age && state.minimum_age < 0 ? i18n.str`should be greater that 0` @@ -126,6 +135,8 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { : undefined, }; + const cList = Object.values(config.currencies).map((d) => d.name); + const hasErrors = Object.keys(errors).some( (k) => (errors as Record<string, unknown>)[k] !== undefined, ); @@ -139,17 +150,23 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!), amount: state.amount_editable ? undefined : state.amount, summary: state.summary_editable ? undefined : state.summary, + currency: + cList.length > 1 && state.currency_editable + ? undefined + : config.currency, }, editable_defaults: { amount: !state.amount_editable ? undefined : state.amount, summary: !state.summary_editable ? undefined : state.summary, + currency: + cList.length === 1 || !state.currency_editable + ? undefined + : config.currency, }, otp_id: state.otpId!, - }) - + }); }; - return ( <div> <section class="section"> @@ -176,7 +193,6 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { valueHandler={updateState} errors={errors} > - <Input<Entity> name="description" label={i18n.str`Description`} @@ -204,12 +220,21 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { label={i18n.str`Amount is editable`} tooltip={i18n.str`Allow the user to select the amount to pay.`} /> - {/* <InputToggle<Entity> - name="currency_editable" - readonly={!state.amount_editable} - label={i18n.str`Currency is editable`} - tooltip={i18n.str`Allow the user to change currency.`} - /> */} + {cList.length > 1 && ( + <Fragment> + <InputToggle<Entity> + name="currency_editable" + readonly={!state.amount_editable} + label={i18n.str`Currency is editable`} + tooltip={i18n.str`Allow the user to change currency.`} + /> + <TextField name="sc" label={i18n.str`Supported currencies`}> + <i18n.Translate> + supported currencies: {cList.join(", ")} + </i18n.Translate> + </TextField> + </Fragment> + )} <InputNumber<Entity> name="minimum_age" label={i18n.str`Minimum age`} @@ -222,26 +247,34 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { help="" tooltip={i18n.str`How much time has the customer to complete the payment once the order was created.`} /> - {!deviceList.length ? <TextField - name="otpId" - label={i18n.str`OTP device`} - tooltip={i18n.str`Use to verify transaction while offline.`} - > - <i18n.Translate>No OTP device.</i18n.Translate> <a href="/otp-devices/new"><i18n.Translate>Add one first</i18n.Translate></a> - </TextField> : + {!deviceList.length ? ( + <TextField + name="otpId" + label={i18n.str`OTP device`} + tooltip={i18n.str`Use to verify transaction while offline.`} + > + <i18n.Translate>No OTP device.</i18n.Translate> + <a href="/otp-devices/new"> + <i18n.Translate>Add one first</i18n.Translate> + </a> + </TextField> + ) : ( <InputSelector<Entity> name="otpId" label={i18n.str`OTP device`} - values={[undefined, ...deviceList.map(e => e.otp_device_id)]} + values={[ + undefined, + ...deviceList.map((e) => e.otp_device_id), + ]} toStr={(v?: string) => { if (!v) { - return i18n.str`No device` + return i18n.str`No device`; } - return deviceMap[v] + return deviceMap[v]; }} tooltip={i18n.str`Use to verify transaction in offline mode.`} /> - } + )} </FormProvider> <div class="buttons is-right mt-5"> |