taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 7c7f32c5ce67f9774cd948389e087b9d853d577a
parent 64e124ee48ccfd694d6a3ffb885be1692c9ea9a1
Author: Sebastian <sebasjm@gmail.com>
Date:   Thu, 30 Oct 2025 09:49:26 -0300

wip orders

Diffstat:
Mpackages/bank-ui/src/pages/WithdrawalConfirmationQuestion.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx | 4++--
Mpackages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx | 114++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mpackages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx | 9+++++----
Mpackages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx | 61+++++--------------------------------------------------------
Mpackages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx | 3---
Mpackages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx | 276++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Mpackages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx | 45+++++++++++++++++++++++++++------------------
Mpackages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx | 4----
Mpackages/merchant-backoffice-ui/src/paths/instance/tokenfamilies/update/index.tsx | 3---
10 files changed, 265 insertions(+), 256 deletions(-)

diff --git a/packages/bank-ui/src/pages/WithdrawalConfirmationQuestion.tsx b/packages/bank-ui/src/pages/WithdrawalConfirmationQuestion.tsx @@ -141,7 +141,7 @@ export function WithdrawalConfirmationQuestion({ abort.onFail = (fail) => { switch (fail.case) { case HttpStatusCode.BadRequest: - return i18n.str``; + return i18n.str`Bad request`; case HttpStatusCode.NotFound: return i18n.str`The withdrawal operation has been aborted.`; case HttpStatusCode.Conflict: 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 @@ -54,7 +54,7 @@ import { rate } from "../../../../utils/amount.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; export interface Props { - onCreate: (d: TalerMerchantApi.PostOrderRequest) => void; + onCreated: (id:string) => void; onBack?: () => void; instanceConfig: InstanceConfig; instanceInventory: (TalerMerchantApi.ProductDetail & WithId)[]; @@ -733,7 +733,7 @@ export function CreatePage({ e.preventDefault(); }} > - remove + <i18n.Translate>remove</i18n.Translate> </button> } /> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx @@ -92,66 +92,66 @@ export default function OrderCreate({ onConfirm, onBack }: Props): VNode { return ( <Fragment> - <LocalNotificationBannerBulma notification={notification} /> <CreatePage onBack={onBack} - onCreate={(request: TalerMerchantApi.PostOrderRequest) => { - lib.instance - .createOrder(state.token, request) - .then((resp) => { - if (resp.type === "ok") { - return onConfirm(resp.body.order_id); - } else { - switch (resp.case) { - case HttpStatusCode.UnavailableForLegalReasons: { - setNotif({ - message: i18n.str`Could not create order`, - type: "ERROR", - description: i18n.str`No exchange would accept a payment because of KYC requirements.`, - }); - return; - } - case HttpStatusCode.Unauthorized: - case HttpStatusCode.Conflict: { - setNotif({ - message: i18n.str`Could not create order`, - type: "ERROR", - description: resp.detail?.hint, - }); - return; - } - case HttpStatusCode.Gone: { - setNotif({ - message: i18n.str`Could not create order`, - type: "ERROR", - description: i18n.str`Product with ID "${resp.body.product_id}" is out of stock.`, - }); - return; - } - case HttpStatusCode.NotFound: { - setNotif({ - message: i18n.str`Could not create order`, - type: "ERROR", - description: resp.detail?.hint, - }); - return; - } - default: { - assertUnreachable(resp); - } - } - } - }) - .catch((error) => { - setNotif({ - message: i18n.str`Could not create order`, - type: "ERROR", - description: - error instanceof Error ? error.message : String(error), - }); - }); - }} + onCreated={onConfirm} + // onCreate={(request: TalerMerchantApi.PostOrderRequest) => { + // lib.instance + // .createOrder(state.token, request) + // .then((resp) => { + // if (resp.type === "ok") { + // return onConfirm(resp.body.order_id); + // } else { + // switch (resp.case) { + // case HttpStatusCode.UnavailableForLegalReasons: { + // setNotif({ + // message: i18n.str`Could not create order`, + // type: "ERROR", + // description: i18n.str`No exchange would accept a payment because of KYC requirements.`, + // }); + // return; + // } + // case HttpStatusCode.Unauthorized: + // case HttpStatusCode.Conflict: { + // setNotif({ + // message: i18n.str`Could not create order`, + // type: "ERROR", + // description: resp.detail?.hint, + // }); + // return; + // } + // case HttpStatusCode.Gone: { + // setNotif({ + // message: i18n.str`Could not create order`, + // type: "ERROR", + // description: i18n.str`Product with ID "${resp.body.product_id}" is out of stock.`, + // }); + // return; + // } + // case HttpStatusCode.NotFound: { + // setNotif({ + // message: i18n.str`Could not create order`, + // type: "ERROR", + // description: resp.detail?.hint, + // }); + // return; + // } + // default: { + // assertUnreachable(resp); + // } + // } + // } + // }) + // .catch((error) => { + // setNotif({ + // message: i18n.str`Could not create order`, + // type: "ERROR", + // description: + // error instanceof Error ? error.message : String(error), + // }); + // }); + // }} instanceConfig={detailsResult.body} instanceInventory={inventoryResult.body} /> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx @@ -56,7 +56,7 @@ export interface Props { onBack: () => void; selected: Entity; id: string; - onRefund: (id: string, value: TalerMerchantApi.RefundRequest) => void; + onRefunded: () => void; } type Paid = TalerMerchantApi.CheckPaymentPaidResponse & { @@ -744,7 +744,7 @@ function UnpaidPage({ ); } -export function DetailPage({ id, selected, onRefund, onBack }: Props): VNode { +export function DetailPage({ id, selected, onRefunded, onBack }: Props): VNode { const [showRefund, setShowRefund] = useState<string | undefined>(undefined); const { i18n } = useTranslationContext(); const DetailByStatus = function () { @@ -773,9 +773,10 @@ export function DetailPage({ id, selected, onRefund, onBack }: Props): VNode { {showRefund && ( <RefundModal order={selected} + id={id} onCancel={() => setShowRefund(undefined)} - onConfirm={(value) => { - onRefund(showRefund, value); + onConfirm={() => { + onRefunded(); setShowRefund(undefined); }} /> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/index.tsx @@ -19,15 +19,14 @@ import { TalerErrorCode, assertUnreachable, } from "@gnu-taler/taler-util"; -import { LocalNotificationBannerBulma, useTranslationContext } from "@gnu-taler/web-util/browser"; +import { + useTranslationContext +} from "@gnu-taler/web-util/browser"; import { Fragment, VNode, h } from "preact"; -import { useState } from "preact/hooks"; import { ErrorLoadingMerchant } from "../../../../components/ErrorLoadingMerchant.js"; import { Loading } from "../../../../components/exception/loading.js"; -import { NotificationCard } from "../../../../components/menu/index.js"; import { useSessionContext } from "../../../../context/session.js"; import { useOrderDetails } from "../../../../hooks/order.js"; -import { Notification } from "../../../../utils/types.js"; import { LoginPage } from "../../../login/index.js"; import { NotFoundPageOrAdminCreate } from "../../../notfound/index.js"; import { DetailPage } from "./DetailPage.js"; @@ -40,8 +39,6 @@ export interface Props { export default function Update({ oid, onBack }: Props): VNode { const result = useOrderDetails(oid); - const { state, lib } = useSessionContext(); - const { i18n } = useTranslationContext(); if (!result) return <Loading />; @@ -54,7 +51,7 @@ export default function Update({ oid, onBack }: Props): VNode { return <NotFoundPageOrAdminCreate />; } case TalerErrorCode.MERCHANT_GENERIC_ORDER_UNKNOWN: { - return <i18n.Translate>Order unkown</i18n.Translate> + return <i18n.Translate>Order unknown</i18n.Translate>; } case HttpStatusCode.Unauthorized: { return <LoginPage />; @@ -67,59 +64,11 @@ export default function Update({ oid, onBack }: Props): VNode { return ( <Fragment> - <LocalNotificationBannerBulma notification={notification} /> <DetailPage onBack={onBack} id={oid} - onRefund={(id, value) => { - if (state.status !== "loggedIn") { - return; - } - lib.instance - .addRefund(state.token, id, value) - .then((resp) => { - if (resp.type === "ok") { - setNotif({ - message: i18n.str`Refund created successfully`, - type: "SUCCESS", - }); - } else { - switch (resp.case) { - case HttpStatusCode.UnavailableForLegalReasons: { - setNotif({ - message: i18n.str`Could not create the refund`, - type: "ERROR", - description: i18n.str`There are pending KYC requirements.` - }); - return; - } - case HttpStatusCode.Unauthorized: - case HttpStatusCode.Forbidden: - case HttpStatusCode.NotFound: - case HttpStatusCode.Conflict: - case HttpStatusCode.Gone: { - setNotif({ - message: i18n.str`Could not create the refund`, - type: "ERROR", - description: resp.detail?.hint, - }); - return; - } - default: { - assertUnreachable(resp) - } - } - } - }) - .catch((error) => - setNotif({ - message: i18n.str`Could not create the refund`, - type: "ERROR", - description: error instanceof Error ? error.message : String(error), - }), - ); - }} + onRefunded={() => {}} selected={result.body} /> </Fragment> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx @@ -36,7 +36,6 @@ export interface ListPageProps { onShowRefunded: () => void; onShowNotWired: () => void; onShowWired: () => void; - onCopyURL: (id: string) => void; isAllActive: string; isPaidActive: string; isNotPaidActive: string; @@ -64,7 +63,6 @@ export function ListPage({ onSelectOrder, onRefundOrder, jumpToDate, - onCopyURL, onShowAll, onShowPaid, onShowNotPaid, @@ -212,7 +210,6 @@ export function ListPage({ <CardTable orders={orders} onCreate={onCreate} - onCopyURL={onCopyURL} onSelect={onSelectOrder} onRefund={onRefundOrder} onLoadMoreAfter={onLoadMoreAfter} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx @@ -19,10 +19,23 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { Amounts, AmountString, MerchantContractVersion, TalerMerchantApi } from "@gnu-taler/taler-util"; -import { useTranslationContext } from "@gnu-taler/web-util/browser"; +import { + AccessToken, + Amounts, + AmountString, + HttpStatusCode, + MerchantContractVersion, + TalerErrorCode, + TalerMerchantApi, +} from "@gnu-taler/taler-util"; +import { + ButtonBetterBulma, + LocalNotificationBannerBulma, + useLocalNotificationBetter, + useTranslationContext, +} from "@gnu-taler/web-util/browser"; import { format } from "date-fns"; -import { VNode, h } from "preact"; +import { Fragment, VNode, h } from "preact"; import { StateUpdater, useState } from "preact/hooks"; import { FormErrors, @@ -45,7 +58,6 @@ type Entity = TalerMerchantApi.OrderHistoryEntry & WithId; interface Props { orders: Entity[]; onRefund: (value: Entity) => void; - onCopyURL: (id: string) => void; onCreate: () => void; onSelect: (order: Entity) => void; onLoadMoreBefore?: () => void; @@ -56,7 +68,6 @@ export function CardTable({ orders, onCreate, onRefund, - onCopyURL, onSelect, onLoadMoreAfter, onLoadMoreBefore, @@ -95,7 +106,6 @@ export function CardTable({ instances={orders} onSelect={onSelect} onRefund={onRefund} - onCopyURL={(o) => onCopyURL(o.id)} rowSelection={rowSelection} rowSelectionHandler={rowSelectionHandler} onLoadMoreAfter={onLoadMoreAfter} @@ -114,7 +124,6 @@ interface TableProps { rowSelection: string[]; instances: Entity[]; onRefund: (id: Entity) => void; - onCopyURL: (id: Entity) => void; onSelect: (id: Entity) => void; rowSelectionHandler: StateUpdater<string[]>; onLoadMoreBefore?: () => void; @@ -125,98 +134,123 @@ function Table({ instances, onSelect, onRefund, - onCopyURL, onLoadMoreAfter, onLoadMoreBefore, }: TableProps): VNode { const { i18n } = useTranslationContext(); const [settings] = usePreference(); + const { state: session, lib } = useSessionContext(); + const [notification, safeFunctionHandler] = useLocalNotificationBetter(); + const copyUrl = safeFunctionHandler((token: AccessToken, id: string) => + lib.instance.getOrderDetails(token, id), + ); + copyUrl.onSuccess = (success) => { + copyToClipboard(success.order_status_url); + }; + copyUrl.onFail = (fail) => { + switch (fail.case) { + case TalerErrorCode.MERCHANT_GENERIC_INSTANCE_UNKNOWN: + return i18n.str`The instance doesn't exist`; + case TalerErrorCode.MERCHANT_GENERIC_ORDER_UNKNOWN: + return i18n.str`The order doesn't exist`; + case HttpStatusCode.Unauthorized: + return i18n.str`Unauthorized.`; + } + }; return ( - <div class="table-container"> - {onLoadMoreBefore && ( - <button class="button is-fullwidth" onClick={onLoadMoreBefore}> - <i18n.Translate>Load first page</i18n.Translate> - </button> - )} - <table class="table is-striped is-hoverable is-fullwidth"> - <thead> - <tr> - <th style={{ minWidth: 100 }}> - <i18n.Translate>Date</i18n.Translate> - </th> - <th style={{ minWidth: 100 }}> - <i18n.Translate>Amount</i18n.Translate> - </th> - <th style={{ minWidth: 400 }}> - <i18n.Translate>Summary</i18n.Translate> - </th> - <th style={{ minWidth: 50 }} /> - </tr> - </thead> - <tbody> - {instances.map((i) => { - return ( - <tr key={i.id}> - <td - onClick={(): void => onSelect(i)} - style={{ cursor: "pointer" }} - > - {i.timestamp.t_s === "never" - ? i18n.str`Never` - : format( - new Date(i.timestamp.t_s * 1000), - datetimeFormatForSettings(settings), + <Fragment> + <LocalNotificationBannerBulma notification={notification} /> + + <div class="table-container"> + {onLoadMoreBefore && ( + <button class="button is-fullwidth" onClick={onLoadMoreBefore}> + <i18n.Translate>Load first page</i18n.Translate> + </button> + )} + <table class="table is-striped is-hoverable is-fullwidth"> + <thead> + <tr> + <th style={{ minWidth: 100 }}> + <i18n.Translate>Date</i18n.Translate> + </th> + <th style={{ minWidth: 100 }}> + <i18n.Translate>Amount</i18n.Translate> + </th> + <th style={{ minWidth: 400 }}> + <i18n.Translate>Summary</i18n.Translate> + </th> + <th style={{ minWidth: 50 }} /> + </tr> + </thead> + <tbody> + {instances.map((i) => { + return ( + <tr key={i.id}> + <td + onClick={(): void => onSelect(i)} + style={{ cursor: "pointer" }} + > + {i.timestamp.t_s === "never" + ? i18n.str`Never` + : format( + new Date(i.timestamp.t_s * 1000), + datetimeFormatForSettings(settings), + )} + </td> + <td + onClick={(): void => onSelect(i)} + style={{ cursor: "pointer" }} + > + {i.amount} + </td> + <td + onClick={(): void => onSelect(i)} + style={{ cursor: "pointer" }} + > + {i.summary} + </td> + <td class="is-actions-cell right-sticky"> + <div class="buttons is-right"> + {i.refundable && ( + <button + class="button is-small is-danger jb-modal" + type="button" + onClick={(): void => onRefund(i)} + > + <i18n.Translate>Refund</i18n.Translate> + </button> )} - </td> - <td - onClick={(): void => onSelect(i)} - style={{ cursor: "pointer" }} - > - {i.amount} - </td> - <td - onClick={(): void => onSelect(i)} - style={{ cursor: "pointer" }} - > - {i.summary} - </td> - <td class="is-actions-cell right-sticky"> - <div class="buttons is-right"> - {i.refundable && ( - <button - class="button is-small is-danger jb-modal" - type="button" - onClick={(): void => onRefund(i)} - > - <i18n.Translate>Refund</i18n.Translate> - </button> - )} - {!i.paid && ( - <button - class="button is-small is-info jb-modal" - type="button" - onClick={(): void => onCopyURL(i)} - > - <i18n.Translate>copy url</i18n.Translate> - </button> - )} - </div> - </td> - </tr> - ); - })} - </tbody> - </table> - {onLoadMoreAfter && ( - <button - class="button is-fullwidth" - data-tooltip={i18n.str`Load more orders after the last one`} - onClick={onLoadMoreAfter} - > - <i18n.Translate>Load next page</i18n.Translate> - </button> - )} - </div> + {!i.paid && ( + <ButtonBetterBulma + class="button is-small is-info jb-modal" + type="button" + onClick={ + !session.token + ? copyUrl + : copyUrl.withArgs(session.token, i.id) + } + > + <i18n.Translate>copy url</i18n.Translate> + </ButtonBetterBulma> + )} + </div> + </td> + </tr> + ); + })} + </tbody> + </table> + {onLoadMoreAfter && ( + <button + class="button is-fullwidth" + data-tooltip={i18n.str`Load more orders after the last one`} + onClick={onLoadMoreAfter} + > + <i18n.Translate>Load next page</i18n.Translate> + </button> + )} + </div> + </Fragment> ); } @@ -240,12 +274,14 @@ function EmptyTable(): VNode { interface RefundModalProps { onCancel: () => void; - onConfirm: (value: TalerMerchantApi.RefundRequest) => void; + onConfirm: () => void; order: TalerMerchantApi.MerchantOrderStatusResponse; + id: string; } export function RefundModal({ order, + id, onCancel, onConfirm, }: RefundModalProps): VNode { @@ -254,13 +290,18 @@ export function RefundModal({ const [settings] = usePreference(); const { i18n } = useTranslationContext(); // const [errors, setErrors] = useState<FormErrors<State>>({}); + const [notification, safeFunctionHandler] = useLocalNotificationBetter(); + const { state: session, lib } = useSessionContext(); let amount: AmountString; if (order.order_status === "paid") { - if (order.contract_terms.version !== undefined && + if ( + order.contract_terms.version !== undefined && order.contract_terms.version !== MerchantContractVersion.V0 ) { - return <div>Unsupported contract version {order.contract_terms.version}</div>; + return ( + <div>Unsupported contract version {order.contract_terms.version}</div> + ); } amount = order.contract_terms.amount; @@ -278,9 +319,7 @@ export function RefundModal({ Amounts.zeroOfCurrency(config.currency), ); const orderPrice = - order.order_status === "paid" - ? Amounts.parseOrThrow(amount!) - : undefined; + order.order_status === "paid" ? Amounts.parseOrThrow(amount!) : undefined; const totalRefundable = !orderPrice ? Amounts.zeroOfCurrency(totalRefunded.currency) : refunds.length @@ -308,10 +347,9 @@ export function RefundModal({ (k) => (errors as Record<string, unknown>)[k] !== undefined, ); - const validateAndConfirm = () => { - try { - if (!form.refund) return; - onConfirm({ + const req: TalerMerchantApi.RefundRequest | undefined = !form.refund + ? undefined + : { refund: Amounts.stringify( Amounts.add(Amounts.parse(form.refund)!, totalRefunded).amount, ), @@ -319,22 +357,40 @@ export function RefundModal({ form.description === undefined ? form.mainReason || "" : `${form.mainReason}: ${form.description}`, - }); - } catch (err) { - console.log(err); + }; + + const refund = safeFunctionHandler( + (token: AccessToken, id: string, request: TalerMerchantApi.RefundRequest) => + lib.instance.addRefund(token, id, request), + !session.token || !req ? undefined : [session.token, id, req], + ); + refund.onSuccess = onConfirm; + refund.onFail = (fail) => { + switch (fail.case) { + case HttpStatusCode.Unauthorized: + return i18n.str`Unauthorized`; + case HttpStatusCode.Forbidden: + return i18n.str`Forbidden`; + case HttpStatusCode.NotFound: + return i18n.str`Not found`; + case HttpStatusCode.Conflict: + return i18n.str`Conflict`; + case HttpStatusCode.Gone: + return i18n.str`Gone`; + case HttpStatusCode.UnavailableForLegalReasons: + return i18n.str`There are pending KYC requirements.`; } }; - //FIXME: parameters in the translation return ( <ConfirmModal description="refund" danger active - disabled={!isRefundable || hasErrors} onCancel={onCancel} - onConfirm={validateAndConfirm} + confirm={refund} > + <LocalNotificationBannerBulma notification={notification} /> {refunds.length > 0 && ( <div class="columns"> <div class="column is-12"> @@ -417,3 +473,7 @@ export function RefundModal({ </ConfirmModal> ); } + +async function copyToClipboard(text: string): Promise<void> { + return navigator.clipboard.writeText(text); +} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx @@ -28,7 +28,11 @@ import { assertUnreachable, stringifyPayUri, } from "@gnu-taler/taler-util"; -import { LocalNotificationBannerBulma, useTranslationContext } from "@gnu-taler/web-util/browser"; +import { + LocalNotificationBannerBulma, + useLocalNotificationBetter, + useTranslationContext, +} from "@gnu-taler/web-util/browser"; import { VNode, h } from "preact"; import { useState } from "preact/hooks"; import { ErrorLoadingMerchant } from "../../../../components/ErrorLoadingMerchant.js"; @@ -64,9 +68,8 @@ export default function OrderList({ onCreate, onSelect }: Props): VNode { const result = useInstanceOrders(filter, (d) => setFilter({ ...filter, position: d }), ); - const { state, lib } = useSessionContext(); - - + const [notification, safeFunctionHandler] = useLocalNotificationBetter(); + const { state: session, lib } = useSessionContext(); const { i18n } = useTranslationContext(); @@ -102,15 +105,26 @@ export default function OrderList({ onCreate, onSelect }: Props): VNode { ? "is-active" : ""; + const create = safeFunctionHandler( + lib.instance.informWireTransfer, + !session.token || !!errors ? undefined : [session.token, data], + ); + create.onSuccess = onCreated; + create.onFail = (fail) => { + switch (fail.case) { + case HttpStatusCode.Unauthorized: + return i18n.str`Unauthorized.`; + case HttpStatusCode.NotFound: + return i18n.str`Not found.`; + case HttpStatusCode.Conflict: + return i18n.str`Conflict.`; + } + }; return ( <section class="section is-main-section"> <LocalNotificationBannerBulma notification={notification} /> <JumpToElementById - testIfExist={async (order) => { - const resp = await lib.instance.getOrderDetails(state.token, order); - return resp.type === "ok"; - }} onSelect={onSelect} description={i18n.str`Jump to order with the given product ID`} placeholder={i18n.str`Order id`} @@ -130,12 +144,6 @@ export default function OrderList({ onCreate, onSelect }: Props): VNode { isRefundedActive={isRefundedActive} jumpToDate={filter.date} onSelectDate={setNewDate} - onCopyURL={async (id) => { - const resp = await lib.instance.getOrderDetails(state.token, id); - if (resp.type === "ok") { - copyToClipboard(resp.body.order_status_url); - } - }} onCreate={onCreate} onShowAll={() => setFilter({})} onShowNotPaid={() => setFilter({ paid: false })} @@ -205,11 +213,11 @@ export default function OrderList({ onCreate, onSelect }: Props): VNode { interface RefundProps { id: string; onCancel: () => void; - onConfirm: (m: TalerMerchantApi.RefundRequest) => void; + onConfirm: () => void; } function RefundModalForTable({ id, onConfirm, onCancel }: RefundProps): VNode { - const {i18n} = useTranslationContext(); + const { i18n } = useTranslationContext(); const result = useOrderDetails(id); if (!result) return <Loading />; @@ -219,10 +227,10 @@ function RefundModalForTable({ id, onConfirm, onCancel }: RefundProps): VNode { if (result.type === "fail") { switch (result.case) { case TalerErrorCode.MERCHANT_GENERIC_INSTANCE_UNKNOWN: { - return <i18n.Translate>Instance unkown</i18n.Translate> + return <i18n.Translate>Instance unkown</i18n.Translate>; } case TalerErrorCode.MERCHANT_GENERIC_ORDER_UNKNOWN: { - return <i18n.Translate>Order unkown</i18n.Translate> + return <i18n.Translate>Order unkown</i18n.Translate>; } case HttpStatusCode.Unauthorized: { return <LoginPage />; @@ -235,6 +243,7 @@ function RefundModalForTable({ id, onConfirm, onCancel }: RefundProps): VNode { return ( <RefundModal + id={id} order={result.body} onCancel={onCancel} onConfirm={onConfirm} 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 @@ -83,10 +83,6 @@ export default function ListTemplates({ <LocalNotificationBannerBulma notification={notification} /> <JumpToElementById - testIfExist={async (id) => { - const resp = await lib.instance.getTemplateDetails(state.token, id); - return resp.type === "ok"; - }} onSelect={onSelect} description={i18n.str`Jump to template with the given template ID`} placeholder={i18n.str`Template identification`} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/tokenfamilies/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/tokenfamilies/update/index.tsx @@ -27,13 +27,10 @@ import { } from "@gnu-taler/taler-util"; import { LocalNotificationBannerBulma, useTranslationContext } from "@gnu-taler/web-util/browser"; import { Fragment, VNode, h } from "preact"; -import { useState } from "preact/hooks"; import { ErrorLoadingMerchant } from "../../../../components/ErrorLoadingMerchant.js"; import { Loading } from "../../../../components/exception/loading.js"; -import { NotificationCard } from "../../../../components/menu/index.js"; import { useSessionContext } from "../../../../context/session.js"; import { useTokenFamilyDetails } from "../../../../hooks/tokenfamily.js"; -import { Notification } from "../../../../utils/types.js"; import { LoginPage } from "../../../login/index.js"; import { NotFoundPageOrAdminCreate } from "../../../notfound/index.js"; import { UpdatePage } from "./UpdatePage.js";