diff options
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/orders')
9 files changed, 205 insertions, 91 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx index fcf611c3c..bd9f65718 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx @@ -42,12 +42,13 @@ function createExample<Props>( export const Example = createExample(TestedComponent, { instanceConfig: { - default_max_deposit_fee: "", - default_max_wire_fee: "", default_pay_delay: { d_us: 1000 * 1000 * 60 * 60, //one hour }, - default_wire_fee_amortization: 1, + default_wire_transfer_delay: { + d_us: 1000 * 1000 * 60 * 60, //one hour + }, + use_stefan: true, }, instanceInventory: [ { 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 index fa9347c6e..ea2cf849a 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx @@ -44,6 +44,7 @@ import { OrderCreateSchema as schema } from "../../../../schemas/index.js"; import { rate } from "../../../../utils/amount.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; import { useSettings } from "../../../../hooks/useSettings.js"; +import { InputToggle } from "../../../../components/form/InputToggle.js"; interface Props { onCreate: (d: MerchantBackend.Orders.PostOrderRequest) => void; @@ -52,34 +53,38 @@ interface Props { instanceInventory: (MerchantBackend.Products.ProductDetail & WithId)[]; } interface InstanceConfig { - default_max_wire_fee: string; - default_max_deposit_fee: string; - default_wire_fee_amortization: number; + use_stefan: boolean; default_pay_delay: Duration; + default_wire_transfer_delay: Duration; } -function with_defaults(config: InstanceConfig): Partial<Entity> { +function with_defaults(config: InstanceConfig, currency: string): Partial<Entity> { const defaultPayDeadline = !config.default_pay_delay || config.default_pay_delay.d_us === "forever" ? undefined : add(new Date(), { seconds: config.default_pay_delay.d_us / (1000 * 1000), }); + const defaultWireDeadline = + !config.default_wire_transfer_delay || config.default_wire_transfer_delay.d_us === "forever" + ? undefined + : add(new Date(), { + seconds: config.default_wire_transfer_delay.d_us / (1000 * 1000), + }); return { inventoryProducts: {}, products: [], pricing: {}, payments: { - max_wire_fee: config.default_max_wire_fee, - max_fee: config.default_max_deposit_fee, - wire_fee_amortization: config.default_wire_fee_amortization, + max_fee: undefined, pay_deadline: defaultPayDeadline, refund_deadline: defaultPayDeadline, createToken: true, + wire_transfer_deadline: defaultWireDeadline, }, shipping: {}, - extra: "", + extra: {}, }; } @@ -107,8 +112,6 @@ interface Payments { wire_transfer_deadline?: Date; auto_refund_deadline?: Date; max_fee?: string; - max_wire_fee?: string; - wire_fee_amortization?: number; createToken: boolean; minimum_age?: number; } @@ -118,7 +121,7 @@ interface Entity { pricing: Partial<Pricing>; payments: Partial<Payments>; shipping: Partial<Shipping>; - extra: string; + extra: Record<string, string>; } const stringIsValidJSON = (value: string) => { @@ -136,8 +139,9 @@ export function CreatePage({ instanceConfig, instanceInventory, }: Props): VNode { - const [value, valueHandler] = useState(with_defaults(instanceConfig)); const config = useConfigContext(); + const instance_default = with_defaults(instanceConfig, config.currency) + const [value, valueHandler] = useState(instance_default); const zero = Amounts.zeroOfCurrency(config.currency); const [settings] = useSettings() const inventoryList = Object.values(value.inventoryProducts || {}); @@ -160,10 +164,10 @@ export function CreatePage({ ? i18n.str`must be greater than 0` : undefined, }), - extra: - value.extra && !stringIsValidJSON(value.extra) - ? i18n.str`not a valid json` - : undefined, + // extra: + // value.extra && !stringIsValidJSON(value.extra) + // ? i18n.str`not a valid json` + // : undefined, payments: undefinedIfEmpty({ refund_deadline: !value.payments?.refund_deadline ? undefined @@ -202,6 +206,7 @@ export function CreatePage({ ) ? i18n.str`auto refund cannot be after refund deadline` : undefined, + }), shipping: undefinedIfEmpty({ delivery_date: !value.shipping?.delivery_date @@ -225,7 +230,7 @@ export function CreatePage({ amount: order.pricing.order_price, summary: order.pricing.summary, products: productList, - extra: value.extra, + extra: JSON.stringify(value.extra), pay_deadline: value.payments.pay_deadline ? { t_s: Math.floor(value.payments.pay_deadline.getTime() / 1000), @@ -250,9 +255,7 @@ export function CreatePage({ ), } : undefined, - wire_fee_amortization: value.payments.wire_fee_amortization as number, max_fee: value.payments.max_fee as string, - max_wire_fee: value.payments.max_wire_fee as string, delivery_date: value.shipping.delivery_date ? { t_s: value.shipping.delivery_date.getTime() / 1000 } @@ -326,6 +329,8 @@ export function CreatePage({ const totalAsString = Amounts.stringify(totalPrice.amount); const allProducts = productList.concat(inventoryList.map(asProduct)); + const [newField, setNewField] = useState("") + useEffect(() => { valueHandler((v) => { return { @@ -486,16 +491,61 @@ export function CreatePage({ name="payments.pay_deadline" label={i18n.str`Payment deadline`} tooltip={i18n.str`Deadline for the customer to pay for the offer before it expires. Inventory products will be reserved until this deadline.`} + side={ + <span> + <button class="button" onClick={() => { + valueHandler({ + ...value, + payments: { + ...(value.payments ?? {}), + pay_deadline: instance_default.payments?.pay_deadline + } + }) + }}> + <i18n.Translate>default</i18n.Translate> + </button> + </span> + } /> <InputDate name="payments.refund_deadline" label={i18n.str`Refund deadline`} tooltip={i18n.str`Time until which the order can be refunded by the merchant.`} + side={ + <span> + <button class="button" onClick={() => { + valueHandler({ + ...value, + payments: { + ...(value.payments ?? {}), + refund_deadline: instance_default.payments?.refund_deadline + } + }) + }}> + <i18n.Translate>default</i18n.Translate> + </button> + </span> + } /> <InputDate name="payments.wire_transfer_deadline" label={i18n.str`Wire transfer deadline`} tooltip={i18n.str`Deadline for the exchange to make the wire transfer.`} + side={ + <span> + <button class="button" onClick={() => { + valueHandler({ + ...value, + payments: { + ...(value.payments ?? {}), + wire_transfer_deadline: instance_default.payments?.wire_transfer_deadline + } + }) + }}> + <i18n.Translate>default</i18n.Translate> + </button> + </span> + } /> <InputDate name="payments.auto_refund_deadline" @@ -505,23 +555,13 @@ export function CreatePage({ <InputCurrency name="payments.max_fee" - label={i18n.str`Maximum deposit fee`} - tooltip={i18n.str`Maximum deposit fees the merchant is willing to cover for this order. Higher deposit fees must be covered in full by the consumer.`} + label={i18n.str`Maximum fee`} + tooltip={i18n.str`Maximum fees the merchant is willing to cover for this order. Higher deposit fees must be covered in full by the consumer.`} /> - <InputCurrency - name="payments.max_wire_fee" - label={i18n.str`Maximum wire fee`} - tooltip={i18n.str`Maximum aggregate wire fees the merchant is willing to cover for this order. Wire fees exceeding this amount are to be covered by the customers.`} - /> - <InputNumber - name="payments.wire_fee_amortization" - label={i18n.str`Wire fee amortization`} - tooltip={i18n.str`Factor by which wire fees exceeding the above threshold are divided to determine the share of excess wire fees to be paid explicitly by the consumer.`} - /> - <InputBoolean + <InputToggle name="payments.createToken" label={i18n.str`Create token`} - tooltip={i18n.str`Uncheck this option if the merchant backend generated an order ID with enough entropy to prevent adversarial claims.`} + tooltip={i18n.str`If the order ID is easy to guess the token will prevent user to steal orders from others.`} /> <InputNumber name="payments.minimum_age" @@ -530,7 +570,7 @@ export function CreatePage({ help={ minAgeByProducts > 0 ? i18n.str`Min age defined by the producs is ${minAgeByProducts}` - : undefined + : i18n.str`No product with age restriction in this order` } /> </InputGroup> @@ -542,12 +582,53 @@ export function CreatePage({ label={i18n.str`Additional information`} tooltip={i18n.str`Custom information to be included in the contract for this order.`} > - <Input - name="extra" - inputType="multiline" - label={`Value`} - tooltip={i18n.str`You must enter a value in JavaScript Object Notation (JSON).`} - /> + {Object.keys(value.extra ?? {}).map((key) => { + + return <Input + name={`extra.${key}`} + inputType="multiline" + label={key} + tooltip={i18n.str`You must enter a value in JavaScript Object Notation (JSON).`} + side={ + <button class="button" onClick={(e) => { + if (value.extra && value.extra[key] !== undefined) { + console.log(value.extra) + delete value.extra[key] + } + valueHandler({ + ...value, + }) + }}>remove</button> + } + /> + })} + <div class="field is-horizontal"> + <div class="field-label is-normal"> + <label class="label"> + <i18n.Translate>Custom field name</i18n.Translate> + <span class="icon has-tooltip-right" data-tooltip={"new extra field"}> + <i class="mdi mdi-information" /> + </span> + </label> + </div> + <div class="field-body is-flex-grow-3"> + <div class="field"> + <p class="control"> + <input class="input " value={newField} onChange={(e) => setNewField(e.currentTarget.value)} /> + </p> + </div> + </div> + <button class="button" onClick={(e) => { + setNewField("") + valueHandler({ + ...value, + extra: { + ...(value.extra ?? {}), + [newField]: "" + } + }) + }}>add</button> + </div> </InputGroup> } </FormProvider> 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 index ffefd5302..2474fd042 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/create/index.tsx @@ -38,7 +38,7 @@ export type Entity = { }; interface Props { onBack?: () => void; - onConfirm: () => void; + onConfirm: (id: string) => void; onUnauthorized: () => VNode; onNotFound: () => VNode; onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode; @@ -95,7 +95,9 @@ export default function OrderCreate({ onBack={onBack} onCreate={(request: MerchantBackend.Orders.PostOrderRequest) => { createOrder(request) - .then(onConfirm) + .then((r) => { + return onConfirm(r.data.order_id) + }) .catch((error) => { setNotif({ message: "could not create order", diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/Detail.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/Detail.stories.tsx index e430ede56..6e73a01a5 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/Detail.stories.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/Detail.stories.tsx @@ -50,13 +50,11 @@ const defaultContractTerm = { auditors: [], exchanges: [], max_fee: "TESTKUDOS:1", - max_wire_fee: "TESTKUDOS:1", merchant: {} as any, merchant_base_url: "http://merchant.url/", order_id: "2021.165-03GDFC26Y1NNG", products: [], summary: "text summary", - wire_fee_amortization: 1, wire_transfer_deadline: { t_s: "never", }, 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 index 8965d41c9..e42adc2ff 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx @@ -19,7 +19,7 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { AmountJson, Amounts } from "@gnu-taler/taler-util"; +import { AmountJson, Amounts, stringifyRefundUri } from "@gnu-taler/taler-util"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { format, formatDistance } from "date-fns"; import { Fragment, h, VNode } from "preact"; @@ -38,6 +38,7 @@ import { MerchantBackend } from "../../../../declaration.js"; import { mergeRefunds } from "../../../../utils/amount.js"; import { RefundModal } from "../list/Table.js"; import { Event, Timeline } from "./Timeline.js"; +import { dateFormatForSettings, datetimeFormatForSettings, useSettings } from "../../../../hooks/useSettings.js"; type Entity = MerchantBackend.Orders.MerchantOrderStatusResponse; type CT = MerchantBackend.ContractTerms; @@ -87,18 +88,6 @@ function ContractTerms({ value }: { value: CT }) { label={i18n.str`Max fee`} tooltip={i18n.str`maximum total deposit fee accepted by the merchant for this contract`} /> - <Input<CT> - readonly - name="max_wire_fee" - label={i18n.str`Max wire fee`} - tooltip={i18n.str`maximum wire fee accepted by the merchant`} - /> - <Input<CT> - readonly - name="wire_fee_amortization" - label={i18n.str`Wire fee amortization`} - tooltip={i18n.str`over how many customer transactions does the merchant expect to amortize wire fees on average`} - /> <InputDate<CT> readonly name="timestamp" @@ -204,6 +193,7 @@ function ClaimedPage({ const [value, valueHandler] = useState<Partial<Claimed>>(order); const { i18n } = useTranslationContext(); + const [settings] = useSettings() return ( <div> @@ -249,7 +239,7 @@ function ClaimedPage({ </b>{" "} {format( new Date(order.contract_terms.timestamp.t_s * 1000), - "yyyy-MM-dd HH:mm:ss", + datetimeFormatForSettings(settings) )} </p> </div> @@ -427,9 +417,10 @@ function PaidPage({ const [value, valueHandler] = useState<Partial<Paid>>(order); const { url } = useBackendContext(); - const refundHost = url.replace(/.*:\/\//, ""); // remove protocol part - const proto = url.startsWith("http://") ? "taler+http" : "taler"; - const refundurl = `${proto}://refund/${refundHost}/${order.contract_terms.order_id}/`; + const refundurl = stringifyRefundUri({ + merchantBaseUrl: url, + orderId: order.contract_terms.order_id + }) const refundable = new Date().getTime() < order.contract_terms.refund_deadline.t_s * 1000; const { i18n } = useTranslationContext(); @@ -618,6 +609,7 @@ function UnpaidPage({ }) { const [value, valueHandler] = useState<Partial<Unpaid>>(order); const { i18n } = useTranslationContext(); + const [settings] = useSettings() return ( <div> <section class="hero is-hero-bar"> @@ -666,7 +658,7 @@ function UnpaidPage({ ? "never" : format( new Date(order.creation_time.t_s * 1000), - "yyyy-MM-dd HH:mm:ss", + datetimeFormatForSettings(settings) )} </p> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/Timeline.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/Timeline.tsx index e68889a92..8c863f386 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/Timeline.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/Timeline.tsx @@ -16,6 +16,7 @@ import { format } from "date-fns"; import { h } from "preact"; import { useEffect, useState } from "preact/hooks"; +import { datetimeFormatForSettings, useSettings } from "../../../../hooks/useSettings.js"; interface Props { events: Event[]; @@ -30,7 +31,7 @@ export function Timeline({ events: e }: Props) { }); events.sort((a, b) => a.when.getTime() - b.when.getTime()); - + const [settings] = useSettings(); const [state, setState] = useState(events); useEffect(() => { const handle = setTimeout(() => { @@ -104,7 +105,7 @@ export function Timeline({ events: e }: Props) { } })()} <div class="timeline-content"> - {e.description !== "now" && <p class="heading">{format(e.when, "yyyy/MM/dd HH:mm:ss")}</p>} + {e.description !== "now" && <p class="heading">{format(e.when, datetimeFormatForSettings(settings))}</p>} <p>{e.description}</p> </div> </div> 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 index 37770d273..c29a6fa6e 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx @@ -26,19 +26,24 @@ import { useState } from "preact/hooks"; import { DatePicker } from "../../../../components/picker/DatePicker.js"; import { MerchantBackend, WithId } from "../../../../declaration.js"; import { CardTable } from "./Table.js"; +import { dateFormatForSettings, useSettings } from "../../../../hooks/useSettings.js"; export interface ListPageProps { errorOrderId: string | undefined; onShowAll: () => void; + onShowNotPaid: () => void; onShowPaid: () => void; onShowRefunded: () => void; onShowNotWired: () => void; + onShowWired: () => void; onCopyURL: (id: string) => void; isAllActive: string; isPaidActive: string; + isNotPaidActive: string; isRefundedActive: string; isNotWiredActive: string; + isWiredActive: string; jumpToDate?: Date; onSelectDate: (date?: Date) => void; @@ -66,18 +71,23 @@ export function ListPage({ onCopyURL, onShowAll, onShowPaid, + onShowNotPaid, onShowRefunded, onShowNotWired, + onShowWired, onSelectDate, isPaidActive, isRefundedActive, isNotWiredActive, onCreate, + isNotPaidActive, + isWiredActive, }: ListPageProps): VNode { const { i18n } = useTranslationContext(); const dateTooltip = i18n.str`select date to show nearby orders`; const [pickDate, setPickDate] = useState(false); const [orderId, setOrderId] = useState<string>(""); + const [settings] = useSettings(); return ( <section class="section is-main-section"> @@ -116,13 +126,13 @@ export function ListPage({ <div class="column is-two-thirds"> <div class="tabs" style={{ overflow: "inherit" }}> <ul> - <li class={isAllActive}> + <li class={isNotPaidActive}> <div class="has-tooltip-right" - data-tooltip={i18n.str`remove all filters`} + data-tooltip={i18n.str`only show paid orders`} > - <a onClick={onShowAll}> - <i18n.Translate>All</i18n.Translate> + <a onClick={onShowNotPaid}> + <i18n.Translate>New</i18n.Translate> </a> </div> </li> @@ -156,6 +166,26 @@ export function ListPage({ </a> </div> </li> + <li class={isWiredActive}> + <div + class="has-tooltip-left" + data-tooltip={i18n.str`only show orders where customers paid, but wire payments from payment provider are still pending`} + > + <a onClick={onShowWired}> + <i18n.Translate>Completed</i18n.Translate> + </a> + </div> + </li> + <li class={isAllActive}> + <div + class="has-tooltip-right" + data-tooltip={i18n.str`remove all filters`} + > + <a onClick={onShowAll}> + <i18n.Translate>All</i18n.Translate> + </a> + </div> + </li> </ul> </div> </div> @@ -180,8 +210,8 @@ export function ListPage({ class="input" type="text" readonly - value={!jumpToDate ? "" : format(jumpToDate, "yyyy/MM/dd")} - placeholder={i18n.str`date (YYYY/MM/DD)`} + value={!jumpToDate ? "" : format(jumpToDate, dateFormatForSettings(settings))} + placeholder={i18n.str`date (${dateFormatForSettings(settings)})`} onClick={() => { setPickDate(true); }} 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 3c927033b..608c9b20d 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 @@ -36,6 +36,7 @@ import { ConfirmModal } from "../../../../components/modal/index.js"; import { useConfigContext } from "../../../../context/config.js"; import { MerchantBackend, WithId } from "../../../../declaration.js"; import { mergeRefunds } from "../../../../utils/amount.js"; +import { datetimeFormatForSettings, useSettings } from "../../../../hooks/useSettings.js"; type Entity = MerchantBackend.Orders.OrderHistoryEntry & WithId; interface Props { @@ -136,6 +137,7 @@ function Table({ hasMoreBefore, }: TableProps): VNode { const { i18n } = useTranslationContext(); + const [settings] = useSettings(); return ( <div class="table-container"> {onLoadMoreBefore && ( @@ -173,9 +175,9 @@ function Table({ {i.timestamp.t_s === "never" ? "never" : format( - new Date(i.timestamp.t_s * 1000), - "yyyy/MM/dd HH:mm:ss", - )} + new Date(i.timestamp.t_s * 1000), + datetimeFormatForSettings(settings), + )} </td> <td onClick={(): void => onSelect(i)} @@ -260,6 +262,7 @@ export function RefundModal({ }: RefundModalProps): VNode { type State = { mainReason?: string; description?: string; refund?: string }; const [form, setValue] = useState<State>({}); + const [settings] = useSettings(); const { i18n } = useTranslationContext(); // const [errors, setErrors] = useState<FormErrors<State>>({}); @@ -281,8 +284,8 @@ 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.str`duplicated`; @@ -296,10 +299,10 @@ export function RefundModal({ refund: !form.refund ? i18n.str`required` : !Amounts.parse(form.refund) - ? i18n.str`invalid format` - : Amounts.cmp(totalRefundable, Amounts.parse(form.refund)!) === -1 - ? i18n.str`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, @@ -361,9 +364,9 @@ export function RefundModal({ {r.timestamp.t_s === "never" ? "never" : format( - new Date(r.timestamp.t_s * 1000), - "yyyy-MM-dd HH:mm:ss", - )} + new Date(r.timestamp.t_s * 1000), + datetimeFormatForSettings(settings), + )} </td> <td>{r.amount}</td> <td>{r.reason}</td> 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 index 6888eda58..48f77e3d3 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx @@ -55,7 +55,7 @@ export default function OrderList({ onSelect, onNotFound, }: Props): VNode { - const [filter, setFilter] = useState<InstanceOrderFilter>({}); + const [filter, setFilter] = useState<InstanceOrderFilter>({ paid: "no" }); const [orderToBeRefunded, setOrderToBeRefunded] = useState< MerchantBackend.Orders.OrderHistoryEntry | undefined >(undefined); @@ -88,13 +88,15 @@ export default function OrderList({ return onLoadError(result); } - const isPaidActive = filter.paid === "yes" ? "is-active" : ""; + const isNotPaidActive = filter.paid === "no" ? "is-active" : ""; + const isPaidActive = filter.paid === "yes" && filter.wired === undefined ? "is-active" : ""; const isRefundedActive = filter.refunded === "yes" ? "is-active" : ""; - const isNotWiredActive = filter.wired === "no" ? "is-active" : ""; + const isNotWiredActive = filter.wired === "no" && filter.paid === "yes" ? "is-active" : ""; + const isWiredActive = filter.wired === "yes" ? "is-active" : ""; const isAllActive = filter.paid === undefined && - filter.refunded === undefined && - filter.wired === undefined + filter.refunded === undefined && + filter.wired === undefined ? "is-active" : ""; @@ -127,7 +129,9 @@ export default function OrderList({ errorOrderId={errorOrderId} isAllActive={isAllActive} isNotWiredActive={isNotWiredActive} + isWiredActive={isWiredActive} isPaidActive={isPaidActive} + isNotPaidActive={isNotPaidActive} isRefundedActive={isRefundedActive} jumpToDate={filter.date} onCopyURL={(id) => @@ -137,9 +141,11 @@ export default function OrderList({ onSearchOrderById={testIfOrderExistAndSelect} onSelectDate={setNewDate} onShowAll={() => setFilter({})} + onShowNotPaid={() => setFilter({ paid: "no" })} onShowPaid={() => setFilter({ paid: "yes" })} onShowRefunded={() => setFilter({ refunded: "yes" })} - onShowNotWired={() => setFilter({ wired: "no" })} + onShowNotWired={() => setFilter({ wired: "no", paid: "yes" })} + onShowWired={() => setFilter({ wired: "yes" })} /> {orderToBeRefunded && ( |