/*
This file is part of GNU Taler
(C) 2021-2023 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
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import {
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Loading } from "../../../../components/exception/loading.js";
import { NotificationCard } from "../../../../components/menu/index.js";
import { MerchantBackend } from "../../../../declaration.js";
import {
InstanceOrderFilter,
useInstanceOrders,
useOrderAPI,
useOrderDetails,
} from "../../../../hooks/order.js";
import { Notification } from "../../../../utils/types.js";
import { ListPage } from "./ListPage.js";
import { RefundModal } from "./Table.js";
interface Props {
onUnauthorized: () => VNode;
onLoadError: (error: HttpError) => VNode;
onNotFound: () => VNode;
onSelect: (id: string) => void;
onCreate: () => void;
}
export default function OrderList({
onUnauthorized,
onLoadError,
onCreate,
onSelect,
onNotFound,
}: Props): VNode {
const [filter, setFilter] = useState({});
const [orderToBeRefunded, setOrderToBeRefunded] = useState<
MerchantBackend.Orders.OrderHistoryEntry | undefined
>(undefined);
const setNewDate = (date?: Date): void =>
setFilter((prev) => ({ ...prev, date }));
const result = useInstanceOrders(filter, setNewDate);
const { refundOrder, getPaymentURL } = useOrderAPI();
const [notif, setNotif] = useState(undefined);
const { i18n } = useTranslationContext();
const [errorOrderId, setErrorOrderId] = useState(
undefined,
);
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return ;
if (!result.ok) return onLoadError(result);
const isPaidActive = filter.paid === "yes" ? "is-active" : "";
const isRefundedActive = filter.refunded === "yes" ? "is-active" : "";
const isNotWiredActive = filter.wired === "no" ? "is-active" : "";
const isAllActive =
filter.paid === undefined &&
filter.refunded === undefined &&
filter.wired === undefined
? "is-active"
: "";
async function testIfOrderExistAndSelect(orderId: string): Promise {
if (!orderId) {
setErrorOrderId(i18n.str`Enter an order id`);
return;
}
try {
await getPaymentURL(orderId);
onSelect(orderId);
setErrorOrderId(undefined);
} catch {
setErrorOrderId(i18n.str`order not found`);
}
}
return (
({ ...o, id: o.order_id }))}
onLoadMoreBefore={result.loadMorePrev}
hasMoreBefore={!result.isReachingStart}
onLoadMoreAfter={result.loadMore}
hasMoreAfter={!result.isReachingEnd}
onSelectOrder={(order) => onSelect(order.id)}
onRefundOrder={(value) => setOrderToBeRefunded(value)}
errorOrderId={errorOrderId}
isAllActive={isAllActive}
isNotWiredActive={isNotWiredActive}
isPaidActive={isPaidActive}
isRefundedActive={isRefundedActive}
jumpToDate={filter.date}
onCopyURL={(id) =>
getPaymentURL(id).then((resp) => copyToClipboard(resp.data))
}
onCreate={onCreate}
onSearchOrderById={testIfOrderExistAndSelect}
onSelectDate={setNewDate}
onShowAll={() => setFilter({})}
onShowPaid={() => setFilter({ paid: "yes" })}
onShowRefunded={() => setFilter({ refunded: "yes" })}
onShowNotWired={() => setFilter({ wired: "no" })}
/>
{orderToBeRefunded && (
setOrderToBeRefunded(undefined)}
onConfirm={(value) =>
refundOrder(orderToBeRefunded.order_id, value)
.then(() =>
setNotif({
message: i18n.str`refund created successfully`,
type: "SUCCESS",
}),
)
.catch((error) =>
setNotif({
message: i18n.str`could not create the refund`,
type: "ERROR",
description: error.message,
}),
)
.then(() => setOrderToBeRefunded(undefined))
}
onLoadError={(error) => {
setNotif({
message: i18n.str`could not create the refund`,
type: "ERROR",
description: error.message,
});
setOrderToBeRefunded(undefined);
return ;
}}
onUnauthorized={onUnauthorized}
onNotFound={() => {
setNotif({
message: i18n.str`could not get the order to refund`,
type: "ERROR",
// description: error.message
});
setOrderToBeRefunded(undefined);
return ;
}}
/>
)}
);
}
interface RefundProps {
id: string;
onUnauthorized: () => VNode;
onLoadError: (error: HttpError) => VNode;
onNotFound: () => VNode;
onCancel: () => void;
onConfirm: (m: MerchantBackend.Orders.RefundRequest) => void;
}
function RefundModalForTable({
id,
onUnauthorized,
onLoadError,
onNotFound,
onConfirm,
onCancel,
}: RefundProps): VNode {
const result = useOrderDetails(id);
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return ;
if (!result.ok) return onLoadError(result);
return (
);
}
async function copyToClipboard(text: string): Promise {
return navigator.clipboard.writeText(text);
}