diff --git a/packages/admin-next/dashboard/src/i18n/translations/en.json b/packages/admin-next/dashboard/src/i18n/translations/en.json index b30df2b76f..7cc3cbe80a 100644 --- a/packages/admin-next/dashboard/src/i18n/translations/en.json +++ b/packages/admin-next/dashboard/src/i18n/translations/en.json @@ -912,6 +912,14 @@ "errorNegativeValue": "Quantity cannot be a negative value.", "errorLargeDamagedValue": "Damaged items quantity + non damaged received quantity exceeds total item quantity on the return. Please decrease quantity of non damaged items." } + }, + "toast": { + "canceledSuccessfully": "Return canceled successfully", + "confirmedSuccessfully": "Return confirmed successfully" + }, + "panel": { + "title": "Return initiated", + "description": "There is an open return request to be completed" } }, "claims": { @@ -931,6 +939,14 @@ }, "tooltips": { "onlyReturnShippingOptions": "This list will consist of only return shipping options." + }, + "toast": { + "canceledSuccessfully": "Claim canceled successfully", + "confirmedSuccessfully": "Claim confirmed successfully" + }, + "panel": { + "title": "Claim initiated", + "description": "There is an open claim request to be completed" } }, "exchanges": { @@ -950,6 +966,14 @@ }, "tooltips": { "onlyReturnShippingOptions": "This list will consist of only return shipping options." + }, + "toast": { + "canceledSuccessfully": "Exchange canceled successfully", + "confirmedSuccessfully": "Exchange confirmed successfully" + }, + "panel": { + "title": "Exchange initiated", + "description": "There is an open exchange request to be completed" } }, "reservations": { diff --git a/packages/admin-next/dashboard/src/routes/orders/order-create-claim/components/claim-create-form/claim-create-form.tsx b/packages/admin-next/dashboard/src/routes/orders/order-create-claim/components/claim-create-form/claim-create-form.tsx index ef049675ac..50d5fe5afb 100644 --- a/packages/admin-next/dashboard/src/routes/orders/order-create-claim/components/claim-create-form/claim-create-form.tsx +++ b/packages/admin-next/dashboard/src/routes/orders/order-create-claim/components/claim-create-form/claim-create-form.tsx @@ -307,15 +307,19 @@ export const ClaimCreateForm = ({ const shippingOptionId = form.watch("inbound_option_id") const handleSubmit = form.handleSubmit(async (data) => { - try { - await confirmClaimRequest({ no_notification: !data.send_notification }) + await confirmClaimRequest( + { no_notification: !data.send_notification }, + { + onSuccess: () => { + toast.success(t("orders.claims.toast.confirmedSuccessfully")) - handleSuccess() - } catch (e) { - toast.error(t("general.error"), { - description: e.message, - }) - } + handleSuccess() + }, + onError: (error) => { + toast.error(error.message) + }, + } + ) }) const onItemsSelected = async () => { diff --git a/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-claim-section/active-order-claim-section.tsx b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-claim-section/active-order-claim-section.tsx new file mode 100644 index 0000000000..0d7bb8b4bd --- /dev/null +++ b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-claim-section/active-order-claim-section.tsx @@ -0,0 +1,79 @@ +import { ExclamationCircle } from "@medusajs/icons" +import { Button, Container, Heading, Text, toast } from "@medusajs/ui" +import { useTranslation } from "react-i18next" + +import { HttpTypes } from "@medusajs/types" +import { useNavigate } from "react-router-dom" +import { useCancelClaimRequest } from "../../../../../hooks/api/claims" + +type ActiveOrderClaimSectionProps = { + orderPreview: HttpTypes.AdminOrderPreview +} + +export const ActiveOrderClaimSection = ({ + orderPreview, +}: ActiveOrderClaimSectionProps) => { + const { t } = useTranslation() + const claimId = orderPreview?.order_change?.claim_id + + const { mutateAsync: cancelClaim } = useCancelClaimRequest( + claimId, + orderPreview.id + ) + + const navigate = useNavigate() + + const onContinueClaim = async () => { + navigate(`/orders/${orderPreview.id}/claims`) + } + + const onCancelClaim = async () => { + await cancelClaim(undefined, { + onSuccess: () => { + toast.success(t("orders.claims.toast.canceledSuccessfully")) + }, + onError: (error) => { + toast.error(error.message) + }, + }) + } + + if (!claimId) { + return + } + + return ( +
+ +
+
+
+ + {t("orders.claims.panel.title")} +
+ +
+ {t("orders.claims.panel.description")} +
+
+ +
+ + + +
+
+
+
+ ) +} diff --git a/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-claim-section/index.ts b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-claim-section/index.ts new file mode 100644 index 0000000000..1e5038872c --- /dev/null +++ b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-claim-section/index.ts @@ -0,0 +1 @@ +export * from "./active-order-claim-section" diff --git a/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-exchange-section/active-order-exchange-section.tsx b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-exchange-section/active-order-exchange-section.tsx new file mode 100644 index 0000000000..26645a5291 --- /dev/null +++ b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-exchange-section/active-order-exchange-section.tsx @@ -0,0 +1,83 @@ +import { ArrowPath } from "@medusajs/icons" +import { Button, Container, Heading, Text, toast } from "@medusajs/ui" +import { useTranslation } from "react-i18next" + +import { HttpTypes } from "@medusajs/types" +import { useNavigate } from "react-router-dom" +import { useCancelExchangeRequest } from "../../../../../hooks/api/exchanges" + +type ActiveOrderExchangeSectionProps = { + orderPreview: HttpTypes.AdminOrderPreview +} + +export const ActiveOrderExchangeSection = ({ + orderPreview, +}: ActiveOrderExchangeSectionProps) => { + const { t } = useTranslation() + const exchangeId = orderPreview?.order_change?.exchange_id + + const { mutateAsync: cancelExchange } = useCancelExchangeRequest( + exchangeId, + orderPreview.id + ) + + const navigate = useNavigate() + + const onContinueExchange = async () => { + navigate(`/orders/${orderPreview.id}/exchanges`) + } + + const onCancelExchange = async () => { + await cancelExchange(undefined, { + onSuccess: () => { + toast.success(t("orders.exchanges.toast.canceledSuccessfully")) + }, + onError: (error) => { + toast.error(error.message) + }, + }) + } + + if (!exchangeId) { + return + } + + return ( +
+ +
+
+
+ + {t("orders.exchanges.panel.title")} +
+ +
+ {t("orders.exchanges.panel.description")} +
+
+ +
+ + + +
+
+
+
+ ) +} diff --git a/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-exchange-section/index.ts b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-exchange-section/index.ts new file mode 100644 index 0000000000..f04f4f86f8 --- /dev/null +++ b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-exchange-section/index.ts @@ -0,0 +1 @@ +export * from "./active-order-exchange-section" diff --git a/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-return-section/active-order-return-section.tsx b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-return-section/active-order-return-section.tsx new file mode 100644 index 0000000000..d8d6c67d78 --- /dev/null +++ b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-return-section/active-order-return-section.tsx @@ -0,0 +1,82 @@ +import { ArrowUturnLeft } from "@medusajs/icons" +import { Button, Container, Heading, Text, toast } from "@medusajs/ui" +import { useTranslation } from "react-i18next" + +import { HttpTypes } from "@medusajs/types" +import { useNavigate } from "react-router-dom" +import { useCancelReturnRequest } from "../../../../../hooks/api/returns" + +type ActiveOrderReturnSectionProps = { + orderPreview: HttpTypes.AdminOrderPreview +} + +export const ActiveOrderReturnSection = ({ + orderPreview, +}: ActiveOrderReturnSectionProps) => { + const { t } = useTranslation() + const orderChange = orderPreview?.order_change + const returnId = orderChange?.return_id + const isReturnRequest = + orderChange?.change_type === "return_request" && !!orderChange.return_id + + const { mutateAsync: cancelReturn } = useCancelReturnRequest( + returnId, + orderPreview.id + ) + + const navigate = useNavigate() + + const onContinueReturn = async () => { + navigate(`/orders/${orderPreview.id}/returns`) + } + + const onCancelReturn = async () => { + await cancelReturn(undefined, { + onSuccess: () => { + toast.success(t("orders.returns.toast.canceledSuccessfully")) + }, + onError: (error) => { + toast.error(error.message) + }, + }) + } + + if (!returnId || !isReturnRequest) { + return + } + + return ( +
+ +
+
+
+ + {t("orders.returns.panel.title")} +
+ +
+ {t("orders.returns.panel.description")} +
+
+ +
+ + + +
+
+
+
+ ) +} diff --git a/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-return-section/index.ts b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-return-section/index.ts new file mode 100644 index 0000000000..8b32fa6b7c --- /dev/null +++ b/packages/admin-next/dashboard/src/routes/orders/order-detail/components/active-order-return-section/index.ts @@ -0,0 +1 @@ +export * from "./active-order-return-section" 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 865511abcd..abd26f1fe5 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 @@ -249,6 +249,8 @@ const Header = ({ (i) => !(getReturnableQuantity(i) > 0) ) + const isOrderEditActive = orderPreview?.order_change?.change_type === "edit" + return (
{t("fields.summary")} @@ -281,6 +283,7 @@ const Header = ({ icon: , disabled: shouldDisableReturn || + isOrderEditActive || !!orderPreview?.order_change?.exchange_id || !!orderPreview?.order_change?.claim_id, }, @@ -294,6 +297,7 @@ const Header = ({ icon: , disabled: shouldDisableReturn || + isOrderEditActive || (!!orderPreview?.order_change?.return_id && !!!orderPreview?.order_change?.exchange_id) || !!orderPreview?.order_change?.claim_id, @@ -308,6 +312,7 @@ const Header = ({ icon: , disabled: shouldDisableReturn || + isOrderEditActive || (!!orderPreview?.order_change?.return_id && !!!orderPreview?.order_change?.claim_id) || !!orderPreview?.order_change?.exchange_id, diff --git a/packages/admin-next/dashboard/src/routes/orders/order-detail/order-detail.tsx b/packages/admin-next/dashboard/src/routes/orders/order-detail/order-detail.tsx index 38f8a5ecee..4ab1be45db 100644 --- a/packages/admin-next/dashboard/src/routes/orders/order-detail/order-detail.tsx +++ b/packages/admin-next/dashboard/src/routes/orders/order-detail/order-detail.tsx @@ -1,7 +1,7 @@ import { Outlet, useLoaderData, useParams } from "react-router-dom" import { JsonViewSection } from "../../../components/common/json-view-section" -import { useOrder } from "../../../hooks/api/orders" +import { useOrder, useOrderPreview } from "../../../hooks/api/orders" import { OrderActivitySection } from "./components/order-activity-section" import { OrderCustomerSection } from "./components/order-customer-section" import { OrderFulfillmentSection } from "./components/order-fulfillment-section" @@ -15,6 +15,9 @@ import after from "virtual:medusa/widgets/order/details/after" import before from "virtual:medusa/widgets/order/details/before" import sideAfter from "virtual:medusa/widgets/order/details/side/after" import sideBefore from "virtual:medusa/widgets/order/details/side/before" +import { ActiveOrderClaimSection } from "./components/active-order-claim-section" +import { ActiveOrderExchangeSection } from "./components/active-order-exchange-section" +import { ActiveOrderReturnSection } from "./components/active-order-return-section" import { OrderActiveEditSection } from "./components/order-active-edit-section" export const OrderDetail = () => { @@ -31,8 +34,11 @@ export const OrderDetail = () => { initialData, } ) + const { order: orderPreview, isLoading: isPreviewLoading } = useOrderPreview( + id! + ) - if (isLoading || !order) { + if (isLoading || !order || isPreviewLoading) { return
Loading...
} @@ -52,6 +58,9 @@ export const OrderDetail = () => {
+ + + diff --git a/packages/core/types/src/http/order/common.ts b/packages/core/types/src/http/order/common.ts index 73311d78b8..cd887545e2 100644 --- a/packages/core/types/src/http/order/common.ts +++ b/packages/core/types/src/http/order/common.ts @@ -321,7 +321,7 @@ export interface BaseOrderChange { /** * The type of the order change */ - change_type?: "return" | "exchange" | "claim" | "edit" + change_type?: "return" | "exchange" | "claim" | "edit" | "return_request" /** * The ID of the associated order