diff options
author | Sebastian <sebasjm@gmail.com> | 2024-04-03 09:52:53 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-04-03 14:56:29 -0300 |
commit | 56da180423029a1b53d2be343eed4f073e96dc89 (patch) | |
tree | e8fd31dcc4c7bc6866b139de097c8f2c01f93597 /packages/merchant-backoffice-ui/src/hooks/order.ts | |
parent | c53c6b8b3c0a66f3862883ec1314c6d4bf68af32 (diff) | |
download | wallet-core-56da180423029a1b53d2be343eed4f073e96dc89.tar.gz wallet-core-56da180423029a1b53d2be343eed4f073e96dc89.tar.bz2 wallet-core-56da180423029a1b53d2be343eed4f073e96dc89.zip |
wip #8655: updating paginated queries
Diffstat (limited to 'packages/merchant-backoffice-ui/src/hooks/order.ts')
-rw-r--r-- | packages/merchant-backoffice-ui/src/hooks/order.ts | 307 |
1 files changed, 56 insertions, 251 deletions
diff --git a/packages/merchant-backoffice-ui/src/hooks/order.ts b/packages/merchant-backoffice-ui/src/hooks/order.ts index 40932ac62..47ddf1c38 100644 --- a/packages/merchant-backoffice-ui/src/hooks/order.ts +++ b/packages/merchant-backoffice-ui/src/hooks/order.ts @@ -14,276 +14,81 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ import { - HttpResponse, - HttpResponseOk, - HttpResponsePaginated, - RequestError, + useMerchantApiContext } from "@gnu-taler/web-util/browser"; -import { useEffect, useState } from "preact/hooks"; -import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js"; -import { useBackendInstanceRequest } from "./backend.js"; +import { PAGE_SIZE } from "../utils/constants.js"; // FIX default import https://github.com/microsoft/TypeScript/issues/49189 -import { TalerErrorDetail, TalerMerchantApi } from "@gnu-taler/taler-util"; -import _useSWR, { SWRHook } from "swr"; +import { AbsoluteTime, AccessToken, TalerHttpError, TalerMerchantManagementResultByMethod } from "@gnu-taler/taler-util"; +import _useSWR, { SWRHook, mutate } from "swr"; +import { useSessionContext } from "../context/session.js"; +import { buildPaginatedResult } from "./webhooks.js"; const useSWR = _useSWR as unknown as SWRHook; -// export interface OrderAPI { -// //FIXME: add OutOfStockResponse on 410 -// createOrder: ( -// data: TalerMerchantApi.PostOrderRequest, -// ) => Promise<HttpResponseOk<TalerMerchantApi.PostOrderResponse>>; -// forgetOrder: ( -// id: string, -// data: TalerMerchantApi.ForgetRequest, -// ) => Promise<HttpResponseOk<void>>; -// refundOrder: ( -// id: string, -// data: TalerMerchantApi.RefundRequest, -// ) => Promise<HttpResponseOk<TalerMerchantApi.MerchantRefundResponse>>; -// deleteOrder: (id: string) => Promise<HttpResponseOk<void>>; -// getPaymentURL: (id: string) => Promise<HttpResponseOk<string>>; -// } -type YesOrNo = "yes" | "no"; -// export function useOrderAPI(): OrderAPI { -// const mutateAll = useMatchMutate(); -// const { request } = useBackendInstanceRequest(); - -// const createOrder = async ( -// data: TalerMerchantApi.PostOrderRequest, -// ): Promise<HttpResponseOk<TalerMerchantApi.PostOrderResponse>> => { -// const res = await request<TalerMerchantApi.PostOrderResponse>( -// `/private/orders`, -// { -// method: "POST", -// data, -// }, -// ); -// await mutateAll(/.*private\/orders.*/); -// // mutate('') -// return res; -// }; -// const refundOrder = async ( -// orderId: string, -// data: TalerMerchantApi.RefundRequest, -// ): Promise<HttpResponseOk<TalerMerchantApi.MerchantRefundResponse>> => { -// mutateAll(/@"\/private\/orders"@/); -// const res = request<TalerMerchantApi.MerchantRefundResponse>( -// `/private/orders/${orderId}/refund`, -// { -// method: "POST", -// data, -// }, -// ); - -// // order list returns refundable information, so we must evict everything -// await mutateAll(/.*private\/orders.*/); -// return res; -// }; - -// const forgetOrder = async ( -// orderId: string, -// data: TalerMerchantApi.ForgetRequest, -// ): Promise<HttpResponseOk<void>> => { -// mutateAll(/@"\/private\/orders"@/); -// const res = request<void>(`/private/orders/${orderId}/forget`, { -// method: "PATCH", -// data, -// }); -// // we may be forgetting some fields that are pare of the listing, so we must evict everything -// await mutateAll(/.*private\/orders.*/); -// return res; -// }; -// const deleteOrder = async ( -// orderId: string, -// ): Promise<HttpResponseOk<void>> => { -// mutateAll(/@"\/private\/orders"@/); -// const res = request<void>(`/private/orders/${orderId}`, { -// method: "DELETE", -// }); -// await mutateAll(/.*private\/orders.*/); -// return res; -// }; - -// const getPaymentURL = async ( -// orderId: string, -// ): Promise<HttpResponseOk<string>> => { -// return request<TalerMerchantApi.MerchantOrderStatusResponse>( -// `/private/orders/${orderId}`, -// { -// method: "GET", -// }, -// ).then((res) => { -// const url = -// res.data.order_status === "unpaid" -// ? res.data.taler_pay_uri -// : res.data.contract_terms.fulfillment_url; -// const response: HttpResponseOk<string> = res as any; -// response.data = url || ""; -// return response; -// }); -// }; - -// return { createOrder, forgetOrder, deleteOrder, refundOrder, getPaymentURL }; -// } +export function revalidateOrderDetails() { + return mutate( + (key) => Array.isArray(key) && key[key.length - 1] === "getOrderDetails", + undefined, + { revalidate: true }, + ); +} +export function useOrderDetails(oderId: string) { + const { state: session } = useSessionContext(); + const { lib: { management } } = useMerchantApiContext(); -export function useOrderDetails( - oderId: string, -): HttpResponse< - TalerMerchantApi.MerchantOrderStatusResponse, - TalerErrorDetail -> { - const { fetcher } = useBackendInstanceRequest(); + async function fetcher([dId, token]: [string, AccessToken]) { + return await management.getOrderDetails(token, dId); + } - const { data, error, isValidating } = useSWR< - HttpResponseOk<TalerMerchantApi.MerchantOrderStatusResponse>, - RequestError<TalerErrorDetail> - >([`/private/orders/${oderId}`], fetcher, { - refreshInterval: 0, - refreshWhenHidden: false, - revalidateOnFocus: false, - revalidateOnReconnect: false, - refreshWhenOffline: false, - }); + const { data, error } = useSWR< + TalerMerchantManagementResultByMethod<"getOrderDetails">, + TalerHttpError + >([oderId, session.token, "getOrderDetails"], fetcher); - if (isValidating) return { loading: true, data: data?.data }; if (data) return data; - if (error) return error.cause; - return { loading: true }; + if (error) return error; + return undefined; } export interface InstanceOrderFilter { - paid?: YesOrNo; - refunded?: YesOrNo; - wired?: YesOrNo; - date?: Date; + paid?: boolean; + refunded?: boolean; + wired?: boolean; + date?: AbsoluteTime; + position?: string; } export function useInstanceOrders( args?: InstanceOrderFilter, - updateFilter?: (d: Date) => void, -): HttpResponsePaginated< - TalerMerchantApi.OrderHistory, - TalerErrorDetail -> { - const { orderFetcher } = useBackendInstanceRequest(); - - const [pageBefore, setPageBefore] = useState(1); - const [pageAfter, setPageAfter] = useState(1); - - const totalAfter = pageAfter * PAGE_SIZE; - const totalBefore = args?.date ? pageBefore * PAGE_SIZE : 0; - - /** - * FIXME: this can be cleaned up a little - * - * the logic of double query should be inside the orderFetch so from the hook perspective and cache - * is just one query and one error status - */ - const { - data: beforeData, - error: beforeError, - isValidating: loadingBefore, - } = useSWR< - HttpResponseOk<TalerMerchantApi.OrderHistory>, - RequestError<TalerErrorDetail> - >( - [ - `/private/orders`, - args?.paid, - args?.refunded, - args?.wired, - args?.date, - totalBefore, - ], - orderFetcher, - ); - const { - data: afterData, - error: afterError, - isValidating: loadingAfter, - } = useSWR< - HttpResponseOk<TalerMerchantApi.OrderHistory>, - RequestError<TalerErrorDetail> - >( - [ - `/private/orders`, - args?.paid, - args?.refunded, - args?.wired, - args?.date, - -totalAfter, - ], - orderFetcher, - ); - - //this will save last result - const [lastBefore, setLastBefore] = useState< - HttpResponse< - TalerMerchantApi.OrderHistory, - TalerErrorDetail - > - >({ loading: true }); - const [lastAfter, setLastAfter] = useState< - HttpResponse< - TalerMerchantApi.OrderHistory, - TalerErrorDetail - > - >({ loading: true }); - useEffect(() => { - if (afterData) setLastAfter(afterData); - if (beforeData) setLastBefore(beforeData); - }, [afterData, beforeData]); - - if (beforeError) return beforeError.cause; - if (afterError) return afterError.cause; + updatePosition: (d: string | undefined) => void = () => { }, +) { + const { state: session } = useSessionContext(); + const { lib: { management } } = useMerchantApiContext(); + + // const [offset, setOffset] = useState<string | undefined>(args?.position); + + async function fetcher([token, o, p, r, w, d]: [AccessToken, string, boolean, boolean, boolean, AbsoluteTime]) { + return await management.listOrders(token, { + limit: PAGE_SIZE, + offset: o, + order: "dec", + paid: p, + refunded: r, + wired: w, + date: d, + }); + } - // if the query returns less that we ask, then we have reach the end or beginning - const isReachingEnd = afterData && afterData.data.orders.length < totalAfter; - const isReachingStart = - args?.date === undefined || - (beforeData && beforeData.data.orders.length < totalBefore); + const { data, error } = useSWR< + TalerMerchantManagementResultByMethod<"listOrders">, + TalerHttpError + >([session.token, args?.position, args?.paid, args?.refunded, args?.wired, args?.date, "listOrders"], fetcher); - const pagination = { - isReachingEnd, - isReachingStart, - loadMore: () => { - if (!afterData || isReachingEnd) return; - if (afterData.data.orders.length < MAX_RESULT_SIZE) { - setPageAfter(pageAfter + 1); - } else { - const from = - afterData.data.orders[afterData.data.orders.length - 1].timestamp.t_s; - if (from && from !== "never" && updateFilter) - updateFilter(new Date(from * 1000)); - } - }, - loadMorePrev: () => { - if (!beforeData || isReachingStart) return; - if (beforeData.data.orders.length < MAX_RESULT_SIZE) { - setPageBefore(pageBefore + 1); - } else if (beforeData) { - const from = - beforeData.data.orders[beforeData.data.orders.length - 1].timestamp - .t_s; - if (from && from !== "never" && updateFilter) - updateFilter(new Date(from * 1000)); - } - }, - }; + if (error) return error; + if (data === undefined) return undefined; + if (data.type !== "ok") return data; - const orders = - !beforeData || !afterData - ? [] - : (beforeData || lastBefore).data.orders - .slice() - .reverse() - .concat((afterData || lastAfter).data.orders); - if (loadingAfter || loadingBefore) return { loading: true, data: { orders } }; - if (beforeData && afterData) { - return { ok: true, data: { orders }, ...pagination }; - } - return { loading: true }; + return buildPaginatedResult(data.body.orders, args?.position, updatePosition, (d) => String(d.row_id)) } |