aboutsummaryrefslogtreecommitdiff
path: root/packages/merchant-backoffice-ui/src/hooks/product.ts
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-04-03 09:52:53 -0300
committerSebastian <sebasjm@gmail.com>2024-04-03 14:56:29 -0300
commit56da180423029a1b53d2be343eed4f073e96dc89 (patch)
treee8fd31dcc4c7bc6866b139de097c8f2c01f93597 /packages/merchant-backoffice-ui/src/hooks/product.ts
parentc53c6b8b3c0a66f3862883ec1314c6d4bf68af32 (diff)
downloadwallet-core-56da180423029a1b53d2be343eed4f073e96dc89.tar.xz
wip #8655: updating paginated queries
Diffstat (limited to 'packages/merchant-backoffice-ui/src/hooks/product.ts')
-rw-r--r--packages/merchant-backoffice-ui/src/hooks/product.ts227
1 files changed, 78 insertions, 149 deletions
diff --git a/packages/merchant-backoffice-ui/src/hooks/product.ts b/packages/merchant-backoffice-ui/src/hooks/product.ts
index 0eb54f717..6721136a5 100644
--- a/packages/merchant-backoffice-ui/src/hooks/product.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/product.ts
@@ -14,164 +14,93 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import {
- HttpResponse,
- HttpResponseOk,
- RequestError,
+ useMerchantApiContext
} from "@gnu-taler/web-util/browser";
-import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
// FIX default import https://github.com/microsoft/TypeScript/issues/49189
-import _useSWR, { SWRHook, useSWRConfig } from "swr";
-import { TalerErrorDetail, TalerMerchantApi } from "@gnu-taler/taler-util";
+import { AccessToken, OperationOk, TalerHttpError, TalerMerchantApi, TalerMerchantManagementErrorsByMethod, TalerMerchantManagementResultByMethod, opFixedSuccess } from "@gnu-taler/taler-util";
+import { useState } from "preact/hooks";
+import _useSWR, { SWRHook, mutate } from "swr";
+import { useSessionContext } from "../context/session.js";
+import { PAGE_SIZE } from "../utils/constants.js";
+import { buildPaginatedResult } from "./webhooks.js";
const useSWR = _useSWR as unknown as SWRHook;
-// export interface ProductAPI {
-// getProduct: (
-// id: string,
-// ) => Promise<void>;
-// createProduct: (
-// data: TalerMerchantApi.ProductAddDetail,
-// ) => Promise<void>;
-// updateProduct: (
-// id: string,
-// data: TalerMerchantApi.ProductPatchDetail,
-// ) => Promise<void>;
-// deleteProduct: (id: string) => Promise<void>;
-// lockProduct: (
-// id: string,
-// data: TalerMerchantApi.LockRequest,
-// ) => Promise<void>;
-// }
-
-// export function useProductAPI(): ProductAPI {
-// const mutateAll = useMatchMutate();
-// const { mutate } = useSWRConfig();
-
-// const { request } = useBackendInstanceRequest();
-
-// const createProduct = async (
-// data: TalerMerchantApi.ProductAddDetail,
-// ): Promise<void> => {
-// const res = await request(`/private/products`, {
-// method: "POST",
-// data,
-// });
-
-// return await mutateAll(/.*\/private\/products.*/);
-// };
-
-// const updateProduct = async (
-// productId: string,
-// data: TalerMerchantApi.ProductPatchDetail,
-// ): Promise<void> => {
-// const r = await request(`/private/products/${productId}`, {
-// method: "PATCH",
-// data,
-// });
-
-// return await mutateAll(/.*\/private\/products.*/);
-// };
-
-// const deleteProduct = async (productId: string): Promise<void> => {
-// await request(`/private/products/${productId}`, {
-// method: "DELETE",
-// });
-// await mutate([`/private/products`]);
-// };
-
-// const lockProduct = async (
-// productId: string,
-// data: TalerMerchantApi.LockRequest,
-// ): Promise<void> => {
-// await request(`/private/products/${productId}/lock`, {
-// method: "POST",
-// data,
-// });
-
-// return await mutateAll(/.*"\/private\/products.*/);
-// };
-
-// const getProduct = async (
-// productId: string,
-// ): Promise<void> => {
-// await request(`/private/products/${productId}`, {
-// method: "GET",
-// });
-
-// return
-// };
-
-// return { createProduct, updateProduct, deleteProduct, lockProduct, getProduct };
-// }
-
-export function useInstanceProducts(): HttpResponse<
- (TalerMerchantApi.ProductDetail & WithId)[],
- TalerErrorDetail
-> {
- const { fetcher, multiFetcher } = useBackendInstanceRequest();
-
- const { data: list, error: listError } = useSWR<
- HttpResponseOk<TalerMerchantApi.InventorySummaryResponse>,
- RequestError<TalerErrorDetail>
- >([`/private/products`], fetcher, {
- refreshInterval: 0,
- refreshWhenHidden: false,
- revalidateOnFocus: false,
- revalidateOnReconnect: false,
- refreshWhenOffline: false,
- });
-
- const paths = (list?.data.products || []).map(
- (p) => `/private/products/${p.product_id}`,
+type ProductWithId = TalerMerchantApi.ProductDetail & { id: string, serial: number };
+function notUndefined(c: ProductWithId | undefined): c is ProductWithId {
+ return c !== undefined;
+}
+
+export function revalidateInstanceProducts() {
+ return mutate(
+ (key) => Array.isArray(key) && key[key.length - 1] === "listProductsWithId",
+ undefined,
+ { revalidate: true },
);
- const { data: products, error: productError } = useSWR<
- HttpResponseOk<TalerMerchantApi.ProductDetail>[],
- RequestError<TalerErrorDetail>
- >([paths], multiFetcher, {
- refreshInterval: 0,
- refreshWhenHidden: false,
- revalidateOnFocus: false,
- revalidateOnReconnect: false,
- refreshWhenOffline: false,
- });
-
- if (listError) return listError.cause;
- if (productError) return productError.cause;
-
- if (products) {
- const dataWithId = products.map((d) => {
- //take the id from the queried url
- return {
- ...d.data,
- id: d.info?.url.replace(/.*\/private\/products\//, "") || "",
- };
+}
+export function useInstanceProducts() {
+ const { state: session } = useSessionContext();
+ const { lib: { management } } = useMerchantApiContext();
+
+ const [offset, setOffset] = useState<number | undefined>();
+
+ async function fetcher([token, bid]: [AccessToken, number]) {
+ const list = await management.listProducts(token, {
+ limit: PAGE_SIZE,
+ offset: String(bid),
+ order: "dec",
});
- return { ok: true, data: dataWithId };
+ if (list.type !== "ok") {
+ return list;
+ }
+ const all: Array<ProductWithId | undefined> = await Promise.all(
+ list.body.products.map(async (c) => {
+ const r = await management.getProductDetails(token, c.product_id);
+ if (r.type === "fail") {
+ return undefined;
+ }
+ return { ...r.body, id: c.product_id, serial: c.product_serial };
+ }),
+ );
+ const products = all.filter(notUndefined);
+
+ return opFixedSuccess({ products });
}
- return { loading: true };
+
+ const { data, error } = useSWR<
+ OperationOk<{ products: ProductWithId[] }> |
+ TalerMerchantManagementErrorsByMethod<"listProducts">,
+ TalerHttpError
+ >([session.token, offset, "listProductsWithId"], fetcher);
+
+ if (error) return error;
+ if (data === undefined) return undefined;
+ if (data.type !== "ok") return data;
+
+ return buildPaginatedResult(data.body.products, offset, setOffset, (d) => d.serial)
+}
+
+export function revalidateProductDetails() {
+ return mutate(
+ (key) => Array.isArray(key) && key[key.length - 1] === "getProductDetails",
+ undefined,
+ { revalidate: true },
+ );
}
+export function useProductDetails(productId: string) {
+ const { state: session } = useSessionContext();
+ const { lib: { management } } = useMerchantApiContext();
+
+ async function fetcher([pid, token]: [string, AccessToken]) {
+ return await management.getProductDetails(token, pid);
+ }
+
+ const { data, error } = useSWR<
+ TalerMerchantManagementResultByMethod<"getProductDetails">,
+ TalerHttpError
+ >([productId, session.token, "getProductDetails"], fetcher);
-export function useProductDetails(
- productId: string,
-): HttpResponse<
- TalerMerchantApi.ProductDetail,
- TalerErrorDetail
-> {
- const { fetcher } = useBackendInstanceRequest();
-
- const { data, error, isValidating } = useSWR<
- HttpResponseOk<TalerMerchantApi.ProductDetail>,
- RequestError<TalerErrorDetail>
- >([`/private/products/${productId}`], fetcher, {
- refreshInterval: 0,
- refreshWhenHidden: false,
- revalidateOnFocus: false,
- revalidateOnReconnect: false,
- refreshWhenOffline: false,
- });
-
- 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;
}