From 842939ab1ebcc0b70f6dbb29cf2c6f0228105b23 Mon Sep 17 00:00:00 2001 From: Aloento <11802769+Aloento@users.noreply.github.com> Date: Mon, 19 Feb 2024 17:53:10 +0100 Subject: [PATCH] [Back] OrderPostClose / Cancel: string - [Front] useOrder replace IOrderRef | useSWR refresh | mutate (#109) * Update OrderGetItems and OrderGetCmts methods * Update Nav function calls in Order components * Update order handling methods and components Updated various methods and components related to order handling. The return type of `OrderPostClose` and `OrderPostCancel` methods in `Post.cs` and `useClose` and `useCancel` methods in `OrderPost` and `AdminOrderPost` classes have been changed from `Task` to `Task`. Renamed `OrderDeleteCancel` method in `Delete.cs` to `OrderDeleteCancelled` and updated `useDelete` method in `OrderDelete` class to invoke the renamed method. Added a `refresh` method to `useSWR` function in `useSWR.ts` to clear cache or remove item from local storage before refreshing data. Removed `Order`, `Status`, and `Refresh` props from `OrderDetailDrawer`, `OrderInfo`, `AdminOrderAction`, and `OrderAction` components in `Drawer.tsx`, `Info.tsx`, and `Action.tsx` respectively, and replaced them with `useOrder` hook. Updated `useItems` method in `OrderGet` class in `Get.ts` to fetch product photo only if `admin` parameter is not true. --- SoarCraft.AwaiShop/AdminHub/Order/Post.cs | 8 ++-- SoarCraft.AwaiShop/Hub/Order/Delete.cs | 2 +- SoarCraft.AwaiShop/Hub/Order/Get.cs | 4 +- SoarCraft.AwaiShop/Hub/Order/Post.cs | 10 +++-- SoarCraft.AwaiShop/SoarCraft.AwaiShop.csproj | 4 +- src/Components/Order/Append.tsx | 44 ++++++++++---------- src/Components/Order/Comment.tsx | 4 +- src/Components/Order/Drawer.tsx | 34 ++++----------- src/Components/Order/Info.tsx | 25 ++++++----- src/Components/Order/index.tsx | 13 +----- src/Components/Order/useOrder.ts | 25 +++++++++++ src/Helpers/useSWR.ts | 16 +++++-- src/Pages/Admin/Order/Action.tsx | 25 ++++++----- src/Pages/Admin/Order/Ship.tsx | 26 +++++------- src/Pages/History/Action.tsx | 22 +++++----- src/ShopNet/Admin/Order/Post.ts | 11 ++--- src/ShopNet/Order/Delete.ts | 2 +- src/ShopNet/Order/Get.ts | 16 ++++--- src/ShopNet/Order/Post.ts | 10 ++--- 19 files changed, 160 insertions(+), 141 deletions(-) create mode 100644 src/Components/Order/useOrder.ts diff --git a/SoarCraft.AwaiShop/AdminHub/Order/Post.cs b/SoarCraft.AwaiShop/AdminHub/Order/Post.cs index d4916496..512c1bf7 100644 --- a/SoarCraft.AwaiShop/AdminHub/Order/Post.cs +++ b/SoarCraft.AwaiShop/AdminHub/Order/Post.cs @@ -41,10 +41,10 @@ await this.Db.Comments.AddAsync(new() { * * @author Aloento * @since 0.5.0 - * @version 1.2.0 + * @version 1.3.0 * */ - public async Task OrderPostClose(uint orderId, string reason) { + public async Task OrderPostClose(uint orderId, string reason) { var valid = typeof(Comment) .GetProperty(nameof(Comment.Content))! .GetCustomAttribute()!; @@ -72,7 +72,9 @@ await this.Db.Comments.AddAsync(new() { Order = order, }); - return await this.Db.SaveChangesAsync() > 0; + await this.Db.SaveChangesAsync(); + + return order.Status.ToString(); } /** diff --git a/SoarCraft.AwaiShop/Hub/Order/Delete.cs b/SoarCraft.AwaiShop/Hub/Order/Delete.cs index 31e309c1..f7905c0b 100644 --- a/SoarCraft.AwaiShop/Hub/Order/Delete.cs +++ b/SoarCraft.AwaiShop/Hub/Order/Delete.cs @@ -13,7 +13,7 @@ internal partial class ShopHub { * */ [Authorize] - public async Task OrderDeleteCancel(uint orderId) { + public async Task OrderDeleteCancelled(uint orderId) { var row = await this.Db.Orders .Where(x => x.UserId == this.UserId) .Where(x => x.OrderId == orderId) diff --git a/SoarCraft.AwaiShop/Hub/Order/Get.cs b/SoarCraft.AwaiShop/Hub/Order/Get.cs index 76c85d2c..3f8f0071 100644 --- a/SoarCraft.AwaiShop/Hub/Order/Get.cs +++ b/SoarCraft.AwaiShop/Hub/Order/Get.cs @@ -32,8 +32,8 @@ await this.Db.Orders [Authorize] public async Task OrderGetItems(uint orderId) => await this.Db.OrderCombos - .Where(x => x.Order.UserId == this.UserId) .Where(x => x.OrderId == orderId) + .Where(x => x.Order.UserId == this.UserId) .Select(x => new { x.Quantity, Types = x.Combo.Types.Select(t => t.TypeId).ToArray() @@ -50,8 +50,8 @@ await this.Db.OrderCombos [Authorize] public Task OrderGetCmts(uint orderId) => this.Db.Comments - .Where(x => x.Order.UserId == this.UserId) .Where(x => x.OrderId == orderId) + .Where(x => x.Order.UserId == this.UserId) .Select(x => x.CommentId) .ToArrayAsync(); } diff --git a/SoarCraft.AwaiShop/Hub/Order/Post.cs b/SoarCraft.AwaiShop/Hub/Order/Post.cs index 7d012268..8cb2fba2 100644 --- a/SoarCraft.AwaiShop/Hub/Order/Post.cs +++ b/SoarCraft.AwaiShop/Hub/Order/Post.cs @@ -105,11 +105,11 @@ await this.Db.Comments.AddAsync(new() { * * @author Aloento * @since 0.5.0 - * @version 1.2.0 + * @version 1.3.0 * */ [Authorize] - public async Task OrderPostCancel(uint orderId, string reason) { + public async Task OrderPostCancel(uint orderId, string reason) { var valid = typeof(Comment) .GetProperty(nameof(Comment.Content))! .GetCustomAttribute()!; @@ -118,8 +118,8 @@ public async Task OrderPostCancel(uint orderId, string reason) { throw new HubException(valid.FormatErrorMessage("Reason")); var order = await this.Db.Orders - .Where(x => x.UserId == this.UserId) .Where(x => x.OrderId == orderId) + .Where(x => x.UserId == this.UserId) .Where(x => x.Status != OrderStatus.Cancelled) .Where(x => x.Status != OrderStatus.Finished) .Include(x => x.OrderCombos) @@ -139,7 +139,9 @@ await this.Db.Comments.AddAsync(new() { Order = order }); - return await this.Db.SaveChangesAsync() > 0; + await this.Db.SaveChangesAsync(); + + return order.Status.ToString(); } /** diff --git a/SoarCraft.AwaiShop/SoarCraft.AwaiShop.csproj b/SoarCraft.AwaiShop/SoarCraft.AwaiShop.csproj index c94095af..1147eb40 100644 --- a/SoarCraft.AwaiShop/SoarCraft.AwaiShop.csproj +++ b/SoarCraft.AwaiShop/SoarCraft.AwaiShop.csproj @@ -38,10 +38,10 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/src/Components/Order/Append.tsx b/src/Components/Order/Append.tsx index 0b6532c7..349363e4 100644 --- a/src/Components/Order/Append.tsx +++ b/src/Components/Order/Append.tsx @@ -2,12 +2,11 @@ import { Button, Field, Textarea, Toast, ToastTitle, makeStyles } from "@fluentu import { useConst } from "@fluentui/react-hooks"; import { useState } from "react"; import { Flex } from "~/Helpers/Styles"; -import { useSWR } from "~/Helpers/useSWR"; import { useErrorToast } from "~/Helpers/useToast"; import { Hub } from "~/ShopNet"; import { AdminHub } from "~/ShopNet/Admin"; -import { SignalR } from "~/ShopNet/SignalR"; -import { IOrderRef } from "."; +import { IOrderComp } from "."; +import { useOrder } from "./useOrder"; /** * @author Aloento @@ -24,9 +23,9 @@ const useStyles = makeStyles({ /** * @author Aloento * @since 0.5.0 - * @version 1.2.0 + * @version 1.3.0 */ -export function CommentAppend({ OrderId, Refresh, Admin, ParentLog }: IOrderRef) { +export function CommentAppend({ OrderId, Refresh, Admin, ParentLog }: IOrderComp & { Refresh: () => void }) { const log = useConst(() => ParentLog.With("Append")); const style = useStyles(); @@ -34,9 +33,7 @@ export function CommentAppend({ OrderId, Refresh, Admin, ParentLog }: IOrderRef) const { dispatch, dispatchToast } = useErrorToast(log); - const hub = (Admin ? AdminHub : Hub).Order.Post as typeof AdminHub.Order.Post & typeof Hub.Order.Post; - - const { run: append } = hub.useAppend({ + const { run: append, loading } = (Admin ? AdminHub : Hub).Order.Post.useAppend({ manual: true, onError(e, req) { dispatch({ @@ -54,10 +51,13 @@ export function CommentAppend({ OrderId, Refresh, Admin, ParentLog }: IOrderRef) ); Refresh(); + setCmt(""); } }); - const { run: cancel } = (Admin ? hub.useClose : hub.useCancel)({ + const { data: order, mutate } = useOrder(OrderId, Admin); + + const { run: cancel, loading: submit } = (Admin ? AdminHub : Hub).Order.Post.useCancel({ manual: true, onError(e, params) { dispatch({ @@ -66,7 +66,7 @@ export function CommentAppend({ OrderId, Refresh, Admin, ParentLog }: IOrderRef) Error: e }); }, - onSuccess() { + onSuccess(data) { dispatchToast( Order {Admin ? "Closed" : "Cancelled"} @@ -74,18 +74,13 @@ export function CommentAppend({ OrderId, Refresh, Admin, ParentLog }: IOrderRef) { intent: "success" } ); - Refresh(); + mutate((old) => ({ + ...old!, + Status: data + })); } }); - const index = useConst(() => SignalR.Index(OrderId, Hub.Order.Get.order)); - - const { data: order } = useSWR( - index, - () => (Admin ? AdminHub : Hub).Order.Get.Order(OrderId), - { useMemory: true } - ); - switch (order?.Status) { case "Cancelled": case "Finished": @@ -100,7 +95,10 @@ export function CommentAppend({ OrderId, Refresh, Admin, ParentLog }: IOrderRef)
{ !(order?.Status === "Finished" || order?.Status === "Returning") && - } -
diff --git a/src/Components/Order/Comment.tsx b/src/Components/Order/Comment.tsx index 9e3aa5fe..2f4fccb1 100644 --- a/src/Components/Order/Comment.tsx +++ b/src/Components/Order/Comment.tsx @@ -22,7 +22,7 @@ export interface IComment { */ export function OrderComment({ OrderId, Admin, ParentLog }: IOrderComp) { const log = useConst(() => ParentLog.With("Comment")); - const { data, run } = Hub.Order.Get.useCmts(OrderId, log, Admin); + const { data, refresh } = Hub.Order.Get.useCmts(OrderId, log, Admin); return <> @@ -38,6 +38,6 @@ export function OrderComment({ OrderId, Admin, ParentLog }: IOrderComp) { )} - + ; } diff --git a/src/Components/Order/Drawer.tsx b/src/Components/Order/Drawer.tsx index 7b0dce0b..bd46b8ac 100644 --- a/src/Components/Order/Drawer.tsx +++ b/src/Components/Order/Drawer.tsx @@ -1,21 +1,16 @@ import { Body1Strong, Caption1, DataGridCell, DataGridHeaderCell, Link, TableColumnDefinition, createTableColumn, makeStyles, tokens } from "@fluentui/react-components"; -import { useConst } from "@fluentui/react-hooks"; import { DelegateDataGrid } from "~/Components/DataGrid"; import { OrderComment } from "~/Components/Order/Comment"; import { OrderInfo } from "~/Components/Order/Info"; import { ICartItem } from "~/Components/ShopCart"; import { MakeCoverCol } from "~/Helpers/CoverCol"; import { ColFlex } from "~/Helpers/Styles"; -import { useSWR } from "~/Helpers/useSWR"; import { AdminOrderAction } from "~/Pages/Admin/Order/Action"; import { AdminOrderList } from "~/Pages/Admin/Order/List"; import { Shipment } from "~/Pages/Admin/Order/Ship"; import { Hub } from "~/ShopNet"; -import { AdminHub } from "~/ShopNet/Admin"; -import { SignalR } from "~/ShopNet/SignalR"; import { IOrderComp } from "."; import { OrderAction } from "../../Pages/History/Action"; -import { useRouter } from "../Router"; /** * @author Aloento @@ -25,7 +20,8 @@ import { useRouter } from "../Router"; const useStyles = makeStyles({ body: { ...ColFlex, - rowGap: tokens.spacingVerticalL + rowGap: tokens.spacingVerticalL, + paddingBottom: tokens.spacingVerticalXXL }, prod: { ...ColFlex, @@ -82,38 +78,22 @@ const columns: TableColumnDefinition[] = [ /** * @author Aloento * @since 1.3.5 - * @version 1.3.0 + * @version 1.4.0 */ export function OrderDetailDrawer({ OrderId, Admin, ParentLog }: IOrderComp) { const style = useStyles(); - - const { Nav } = useRouter(); - const index = useConst(() => SignalR.Index(OrderId, Hub.Order.Get.order)); - - const { data: order, run } = useSWR( - index, - () => (Admin ? AdminHub : Hub).Order.Get.Order(OrderId), - { - onError(e) { - Nav("History"); - ParentLog.error(e); - }, - useMemory: true - } - ); - const { data: cart } = Hub.Order.Get.useItems(OrderId, ParentLog, Admin); return (
- + { Admin ? <> - + : + : - + }
); diff --git a/src/Components/Order/Info.tsx b/src/Components/Order/Info.tsx index df7e8763..dd167f0c 100644 --- a/src/Components/Order/Info.tsx +++ b/src/Components/Order/Info.tsx @@ -4,8 +4,9 @@ import { useRequest } from "ahooks"; import { ColFlex, Flex } from "~/Helpers/Styles"; import { Hub } from "~/ShopNet"; import { AdminHub } from "~/ShopNet/Admin"; -import type { OrderEntity } from "~/ShopNet/Order/Entity"; import type { IOrderComp } from "."; +import { useRouter } from "../Router"; +import { useOrder } from "./useOrder"; /** * @author Aloento @@ -21,19 +22,23 @@ const useStyles = makeStyles({ }, }); -interface IOrderInfo extends IOrderComp { - Order?: OrderEntity.Order; -} - /** * @author Aloento * @since 0.5.0 - * @version 1.0.0 + * @version 1.1.0 */ -export function OrderInfo({ OrderId, Order, Admin, ParentLog }: IOrderInfo) { +export function OrderInfo({ OrderId, Admin, ParentLog }: IOrderComp) { const log = useConst(() => ParentLog.With("Info")); const style = useStyles(); + const { Nav } = useRouter(); + const { data: order } = useOrder(OrderId, Admin, { + onError(e) { + Nav(Admin ? "Admin/Order" : "History"); + ParentLog.error(e); + } + }); + const { data: admin } = useRequest(() => AdminHub.User.Get.OrderUser(OrderId), { manual: !Admin, onError: log.error @@ -61,13 +66,13 @@ export function OrderInfo({ OrderId, Order, Admin, ParentLog }: IOrderInfo) {
- +
- +
@@ -83,7 +88,7 @@ export function OrderInfo({ OrderId, Order, Admin, ParentLog }: IOrderInfo) { !Admin &&
- +
} diff --git a/src/Components/Order/index.tsx b/src/Components/Order/index.tsx index 7d3290f8..45bf8325 100644 --- a/src/Components/Order/index.tsx +++ b/src/Components/Order/index.tsx @@ -13,15 +13,6 @@ export interface IOrderComp extends ICompLog { Admin?: true; } -/** - * @author Aloento - * @since 0.5.0 - * @version 0.2.0 - */ -export interface IOrderRef extends IOrderComp { - Refresh: () => void; -} - /** * @author Aloento * @since 0.5.0 @@ -42,7 +33,7 @@ export function OrderDetail({ OrderId, Admin, ParentLog }: IOrderComp) { } diff --git a/src/Pages/Admin/Order/Ship.tsx b/src/Pages/Admin/Order/Ship.tsx index ffb41f4f..9f73f307 100644 --- a/src/Pages/Admin/Order/Ship.tsx +++ b/src/Pages/Admin/Order/Ship.tsx @@ -2,34 +2,25 @@ import { Button, Field, Input, Toast, ToastTitle } from "@fluentui/react-compone import { EditRegular, SendRegular } from "@fluentui/react-icons"; import { useBoolean } from "ahooks"; import { useState } from "react"; +import { useOrder } from "~/Components/Order/useOrder"; import { Logger } from "~/Helpers/Logger"; import { useErrorToast } from "~/Helpers/useToast"; import { AdminHub } from "~/ShopNet/Admin"; -/** - * @author Aloento - * @since 1.0.0 - * @version 0.1.0 - */ -interface IShipment { - OrderId: number; - TrackingNumber?: string; - Refresh: () => void; -} - const log = new Logger("Admin", "Order", "Detail", "Shipment"); /** * @author Aloento * @since 0.5.0 - * @version 0.2.3 + * @version 0.3.0 */ -export function Shipment({ OrderId, TrackingNumber, Refresh }: IShipment) { +export function Shipment({ OrderId }: { OrderId: number }) { const [edit, { setTrue, setFalse }] = useBoolean(); - const [track, setTrack] = useState(TrackingNumber); - const { dispatch, dispatchToast } = useErrorToast(log); + const { data: order, mutate } = useOrder(OrderId, true); + const [track, setTrack] = useState(order?.TrackingNumber); + const { run } = AdminHub.Order.Post.useShip({ manual: true, onError(e, params) { @@ -48,7 +39,10 @@ export function Shipment({ OrderId, TrackingNumber, Refresh }: IShipment) { ); setFalse(); - Refresh(); + mutate((old) => ({ + ...old!, + TrackingNumber: track + })); } }); diff --git a/src/Pages/History/Action.tsx b/src/Pages/History/Action.tsx index 5e545080..d80eedca 100644 --- a/src/Pages/History/Action.tsx +++ b/src/Pages/History/Action.tsx @@ -1,7 +1,7 @@ import { Button, Field, Toast, ToastTitle, makeStyles } from "@fluentui/react-components"; -import { useConst } from "@fluentui/react-hooks"; -import { IOrderRef } from "~/Components/Order"; +import { useOrder } from "~/Components/Order/useOrder"; import { useRouter } from "~/Components/Router"; +import { Logger } from "~/Helpers/Logger"; import { ColFlex } from "~/Helpers/Styles"; import { useErrorToast } from "~/Helpers/useToast"; import { Hub } from "~/ShopNet"; @@ -18,16 +18,18 @@ const useStyles = makeStyles({ }, }); +const log = new Logger("History", "Detail", "Action"); + /** * @author Aloento * @since 1.0.0 - * @version 0.2.0 + * @version 0.3.0 */ -export function OrderAction({ OrderId, Status, Refresh, ParentLog }: IOrderRef & { Status?: string; }) { - const log = useConst(() => ParentLog.With("Action")); - +export function OrderAction({ OrderId }: { OrderId: number; }) { const style = useStyles(); const { Reload } = useRouter(); + + const { data: order, mutate } = useOrder(OrderId); const { dispatch, dispatchToast } = useErrorToast(log); const { run: received } = Hub.Order.Post.useReceived({ @@ -47,7 +49,7 @@ export function OrderAction({ OrderId, Status, Refresh, ParentLog }: IOrderRef & { intent: "success" } ); - Refresh(); + mutate((old) => ({ ...old!, Status: "Finished" })); } }); @@ -72,7 +74,7 @@ export function OrderAction({ OrderId, Status, Refresh, ParentLog }: IOrderRef & } }); - switch (Status) { + switch (order?.Status) { case "Pending": case "Processing": // case "Shipping": @@ -86,14 +88,14 @@ export function OrderAction({ OrderId, Status, Refresh, ParentLog }: IOrderRef &
{ - Status === "Cancelled" && + order?.Status === "Cancelled" && } { - Status === "Shipping" && + order?.Status === "Shipping" && diff --git a/src/ShopNet/Admin/Order/Post.ts b/src/ShopNet/Admin/Order/Post.ts index b4f40817..07438291 100644 --- a/src/ShopNet/Admin/Order/Post.ts +++ b/src/ShopNet/Admin/Order/Post.ts @@ -24,15 +24,12 @@ export abstract class AdminOrderPost extends AdminNet { /** * @author Aloento * @since 0.5.0 - * @version 0.2.1 + * @version 0.3.0 */ - public static useClose(options: Options) { - return useRequest(async (orderId, reason) => { - const res = await this.Invoke("OrderPostClose", orderId, reason); - this.EnsureTrue(res); - return res; - }, options); + public static useClose(options: Options) { + return useRequest((orderId, reason) => this.Invoke("OrderPostClose", orderId, reason), options); } + public static useCancel = this.useClose; /** * @author Aloento diff --git a/src/ShopNet/Order/Delete.ts b/src/ShopNet/Order/Delete.ts index dfa31f3a..1831f115 100644 --- a/src/ShopNet/Order/Delete.ts +++ b/src/ShopNet/Order/Delete.ts @@ -16,7 +16,7 @@ export abstract class OrderDelete extends ShopNet { public static useDelete(options: Options) { return useRequest(async orderId => { this.EnsureLogin(); - const res = await this.Invoke("OrderDeleteCancel", orderId); + const res = await this.Invoke("OrderDeleteCancelled", orderId); this.EnsureTrue(res); return res; }, options); diff --git a/src/ShopNet/Order/Get.ts b/src/ShopNet/Order/Get.ts index a0c26aae..9bc265f7 100644 --- a/src/ShopNet/Order/Get.ts +++ b/src/ShopNet/Order/Get.ts @@ -78,7 +78,7 @@ export abstract class OrderGet extends OrderEntity { /** * @author Aloento * @since 0.5.0 - * @version 2.1.0 + * @version 2.2.0 */ public static useItems(orderId: number, pLog: Logger, admin?: true) { const log = useConst(() => pLog.With(...this.Log, "Items")); @@ -136,15 +136,21 @@ export abstract class OrderGet extends OrderEntity { continue; } - const [_, cover] = await ProductGet.PhotoList(prodId, log); + let cover = ""; - if (!cover) - log.warn(`Product ${prodId} has no photo`); + if (!admin) { + const [_, res] = await ProductGet.PhotoList(prodId, log); + + if (!res) + log.warn(`Product ${prodId} has no photo`); + + cover = res; + } items.push({ Id: index++, ProdId: prodId, - Cover: cover || "", + Cover: cover, Name: prod.Name, Type: variType, Quantity: combo.Quantity, diff --git a/src/ShopNet/Order/Post.ts b/src/ShopNet/Order/Post.ts index 68f02236..ef195e66 100644 --- a/src/ShopNet/Order/Post.ts +++ b/src/ShopNet/Order/Post.ts @@ -47,14 +47,12 @@ export abstract class OrderPost extends ShopNet { /** * @author Aloento * @since 0.5.0 - * @version 0.2.0 + * @version 0.3.0 */ - public static useCancel(options: Options) { - return useRequest(async (orderId, reason) => { + public static useCancel(options: Options) { + return useRequest((orderId, reason) => { this.EnsureLogin(); - const res = await this.Invoke("OrderPostCancel", orderId, reason); - this.EnsureTrue(res); - return res; + return this.Invoke("OrderPostCancel", orderId, reason); }, options); }