From dbb10ff0514b6cd46597f57e5a588e8d81336db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frane=20Poli=C4=87?= <16856471+fPolic@users.noreply.github.com> Date: Sun, 1 Sep 2024 09:49:14 +0200 Subject: [PATCH] feat(dashboard): order edits in timeline (#8899) **What** - add order edit confirmed/created events in the timeline - add order change endpoint clients - panel for active edit and pending edit - few fixes around the edit domain --- .../dashboard/src/hooks/api/order-edits.tsx | 12 +++ .../dashboard/src/hooks/api/orders.tsx | 27 +++++ .../dashboard/src/i18n/translations/en.json | 12 ++- .../order-active-edit-section.tsx | 36 +++++-- .../order-activity-section/order-timeline.tsx | 100 +++++++++++++++++- .../order-summary-section.tsx | 11 +- packages/core/js-sdk/src/admin/order.ts | 15 +++ .../types/src/http/order/admin/entities.ts | 1 + .../types/src/http/order/admin/queries.ts | 4 + packages/core/types/src/http/order/common.ts | 7 ++ 10 files changed, 213 insertions(+), 12 deletions(-) diff --git a/packages/admin-next/dashboard/src/hooks/api/order-edits.tsx b/packages/admin-next/dashboard/src/hooks/api/order-edits.tsx index f6378db891..796d975aa4 100644 --- a/packages/admin-next/dashboard/src/hooks/api/order-edits.tsx +++ b/packages/admin-next/dashboard/src/hooks/api/order-edits.tsx @@ -50,6 +50,10 @@ export const useRequestOrderEdit = ( queryClient.invalidateQueries({ queryKey: ordersQueryKeys.preview(id), }) + + queryClient.invalidateQueries({ + queryKey: ordersQueryKeys.changes(id), + }) options?.onSuccess?.(data, variables, context) }, ...options, @@ -74,6 +78,10 @@ export const useConfirmOrderEdit = ( queryClient.invalidateQueries({ queryKey: ordersQueryKeys.preview(id), }) + + queryClient.invalidateQueries({ + queryKey: ordersQueryKeys.changes(id), + }) options?.onSuccess?.(data, variables, context) }, ...options, @@ -94,6 +102,10 @@ export const useCancelOrderEdit = ( queryClient.invalidateQueries({ queryKey: ordersQueryKeys.preview(orderId), }) + + queryClient.invalidateQueries({ + queryKey: ordersQueryKeys.changes(id), + }) options?.onSuccess?.(data, variables, context) }, ...options, diff --git a/packages/admin-next/dashboard/src/hooks/api/orders.tsx b/packages/admin-next/dashboard/src/hooks/api/orders.tsx index 43ca8ade9b..45d4b565cd 100644 --- a/packages/admin-next/dashboard/src/hooks/api/orders.tsx +++ b/packages/admin-next/dashboard/src/hooks/api/orders.tsx @@ -18,12 +18,17 @@ const _orderKeys = queryKeysFactory(ORDERS_QUERY_KEY) as TQueryKey< string > & { preview: (orderId: string) => any + changes: (orderId: string) => any } _orderKeys.preview = function (id: string) { return [this.detail(id), "preview"] } +_orderKeys.changes = function (id: string) { + return [this.detail(id), "changes"] +} + export const ordersQueryKeys = _orderKeys export const useOrder = ( @@ -81,6 +86,28 @@ export const useOrders = ( return { ...data, ...rest } } +export const useOrderChanges = ( + id: string, + query?: HttpTypes.AdminOrderChangesFilters, + options?: Omit< + UseQueryOptions< + HttpTypes.AdminOrderChangesResponse, + Error, + HttpTypes.AdminOrderChangesResponse, + QueryKey + >, + "queryFn" | "queryKey" + > +) => { + const { data, ...rest } = useQuery({ + queryFn: async () => sdk.admin.order.listChanges(id, query), + queryKey: ordersQueryKeys.changes(id), + ...options, + }) + + return { ...data, ...rest } +} + export const useCreateOrderFulfillment = ( orderId: string, options?: UseMutationOptions< diff --git a/packages/admin-next/dashboard/src/i18n/translations/en.json b/packages/admin-next/dashboard/src/i18n/translations/en.json index cd5e23e8c1..9d8a3ea4ff 100644 --- a/packages/admin-next/dashboard/src/i18n/translations/en.json +++ b/packages/admin-next/dashboard/src/i18n/translations/en.json @@ -105,6 +105,7 @@ "revoke": "Revoke", "cancel": "Cancel", "forceConfirm": "Force confirm", + "continueEdit": "Continue edit", "enable": "Enable", "disable": "Disable", "undo": "Undo", @@ -837,7 +838,8 @@ "summary": { "requestReturn": "Request return", "allocateItems": "Allocate items", - "editOrder": "Edit order" + "editOrder": "Edit order", + "editOrderContinue": "Continue order edit" }, "payment": { "title": "Payments", @@ -890,7 +892,8 @@ "createSuccessToast": "Order edit request created", "activeChangeError": "There is already active order change on the order (return, claim, exchange etc.). Please finish or cancel the change before editing the order.", "panel": { - "title": "Order edit requested" + "title": "Order edit requested", + "titlePending": "Order edit pending" }, "toast": { "canceledSuccessfully": "Order edit cancelled", @@ -1162,6 +1165,11 @@ "created": "Exchange #{{exchangeId}} requested", "itemsInbound": "{{count}} item to return", "itemsOutbound": "{{count}} item to send" + }, + "edit": { + "requested": "Order edit #{{editId}} requested", + "requested": "Order edit #{{editId}} requested", + "confirmed": "Order edit #{{editId}} confirmed" } } } diff --git a/packages/admin-next/dashboard/src/routes/orders/order-detail/components/order-active-edit-section/order-active-edit-section.tsx b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/order-active-edit-section/order-active-edit-section.tsx index 4b901e9541..bd3cc3d541 100644 --- a/packages/admin-next/dashboard/src/routes/orders/order-detail/components/order-active-edit-section/order-active-edit-section.tsx +++ b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/order-active-edit-section/order-active-edit-section.tsx @@ -10,6 +10,7 @@ import { import { useMemo } from "react" import { HttpTypes } from "@medusajs/types" import { Thumbnail } from "../../../../../components/common/thumbnail" +import { useNavigate } from "react-router-dom" type OrderActiveEditSectionProps = { order: HttpTypes.AdminOrder @@ -51,12 +52,15 @@ export const OrderActiveEditSection = ({ order, }: OrderActiveEditSectionProps) => { const { t } = useTranslation() + const navigate = useNavigate() const { order: orderPreview } = useOrderPreview(order.id) const { mutateAsync: cancelOrderEdit } = useCancelOrderEdit(order.id) const { mutateAsync: confirmOrderEdit } = useConfirmOrderEdit(order.id) + const isPending = orderPreview.order_change?.status === "pending" + const [addedItems, removedItems] = useMemo(() => { const added = [] const removed = [] @@ -125,7 +129,13 @@ export const OrderActiveEditSection = ({
- {t("orders.edits.panel.title")} + + {t( + isPending + ? "orders.edits.panel.titlePending" + : "orders.edits.panel.title" + )} +
{/*ADDED ITEMS*/} @@ -155,13 +165,23 @@ export const OrderActiveEditSection = ({ )}
- + {isPending ? ( + + ) : ( + + )}
) } + +const OrderEditBody = ({ + edit, + itemsMap, +}: { + edit: AdminOrderChange + isRequested: boolean + itemsMap: Record +}) => { + const { t } = useTranslation() + + const [itemsAdded, itemsRemoved] = useMemo( + () => countItemsChange(edit.actions, itemsMap), + [edit] + ) + + return ( +
+ {itemsAdded > 0 && ( + + {t("labels.added")}: {itemsAdded} + + )} + + {itemsRemoved > 0 && ( + + {t("labels.removed")}: {itemsRemoved} + + )} +
+ ) +} + +function countItemsChange( + actions: AdminOrderChange["actions"], + itemsMap: Record +) { + let added = 0 + let removed = 0 + + actions.forEach((action) => { + if (action.action === "ITEM_ADD") { + added += action.details.quantity + } + if (action.action === "ITEM_UPDATE") { + const newQuantity: number = action.details!.quantity + const originalQuantity: number | undefined = itemsMap.get( + action.details!.reference_id + )?.quantity + + if (typeof originalQuantity === "number") { + const diff = Math.abs(newQuantity - originalQuantity) + + if (newQuantity > originalQuantity) { + added += diff + } + if (newQuantity < originalQuantity) { + removed += diff + } + } + } + }) + + return [added, removed] +} diff --git a/packages/admin-next/dashboard/src/routes/orders/order-detail/components/order-summary-section/order-summary-section.tsx b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/order-summary-section/order-summary-section.tsx index cfebe166e8..c2a209ac04 100644 --- a/packages/admin-next/dashboard/src/routes/orders/order-detail/components/order-summary-section/order-summary-section.tsx +++ b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/order-summary-section/order-summary-section.tsx @@ -285,6 +285,10 @@ const Header = ({ ) const isOrderEditActive = orderPreview?.order_change?.change_type === "edit" + // State where creation of order edit was interrupted i.e. order edit is drafted but not confirmed + const isOrderEditPending = + orderPreview?.order_change?.change_type === "edit" && + orderPreview?.order_change?.status === "pending" return (
@@ -294,7 +298,11 @@ const Header = ({ { actions: [ { - label: t("orders.summary.editOrder"), + label: t( + isOrderEditPending + ? "orders.summary.editOrderContinue" + : "orders.summary.editOrder" + ), to: `/orders/${order.id}/edits`, icon: , disabled: @@ -557,6 +565,7 @@ const CostBreakdown = ({ order }: { order: AdminOrder }) => { ) .map((sm, i) => ( + >(`/admin/orders/${id}/changes`, { + query: queryParams, + headers, + }) + } } diff --git a/packages/core/types/src/http/order/admin/entities.ts b/packages/core/types/src/http/order/admin/entities.ts index 9992d86b6e..6f0b35cc5b 100644 --- a/packages/core/types/src/http/order/admin/entities.ts +++ b/packages/core/types/src/http/order/admin/entities.ts @@ -25,6 +25,7 @@ export interface AdminOrder extends BaseOrder { export interface AdminOrderLineItem extends BaseOrderLineItem { variant?: AdminProductVariant } +export interface AdminOrderChange extends BaseOrderChange {} export interface AdminOrderFulfillment extends BaseOrderFulfillment {} diff --git a/packages/core/types/src/http/order/admin/queries.ts b/packages/core/types/src/http/order/admin/queries.ts index a4b6c56337..1be9e9b7d0 100644 --- a/packages/core/types/src/http/order/admin/queries.ts +++ b/packages/core/types/src/http/order/admin/queries.ts @@ -1,6 +1,7 @@ import { OperatorMap } from "../../../dal" import { FindParams } from "../../common" import { BaseOrderFilters } from "../common" +import { BaseOrderChangesFilters } from "../common" export interface AdminOrderFilters extends FindParams, BaseOrderFilters { id?: string[] | string @@ -13,3 +14,6 @@ export interface AdminOrderFilters extends FindParams, BaseOrderFilters { created_at?: OperatorMap updated_at?: OperatorMap } + + +export interface AdminOrderChangesFilters extends BaseOrderChangesFilters {} diff --git a/packages/core/types/src/http/order/common.ts b/packages/core/types/src/http/order/common.ts index 44b390a48f..498b4c4b7b 100644 --- a/packages/core/types/src/http/order/common.ts +++ b/packages/core/types/src/http/order/common.ts @@ -310,6 +310,13 @@ export interface BaseOrderFilters status?: string[] | string | OperatorMap } +export interface BaseOrderChangesFilters + extends BaseFilterable { + id?: string[] | string | OperatorMap + status?: string[] | string | OperatorMap + change_type?: string[] | string | OperatorMap +} + export interface BaseOrderChange { /** * The ID of the order change