aboutsummaryrefslogtreecommitdiff
path: root/packages/merchant-backoffice-ui/src/paths/instance/transfers
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2022-10-24 10:46:14 +0200
committerFlorian Dold <florian@dold.me>2022-10-24 10:46:14 +0200
commit3e060b80428943c6562250a6ff77eff10a0259b7 (patch)
treed08472bc5ca28621c62ac45b229207d8215a9ea7 /packages/merchant-backoffice-ui/src/paths/instance/transfers
parentfb52ced35ac872349b0e1062532313662552ff6c (diff)
downloadwallet-core-3e060b80428943c6562250a6ff77eff10a0259b7.tar.xz
repo: integrate packages from former merchant-backoffice.git
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/transfers')
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/create/Create.stories.tsx43
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx104
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx60
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/list/List.stories.tsx93
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx89
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx225
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/list/index.tsx85
-rw-r--r--packages/merchant-backoffice-ui/src/paths/instance/transfers/update/index.tsx26
8 files changed, 725 insertions, 0 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/Create.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/Create.stories.tsx
new file mode 100644
index 000000000..535cb1e37
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/Create.stories.tsx
@@ -0,0 +1,43 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 './CreatePage';
+
+
+export default {
+ title: 'Pages/Transfer/Create',
+ component: TestedComponent,
+ argTypes: {
+ onUpdate: { action: 'onUpdate' },
+ onBack: { action: 'onBack' },
+ },
+};
+
+function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
+ const r = (args: any) => <Component {...args} />
+ r.args = props
+ return r
+}
+
+export const Example = createExample(TestedComponent, {
+ accounts: ['payto://x-taler-bank/account1','payto://x-taler-bank/account2']
+});
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx
new file mode 100644
index 000000000..d0f5c5e95
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx
@@ -0,0 +1,104 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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";
+import { FormErrors, FormProvider } from "../../../../components/form/FormProvider";
+import { Input } from "../../../../components/form/Input";
+import { InputCurrency } from "../../../../components/form/InputCurrency";
+import { InputSelector } from "../../../../components/form/InputSelector";
+import { useConfigContext } from "../../../../context/config";
+import { MerchantBackend } from "../../../../declaration";
+import { Translate, useTranslator } from "../../../../i18n";
+import { CROCKFORD_BASE32_REGEX, URL_REGEX } from "../../../../utils/constants";
+
+type Entity = MerchantBackend.Transfers.TransferInformation
+
+interface Props {
+ onCreate: (d: Entity) => Promise<void>;
+ onBack?: () => void;
+ accounts: string[],
+}
+
+export function CreatePage({ accounts, onCreate, onBack }: Props): VNode {
+ const i18n = useTranslator()
+ const { currency } = useConfigContext()
+
+ const [state, setState] = useState<Partial<Entity>>({
+ wtid: '',
+ // payto_uri: ,
+ // exchange_url: 'http://exchange.taler:8081/',
+ credit_amount: ``,
+ });
+
+ const errors: FormErrors<Entity> = {
+ wtid: !state.wtid ? i18n`cannot be empty` :
+ (!CROCKFORD_BASE32_REGEX.test(state.wtid) ? i18n`check the id, does not look valid` :
+ (state.wtid.length !== 52 ? i18n`should have 52 characters, current ${state.wtid.length}` :
+ undefined)),
+ payto_uri: !state.payto_uri ? i18n`cannot be empty` : undefined,
+ credit_amount: !state.credit_amount ? i18n`cannot be empty` : undefined,
+ exchange_url: !state.exchange_url ? i18n`cannot be empty` :
+ (!URL_REGEX.test(state.exchange_url) ? i18n`URL doesn't have the right format` : undefined),
+ }
+
+ const hasErrors = Object.keys(errors).some(k => (errors as any)[k] !== undefined)
+
+ const submitForm = () => {
+ if (hasErrors) return Promise.reject()
+ return onCreate(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}>
+ <InputSelector name="payto_uri" label={i18n`Credited bank account`}
+ values={accounts}
+ placeholder={i18n`Select one account`}
+ tooltip={i18n`Bank account of the merchant where the payment was received`}
+ />
+ <Input<Entity> name="wtid" label={i18n`Wire transfer ID`} help="" tooltip={i18n`unique identifier of the wire transfer used by the exchange, must be 52 characters long`} />
+ <Input<Entity> name="exchange_url"
+ label={i18n`Exchange URL`}
+ tooltip={i18n`Base URL of the exchange that made the transfer, should have been in the wire transfer subject`}
+ help="http://exchange.taler:8081/" />
+ <InputCurrency<Entity> name="credit_amount" label={i18n`Amount credited`} tooltip={i18n`Actual amount that was wired to the merchant's bank account`} />
+
+ </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 class="column" />
+ </div>
+ </section>
+ </div>
+}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx
new file mode 100644
index 000000000..d95929a0e
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/create/index.tsx
@@ -0,0 +1,60 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 { NotificationCard } from '../../../../components/menu';
+import { MerchantBackend } from '../../../../declaration';
+import { useInstanceDetails } from '../../../../hooks/instance';
+import { useTransferAPI } from '../../../../hooks/transfer';
+import { useTranslator } from '../../../../i18n';
+import { Notification } from '../../../../utils/types';
+import { CreatePage } from './CreatePage';
+
+export type Entity = MerchantBackend.Transfers.TransferInformation
+interface Props {
+ onBack?: () => void;
+ onConfirm: () => void;
+}
+
+export default function CreateTransfer({onConfirm, onBack}:Props): VNode {
+ const { informTransfer } = useTransferAPI()
+ const [notif, setNotif] = useState<Notification | undefined>(undefined)
+ const i18n = useTranslator()
+ const instance = useInstanceDetails()
+ const accounts = !instance.ok ? [] : instance.data.accounts.map(a => a.payto_uri)
+
+ return <>
+ <NotificationCard notification={notif} />
+ <CreatePage
+ onBack={onBack}
+ accounts={accounts}
+ onCreate={(request: MerchantBackend.Transfers.TransferInformation) => {
+ return informTransfer(request).then(() => onConfirm()).catch((error) => {
+ setNotif({
+ message: i18n`could not inform transfer`,
+ type: "ERROR",
+ description: error.message
+ })
+ })
+ }} />
+ </>
+} \ No newline at end of file
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/List.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/List.stories.tsx
new file mode 100644
index 000000000..24a791187
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/List.stories.tsx
@@ -0,0 +1,93 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 { ListPage as TestedComponent } from "./ListPage";
+
+export default {
+ title: "Pages/Transfer/List",
+ component: TestedComponent,
+ argTypes: {
+ onCreate: { action: "onCreate" },
+ onDelete: { action: "onDelete" },
+ onLoadMoreBefore: { action: "onLoadMoreBefore" },
+ onLoadMoreAfter: { action: "onLoadMoreAfter" },
+ onShowAll: { action: "onShowAll" },
+ onShowVerified: { action: "onShowVerified" },
+ onShowUnverified: { action: "onShowUnverified" },
+ onChangePayTo: { action: "onChangePayTo" },
+ },
+};
+
+function createExample<Props>(
+ Component: FunctionalComponent<Props>,
+ props: Partial<Props>
+) {
+ const r = (args: any) => <Component {...args} />;
+ r.args = props;
+ return r;
+}
+
+export const Example = createExample(TestedComponent, {
+ transfers: [
+ {
+ exchange_url: "http://exchange.url/",
+ credit_amount: "TESTKUDOS:10",
+ payto_uri: "payto//x-taler-bank/bank:8080/account",
+ transfer_serial_id: 123123123,
+ wtid: "!@KJELQKWEJ!L@K#!J@",
+ confirmed: true,
+ execution_time: {
+ t_s: new Date().getTime() / 1000,
+ },
+ verified: false,
+ },
+ {
+ exchange_url: "http://exchange.url/",
+ credit_amount: "TESTKUDOS:10",
+ payto_uri: "payto//x-taler-bank/bank:8080/account",
+ transfer_serial_id: 123123123,
+ wtid: "!@KJELQKWEJ!L@K#!J@",
+ confirmed: true,
+ execution_time: {
+ t_s: new Date().getTime() / 1000,
+ },
+ verified: false,
+ },
+ {
+ exchange_url: "http://exchange.url/",
+ credit_amount: "TESTKUDOS:10",
+ payto_uri: "payto//x-taler-bank/bank:8080/account",
+ transfer_serial_id: 123123123,
+ wtid: "!@KJELQKWEJ!L@K#!J@",
+ confirmed: true,
+ execution_time: {
+ t_s: new Date().getTime() / 1000,
+ },
+ verified: false,
+ },
+ ],
+ accounts: ["payto://x-taler-bank/bank/some_account"],
+});
+export const Empty = createExample(TestedComponent, {
+ transfers: [],
+ accounts: [],
+});
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx
new file mode 100644
index 000000000..544a720b8
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx
@@ -0,0 +1,89 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 { FormProvider } from '../../../../components/form/FormProvider';
+import { InputSelector } from '../../../../components/form/InputSelector';
+import { MerchantBackend } from '../../../../declaration';
+import { Translate, useTranslator } from '../../../../i18n';
+import { CardTable } from './Table';
+
+export interface Props {
+ transfers: MerchantBackend.Transfers.TransferDetails[];
+ onLoadMoreBefore?: () => void;
+ onLoadMoreAfter?: () => void;
+ onShowAll: () => void;
+ onShowVerified: () => void;
+ onShowUnverified: () => void;
+ isVerifiedTransfers?: boolean;
+ isNonVerifiedTransfers?: boolean;
+ isAllTransfers?: boolean;
+ accounts: string[];
+ onChangePayTo: (p?: string) => void;
+ payTo?: string;
+ onCreate: () => void;
+ onDelete: () => void;
+}
+
+export function ListPage({ payTo, onChangePayTo, transfers, onCreate, onDelete, accounts, onLoadMoreBefore, onLoadMoreAfter, isAllTransfers, isNonVerifiedTransfers, isVerifiedTransfers, onShowAll, onShowUnverified, onShowVerified }: Props): VNode {
+ const form = { payto_uri: payTo }
+
+ const i18n = useTranslator();
+ return <section class="section is-main-section">
+ <div class="columns">
+ <div class="column" />
+ <div class="column is-10">
+ <FormProvider object={form} valueHandler={(updater) => onChangePayTo(updater(form).payto_uri)}>
+ <InputSelector name="payto_uri" label={i18n`Address`}
+ values={accounts}
+ placeholder={i18n`Select one account`}
+ tooltip={i18n`filter by account address`} />
+ </FormProvider>
+ </div>
+ <div class="column" />
+ </div>
+ <div class="tabs">
+ <ul>
+ <li class={isAllTransfers ? 'is-active' : ''}>
+ <div class="has-tooltip-right" data-tooltip={i18n`remove all filters`}>
+ <a onClick={onShowAll}><Translate>All</Translate></a>
+ </div>
+ </li>
+ <li class={isVerifiedTransfers ? 'is-active' : ''}>
+ <div class="has-tooltip-right" data-tooltip={i18n`only show wire transfers confirmed by the merchant`}>
+ <a onClick={onShowVerified}><Translate>Verified</Translate></a>
+ </div>
+ </li>
+ <li class={isNonVerifiedTransfers ? 'is-active' : ''}>
+ <div class="has-tooltip-right" data-tooltip={i18n`only show wire transfers claimed by the exchange`}>
+ <a onClick={onShowUnverified}><Translate>Unverified</Translate></a>
+ </div>
+ </li>
+ </ul>
+ </div>
+ <CardTable transfers={transfers.map(o => ({ ...o, id: String(o.transfer_serial_id) }))}
+ accounts={accounts}
+ onCreate={onCreate}
+ onDelete={onDelete}
+ onLoadMoreBefore={onLoadMoreBefore} hasMoreBefore={!onLoadMoreBefore}
+ onLoadMoreAfter={onLoadMoreAfter} hasMoreAfter={!onLoadMoreAfter} />
+ </section>;
+}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx
new file mode 100644
index 000000000..4cb04694d
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx
@@ -0,0 +1,225 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 { format } from "date-fns";
+import { h, VNode } from "preact";
+import { StateUpdater, useState } from "preact/hooks";
+import { MerchantBackend, WithId } from "../../../../declaration";
+import { Translate, useTranslator } from "../../../../i18n";
+
+type Entity = MerchantBackend.Transfers.TransferDetails & WithId;
+
+interface Props {
+ transfers: Entity[];
+ onDelete: (id: Entity) => void;
+ onCreate: () => void;
+ accounts: string[];
+ onLoadMoreBefore?: () => void;
+ hasMoreBefore?: boolean;
+ hasMoreAfter?: boolean;
+ onLoadMoreAfter?: () => void;
+}
+
+export function CardTable({
+ transfers,
+ onCreate,
+ onDelete,
+ onLoadMoreAfter,
+ onLoadMoreBefore,
+ hasMoreAfter,
+ hasMoreBefore,
+}: Props): VNode {
+ const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
+
+ const i18n = useTranslator();
+
+ return (
+ <div class="card has-table">
+ <header class="card-header">
+ <p class="card-header-title">
+ <span class="icon">
+ <i class="mdi mdi-bank" />
+ </span>
+ <Translate>Transfers</Translate>
+ </p>
+ <div class="card-header-icon" aria-label="more options">
+ <span class="has-tooltip-left" data-tooltip={i18n`add new transfer`}>
+ <button class="button is-info" type="button" onClick={onCreate}>
+ <span class="icon is-small">
+ <i class="mdi mdi-plus mdi-36px" />
+ </span>
+ </button>
+ </span>
+ </div>
+ </header>
+ <div class="card-content">
+ <div class="b-table has-pagination">
+ <div class="table-wrapper has-mobile-cards">
+ {transfers.length > 0 ? (
+ <Table
+ instances={transfers}
+ onDelete={onDelete}
+ rowSelection={rowSelection}
+ rowSelectionHandler={rowSelectionHandler}
+ onLoadMoreAfter={onLoadMoreAfter}
+ onLoadMoreBefore={onLoadMoreBefore}
+ hasMoreAfter={hasMoreAfter}
+ hasMoreBefore={hasMoreBefore}
+ />
+ ) : (
+ <EmptyTable />
+ )}
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+}
+interface TableProps {
+ rowSelection: string[];
+ instances: Entity[];
+ onDelete: (id: Entity) => void;
+ rowSelectionHandler: StateUpdater<string[]>;
+ onLoadMoreBefore?: () => void;
+ hasMoreBefore?: boolean;
+ hasMoreAfter?: boolean;
+ onLoadMoreAfter?: () => void;
+}
+
+function toggleSelected<T>(id: T): (prev: T[]) => T[] {
+ return (prev: T[]): T[] =>
+ prev.indexOf(id) == -1 ? [...prev, id] : prev.filter((e) => e != id);
+}
+
+function Table({
+ instances,
+ onLoadMoreAfter,
+ onDelete,
+ onLoadMoreBefore,
+ hasMoreAfter,
+ hasMoreBefore,
+}: TableProps): VNode {
+ const i18n = useTranslator();
+ return (
+ <div class="table-container">
+ {onLoadMoreBefore && (
+ <button
+ class="button is-fullwidth"
+ data-tooltip={i18n`load more transfers before the first one`}
+ disabled={!hasMoreBefore}
+ onClick={onLoadMoreBefore}
+ >
+ <Translate>load newer transfers</Translate>
+ </button>
+ )}
+ <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+ <thead>
+ <tr>
+ <th>
+ <Translate>ID</Translate>
+ </th>
+ <th>
+ <Translate>Credit</Translate>
+ </th>
+ <th>
+ <Translate>Address</Translate>
+ </th>
+ <th>
+ <Translate>Exchange URL</Translate>
+ </th>
+ <th>
+ <Translate>Confirmed</Translate>
+ </th>
+ <th>
+ <Translate>Verified</Translate>
+ </th>
+ <th>
+ <Translate>Executed at</Translate>
+ </th>
+ <th />
+ </tr>
+ </thead>
+ <tbody>
+ {instances.map((i) => {
+ return (
+ <tr key={i.id}>
+ <td>{i.id}</td>
+ <td>{i.credit_amount}</td>
+ <td>{i.payto_uri}</td>
+ <td>{i.exchange_url}</td>
+ <td>{i.confirmed ? i18n`yes` : i18n`no`}</td>
+ <td>{i.verified ? i18n`yes` : i18n`no`}</td>
+ <td>
+ {i.execution_time
+ ? i.execution_time.t_s == "never"
+ ? i18n`never`
+ : format(
+ i.execution_time.t_s * 1000,
+ "yyyy/MM/dd HH:mm:ss"
+ )
+ : i18n`unknown`}
+ </td>
+ <td>
+ {i.verified === undefined ? (
+ <button
+ class="button is-danger is-small has-tooltip-left"
+ data-tooltip={i18n`delete selected transfer from the database`}
+ onClick={() => onDelete(i)}
+ >
+ Delete
+ </button>
+ ) : undefined}
+ </td>
+ </tr>
+ );
+ })}
+ </tbody>
+ </table>
+ {onLoadMoreAfter && (
+ <button
+ class="button is-fullwidth"
+ data-tooltip={i18n`load more transfer after the last one`}
+ disabled={!hasMoreAfter}
+ onClick={onLoadMoreAfter}
+ >
+ <Translate>load older transfers</Translate>
+ </button>
+ )}
+ </div>
+ );
+}
+
+function EmptyTable(): VNode {
+ return (
+ <div class="content has-text-grey has-text-centered">
+ <p>
+ <span class="icon is-large">
+ <i class="mdi mdi-emoticon-sad mdi-48px" />
+ </span>
+ </p>
+ <p>
+ <Translate>
+ There is no transfer yet, add more pressing the + sign
+ </Translate>
+ </p>
+ </div>
+ );
+}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/index.tsx
new file mode 100644
index 000000000..d8e2f60e9
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/index.tsx
@@ -0,0 +1,85 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 { Loading } from '../../../../components/exception/loading';
+import { MerchantBackend } from '../../../../declaration';
+import { HttpError } from '../../../../hooks/backend';
+import { useInstanceDetails } from '../../../../hooks/instance';
+import { useInstanceTransfers } from "../../../../hooks/transfer";
+import { ListPage } from './ListPage';
+
+interface Props {
+ onUnauthorized: () => VNode;
+ onLoadError: (error: HttpError) => VNode;
+ onNotFound: () => VNode;
+ onCreate: () => void;
+}
+interface Form {
+ verified?: 'yes' | 'no';
+ payto_uri?: string;
+}
+
+export default function ListTransfer({ onUnauthorized, onLoadError, onCreate, onNotFound }: Props): VNode {
+ const [form, setForm] = useState<Form>({ payto_uri: '' })
+ const setFilter = (s?: 'yes' | 'no') => setForm({ ...form, verified: s })
+
+ const [position, setPosition] = useState<string | undefined>(undefined)
+
+ const instance = useInstanceDetails()
+ const accounts = !instance.ok ? [] : instance.data.accounts.map(a => a.payto_uri)
+
+ const isVerifiedTransfers = form.verified === 'yes'
+ const isNonVerifiedTransfers = form.verified === 'no'
+ const isAllTransfers = form.verified === undefined
+
+ const result = useInstanceTransfers({
+ position,
+ payto_uri: form.payto_uri === '' ? undefined : form.payto_uri,
+ verified: form.verified,
+ }, (id) => setPosition(id))
+
+ 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 <ListPage
+ accounts={accounts}
+ transfers={result.data.transfers}
+ onLoadMoreBefore={result.isReachingStart ? result.loadMorePrev : undefined}
+ onLoadMoreAfter={result.isReachingEnd ? result.loadMore : undefined}
+ onCreate={onCreate}
+ onDelete={() => {null}}
+ // position={position} setPosition={setPosition}
+ onShowAll={() => setFilter(undefined)}
+ onShowUnverified={() => setFilter('no')}
+ onShowVerified={() => setFilter('yes')}
+ isAllTransfers={isAllTransfers}
+ isVerifiedTransfers={isVerifiedTransfers}
+ isNonVerifiedTransfers={isNonVerifiedTransfers}
+ payTo={form.payto_uri}
+ onChangePayTo={(p) => setForm(v => ({ ...v, payto_uri: p }))}
+ />
+
+}
+
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/transfers/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/transfers/update/index.tsx
new file mode 100644
index 000000000..caa808693
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/paths/instance/transfers/update/index.tsx
@@ -0,0 +1,26 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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';
+
+export default function UpdateTransfer():VNode {
+ return <div>order transfer page</div>
+} \ No newline at end of file