diff options
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths')
13 files changed, 282 insertions, 18 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/details/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/details/DetailPage.tsx index 4ab415e85..9a35b0797 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/details/DetailPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/details/DetailPage.tsx @@ -40,8 +40,8 @@ function convert( const payto_uris = accounts.filter((a) => a.active).map((a) => a.payto_uri); const defaults = { default_wire_fee_amortization: 1, - default_pay_delay: { d_us: 1000 * 60 * 60 }, //one hour - default_wire_transfer_delay: { d_us: 1000 * 60 * 60 * 2 }, //two hours + default_pay_delay: { d_us: 1000 * 60 * 60 * 1000 }, //one hour + default_wire_transfer_delay: { d_us: 1000 * 60 * 60 * 2 * 1000 }, //two hours }; return { ...defaults, ...rest, payto_uris }; } diff --git a/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx index cdbe732a4..3a6e0fbfe 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/details/stories.tsx @@ -59,11 +59,11 @@ export const Example = createExample(TestedComponent, { default_max_deposit_fee: "TESTKUDOS:2", default_max_wire_fee: "TESTKUDOS:1", default_pay_delay: { - d_us: 1000000, + d_us: 1000 * 1000, //one second }, default_wire_fee_amortization: 1, default_wire_transfer_delay: { - d_us: 100000, + d_us: 1000 * 1000, //one second }, merchant_pub: "ASDWQEKASJDKSADJ", }, diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx index 5f8dbbdd9..fcf611c3c 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx @@ -45,7 +45,7 @@ export const Example = createExample(TestedComponent, { default_max_deposit_fee: "", default_max_wire_fee: "", default_pay_delay: { - d_us: 1000 * 60 * 60, + d_us: 1000 * 1000 * 60 * 60, //one hour }, default_wire_fee_amortization: 1, }, diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx index 0c2e92418..f4a82f377 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx @@ -61,7 +61,9 @@ function with_defaults(config: InstanceConfig): Partial<Entity> { const defaultPayDeadline = !config.default_pay_delay || config.default_pay_delay.d_us === "forever" ? undefined - : add(new Date(), { seconds: config.default_pay_delay.d_us / 1000 }); + : add(new Date(), { + seconds: config.default_pay_delay.d_us / (1000 * 1000), + }); return { inventoryProducts: {}, 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 2a47c22a0..2b8d718fb 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 @@ -72,7 +72,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { ? i18n.str`can't be empty` : state.template_contract.pay_duration.d_us === "forever" ? undefined - : state.template_contract.pay_duration.d_us < 1000 + : state.template_contract.pay_duration.d_us < 1000 * 1000 //less than one second ? i18n.str`to short` : undefined, }), diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx index 9d289e957..8482f7f52 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx @@ -31,6 +31,7 @@ export interface Props { onCreate: () => void; onDelete: (e: MerchantBackend.Template.TemplateEntry) => void; onSelect: (e: MerchantBackend.Template.TemplateEntry) => void; + onNewOrder: (e: MerchantBackend.Template.TemplateEntry) => void; } export function ListPage({ @@ -38,6 +39,7 @@ export function ListPage({ onCreate, onDelete, onSelect, + onNewOrder, onLoadMoreBefore, onLoadMoreAfter, }: Props): VNode { @@ -54,6 +56,7 @@ export function ListPage({ onCreate={onCreate} onDelete={onDelete} onSelect={onSelect} + onNewOrder={onNewOrder} onLoadMoreBefore={onLoadMoreBefore} hasMoreBefore={!onLoadMoreBefore} onLoadMoreAfter={onLoadMoreAfter} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx index fd6ea5f6f..6635d6c55 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx @@ -30,6 +30,7 @@ interface Props { templates: Entity[]; onDelete: (e: Entity) => void; onSelect: (e: Entity) => void; + onNewOrder: (e: Entity) => void; onCreate: () => void; onLoadMoreBefore?: () => void; hasMoreBefore?: boolean; @@ -42,6 +43,7 @@ export function CardTable({ onCreate, onDelete, onSelect, + onNewOrder, onLoadMoreAfter, onLoadMoreBefore, hasMoreAfter, @@ -81,6 +83,7 @@ export function CardTable({ instances={templates} onDelete={onDelete} onSelect={onSelect} + onNewOrder={onNewOrder} rowSelection={rowSelection} rowSelectionHandler={rowSelectionHandler} onLoadMoreAfter={onLoadMoreAfter} @@ -101,6 +104,7 @@ interface TableProps { rowSelection: string[]; instances: Entity[]; onDelete: (e: Entity) => void; + onNewOrder: (e: Entity) => void; onSelect: (e: Entity) => void; rowSelectionHandler: StateUpdater<string[]>; onLoadMoreBefore?: () => void; @@ -118,6 +122,7 @@ function Table({ instances, onLoadMoreAfter, onDelete, + onNewOrder, onSelect, onLoadMoreBefore, hasMoreAfter, @@ -164,14 +169,23 @@ function Table({ > {i.template_description} </td> - <td> - <button - class="button is-danger is-small has-tooltip-left" - data-tooltip={i18n.str`delete selected templates from the database`} - onClick={() => onDelete(i)} - > - Delete - </button> + <td class="is-actions-cell right-sticky"> + <div class="buttons is-right"> + <button + class="button is-danger is-small has-tooltip-left" + data-tooltip={i18n.str`delete selected templates from the database`} + onClick={() => onDelete(i)} + > + Delete + </button> + <button + class="button is-info is-small has-tooltip-left" + data-tooltip={i18n.str`delete selected templates from the database`} + onClick={() => onNewOrder(i)} + > + New order + </button> + </div> </td> </tr> ); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx index e1a2d019e..5fce3a819 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx @@ -39,6 +39,7 @@ interface Props { onNotFound: () => VNode; onCreate: () => void; onSelect: (id: string) => void; + onNewOrder: (id: string) => void; } export default function ListTemplates({ @@ -46,6 +47,7 @@ export default function ListTemplates({ onLoadError, onCreate, onSelect, + onNewOrder, onNotFound, }: Props): VNode { const [position, setPosition] = useState<string | undefined>(undefined); @@ -73,6 +75,9 @@ export default function ListTemplates({ onSelect={(e) => { onSelect(e.template_id); }} + onNewOrder={(e) => { + onNewOrder(e.template_id); + }} onDelete={(e: MerchantBackend.Template.TemplateEntry) => deleteTemplate(e.template_id) .then(() => 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 a49e8000b..718a67ae0 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 @@ -65,7 +65,7 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { ? i18n.str`can't be empty` : state.template_contract.pay_duration.d_us === "forever" ? undefined - : state.template_contract.pay_duration.d_us < 1000 + : state.template_contract.pay_duration.d_us < 1000 * 1000 // less than one second ? i18n.str`to short` : undefined, }), diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/Use.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/Use.stories.tsx new file mode 100644 index 000000000..f073b4235 --- /dev/null +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/Use.stories.tsx @@ -0,0 +1,28 @@ +/* + 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 { h, VNode, FunctionalComponent } from "preact"; +import { CreatePage as TestedComponent } from "./UsePage.js"; + +export default { + title: "Pages/Templates/Create", + component: TestedComponent, +}; diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx new file mode 100644 index 000000000..a63469763 --- /dev/null +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx @@ -0,0 +1,126 @@ +/* + 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/lib/index.browser"; +import { 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 { InputCurrency } from "../../../../components/form/InputCurrency.js"; +import { MerchantBackend } from "../../../../declaration.js"; + +type Entity = MerchantBackend.Template.UsingTemplateDetails; + +interface Props { + template: MerchantBackend.Template.TemplateDetails; + onCreateOrder: (d: Entity) => Promise<void>; + onBack?: () => void; +} + +export function UsePage({ template, onCreateOrder, onBack }: Props): VNode { + const { i18n } = useTranslationContext(); + + const [state, setState] = useState<Partial<Entity>>({ + amount: template.template_contract.amount, + summary: template.template_contract.summary, + }); + + const errors: FormErrors<Entity> = { + amount: + !template.template_contract.amount && !state.amount + ? i18n.str`Amount is required` + : undefined, + summary: + !template.template_contract.summary && !state.summary + ? i18n.str`Order summary is required` + : undefined, + }; + + const hasErrors = Object.keys(errors).some( + (k) => (errors as any)[k] !== undefined, + ); + + const submitForm = () => { + if (hasErrors) return Promise.reject(); + if (template.template_contract.amount) { + delete state.amount; + } + if (template.template_contract.summary) { + delete state.summary; + } + return onCreateOrder(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} + > + <InputCurrency<Entity> + name="amount" + label={i18n.str`Amount`} + readonly={!!template.template_contract.amount} + tooltip={i18n.str`Amount of the order`} + /> + <Input<Entity> + name="summary" + inputType="multiline" + label={i18n.str`Order summary`} + readonly={!!template.template_contract.summary} + tooltip={i18n.str`Title of the order to be shown to the customer`} + /> + </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> + ); +} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx new file mode 100644 index 000000000..fa9a98c6d --- /dev/null +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/index.tsx @@ -0,0 +1,86 @@ +/* + 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/lib/index.browser"; +import { Fragment, h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { Loading } from "../../../../components/exception/loading.js"; +import { NotificationCard } from "../../../../components/menu/index.js"; +import { MerchantBackend } from "../../../../declaration.js"; +import { + useTemplateAPI, + useTemplateDetails, +} from "../../../../hooks/templates.js"; +import { HttpError } from "../../../../utils/request.js"; +import { Notification } from "../../../../utils/types.js"; +import { UsePage } from "./UsePage.js"; + +export type Entity = MerchantBackend.Transfers.TransferInformation; +interface Props { + onBack?: () => void; + onOrderCreated: (id: string) => void; + onUnauthorized: () => VNode; + onNotFound: () => VNode; + onLoadError: (e: HttpError) => VNode; + tid: string; +} + +export default function TemplateUsePage({ + tid, + onOrderCreated, + onBack, + onLoadError, + onNotFound, + onUnauthorized, +}: Props): VNode { + const { createOrderFromTemplate } = useTemplateAPI(); + const result = useTemplateDetails(tid); + const [notif, setNotif] = useState<Notification | undefined>(undefined); + const { i18n } = useTranslationContext(); + + if (result.clientError && result.isUnauthorized) return onUnauthorized(); + if (result.clientError && result.isNotfound) return onNotFound(); + if (result.loading) return <Loading />; + if (!result.ok) return onLoadError(result); + + return ( + <> + <NotificationCard notification={notif} /> + <UsePage + template={result.data} + onBack={onBack} + onCreateOrder={( + request: MerchantBackend.Template.UsingTemplateDetails, + ) => { + return createOrderFromTemplate(tid, request) + .then((res) => onOrderCreated(res.data.order_id)) + .catch((error) => { + setNotif({ + message: i18n.str`could not create order from template`, + type: "ERROR", + description: error.message, + }); + }); + }} + /> + </> + ); +} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/update/Update.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/update/Update.stories.tsx index 58b8d87ea..045c96c2c 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/update/Update.stories.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/update/Update.stories.tsx @@ -50,11 +50,11 @@ export const Example = createExample(TestedComponent, { default_max_deposit_fee: "TESTKUDOS:2", default_max_wire_fee: "TESTKUDOS:1", default_pay_delay: { - d_us: 1000000, + d_us: 1000 * 1000, //one second }, default_wire_fee_amortization: 1, default_wire_transfer_delay: { - d_us: 100000, + d_us: 1000 * 1000, //one second }, merchant_pub: "ASDWQEKASJDKSADJ", }, |