feat(dashboard): cancel return request (#8761)

* wip: cancel return request

* fix: refactor

* feat: correct endpoint, add hook, fix types

* feat: add prompt
This commit is contained in:
Frane Polić
2024-08-27 13:57:12 +02:00
committed by GitHub
parent c11ef01c15
commit 9197bdd77b
5 changed files with 110 additions and 11 deletions

View File

@@ -53,10 +53,6 @@ export const useReturns = (
return { ...data, ...rest }
}
/**
* REQUEST RETURN
*/
export const useInitiateReturn = (
orderId: string,
options?: UseMutationOptions<
@@ -86,6 +82,39 @@ export const useInitiateReturn = (
})
}
export const useCancelReturn = (
id: string,
orderId: string,
options?: UseMutationOptions<HttpTypes.AdminReturnResponse, Error>
) => {
return useMutation({
mutationFn: () => sdk.admin.return.cancel(id),
onSuccess: (data: any, variables: any, context: any) => {
queryClient.invalidateQueries({
queryKey: ordersQueryKeys.details(),
})
queryClient.invalidateQueries({
queryKey: ordersQueryKeys.preview(orderId),
refetchType: "all",
})
queryClient.invalidateQueries({
queryKey: returnsQueryKeys.details(),
})
queryClient.invalidateQueries({
queryKey: returnsQueryKeys.lists(),
})
options?.onSuccess?.(data, variables, context)
},
...options,
})
}
/**
* REQUEST RETURN
*/
export const useConfirmReturnRequest = (
id: string,
orderId: string,

View File

@@ -897,6 +897,10 @@
"returnRequestedInfo": "{{requestedItemsCount}}x item return requested",
"returnReceivedInfo": "{{requestedItemsCount}}x item return received",
"activeChangeError": "There is an active order change in progress on this order. Please finish or discard the change first.",
"cancel": {
"title": "Cancel Return",
"description": "Are you sure you want to cancel the return request?"
},
"receive": {
"action": "Receive items",
"receive": "Return {{label}}",
@@ -1095,7 +1099,8 @@
"items_other": "{{count}} items"
},
"return": {
"created": "Return #{{returnId}} created",
"created": "Return #{{returnId}} requested",
"canceled": "Return #{{returnId}} canceled",
"received": "Return #{{returnId}} received",
"items_one": "{{count}} item returned",
"items_other": "{{count}} items returned"

View File

@@ -1,4 +1,4 @@
import { IconButton, Text, Tooltip, clx, usePrompt } from "@medusajs/ui"
import { IconButton, Text, Tooltip, clx, usePrompt, Button } from "@medusajs/ui"
import * as Collapsible from "@radix-ui/react-collapsible"
import { PropsWithChildren, ReactNode, useMemo, useState } from "react"
@@ -16,10 +16,10 @@ import { useTranslation } from "react-i18next"
import { useClaims } from "../../../../../hooks/api/claims"
import { useExchanges } from "../../../../../hooks/api/exchanges"
import { useReturns } from "../../../../../hooks/api/returns"
import { useDate } from "../../../../../hooks/use-date"
import { useCancelReturn, useReturns } from "../../../../../hooks/api/returns"
import { getStylizedAmount } from "../../../../../lib/money-amount-helpers"
import { getPaymentsFromOrder } from "../order-payment-section"
import { useDate } from "../../../../../hooks/use-date"
type OrderTimelineProps = {
order: AdminOrder
@@ -224,9 +224,18 @@ const useActivityItems = (order: AdminOrder) => {
returnId: ret.id.slice(-7),
}),
timestamp: ret.created_at,
children: <ReturnBody orderReturn={ret} />,
children: <ReturnBody orderReturn={ret} isCreated={!ret.canceled_at} />,
})
if (ret.canceled_at) {
items.push({
title: t("orders.activity.events.return.canceled", {
returnId: ret.id.slice(-7),
}),
timestamp: ret.canceled_at,
})
}
if (ret.status === "received" || ret.status === "partially_received") {
items.push({
title: t("orders.activity.events.return.received", {
@@ -486,20 +495,60 @@ const FulfillmentCreatedBody = ({
)
}
const ReturnBody = ({ orderReturn }: { orderReturn: AdminReturn }) => {
const ReturnBody = ({
orderReturn,
isCreated,
}: {
orderReturn: AdminReturn
isCreated: boolean
}) => {
const prompt = usePrompt()
const { t } = useTranslation()
const { mutateAsync: cancelReturnRequest } = useCancelReturn(
orderReturn.id,
orderReturn.order_id
)
const onCancel = async () => {
const res = await prompt({
title: t("orders.returns.cancel.title"),
description: t("orders.returns.cancel.description"),
confirmText: t("actions.confirm"),
cancelText: t("actions.cancel"),
})
if (!res) {
return
}
await cancelReturnRequest()
}
const numberOfItems = orderReturn.items.reduce((acc, item) => {
return acc + item.quantity
}, 0)
return (
<div>
<div className="flex items-start gap-1">
<Text size="small" className="text-ui-fg-subtle">
{t("orders.activity.events.return.items", {
count: numberOfItems,
})}
</Text>
{isCreated && (
<>
<div className="mt-[2px] flex items-center leading-none"></div>
<Button
onClick={onCancel}
className="text-ui-fg-subtle h-auto px-0 leading-none hover:bg-transparent"
variant="transparent"
size="small"
>
{t("actions.cancel")}
</Button>
</>
)}
</div>
)
}

View File

@@ -45,6 +45,21 @@ export class Return {
)
}
async cancel(
id: string,
query?: HttpTypes.SelectParams,
headers?: ClientHeaders
) {
return await this.client.fetch<HttpTypes.AdminReturnResponse>(
`/admin/returns/${id}/cancel`,
{
method: "POST",
headers,
query,
}
)
}
async cancelRequest(
id: string,
query?: HttpTypes.SelectParams,

View File

@@ -23,4 +23,5 @@ export interface BaseReturn {
items: BaseReturnItem[]
received_at: string
created_at: string
canceled_at: string
}