diff options
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx')
-rw-r--r-- | packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx | 139 |
1 files changed, 67 insertions, 72 deletions
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 index 02d5b0bfc..5ece34409 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx @@ -1,6 +1,6 @@ /* This file is part of GNU Taler - (C) 2021 Taler Systems S.A. + (C) 2021-2024 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 @@ -19,9 +19,12 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { Amounts } from "@gnu-taler/taler-util"; +import { Amounts, 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 { VNode, h } from "preact"; import { StateUpdater, useState } from "preact/hooks"; import { FormErrors, @@ -32,12 +35,14 @@ import { InputCurrency } from "../../../../components/form/InputCurrency.js"; import { InputGroup } from "../../../../components/form/InputGroup.js"; import { InputSelector } from "../../../../components/form/InputSelector.js"; import { ConfirmModal } from "../../../../components/modal/index.js"; -import { useConfigContext } from "../../../../context/config.js"; -import { MerchantBackend, WithId } from "../../../../declaration.js"; -import { Translate, useTranslator } from "../../../../i18n/index.js"; +import { useSessionContext } from "../../../../context/session.js"; +import { + datetimeFormatForSettings, + usePreference, +} from "../../../../hooks/preference.js"; import { mergeRefunds } from "../../../../utils/amount.js"; -type Entity = MerchantBackend.Orders.OrderHistoryEntry & WithId; +type Entity = TalerMerchantApi.OrderHistoryEntry & WithId; interface Props { orders: Entity[]; onRefund: (value: Entity) => void; @@ -45,8 +50,6 @@ interface Props { onCreate: () => void; onSelect: (order: Entity) => void; onLoadMoreBefore?: () => void; - hasMoreBefore?: boolean; - hasMoreAfter?: boolean; onLoadMoreAfter?: () => void; } @@ -58,12 +61,10 @@ export function CardTable({ onSelect, onLoadMoreAfter, onLoadMoreBefore, - hasMoreAfter, - hasMoreBefore, }: Props): VNode { const [rowSelection, rowSelectionHandler] = useState<string[]>([]); - const i18n = useTranslator(); + const { i18n } = useTranslationContext(); return ( <div class="card has-table"> @@ -72,13 +73,13 @@ export function CardTable({ <span class="icon"> <i class="mdi mdi-cash-register" /> </span> - <Translate>Orders</Translate> + <i18n.Translate>Orders</i18n.Translate> </p> <div class="card-header-icon" aria-label="more options" /> <div class="card-header-icon" aria-label="more options"> - <span class="has-tooltip-left" data-tooltip={i18n`create order`}> + <span class="has-tooltip-left" data-tooltip={i18n.str`create order`}> <button class="button is-info" type="button" onClick={onCreate}> <span class="icon is-small"> <i class="mdi mdi-plus mdi-36px" /> @@ -100,8 +101,6 @@ export function CardTable({ rowSelectionHandler={rowSelectionHandler} onLoadMoreAfter={onLoadMoreAfter} onLoadMoreBefore={onLoadMoreBefore} - hasMoreAfter={hasMoreAfter} - hasMoreBefore={hasMoreBefore} /> ) : ( <EmptyTable /> @@ -120,8 +119,6 @@ interface TableProps { onSelect: (id: Entity) => void; rowSelectionHandler: StateUpdater<string[]>; onLoadMoreBefore?: () => void; - hasMoreBefore?: boolean; - hasMoreAfter?: boolean; onLoadMoreAfter?: () => void; } @@ -132,31 +129,27 @@ function Table({ onCopyURL, onLoadMoreAfter, onLoadMoreBefore, - hasMoreAfter, - hasMoreBefore, }: TableProps): VNode { + const { i18n } = useTranslationContext(); + const [settings] = usePreference(); return ( <div class="table-container"> {onLoadMoreBefore && ( - <button - class="button is-fullwidth" - disabled={!hasMoreBefore} - onClick={onLoadMoreBefore} - > - <Translate>load newer orders</Translate> + <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 }}> - <Translate>Date</Translate> + <i18n.Translate>Date</i18n.Translate> </th> <th style={{ minWidth: 100 }}> - <Translate>Amount</Translate> + <i18n.Translate>Amount</i18n.Translate> </th> <th style={{ minWidth: 400 }}> - <Translate>Summary</Translate> + <i18n.Translate>Summary</i18n.Translate> </th> <th style={{ minWidth: 50 }} /> </tr> @@ -173,7 +166,7 @@ function Table({ ? "never" : format( new Date(i.timestamp.t_s * 1000), - "yyyy/MM/dd HH:mm:ss" + datetimeFormatForSettings(settings), )} </td> <td @@ -196,7 +189,7 @@ function Table({ type="button" onClick={(): void => onRefund(i)} > - <Translate>Refund</Translate> + <i18n.Translate>Refund</i18n.Translate> </button> )} {!i.paid && ( @@ -205,7 +198,7 @@ function Table({ type="button" onClick={(): void => onCopyURL(i)} > - <Translate>copy url</Translate> + <i18n.Translate>copy url</i18n.Translate> </button> )} </div> @@ -216,12 +209,10 @@ function Table({ </tbody> </table> {onLoadMoreAfter && ( - <button - class="button is-fullwidth" - disabled={!hasMoreAfter} - onClick={onLoadMoreAfter} - > - <Translate>load older orders</Translate> + <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> @@ -229,15 +220,18 @@ function Table({ } function EmptyTable(): VNode { + const { i18n } = useTranslationContext(); return ( <div class="content has-text-grey has-text-centered"> <p> <span class="icon is-large"> - <i class="mdi mdi-emoticon-sad mdi-48px" /> + <i class="mdi mdi-magnify mdi-48px" /> </span> </p> <p> - <Translate>No orders have been found matching your query!</Translate> + <i18n.Translate> + No orders have been found matching your query! + </i18n.Translate> </p> </div> ); @@ -245,8 +239,8 @@ function EmptyTable(): VNode { interface RefundModalProps { onCancel: () => void; - onConfirm: (value: MerchantBackend.Orders.RefundRequest) => void; - order: MerchantBackend.Orders.MerchantOrderStatusResponse; + onConfirm: (value: TalerMerchantApi.RefundRequest) => void; + order: TalerMerchantApi.MerchantOrderStatusResponse; } export function RefundModal({ @@ -256,19 +250,20 @@ export function RefundModal({ }: RefundModalProps): VNode { type State = { mainReason?: string; description?: string; refund?: string }; const [form, setValue] = useState<State>({}); - const i18n = useTranslator(); + const [settings] = usePreference(); + const { i18n } = useTranslationContext(); // const [errors, setErrors] = useState<FormErrors<State>>({}); const refunds = ( order.order_status === "paid" ? order.refund_details : [] ).reduce(mergeRefunds, []); - const config = useConfigContext(); + const { config } = useSessionContext(); const totalRefunded = refunds .map((r) => r.amount) .reduce( (p, c) => Amounts.add(p, Amounts.parseOrThrow(c)).amount, - Amounts.zeroOfCurrency(config.currency) + Amounts.zeroOfCurrency(config.currency), ); const orderPrice = order.order_status === "paid" @@ -277,28 +272,28 @@ export function RefundModal({ const totalRefundable = !orderPrice ? Amounts.zeroOfCurrency(totalRefunded.currency) : refunds.length - ? Amounts.sub(orderPrice, totalRefunded).amount - : orderPrice; + ? Amounts.sub(orderPrice, totalRefunded).amount + : orderPrice; const isRefundable = Amounts.isNonZero(totalRefundable); - const duplicatedText = i18n`duplicated`; + const duplicatedText = i18n.str`duplicated`; const errors: FormErrors<State> = { - mainReason: !form.mainReason ? i18n`required` : undefined, + mainReason: !form.mainReason ? i18n.str`required` : undefined, description: !form.description && form.mainReason !== duplicatedText - ? i18n`required` + ? i18n.str`required` : undefined, refund: !form.refund - ? i18n`required` + ? i18n.str`required` : !Amounts.parse(form.refund) - ? i18n`invalid format` - : Amounts.cmp(totalRefundable, Amounts.parse(form.refund)!) === -1 - ? i18n`this value exceed the refundable amount` - : undefined, + ? i18n.str`invalid format` + : Amounts.cmp(totalRefundable, Amounts.parse(form.refund)!) === -1 + ? i18n.str`this value exceed the refundable amount` + : undefined, }; const hasErrors = Object.keys(errors).some( - (k) => (errors as any)[k] !== undefined + (k) => (errors as Record<string, unknown>)[k] !== undefined, ); const validateAndConfirm = () => { @@ -306,7 +301,7 @@ export function RefundModal({ if (!form.refund) return; onConfirm({ refund: Amounts.stringify( - Amounts.add(Amounts.parse(form.refund)!, totalRefunded).amount + Amounts.add(Amounts.parse(form.refund)!, totalRefunded).amount, ), reason: form.description === undefined @@ -339,13 +334,13 @@ export function RefundModal({ <thead> <tr> <th> - <Translate>date</Translate> + <i18n.Translate>date</i18n.Translate> </th> <th> - <Translate>amount</Translate> + <i18n.Translate>amount</i18n.Translate> </th> <th> - <Translate>reason</Translate> + <i18n.Translate>reason</i18n.Translate> </th> </tr> </thead> @@ -358,7 +353,7 @@ export function RefundModal({ ? "never" : format( new Date(r.timestamp.t_s * 1000), - "yyyy-MM-dd HH:mm:ss" + datetimeFormatForSettings(settings), )} </td> <td>{r.amount}</td> @@ -377,32 +372,32 @@ export function RefundModal({ <FormProvider<State> errors={errors} object={form} - valueHandler={(d) => setValue(d as any)} + valueHandler={(d) => setValue(d)} > <InputCurrency<State> name="refund" - label={i18n`Refund`} - tooltip={i18n`amount to be refunded`} + label={i18n.str`Refund`} + tooltip={i18n.str`amount to be refunded`} > - <Translate>Max refundable:</Translate>{" "} + <i18n.Translate>Max refundable:</i18n.Translate>{" "} {Amounts.stringify(totalRefundable)} </InputCurrency> <InputSelector name="mainReason" - label={i18n`Reason`} + label={i18n.str`Reason`} values={[ - i18n`Choose one...`, + i18n.str`Choose one...`, duplicatedText, - i18n`requested by the customer`, - i18n`other`, + i18n.str`requested by the customer`, + i18n.str`other`, ]} - tooltip={i18n`why this order is being refunded`} + tooltip={i18n.str`why this order is being refunded`} /> {form.mainReason && form.mainReason !== duplicatedText ? ( <Input<State> - label={i18n`Description`} + label={i18n.str`Description`} name="description" - tooltip={i18n`more information to give context`} + tooltip={i18n.str`more information to give context`} /> ) : undefined} </FormProvider> |