diff --git a/src/Pages/History/Detail.tsx b/src/Pages/History/Detail.tsx index 3be4c88..fce0f43 100644 --- a/src/Pages/History/Detail.tsx +++ b/src/Pages/History/Detail.tsx @@ -1,4 +1,4 @@ -import { Body1Strong, Button, Caption1, DataGridCell, DataGridHeaderCell, Link, TableColumnDefinition, createTableColumn, makeStyles, tokens } from "@fluentui/react-components"; +import { Body1Strong, Button, Caption1, DataGridCell, DataGridHeaderCell, Link, SkeletonItem, TableColumnDefinition, createTableColumn, makeStyles, tokens } from "@fluentui/react-components"; import { Drawer, DrawerBody, DrawerHeader, DrawerHeaderTitle } from "@fluentui/react-components/unstable"; import { useConst } from "@fluentui/react-hooks"; import { DismissRegular, OpenRegular } from "@fluentui/react-icons"; @@ -146,8 +146,6 @@ function DeferredBody({ OrderId, ParentLog }: { OrderId: number } & ICompLog) { const style = useStyles(); const { Nav } = useRouter(); - const { data: cart, run: runItems } = Hub.Order.Get.useItems(OrderId, ParentLog); - const { data: order, run: runOrder } = useRequest(() => Hub.Order.Get.Order(OrderId), { onError(e) { Nav("History"); @@ -156,6 +154,8 @@ function DeferredBody({ OrderId, ParentLog }: { OrderId: number } & ICompLog) { manual: true }); + const { data: cart, run: runItems, loading } = Hub.Order.Get.useItems(OrderId, ParentLog); + const run = () => { runItems(); runOrder(); @@ -170,6 +170,8 @@ function DeferredBody({ OrderId, ParentLog }: { OrderId: number } & ICompLog) { Columns={[MakeCoverCol(44, ParentLog), ...columns]} /> + {loading && } + diff --git a/src/ShopNet/Order/Get.ts b/src/ShopNet/Order/Get.ts index 3016c71..b9bdf05 100644 --- a/src/ShopNet/Order/Get.ts +++ b/src/ShopNet/Order/Get.ts @@ -1,4 +1,5 @@ import { useConst } from "@fluentui/react-hooks"; +import { useAsyncEffect } from "ahooks"; import { useState } from "react"; import { IComment } from "~/Components/Order/Comment"; import { ICartItem } from "~/Components/ShopCart"; @@ -90,60 +91,65 @@ export abstract class OrderGet extends OrderEntity { this.items, { defaultParams: [orderId], - onError: log.error, - async onSuccess(meta) { - const items: ICartItem[] = []; - let index = 0; - - for (const combo of meta) { - const variType: Record = {}; - let prodId = 0; - - for (const typeId of combo.Types) { - const type = await ProductData.Type(typeId); - - if (!type) { - log.warn(`[Mismatch] Type ${typeId} not found. Order : ${orderId}`); - continue; - } - - const vari = await ProductData.Variant(type.VariantId); - - if (!vari) { - log.warn(`[Mismatch] Variant ${type.VariantId} not found. Type : ${typeId}, Order : ${orderId}`); - continue; - } - - variType[vari.Name] = type.Name; - prodId = vari.ProductId; - } - - const prod = await ProductData.Product(prodId); - - if (!prod) { - log.warn(`[Mismatch] Product ${prodId} not found. Order : ${orderId}`); - continue; - } - - const [_, cover] = await ProductGet.PhotoList(prodId, log); - - if (!cover) - log.warn(`Product ${prodId} has no photo`); - - items.push({ - Id: index++, - ProdId: prodId, - Cover: cover || "", - Name: prod.Name, - Type: variType, - Quantity: combo.Quantity, - }); + onError: log.error + } + ); + + useAsyncEffect(async () => { + const meta = req.data; + if (!meta) + return; + + const items: ICartItem[] = []; + let index = 0; + + for (const combo of meta) { + const variType: Record = {}; + let prodId = 0; + + for (const typeId of combo.Types) { + const type = await ProductData.Type(typeId); + + if (!type) { + log.warn(`[Mismatch] Type ${typeId} not found. Order : ${orderId}`); + continue; } - setRes(items); + const vari = await ProductData.Variant(type.VariantId); + + if (!vari) { + log.warn(`[Mismatch] Variant ${type.VariantId} not found. Type : ${typeId}, Order : ${orderId}`); + continue; + } + + variType[vari.Name] = type.Name; + prodId = vari.ProductId; } + + const prod = await ProductData.Product(prodId); + + if (!prod) { + log.warn(`[Mismatch] Product ${prodId} not found. Order : ${orderId}`); + continue; + } + + const [_, cover] = await ProductGet.PhotoList(prodId, log); + + if (!cover) + log.warn(`Product ${prodId} has no photo`); + + items.push({ + Id: index++, + ProdId: prodId, + Cover: cover || "", + Name: prod.Name, + Type: variType, + Quantity: combo.Quantity, + }); } - ); + + setRes(items); + }, [req.data]); return { ...req, diff --git a/src/ShopNet/SignalR.ts b/src/ShopNet/SignalR.ts index 14e069b..821b414 100644 --- a/src/ShopNet/SignalR.ts +++ b/src/ShopNet/SignalR.ts @@ -127,13 +127,20 @@ export abstract class SignalR { const update = async () => { const res = await Dexie.waitFor(this.Invoke(methodName, key, find?.Version)); + function setCache(value: T) { + Shared.Set(index, { + ...value, + QueryExp: dayjs().add(10, "s").unix() + }, dayjs().add(1, "w")); + } + if (res === true) { setCache(find!) return find!; } if (!res) { - await Shared.Sto.delete(index); + Shared.Sto.delete(index); throw new EmptyResponseError(); } @@ -142,20 +149,13 @@ export abstract class SignalR { } if (find) { - if (find.QueryExp <= dayjs().unix()) + if (find.QueryExp < dayjs().unix()) update(); return find; } return update(); - - function setCache(value: T) { - Shared.Set(index, { - ...value, - QueryExp: dayjs().add(5, "s").unix() - }, dayjs().add(1, "w")); - } } /** @@ -171,7 +171,7 @@ export abstract class SignalR { const req = useRequest( (...params) => this.Invoke(methodName, ...params), { - staleTime: 1000, + staleTime: 5000, ...options, cacheKey: index, setCache: (data) => localStorage.setItem(index, JSON.stringify(data)),