diff --git a/.changeset/metal-singers-watch.md b/.changeset/metal-singers-watch.md new file mode 100644 index 0000000000..7685aa4b4d --- /dev/null +++ b/.changeset/metal-singers-watch.md @@ -0,0 +1,5 @@ +--- +"@medusajs/admin-ui": patch +--- + +fix(admin-ui): delete inventory items when removing product diff --git a/packages/admin-ui/ui/src/components/templates/product-table/use-product-actions.tsx b/packages/admin-ui/ui/src/components/templates/product-table/use-product-actions.tsx index 5af83b01af..3ba9658245 100644 --- a/packages/admin-ui/ui/src/components/templates/product-table/use-product-actions.tsx +++ b/packages/admin-ui/ui/src/components/templates/product-table/use-product-actions.tsx @@ -1,17 +1,25 @@ -import { Product } from "@medusajs/medusa" -import { useAdminDeleteProduct, useAdminUpdateProduct } from "medusa-react" -import { useNavigate } from "react-router-dom" -import { useTranslation } from "react-i18next" -import useImperativeDialog from "../../../hooks/use-imperative-dialog" -import useNotification from "../../../hooks/use-notification" -import { getErrorMessage } from "../../../utils/error-messages" +import { + adminInventoryItemsKeys, + useAdminDeleteProduct, + useAdminUpdateProduct, + useMedusa, +} from "medusa-react" + +import { ActionType } from "../../molecules/actionables" import DuplicateIcon from "../../fundamentals/icons/duplicate-icon" import EditIcon from "../../fundamentals/icons/edit-icon" +import { Product } from "@medusajs/medusa" import PublishIcon from "../../fundamentals/icons/publish-icon" import TrashIcon from "../../fundamentals/icons/trash-icon" import UnpublishIcon from "../../fundamentals/icons/unpublish-icon" -import { ActionType } from "../../molecules/actionables" +import { getErrorMessage } from "../../../utils/error-messages" import useCopyProduct from "./use-copy-product" +import { useFeatureFlag } from "../../../providers/feature-flag-provider" +import useImperativeDialog from "../../../hooks/use-imperative-dialog" +import { useNavigate } from "react-router-dom" +import useNotification from "../../../hooks/use-notification" +import { useQueryClient } from "@tanstack/react-query" +import { useTranslation } from "react-i18next" const useProductActions = (product: Product) => { const { t } = useTranslation() @@ -21,6 +29,9 @@ const useProductActions = (product: Product) => { const copyProduct = useCopyProduct() const deleteProduct = useAdminDeleteProduct(product?.id) const updateProduct = useAdminUpdateProduct(product?.id) + const queryClient = useQueryClient() + const { isFeatureEnabled } = useFeatureFlag() + const { client } = useMedusa() const handleDelete = async () => { const shouldDelete = await dialog({ @@ -32,6 +43,22 @@ const useProductActions = (product: Product) => { }) if (shouldDelete) { + if (isFeatureEnabled("inventoryService")) { + const { variants } = await client.admin.variants.list({ + id: product.variants.map((v) => v.id), + expand: "inventory_items", + }) + + variants + .filter(({ inventory_items }) => !!inventory_items?.length) + .map(({ inventory_items }) => + client.admin.inventoryItems.delete( + inventory_items![0].inventory_item_id + ) + ) + queryClient.invalidateQueries(adminInventoryItemsKeys.lists()) + } + deleteProduct.mutate() } } diff --git a/packages/admin-ui/ui/src/hooks/use-edit-product-actions.tsx b/packages/admin-ui/ui/src/hooks/use-edit-product-actions.tsx index 8b61aeb134..dca980c9fd 100644 --- a/packages/admin-ui/ui/src/hooks/use-edit-product-actions.tsx +++ b/packages/admin-ui/ui/src/hooks/use-edit-product-actions.tsx @@ -5,19 +5,22 @@ import { Product, } from "@medusajs/medusa" import { + adminInventoryItemsKeys, useAdminCreateVariant, useAdminDeleteProduct, useAdminDeleteVariant, useAdminProduct, useAdminUpdateProduct, useAdminUpdateVariant, + useMedusa, } from "medusa-react" import { getErrorMessage } from "../utils/error-messages" -import { removeFalsy } from "../utils/remove-nullish" +import { useFeatureFlag } from "../providers/feature-flag-provider" import useImperativeDialog from "./use-imperative-dialog" import { useNavigate } from "react-router-dom" import useNotification from "./use-notification" +import { useQueryClient } from "@tanstack/react-query" const useEditProductActions = (productId: string) => { const dialog = useImperativeDialog() @@ -29,13 +32,33 @@ const useEditProductActions = (productId: string) => { const updateVariant = useAdminUpdateVariant(productId) const deleteVariant = useAdminDeleteVariant(productId) const addVariant = useAdminCreateVariant(productId) + const queryClient = useQueryClient() + const { isFeatureEnabled } = useFeatureFlag() + const { client } = useMedusa() const onDelete = async () => { const shouldDelete = await dialog({ heading: "Delete Product", text: "Are you sure you want to delete this product", }) + if (shouldDelete) { + if (isFeatureEnabled("inventoryService") && getProduct.product) { + const { variants } = await client.admin.variants.list({ + id: getProduct.product.variants.map((v) => v.id), + expand: "inventory_items", + }) + + variants + .filter(({ inventory_items }) => !!inventory_items?.length) + .map(({ inventory_items }) => + client.admin.inventoryItems.delete( + inventory_items![0].inventory_item_id + ) + ) + queryClient.invalidateQueries(adminInventoryItemsKeys.lists()) + } + deleteProduct.mutate(undefined, { onSuccess: () => { notification("Success", "Product deleted successfully", "success")