From c57223a3a286b1936c2c0c975491030b162675d5 Mon Sep 17 00:00:00 2001 From: Riqwan Thamir Date: Thu, 13 Jun 2024 12:19:09 +0200 Subject: [PATCH] chore: price list prices of a product can be deleted (#7700) --- .../dashboard/src/hooks/api/price-lists.tsx | 29 +++++++++- .../dashboard/src/i18n/translations/en.json | 3 +- .../pricing-product-section.tsx | 54 ++++++++++++++----- packages/core/js-sdk/src/admin/index.ts | 5 +- packages/core/js-sdk/src/admin/price-list.ts | 28 ++++++++++ packages/core/types/src/http/index.ts | 1 - .../admin/{entitites.ts => entities.ts} | 16 ++++++ .../types/src/http/pricing/admin/index.ts | 5 +- .../types/src/http/pricing/admin/payloads.ts | 3 ++ .../types/src/http/pricing/admin/queries.ts | 3 ++ .../types/src/http/pricing/admin/responses.ts | 5 ++ 11 files changed, 132 insertions(+), 20 deletions(-) create mode 100644 packages/core/js-sdk/src/admin/price-list.ts rename packages/core/types/src/http/pricing/admin/{entitites.ts => entities.ts} (68%) create mode 100644 packages/core/types/src/http/pricing/admin/payloads.ts create mode 100644 packages/core/types/src/http/pricing/admin/queries.ts create mode 100644 packages/core/types/src/http/pricing/admin/responses.ts diff --git a/packages/admin-next/dashboard/src/hooks/api/price-lists.tsx b/packages/admin-next/dashboard/src/hooks/api/price-lists.tsx index 79d52bdc62..afa00d6a37 100644 --- a/packages/admin-next/dashboard/src/hooks/api/price-lists.tsx +++ b/packages/admin-next/dashboard/src/hooks/api/price-lists.tsx @@ -1,3 +1,5 @@ +import { FetchError } from "@medusajs/js-sdk" +import { HttpTypes } from "@medusajs/types" import { QueryKey, UseMutationOptions, @@ -5,7 +7,7 @@ import { useMutation, useQuery, } from "@tanstack/react-query" -import { client } from "../../lib/client" +import { client, sdk } from "../../lib/client" import { queryClient } from "../../lib/query-client" import { queryKeysFactory } from "../../lib/query-key-factory" import { @@ -19,6 +21,7 @@ import { PriceListListRes, PriceListRes, } from "../../types/api-responses" +import { productsQueryKeys } from "./products" const PRICE_LISTS_QUERY_KEY = "price-lists" as const export const priceListsQueryKeys = queryKeysFactory(PRICE_LISTS_QUERY_KEY) @@ -114,6 +117,7 @@ export const usePriceListAddPrices = ( queryKey: priceListsQueryKeys.detail(id), }) queryClient.invalidateQueries({ queryKey: priceListsQueryKeys.lists() }) + queryClient.invalidateQueries({ queryKey: productsQueryKeys.lists() }) options?.onSuccess?.(data, variables, context) }, @@ -138,3 +142,26 @@ export const usePriceListRemovePrices = ( ...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, + }) +} diff --git a/packages/admin-next/dashboard/src/i18n/translations/en.json b/packages/admin-next/dashboard/src/i18n/translations/en.json index bf7034aa18..7cf0c4be41 100644 --- a/packages/admin-next/dashboard/src/i18n/translations/en.json +++ b/packages/admin-next/dashboard/src/i18n/translations/en.json @@ -1247,8 +1247,7 @@ "override": "Override" }, "products": { - "deleteProductsPricesWarning_one": "You are about to delete {{count}} product price. This action cannot be undone.", - "deleteProductsPricesWarning_other": "You are about to delete {{count}} product prices. This action cannot be undone." + "deleteProductsPricesWarning": "You are about to delete all prices of {{count}} product(s). This action cannot be undone." }, "prices": { "addPrices": "Add prices", diff --git a/packages/admin-next/dashboard/src/routes/pricing/pricing-detail/components/pricing-product-section/pricing-product-section.tsx b/packages/admin-next/dashboard/src/routes/pricing/pricing-detail/components/pricing-product-section/pricing-product-section.tsx index 6db06e4dc5..6c360a3d90 100644 --- a/packages/admin-next/dashboard/src/routes/pricing/pricing-detail/components/pricing-product-section/pricing-product-section.tsx +++ b/packages/admin-next/dashboard/src/routes/pricing/pricing-detail/components/pricing-product-section/pricing-product-section.tsx @@ -1,5 +1,5 @@ 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 { keepPreviousData } from "@tanstack/react-query" import { RowSelectionState, createColumnHelper } from "@tanstack/react-table" @@ -8,6 +8,7 @@ import { useTranslation } from "react-i18next" import { useNavigate } from "react-router-dom" import { ActionMenu } from "../../../../../components/common/action-menu" import { DataTable } from "../../../../../components/table/data-table" +import { usePriceListLinkProducts } from "../../../../../hooks/api/price-lists" import { useProducts } from "../../../../../hooks/api/products" import { useProductTableColumns } from "../../../../../hooks/table/columns/use-product-table-columns" import { useProductTableFilters } from "../../../../../hooks/table/filters/use-product-table-filters" @@ -45,7 +46,8 @@ export const PricingProductSection = ({ ) const filters = useProductTableFilters() - const columns = useColumns() + const columns = useColumns(priceList) + const { mutateAsync } = usePriceListLinkProducts(priceList.id) const { table } = useDataTable({ data: products || [], @@ -76,9 +78,9 @@ export const PricingProductSection = ({ return } - // The endpoint to batch remove prices by product ids is not implemented in - // v2. We either need to implement it or remove the feature. - console.log("Not implemented yet.") + mutateAsync({ + remove: Object.keys(rowSelection), + }) } 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 { 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 ( { { icon: , label: t("actions.remove"), - onClick: () => { - console.log( - `Removing prices for ${product.id}. Not implemented yet.` - ) - }, + onClick: handleDelete, }, ], }, @@ -172,7 +196,7 @@ const ProductRowAction = ({ product }: { product: HttpTypes.AdminProduct }) => { const columnHelper = createColumnHelper() -const useColumns = () => { +const useColumns = (priceList: HttpTypes.AdminPriceList) => { const base = useProductTableColumns() return useMemo( @@ -208,7 +232,9 @@ const useColumns = () => { ...base, columnHelper.display({ id: "actions", - cell: ({ row }) => , + cell: ({ row }) => ( + + ), }), ], [base] diff --git a/packages/core/js-sdk/src/admin/index.ts b/packages/core/js-sdk/src/admin/index.ts index 8cd22263d7..600512d179 100644 --- a/packages/core/js-sdk/src/admin/index.ts +++ b/packages/core/js-sdk/src/admin/index.ts @@ -2,8 +2,10 @@ import { Client } from "../client" import { Customer } from "./customer" import { Fulfillment } from "./fulfillment" import { FulfillmentSet } from "./fulfillment-set" +import { InventoryItem } from "./inventory-item" import { Invite } from "./invite" import { Order } from "./order" +import { PriceList } from "./price-list" import { Product } from "./product" import { ProductCategory } from "./product-category" import { ProductCollection } from "./product-collection" @@ -15,13 +17,13 @@ import { StockLocation } from "./stock-location" import { TaxRate } from "./tax-rate" import { TaxRegion } from "./tax-region" import { Upload } from "./upload" -import { InventoryItem } from "./inventory-item" export class Admin { public invite: Invite public customer: Customer public productCollection: ProductCollection public productCategory: ProductCategory + public priceList: PriceList public product: Product public upload: Upload public region: Region @@ -41,6 +43,7 @@ export class Admin { this.customer = new Customer(client) this.productCollection = new ProductCollection(client) this.productCategory = new ProductCategory(client) + this.priceList = new PriceList(client) this.product = new Product(client) this.upload = new Upload(client) this.region = new Region(client) diff --git a/packages/core/js-sdk/src/admin/price-list.ts b/packages/core/js-sdk/src/admin/price-list.ts new file mode 100644 index 0000000000..395a9bd694 --- /dev/null +++ b/packages/core/js-sdk/src/admin/price-list.ts @@ -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( + `/admin/price-lists/${id}/products`, + { + method: "POST", + headers, + body, + query, + } + ) + } +} diff --git a/packages/core/types/src/http/index.ts b/packages/core/types/src/http/index.ts index e0f94177e8..8885dd4736 100644 --- a/packages/core/types/src/http/index.ts +++ b/packages/core/types/src/http/index.ts @@ -26,4 +26,3 @@ export * from "./stock-locations" export * from "./tax-rate" export * from "./tax-region" export * from "./user" - diff --git a/packages/core/types/src/http/pricing/admin/entitites.ts b/packages/core/types/src/http/pricing/admin/entities.ts similarity index 68% rename from packages/core/types/src/http/pricing/admin/entitites.ts rename to packages/core/types/src/http/pricing/admin/entities.ts index 5e5a368dc0..4c11150a7a 100644 --- a/packages/core/types/src/http/pricing/admin/entitites.ts +++ b/packages/core/types/src/http/pricing/admin/entities.ts @@ -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 * 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 deleted_at: string | null } + +export interface AdminPriceList { + id: string + title: string + description: string + rules: Record + starts_at: string | null + ends_at: string | null + status: PriceListStatus + type: PriceListType + prices: AdminPrice[] + created_at: string + updated_at: string +} diff --git a/packages/core/types/src/http/pricing/admin/index.ts b/packages/core/types/src/http/pricing/admin/index.ts index f28a420d22..1f82a2ead5 100644 --- a/packages/core/types/src/http/pricing/admin/index.ts +++ b/packages/core/types/src/http/pricing/admin/index.ts @@ -1 +1,4 @@ -export * from "./entitites" +export * from "./entities" +export * from "./payloads" +export * from "./queries" +export * from "./responses" diff --git a/packages/core/types/src/http/pricing/admin/payloads.ts b/packages/core/types/src/http/pricing/admin/payloads.ts new file mode 100644 index 0000000000..cd2d6fa169 --- /dev/null +++ b/packages/core/types/src/http/pricing/admin/payloads.ts @@ -0,0 +1,3 @@ +export interface AdminLinkPriceListProducts { + remove?: string[] +} diff --git a/packages/core/types/src/http/pricing/admin/queries.ts b/packages/core/types/src/http/pricing/admin/queries.ts new file mode 100644 index 0000000000..ed59fe4b81 --- /dev/null +++ b/packages/core/types/src/http/pricing/admin/queries.ts @@ -0,0 +1,3 @@ +import { SelectParams } from "../../common" + +export interface AdminPriceListParams extends SelectParams {} diff --git a/packages/core/types/src/http/pricing/admin/responses.ts b/packages/core/types/src/http/pricing/admin/responses.ts new file mode 100644 index 0000000000..8acfad59ad --- /dev/null +++ b/packages/core/types/src/http/pricing/admin/responses.ts @@ -0,0 +1,5 @@ +import { AdminPriceList } from "./entities" + +export interface AdminPriceListResponse { + price_list: AdminPriceList +}