diff --git a/src/RookieShop.Application/Orders/Events/UpdatedOrderHandler.cs b/src/RookieShop.Application/Orders/Events/UpdatedOrderHandler.cs index d91153a4..83689f45 100644 --- a/src/RookieShop.Application/Orders/Events/UpdatedOrderHandler.cs +++ b/src/RookieShop.Application/Orders/Events/UpdatedOrderHandler.cs @@ -13,10 +13,10 @@ public async Task Handle(UpdatedOrderEvent notification, CancellationToken cance EmailMetadata metadata = new( $"Your order status has been updated to { notification.Order.OrderStatus switch { - OrderStatus.Pending => "Pending", - OrderStatus.Shipping => "Processing", - OrderStatus.Canceled => "Canceled", - OrderStatus.Completed => "Completed", + OrderStatus.Pending => nameof(OrderStatus.Pending), + OrderStatus.Shipping => nameof(OrderStatus.Shipping), + OrderStatus.Canceled => nameof(OrderStatus.Canceled), + OrderStatus.Completed => nameof(OrderStatus.Completed), _ => "Unknown" } }", "Order Status", diff --git a/ui/backoffice/app/(dashboard)/dashboard/order/[id]/page.tsx b/ui/backoffice/app/(dashboard)/dashboard/order/[id]/page.tsx index e69de29b..85bdf92b 100644 --- a/ui/backoffice/app/(dashboard)/dashboard/order/[id]/page.tsx +++ b/ui/backoffice/app/(dashboard)/dashboard/order/[id]/page.tsx @@ -0,0 +1,41 @@ +"use client" + +import useGetOrder from "@/features/order/useGetOrder" +import { Separator } from "@radix-ui/react-dropdown-menu" + +import BreadCrumb from "@/components/ui/breadcrumb" +import { Heading } from "@/components/ui/heading" +import { OrderForm } from "@/components/forms/order-form" +import OrderDetailTable from "@/components/tables/order_details/table" + +export default function EditOrder({ + params, +}: Readonly<{ params: { id: string } }>) { + const breadcrumbItems = [ + { title: "Order", link: "/dashboard/order" }, + { title: "Edit", link: `/dashboard/order/${params.id}` }, + ] + + const { data: GetOrder } = useGetOrder(params.id) + + console.log(GetOrder) + + return ( +
+ + {GetOrder && ( + + )} + +
+ +
+ +
+ ) +} diff --git a/ui/backoffice/components/forms/category-form.tsx b/ui/backoffice/components/forms/category-form.tsx index fc63949e..fa8f6f33 100644 --- a/ui/backoffice/components/forms/category-form.tsx +++ b/ui/backoffice/components/forms/category-form.tsx @@ -61,8 +61,6 @@ export const CategoryForm: FC = ({ initialData }) => { description: "", } - console.log("defaultValues", defaultValues) - const form = useForm({ resolver: zodResolver(categorySchema), defaultValues, diff --git a/ui/backoffice/components/forms/order-form.tsx b/ui/backoffice/components/forms/order-form.tsx new file mode 100644 index 00000000..c6076561 --- /dev/null +++ b/ui/backoffice/components/forms/order-form.tsx @@ -0,0 +1,160 @@ +"use client" + +import { FC, useEffect } from "react" +import { useRouter } from "next/navigation" +import { OrderStatus, UpdateOrderRequest } from "@/features/order/order.type" +import useUpdateOrder from "@/features/order/useUpdateOrder" +import { zodResolver } from "@hookform/resolvers/zod" +import { useForm } from "react-hook-form" +import { z } from "zod" + +import { orderSchema } from "@/lib/validations/order" + +import { Button } from "../ui/button" +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "../ui/form" +import { Heading } from "../ui/heading" +import { Input } from "../ui/input" +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectTrigger, + SelectValue, +} from "../ui/select" +import { Separator } from "../ui/separator" +import { useToast } from "../ui/use-toast" + +type OrderFormValues = z.infer + +type OrderFormProps = { + initialData: UpdateOrderRequest +} + +export const OrderForm: FC = ({ initialData }) => { + const router = useRouter() + const { toast } = useToast() + const { + mutate: updateOrder, + isSuccess: updateOrderSuccess, + isPending: updateOrderPending, + } = useUpdateOrder() + + const isDisabled = updateOrderSuccess || updateOrderPending + + const title = "Edit order" + const description = "Edit an order." + const toastMessage = "Order updated." + const action = "Save changes" + + const defaultValues = initialData + + const form = useForm({ + resolver: zodResolver(orderSchema), + defaultValues, + }) + + const onSubmit = async (data: OrderFormValues) => { + try { + updateOrder(data) + + console.log("Order data: ", data) + } catch (error: any) { + toast({ + variant: "destructive", + title: "Uh oh! Something went wrong.", + description: "There was a problem with your request.", + }) + } + } + + useEffect(() => { + if (updateOrderSuccess) { + toast({ + title: "Success!", + description: toastMessage, + }) + + setTimeout(() => { + router.replace(`/dashboard/order`) + }, 2000) + } + }, [updateOrderSuccess]) + + return ( + <> +
+ +
+ +
+ +
+ ( + + Name + + + + + + )} + /> + ( + + Status + + + + )} + /> +
+ +
+ + + ) +} diff --git a/ui/backoffice/components/forms/profile-form.tsx b/ui/backoffice/components/forms/profile-form.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/ui/backoffice/components/tables/order/columns.tsx b/ui/backoffice/components/tables/order/columns.tsx index 0d50ce76..5e6b6c42 100644 --- a/ui/backoffice/components/tables/order/columns.tsx +++ b/ui/backoffice/components/tables/order/columns.tsx @@ -20,25 +20,23 @@ export const columns: ColumnDef[] = [ header: "CARD", cell: (props) => { const { last4, brand, chargeId } = props.row.original - if (last4 === null && brand === null && chargeId === null) { - return - } else { - return ( -
- - Last4: {last4} - -
- - Brand: {brand} - -
- - Charge ID: {chargeId} - -
- ) - } + return last4 === null && brand === null && chargeId === null ? ( + + ) : ( +
+ + Last4: {last4} + +
+ + Brand: {brand} + +
+ + Charge ID: {chargeId} + +
+ ) }, }, { diff --git a/ui/backoffice/components/tables/order_details/columns.tsx b/ui/backoffice/components/tables/order_details/columns.tsx new file mode 100644 index 00000000..701ae7d2 --- /dev/null +++ b/ui/backoffice/components/tables/order_details/columns.tsx @@ -0,0 +1,36 @@ +"use client" + +import { OrderItem } from "@/features/order/order.type" +import { ColumnDef } from "@tanstack/react-table" + +export const columns: ColumnDef[] = [ + { + accessorKey: "id", + header: "PRODUCT ID", + }, + { + accessorKey: "price", + header: "PRICE", + cell: (props) => { + const price = props.getValue() as number + return new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + }).format(price) + }, + }, + { + accessorKey: "quantity", + header: "QUANTITY", + }, + { + header: "TOTAL", + cell: (props) => { + const { price, quantity } = props.row.original + return new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + }).format(price * quantity) + }, + }, +] diff --git a/ui/backoffice/components/tables/order_details/table.tsx b/ui/backoffice/components/tables/order_details/table.tsx new file mode 100644 index 00000000..a00efa3a --- /dev/null +++ b/ui/backoffice/components/tables/order_details/table.tsx @@ -0,0 +1,24 @@ +"use client" + +import { OrderItem } from "@/features/order/order.type" + +import FilterTable from "@/components/custom/filter-table" + +import { columns } from "./columns" + +export default function OrderDetailTable({ + data, +}: Readonly<{ + data: OrderItem[] +}>) { + return ( + + ) +} diff --git a/ui/backoffice/components/tables/product/columns.tsx b/ui/backoffice/components/tables/product/columns.tsx index 476e2093..cce9f12e 100644 --- a/ui/backoffice/components/tables/product/columns.tsx +++ b/ui/backoffice/components/tables/product/columns.tsx @@ -159,6 +159,10 @@ export const columns: ColumnDef[] = [ ) }, }, + { + accessorKey: "totalReviews", + header: "REVIEWS", + }, { accessorKey: "createdDate", header: "CREATED", diff --git a/ui/backoffice/features/order/order.type.ts b/ui/backoffice/features/order/order.type.ts index 6d96cd05..0d2a89ce 100644 --- a/ui/backoffice/features/order/order.type.ts +++ b/ui/backoffice/features/order/order.type.ts @@ -35,10 +35,10 @@ export enum PaymentMethod { } export enum OrderStatus { - Pending = 1, - Shipping = 2, - Completed = 3, - Cancelled = 4, + Pending = "Pending", + Shipping = "Shipping", + Completed = "Completed", + Cancelled = "Cancelled", } export type OrderFilterParams = PagingFilter & { diff --git a/ui/backoffice/lib/validations/order.ts b/ui/backoffice/lib/validations/order.ts new file mode 100644 index 00000000..d952007b --- /dev/null +++ b/ui/backoffice/lib/validations/order.ts @@ -0,0 +1,7 @@ +import { OrderStatus } from "@/features/order/order.type" +import { z } from "zod" + +export const orderSchema = z.object({ + id: z.string(), + orderStatus: z.nativeEnum(OrderStatus), +})