commit 6c60ee2c41a34dec46d3cc91f401f04822c63c13
parent 8b0453c244374b6af2e2039a89650cd066e6394e
Author: Sebastian <sebasjm@taler-systems.com>
Date: Thu, 27 Nov 2025 13:04:01 -0300
fix incoming api
Diffstat:
4 files changed, 197 insertions(+), 150 deletions(-)
diff --git a/packages/merchant-backoffice-ui/src/hooks/transfer.ts b/packages/merchant-backoffice-ui/src/hooks/transfer.ts
@@ -88,10 +88,10 @@ export function useInstanceIncomingTransfers(
if (data.type !== "ok") return data;
return buildPaginatedResult(
- data.body.transfers,
+ data.body.incoming,
args?.position,
updatePosition,
- (d) => String(d.transfer_serial_id),
+ (d) => String(d.wtid),
PAGINATED_LIST_REQUEST,
);
}
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
@@ -24,12 +24,13 @@ import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { h, VNode } from "preact";
import { FormProvider } from "../../../../components/form/FormProvider.js";
import { InputSelector } from "../../../../components/form/InputSelector.js";
-import { CardTable } from "./Table.js";
+import { CardTableIncoming, CardTableVerified } from "./Table.js";
const TALER_SCREEN_ID = 71;
export interface Props {
transfers: TalerMerchantApi.TransferDetails[];
+ incomings: TalerMerchantApi.IncomingTransferDetails[];
onLoadMoreBefore?: () => void;
onLoadMoreAfter?: () => void;
// onShowAll: () => void;
@@ -49,6 +50,7 @@ export function ListPage({
payTo,
onChangePayTo,
transfers,
+ incomings,
// onCreate,
// onDelete,
accounts,
@@ -78,9 +80,9 @@ export function ListPage({
label={i18n.str`Bank account`}
values={accounts}
fromStr={(d) => {
- const idx = accounts.indexOf(d)
+ const idx = accounts.indexOf(d);
if (idx === -1) return undefined;
- return d
+ return d;
}}
placeholder={i18n.str`All accounts`}
tooltip={i18n.str`Filter by account address`}
@@ -113,17 +115,26 @@ export function ListPage({
</li>
</ul>
</div>
- <CardTable
- transfers={transfers.map((o) => ({
- ...o,
- id: String(o.transfer_serial_id),
- }))}
- accounts={accounts}
- // onCreate={onCreate}
- // onDelete={onDelete}
- onLoadMoreBefore={onLoadMoreBefore}
- onLoadMoreAfter={onLoadMoreAfter}
- />
+
+ {isNonVerifiedTransfers ? (
+ <CardTableIncoming
+ transfers={incomings.map((o) => ({
+ ...o,
+ id: String(o.wtid),
+ }))}
+ onLoadMoreBefore={onLoadMoreBefore}
+ onLoadMoreAfter={onLoadMoreAfter}
+ />
+ ) : (
+ <CardTableVerified
+ transfers={transfers.map((o) => ({
+ ...o,
+ id: String(o.wtid),
+ }))}
+ onLoadMoreBefore={onLoadMoreBefore}
+ onLoadMoreAfter={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
@@ -23,37 +23,27 @@ import { TalerMerchantApi } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { format } from "date-fns";
import { h, VNode } from "preact";
-import { StateUpdater, useState } from "preact/hooks";
+import { WithId } from "../../../../declaration.js";
import {
datetimeFormatForSettings,
usePreference,
} from "../../../../hooks/preference.js";
-import { WithId } from "../../../../declaration.js";
const TALER_SCREEN_ID = 72;
-type Entity = TalerMerchantApi.TransferDetails & WithId;
-
-interface Props {
- transfers: Entity[];
- // onDelete: (id: Entity) => void;
- // onCreate: () => void;
- accounts: string[];
+interface TablePropsIncoming {
+ transfers: (TalerMerchantApi.IncomingTransferDetails & WithId)[];
onLoadMoreBefore?: () => void;
onLoadMoreAfter?: () => void;
}
-export function CardTable({
+export function CardTableIncoming({
transfers,
- // onCreate,
- // onDelete,
onLoadMoreAfter,
onLoadMoreBefore,
-}: Props): VNode {
- const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
-
+}: TablePropsIncoming): VNode {
const { i18n } = useTranslationContext();
-
+ const [settings] = usePreference();
return (
<div class="card has-table">
<header class="card-header">
@@ -61,38 +51,79 @@ export function CardTable({
<span class="icon">
<i class="mdi mdi-arrow-left-right" />
</span>
- <i18n.Translate>Wire transfers</i18n.Translate>
+ <i18n.Translate>Incoming wire transfers</i18n.Translate>
</p>
- {/* <div class="card-header-icon" aria-label="more options">
- <span
- class="has-tooltip-left"
- data-tooltip={i18n.str`Add new transfer`}
- >
- <button
- type="button"
- class="button is-info"
- onClick={onCreate}
- accessKey="+"
- >
- <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}
- />
+ <div class="table-container">
+ {onLoadMoreBefore && (
+ <button
+ type="button"
+ class="button is-fullwidth"
+ data-tooltip={i18n.str`Load more wire transfers preceding the first one`}
+ onClick={onLoadMoreBefore}
+ >
+ <i18n.Translate>Load first page</i18n.Translate>
+ </button>
+ )}
+ <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+ <thead>
+ <tr>
+ <th>
+ <i18n.Translate>ID</i18n.Translate>
+ </th>
+ <th>
+ <i18n.Translate>Expected credit</i18n.Translate>
+ </th>
+ <th>
+ <i18n.Translate>Confirmed</i18n.Translate>
+ </th>
+ <th>
+ <i18n.Translate>Validated</i18n.Translate>
+ </th>
+ <th>
+ <i18n.Translate>Executed on</i18n.Translate>
+ </th>
+ {/* <th /> */}
+ </tr>
+ </thead>
+ <tbody>
+ {transfers.map((i) => {
+ return (
+ <tr key={i.id}>
+ <td title={i.wtid}>{i.wtid.substring(0, 16)}...</td>
+ <td>{i.expected_credit_amount}</td>
+ <td>{i.confirmed ? i18n.str`yes` : i18n.str`no`}</td>
+ <td>{i.validated ? i18n.str`yes` : i18n.str`no`}</td>
+ <td>
+ {i.execution_time
+ ? i.execution_time.t_s == "never"
+ ? i18n.str`never`
+ : format(
+ i.execution_time.t_s * 1000,
+ datetimeFormatForSettings(settings),
+ )
+ : i18n.str`unknown`}
+ </td>
+ </tr>
+ );
+ })}
+ </tbody>
+ </table>
+ {onLoadMoreAfter && (
+ <button
+ type="button"
+ class="button is-fullwidth"
+ data-tooltip={i18n.str`Load more transfers after the last one`}
+ onClick={onLoadMoreAfter}
+ >
+ <i18n.Translate>Load next page</i18n.Translate>
+ </button>
+ )}
+ </div>
) : (
<EmptyTable />
)}
@@ -102,101 +133,106 @@ export function CardTable({
</div>
);
}
-interface TableProps {
- rowSelection: string[];
- instances: Entity[];
- // onDelete: (id: Entity) => void;
- rowSelectionHandler: StateUpdater<string[]>;
+
+interface TablePropsVerified {
+ transfers: (TalerMerchantApi.TransferDetails & WithId)[];
onLoadMoreBefore?: () => void;
onLoadMoreAfter?: () => void;
}
-function Table({
- instances,
+export function CardTableVerified({
+ transfers,
onLoadMoreAfter,
- // onDelete,
onLoadMoreBefore,
-}: TableProps): VNode {
+}: TablePropsVerified): VNode {
const { i18n } = useTranslationContext();
const [settings] = usePreference();
return (
- <div class="table-container">
- {onLoadMoreBefore && (
- <button
- type="button"
- class="button is-fullwidth"
- data-tooltip={i18n.str`Load more wire transfers preceding the first one`}
- onClick={onLoadMoreBefore}
- >
- <i18n.Translate>Load first page</i18n.Translate>
- </button>
- )}
- <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
- <thead>
- <tr>
- <th>
- <i18n.Translate>ID</i18n.Translate>
- </th>
- <th>
- <i18n.Translate>Credit</i18n.Translate>
- </th>
- <th>
- <i18n.Translate>Confirmed</i18n.Translate>
- </th>
- <th>
- <i18n.Translate>Verified</i18n.Translate>
- </th>
- <th>
- <i18n.Translate>Executed on</i18n.Translate>
- </th>
- {/* <th /> */}
- </tr>
- </thead>
- <tbody>
- {instances.map((i) => {
- return (
- <tr key={i.id}>
- <td title={i.wtid}>{i.wtid.substring(0, 16)}...</td>
- <td>{i.credit_amount}</td>
- <td>{i.confirmed ? i18n.str`yes` : i18n.str`no`}</td>
- <td>{i.verified ? i18n.str`yes` : i18n.str`no`}</td>
- <td>
- {i.execution_time
- ? i.execution_time.t_s == "never"
- ? i18n.str`never`
- : format(
- i.execution_time.t_s * 1000,
- datetimeFormatForSettings(settings),
- )
- : i18n.str`unknown`}
- </td>
- {/* <td>
- {i.verified !== true ? (
- <button
- type="button"
- class="button is-danger is-small has-tooltip-left"
- data-tooltip={i18n.str`Delete selected transfer from the database`}
- onClick={() => onDelete(i)}
- >
- <i18n.Translate>Delete</i18n.Translate>
- </button>
- ) : undefined}
- </td> */}
- </tr>
- );
- })}
- </tbody>
- </table>
- {onLoadMoreAfter && (
- <button
- type="button"
- class="button is-fullwidth"
- data-tooltip={i18n.str`Load more transfers after the last one`}
- onClick={onLoadMoreAfter}
- >
- <i18n.Translate>Load next page</i18n.Translate>
- </button>
- )}
+ <div class="card has-table">
+ <header class="card-header">
+ <p class="card-header-title">
+ <span class="icon">
+ <i class="mdi mdi-arrow-left-right" />
+ </span>
+ <i18n.Translate>Verified wire transfers</i18n.Translate>
+ </p>
+ </header>
+ <div class="card-content">
+ <div class="b-table has-pagination">
+ <div class="table-wrapper has-mobile-cards">
+ {transfers.length > 0 ? (
+ <div class="table-container">
+ {onLoadMoreBefore && (
+ <button
+ type="button"
+ class="button is-fullwidth"
+ data-tooltip={i18n.str`Load more wire transfers preceding the first one`}
+ onClick={onLoadMoreBefore}
+ >
+ <i18n.Translate>Load first page</i18n.Translate>
+ </button>
+ )}
+ <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+ <thead>
+ <tr>
+ <th>
+ <i18n.Translate>ID</i18n.Translate>
+ </th>
+ <th>
+ <i18n.Translate>Amount</i18n.Translate>
+ </th>
+ <th>
+ <i18n.Translate>Confirmed</i18n.Translate>
+ </th>
+ <th>
+ <i18n.Translate>Verified</i18n.Translate>
+ </th>
+ <th>
+ <i18n.Translate>Executed on</i18n.Translate>
+ </th>
+ {/* <th /> */}
+ </tr>
+ </thead>
+ <tbody>
+ {transfers.map((i) => {
+ return (
+ <tr key={i.id}>
+ <td title={i.wtid}>{i.wtid.substring(0, 16)}...</td>
+ <td>{i.credit_amount}</td>
+ <td>{i.confirmed ? i18n.str`yes` : i18n.str`no`}</td>
+ <td>{i.verified ? i18n.str`yes` : i18n.str`no`}</td>
+ <td>
+ {i.execution_time
+ ? i.execution_time.t_s == "never"
+ ? i18n.str`never`
+ : format(
+ i.execution_time.t_s * 1000,
+ datetimeFormatForSettings(settings),
+ )
+ : i18n.str`unknown`}
+ </td>
+ </tr>
+ );
+ })}
+ </tbody>
+ </table>
+ {onLoadMoreAfter && (
+ <button
+ type="button"
+ class="button is-fullwidth"
+ data-tooltip={i18n.str`Load more transfers after the last one`}
+ onClick={onLoadMoreAfter}
+ >
+ <i18n.Translate>Load next page</i18n.Translate>
+ </button>
+ )}
+ </div>
+ ) : (
+ <EmptyTable />
+ )}
+ </div>
+ </div>
+ </div>
</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
@@ -21,14 +21,13 @@
import {
HttpStatusCode,
+ IncomingTransferDetails,
TalerError,
TransferDetails,
assertUnreachable,
} from "@gnu-taler/taler-util";
import {
- LocalNotificationBannerBulma,
- PaginatedResult,
- useLocalNotificationBetter,
+ PaginatedResult
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useEffect, useState } from "preact/hooks";
@@ -67,7 +66,7 @@ export default function ListTransfer({}: Props): VNode {
!instance || instance instanceof TalerError || instance.type === "fail"
? []
: instance.body.accounts.map((a) => a.payto_uri);
- const [form, setForm] = useState<Form>({ payto_uri: "" });
+ const [form, setForm] = useState<Form>({ payto_uri: "", verified: true });
const shoulUseDefaultAccount = accounts.length === 1;
useEffect(() => {
@@ -80,7 +79,7 @@ export default function ListTransfer({}: Props): VNode {
// const isNonVerifiedTransfers = form.verified === false;
// const isAllTransfers = form.verified === undefined;
- let incoming: PaginatedResult<TransferDetails[]>;
+ let incoming: PaginatedResult<IncomingTransferDetails[]>;
{
const result = useInstanceIncomingTransfers(
{
@@ -147,7 +146,8 @@ export default function ListTransfer({}: Props): VNode {
<ListPage
accounts={accounts}
- transfers={show.body}
+ transfers={confirmed.body}
+ incomings={incoming.body}
onLoadMoreBefore={show.loadFirst}
onLoadMoreAfter={show.loadNext}
// onShowAll={() => setFilter(undefined)}