aboutsummaryrefslogtreecommitdiff
path: root/packages/merchant-backoffice-ui/src/paths/instance/templates/update
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2022-12-19 16:25:09 -0300
committerSebastian <sebasjm@gmail.com>2022-12-19 16:25:09 -0300
commitcf7f819685c19adfe6443a6bdd10f3afe10b247d (patch)
tree20ace56c90d25a05995dce04432733445646e51e /packages/merchant-backoffice-ui/src/paths/instance/templates/update
parent45691dc991945d8c0a3d4bc95078bd1af5932927 (diff)
downloadwallet-core-cf7f819685c19adfe6443a6bdd10f3afe10b247d.tar.xz
templates
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/templates/update')
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/update/Update.stories.tsx32
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx174
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx86
3 files changed, 292 insertions, 0 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/Update.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/Update.stories.tsx
new file mode 100644
index 000000000..8d07cb31f
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/Update.stories.tsx
@@ -0,0 +1,32 @@
+/*
+ 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 { UpdatePage as TestedComponent } from "./UpdatePage.js";
+
+export default {
+ title: "Pages/Templates/Update",
+ component: TestedComponent,
+ argTypes: {
+ onUpdate: { action: "onUpdate" },
+ onBack: { action: "onBack" },
+ },
+};
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
new file mode 100644
index 000000000..42d9e5825
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
@@ -0,0 +1,174 @@
+/*
+ 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 } 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 { InputDuration } from "../../../../components/form/InputDuration.js";
+import { InputNumber } from "../../../../components/form/InputNumber.js";
+import { InputWithAddon } from "../../../../components/form/InputWithAddon.js";
+import { ProductForm } from "../../../../components/product/ProductForm.js";
+import { useBackendContext } from "../../../../context/backend.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { useListener } from "../../../../hooks/listener.js";
+import { Translate, useTranslator } from "../../../../i18n/index.js";
+import { undefinedIfEmpty } from "../../../../utils/table.js";
+
+type Entity = MerchantBackend.Template.TemplatePatchDetails & WithId;
+
+interface Props {
+ onUpdate: (d: Entity) => Promise<void>;
+ onBack?: () => void;
+ template: Entity;
+}
+
+export function UpdatePage({ template, onUpdate, onBack }: Props): VNode {
+ const i18n = useTranslator();
+ const backend = useBackendContext();
+
+ const [state, setState] = useState<Partial<Entity>>(template);
+
+ const errors: FormErrors<Entity> = {
+ template_description: !state.template_description
+ ? i18n`should not be empty`
+ : undefined,
+ template_contract: !state.template_contract
+ ? undefined
+ : undefinedIfEmpty({
+ minimum_age:
+ state.template_contract.minimum_age < 0
+ ? i18n`should be greater that 0`
+ : undefined,
+ pay_duration: !state.template_contract.pay_duration
+ ? i18n`can't be empty`
+ : state.template_contract.pay_duration.d_us === "forever"
+ ? undefined
+ : state.template_contract.pay_duration.d_us < 1000
+ ? i18n`to short`
+ : undefined,
+ }),
+ };
+
+ const hasErrors = Object.keys(errors).some(
+ (k) => (errors as any)[k] !== undefined,
+ );
+
+ const submitForm = () => {
+ if (hasErrors) return Promise.reject();
+ return onUpdate(state as any);
+ };
+
+ return (
+ <div>
+ <section class="section">
+ <section class="hero is-hero-bar">
+ <div class="hero-body">
+ <div class="level">
+ <div class="level-left">
+ <div class="level-item">
+ <span class="is-size-4">
+ {backend.url}/instances/template/{template.id}
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </section>
+ <hr />
+
+ <section class="section is-main-section">
+ <div class="columns">
+ <div class="column is-four-fifths">
+ <FormProvider
+ object={state}
+ valueHandler={setState}
+ errors={errors}
+ >
+ <InputWithAddon<Entity>
+ name="id"
+ addonBefore={`templates/`}
+ readonly
+ label={i18n`Identifier`}
+ tooltip={i18n`Name of the template in URLs.`}
+ />
+
+ <Input<Entity>
+ name="template_description"
+ label={i18n`Description`}
+ help=""
+ tooltip={i18n`Describe what this template stands for`}
+ />
+ <Input
+ name="template_contract.summary"
+ inputType="multiline"
+ label={i18n`Order summary`}
+ tooltip={i18n`Title of the order to be shown to the customer`}
+ />
+ <InputCurrency
+ name="template_contract.amount"
+ label={i18n`Order price`}
+ tooltip={i18n`total product price added up`}
+ />
+ <InputNumber
+ name="template_contract.minimum_age"
+ label={i18n`Minimum age`}
+ help=""
+ tooltip={i18n`Is this contract restricted to some age?`}
+ />
+ <InputDuration
+ name="template_contract.pay_duration"
+ label={i18n`Payment timeout`}
+ help=""
+ tooltip={i18n`How much time has the customer to complete the payment once the order was created.`}
+ />
+ </FormProvider>
+
+ <div class="buttons is-right mt-5">
+ {onBack && (
+ <button class="button" onClick={onBack}>
+ <Translate>Cancel</Translate>
+ </button>
+ )}
+ <AsyncButton
+ disabled={hasErrors}
+ data-tooltip={
+ hasErrors
+ ? i18n`Need to complete marked fields`
+ : "confirm operation"
+ }
+ onClick={submitForm}
+ >
+ <Translate>Confirm</Translate>
+ </AsyncButton>
+ </div>
+ </div>
+ </div>
+ </section>
+ </section>
+ </div>
+ );
+}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/index.tsx
new file mode 100644
index 000000000..25dc9abdc
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/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 { 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, WithId } from "../../../../declaration.js";
+import { HttpError } from "../../../../hooks/backend.js";
+import { useProductAPI, useProductDetails } from "../../../../hooks/product.js";
+import {
+ useTemplateAPI,
+ useTemplateDetails,
+} from "../../../../hooks/templates.js";
+import { useTranslator } from "../../../../i18n/index.js";
+import { Notification } from "../../../../utils/types.js";
+import { UpdatePage } from "./UpdatePage.js";
+
+export type Entity = MerchantBackend.Template.TemplatePatchDetails & WithId;
+
+interface Props {
+ onBack?: () => void;
+ onConfirm: () => void;
+ onUnauthorized: () => VNode;
+ onNotFound: () => VNode;
+ onLoadError: (e: HttpError) => VNode;
+ tid: string;
+}
+export default function UpdateTemplate({
+ tid,
+ onConfirm,
+ onBack,
+ onUnauthorized,
+ onNotFound,
+ onLoadError,
+}: Props): VNode {
+ const { updateTemplate } = useTemplateAPI();
+ const result = useTemplateDetails(tid);
+ const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+ const i18n = useTranslator();
+
+ 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 (
+ <Fragment>
+ <NotificationCard notification={notif} />
+ <UpdatePage
+ template={{ ...result.data, id: tid }}
+ onBack={onBack}
+ onUpdate={(data) => {
+ return updateTemplate(tid, data)
+ .then(onConfirm)
+ .catch((error) => {
+ setNotif({
+ message: i18n`could not update template`,
+ type: "ERROR",
+ description: error.message,
+ });
+ });
+ }}
+ />
+ </Fragment>
+ );
+}