chore: price list prices of a product can be deleted (#7700)
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import { FetchError } from "@medusajs/js-sdk"
|
||||||
|
import { HttpTypes } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
QueryKey,
|
QueryKey,
|
||||||
UseMutationOptions,
|
UseMutationOptions,
|
||||||
@@ -5,7 +7,7 @@ import {
|
|||||||
useMutation,
|
useMutation,
|
||||||
useQuery,
|
useQuery,
|
||||||
} from "@tanstack/react-query"
|
} from "@tanstack/react-query"
|
||||||
import { client } from "../../lib/client"
|
import { client, sdk } from "../../lib/client"
|
||||||
import { queryClient } from "../../lib/query-client"
|
import { queryClient } from "../../lib/query-client"
|
||||||
import { queryKeysFactory } from "../../lib/query-key-factory"
|
import { queryKeysFactory } from "../../lib/query-key-factory"
|
||||||
import {
|
import {
|
||||||
@@ -19,6 +21,7 @@ import {
|
|||||||
PriceListListRes,
|
PriceListListRes,
|
||||||
PriceListRes,
|
PriceListRes,
|
||||||
} from "../../types/api-responses"
|
} from "../../types/api-responses"
|
||||||
|
import { productsQueryKeys } from "./products"
|
||||||
|
|
||||||
const PRICE_LISTS_QUERY_KEY = "price-lists" as const
|
const PRICE_LISTS_QUERY_KEY = "price-lists" as const
|
||||||
export const priceListsQueryKeys = queryKeysFactory(PRICE_LISTS_QUERY_KEY)
|
export const priceListsQueryKeys = queryKeysFactory(PRICE_LISTS_QUERY_KEY)
|
||||||
@@ -114,6 +117,7 @@ export const usePriceListAddPrices = (
|
|||||||
queryKey: priceListsQueryKeys.detail(id),
|
queryKey: priceListsQueryKeys.detail(id),
|
||||||
})
|
})
|
||||||
queryClient.invalidateQueries({ queryKey: priceListsQueryKeys.lists() })
|
queryClient.invalidateQueries({ queryKey: priceListsQueryKeys.lists() })
|
||||||
|
queryClient.invalidateQueries({ queryKey: productsQueryKeys.lists() })
|
||||||
|
|
||||||
options?.onSuccess?.(data, variables, context)
|
options?.onSuccess?.(data, variables, context)
|
||||||
},
|
},
|
||||||
@@ -138,3 +142,26 @@ export const usePriceListRemovePrices = (
|
|||||||
...options,
|
...options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const usePriceListLinkProducts = (
|
||||||
|
id: string,
|
||||||
|
options?: UseMutationOptions<
|
||||||
|
HttpTypes.AdminPriceListResponse,
|
||||||
|
FetchError,
|
||||||
|
HttpTypes.AdminLinkPriceListProducts
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: (payload) => sdk.admin.priceList.linkProducts(id, payload),
|
||||||
|
onSuccess: (data, variables, context) => {
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: priceListsQueryKeys.detail(id),
|
||||||
|
})
|
||||||
|
queryClient.invalidateQueries({ queryKey: priceListsQueryKeys.lists() })
|
||||||
|
queryClient.invalidateQueries({ queryKey: productsQueryKeys.lists() })
|
||||||
|
|
||||||
|
options?.onSuccess?.(data, variables, context)
|
||||||
|
},
|
||||||
|
...options,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -1247,8 +1247,7 @@
|
|||||||
"override": "Override"
|
"override": "Override"
|
||||||
},
|
},
|
||||||
"products": {
|
"products": {
|
||||||
"deleteProductsPricesWarning_one": "You are about to delete {{count}} product price. This action cannot be undone.",
|
"deleteProductsPricesWarning": "You are about to delete all prices of {{count}} product(s). This action cannot be undone."
|
||||||
"deleteProductsPricesWarning_other": "You are about to delete {{count}} product prices. This action cannot be undone."
|
|
||||||
},
|
},
|
||||||
"prices": {
|
"prices": {
|
||||||
"addPrices": "Add prices",
|
"addPrices": "Add prices",
|
||||||
|
|||||||
+40
-14
@@ -1,5 +1,5 @@
|
|||||||
import { PencilSquare, Plus, Trash } from "@medusajs/icons"
|
import { PencilSquare, Plus, Trash } from "@medusajs/icons"
|
||||||
import { PriceListDTO, HttpTypes } from "@medusajs/types"
|
import { HttpTypes, PriceListDTO } from "@medusajs/types"
|
||||||
import { Checkbox, Container, Heading, usePrompt } from "@medusajs/ui"
|
import { Checkbox, Container, Heading, usePrompt } from "@medusajs/ui"
|
||||||
import { keepPreviousData } from "@tanstack/react-query"
|
import { keepPreviousData } from "@tanstack/react-query"
|
||||||
import { RowSelectionState, createColumnHelper } from "@tanstack/react-table"
|
import { RowSelectionState, createColumnHelper } from "@tanstack/react-table"
|
||||||
@@ -8,6 +8,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
import { useNavigate } from "react-router-dom"
|
import { useNavigate } from "react-router-dom"
|
||||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
|
import { usePriceListLinkProducts } from "../../../../../hooks/api/price-lists"
|
||||||
import { useProducts } from "../../../../../hooks/api/products"
|
import { useProducts } from "../../../../../hooks/api/products"
|
||||||
import { useProductTableColumns } from "../../../../../hooks/table/columns/use-product-table-columns"
|
import { useProductTableColumns } from "../../../../../hooks/table/columns/use-product-table-columns"
|
||||||
import { useProductTableFilters } from "../../../../../hooks/table/filters/use-product-table-filters"
|
import { useProductTableFilters } from "../../../../../hooks/table/filters/use-product-table-filters"
|
||||||
@@ -45,7 +46,8 @@ export const PricingProductSection = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const filters = useProductTableFilters()
|
const filters = useProductTableFilters()
|
||||||
const columns = useColumns()
|
const columns = useColumns(priceList)
|
||||||
|
const { mutateAsync } = usePriceListLinkProducts(priceList.id)
|
||||||
|
|
||||||
const { table } = useDataTable({
|
const { table } = useDataTable({
|
||||||
data: products || [],
|
data: products || [],
|
||||||
@@ -76,9 +78,9 @@ export const PricingProductSection = ({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// The endpoint to batch remove prices by product ids is not implemented in
|
mutateAsync({
|
||||||
// v2. We either need to implement it or remove the feature.
|
remove: Object.keys(rowSelection),
|
||||||
console.log("Not implemented yet.")
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleEdit = async () => {
|
const handleEdit = async () => {
|
||||||
@@ -144,10 +146,36 @@ export const PricingProductSection = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductRowAction = ({ product }: { product: HttpTypes.AdminProduct }) => {
|
const ProductRowAction = ({
|
||||||
|
product,
|
||||||
|
priceList,
|
||||||
|
}: {
|
||||||
|
product: HttpTypes.AdminProduct
|
||||||
|
priceList: HttpTypes.AdminPriceList
|
||||||
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { mutateAsync } = usePriceListLinkProducts(priceList.id)
|
||||||
|
|
||||||
// TODO: The endpoint to remove prices by product id is not implemented in v2.
|
const handleDelete = async () => {
|
||||||
|
const prompt = usePrompt()
|
||||||
|
|
||||||
|
const res = await prompt({
|
||||||
|
title: t("general.areYouSure"),
|
||||||
|
description: t("pricing.products.deleteProductsPricesWarning", {
|
||||||
|
count: 1,
|
||||||
|
}),
|
||||||
|
confirmText: t("actions.delete"),
|
||||||
|
cancelText: t("actions.cancel"),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mutateAsync({
|
||||||
|
remove: [product.id],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ActionMenu
|
<ActionMenu
|
||||||
@@ -157,11 +185,7 @@ const ProductRowAction = ({ product }: { product: HttpTypes.AdminProduct }) => {
|
|||||||
{
|
{
|
||||||
icon: <Trash />,
|
icon: <Trash />,
|
||||||
label: t("actions.remove"),
|
label: t("actions.remove"),
|
||||||
onClick: () => {
|
onClick: handleDelete,
|
||||||
console.log(
|
|
||||||
`Removing prices for ${product.id}. Not implemented yet.`
|
|
||||||
)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -172,7 +196,7 @@ const ProductRowAction = ({ product }: { product: HttpTypes.AdminProduct }) => {
|
|||||||
|
|
||||||
const columnHelper = createColumnHelper<HttpTypes.AdminProduct>()
|
const columnHelper = createColumnHelper<HttpTypes.AdminProduct>()
|
||||||
|
|
||||||
const useColumns = () => {
|
const useColumns = (priceList: HttpTypes.AdminPriceList) => {
|
||||||
const base = useProductTableColumns()
|
const base = useProductTableColumns()
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
@@ -208,7 +232,9 @@ const useColumns = () => {
|
|||||||
...base,
|
...base,
|
||||||
columnHelper.display({
|
columnHelper.display({
|
||||||
id: "actions",
|
id: "actions",
|
||||||
cell: ({ row }) => <ProductRowAction product={row.original} />,
|
cell: ({ row }) => (
|
||||||
|
<ProductRowAction product={row.original} priceList={priceList} />
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
[base]
|
[base]
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import { Client } from "../client"
|
|||||||
import { Customer } from "./customer"
|
import { Customer } from "./customer"
|
||||||
import { Fulfillment } from "./fulfillment"
|
import { Fulfillment } from "./fulfillment"
|
||||||
import { FulfillmentSet } from "./fulfillment-set"
|
import { FulfillmentSet } from "./fulfillment-set"
|
||||||
|
import { InventoryItem } from "./inventory-item"
|
||||||
import { Invite } from "./invite"
|
import { Invite } from "./invite"
|
||||||
import { Order } from "./order"
|
import { Order } from "./order"
|
||||||
|
import { PriceList } from "./price-list"
|
||||||
import { Product } from "./product"
|
import { Product } from "./product"
|
||||||
import { ProductCategory } from "./product-category"
|
import { ProductCategory } from "./product-category"
|
||||||
import { ProductCollection } from "./product-collection"
|
import { ProductCollection } from "./product-collection"
|
||||||
@@ -15,13 +17,13 @@ import { StockLocation } from "./stock-location"
|
|||||||
import { TaxRate } from "./tax-rate"
|
import { TaxRate } from "./tax-rate"
|
||||||
import { TaxRegion } from "./tax-region"
|
import { TaxRegion } from "./tax-region"
|
||||||
import { Upload } from "./upload"
|
import { Upload } from "./upload"
|
||||||
import { InventoryItem } from "./inventory-item"
|
|
||||||
|
|
||||||
export class Admin {
|
export class Admin {
|
||||||
public invite: Invite
|
public invite: Invite
|
||||||
public customer: Customer
|
public customer: Customer
|
||||||
public productCollection: ProductCollection
|
public productCollection: ProductCollection
|
||||||
public productCategory: ProductCategory
|
public productCategory: ProductCategory
|
||||||
|
public priceList: PriceList
|
||||||
public product: Product
|
public product: Product
|
||||||
public upload: Upload
|
public upload: Upload
|
||||||
public region: Region
|
public region: Region
|
||||||
@@ -41,6 +43,7 @@ export class Admin {
|
|||||||
this.customer = new Customer(client)
|
this.customer = new Customer(client)
|
||||||
this.productCollection = new ProductCollection(client)
|
this.productCollection = new ProductCollection(client)
|
||||||
this.productCategory = new ProductCategory(client)
|
this.productCategory = new ProductCategory(client)
|
||||||
|
this.priceList = new PriceList(client)
|
||||||
this.product = new Product(client)
|
this.product = new Product(client)
|
||||||
this.upload = new Upload(client)
|
this.upload = new Upload(client)
|
||||||
this.region = new Region(client)
|
this.region = new Region(client)
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { HttpTypes } from "@medusajs/types"
|
||||||
|
import { Client } from "../client"
|
||||||
|
import { ClientHeaders } from "../types"
|
||||||
|
|
||||||
|
export class PriceList {
|
||||||
|
private client: Client
|
||||||
|
|
||||||
|
constructor(client: Client) {
|
||||||
|
this.client = client
|
||||||
|
}
|
||||||
|
|
||||||
|
async linkProducts(
|
||||||
|
id: string,
|
||||||
|
body: HttpTypes.AdminLinkPriceListProducts,
|
||||||
|
query?: HttpTypes.AdminPriceListParams,
|
||||||
|
headers?: ClientHeaders
|
||||||
|
) {
|
||||||
|
return this.client.fetch<HttpTypes.AdminPriceListResponse>(
|
||||||
|
`/admin/price-lists/${id}/products`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers,
|
||||||
|
body,
|
||||||
|
query,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,4 +26,3 @@ export * from "./stock-locations"
|
|||||||
export * from "./tax-rate"
|
export * from "./tax-rate"
|
||||||
export * from "./tax-region"
|
export * from "./tax-region"
|
||||||
export * from "./user"
|
export * from "./user"
|
||||||
|
|
||||||
|
|||||||
+16
@@ -1,3 +1,5 @@
|
|||||||
|
import { PriceListStatus, PriceListType } from "../../../pricing"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Not sure how to type this properly, as it's unclear to me what is returned
|
* TODO: Not sure how to type this properly, as it's unclear to me what is returned
|
||||||
* by our API. As an example we return `price_list: null` but `price_list_id` is missing.
|
* by our API. As an example we return `price_list: null` but `price_list_id` is missing.
|
||||||
@@ -29,3 +31,17 @@ export interface AdminPrice {
|
|||||||
updated_at: string
|
updated_at: string
|
||||||
deleted_at: string | null
|
deleted_at: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AdminPriceList {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
rules: Record<string, any>
|
||||||
|
starts_at: string | null
|
||||||
|
ends_at: string | null
|
||||||
|
status: PriceListStatus
|
||||||
|
type: PriceListType
|
||||||
|
prices: AdminPrice[]
|
||||||
|
created_at: string
|
||||||
|
updated_at: string
|
||||||
|
}
|
||||||
@@ -1 +1,4 @@
|
|||||||
export * from "./entitites"
|
export * from "./entities"
|
||||||
|
export * from "./payloads"
|
||||||
|
export * from "./queries"
|
||||||
|
export * from "./responses"
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export interface AdminLinkPriceListProducts {
|
||||||
|
remove?: string[]
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { SelectParams } from "../../common"
|
||||||
|
|
||||||
|
export interface AdminPriceListParams extends SelectParams {}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { AdminPriceList } from "./entities"
|
||||||
|
|
||||||
|
export interface AdminPriceListResponse {
|
||||||
|
price_list: AdminPriceList
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user