aboutsummaryrefslogtreecommitdiff
path: root/packages/merchant-backoffice-ui/src/paths
diff options
context:
space:
mode:
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths')
-rw-r--r--packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx96
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx8
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx3
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx12
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx5
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/qr/Qr.stories.tsx27
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx133
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx70
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx8
9 files changed, 305 insertions, 57 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx b/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx
index 7376a88cb..fd1b8dc05 100644
--- a/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/admin/list/View.tsx
@@ -57,56 +57,54 @@ export function View({
: instances;
return (
- <div id="app">
- <section class="section is-main-section">
- <div class="columns">
- <div class="column is-two-thirds">
- <div class="tabs" style={{ overflow: "inherit" }}>
- <ul>
- <li class={showIsActive}>
- <div
- class="has-tooltip-right"
- data-tooltip={i18n.str`Only show active instances`}
- >
- <a onClick={() => setShow("active")}>
- <i18n.Translate>Active</i18n.Translate>
- </a>
- </div>
- </li>
- <li class={showIsDeleted}>
- <div
- class="has-tooltip-right"
- data-tooltip={i18n.str`Only show deleted instances`}
- >
- <a onClick={() => setShow("deleted")}>
- <i18n.Translate>Deleted</i18n.Translate>
- </a>
- </div>
- </li>
- <li class={showAll}>
- <div
- class="has-tooltip-right"
- data-tooltip={i18n.str`Show all instances`}
- >
- <a onClick={() => setShow(null)}>
- <i18n.Translate>All</i18n.Translate>
- </a>
- </div>
- </li>
- </ul>
- </div>
+ <section class="section is-main-section">
+ <div class="columns">
+ <div class="column is-two-thirds">
+ <div class="tabs" style={{ overflow: "inherit" }}>
+ <ul>
+ <li class={showIsActive}>
+ <div
+ class="has-tooltip-right"
+ data-tooltip={i18n.str`Only show active instances`}
+ >
+ <a onClick={() => setShow("active")}>
+ <i18n.Translate>Active</i18n.Translate>
+ </a>
+ </div>
+ </li>
+ <li class={showIsDeleted}>
+ <div
+ class="has-tooltip-right"
+ data-tooltip={i18n.str`Only show deleted instances`}
+ >
+ <a onClick={() => setShow("deleted")}>
+ <i18n.Translate>Deleted</i18n.Translate>
+ </a>
+ </div>
+ </li>
+ <li class={showAll}>
+ <div
+ class="has-tooltip-right"
+ data-tooltip={i18n.str`Show all instances`}
+ >
+ <a onClick={() => setShow(null)}>
+ <i18n.Translate>All</i18n.Translate>
+ </a>
+ </div>
+ </li>
+ </ul>
</div>
</div>
- <CardTableActive
- instances={showingInstances}
- onDelete={onDelete}
- onPurge={onPurge}
- setInstanceName={setInstanceName}
- onUpdate={onUpdate}
- selected={selected}
- onCreate={onCreate}
- />
- </section>
- </div>
+ </div>
+ <CardTableActive
+ instances={showingInstances}
+ onDelete={onDelete}
+ onPurge={onPurge}
+ setInstanceName={setInstanceName}
+ onUpdate={onUpdate}
+ selected={selected}
+ onCreate={onCreate}
+ />
+ </section>
);
}
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 b23c52362..22f86002a 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
@@ -114,13 +114,13 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
<Input
name="template_contract.summary"
inputType="multiline"
- label={i18n.str`Order summary`}
- tooltip={i18n.str`Title of the order to be shown to the customer`}
+ label={i18n.str`Fixed summary`}
+ tooltip={i18n.str`If specified, this template will create order with the same summary`}
/>
<InputCurrency
name="template_contract.amount"
- label={i18n.str`Order price`}
- tooltip={i18n.str`Order price`}
+ label={i18n.str`Fixed price`}
+ tooltip={i18n.str`If specified, this template will create order with the same price`}
/>
<InputNumber
name="template_contract.minimum_age"
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 8482f7f52..708720818 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
@@ -32,6 +32,7 @@ export interface Props {
onDelete: (e: MerchantBackend.Template.TemplateEntry) => void;
onSelect: (e: MerchantBackend.Template.TemplateEntry) => void;
onNewOrder: (e: MerchantBackend.Template.TemplateEntry) => void;
+ onQR: (e: MerchantBackend.Template.TemplateEntry) => void;
}
export function ListPage({
@@ -40,6 +41,7 @@ export function ListPage({
onDelete,
onSelect,
onNewOrder,
+ onQR,
onLoadMoreBefore,
onLoadMoreAfter,
}: Props): VNode {
@@ -53,6 +55,7 @@ export function ListPage({
...o,
id: String(o.template_id),
}))}
+ onQR={onQR}
onCreate={onCreate}
onDelete={onDelete}
onSelect={onSelect}
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 57d328d39..700c332d7 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
@@ -31,6 +31,7 @@ interface Props {
onDelete: (e: Entity) => void;
onSelect: (e: Entity) => void;
onNewOrder: (e: Entity) => void;
+ onQR: (e: Entity) => void;
onCreate: () => void;
onLoadMoreBefore?: () => void;
hasMoreBefore?: boolean;
@@ -43,6 +44,7 @@ export function CardTable({
onCreate,
onDelete,
onSelect,
+ onQR,
onNewOrder,
onLoadMoreAfter,
onLoadMoreBefore,
@@ -84,6 +86,7 @@ export function CardTable({
onDelete={onDelete}
onSelect={onSelect}
onNewOrder={onNewOrder}
+ onQR={onQR}
rowSelection={rowSelection}
rowSelectionHandler={rowSelectionHandler}
onLoadMoreAfter={onLoadMoreAfter}
@@ -105,6 +108,7 @@ interface TableProps {
instances: Entity[];
onDelete: (e: Entity) => void;
onNewOrder: (e: Entity) => void;
+ onQR: (e: Entity) => void;
onSelect: (e: Entity) => void;
rowSelectionHandler: StateUpdater<string[]>;
onLoadMoreBefore?: () => void;
@@ -123,6 +127,7 @@ function Table({
onLoadMoreAfter,
onDelete,
onNewOrder,
+ onQR,
onSelect,
onLoadMoreBefore,
hasMoreAfter,
@@ -185,6 +190,13 @@ function Table({
>
New order
</button>
+ <button
+ class="button is-info is-small has-tooltip-left"
+ data-tooltip={i18n.str`create qr code for the template`}
+ onClick={() => onQR(i)}
+ >
+ QR
+ </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 0b7c191bd..ea8f4e7e3 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
@@ -42,12 +42,14 @@ interface Props {
onCreate: () => void;
onSelect: (id: string) => void;
onNewOrder: (id: string) => void;
+ onQR: (id: string) => void;
}
export default function ListTemplates({
onUnauthorized,
onLoadError,
onCreate,
+ onQR,
onSelect,
onNewOrder,
onNotFound,
@@ -80,6 +82,9 @@ export default function ListTemplates({
onNewOrder={(e) => {
onNewOrder(e.template_id);
}}
+ onQR={(e) => {
+ onQR(e.template_id);
+ }}
onDelete={(e: MerchantBackend.Template.TemplateEntry) =>
deleteTemplate(e.template_id)
.then(() =>
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/Qr.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/Qr.stories.tsx
new file mode 100644
index 000000000..eb853c8ff
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/Qr.stories.tsx
@@ -0,0 +1,27 @@
+/*
+ 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 { QrPage as TestedComponent } from "./QrPage.js";
+
+export default {
+ title: "Pages/Templates/QR",
+ component: TestedComponent,
+};
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx
new file mode 100644
index 000000000..756909d15
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx
@@ -0,0 +1,133 @@
+/*
+ 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 { buildPayto, classifyTalerUri } 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";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import { QR } from "../../../../components/exception/QR.js";
+import {
+ FormErrors,
+ FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { useBackendContext } from "../../../../context/backend.js";
+import { useConfigContext } from "../../../../context/config.js";
+import { MerchantBackend } from "../../../../declaration.js";
+
+type Entity = MerchantBackend.Template.UsingTemplateDetails;
+
+interface Props {
+ template: MerchantBackend.Template.TemplateDetails;
+ id: string;
+ onBack?: () => void;
+}
+
+export function QrPage({ template, id: templateId, onBack }: Props): VNode {
+ const { i18n } = useTranslationContext();
+ const { url: backendUrl } = useBackendContext();
+ const config = useConfigContext();
+
+ const [state, setState] = useState<Partial<Entity>>({
+ amount: template.template_contract.amount,
+ summary: template.template_contract.summary,
+ });
+
+ const errors: FormErrors<Entity> = {};
+
+ const hasErrors = Object.keys(errors).some(
+ (k) => (errors as any)[k] !== undefined,
+ );
+
+ const fixedAmount = !!template.template_contract.amount;
+ const fixedSummary = !!template.template_contract.summary;
+
+ const params = new URLSearchParams();
+ if (!fixedAmount) {
+ if (state.amount) {
+ params.append("amount", state.amount);
+ } else {
+ params.append("amount", config.currency);
+ }
+ }
+ if (!fixedSummary) {
+ params.append("summary", state.summary ?? "");
+ }
+
+ const paramsStr = fixedAmount && fixedSummary ? "" : "?" + params.toString();
+ const merchantURL = new URL(backendUrl);
+
+ const talerProto =
+ merchantURL.protocol === "http:" ? "taler+http:" : "taler:";
+
+ const payTemplateUri = `${talerProto}//pay-template/${merchantURL.hostname}/${templateId}${paramsStr}`;
+
+ 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={fixedAmount}
+ tooltip={i18n.str`Amount of the order`}
+ />
+ <Input<Entity>
+ name="summary"
+ inputType="multiline"
+ readonly={fixedSummary}
+ label={i18n.str`Order 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>
+ )}
+ <button class="button is-info" onClick={onBack}>
+ <i18n.Translate>Print</i18n.Translate>
+ </button>
+ </div>
+ </div>
+ <div class="column" />
+ </div>
+ </section>
+ <section>
+ <pre>
+ <a href={payTemplateUri}>{payTemplateUri}</a>
+ </pre>
+ <QR text={payTemplateUri} />
+ </section>
+ </div>
+ );
+}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx
new file mode 100644
index 000000000..97d25b700
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/index.tsx
@@ -0,0 +1,70 @@
+/*
+ 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 {
+ HttpError,
+ 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 { Notification } from "../../../../utils/types.js";
+import { QrPage } from "./QrPage.js";
+
+export type Entity = MerchantBackend.Transfers.TransferInformation;
+interface Props {
+ onBack?: () => void;
+ onUnauthorized: () => VNode;
+ onNotFound: () => VNode;
+ onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+ tid: string;
+}
+
+export default function TemplateQrPage({
+ tid,
+ 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} />
+ <QrPage template={result.data} id={tid} onBack={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
index 5bd9bd38d..eba212517 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
@@ -123,13 +123,13 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode {
<Input
name="template_contract.summary"
inputType="multiline"
- label={i18n.str`Order summary`}
- tooltip={i18n.str`Title of the order to be shown to the customer`}
+ label={i18n.str`Fixed summary`}
+ tooltip={i18n.str`If specified, this template will create order with the same summary`}
/>
<InputCurrency
name="template_contract.amount"
- label={i18n.str`Order price`}
- tooltip={i18n.str`total product price added up`}
+ label={i18n.str`Fixed price`}
+ tooltip={i18n.str`If specified, this template will create order with the same price`}
/>
<InputNumber
name="template_contract.minimum_age"