fix(dashboard): RMA allow shipping unset (#12021)
**What** - allow unsetting shipping in RMA flows + bug cleanup around shipping flows in claims / exchanges - additional fixes: - product type create form - product type delete - delete confirmation messages - fix a few inventory strings + material field --- CLOSES CMRC-945 CLOSES CMRC-953 CLOSES CMRC-967 CLOSES CMRC-963 CLOSES CMRC-954 Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
@@ -3034,6 +3034,9 @@
|
||||
"manageLocations": {
|
||||
"type": "string"
|
||||
},
|
||||
"manageLocationQuantity": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleteWarning": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -3252,6 +3255,7 @@
|
||||
"locationLevels",
|
||||
"associatedVariants",
|
||||
"manageLocations",
|
||||
"manageLocationQuantity",
|
||||
"deleteWarning",
|
||||
"editItemDetails",
|
||||
"create",
|
||||
|
||||
@@ -811,6 +811,7 @@
|
||||
"locationLevels": "Locations",
|
||||
"associatedVariants": "Associated variants",
|
||||
"manageLocations": "Manage locations",
|
||||
"manageLocationQuantity": "Manage location quantity",
|
||||
"deleteWarning": "You are about to delete an inventory item. This action cannot be undone.",
|
||||
"editItemDetails": "Edit item details",
|
||||
"create": {
|
||||
@@ -1501,7 +1502,7 @@
|
||||
"successToast": "Location {{name}} was successfully updated."
|
||||
},
|
||||
"delete": {
|
||||
"confirmation": "You are about to delete the stock location {{name}}. This action cannot be undone."
|
||||
"confirmation": "You are about to delete the stock location \"{{name}}\". This action cannot be undone."
|
||||
},
|
||||
"fulfillmentProviders": {
|
||||
"header": "Fulfillment Providers",
|
||||
@@ -1520,7 +1521,7 @@
|
||||
"header": "Shipping"
|
||||
},
|
||||
"disable": {
|
||||
"confirmation": "Are you sure that you want to disable {{name}}? This will delete all associated service zones and shipping options, and cannot be undone.",
|
||||
"confirmation": "Are you sure that you want to disable \"{{name}}\"? This will delete all associated service zones and shipping options, and cannot be undone.",
|
||||
"pickup": "Pickup was successfully disabled.",
|
||||
"shipping": "Shipping was successfully disabled."
|
||||
},
|
||||
@@ -1577,7 +1578,7 @@
|
||||
"action": "Create option"
|
||||
},
|
||||
"delete": {
|
||||
"confirmation": "You are about to delete the shipping option {{name}}. This action cannot be undone.",
|
||||
"confirmation": "You are about to delete the shipping option \"{{name}}\". This action cannot be undone.",
|
||||
"successToast": "Shipping option {{name}} was successfully deleted."
|
||||
},
|
||||
"edit": {
|
||||
@@ -1666,7 +1667,7 @@
|
||||
"successToast": "Service zone {{name}} was successfully updated."
|
||||
},
|
||||
"delete": {
|
||||
"confirmation": "You are about to delete the service zone {{name}}. This action cannot be undone.",
|
||||
"confirmation": "You are about to delete the service zone \"{{name}}\". This action cannot be undone.",
|
||||
"successToast": "Service zone {{name}} was successfully deleted."
|
||||
},
|
||||
"manageAreas": {
|
||||
@@ -1831,7 +1832,7 @@
|
||||
"successToast": "Tax rate was successfully updated."
|
||||
},
|
||||
"delete": {
|
||||
"confirmation": "You are about to delete the tax rate {{name}}. This action cannot be undone.",
|
||||
"confirmation": "You are about to delete the tax rate \"{{name}}\". This action cannot be undone.",
|
||||
"successToast": "Tax rate was successfully deleted."
|
||||
}
|
||||
},
|
||||
@@ -2089,11 +2090,11 @@
|
||||
},
|
||||
"value_type": {
|
||||
"fixed": {
|
||||
"title": "Promotion Value",
|
||||
"title": "Fixed amount",
|
||||
"description": "The amount to be discounted. eg. 100"
|
||||
},
|
||||
"percentage": {
|
||||
"title": "Promotion Value",
|
||||
"title": "Percentage",
|
||||
"description": "The percentage to discount off the amount. eg. 8%"
|
||||
}
|
||||
}
|
||||
@@ -2206,8 +2207,8 @@
|
||||
"domain": "Price Lists",
|
||||
"subtitle": "Create sales or override prices for specific conditions.",
|
||||
"delete": {
|
||||
"confirmation": "You are about to delete the price list {{title}}. This action cannot be undone.",
|
||||
"successToast": "Price list {{title}} was successfully deleted."
|
||||
"confirmation": "You are about to delete the price list \"{{title}}\". This action cannot be undone.",
|
||||
"successToast": "Price list \"{{title}}\" was successfully deleted."
|
||||
},
|
||||
"create": {
|
||||
"header": "Create Price List",
|
||||
@@ -2643,8 +2644,8 @@
|
||||
"successToast": "Return reason {{label}} was successfully updated."
|
||||
},
|
||||
"delete": {
|
||||
"confirmation": "You are about to delete the return reason {{label}}. This action cannot be undone.",
|
||||
"successToast": "Return reason {{label}} was successfully deleted."
|
||||
"confirmation": "You are about to delete the return reason \"{{label}}\". This action cannot be undone.",
|
||||
"successToast": "Return reason \"{{label}}\" was successfully deleted."
|
||||
},
|
||||
"fields": {
|
||||
"value": {
|
||||
@@ -2764,8 +2765,8 @@
|
||||
"successToast": "Product type {{value}} was successfully updated."
|
||||
},
|
||||
"delete": {
|
||||
"confirmation": "You are about to delete the product type {{value}}. This action cannot be undone.",
|
||||
"successToast": "Product type {{value}} was successfully deleted."
|
||||
"confirmation": "You are about to delete the product type \"{{value}}\". This action cannot be undone.",
|
||||
"successToast": "Product type \"{{value}}\" was successfully deleted."
|
||||
},
|
||||
"fields": {
|
||||
"value": "Value"
|
||||
|
||||
@@ -41,7 +41,7 @@ export const AdjustInventoryDrawer = () => {
|
||||
return (
|
||||
<RouteDrawer>
|
||||
<RouteDrawer.Header>
|
||||
<Heading>{t("inventory.manageLocations")}</Heading>
|
||||
<Heading>{t("inventory.manageLocationQuantity")}</Heading>
|
||||
</RouteDrawer.Header>
|
||||
{ready && (
|
||||
<AdjustInventoryForm
|
||||
|
||||
@@ -24,6 +24,7 @@ const EditInventoryItemAttributesSchema = z.object({
|
||||
length: z.number().positive().optional(),
|
||||
weight: z.number().positive().optional(),
|
||||
mid_code: z.string().optional(),
|
||||
material: z.string().optional(),
|
||||
hs_code: z.string().optional(),
|
||||
origin_country: z.string().optional(),
|
||||
})
|
||||
@@ -35,6 +36,7 @@ const getDefaultValues = (item: InventoryTypes.InventoryItemDTO) => {
|
||||
length: item.length ?? undefined,
|
||||
weight: item.weight ?? undefined,
|
||||
mid_code: item.mid_code ?? undefined,
|
||||
material: item.material ?? undefined,
|
||||
hs_code: item.hs_code ?? undefined,
|
||||
origin_country: item.origin_country ?? undefined,
|
||||
}
|
||||
@@ -216,6 +218,21 @@ export const EditInventoryItemAttributesForm = ({
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="material"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label optional>{t("fields.material")}</Form.Label>
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
|
||||
@@ -39,6 +39,7 @@ export const InventoryItemAttributeSection = ({
|
||||
<SectionRow title={t("fields.length")} value={inventoryItem.length} />
|
||||
<SectionRow title={t("fields.weight")} value={inventoryItem.weight} />
|
||||
<SectionRow title={t("fields.midCode")} value={inventoryItem.mid_code} />
|
||||
<SectionRow title={t("fields.material")} value={inventoryItem.material} />
|
||||
<SectionRow title={t("fields.hsCode")} value={inventoryItem.hs_code} />
|
||||
<SectionRow
|
||||
title={t("fields.countryOfOrigin")}
|
||||
|
||||
@@ -425,13 +425,15 @@ export const ClaimCreateForm = ({
|
||||
await updateReturn({ location_id: selectedLocationId })
|
||||
}
|
||||
|
||||
const onShippingOptionChange = async (selectedOptionId: string) => {
|
||||
const onShippingOptionChange = async (
|
||||
selectedOptionId: string | undefined
|
||||
) => {
|
||||
const inboundShippingMethods = preview.shipping_methods.filter((s) => {
|
||||
const action = s.actions?.find(
|
||||
(a) => a.action === "SHIPPING_ADD" && !!a.return_id
|
||||
)
|
||||
|
||||
return action && !action?.return_id
|
||||
return action && !!action?.return_id
|
||||
})
|
||||
|
||||
const promises = inboundShippingMethods
|
||||
@@ -448,14 +450,16 @@ export const ClaimCreateForm = ({
|
||||
|
||||
await Promise.all(promises)
|
||||
|
||||
await addInboundShipping(
|
||||
{ shipping_option_id: selectedOptionId },
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(error.message)
|
||||
},
|
||||
}
|
||||
)
|
||||
if (selectedOptionId) {
|
||||
await addInboundShipping(
|
||||
{ shipping_option_id: selectedOptionId },
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(error.message)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@@ -740,10 +744,11 @@ export const ClaimCreateForm = ({
|
||||
<Form.Item>
|
||||
<Form.Control>
|
||||
<Combobox
|
||||
allowClear
|
||||
value={value ?? undefined}
|
||||
onChange={(val) => {
|
||||
onChange(val)
|
||||
val && onShippingOptionChange(val)
|
||||
onShippingOptionChange(val)
|
||||
}}
|
||||
{...field}
|
||||
options={inboundShippingOptions.map((so) => ({
|
||||
|
||||
@@ -197,7 +197,9 @@ export const ClaimOutboundSection = ({
|
||||
setIsOpen("outbound-items", false)
|
||||
}
|
||||
|
||||
const onShippingOptionChange = async (selectedOptionId: string) => {
|
||||
const onShippingOptionChange = async (
|
||||
selectedOptionId: string | undefined
|
||||
) => {
|
||||
const outboundShippingMethods = preview.shipping_methods.filter((s) => {
|
||||
const action = s.actions?.find(
|
||||
(a) => a.action === "SHIPPING_ADD" && !a.return_id
|
||||
@@ -220,14 +222,16 @@ export const ClaimOutboundSection = ({
|
||||
|
||||
await Promise.all(promises)
|
||||
|
||||
await addOutboundShipping(
|
||||
{ shipping_option_id: selectedOptionId },
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(error.message)
|
||||
},
|
||||
}
|
||||
)
|
||||
if (selectedOptionId) {
|
||||
await addOutboundShipping(
|
||||
{ shipping_option_id: selectedOptionId },
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(error.message)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const showLevelsWarning = useMemo(() => {
|
||||
@@ -403,10 +407,11 @@ export const ClaimOutboundSection = ({
|
||||
<Form.Item>
|
||||
<Form.Control>
|
||||
<Combobox
|
||||
allowClear
|
||||
value={value ?? undefined}
|
||||
onChange={(val) => {
|
||||
onChange(val)
|
||||
val && onShippingOptionChange(val)
|
||||
onShippingOptionChange(val)
|
||||
}}
|
||||
{...field}
|
||||
options={outboundShippingOptions.map((so) => ({
|
||||
|
||||
@@ -199,7 +199,7 @@ export const ExchangeInboundSection = ({
|
||||
inboundShippingMethod.shipping_option_id
|
||||
)
|
||||
} else {
|
||||
form.setValue("inbound_option_id", null)
|
||||
form.setValue("inbound_option_id", "")
|
||||
}
|
||||
}, [preview.shipping_methods])
|
||||
|
||||
@@ -246,7 +246,9 @@ export const ExchangeInboundSection = ({
|
||||
await updateReturn({ location_id: selectedLocationId })
|
||||
}
|
||||
|
||||
const onShippingOptionChange = async (selectedOptionId: string) => {
|
||||
const onShippingOptionChange = async (
|
||||
selectedOptionId: string | undefined
|
||||
) => {
|
||||
const inboundShippingMethods = preview.shipping_methods.filter((s) =>
|
||||
s.actions?.find((a) => a.action === "SHIPPING_ADD" && !!a.return_id)
|
||||
)
|
||||
@@ -265,14 +267,16 @@ export const ExchangeInboundSection = ({
|
||||
|
||||
await Promise.all(promises)
|
||||
|
||||
await addInboundShipping(
|
||||
{ shipping_option_id: selectedOptionId },
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(error.message)
|
||||
},
|
||||
}
|
||||
)
|
||||
if (selectedOptionId) {
|
||||
await addInboundShipping(
|
||||
{ shipping_option_id: selectedOptionId },
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(error.message)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const showLevelsWarning = useMemo(() => {
|
||||
@@ -505,10 +509,11 @@ export const ExchangeInboundSection = ({
|
||||
<Form.Item>
|
||||
<Form.Control>
|
||||
<Combobox
|
||||
allowClear
|
||||
value={value ?? undefined}
|
||||
onChange={(val) => {
|
||||
onChange(val)
|
||||
val && onShippingOptionChange(val)
|
||||
onShippingOptionChange(val)
|
||||
}}
|
||||
{...field}
|
||||
options={inboundShippingOptions.map((so) => ({
|
||||
|
||||
@@ -30,7 +30,6 @@ import { ItemPlaceholder } from "../../../order-create-claim/components/claim-cr
|
||||
import { AddExchangeOutboundItemsTable } from "../add-exchange-outbound-items-table"
|
||||
import { ExchangeOutboundItem } from "./exchange-outbound-item"
|
||||
import { CreateExchangeSchemaType } from "./schema"
|
||||
import { log } from "console"
|
||||
|
||||
type ExchangeOutboundSectionProps = {
|
||||
order: AdminOrder
|
||||
@@ -206,11 +205,13 @@ export const ExchangeOutboundSection = ({
|
||||
if (outboundShipping) {
|
||||
form.setValue("outbound_option_id", outboundShipping.shipping_option_id)
|
||||
} else {
|
||||
form.setValue("outbound_option_id", null)
|
||||
form.setValue("outbound_option_id", "")
|
||||
}
|
||||
}, [preview.shipping_methods])
|
||||
|
||||
const onShippingOptionChange = async (selectedOptionId: string) => {
|
||||
const onShippingOptionChange = async (
|
||||
selectedOptionId: string | undefined
|
||||
) => {
|
||||
const outboundShippingMethods = preview.shipping_methods.filter(
|
||||
(s) =>
|
||||
!!s.actions?.find((a) => a.action === "SHIPPING_ADD" && !a.return_id)
|
||||
@@ -230,14 +231,16 @@ export const ExchangeOutboundSection = ({
|
||||
|
||||
await Promise.all(promises)
|
||||
|
||||
await addOutboundShipping(
|
||||
{ shipping_option_id: selectedOptionId },
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(error.message)
|
||||
},
|
||||
}
|
||||
)
|
||||
if (selectedOptionId) {
|
||||
await addOutboundShipping(
|
||||
{ shipping_option_id: selectedOptionId },
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(error.message)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const showLevelsWarning = useMemo(() => {
|
||||
@@ -412,11 +415,12 @@ export const ExchangeOutboundSection = ({
|
||||
<Form.Item>
|
||||
<Form.Control>
|
||||
<Combobox
|
||||
allowClear
|
||||
noResultsPlaceholder={<OutboundShippingPlaceholder />}
|
||||
value={value ?? undefined}
|
||||
onChange={(val) => {
|
||||
onChange(val)
|
||||
val && onShippingOptionChange(val)
|
||||
onShippingOptionChange(val)
|
||||
}}
|
||||
{...field}
|
||||
options={outboundShippingOptions.map((so) => ({
|
||||
|
||||
@@ -292,7 +292,9 @@ export const ReturnCreateForm = ({
|
||||
await updateReturnRequest({ location_id: selectedLocationId })
|
||||
}
|
||||
|
||||
const onShippingOptionChange = async (selectedOptionId: string) => {
|
||||
const onShippingOptionChange = async (
|
||||
selectedOptionId: string | undefined
|
||||
) => {
|
||||
const promises = preview.shipping_methods
|
||||
.map((s) => s.actions?.find((a) => a.action === "SHIPPING_ADD")?.id)
|
||||
.filter(Boolean)
|
||||
@@ -300,7 +302,9 @@ export const ReturnCreateForm = ({
|
||||
|
||||
await Promise.all(promises)
|
||||
|
||||
await addReturnShipping({ shipping_option_id: selectedOptionId })
|
||||
if (selectedOptionId) {
|
||||
await addReturnShipping({ shipping_option_id: selectedOptionId })
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@@ -562,7 +566,6 @@ export const ReturnCreateForm = ({
|
||||
</Form.Hint>
|
||||
</div>
|
||||
|
||||
{/* TODO: WHAT IF THE RETURN OPTION HAS COMPUTED PRICE*/}
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="option_id"
|
||||
@@ -571,6 +574,7 @@ export const ReturnCreateForm = ({
|
||||
<Form.Item>
|
||||
<Form.Control>
|
||||
<Combobox
|
||||
allowClear
|
||||
value={value}
|
||||
onChange={(v) => {
|
||||
onChange(v)
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import { useNavigate } from "react-router-dom"
|
||||
import { toast, usePrompt } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { useDeleteProductType } from "../../../../hooks/api/product-types"
|
||||
|
||||
export const useDeleteProductTypeAction = (id: string) => {
|
||||
export const useDeleteProductTypeAction = (id: string, value: string) => {
|
||||
const { t } = useTranslation()
|
||||
const prompt = usePrompt()
|
||||
const navigate = useNavigate()
|
||||
|
||||
const { mutateAsync } = useDeleteProductType(id)
|
||||
|
||||
const handleDelete = async () => {
|
||||
const result = await prompt({
|
||||
title: t("general.areYouSure"),
|
||||
description: t("productTypes.delete.confirmation"),
|
||||
description: t("productTypes.delete.confirmation", { value }),
|
||||
confirmText: t("actions.delete"),
|
||||
cancelText: t("actions.cancel"),
|
||||
})
|
||||
@@ -22,7 +25,8 @@ export const useDeleteProductTypeAction = (id: string) => {
|
||||
|
||||
await mutateAsync(undefined, {
|
||||
onSuccess: () => {
|
||||
toast.success(t("productTypes.delete.successToast"))
|
||||
navigate("/settings/product-types", { replace: true })
|
||||
toast.success(t("productTypes.delete.successToast", { value }))
|
||||
},
|
||||
onError: (e) => {
|
||||
toast.error(e.message)
|
||||
|
||||
@@ -34,7 +34,7 @@ export const CreateProductTypeForm = () => {
|
||||
onSuccess: ({ product_type }) => {
|
||||
toast.success(
|
||||
t("productTypes.create.successToast", {
|
||||
value: product_type.value,
|
||||
value: product_type.value.trim(),
|
||||
})
|
||||
)
|
||||
|
||||
@@ -49,28 +49,8 @@ export const CreateProductTypeForm = () => {
|
||||
|
||||
return (
|
||||
<RouteFocusModal.Form form={form}>
|
||||
<KeyboundForm
|
||||
onSubmit={handleSubmit}
|
||||
className="flex flex-col overflow-hidden"
|
||||
>
|
||||
<RouteFocusModal.Header>
|
||||
<div className="flex items-center justify-end gap-x-2">
|
||||
<RouteFocusModal.Close asChild>
|
||||
<Button size="small" variant="secondary">
|
||||
{t("actions.cancel")}
|
||||
</Button>
|
||||
</RouteFocusModal.Close>
|
||||
<Button
|
||||
size="small"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
isLoading={isPending}
|
||||
>
|
||||
{t("actions.create")}
|
||||
</Button>
|
||||
</div>
|
||||
</RouteFocusModal.Header>
|
||||
<RouteFocusModal.Body className="flex flex-col items-center overflow-y-auto p-16">
|
||||
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||
<RouteFocusModal.Body className="flex flex-col items-center overflow-auto p-16">
|
||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
||||
<div>
|
||||
<Heading>{t("productTypes.create.header")}</Heading>
|
||||
@@ -97,6 +77,23 @@ export const CreateProductTypeForm = () => {
|
||||
</div>
|
||||
</div>
|
||||
</RouteFocusModal.Body>
|
||||
<RouteFocusModal.Footer>
|
||||
<div className="flex items-center justify-end gap-x-2">
|
||||
<RouteFocusModal.Close asChild>
|
||||
<Button size="small" variant="secondary">
|
||||
{t("actions.cancel")}
|
||||
</Button>
|
||||
</RouteFocusModal.Close>
|
||||
<Button
|
||||
size="small"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
isLoading={isPending}
|
||||
>
|
||||
{t("actions.create")}
|
||||
</Button>
|
||||
</div>
|
||||
</RouteFocusModal.Footer>
|
||||
</KeyboundForm>
|
||||
</RouteFocusModal.Form>
|
||||
)
|
||||
|
||||
@@ -13,7 +13,10 @@ export const ProductTypeGeneralSection = ({
|
||||
productType,
|
||||
}: ProductTypeGeneralSectionProps) => {
|
||||
const { t } = useTranslation()
|
||||
const handleDelete = useDeleteProductTypeAction(productType.id)
|
||||
const handleDelete = useDeleteProductTypeAction(
|
||||
productType.id,
|
||||
productType.value
|
||||
)
|
||||
|
||||
return (
|
||||
<Container className="flex items-center justify-between">
|
||||
|
||||
@@ -12,7 +12,10 @@ export const ProductTypeRowActions = ({
|
||||
productType,
|
||||
}: ProductTypeRowActionsProps) => {
|
||||
const { t } = useTranslation()
|
||||
const handleDelete = useDeleteProductTypeAction(productType.id)
|
||||
const handleDelete = useDeleteProductTypeAction(
|
||||
productType.id,
|
||||
productType.value
|
||||
)
|
||||
|
||||
return (
|
||||
<ActionMenu
|
||||
|
||||
Reference in New Issue
Block a user